forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_cfg80211.c
....@@ -1,15 +1,16 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
21 /*
32 * Linux cfg80211 driver - Dongle Host Driver (DHD) related
43 *
5
- * Copyright (C) 1999-2019, Broadcom Corporation
6
- *
4
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
5
+ *
6
+ * Copyright (C) 1999-2017, Broadcom Corporation
7
+ *
78 * Unless you and Broadcom execute a separate written software license
89 * agreement governing use of this software, this software is licensed to you
910 * under the terms of the GNU General Public License version 2 (the "GPL"),
1011 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
1112 * following added to such license:
12
- *
13
+ *
1314 * As a special exception, the copyright holders of this software give you
1415 * permission to link this software with independent modules, and to copy and
1516 * distribute the resulting executable under terms of your choice, provided that
....@@ -17,7 +18,7 @@
1718 * the license of that module. An independent module is a module which is not
1819 * derived from this software. The special exception does not apply to any
1920 * modifications of the software.
20
- *
21
+ *
2122 * Notwithstanding the above, under no circumstances may you combine this
2223 * software in any way with any other Broadcom software provided under a license
2324 * other than the GPL, without Broadcom's express prior written consent.
....@@ -25,7 +26,7 @@
2526 *
2627 * <<Broadcom-WL-IPTag/Open:>>
2728 *
28
- * $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011/02/09 01:40:07 Exp $
29
+ * $Id: dhd_cfg80211.c 696903 2017-04-28 19:48:01Z $
2930 */
3031
3132 #include <linux/vmalloc.h>
....@@ -39,15 +40,13 @@
3940 #ifdef PKT_FILTER_SUPPORT
4041 #include <dngl_stats.h>
4142 #include <dhd.h>
42
-#endif
43
-
44
-extern struct bcm_cfg80211 *g_bcm_cfg;
43
+#endif // endif
4544
4645 #ifdef PKT_FILTER_SUPPORT
4746 extern uint dhd_pkt_filter_enable;
4847 extern uint dhd_master_mode;
4948 extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
50
-#endif
49
+#endif // endif
5150
5251 static int dhd_dongle_up = FALSE;
5352
....@@ -60,6 +59,16 @@
6059
6160 static s32 wl_dongle_up(struct net_device *ndev);
6261 static s32 wl_dongle_down(struct net_device *ndev);
62
+#ifndef OEM_ANDROID
63
+static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode);
64
+#ifdef BCMSDIO /* glomming is a sdio specific feature */
65
+static s32 wl_dongle_glom(struct net_device *ndev, s32 glom, u32 dongle_align);
66
+#endif // endif
67
+static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, s32 scan_unassoc_time);
68
+static s32 wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol);
69
+static s32 wl_pattern_atoh(s8 *src, s8 *dst);
70
+static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode);
71
+#endif /* OEM_ANDROID */
6372
6473 /**
6574 * Function implementations
....@@ -81,17 +90,19 @@
8190 {
8291 struct net_device *ndev;
8392 s32 err = 0;
93
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8494
8595 WL_TRACE(("In\n"));
86
- if (!dhd_dongle_up) {
87
- WL_ERR(("Dongle is already down\n"));
88
- return err;
96
+ if ((!dhd_dongle_up) || (!dhd->up)) {
97
+ WL_INFORM_MEM(("Dongle is already down\n"));
98
+ err = 0;
99
+ goto done;
89100 }
90
-
91101 ndev = bcmcfg_to_prmry_ndev(cfg);
92102 wl_dongle_down(ndev);
103
+done:
93104 dhd_dongle_up = FALSE;
94
- return 0;
105
+ return err;
95106 }
96107
97108 s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val)
....@@ -127,27 +138,55 @@
127138 return 0;
128139 }
129140
130
-struct net_device* wl_cfg80211_allocate_if(struct bcm_cfg80211 *cfg, int ifidx, char *name,
131
- uint8 *mac, uint8 bssidx, char *dngl_name)
141
+#ifdef WL_STATIC_IF
142
+int32
143
+wl_cfg80211_update_iflist_info(struct bcm_cfg80211 *cfg, struct net_device *ndev,
144
+ int ifidx, uint8 *addr, int bssidx, char *name, int if_state)
145
+{
146
+ return dhd_update_iflist_info(cfg->pub, ndev, ifidx, addr, bssidx, name, if_state);
147
+}
148
+#endif /* WL_STATIC_IF */
149
+
150
+struct net_device* wl_cfg80211_allocate_if(struct bcm_cfg80211 *cfg, int ifidx, const char *name,
151
+ uint8 *mac, uint8 bssidx, const char *dngl_name)
132152 {
133153 return dhd_allocate_if(cfg->pub, ifidx, name, mac, bssidx, FALSE, dngl_name);
134154 }
135155
136
-int wl_cfg80211_register_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
156
+int wl_cfg80211_register_if(struct bcm_cfg80211 *cfg,
157
+ int ifidx, struct net_device* ndev, bool rtnl_lock_reqd)
137158 {
138
- return dhd_register_if(cfg->pub, ifidx, FALSE);
159
+ return dhd_register_if(cfg->pub, ifidx, rtnl_lock_reqd);
139160 }
140161
141
-int wl_cfg80211_remove_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
162
+int wl_cfg80211_remove_if(struct bcm_cfg80211 *cfg,
163
+ int ifidx, struct net_device* ndev, bool rtnl_lock_reqd)
142164 {
143
- return dhd_remove_if(cfg->pub, ifidx, FALSE);
165
+#ifdef DHD_PCIE_RUNTIMEPM
166
+ dhdpcie_runtime_bus_wake(cfg->pub, CAN_SLEEP(), __builtin_return_address(0));
167
+#endif /* DHD_PCIE_RUNTIMEPM */
168
+ return dhd_remove_if(cfg->pub, ifidx, rtnl_lock_reqd);
169
+}
170
+
171
+void wl_cfg80211_cleanup_if(struct net_device *net)
172
+{
173
+ struct bcm_cfg80211 *cfg = wl_get_cfg(net);
174
+#ifdef DHD_PCIE_RUNTIMEPM
175
+ dhdpcie_runtime_bus_wake(cfg->pub, CAN_SLEEP(), __builtin_return_address(0));
176
+#else
177
+ BCM_REFERENCE(cfg);
178
+#endif /* DHD_PCIE_RUNTIMEPM */
179
+ dhd_cleanup_if(net);
144180 }
145181
146182 struct net_device * dhd_cfg80211_netdev_free(struct net_device *ndev)
147183 {
184
+ struct bcm_cfg80211 *cfg;
185
+
148186 if (ndev) {
187
+ cfg = wl_get_cfg(ndev);
149188 if (ndev->ieee80211_ptr) {
150
- kfree(ndev->ieee80211_ptr);
189
+ MFREE(cfg->osh, ndev->ieee80211_ptr, sizeof(struct wireless_dev));
151190 ndev->ieee80211_ptr = NULL;
152191 }
153192 free_netdev(ndev);
....@@ -161,7 +200,7 @@
161200 {
162201 #ifdef WL_CFG80211
163202 ndev = dhd_cfg80211_netdev_free(ndev);
164
-#endif
203
+#endif // endif
165204 if (ndev)
166205 free_netdev(ndev);
167206 }
....@@ -170,9 +209,9 @@
170209 wl_dongle_up(struct net_device *ndev)
171210 {
172211 s32 err = 0;
173
- u32 up = 0;
212
+ u32 local_up = 0;
174213
175
- err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true);
214
+ err = wldev_ioctl_set(ndev, WLC_UP, &local_up, sizeof(local_up));
176215 if (unlikely(err)) {
177216 WL_ERR(("WLC_UP error (%d)\n", err));
178217 }
....@@ -183,23 +222,269 @@
183222 wl_dongle_down(struct net_device *ndev)
184223 {
185224 s32 err = 0;
186
- u32 down = 0;
225
+ u32 local_down = 0;
187226
188
- err = wldev_ioctl(ndev, WLC_DOWN, &down, sizeof(down), true);
227
+ err = wldev_ioctl_set(ndev, WLC_DOWN, &local_down, sizeof(local_down));
189228 if (unlikely(err)) {
190229 WL_ERR(("WLC_DOWN error (%d)\n", err));
191230 }
192231 return err;
193232 }
194233
234
+#ifndef OEM_ANDROID
235
+static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode)
236
+{
237
+ s32 err = 0;
238
+
239
+ WL_TRACE(("In\n"));
240
+ err = wldev_ioctl_set(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode));
241
+ if (unlikely(err)) {
242
+ WL_ERR(("WLC_SET_PM error (%d)\n", err));
243
+ }
244
+ return err;
245
+}
246
+
247
+#ifdef BCMSDIO
248
+static s32
249
+wl_dongle_glom(struct net_device *ndev, s32 glom, u32 dongle_align)
250
+{
251
+ s32 err = 0;
252
+
253
+ /* Match Host and Dongle rx alignment */
254
+ err = wldev_iovar_setint(ndev, "bus:txglomalign", dongle_align);
255
+ if (unlikely(err)) {
256
+ WL_ERR(("txglomalign error (%d)\n", err));
257
+ goto dongle_glom_out;
258
+ }
259
+ /* disable glom option per default */
260
+ if (glom != DEFAULT_GLOM_VALUE) {
261
+ err = wldev_iovar_setint(ndev, "bus:txglom", glom);
262
+ if (unlikely(err)) {
263
+ WL_ERR(("txglom error (%d)\n", err));
264
+ goto dongle_glom_out;
265
+ }
266
+ }
267
+dongle_glom_out:
268
+ return err;
269
+}
270
+
271
+#endif /* BCMSDIO */
272
+#endif /* OEM_ANDROID */
273
+
274
+s32
275
+wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
276
+{
277
+ s32 err = 0;
278
+
279
+ /* Setup timeout if Beacons are lost and roam is off to report link down */
280
+ if (roamvar) {
281
+ err = wldev_iovar_setint(ndev, "bcn_timeout", bcn_timeout);
282
+ if (unlikely(err)) {
283
+ WL_ERR(("bcn_timeout error (%d)\n", err));
284
+ goto dongle_rom_out;
285
+ }
286
+ }
287
+ /* Enable/Disable built-in roaming to allow supplicant to take care of roaming */
288
+ err = wldev_iovar_setint(ndev, "roam_off", roamvar);
289
+ if (unlikely(err)) {
290
+ WL_ERR(("roam_off error (%d)\n", err));
291
+ goto dongle_rom_out;
292
+ }
293
+dongle_rom_out:
294
+ return err;
295
+}
296
+
297
+#ifndef OEM_ANDROID
298
+static s32
299
+wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
300
+ s32 scan_unassoc_time)
301
+{
302
+ s32 err = 0;
303
+
304
+ err = wldev_ioctl_set(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
305
+ sizeof(scan_assoc_time));
306
+ if (err) {
307
+ if (err == -EOPNOTSUPP) {
308
+ WL_INFORM(("Scan assoc time is not supported\n"));
309
+ } else {
310
+ WL_ERR(("Scan assoc time error (%d)\n", err));
311
+ }
312
+ goto dongle_scantime_out;
313
+ }
314
+ err = wldev_ioctl_set(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
315
+ sizeof(scan_unassoc_time));
316
+ if (err) {
317
+ if (err == -EOPNOTSUPP) {
318
+ WL_INFORM(("Scan unassoc time is not supported\n"));
319
+ } else {
320
+ WL_ERR(("Scan unassoc time error (%d)\n", err));
321
+ }
322
+ goto dongle_scantime_out;
323
+ }
324
+
325
+dongle_scantime_out:
326
+ return err;
327
+}
328
+
329
+static s32
330
+wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol)
331
+{
332
+ s8 iovbuf[WLC_IOCTL_SMLEN];
333
+ s32 err = 0;
334
+ s32 len;
335
+
336
+ /* Set ARP offload */
337
+ len = bcm_mkiovar("arpoe", (char *)&arpoe, sizeof(arpoe), iovbuf, sizeof(iovbuf));
338
+ if (!len) {
339
+ WL_ERR(("%s: bcm_mkiovar failed:%d\n", __FUNCTION__, len));
340
+ return BCME_BADARG;
341
+ }
342
+ err = wldev_ioctl_set(ndev, WLC_SET_VAR, iovbuf, len);
343
+ if (err) {
344
+ if (err == -EOPNOTSUPP)
345
+ WL_INFORM(("arpoe is not supported\n"));
346
+ else
347
+ WL_ERR(("arpoe error (%d)\n", err));
348
+
349
+ goto dongle_offload_out;
350
+ }
351
+ len = bcm_mkiovar("arp_ol", (char *)&arp_ol, sizeof(arp_ol), iovbuf, sizeof(iovbuf));
352
+ if (!len) {
353
+ WL_ERR(("%s: bcm_mkiovar failed:%d\n", __FUNCTION__, len));
354
+ return BCME_BADARG;
355
+ }
356
+ err = wldev_ioctl_set(ndev, WLC_SET_VAR, iovbuf, len);
357
+ if (err) {
358
+ if (err == -EOPNOTSUPP)
359
+ WL_INFORM(("arp_ol is not supported\n"));
360
+ else
361
+ WL_ERR(("arp_ol error (%d)\n", err));
362
+
363
+ goto dongle_offload_out;
364
+ }
365
+
366
+dongle_offload_out:
367
+ return err;
368
+}
369
+
370
+static s32 wl_pattern_atoh(s8 *src, s8 *dst)
371
+{
372
+ int i;
373
+ if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
374
+ WL_ERR(("Mask invalid format. Needs to start with 0x\n"));
375
+ return -1;
376
+ }
377
+ src = src + 2; /* Skip past 0x */
378
+ if (strlen(src) % 2 != 0) {
379
+ WL_ERR(("Mask invalid format. Needs to be of even length\n"));
380
+ return -1;
381
+ }
382
+ for (i = 0; *src != '\0'; i++) {
383
+ char num[3];
384
+ strncpy(num, src, 2);
385
+ num[2] = '\0';
386
+ dst[i] = (u8) simple_strtoul(num, NULL, 16);
387
+ src += 2;
388
+ }
389
+ return i;
390
+}
391
+
392
+static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode)
393
+{
394
+ const s8 *str;
395
+ struct wl_pkt_filter pkt_filter;
396
+ struct wl_pkt_filter *pkt_filterp;
397
+ s32 buf_len;
398
+ s32 str_len;
399
+ u32 mask_size;
400
+ u32 pattern_size;
401
+ s8 buf[64] = {0};
402
+ s32 err = 0;
403
+
404
+ /* add a default packet filter pattern */
405
+ str = "pkt_filter_add";
406
+ str_len = strlen(str);
407
+ strncpy(buf, str, sizeof(buf) - 1);
408
+ buf[ sizeof(buf) - 1 ] = '\0';
409
+ buf_len = str_len + 1;
410
+
411
+ pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1);
412
+
413
+ /* Parse packet filter id. */
414
+ pkt_filter.id = htod32(100);
415
+
416
+ /* Parse filter polarity. */
417
+ pkt_filter.negate_match = htod32(0);
418
+
419
+ /* Parse filter type. */
420
+ pkt_filter.type = htod32(0);
421
+
422
+ /* Parse pattern filter offset. */
423
+ pkt_filter.u.pattern.offset = htod32(0);
424
+
425
+ /* Parse pattern filter mask. */
426
+ mask_size = htod32(wl_pattern_atoh("0xff",
427
+ (char *)pkt_filterp->u.pattern.
428
+ mask_and_pattern));
429
+
430
+ /* Parse pattern filter pattern. */
431
+ pattern_size = htod32(wl_pattern_atoh("0x00",
432
+ (char *)&pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
433
+
434
+ if (mask_size != pattern_size) {
435
+ WL_ERR(("Mask and pattern not the same size\n"));
436
+ err = -EINVAL;
437
+ goto dongle_filter_out;
438
+ }
439
+
440
+ pkt_filter.u.pattern.size_bytes = mask_size;
441
+ buf_len += WL_PKT_FILTER_FIXED_LEN;
442
+ buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
443
+
444
+ /* Keep-alive attributes are set in local
445
+ * variable (keep_alive_pkt), and
446
+ * then memcpy'ed into buffer (keep_alive_pktp) since there is no
447
+ * guarantee that the buffer is properly aligned.
448
+ */
449
+ memcpy((char *)pkt_filterp, &pkt_filter,
450
+ WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
451
+
452
+ err = wldev_ioctl_set(ndev, WLC_SET_VAR, buf, buf_len);
453
+ if (err) {
454
+ if (err == -EOPNOTSUPP) {
455
+ WL_INFORM(("filter not supported\n"));
456
+ } else {
457
+ WL_ERR(("filter (%d)\n", err));
458
+ }
459
+ goto dongle_filter_out;
460
+ }
461
+
462
+ /* set mode to allow pattern */
463
+ err = wldev_iovar_setint(ndev, "pkt_filter_mode", filter_mode);
464
+ if (err) {
465
+ if (err == -EOPNOTSUPP) {
466
+ WL_INFORM(("filter_mode not supported\n"));
467
+ } else {
468
+ WL_ERR(("filter_mode (%d)\n", err));
469
+ }
470
+ goto dongle_filter_out;
471
+ }
472
+
473
+dongle_filter_out:
474
+ return err;
475
+}
476
+#endif /* OEM_ANDROID */
195477
196478 s32 dhd_config_dongle(struct bcm_cfg80211 *cfg)
197479 {
198480 #ifndef DHD_SDALIGN
199481 #define DHD_SDALIGN 32
200
-#endif
482
+#endif // endif
201483 struct net_device *ndev;
202484 s32 err = 0;
485
+#if !defined(OEM_ANDROID) && defined(BCMSDIO)
486
+ s32 glom = CUSTOM_GLOM_SETTING;
487
+#endif // endif
203488
204489 WL_TRACE(("In\n"));
205490 if (dhd_dongle_up) {
....@@ -214,6 +499,32 @@
214499 WL_ERR(("wl_dongle_up failed\n"));
215500 goto default_conf_out;
216501 }
502
+#ifndef OEM_ANDROID
503
+ err = wl_dongle_power(ndev, PM_FAST);
504
+ if (unlikely(err)) {
505
+ WL_ERR(("wl_dongle_power failed\n"));
506
+ goto default_conf_out;
507
+ }
508
+#ifdef BCMSDIO
509
+ if (glom != DEFAULT_GLOM_VALUE) {
510
+ err = wl_dongle_glom(ndev, glom, DHD_SDALIGN);
511
+ } else {
512
+ err = wl_dongle_glom(ndev, DEFAULT_GLOM_VALUE, DHD_SDALIGN);
513
+ }
514
+ if (unlikely(err)) {
515
+ WL_ERR(("wl_dongle_glom failed\n"));
516
+ goto default_conf_out;
517
+ }
518
+#endif /* BCMSDIO */
519
+ err = wl_dongle_roam(ndev, (cfg->roam_on ? 0 : 1), 3);
520
+ if (unlikely(err)) {
521
+ WL_ERR(("wl_dongle_roam failed\n"));
522
+ goto default_conf_out;
523
+ }
524
+ wl_dongle_scantime(ndev, 40, 80);
525
+ wl_dongle_offload(ndev, 1, 0xf);
526
+ wl_dongle_filter(ndev, 1);
527
+#endif /* OEM_ANDROID */
217528 dhd_dongle_up = true;
218529
219530 default_conf_out:
....@@ -227,7 +538,7 @@
227538 {
228539 struct net_device *ndev = NULL;
229540 dhd_pub_t *dhd;
230
- dhd_ioctl_t ioc = { 0 };
541
+ dhd_ioctl_t ioc = { 0, NULL, 0, 0, 0, 0, 0};
231542 int ret = 0;
232543 int8 index;
233544
....@@ -235,14 +546,6 @@
235546
236547 dhd = cfg->pub;
237548 DHD_OS_WAKE_LOCK(dhd);
238
-
239
- /* send to dongle only if we are not waiting for reload already */
240
- if (dhd->hang_was_sent) {
241
- WL_ERR(("HANG was sent up earlier\n"));
242
- DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS);
243
- DHD_OS_WAKE_UNLOCK(dhd);
244
- return OSL_ERROR(BCME_DONGLE_DOWN);
245
- }
246549
247550 ndev = wdev_to_wlc_ndev(wdev, cfg);
248551 index = dhd_net2idx(dhd->info, ndev);
....@@ -256,6 +559,7 @@
256559 ioc.len = nlioc->len;
257560 ioc.set = nlioc->set;
258561 ioc.driver = nlioc->magic;
562
+ ioc.buf = buf;
259563 ret = dhd_ioctl_process(dhd, index, &ioc, buf);
260564 if (ret) {
261565 WL_TRACE(("dhd_ioctl_process return err %d\n", ret));