.. | .. |
---|
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_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 $ |
---|
29 | 30 | */ |
---|
30 | 31 | |
---|
31 | 32 | #include <linux/vmalloc.h> |
---|
.. | .. |
---|
39 | 40 | #ifdef PKT_FILTER_SUPPORT |
---|
40 | 41 | #include <dngl_stats.h> |
---|
41 | 42 | #include <dhd.h> |
---|
42 | | -#endif |
---|
43 | | - |
---|
44 | | -extern struct bcm_cfg80211 *g_bcm_cfg; |
---|
| 43 | +#endif // endif |
---|
45 | 44 | |
---|
46 | 45 | #ifdef PKT_FILTER_SUPPORT |
---|
47 | 46 | extern uint dhd_pkt_filter_enable; |
---|
48 | 47 | extern uint dhd_master_mode; |
---|
49 | 48 | extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode); |
---|
50 | | -#endif |
---|
| 49 | +#endif // endif |
---|
51 | 50 | |
---|
52 | 51 | static int dhd_dongle_up = FALSE; |
---|
53 | 52 | |
---|
.. | .. |
---|
60 | 59 | |
---|
61 | 60 | static s32 wl_dongle_up(struct net_device *ndev); |
---|
62 | 61 | 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 */ |
---|
63 | 72 | |
---|
64 | 73 | /** |
---|
65 | 74 | * Function implementations |
---|
.. | .. |
---|
81 | 90 | { |
---|
82 | 91 | struct net_device *ndev; |
---|
83 | 92 | s32 err = 0; |
---|
| 93 | + dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub); |
---|
84 | 94 | |
---|
85 | 95 | 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; |
---|
89 | 100 | } |
---|
90 | | - |
---|
91 | 101 | ndev = bcmcfg_to_prmry_ndev(cfg); |
---|
92 | 102 | wl_dongle_down(ndev); |
---|
| 103 | +done: |
---|
93 | 104 | dhd_dongle_up = FALSE; |
---|
94 | | - return 0; |
---|
| 105 | + return err; |
---|
95 | 106 | } |
---|
96 | 107 | |
---|
97 | 108 | s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val) |
---|
.. | .. |
---|
127 | 138 | return 0; |
---|
128 | 139 | } |
---|
129 | 140 | |
---|
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) |
---|
132 | 152 | { |
---|
133 | 153 | return dhd_allocate_if(cfg->pub, ifidx, name, mac, bssidx, FALSE, dngl_name); |
---|
134 | 154 | } |
---|
135 | 155 | |
---|
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) |
---|
137 | 158 | { |
---|
138 | | - return dhd_register_if(cfg->pub, ifidx, FALSE); |
---|
| 159 | + return dhd_register_if(cfg->pub, ifidx, rtnl_lock_reqd); |
---|
139 | 160 | } |
---|
140 | 161 | |
---|
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) |
---|
142 | 164 | { |
---|
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); |
---|
144 | 180 | } |
---|
145 | 181 | |
---|
146 | 182 | struct net_device * dhd_cfg80211_netdev_free(struct net_device *ndev) |
---|
147 | 183 | { |
---|
| 184 | + struct bcm_cfg80211 *cfg; |
---|
| 185 | + |
---|
148 | 186 | if (ndev) { |
---|
| 187 | + cfg = wl_get_cfg(ndev); |
---|
149 | 188 | if (ndev->ieee80211_ptr) { |
---|
150 | | - kfree(ndev->ieee80211_ptr); |
---|
| 189 | + MFREE(cfg->osh, ndev->ieee80211_ptr, sizeof(struct wireless_dev)); |
---|
151 | 190 | ndev->ieee80211_ptr = NULL; |
---|
152 | 191 | } |
---|
153 | 192 | free_netdev(ndev); |
---|
.. | .. |
---|
161 | 200 | { |
---|
162 | 201 | #ifdef WL_CFG80211 |
---|
163 | 202 | ndev = dhd_cfg80211_netdev_free(ndev); |
---|
164 | | -#endif |
---|
| 203 | +#endif // endif |
---|
165 | 204 | if (ndev) |
---|
166 | 205 | free_netdev(ndev); |
---|
167 | 206 | } |
---|
.. | .. |
---|
170 | 209 | wl_dongle_up(struct net_device *ndev) |
---|
171 | 210 | { |
---|
172 | 211 | s32 err = 0; |
---|
173 | | - u32 up = 0; |
---|
| 212 | + u32 local_up = 0; |
---|
174 | 213 | |
---|
175 | | - err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true); |
---|
| 214 | + err = wldev_ioctl_set(ndev, WLC_UP, &local_up, sizeof(local_up)); |
---|
176 | 215 | if (unlikely(err)) { |
---|
177 | 216 | WL_ERR(("WLC_UP error (%d)\n", err)); |
---|
178 | 217 | } |
---|
.. | .. |
---|
183 | 222 | wl_dongle_down(struct net_device *ndev) |
---|
184 | 223 | { |
---|
185 | 224 | s32 err = 0; |
---|
186 | | - u32 down = 0; |
---|
| 225 | + u32 local_down = 0; |
---|
187 | 226 | |
---|
188 | | - err = wldev_ioctl(ndev, WLC_DOWN, &down, sizeof(down), true); |
---|
| 227 | + err = wldev_ioctl_set(ndev, WLC_DOWN, &local_down, sizeof(local_down)); |
---|
189 | 228 | if (unlikely(err)) { |
---|
190 | 229 | WL_ERR(("WLC_DOWN error (%d)\n", err)); |
---|
191 | 230 | } |
---|
192 | 231 | return err; |
---|
193 | 232 | } |
---|
194 | 233 | |
---|
| 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 */ |
---|
195 | 477 | |
---|
196 | 478 | s32 dhd_config_dongle(struct bcm_cfg80211 *cfg) |
---|
197 | 479 | { |
---|
198 | 480 | #ifndef DHD_SDALIGN |
---|
199 | 481 | #define DHD_SDALIGN 32 |
---|
200 | | -#endif |
---|
| 482 | +#endif // endif |
---|
201 | 483 | struct net_device *ndev; |
---|
202 | 484 | s32 err = 0; |
---|
| 485 | +#if !defined(OEM_ANDROID) && defined(BCMSDIO) |
---|
| 486 | + s32 glom = CUSTOM_GLOM_SETTING; |
---|
| 487 | +#endif // endif |
---|
203 | 488 | |
---|
204 | 489 | WL_TRACE(("In\n")); |
---|
205 | 490 | if (dhd_dongle_up) { |
---|
.. | .. |
---|
214 | 499 | WL_ERR(("wl_dongle_up failed\n")); |
---|
215 | 500 | goto default_conf_out; |
---|
216 | 501 | } |
---|
| 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 */ |
---|
217 | 528 | dhd_dongle_up = true; |
---|
218 | 529 | |
---|
219 | 530 | default_conf_out: |
---|
.. | .. |
---|
227 | 538 | { |
---|
228 | 539 | struct net_device *ndev = NULL; |
---|
229 | 540 | dhd_pub_t *dhd; |
---|
230 | | - dhd_ioctl_t ioc = { 0 }; |
---|
| 541 | + dhd_ioctl_t ioc = { 0, NULL, 0, 0, 0, 0, 0}; |
---|
231 | 542 | int ret = 0; |
---|
232 | 543 | int8 index; |
---|
233 | 544 | |
---|
.. | .. |
---|
235 | 546 | |
---|
236 | 547 | dhd = cfg->pub; |
---|
237 | 548 | 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 | | - } |
---|
246 | 549 | |
---|
247 | 550 | ndev = wdev_to_wlc_ndev(wdev, cfg); |
---|
248 | 551 | index = dhd_net2idx(dhd->info, ndev); |
---|
.. | .. |
---|
256 | 559 | ioc.len = nlioc->len; |
---|
257 | 560 | ioc.set = nlioc->set; |
---|
258 | 561 | ioc.driver = nlioc->magic; |
---|
| 562 | + ioc.buf = buf; |
---|
259 | 563 | ret = dhd_ioctl_process(dhd, index, &ioc, buf); |
---|
260 | 564 | if (ret) { |
---|
261 | 565 | WL_TRACE(("dhd_ioctl_process return err %d\n", ret)); |
---|