.. | .. |
---|
1 | | -/* SPDX-License-Identifier: GPL-2.0 */ |
---|
2 | 1 | /* |
---|
3 | 2 | * Linux cfg80211 driver - Dongle Host Driver (DHD) related |
---|
4 | 3 | * |
---|
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 | + * |
---|
7 | 8 | * Unless you and Broadcom execute a separate written software license |
---|
8 | 9 | * agreement governing use of this software, this software is licensed to you |
---|
9 | 10 | * under the terms of the GNU General Public License version 2 (the "GPL"), |
---|
10 | 11 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the |
---|
11 | 12 | * following added to such license: |
---|
12 | | - * |
---|
| 13 | + * |
---|
13 | 14 | * As a special exception, the copyright holders of this software give you |
---|
14 | 15 | * permission to link this software with independent modules, and to copy and |
---|
15 | 16 | * distribute the resulting executable under terms of your choice, provided that |
---|
.. | .. |
---|
17 | 18 | * the license of that module. An independent module is a module which is not |
---|
18 | 19 | * derived from this software. The special exception does not apply to any |
---|
19 | 20 | * modifications of the software. |
---|
20 | | - * |
---|
| 21 | + * |
---|
21 | 22 | * Notwithstanding the above, under no circumstances may you combine this |
---|
22 | 23 | * software in any way with any other Broadcom software provided under a license |
---|
23 | 24 | * other than the GPL, without Broadcom's express prior written consent. |
---|
.. | .. |
---|
25 | 26 | * |
---|
26 | 27 | * <<Broadcom-WL-IPTag/Open:>> |
---|
27 | 28 | * |
---|
28 | | - * $Id: wl_cfg_btcoex.c 709309 2019-01-17 09:04:00Z $ |
---|
| 29 | + * $Id: wl_cfg_btcoex.c 814554 2019-04-11 23:06:22Z $ |
---|
29 | 30 | */ |
---|
30 | 31 | |
---|
31 | 32 | #include <net/rtnetlink.h> |
---|
.. | .. |
---|
43 | 44 | extern uint dhd_pkt_filter_enable; |
---|
44 | 45 | extern uint dhd_master_mode; |
---|
45 | 46 | extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode); |
---|
46 | | -#endif |
---|
| 47 | +#endif // endif |
---|
47 | 48 | |
---|
48 | 49 | struct btcoex_info { |
---|
49 | | - struct timer_list timer; |
---|
| 50 | + timer_list_compat_t timer; |
---|
50 | 51 | u32 timer_ms; |
---|
51 | 52 | u32 timer_on; |
---|
52 | 53 | u32 ts_dhcp_start; /* ms ts ecord time stats */ |
---|
.. | .. |
---|
59 | 60 | struct net_device *dev; |
---|
60 | 61 | }; |
---|
61 | 62 | |
---|
| 63 | +#if defined(OEM_ANDROID) |
---|
62 | 64 | static struct btcoex_info *btcoex_info_loc = NULL; |
---|
63 | 65 | |
---|
64 | 66 | /* TODO: clean up the BT-Coex code, it still have some legacy ioctl/iovar functions */ |
---|
.. | .. |
---|
71 | 73 | #define BT_DHCP_OPPR_WIN_TIME 2500 |
---|
72 | 74 | /* T2 turn off SCO/SCO supperesion is (timeout) */ |
---|
73 | 75 | #define BT_DHCP_FLAG_FORCE_TIME 5500 |
---|
| 76 | + |
---|
| 77 | +#define BTCOEXMODE "BTCOEXMODE" |
---|
| 78 | +#define POWERMODE "POWERMODE" |
---|
74 | 79 | |
---|
75 | 80 | enum wl_cfg80211_btcoex_status { |
---|
76 | 81 | BT_DHCP_IDLE, |
---|
.. | .. |
---|
93 | 98 | } var; |
---|
94 | 99 | int error; |
---|
95 | 100 | |
---|
96 | | - bcm_mkiovar(name, (char *)(®), sizeof(reg), |
---|
97 | | - (char *)(&var), sizeof(var.buf)); |
---|
98 | | - error = wldev_ioctl(dev, WLC_GET_VAR, (char *)(&var), sizeof(var.buf), false); |
---|
| 101 | + bzero(&var, sizeof(var)); |
---|
| 102 | + error = bcm_mkiovar(name, (char *)(®), sizeof(reg), (char *)(&var), sizeof(var.buf)); |
---|
| 103 | + if (error == 0) { |
---|
| 104 | + return BCME_BUFTOOSHORT; |
---|
| 105 | + } |
---|
| 106 | + error = wldev_ioctl_get(dev, WLC_GET_VAR, (char *)(&var), sizeof(var.buf)); |
---|
99 | 107 | |
---|
100 | 108 | *retval = dtoh32(var.val); |
---|
101 | 109 | return (error); |
---|
.. | .. |
---|
104 | 112 | static int |
---|
105 | 113 | dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len) |
---|
106 | 114 | { |
---|
107 | | -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) |
---|
108 | | - char ioctlbuf_local[1024]; |
---|
109 | | -#else |
---|
110 | | - static char ioctlbuf_local[1024]; |
---|
111 | | -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */ |
---|
| 115 | + char ioctlbuf_local[WLC_IOCTL_SMLEN]; |
---|
| 116 | + int ret; |
---|
112 | 117 | |
---|
113 | | - bcm_mkiovar(name, buf, len, ioctlbuf_local, sizeof(ioctlbuf_local)); |
---|
114 | | - |
---|
115 | | - return (wldev_ioctl(dev, WLC_SET_VAR, ioctlbuf_local, sizeof(ioctlbuf_local), true)); |
---|
| 118 | + ret = bcm_mkiovar(name, buf, len, ioctlbuf_local, sizeof(ioctlbuf_local)); |
---|
| 119 | + if (ret == 0) |
---|
| 120 | + return BCME_BUFTOOSHORT; |
---|
| 121 | + return (wldev_ioctl_set(dev, WLC_SET_VAR, ioctlbuf_local, ret)); |
---|
116 | 122 | } |
---|
| 123 | + |
---|
117 | 124 | /* |
---|
118 | 125 | get named driver variable to uint register value and return error indication |
---|
119 | 126 | calling example: dev_wlc_intvar_set_reg(dev, "btc_params",66, value) |
---|
.. | .. |
---|
123 | 130 | { |
---|
124 | 131 | char reg_addr[8]; |
---|
125 | 132 | |
---|
126 | | - memset(reg_addr, 0, sizeof(reg_addr)); |
---|
| 133 | + bzero(reg_addr, sizeof(reg_addr)); |
---|
127 | 134 | memcpy((char *)®_addr[0], (char *)addr, 4); |
---|
128 | 135 | memcpy((char *)®_addr[4], (char *)val, 4); |
---|
129 | 136 | |
---|
.. | .. |
---|
276 | 283 | #if defined(BT_DHCP_USE_FLAGS) |
---|
277 | 284 | char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 }; |
---|
278 | 285 | char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; |
---|
279 | | -#endif |
---|
280 | | - |
---|
| 286 | +#endif // endif |
---|
281 | 287 | |
---|
282 | 288 | #if defined(BT_DHCP_eSCO_FIX) |
---|
283 | 289 | /* set = 1, save & turn on 0 - off & restore prev settings */ |
---|
284 | 290 | set_btc_esco_params(dev, set); |
---|
285 | | -#endif |
---|
| 291 | +#endif // endif |
---|
286 | 292 | |
---|
287 | 293 | #if defined(BT_DHCP_USE_FLAGS) |
---|
288 | 294 | WL_TRACE(("WI-FI priority boost via bt flags, set:%d\n", set)); |
---|
.. | .. |
---|
296 | 302 | dev_wlc_bufvar_set(dev, "btc_flags", |
---|
297 | 303 | (char *)&buf_flag7_default[0], |
---|
298 | 304 | sizeof(buf_flag7_default)); |
---|
299 | | -#endif |
---|
| 305 | +#endif // endif |
---|
300 | 306 | } |
---|
301 | 307 | |
---|
302 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) |
---|
303 | | -static void wl_cfg80211_bt_timerfunc(struct timer_list *t) |
---|
304 | | -{ |
---|
305 | | - struct btcoex_info *bt_local = from_timer(bt_local, t, timer); |
---|
306 | | -#else |
---|
307 | 308 | static void wl_cfg80211_bt_timerfunc(ulong data) |
---|
308 | 309 | { |
---|
309 | 310 | struct btcoex_info *bt_local = (struct btcoex_info *)data; |
---|
310 | | -#endif |
---|
311 | 311 | WL_TRACE(("Enter\n")); |
---|
312 | 312 | bt_local->timer_on = 0; |
---|
313 | 313 | schedule_work(&bt_local->work); |
---|
.. | .. |
---|
317 | 317 | { |
---|
318 | 318 | struct btcoex_info *btcx_inf; |
---|
319 | 319 | |
---|
| 320 | + GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST(); |
---|
320 | 321 | btcx_inf = container_of(work, struct btcoex_info, work); |
---|
| 322 | + GCC_DIAGNOSTIC_POP(); |
---|
321 | 323 | |
---|
322 | 324 | if (btcx_inf->timer_on) { |
---|
323 | 325 | btcx_inf->timer_on = 0; |
---|
.. | .. |
---|
397 | 399 | btco_inf->ts_dhcp_ok = 0; |
---|
398 | 400 | /* Set up timer for BT */ |
---|
399 | 401 | btco_inf->timer_ms = 10; |
---|
400 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) |
---|
401 | | - timer_setup(&btco_inf->timer, wl_cfg80211_bt_timerfunc, 0); |
---|
402 | | -#else |
---|
403 | | - init_timer(&btco_inf->timer); |
---|
404 | | - btco_inf->timer.data = (ulong)btco_inf; |
---|
405 | | - btco_inf->timer.function = wl_cfg80211_bt_timerfunc; |
---|
406 | | -#endif |
---|
| 402 | + init_timer_compat(&btco_inf->timer, wl_cfg80211_bt_timerfunc, btco_inf); |
---|
407 | 403 | |
---|
408 | 404 | btco_inf->dev = ndev; |
---|
409 | 405 | |
---|
.. | .. |
---|
431 | 427 | int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, dhd_pub_t *dhd, char *command) |
---|
432 | 428 | { |
---|
433 | 429 | |
---|
| 430 | +#ifndef OEM_ANDROID |
---|
| 431 | + static int pm = PM_FAST; |
---|
| 432 | + int pm_local = PM_OFF; |
---|
| 433 | +#endif /* OEM_ANDROID */ |
---|
434 | 434 | struct btcoex_info *btco_inf = btcoex_info_loc; |
---|
435 | 435 | char powermode_val = 0; |
---|
| 436 | + uint8 cmd_len = 0; |
---|
436 | 437 | char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 }; |
---|
437 | 438 | char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 }; |
---|
438 | 439 | char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 }; |
---|
.. | .. |
---|
446 | 447 | char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; |
---|
447 | 448 | |
---|
448 | 449 | /* Figure out powermode 1 or o command */ |
---|
449 | | - strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1); |
---|
| 450 | +#ifdef OEM_ANDROID |
---|
| 451 | + cmd_len = sizeof(BTCOEXMODE); |
---|
| 452 | +#else |
---|
| 453 | + cmd_len = sizeof(POWERMODE); |
---|
| 454 | +#endif // endif |
---|
| 455 | + powermode_val = command[cmd_len]; |
---|
450 | 456 | |
---|
451 | | - if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { |
---|
| 457 | + if (powermode_val == '1') { |
---|
452 | 458 | WL_TRACE_HW4(("DHCP session starts\n")); |
---|
453 | | - |
---|
454 | 459 | |
---|
455 | 460 | #ifdef PKT_FILTER_SUPPORT |
---|
456 | 461 | dhd->dhcp_in_progress = 1; |
---|
457 | 462 | |
---|
| 463 | +#if defined(APSTA_BLOCK_ARP_DURING_DHCP) |
---|
| 464 | + if (DHD_OPMODE_STA_SOFTAP_CONCURR(dhd)) { |
---|
| 465 | + /* Block ARP frames while DHCP of STA interface is in |
---|
| 466 | + * progress in case of STA/SoftAP concurrent mode |
---|
| 467 | + */ |
---|
| 468 | + wl_cfg80211_block_arp(dev, TRUE); |
---|
| 469 | + } else |
---|
| 470 | +#endif /* APSTA_BLOCK_ARP_DURING_DHCP */ |
---|
458 | 471 | if (dhd->early_suspended) { |
---|
459 | 472 | WL_TRACE_HW4(("DHCP in progressing , disable packet filter!!!\n")); |
---|
460 | 473 | dhd_enable_packet_filter(0, dhd); |
---|
461 | 474 | } |
---|
462 | | -#endif |
---|
| 475 | +#endif /* PKT_FILTER_SUPPORT */ |
---|
463 | 476 | |
---|
464 | 477 | /* Retrieve and saved orig regs value */ |
---|
465 | 478 | if ((saved_status == FALSE) && |
---|
| 479 | +#ifndef OEM_ANDROID |
---|
| 480 | + (!dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))) && |
---|
| 481 | +#endif // endif |
---|
466 | 482 | (!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) && |
---|
467 | 483 | (!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) && |
---|
468 | 484 | (!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) { |
---|
.. | .. |
---|
471 | 487 | saved_reg66, saved_reg41, saved_reg68)); |
---|
472 | 488 | |
---|
473 | 489 | /* Disable PM mode during dhpc session */ |
---|
| 490 | +#ifndef OEM_ANDROID |
---|
| 491 | + dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local)); |
---|
| 492 | +#endif // endif |
---|
474 | 493 | |
---|
475 | 494 | /* Disable PM mode during dhpc session */ |
---|
476 | 495 | /* Start BT timer only for SCO connection */ |
---|
.. | .. |
---|
491 | 510 | |
---|
492 | 511 | btco_inf->bt_state = BT_DHCP_START; |
---|
493 | 512 | btco_inf->timer_on = 1; |
---|
494 | | - mod_timer(&btco_inf->timer, btco_inf->timer.expires); |
---|
| 513 | + mod_timer(&btco_inf->timer, |
---|
| 514 | + timer_expires(&btco_inf->timer)); |
---|
495 | 515 | WL_TRACE(("enable BT DHCP Timer\n")); |
---|
496 | 516 | } |
---|
497 | 517 | } |
---|
.. | .. |
---|
499 | 519 | WL_ERR(("was called w/o DHCP OFF. Continue\n")); |
---|
500 | 520 | } |
---|
501 | 521 | } |
---|
502 | | - else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) { |
---|
503 | | - |
---|
504 | | - |
---|
| 522 | +#ifdef OEM_ANDROID |
---|
| 523 | + else if (powermode_val == '2') { |
---|
| 524 | +#else |
---|
| 525 | + else if (powermode_val == '0') { |
---|
| 526 | +#endif // endif |
---|
505 | 527 | |
---|
506 | 528 | #ifdef PKT_FILTER_SUPPORT |
---|
507 | 529 | dhd->dhcp_in_progress = 0; |
---|
508 | 530 | WL_TRACE_HW4(("DHCP is complete \n")); |
---|
509 | 531 | |
---|
510 | | - /* Enable packet filtering */ |
---|
| 532 | +#if defined(APSTA_BLOCK_ARP_DURING_DHCP) |
---|
| 533 | + if (DHD_OPMODE_STA_SOFTAP_CONCURR(dhd)) { |
---|
| 534 | + /* Unblock ARP frames */ |
---|
| 535 | + wl_cfg80211_block_arp(dev, FALSE); |
---|
| 536 | + } else |
---|
| 537 | +#endif /* APSTA_BLOCK_ARP_DURING_DHCP */ |
---|
511 | 538 | if (dhd->early_suspended) { |
---|
| 539 | + /* Enable packet filtering */ |
---|
512 | 540 | WL_TRACE_HW4(("DHCP is complete , enable packet filter!!!\n")); |
---|
513 | 541 | dhd_enable_packet_filter(1, dhd); |
---|
514 | 542 | } |
---|
515 | 543 | #endif /* PKT_FILTER_SUPPORT */ |
---|
516 | 544 | |
---|
517 | 545 | /* Restoring PM mode */ |
---|
| 546 | +#ifndef OEM_ANDROID |
---|
| 547 | + dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); |
---|
| 548 | +#endif // endif |
---|
518 | 549 | |
---|
519 | 550 | /* Stop any bt timer because DHCP session is done */ |
---|
520 | 551 | WL_TRACE(("disable BT DHCP Timer\n")); |
---|
.. | .. |
---|
557 | 588 | WL_ERR(("Unkwown yet power setting, ignored\n")); |
---|
558 | 589 | } |
---|
559 | 590 | |
---|
560 | | - snprintf(command, 3, "OK"); |
---|
561 | | - |
---|
562 | | - return (strlen("OK")); |
---|
| 591 | + return (snprintf(command, sizeof("OK"), "OK") + 1); |
---|
563 | 592 | } |
---|
| 593 | +#endif /* defined(OEM_ANDROID) */ |
---|