.. | .. |
---|
1 | | -/* SPDX-License-Identifier: GPL-2.0 */ |
---|
2 | 1 | /* |
---|
3 | 2 | * Broadcom Dongle Host Driver (DHD), Linux-specific network interface |
---|
4 | 3 | * Basically selected code segments from usb-cdc.c and usb-rndis.c |
---|
5 | 4 | * |
---|
6 | | - * Copyright (C) 1999-2019, Broadcom Corporation |
---|
7 | | - * |
---|
| 5 | + * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation |
---|
| 6 | + * |
---|
| 7 | + * Copyright (C) 1999-2017, Broadcom Corporation |
---|
| 8 | + * |
---|
8 | 9 | * Unless you and Broadcom execute a separate written software license |
---|
9 | 10 | * agreement governing use of this software, this software is licensed to you |
---|
10 | 11 | * under the terms of the GNU General Public License version 2 (the "GPL"), |
---|
11 | 12 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the |
---|
12 | 13 | * following added to such license: |
---|
13 | | - * |
---|
| 14 | + * |
---|
14 | 15 | * As a special exception, the copyright holders of this software give you |
---|
15 | 16 | * permission to link this software with independent modules, and to copy and |
---|
16 | 17 | * distribute the resulting executable under terms of your choice, provided that |
---|
.. | .. |
---|
18 | 19 | * the license of that module. An independent module is a module which is not |
---|
19 | 20 | * derived from this software. The special exception does not apply to any |
---|
20 | 21 | * modifications of the software. |
---|
21 | | - * |
---|
| 22 | + * |
---|
22 | 23 | * Notwithstanding the above, under no circumstances may you combine this |
---|
23 | 24 | * software in any way with any other Broadcom software provided under a license |
---|
24 | 25 | * other than the GPL, without Broadcom's express prior written consent. |
---|
.. | .. |
---|
26 | 27 | * |
---|
27 | 28 | * <<Broadcom-WL-IPTag/Open:>> |
---|
28 | 29 | * |
---|
29 | | - * $Id: dhd_linux.c 715966 2019-05-30 02:36:59Z $ |
---|
| 30 | + * $Id: dhd_linux.c 702611 2017-06-02 06:40:15Z $ |
---|
30 | 31 | */ |
---|
31 | 32 | |
---|
32 | 33 | #include <typedefs.h> |
---|
33 | 34 | #include <linuxver.h> |
---|
34 | 35 | #include <osl.h> |
---|
| 36 | +#include <bcmstdlib_s.h> |
---|
35 | 37 | #ifdef SHOW_LOGTRACE |
---|
36 | 38 | #include <linux/syscalls.h> |
---|
37 | 39 | #include <event_log.h> |
---|
38 | 40 | #endif /* SHOW_LOGTRACE */ |
---|
39 | 41 | |
---|
| 42 | +#ifdef PCIE_FULL_DONGLE |
---|
| 43 | +#include <bcmmsgbuf.h> |
---|
| 44 | +#endif /* PCIE_FULL_DONGLE */ |
---|
40 | 45 | |
---|
41 | 46 | #include <linux/init.h> |
---|
42 | 47 | #include <linux/kernel.h> |
---|
.. | .. |
---|
54 | 59 | #include <linux/ip.h> |
---|
55 | 60 | #include <linux/reboot.h> |
---|
56 | 61 | #include <linux/notifier.h> |
---|
| 62 | +#include <linux/irq.h> |
---|
57 | 63 | #include <net/addrconf.h> |
---|
58 | 64 | #ifdef ENABLE_ADAPTIVE_SCHED |
---|
59 | 65 | #include <linux/cpufreq.h> |
---|
60 | 66 | #endif /* ENABLE_ADAPTIVE_SCHED */ |
---|
61 | | - |
---|
62 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) |
---|
63 | | -#include <uapi/linux/sched/types.h> |
---|
64 | | -#include <linux/sched/signal.h> |
---|
65 | | -#endif |
---|
66 | | -#include <linux/uaccess.h> |
---|
| 67 | +#include <linux/rtc.h> |
---|
| 68 | +#include <linux/namei.h> |
---|
| 69 | +#include <asm/uaccess.h> |
---|
67 | 70 | #include <asm/unaligned.h> |
---|
| 71 | +#include <dhd_linux_priv.h> |
---|
| 72 | + |
---|
| 73 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) |
---|
| 74 | +#include <uapi/linux/sched/types.h> |
---|
| 75 | +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */ |
---|
68 | 76 | |
---|
69 | 77 | #include <epivers.h> |
---|
70 | 78 | #include <bcmutils.h> |
---|
71 | 79 | #include <bcmendian.h> |
---|
72 | 80 | #include <bcmdevs.h> |
---|
| 81 | +#include <bcmiov.h> |
---|
73 | 82 | |
---|
74 | | -#include <proto/ethernet.h> |
---|
75 | | -#include <proto/bcmevent.h> |
---|
76 | | -#include <proto/vlan.h> |
---|
77 | | -#include <proto/802.3.h> |
---|
| 83 | +#include <ethernet.h> |
---|
| 84 | +#include <bcmevent.h> |
---|
| 85 | +#include <vlan.h> |
---|
| 86 | +#include <802.3.h> |
---|
78 | 87 | |
---|
79 | | -#include <dngl_stats.h> |
---|
80 | 88 | #include <dhd_linux_wq.h> |
---|
81 | 89 | #include <dhd.h> |
---|
82 | | -#include <dhd_debug.h> |
---|
83 | 90 | #include <dhd_linux.h> |
---|
| 91 | +#include <dhd_linux_pktdump.h> |
---|
84 | 92 | #ifdef DHD_WET |
---|
85 | 93 | #include <dhd_wet.h> |
---|
86 | 94 | #endif /* DHD_WET */ |
---|
87 | 95 | #ifdef PCIE_FULL_DONGLE |
---|
88 | 96 | #include <dhd_flowring.h> |
---|
89 | | -#endif |
---|
| 97 | +#endif // endif |
---|
90 | 98 | #include <dhd_bus.h> |
---|
91 | 99 | #include <dhd_proto.h> |
---|
92 | 100 | #include <dhd_dbg.h> |
---|
93 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 101 | +#include <dhd_dbg_ring.h> |
---|
| 102 | +#include <dhd_debug.h> |
---|
| 103 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
94 | 104 | #include <linux/wakelock.h> |
---|
95 | | -#endif |
---|
96 | | -#ifdef WL_CFG80211 |
---|
| 105 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
| 106 | +#if defined(WL_CFG80211) |
---|
97 | 107 | #include <wl_cfg80211.h> |
---|
98 | | -#endif |
---|
| 108 | +#ifdef WL_BAM |
---|
| 109 | +#include <wl_bam.h> |
---|
| 110 | +#endif /* WL_BAM */ |
---|
| 111 | +#endif /* WL_CFG80211 */ |
---|
99 | 112 | #ifdef PNO_SUPPORT |
---|
100 | 113 | #include <dhd_pno.h> |
---|
101 | | -#endif |
---|
| 114 | +#endif // endif |
---|
102 | 115 | #ifdef RTT_SUPPORT |
---|
103 | 116 | #include <dhd_rtt.h> |
---|
104 | | -#endif |
---|
| 117 | +#endif // endif |
---|
105 | 118 | |
---|
106 | | -#ifdef CONFIG_COMPAT |
---|
107 | | -#include <linux/compat.h> |
---|
108 | | -#endif |
---|
109 | | - |
---|
110 | | -#ifdef DHD_WMF |
---|
111 | | -#include <dhd_wmf_linux.h> |
---|
112 | | -#endif /* DHD_WMF */ |
---|
| 119 | +#if defined(CONFIG_SOC_EXYNOS8895) || defined(CONFIG_SOC_EXYNOS9810) || \ |
---|
| 120 | + defined(CONFIG_SOC_EXYNOS9820) |
---|
| 121 | +#include <linux/exynos-pci-ctrl.h> |
---|
| 122 | +#endif /* CONFIG_SOC_EXYNOS8895 || CONFIG_SOC_EXYNOS9810 || CONFIG_SOC_EXYNOS9820 */ |
---|
113 | 123 | |
---|
114 | 124 | #ifdef DHD_L2_FILTER |
---|
115 | | -#include <proto/bcmicmp.h> |
---|
| 125 | +#include <bcmicmp.h> |
---|
116 | 126 | #include <bcm_l2_filter.h> |
---|
117 | 127 | #include <dhd_l2_filter.h> |
---|
118 | 128 | #endif /* DHD_L2_FILTER */ |
---|
.. | .. |
---|
121 | 131 | #include <dhd_psta.h> |
---|
122 | 132 | #endif /* DHD_PSTA */ |
---|
123 | 133 | |
---|
| 134 | +#ifdef AMPDU_VO_ENABLE |
---|
| 135 | +#include <802.1d.h> |
---|
| 136 | +#endif /* AMPDU_VO_ENABLE */ |
---|
| 137 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) |
---|
| 138 | +#include <uapi/linux/sched/types.h> |
---|
| 139 | +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */ |
---|
124 | 140 | |
---|
125 | | -#ifdef DHDTCPACK_SUPPRESS |
---|
| 141 | +#if defined(DHDTCPACK_SUPPRESS) || defined(DHDTCPSYNC_FLOOD_BLK) |
---|
126 | 142 | #include <dhd_ip.h> |
---|
127 | | -#endif /* DHDTCPACK_SUPPRESS */ |
---|
| 143 | +#endif /* DHDTCPACK_SUPPRESS || DHDTCPSYNC_FLOOD_BLK */ |
---|
| 144 | +#include <dhd_daemon.h> |
---|
| 145 | +#ifdef DHD_PKT_LOGGING |
---|
| 146 | +#include <dhd_pktlog.h> |
---|
| 147 | +#endif /* DHD_PKT_LOGGING */ |
---|
| 148 | +#ifdef DHD_4WAYM4_FAIL_DISCONNECT |
---|
| 149 | +#include <eapol.h> |
---|
| 150 | +#endif /* DHD_4WAYM4_FAIL_DISCONNECT */ |
---|
128 | 151 | |
---|
| 152 | +#ifdef DHD_BANDSTEER |
---|
| 153 | +#include <dhd_bandsteer.h> |
---|
| 154 | +#endif /* DHD_BANDSTEER */ |
---|
129 | 155 | #ifdef DHD_DEBUG_PAGEALLOC |
---|
130 | 156 | typedef void (*page_corrupt_cb_t)(void *handle, void *addr_corrupt, size_t len); |
---|
131 | 157 | void dhd_page_corrupt_cb(void *handle, void *addr_corrupt, size_t len); |
---|
132 | 158 | extern void register_page_corrupt_cb(page_corrupt_cb_t cb, void* handle); |
---|
133 | 159 | #endif /* DHD_DEBUG_PAGEALLOC */ |
---|
134 | 160 | |
---|
135 | | -static void dhd_tcp_dump(char *ifname, uint8 *pktdata, bool tx); |
---|
| 161 | +#define IP_PROT_RESERVED 0xFF |
---|
136 | 162 | |
---|
137 | | -#if defined(DHD_LB) |
---|
138 | | -/* Dynamic CPU selection for load balancing */ |
---|
139 | | -#include <linux/cpu.h> |
---|
140 | | -#include <linux/cpumask.h> |
---|
141 | | -#include <linux/notifier.h> |
---|
142 | | -#include <linux/workqueue.h> |
---|
143 | | -#include <asm/atomic.h> |
---|
144 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) |
---|
145 | | -#include <linux/cpuhotplug.h> |
---|
146 | | -#endif |
---|
| 163 | +#ifdef DHD_4WAYM4_FAIL_DISCONNECT |
---|
| 164 | +static void dhd_m4_state_handler(struct work_struct * work); |
---|
| 165 | +#endif /* DHD_4WAYM4_FAIL_DISCONNECT */ |
---|
147 | 166 | |
---|
148 | | -#if !defined(DHD_LB_PRIMARY_CPUS) |
---|
149 | | -#define DHD_LB_PRIMARY_CPUS 0x0 /* Big CPU coreids mask */ |
---|
150 | | -#endif |
---|
| 167 | +#ifdef DHDTCPSYNC_FLOOD_BLK |
---|
| 168 | +static void dhd_blk_tsfl_handler(struct work_struct * work); |
---|
| 169 | +#endif /* DHDTCPSYNC_FLOOD_BLK */ |
---|
151 | 170 | |
---|
152 | | -#if !defined(DHD_LB_SECONDARY_CPUS) |
---|
153 | | -#define DHD_LB_SECONDARY_CPUS 0xFE /* Little CPU coreids mask */ |
---|
154 | | -#endif |
---|
| 171 | +#ifdef WL_NATOE |
---|
| 172 | +#include <dhd_linux_nfct.h> |
---|
| 173 | +#endif /* WL_NATOE */ |
---|
155 | 174 | |
---|
156 | | -#if (NR_CPUS > 8) |
---|
157 | | -#undef NR_CPUS |
---|
158 | | -#define NR_CPUS 8 |
---|
159 | | -#endif |
---|
160 | | -#define HIST_BIN_SIZE 8 |
---|
161 | | - |
---|
162 | | -#if defined(DHD_LB_RXP) |
---|
163 | | -static void dhd_rx_napi_dispatcher_fn(struct work_struct * work); |
---|
164 | | -#endif /* DHD_LB_RXP */ |
---|
165 | | - |
---|
166 | | -#endif /* DHD_LB */ |
---|
167 | | - |
---|
168 | | -#ifdef WLMEDIA_HTSF |
---|
169 | | -#include <linux/time.h> |
---|
170 | | -#include <htsf.h> |
---|
171 | | - |
---|
172 | | -#define HTSF_MINLEN 200 /* min. packet length to timestamp */ |
---|
173 | | -#define HTSF_BUS_DELAY 150 /* assume a fix propagation in us */ |
---|
174 | | -#define TSMAX 1000 /* max no. of timing record kept */ |
---|
175 | | -#define NUMBIN 34 |
---|
176 | | - |
---|
177 | | -static uint32 tsidx = 0; |
---|
178 | | -static uint32 htsf_seqnum = 0; |
---|
179 | | -uint32 tsfsync; |
---|
180 | | -struct timeval tsync; |
---|
181 | | -static uint32 tsport = 5010; |
---|
182 | | - |
---|
183 | | -typedef struct histo_ { |
---|
184 | | - uint32 bin[NUMBIN]; |
---|
185 | | -} histo_t; |
---|
186 | | - |
---|
187 | | -#if !ISPOWEROF2(DHD_SDALIGN) |
---|
188 | | -#error DHD_SDALIGN is not a power of 2! |
---|
189 | | -#endif |
---|
190 | | - |
---|
191 | | -static histo_t vi_d1, vi_d2, vi_d3, vi_d4; |
---|
192 | | -#endif /* WLMEDIA_HTSF */ |
---|
193 | | - |
---|
194 | | -#ifdef STBLINUX |
---|
195 | | -#ifdef quote_str |
---|
196 | | -#undef quote_str |
---|
197 | | -#endif /* quote_str */ |
---|
198 | | -#ifdef to_str |
---|
199 | | -#undef to_str |
---|
200 | | -#endif /* quote_str */ |
---|
201 | | -#define to_str(s) #s |
---|
202 | | -#define quote_str(s) to_str(s) |
---|
203 | | - |
---|
204 | | -static char *driver_target = "driver_target: "quote_str(BRCM_DRIVER_TARGET); |
---|
205 | | -#endif /* STBLINUX */ |
---|
206 | | - |
---|
207 | | - |
---|
208 | | - |
---|
209 | | -#if defined(SOFTAP) |
---|
| 175 | +#if defined(OEM_ANDROID) && defined(SOFTAP) |
---|
210 | 176 | extern bool ap_cfg_running; |
---|
211 | 177 | extern bool ap_fw_loaded; |
---|
212 | | -#endif |
---|
| 178 | +#endif // endif |
---|
| 179 | + |
---|
| 180 | +#ifdef FIX_CPU_MIN_CLOCK |
---|
| 181 | +#include <linux/pm_qos.h> |
---|
| 182 | +#endif /* FIX_CPU_MIN_CLOCK */ |
---|
213 | 183 | |
---|
214 | 184 | #ifdef SET_RANDOM_MAC_SOFTAP |
---|
215 | 185 | #ifndef CONFIG_DHD_SET_RANDOM_MAC_VAL |
---|
216 | 186 | #define CONFIG_DHD_SET_RANDOM_MAC_VAL 0x001A11 |
---|
217 | | -#endif |
---|
| 187 | +#endif // endif |
---|
218 | 188 | static u32 vendor_oui = CONFIG_DHD_SET_RANDOM_MAC_VAL; |
---|
219 | 189 | #endif /* SET_RANDOM_MAC_SOFTAP */ |
---|
| 190 | + |
---|
220 | 191 | #ifdef ENABLE_ADAPTIVE_SCHED |
---|
221 | 192 | #define DEFAULT_CPUFREQ_THRESH 1000000 /* threshold frequency : 1000000 = 1GHz */ |
---|
222 | 193 | #ifndef CUSTOM_CPUFREQ_THRESH |
---|
.. | .. |
---|
227 | 198 | /* enable HOSTIP cache update from the host side when an eth0:N is up */ |
---|
228 | 199 | #define AOE_IP_ALIAS_SUPPORT 1 |
---|
229 | 200 | |
---|
230 | | -#ifdef BCM_FD_AGGR |
---|
231 | | -#include <bcm_rpc.h> |
---|
232 | | -#include <bcm_rpc_tp.h> |
---|
233 | | -#endif |
---|
234 | 201 | #ifdef PROP_TXSTATUS |
---|
235 | 202 | #include <wlfc_proto.h> |
---|
236 | 203 | #include <dhd_wlfc.h> |
---|
237 | | -#endif |
---|
| 204 | +#endif // endif |
---|
238 | 205 | |
---|
| 206 | +#if defined(OEM_ANDROID) |
---|
239 | 207 | #include <wl_android.h> |
---|
| 208 | +#endif // endif |
---|
240 | 209 | |
---|
241 | 210 | /* Maximum STA per radio */ |
---|
242 | 211 | #define DHD_MAX_STA 32 |
---|
243 | 212 | |
---|
244 | | - |
---|
245 | | - |
---|
246 | | - |
---|
247 | | -#ifdef HOST_FLAG |
---|
248 | | -int hostsleep = 0; |
---|
249 | | -#endif |
---|
| 213 | +#ifdef DHD_EVENT_LOG_FILTER |
---|
| 214 | +#include <dhd_event_log_filter.h> |
---|
| 215 | +#endif /* DHD_EVENT_LOG_FILTER */ |
---|
250 | 216 | |
---|
251 | 217 | const uint8 wme_fifo2ac[] = { 0, 1, 2, 3, 1, 1 }; |
---|
252 | 218 | const uint8 prio2fifo[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; |
---|
.. | .. |
---|
265 | 231 | static bool dhd_inetaddr_notifier_registered = FALSE; |
---|
266 | 232 | #endif /* ARP_OFFLOAD_SUPPORT */ |
---|
267 | 233 | |
---|
268 | | -#if defined(CONFIG_IPV6) |
---|
269 | | -static int dhd_inet6addr_notifier_call(struct notifier_block *this, |
---|
| 234 | +#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT) |
---|
| 235 | +int dhd_inet6addr_notifier_call(struct notifier_block *this, |
---|
270 | 236 | unsigned long event, void *ptr); |
---|
271 | 237 | static struct notifier_block dhd_inet6addr_notifier = { |
---|
272 | 238 | .notifier_call = dhd_inet6addr_notifier_call |
---|
.. | .. |
---|
275 | 241 | * created in kernel notifier link list (with 'next' pointing to itself) |
---|
276 | 242 | */ |
---|
277 | 243 | static bool dhd_inet6addr_notifier_registered = FALSE; |
---|
278 | | -#endif /* OEM_ANDROID && CONFIG_IPV6 */ |
---|
| 244 | +#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */ |
---|
279 | 245 | |
---|
280 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) |
---|
| 246 | +#if defined(CONFIG_PM_SLEEP) |
---|
281 | 247 | #include <linux/suspend.h> |
---|
282 | 248 | volatile bool dhd_mmc_suspend = FALSE; |
---|
283 | 249 | DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait); |
---|
284 | | -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ |
---|
| 250 | +#endif /* defined(CONFIG_PM_SLEEP) */ |
---|
285 | 251 | |
---|
286 | | -#if defined(OOB_INTR_ONLY) |
---|
| 252 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) |
---|
287 | 253 | extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable); |
---|
288 | | -#endif |
---|
289 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) |
---|
290 | | -static void dhd_hang_process(void *dhd_info, void *event_data, u8 event); |
---|
291 | | -#endif |
---|
292 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) |
---|
| 254 | +#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ |
---|
| 255 | +#if defined(OEM_ANDROID) |
---|
| 256 | +static void dhd_hang_process(struct work_struct *work_data); |
---|
| 257 | +#endif /* #OEM_ANDROID */ |
---|
293 | 258 | MODULE_LICENSE("GPL and additional rights"); |
---|
294 | | -#endif /* LinuxVer */ |
---|
| 259 | +MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); |
---|
295 | 260 | |
---|
296 | | -#ifdef BCMDBUS |
---|
297 | | -#include <dbus.h> |
---|
298 | | -extern int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex); |
---|
299 | | -extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex); |
---|
300 | | -extern void dhd_bus_unregister(void); |
---|
| 261 | +#ifdef CONFIG_BCM_DETECT_CONSECUTIVE_HANG |
---|
| 262 | +#define MAX_CONSECUTIVE_HANG_COUNTS 5 |
---|
| 263 | +#endif /* CONFIG_BCM_DETECT_CONSECUTIVE_HANG */ |
---|
301 | 264 | |
---|
302 | | -#ifdef BCMSDIO |
---|
303 | | -extern bool dhd_bus_dpc(struct dhd_bus *bus); |
---|
304 | | -#endif /* BCMSDIO */ |
---|
305 | | -#else |
---|
306 | 265 | #include <dhd_bus.h> |
---|
307 | | -#endif /* BCMDBUS */ |
---|
308 | 266 | |
---|
309 | 267 | #ifdef DHD_ULP |
---|
310 | 268 | #include <dhd_ulp.h> |
---|
311 | 269 | #endif /* DHD_ULP */ |
---|
312 | 270 | |
---|
313 | | -#ifdef BCM_FD_AGGR |
---|
314 | | -#define DBUS_RX_BUFFER_SIZE_DHD(net) (BCM_RPC_TP_DNGL_AGG_MAX_BYTE) |
---|
315 | | -#else |
---|
316 | 271 | #ifndef PROP_TXSTATUS |
---|
317 | 272 | #define DBUS_RX_BUFFER_SIZE_DHD(net) (net->mtu + net->hard_header_len + dhd->pub.hdrlen) |
---|
318 | 273 | #else |
---|
319 | 274 | #define DBUS_RX_BUFFER_SIZE_DHD(net) (net->mtu + net->hard_header_len + dhd->pub.hdrlen + 128) |
---|
320 | | -#endif |
---|
321 | | -#endif /* BCM_FD_AGGR */ |
---|
| 275 | +#endif // endif |
---|
322 | 276 | |
---|
323 | 277 | #ifdef PROP_TXSTATUS |
---|
324 | | -extern bool dhd_wlfc_skip_fc(void); |
---|
| 278 | +extern bool dhd_wlfc_skip_fc(void * dhdp, uint8 idx); |
---|
325 | 279 | extern void dhd_wlfc_plat_init(void *dhd); |
---|
326 | 280 | extern void dhd_wlfc_plat_deinit(void *dhd); |
---|
327 | 281 | #endif /* PROP_TXSTATUS */ |
---|
328 | | - |
---|
329 | | -#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) |
---|
330 | | -const char * |
---|
331 | | -print_tainted() |
---|
332 | | -{ |
---|
333 | | - return ""; |
---|
334 | | -} |
---|
335 | | -#endif /* LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) */ |
---|
| 282 | +#ifdef USE_DYNAMIC_F2_BLKSIZE |
---|
| 283 | +extern uint sd_f2_blocksize; |
---|
| 284 | +extern int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size); |
---|
| 285 | +#endif /* USE_DYNAMIC_F2_BLKSIZE */ |
---|
336 | 286 | |
---|
337 | 287 | /* Linux wireless extension support */ |
---|
338 | 288 | #if defined(WL_WIRELESS_EXT) |
---|
.. | .. |
---|
340 | 290 | extern wl_iw_extra_params_t g_wl_iw_params; |
---|
341 | 291 | #endif /* defined(WL_WIRELESS_EXT) */ |
---|
342 | 292 | |
---|
| 293 | +#ifdef CONFIG_PARTIALSUSPEND_SLP |
---|
| 294 | +#include <linux/partialsuspend_slp.h> |
---|
| 295 | +#define CONFIG_HAS_EARLYSUSPEND |
---|
| 296 | +#define DHD_USE_EARLYSUSPEND |
---|
| 297 | +#define register_early_suspend register_pre_suspend |
---|
| 298 | +#define unregister_early_suspend unregister_pre_suspend |
---|
| 299 | +#define early_suspend pre_suspend |
---|
| 300 | +#define EARLY_SUSPEND_LEVEL_BLANK_SCREEN 50 |
---|
| 301 | +#else |
---|
343 | 302 | #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) |
---|
344 | 303 | #include <linux/earlysuspend.h> |
---|
345 | 304 | #endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */ |
---|
| 305 | +#endif /* CONFIG_PARTIALSUSPEND_SLP */ |
---|
346 | 306 | |
---|
347 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) |
---|
| 307 | +#if defined(OEM_ANDROID) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) |
---|
348 | 308 | #include <linux/nl80211.h> |
---|
349 | 309 | #endif /* OEM_ANDROID && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) */ |
---|
350 | 310 | |
---|
351 | | -extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd); |
---|
| 311 | +#if defined(PKT_FILTER_SUPPORT) && defined(APF) |
---|
| 312 | +static int __dhd_apf_add_filter(struct net_device *ndev, uint32 filter_id, |
---|
| 313 | + u8* program, uint32 program_len); |
---|
| 314 | +static int __dhd_apf_config_filter(struct net_device *ndev, uint32 filter_id, |
---|
| 315 | + uint32 mode, uint32 enable); |
---|
| 316 | +static int __dhd_apf_delete_filter(struct net_device *ndev, uint32 filter_id); |
---|
| 317 | +#endif /* PKT_FILTER_SUPPORT && APF */ |
---|
352 | 318 | |
---|
353 | | -#ifdef PKT_FILTER_SUPPORT |
---|
354 | | -extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg); |
---|
355 | | -extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode); |
---|
356 | | -extern void dhd_pktfilter_offload_delete(dhd_pub_t *dhd, int id); |
---|
357 | | -#endif |
---|
| 319 | +#if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT) && defined(DHD_FW_COREDUMP) |
---|
| 320 | +static int dhd_wait_for_file_dump(dhd_pub_t *dhdp); |
---|
| 321 | +#endif /* WL_CFG80211 && DHD_FILE_DUMP_EVENT && DHD_FW_COREDUMP */ |
---|
358 | 322 | |
---|
359 | | - |
---|
360 | | -#ifdef READ_MACADDR |
---|
361 | | -extern int dhd_read_macaddr(struct dhd_info *dhd); |
---|
362 | | -#else |
---|
363 | | -static inline int dhd_read_macaddr(struct dhd_info *dhd) { return 0; } |
---|
364 | | -#endif |
---|
365 | | -#ifdef WRITE_MACADDR |
---|
366 | | -extern int dhd_write_macaddr(struct ether_addr *mac); |
---|
367 | | -#else |
---|
368 | | -static inline int dhd_write_macaddr(struct ether_addr *mac) { return 0; } |
---|
369 | | -#endif |
---|
370 | | - |
---|
371 | | - |
---|
372 | | - |
---|
373 | | - |
---|
374 | | -#if defined(TRAFFIC_MGMT_DWM) |
---|
375 | | -void traffic_mgmt_pkt_set_prio(dhd_pub_t *dhdp, void * pktbuf); |
---|
376 | | -#endif |
---|
| 323 | +#if defined(ARGOS_NOTIFY_CB) |
---|
| 324 | +/* ARGOS notifer data */ |
---|
| 325 | +static struct notifier_block argos_wifi; /* STA */ |
---|
| 326 | +static struct notifier_block argos_p2p; /* P2P */ |
---|
| 327 | +argos_rps_ctrl argos_rps_ctrl_data; |
---|
| 328 | +#endif // endif |
---|
377 | 329 | |
---|
378 | 330 | #ifdef DHD_FW_COREDUMP |
---|
379 | 331 | static void dhd_mem_dump(void *dhd_info, void *event_info, u8 event); |
---|
380 | | -int dhd_os_socram_dump(struct net_device *dev, uint32 *dump_size); |
---|
381 | 332 | #endif /* DHD_FW_COREDUMP */ |
---|
| 333 | + |
---|
| 334 | +#ifdef DHD_LOG_DUMP |
---|
| 335 | + |
---|
| 336 | +struct dhd_log_dump_buf g_dld_buf[DLD_BUFFER_NUM]; |
---|
| 337 | + |
---|
| 338 | +/* Only header for log dump buffers is stored in array |
---|
| 339 | + * header for sections like 'dhd dump', 'ext trap' |
---|
| 340 | + * etc, is not in the array, because they are not log |
---|
| 341 | + * ring buffers |
---|
| 342 | + */ |
---|
| 343 | +dld_hdr_t dld_hdrs[DLD_BUFFER_NUM] = { |
---|
| 344 | + {GENERAL_LOG_HDR, LOG_DUMP_SECTION_GENERAL}, |
---|
| 345 | + {PRESERVE_LOG_HDR, LOG_DUMP_SECTION_PRESERVE}, |
---|
| 346 | + {SPECIAL_LOG_HDR, LOG_DUMP_SECTION_SPECIAL} |
---|
| 347 | +}; |
---|
| 348 | + |
---|
| 349 | +static int dld_buf_size[DLD_BUFFER_NUM] = { |
---|
| 350 | + LOG_DUMP_GENERAL_MAX_BUFSIZE, /* DLD_BUF_TYPE_GENERAL */ |
---|
| 351 | + LOG_DUMP_PRESERVE_MAX_BUFSIZE, /* DLD_BUF_TYPE_PRESERVE */ |
---|
| 352 | + LOG_DUMP_SPECIAL_MAX_BUFSIZE, /* DLD_BUF_TYPE_SPECIAL */ |
---|
| 353 | +}; |
---|
| 354 | + |
---|
| 355 | +static void dhd_log_dump_init(dhd_pub_t *dhd); |
---|
| 356 | +static void dhd_log_dump_deinit(dhd_pub_t *dhd); |
---|
| 357 | +static void dhd_log_dump(void *handle, void *event_info, u8 event); |
---|
| 358 | +static int do_dhd_log_dump(dhd_pub_t *dhdp, log_dump_type_t *type); |
---|
| 359 | +static int dhd_log_flush(dhd_pub_t *dhdp, log_dump_type_t *type); |
---|
| 360 | +static void dhd_get_time_str(dhd_pub_t *dhdp, char *time_str, int size); |
---|
| 361 | +void dhd_get_debug_dump_len(void *handle, struct sk_buff *skb, void *event_info, u8 event); |
---|
| 362 | +void cfgvendor_log_dump_len(dhd_pub_t *dhdp, log_dump_type_t *type, struct sk_buff *skb); |
---|
| 363 | +static void dhd_print_buf_addr(dhd_pub_t *dhdp, char *name, void *buf, unsigned int size); |
---|
| 364 | +static void dhd_log_dump_buf_addr(dhd_pub_t *dhdp, log_dump_type_t *type); |
---|
| 365 | +#endif /* DHD_LOG_DUMP */ |
---|
| 366 | + |
---|
| 367 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 368 | +#include <linux/workqueue.h> |
---|
| 369 | +#include <linux/pm_runtime.h> |
---|
| 370 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
| 371 | + |
---|
| 372 | +#ifdef DHD_DEBUG_UART |
---|
| 373 | +#include <linux/kmod.h> |
---|
| 374 | +#define DHD_DEBUG_UART_EXEC_PATH "/system/bin/wldu" |
---|
| 375 | +static void dhd_debug_uart_exec_rd(void *handle, void *event_info, u8 event); |
---|
| 376 | +static void dhd_debug_uart_exec(dhd_pub_t *dhdp, char *cmd); |
---|
| 377 | +#endif /* DHD_DEBUG_UART */ |
---|
382 | 378 | |
---|
383 | 379 | static int dhd_reboot_callback(struct notifier_block *this, unsigned long code, void *unused); |
---|
384 | 380 | static struct notifier_block dhd_reboot_notifier = { |
---|
.. | .. |
---|
386 | 382 | .priority = 1, |
---|
387 | 383 | }; |
---|
388 | 384 | |
---|
| 385 | +#ifdef OEM_ANDROID |
---|
389 | 386 | #ifdef BCMPCIE |
---|
390 | 387 | static int is_reboot = 0; |
---|
391 | 388 | #endif /* BCMPCIE */ |
---|
| 389 | +#endif /* OEM_ANDROID */ |
---|
392 | 390 | |
---|
393 | | -typedef struct dhd_if_event { |
---|
394 | | - struct list_head list; |
---|
395 | | - wl_event_data_if_t event; |
---|
396 | | - char name[IFNAMSIZ+1]; |
---|
397 | | - uint8 mac[ETHER_ADDR_LEN]; |
---|
398 | | -} dhd_if_event_t; |
---|
| 391 | +dhd_pub_t *g_dhd_pub = NULL; |
---|
399 | 392 | |
---|
400 | | -/* Interface control information */ |
---|
401 | | -typedef struct dhd_if { |
---|
402 | | - struct dhd_info *info; /* back pointer to dhd_info */ |
---|
403 | | - /* OS/stack specifics */ |
---|
404 | | - struct net_device *net; |
---|
405 | | - int idx; /* iface idx in dongle */ |
---|
406 | | - uint subunit; /* subunit */ |
---|
407 | | - uint8 mac_addr[ETHER_ADDR_LEN]; /* assigned MAC address */ |
---|
408 | | - bool set_macaddress; |
---|
409 | | - bool set_multicast; |
---|
410 | | - uint8 bssidx; /* bsscfg index for the interface */ |
---|
411 | | - bool attached; /* Delayed attachment when unset */ |
---|
412 | | - bool txflowcontrol; /* Per interface flow control indicator */ |
---|
413 | | - char name[IFNAMSIZ+1]; /* linux interface name */ |
---|
414 | | - char dngl_name[IFNAMSIZ+1]; /* corresponding dongle interface name */ |
---|
415 | | - struct net_device_stats stats; |
---|
416 | | -#ifdef DHD_WMF |
---|
417 | | - dhd_wmf_t wmf; /* per bsscfg wmf setting */ |
---|
418 | | - bool wmf_psta_disable; /* enable/disable MC pkt to each mac |
---|
419 | | - * of MC group behind PSTA |
---|
420 | | - */ |
---|
421 | | -#endif /* DHD_WMF */ |
---|
422 | | -#ifdef PCIE_FULL_DONGLE |
---|
423 | | - struct list_head sta_list; /* sll of associated stations */ |
---|
424 | | -#if !defined(BCM_GMAC3) |
---|
425 | | - spinlock_t sta_list_lock; /* lock for manipulating sll */ |
---|
426 | | -#endif /* ! BCM_GMAC3 */ |
---|
427 | | -#endif /* PCIE_FULL_DONGLE */ |
---|
428 | | - uint32 ap_isolate; /* ap-isolation settings */ |
---|
429 | | -#ifdef DHD_L2_FILTER |
---|
430 | | - bool parp_enable; |
---|
431 | | - bool parp_discard; |
---|
432 | | - bool parp_allnode; |
---|
433 | | - arp_table_t *phnd_arp_table; |
---|
434 | | -/* for Per BSS modification */ |
---|
435 | | - bool dhcp_unicast; |
---|
436 | | - bool block_ping; |
---|
437 | | - bool grat_arp; |
---|
438 | | -#endif /* DHD_L2_FILTER */ |
---|
439 | | -#ifdef DHD_MCAST_REGEN |
---|
440 | | - bool mcast_regen_bss_enable; |
---|
441 | | -#endif |
---|
442 | | - bool rx_pkt_chainable; /* set all rx packet to chainable config by default */ |
---|
443 | | - cumm_ctr_t cumm_ctr; /* cummulative queue length of child flowrings */ |
---|
444 | | -} dhd_if_t; |
---|
| 393 | +#if defined(BT_OVER_SDIO) |
---|
| 394 | +#include "dhd_bt_interface.h" |
---|
| 395 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
445 | 396 | |
---|
446 | | -#ifdef WLMEDIA_HTSF |
---|
447 | | -typedef struct { |
---|
448 | | - uint32 low; |
---|
449 | | - uint32 high; |
---|
450 | | -} tsf_t; |
---|
| 397 | +#ifdef WL_STATIC_IF |
---|
| 398 | +bool dhd_is_static_ndev(dhd_pub_t *dhdp, struct net_device *ndev); |
---|
| 399 | +#endif /* WL_STATIC_IF */ |
---|
451 | 400 | |
---|
452 | | -typedef struct { |
---|
453 | | - uint32 last_cycle; |
---|
454 | | - uint32 last_sec; |
---|
455 | | - uint32 last_tsf; |
---|
456 | | - uint32 coef; /* scaling factor */ |
---|
457 | | - uint32 coefdec1; /* first decimal */ |
---|
458 | | - uint32 coefdec2; /* second decimal */ |
---|
459 | | -} htsf_t; |
---|
| 401 | +atomic_t exit_in_progress = ATOMIC_INIT(0); |
---|
460 | 402 | |
---|
461 | | -typedef struct { |
---|
462 | | - uint32 t1; |
---|
463 | | - uint32 t2; |
---|
464 | | - uint32 t3; |
---|
465 | | - uint32 t4; |
---|
466 | | -} tstamp_t; |
---|
| 403 | +static void dhd_process_daemon_msg(struct sk_buff *skb); |
---|
| 404 | +static void dhd_destroy_to_notifier_skt(void); |
---|
| 405 | +static int dhd_create_to_notifier_skt(void); |
---|
| 406 | +static struct sock *nl_to_event_sk = NULL; |
---|
| 407 | +int sender_pid = 0; |
---|
467 | 408 | |
---|
468 | | -static tstamp_t ts[TSMAX]; |
---|
469 | | -static tstamp_t maxdelayts; |
---|
470 | | -static uint32 maxdelay = 0, tspktcnt = 0, maxdelaypktno = 0; |
---|
471 | | - |
---|
472 | | -#endif /* WLMEDIA_HTSF */ |
---|
473 | | - |
---|
474 | | -struct ipv6_work_info_t { |
---|
475 | | - uint8 if_idx; |
---|
476 | | - char ipv6_addr[16]; |
---|
477 | | - unsigned long event; |
---|
| 409 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) |
---|
| 410 | +struct netlink_kernel_cfg dhd_netlink_cfg = { |
---|
| 411 | + .groups = 1, |
---|
| 412 | + .input = dhd_process_daemon_msg, |
---|
478 | 413 | }; |
---|
| 414 | +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) */ |
---|
479 | 415 | |
---|
480 | | -#ifdef DHD_DEBUG |
---|
481 | | -typedef struct dhd_dump { |
---|
482 | | - uint8 *buf; |
---|
483 | | - int bufsize; |
---|
484 | | -} dhd_dump_t; |
---|
485 | | -#endif /* DHD_DEBUG */ |
---|
486 | | - |
---|
487 | | - |
---|
488 | | -/* When Perimeter locks are deployed, any blocking calls must be preceeded |
---|
489 | | - * with a PERIM UNLOCK and followed by a PERIM LOCK. |
---|
490 | | - * Examples of blocking calls are: schedule_timeout(), down_interruptible(), |
---|
491 | | - * wait_event_timeout(). |
---|
492 | | - */ |
---|
493 | | - |
---|
494 | | -/* Local private structure (extension of pub) */ |
---|
495 | | -typedef struct dhd_info { |
---|
496 | | -#if defined(WL_WIRELESS_EXT) |
---|
497 | | - wl_iw_t iw; /* wireless extensions state (must be first) */ |
---|
498 | | -#endif /* defined(WL_WIRELESS_EXT) */ |
---|
499 | | - dhd_pub_t pub; |
---|
500 | | - dhd_if_t *iflist[DHD_MAX_IFS]; /* for supporting multiple interfaces */ |
---|
501 | | - |
---|
502 | | - void *adapter; /* adapter information, interrupt, fw path etc. */ |
---|
503 | | - char fw_path[PATH_MAX]; /* path to firmware image */ |
---|
504 | | - char nv_path[PATH_MAX]; /* path to nvram vars file */ |
---|
505 | | - |
---|
506 | | - struct semaphore proto_sem; |
---|
507 | | -#ifdef PROP_TXSTATUS |
---|
508 | | - spinlock_t wlfc_spinlock; |
---|
509 | | - |
---|
510 | | -#ifdef BCMDBUS |
---|
511 | | - ulong wlfc_lock_flags; |
---|
512 | | - ulong wlfc_pub_lock_flags; |
---|
513 | | -#endif |
---|
514 | | -#endif /* PROP_TXSTATUS */ |
---|
515 | | -#ifdef WLMEDIA_HTSF |
---|
516 | | - htsf_t htsf; |
---|
517 | | -#endif |
---|
518 | | - wait_queue_head_t ioctl_resp_wait; |
---|
519 | | - wait_queue_head_t d3ack_wait; |
---|
520 | | - wait_queue_head_t dhd_bus_busy_state_wait; |
---|
521 | | - uint32 default_wd_interval; |
---|
522 | | - |
---|
523 | | - struct timer_list timer; |
---|
524 | | - bool wd_timer_valid; |
---|
525 | | - struct tasklet_struct tasklet; |
---|
526 | | - spinlock_t sdlock; |
---|
527 | | - spinlock_t txqlock; |
---|
528 | | - spinlock_t dhd_lock; |
---|
529 | | -#ifdef BCMDBUS |
---|
530 | | - ulong txqlock_flags; |
---|
| 416 | +#if defined(BT_OVER_SDIO) |
---|
| 417 | +/* Flag to indicate if driver is initialized */ |
---|
| 418 | +uint dhd_driver_init_done = TRUE; |
---|
531 | 419 | #else |
---|
532 | | - |
---|
533 | | - struct semaphore sdsem; |
---|
534 | | - tsk_ctl_t thr_dpc_ctl; |
---|
535 | | - tsk_ctl_t thr_wdt_ctl; |
---|
536 | | -#endif /* BCMDBUS */ |
---|
537 | | - |
---|
538 | | - tsk_ctl_t thr_rxf_ctl; |
---|
539 | | - spinlock_t rxf_lock; |
---|
540 | | - bool rxthread_enabled; |
---|
541 | | - |
---|
542 | | - /* Wakelocks */ |
---|
543 | | -#if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) |
---|
544 | | - struct wake_lock wl_wifi; /* Wifi wakelock */ |
---|
545 | | - struct wake_lock wl_rxwake; /* Wifi rx wakelock */ |
---|
546 | | - struct wake_lock wl_ctrlwake; /* Wifi ctrl wakelock */ |
---|
547 | | - struct wake_lock wl_wdwake; /* Wifi wd wakelock */ |
---|
548 | | - struct wake_lock wl_evtwake; /* Wifi event wakelock */ |
---|
549 | | - struct wake_lock wl_txflwake; /* Wifi tx flow wakelock*/ |
---|
550 | | -#ifdef BCMPCIE_OOB_HOST_WAKE |
---|
551 | | - struct wake_lock wl_intrwake; /* Host wakeup wakelock */ |
---|
552 | | -#endif /* BCMPCIE_OOB_HOST_WAKE */ |
---|
553 | | -#ifdef DHD_USE_SCAN_WAKELOCK |
---|
554 | | - struct wake_lock wl_scanwake; /* Wifi scan wakelock */ |
---|
555 | | -#endif /* DHD_USE_SCAN_WAKELOCK */ |
---|
556 | | -#endif /* CONFIG_HAS_WAKELOCK && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */ |
---|
557 | | - |
---|
558 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) |
---|
559 | | - /* net_device interface lock, prevent race conditions among net_dev interface |
---|
560 | | - * calls and wifi_on or wifi_off |
---|
561 | | - */ |
---|
562 | | - struct mutex dhd_net_if_mutex; |
---|
563 | | - struct mutex dhd_suspend_mutex; |
---|
564 | | -#endif |
---|
565 | | - spinlock_t wakelock_spinlock; |
---|
566 | | - uint32 wakelock_counter; |
---|
567 | | - int wakelock_wd_counter; |
---|
568 | | - int wakelock_rx_timeout_enable; |
---|
569 | | - int wakelock_ctrl_timeout_enable; |
---|
570 | | - bool waive_wakelock; |
---|
571 | | - uint32 wakelock_before_waive; |
---|
572 | | - |
---|
573 | | - /* Thread to issue ioctl for multicast */ |
---|
574 | | - wait_queue_head_t ctrl_wait; |
---|
575 | | - atomic_t pend_8021x_cnt; |
---|
576 | | - dhd_attach_states_t dhd_state; |
---|
577 | | -#ifdef SHOW_LOGTRACE |
---|
578 | | - dhd_event_log_t event_data; |
---|
579 | | -#endif /* SHOW_LOGTRACE */ |
---|
580 | | - |
---|
581 | | -#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) |
---|
582 | | - struct early_suspend early_suspend; |
---|
583 | | -#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ |
---|
584 | | - |
---|
585 | | -#ifdef ARP_OFFLOAD_SUPPORT |
---|
586 | | - u32 pend_ipaddr; |
---|
587 | | -#endif /* ARP_OFFLOAD_SUPPORT */ |
---|
588 | | -#ifdef BCM_FD_AGGR |
---|
589 | | - void *rpc_th; |
---|
590 | | - void *rpc_osh; |
---|
591 | | - struct timer_list rpcth_timer; |
---|
592 | | - bool rpcth_timer_active; |
---|
593 | | - uint8 fdaggr; |
---|
594 | | -#endif |
---|
595 | | -#ifdef DHDTCPACK_SUPPRESS |
---|
596 | | - spinlock_t tcpack_lock; |
---|
597 | | -#endif /* DHDTCPACK_SUPPRESS */ |
---|
598 | | - void *dhd_deferred_wq; |
---|
599 | | -#ifdef DEBUG_CPU_FREQ |
---|
600 | | - struct notifier_block freq_trans; |
---|
601 | | - int __percpu *new_freq; |
---|
602 | | -#endif |
---|
603 | | - unsigned int unit; |
---|
604 | | - struct notifier_block pm_notifier; |
---|
605 | | -#ifdef DHD_PSTA |
---|
606 | | - uint32 psta_mode; /* PSTA or PSR */ |
---|
607 | | -#endif /* DHD_PSTA */ |
---|
608 | | -#ifdef DHD_WET |
---|
609 | | - uint32 wet_mode; |
---|
610 | | -#endif /* DHD_PSTA */ |
---|
611 | | -#ifdef DHD_DEBUG |
---|
612 | | - dhd_dump_t *dump; |
---|
613 | | - struct timer_list join_timer; |
---|
614 | | - u32 join_timeout_val; |
---|
615 | | - bool join_timer_active; |
---|
616 | | - uint scan_time_count; |
---|
617 | | - struct timer_list scan_timer; |
---|
618 | | - bool scan_timer_active; |
---|
619 | | -#endif |
---|
620 | | - |
---|
621 | | -#if defined(DHD_LB) |
---|
622 | | - /* CPU Load Balance dynamic CPU selection */ |
---|
623 | | - |
---|
624 | | - /* Variable that tracks the currect CPUs available for candidacy */ |
---|
625 | | - cpumask_var_t cpumask_curr_avail; |
---|
626 | | - |
---|
627 | | - /* Primary and secondary CPU mask */ |
---|
628 | | - cpumask_var_t cpumask_primary, cpumask_secondary; /* configuration */ |
---|
629 | | - cpumask_var_t cpumask_primary_new, cpumask_secondary_new; /* temp */ |
---|
630 | | - |
---|
631 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) |
---|
632 | | - struct hlist_node node_online; |
---|
633 | | -#else |
---|
634 | | - struct notifier_block cpu_notifier; |
---|
635 | | -#endif |
---|
636 | | - |
---|
637 | | - /* Tasklet to handle Tx Completion packet freeing */ |
---|
638 | | - struct tasklet_struct tx_compl_tasklet; |
---|
639 | | - atomic_t tx_compl_cpu; |
---|
640 | | - |
---|
641 | | - |
---|
642 | | - /* Tasklet to handle RxBuf Post during Rx completion */ |
---|
643 | | - struct tasklet_struct rx_compl_tasklet; |
---|
644 | | - atomic_t rx_compl_cpu; |
---|
645 | | - |
---|
646 | | - /* Napi struct for handling rx packet sendup. Packets are removed from |
---|
647 | | - * H2D RxCompl ring and placed into rx_pend_queue. rx_pend_queue is then |
---|
648 | | - * appended to rx_napi_queue (w/ lock) and the rx_napi_struct is scheduled |
---|
649 | | - * to run to rx_napi_cpu. |
---|
650 | | - */ |
---|
651 | | - struct sk_buff_head rx_pend_queue ____cacheline_aligned; |
---|
652 | | - struct sk_buff_head rx_napi_queue ____cacheline_aligned; |
---|
653 | | - struct napi_struct rx_napi_struct ____cacheline_aligned; |
---|
654 | | - atomic_t rx_napi_cpu; /* cpu on which the napi is dispatched */ |
---|
655 | | - struct net_device *rx_napi_netdev; /* netdev of primary interface */ |
---|
656 | | - |
---|
657 | | - struct work_struct rx_napi_dispatcher_work; |
---|
658 | | - struct work_struct tx_compl_dispatcher_work; |
---|
659 | | - struct work_struct rx_compl_dispatcher_work; |
---|
660 | | - /* Number of times DPC Tasklet ran */ |
---|
661 | | - uint32 dhd_dpc_cnt; |
---|
662 | | - |
---|
663 | | - /* Number of times NAPI processing got scheduled */ |
---|
664 | | - uint32 napi_sched_cnt; |
---|
665 | | - |
---|
666 | | - /* Number of times NAPI processing ran on each available core */ |
---|
667 | | - uint32 napi_percpu_run_cnt[NR_CPUS]; |
---|
668 | | - |
---|
669 | | - /* Number of times RX Completions got scheduled */ |
---|
670 | | - uint32 rxc_sched_cnt; |
---|
671 | | - /* Number of times RX Completion ran on each available core */ |
---|
672 | | - uint32 rxc_percpu_run_cnt[NR_CPUS]; |
---|
673 | | - |
---|
674 | | - /* Number of times TX Completions got scheduled */ |
---|
675 | | - uint32 txc_sched_cnt; |
---|
676 | | - /* Number of times TX Completions ran on each available core */ |
---|
677 | | - uint32 txc_percpu_run_cnt[NR_CPUS]; |
---|
678 | | - |
---|
679 | | - /* CPU status */ |
---|
680 | | - /* Number of times each CPU came online */ |
---|
681 | | - uint32 cpu_online_cnt[NR_CPUS]; |
---|
682 | | - |
---|
683 | | - /* Number of times each CPU went offline */ |
---|
684 | | - uint32 cpu_offline_cnt[NR_CPUS]; |
---|
685 | | - |
---|
686 | | - /* |
---|
687 | | - * Consumer Histogram - NAPI RX Packet processing |
---|
688 | | - * ----------------------------------------------- |
---|
689 | | - * On Each CPU, when the NAPI RX Packet processing call back was invoked |
---|
690 | | - * how many packets were processed is captured in this data structure. |
---|
691 | | - * Now its difficult to capture the "exact" number of packets processed. |
---|
692 | | - * So considering the packet counter to be a 32 bit one, we have a |
---|
693 | | - * bucket with 8 bins (2^1, 2^2 ... 2^8). The "number" of packets |
---|
694 | | - * processed is rounded off to the next power of 2 and put in the |
---|
695 | | - * approriate "bin" the value in the bin gets incremented. |
---|
696 | | - * For example, assume that in CPU 1 if NAPI Rx runs 3 times |
---|
697 | | - * and the packet count processed is as follows (assume the bin counters are 0) |
---|
698 | | - * iteration 1 - 10 (the bin counter 2^4 increments to 1) |
---|
699 | | - * iteration 2 - 30 (the bin counter 2^5 increments to 1) |
---|
700 | | - * iteration 3 - 15 (the bin counter 2^4 increments by 1 to become 2) |
---|
701 | | - */ |
---|
702 | | - uint32 napi_rx_hist[NR_CPUS][HIST_BIN_SIZE]; |
---|
703 | | - uint32 txc_hist[NR_CPUS][HIST_BIN_SIZE]; |
---|
704 | | - uint32 rxc_hist[NR_CPUS][HIST_BIN_SIZE]; |
---|
705 | | -#endif /* DHD_LB */ |
---|
706 | | - |
---|
707 | | -#if defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) |
---|
708 | | -#if defined(BCMDBUS) |
---|
709 | | - struct task_struct *fw_download_task; |
---|
710 | | - struct semaphore fw_download_lock; |
---|
711 | | -#endif /* BCMDBUS */ |
---|
712 | | -#endif /* defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) */ |
---|
713 | | - struct net_device *monitor_dev; /* monitor pseudo device */ |
---|
714 | | - uint monitor_type; /* monitor pseudo device */ |
---|
715 | | -} dhd_info_t; |
---|
716 | | - |
---|
717 | | -#define DHDIF_FWDER(dhdif) FALSE |
---|
718 | | - |
---|
719 | | -/* Flag to indicate if we should download firmware on driver load */ |
---|
720 | | -uint dhd_download_fw_on_driverload = TRUE; |
---|
721 | | - |
---|
722 | 420 | /* Flag to indicate if driver is initialized */ |
---|
723 | 421 | uint dhd_driver_init_done = FALSE; |
---|
| 422 | +#endif // endif |
---|
| 423 | +/* Flag to indicate if we should download firmware on driver load */ |
---|
| 424 | +uint dhd_download_fw_on_driverload = TRUE; |
---|
724 | 425 | |
---|
725 | 426 | /* Definitions to provide path to the firmware and nvram |
---|
726 | 427 | * example nvram_path[MOD_PARAM_PATHLEN]="/projects/wlan/nvram.txt" |
---|
727 | 428 | */ |
---|
728 | 429 | char firmware_path[MOD_PARAM_PATHLEN]; |
---|
729 | 430 | char nvram_path[MOD_PARAM_PATHLEN]; |
---|
| 431 | +char clm_path[MOD_PARAM_PATHLEN] = "/vendor/etc/firmware/cyfmac4373-sdio.clm_blob"; |
---|
| 432 | +#ifdef DHD_UCODE_DOWNLOAD |
---|
| 433 | +char ucode_path[MOD_PARAM_PATHLEN]; |
---|
| 434 | +#endif /* DHD_UCODE_DOWNLOAD */ |
---|
| 435 | + |
---|
| 436 | +module_param_string(clm_path, clm_path, MOD_PARAM_PATHLEN, 0660); |
---|
730 | 437 | |
---|
731 | 438 | /* backup buffer for firmware and nvram path */ |
---|
732 | 439 | char fw_bak_path[MOD_PARAM_PATHLEN]; |
---|
733 | 440 | char nv_bak_path[MOD_PARAM_PATHLEN]; |
---|
734 | | - |
---|
735 | | -char clm_path[MOD_PARAM_PATHLEN]; |
---|
736 | | - |
---|
737 | | -module_param_string(clm_path, clm_path, MOD_PARAM_PATHLEN, 0660); |
---|
738 | 441 | |
---|
739 | 442 | /* information string to keep firmware, chio, cheip version info visiable from log */ |
---|
740 | 443 | char info_string[MOD_PARAM_INFOLEN]; |
---|
.. | .. |
---|
742 | 445 | int op_mode = 0; |
---|
743 | 446 | int disable_proptx = 0; |
---|
744 | 447 | module_param(op_mode, int, 0644); |
---|
745 | | - |
---|
746 | | -#if defined(DHD_LB_RXP) |
---|
747 | | -static int dhd_napi_weight = 32; |
---|
748 | | -module_param(dhd_napi_weight, int, 0644); |
---|
749 | | -#endif /* DHD_LB_RXP */ |
---|
750 | | - |
---|
| 448 | +#if defined(OEM_ANDROID) |
---|
751 | 449 | extern int wl_control_wl_start(struct net_device *dev); |
---|
752 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(BCMLXSDMMC) |
---|
| 450 | +#if defined(BCMLXSDMMC) |
---|
753 | 451 | struct semaphore dhd_registration_sem; |
---|
754 | | -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ |
---|
| 452 | +#endif /* BCMXSDMMC */ |
---|
| 453 | +#endif /* defined(OEM_ANDROID) */ |
---|
| 454 | + |
---|
| 455 | +#ifdef DHD_LOG_DUMP |
---|
| 456 | +int logdump_max_filesize = LOG_DUMP_MAX_FILESIZE; |
---|
| 457 | +module_param(logdump_max_filesize, int, 0644); |
---|
| 458 | +int logdump_max_bufsize = LOG_DUMP_GENERAL_MAX_BUFSIZE; |
---|
| 459 | +module_param(logdump_max_bufsize, int, 0644); |
---|
| 460 | +int logdump_prsrv_tailsize = DHD_LOG_DUMP_MAX_TAIL_FLUSH_SIZE; |
---|
| 461 | +int logdump_periodic_flush = FALSE; |
---|
| 462 | +module_param(logdump_periodic_flush, int, 0644); |
---|
| 463 | +#ifdef EWP_ECNTRS_LOGGING |
---|
| 464 | +int logdump_ecntr_enable = TRUE; |
---|
| 465 | +#else |
---|
| 466 | +int logdump_ecntr_enable = FALSE; |
---|
| 467 | +#endif /* EWP_ECNTRS_LOGGING */ |
---|
| 468 | +module_param(logdump_ecntr_enable, int, 0644); |
---|
| 469 | +#ifdef EWP_RTT_LOGGING |
---|
| 470 | +int logdump_rtt_enable = TRUE; |
---|
| 471 | +#else |
---|
| 472 | +int logdump_rtt_enable = FALSE; |
---|
| 473 | +#endif /* EWP_RTT_LOGGING */ |
---|
| 474 | +module_param(logdump_rtt_enable, int, 0644); |
---|
| 475 | +#endif /* DHD_LOG_DUMP */ |
---|
| 476 | +#ifdef EWP_EDL |
---|
| 477 | +int host_edl_support = TRUE; |
---|
| 478 | +module_param(host_edl_support, int, 0644); |
---|
| 479 | +#endif // endif |
---|
755 | 480 | |
---|
756 | 481 | /* deferred handlers */ |
---|
757 | 482 | static void dhd_ifadd_event_handler(void *handle, void *event_info, u8 event); |
---|
758 | 483 | static void dhd_ifdel_event_handler(void *handle, void *event_info, u8 event); |
---|
| 484 | +#ifndef DHD_DIRECT_SET_MAC |
---|
759 | 485 | static void dhd_set_mac_addr_handler(void *handle, void *event_info, u8 event); |
---|
| 486 | +#endif // endif |
---|
760 | 487 | static void dhd_set_mcast_list_handler(void *handle, void *event_info, u8 event); |
---|
761 | | -#if defined(CONFIG_IPV6) |
---|
| 488 | +#ifdef WL_NATOE |
---|
| 489 | +static void dhd_natoe_ct_event_hanlder(void *handle, void *event_info, u8 event); |
---|
| 490 | +static void dhd_natoe_ct_ioctl_handler(void *handle, void *event_info, uint8 event); |
---|
| 491 | +#endif /* WL_NATOE */ |
---|
| 492 | + |
---|
| 493 | +#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT) |
---|
762 | 494 | static void dhd_inet6_work_handler(void *dhd_info, void *event_data, u8 event); |
---|
763 | | -#endif /* OEM_ANDROID && CONFIG_IPV6 */ |
---|
| 495 | +#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */ |
---|
764 | 496 | #ifdef WL_CFG80211 |
---|
765 | 497 | extern void dhd_netdev_free(struct net_device *ndev); |
---|
766 | 498 | #endif /* WL_CFG80211 */ |
---|
| 499 | +static dhd_if_t * dhd_get_ifp_by_ndev(dhd_pub_t *dhdp, struct net_device *ndev); |
---|
767 | 500 | |
---|
768 | 501 | #if (defined(DHD_WET) || defined(DHD_MCAST_REGEN) || defined(DHD_L2_FILTER)) |
---|
769 | 502 | /* update rx_pkt_chainable state of dhd interface */ |
---|
.. | .. |
---|
771 | 504 | #endif /* DHD_WET || DHD_MCAST_REGEN || DHD_L2_FILTER */ |
---|
772 | 505 | |
---|
773 | 506 | /* Error bits */ |
---|
774 | | -module_param(dhd_msg_level, int, 0664); |
---|
| 507 | +module_param(dhd_msg_level, int, 0); |
---|
775 | 508 | |
---|
776 | 509 | #ifdef ARP_OFFLOAD_SUPPORT |
---|
777 | 510 | /* ARP offload enable */ |
---|
.. | .. |
---|
780 | 513 | |
---|
781 | 514 | /* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */ |
---|
782 | 515 | |
---|
783 | | -uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY; |
---|
| 516 | +#ifdef ENABLE_ARP_SNOOP_MODE |
---|
| 517 | +uint dhd_arp_mode = (ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY | ARP_OL_SNOOP | ARP_OL_HOST_AUTO_REPLY | |
---|
| 518 | + ARP_OL_UPDATE_HOST_CACHE); |
---|
| 519 | +#else |
---|
| 520 | +uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY | ARP_OL_UPDATE_HOST_CACHE; |
---|
| 521 | +#endif /* ENABLE_ARP_SNOOP_MODE */ |
---|
784 | 522 | |
---|
785 | 523 | module_param(dhd_arp_mode, uint, 0); |
---|
786 | 524 | #endif /* ARP_OFFLOAD_SUPPORT */ |
---|
.. | .. |
---|
790 | 528 | /* load firmware and/or nvram values from the filesystem */ |
---|
791 | 529 | module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660); |
---|
792 | 530 | module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0660); |
---|
| 531 | +#ifdef DHD_UCODE_DOWNLOAD |
---|
| 532 | +module_param_string(ucode_path, ucode_path, MOD_PARAM_PATHLEN, 0660); |
---|
| 533 | +#endif /* DHD_UCODE_DOWNLOAD */ |
---|
| 534 | + |
---|
| 535 | +/* wl event forwarding */ |
---|
| 536 | +#ifdef WL_EVENT_ENAB |
---|
| 537 | +uint wl_event_enable = true; |
---|
| 538 | +#else |
---|
| 539 | +uint wl_event_enable = false; |
---|
| 540 | +#endif /* WL_EVENT_ENAB */ |
---|
| 541 | +module_param(wl_event_enable, uint, 0660); |
---|
| 542 | + |
---|
| 543 | +/* wl event forwarding */ |
---|
| 544 | +#ifdef LOGTRACE_PKT_SENDUP |
---|
| 545 | +uint logtrace_pkt_sendup = true; |
---|
| 546 | +#else |
---|
| 547 | +uint logtrace_pkt_sendup = false; |
---|
| 548 | +#endif /* LOGTRACE_PKT_SENDUP */ |
---|
| 549 | +module_param(logtrace_pkt_sendup, uint, 0660); |
---|
793 | 550 | |
---|
794 | 551 | /* Watchdog interval */ |
---|
795 | | - |
---|
796 | 552 | /* extend watchdog expiration to 2 seconds when DPC is running */ |
---|
797 | 553 | #define WATCHDOG_EXTEND_INTERVAL (2000) |
---|
798 | 554 | |
---|
799 | 555 | uint dhd_watchdog_ms = CUSTOM_DHD_WATCHDOG_MS; |
---|
800 | 556 | module_param(dhd_watchdog_ms, uint, 0); |
---|
801 | 557 | |
---|
| 558 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 559 | +uint dhd_runtimepm_ms = CUSTOM_DHD_RUNTIME_MS; |
---|
| 560 | +#endif /* DHD_PCIE_RUNTIMEPMT */ |
---|
802 | 561 | #if defined(DHD_DEBUG) |
---|
803 | 562 | /* Console poll interval */ |
---|
| 563 | +#if defined(OEM_ANDROID) |
---|
804 | 564 | uint dhd_console_ms = 0; |
---|
| 565 | +#else |
---|
| 566 | +uint dhd_console_ms = 250; |
---|
| 567 | +#endif /* OEM_ANDROID */ |
---|
805 | 568 | module_param(dhd_console_ms, uint, 0644); |
---|
806 | | -#endif /* defined(DHD_DEBUG) */ |
---|
| 569 | +#else |
---|
| 570 | +uint dhd_console_ms = 0; |
---|
| 571 | +#endif /* DHD_DEBUG */ |
---|
807 | 572 | |
---|
808 | 573 | uint dhd_slpauto = TRUE; |
---|
809 | 574 | module_param(dhd_slpauto, uint, 0); |
---|
.. | .. |
---|
812 | 577 | /* Global Pkt filter enable control */ |
---|
813 | 578 | uint dhd_pkt_filter_enable = TRUE; |
---|
814 | 579 | module_param(dhd_pkt_filter_enable, uint, 0); |
---|
815 | | -#endif |
---|
| 580 | +#endif // endif |
---|
816 | 581 | |
---|
817 | 582 | /* Pkt filter init setup */ |
---|
818 | 583 | uint dhd_pkt_filter_init = 0; |
---|
819 | 584 | module_param(dhd_pkt_filter_init, uint, 0); |
---|
820 | 585 | |
---|
821 | 586 | /* Pkt filter mode control */ |
---|
| 587 | +#ifdef GAN_LITE_NAT_KEEPALIVE_FILTER |
---|
| 588 | +uint dhd_master_mode = FALSE; |
---|
| 589 | +#else |
---|
822 | 590 | uint dhd_master_mode = TRUE; |
---|
| 591 | +#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */ |
---|
823 | 592 | module_param(dhd_master_mode, uint, 0); |
---|
824 | 593 | |
---|
825 | 594 | int dhd_watchdog_prio = 0; |
---|
.. | .. |
---|
843 | 612 | module_param(passive_channel_skip, int, (S_IRUSR|S_IWUSR)); |
---|
844 | 613 | #endif /* WL_CFG80211 */ |
---|
845 | 614 | |
---|
| 615 | +#ifdef DHD_MSI_SUPPORT |
---|
| 616 | +uint enable_msi = TRUE; |
---|
| 617 | +module_param(enable_msi, uint, 0); |
---|
| 618 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 619 | + |
---|
| 620 | +#ifdef DHD_SSSR_DUMP |
---|
| 621 | +int dhdpcie_sssr_dump_get_before_after_len(dhd_pub_t *dhd, uint32 *arr_len); |
---|
| 622 | +extern uint support_sssr_dump; |
---|
| 623 | +module_param(support_sssr_dump, uint, 0); |
---|
| 624 | +#endif /* DHD_SSSR_DUMP */ |
---|
| 625 | + |
---|
846 | 626 | /* Keep track of number of instances */ |
---|
847 | 627 | static int dhd_found = 0; |
---|
848 | 628 | static int instance_base = 0; /* Starting instance number */ |
---|
849 | 629 | module_param(instance_base, int, 0644); |
---|
850 | 630 | |
---|
851 | | -#ifdef DHD_DHCP_DUMP |
---|
852 | | -struct bootp_fmt { |
---|
853 | | - struct iphdr ip_header; |
---|
854 | | - struct udphdr udp_header; |
---|
855 | | - uint8 op; |
---|
856 | | - uint8 htype; |
---|
857 | | - uint8 hlen; |
---|
858 | | - uint8 hops; |
---|
859 | | - uint32 transaction_id; |
---|
860 | | - uint16 secs; |
---|
861 | | - uint16 flags; |
---|
862 | | - uint32 client_ip; |
---|
863 | | - uint32 assigned_ip; |
---|
864 | | - uint32 server_ip; |
---|
865 | | - uint32 relay_ip; |
---|
866 | | - uint8 hw_address[16]; |
---|
867 | | - uint8 server_name[64]; |
---|
868 | | - uint8 file_name[128]; |
---|
869 | | - uint8 options[312]; |
---|
870 | | -}; |
---|
871 | | - |
---|
872 | | -static const uint8 bootp_magic_cookie[4] = { 99, 130, 83, 99 }; |
---|
873 | | -static const char dhcp_ops[][10] = { |
---|
874 | | - "NA", "REQUEST", "REPLY" |
---|
875 | | -}; |
---|
876 | | -static const char dhcp_types[][10] = { |
---|
877 | | - "NA", "DISCOVER", "OFFER", "REQUEST", "DECLINE", "ACK", "NAK", "RELEASE", "INFORM" |
---|
878 | | -}; |
---|
879 | | -static void dhd_dhcp_dump(uint8 *pktdata, bool tx); |
---|
880 | | -#endif /* DHD_DHCP_DUMP */ |
---|
881 | | - |
---|
882 | | -#if defined(DHD_LB) |
---|
883 | | - |
---|
884 | | -static void |
---|
885 | | -dhd_lb_set_default_cpus(dhd_info_t *dhd) |
---|
886 | | -{ |
---|
887 | | - /* Default CPU allocation for the jobs */ |
---|
888 | | - atomic_set(&dhd->rx_napi_cpu, 1); |
---|
889 | | - atomic_set(&dhd->rx_compl_cpu, 2); |
---|
890 | | - atomic_set(&dhd->tx_compl_cpu, 2); |
---|
891 | | -} |
---|
892 | | - |
---|
893 | | -static void |
---|
894 | | -dhd_cpumasks_deinit(dhd_info_t *dhd) |
---|
895 | | -{ |
---|
896 | | - free_cpumask_var(dhd->cpumask_curr_avail); |
---|
897 | | - free_cpumask_var(dhd->cpumask_primary); |
---|
898 | | - free_cpumask_var(dhd->cpumask_primary_new); |
---|
899 | | - free_cpumask_var(dhd->cpumask_secondary); |
---|
900 | | - free_cpumask_var(dhd->cpumask_secondary_new); |
---|
901 | | -} |
---|
902 | | - |
---|
903 | | -static int |
---|
904 | | -dhd_cpumasks_init(dhd_info_t *dhd) |
---|
905 | | -{ |
---|
906 | | - int id; |
---|
907 | | - uint32 cpus; |
---|
908 | | - int ret = 0; |
---|
909 | | - |
---|
910 | | - if (!alloc_cpumask_var(&dhd->cpumask_curr_avail, GFP_KERNEL) || |
---|
911 | | - !alloc_cpumask_var(&dhd->cpumask_primary, GFP_KERNEL) || |
---|
912 | | - !alloc_cpumask_var(&dhd->cpumask_primary_new, GFP_KERNEL) || |
---|
913 | | - !alloc_cpumask_var(&dhd->cpumask_secondary, GFP_KERNEL) || |
---|
914 | | - !alloc_cpumask_var(&dhd->cpumask_secondary_new, GFP_KERNEL)) { |
---|
915 | | - DHD_ERROR(("%s Failed to init cpumasks\n", __FUNCTION__)); |
---|
916 | | - ret = -ENOMEM; |
---|
917 | | - goto fail; |
---|
918 | | - } |
---|
919 | | - |
---|
920 | | - cpumask_copy(dhd->cpumask_curr_avail, cpu_online_mask); |
---|
921 | | - cpumask_clear(dhd->cpumask_primary); |
---|
922 | | - cpumask_clear(dhd->cpumask_secondary); |
---|
923 | | - |
---|
924 | | - cpus = DHD_LB_PRIMARY_CPUS; |
---|
925 | | - for (id = 0; id < NR_CPUS; id++) { |
---|
926 | | - if (isset(&cpus, id)) |
---|
927 | | - cpumask_set_cpu(id, dhd->cpumask_primary); |
---|
928 | | - } |
---|
929 | | - |
---|
930 | | - cpus = DHD_LB_SECONDARY_CPUS; |
---|
931 | | - for (id = 0; id < NR_CPUS; id++) { |
---|
932 | | - if (isset(&cpus, id)) |
---|
933 | | - cpumask_set_cpu(id, dhd->cpumask_secondary); |
---|
934 | | - } |
---|
935 | | - |
---|
936 | | - return ret; |
---|
937 | | -fail: |
---|
938 | | - dhd_cpumasks_deinit(dhd); |
---|
939 | | - return ret; |
---|
940 | | -} |
---|
941 | | - |
---|
942 | | -/* |
---|
943 | | - * The CPU Candidacy Algorithm |
---|
944 | | - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
945 | | - * The available CPUs for selection are divided into two groups |
---|
946 | | - * Primary Set - A CPU mask that carries the First Choice CPUs |
---|
947 | | - * Secondary Set - A CPU mask that carries the Second Choice CPUs. |
---|
948 | | - * |
---|
949 | | - * There are two types of Job, that needs to be assigned to |
---|
950 | | - * the CPUs, from one of the above mentioned CPU group. The Jobs are |
---|
951 | | - * 1) Rx Packet Processing - napi_cpu |
---|
952 | | - * 2) Completion Processiong (Tx, RX) - compl_cpu |
---|
953 | | - * |
---|
954 | | - * To begin with both napi_cpu and compl_cpu are on CPU0. Whenever a CPU goes |
---|
955 | | - * on-line/off-line the CPU candidacy algorithm is triggerd. The candidacy |
---|
956 | | - * algo tries to pickup the first available non boot CPU (CPU0) for napi_cpu. |
---|
957 | | - * If there are more processors free, it assigns one to compl_cpu. |
---|
958 | | - * It also tries to ensure that both napi_cpu and compl_cpu are not on the same |
---|
959 | | - * CPU, as much as possible. |
---|
960 | | - * |
---|
961 | | - * By design, both Tx and Rx completion jobs are run on the same CPU core, as it |
---|
962 | | - * would allow Tx completion skb's to be released into a local free pool from |
---|
963 | | - * which the rx buffer posts could have been serviced. it is important to note |
---|
964 | | - * that a Tx packet may not have a large enough buffer for rx posting. |
---|
| 631 | +/* Takes value of LL of OTP param customvar2=0xKKLLMMNN. |
---|
| 632 | + * LL is module variant |
---|
965 | 633 | */ |
---|
966 | | -void dhd_select_cpu_candidacy(dhd_info_t *dhd) |
---|
967 | | -{ |
---|
968 | | - uint32 primary_available_cpus; /* count of primary available cpus */ |
---|
969 | | - uint32 secondary_available_cpus; /* count of secondary available cpus */ |
---|
970 | | - uint32 napi_cpu = 0; /* cpu selected for napi rx processing */ |
---|
971 | | - uint32 compl_cpu = 0; /* cpu selected for completion jobs */ |
---|
| 634 | +uint32 hw_module_variant = 0; |
---|
| 635 | +module_param(hw_module_variant, uint, 0644); |
---|
972 | 636 | |
---|
973 | | - cpumask_clear(dhd->cpumask_primary_new); |
---|
974 | | - cpumask_clear(dhd->cpumask_secondary_new); |
---|
975 | | - |
---|
976 | | - /* |
---|
977 | | - * Now select from the primary mask. Even if a Job is |
---|
978 | | - * already running on a CPU in secondary group, we still move |
---|
979 | | - * to primary CPU. So no conditional checks. |
---|
980 | | - */ |
---|
981 | | - cpumask_and(dhd->cpumask_primary_new, dhd->cpumask_primary, |
---|
982 | | - dhd->cpumask_curr_avail); |
---|
983 | | - |
---|
984 | | - cpumask_and(dhd->cpumask_secondary_new, dhd->cpumask_secondary, |
---|
985 | | - dhd->cpumask_curr_avail); |
---|
986 | | - |
---|
987 | | - primary_available_cpus = cpumask_weight(dhd->cpumask_primary_new); |
---|
988 | | - |
---|
989 | | - if (primary_available_cpus > 0) { |
---|
990 | | - napi_cpu = cpumask_first(dhd->cpumask_primary_new); |
---|
991 | | - |
---|
992 | | - /* If no further CPU is available, |
---|
993 | | - * cpumask_next returns >= nr_cpu_ids |
---|
994 | | - */ |
---|
995 | | - compl_cpu = cpumask_next(napi_cpu, dhd->cpumask_primary_new); |
---|
996 | | - if (compl_cpu >= nr_cpu_ids) |
---|
997 | | - compl_cpu = 0; |
---|
998 | | - } |
---|
999 | | - |
---|
1000 | | - DHD_INFO(("%s After primary CPU check napi_cpu %d compl_cpu %d\n", |
---|
1001 | | - __FUNCTION__, napi_cpu, compl_cpu)); |
---|
1002 | | - |
---|
1003 | | - /* -- Now check for the CPUs from the secondary mask -- */ |
---|
1004 | | - secondary_available_cpus = cpumask_weight(dhd->cpumask_secondary_new); |
---|
1005 | | - |
---|
1006 | | - DHD_INFO(("%s Available secondary cpus %d nr_cpu_ids %d\n", |
---|
1007 | | - __FUNCTION__, secondary_available_cpus, nr_cpu_ids)); |
---|
1008 | | - |
---|
1009 | | - if (secondary_available_cpus > 0) { |
---|
1010 | | - /* At this point if napi_cpu is unassigned it means no CPU |
---|
1011 | | - * is online from Primary Group |
---|
1012 | | - */ |
---|
1013 | | - if (napi_cpu == 0) { |
---|
1014 | | - napi_cpu = cpumask_first(dhd->cpumask_secondary_new); |
---|
1015 | | - compl_cpu = cpumask_next(napi_cpu, dhd->cpumask_secondary_new); |
---|
1016 | | - } else if (compl_cpu == 0) { |
---|
1017 | | - compl_cpu = cpumask_first(dhd->cpumask_secondary_new); |
---|
1018 | | - } |
---|
1019 | | - |
---|
1020 | | - /* If no CPU was available for completion, choose CPU 0 */ |
---|
1021 | | - if (compl_cpu >= nr_cpu_ids) |
---|
1022 | | - compl_cpu = 0; |
---|
1023 | | - } |
---|
1024 | | - if ((primary_available_cpus == 0) && |
---|
1025 | | - (secondary_available_cpus == 0)) { |
---|
1026 | | - /* No CPUs available from primary or secondary mask */ |
---|
1027 | | - napi_cpu = 0; |
---|
1028 | | - compl_cpu = 0; |
---|
1029 | | - } |
---|
1030 | | - |
---|
1031 | | - DHD_INFO(("%s After secondary CPU check napi_cpu %d compl_cpu %d\n", |
---|
1032 | | - __FUNCTION__, napi_cpu, compl_cpu)); |
---|
1033 | | - ASSERT(napi_cpu < nr_cpu_ids); |
---|
1034 | | - ASSERT(compl_cpu < nr_cpu_ids); |
---|
1035 | | - |
---|
1036 | | - atomic_set(&dhd->rx_napi_cpu, napi_cpu); |
---|
1037 | | - atomic_set(&dhd->tx_compl_cpu, compl_cpu); |
---|
1038 | | - atomic_set(&dhd->rx_compl_cpu, compl_cpu); |
---|
1039 | | - return; |
---|
1040 | | -} |
---|
1041 | | - |
---|
1042 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) |
---|
1043 | | -int dhd_cpuhp_online(unsigned int cpu, struct hlist_node *node) |
---|
1044 | | -{ |
---|
1045 | | - dhd_info_t *dhd = hlist_entry_safe(node, dhd_info_t, |
---|
1046 | | - node_online); |
---|
1047 | | - |
---|
1048 | | - DHD_INFO(("%s: cpu=%d\n", __func__, cpu)); |
---|
1049 | | - DHD_LB_STATS_INCR(dhd->cpu_online_cnt[cpu]); |
---|
1050 | | - cpumask_set_cpu(cpu, dhd->cpumask_curr_avail); |
---|
1051 | | - dhd_select_cpu_candidacy(dhd); |
---|
1052 | | - return 0; |
---|
1053 | | -} |
---|
1054 | | - |
---|
1055 | | -int dhd_cpuhp_dead(unsigned int cpu, struct hlist_node *node) |
---|
1056 | | -{ |
---|
1057 | | - dhd_info_t *dhd = hlist_entry_safe(node, dhd_info_t, |
---|
1058 | | - node_online); |
---|
1059 | | - |
---|
1060 | | - DHD_INFO(("%s: cpu=%d\n", __func__, cpu)); |
---|
1061 | | - DHD_LB_STATS_INCR(dhd->cpu_offline_cnt[cpu]); |
---|
1062 | | - cpumask_clear_cpu(cpu, dhd->cpumask_curr_avail); |
---|
1063 | | - dhd_select_cpu_candidacy(dhd); |
---|
1064 | | - return 0; |
---|
1065 | | -} |
---|
1066 | | -#else |
---|
1067 | | -/* |
---|
1068 | | - * Function to handle CPU Hotplug notifications. |
---|
1069 | | - * One of the task it does is to trigger the CPU Candidacy algorithm |
---|
1070 | | - * for load balancing. |
---|
1071 | | - */ |
---|
1072 | | -int |
---|
1073 | | -dhd_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) |
---|
1074 | | -{ |
---|
1075 | | - unsigned int cpu = (unsigned int)(long)hcpu; |
---|
1076 | | - |
---|
1077 | | - dhd_info_t *dhd = container_of(nfb, dhd_info_t, cpu_notifier); |
---|
1078 | | - |
---|
1079 | | - switch (action) |
---|
1080 | | - { |
---|
1081 | | - case CPU_ONLINE: |
---|
1082 | | - DHD_LB_STATS_INCR(dhd->cpu_online_cnt[cpu]); |
---|
1083 | | - cpumask_set_cpu(cpu, dhd->cpumask_curr_avail); |
---|
1084 | | - dhd_select_cpu_candidacy(dhd); |
---|
1085 | | - break; |
---|
1086 | | - |
---|
1087 | | - case CPU_DOWN_PREPARE: |
---|
1088 | | - case CPU_DOWN_PREPARE_FROZEN: |
---|
1089 | | - DHD_LB_STATS_INCR(dhd->cpu_offline_cnt[cpu]); |
---|
1090 | | - cpumask_clear_cpu(cpu, dhd->cpumask_curr_avail); |
---|
1091 | | - dhd_select_cpu_candidacy(dhd); |
---|
1092 | | - break; |
---|
1093 | | - default: |
---|
1094 | | - break; |
---|
1095 | | - } |
---|
1096 | | - |
---|
1097 | | - return NOTIFY_OK; |
---|
1098 | | -} |
---|
1099 | | -#endif |
---|
1100 | | - |
---|
1101 | | -#if defined(DHD_LB_STATS) |
---|
1102 | | -void dhd_lb_stats_init(dhd_pub_t *dhdp) |
---|
1103 | | -{ |
---|
1104 | | - dhd_info_t *dhd; |
---|
1105 | | - int i, j; |
---|
1106 | | - |
---|
1107 | | - if (dhdp == NULL) { |
---|
1108 | | - DHD_ERROR(("%s(): Invalid argument dhdp is NULL \n", |
---|
1109 | | - __FUNCTION__)); |
---|
1110 | | - return; |
---|
1111 | | - } |
---|
1112 | | - |
---|
1113 | | - dhd = dhdp->info; |
---|
1114 | | - if (dhd == NULL) { |
---|
1115 | | - DHD_ERROR(("%s(): DHD pointer is NULL \n", __FUNCTION__)); |
---|
1116 | | - return; |
---|
1117 | | - } |
---|
1118 | | - |
---|
1119 | | - DHD_LB_STATS_CLR(dhd->dhd_dpc_cnt); |
---|
1120 | | - DHD_LB_STATS_CLR(dhd->napi_sched_cnt); |
---|
1121 | | - DHD_LB_STATS_CLR(dhd->rxc_sched_cnt); |
---|
1122 | | - DHD_LB_STATS_CLR(dhd->txc_sched_cnt); |
---|
1123 | | - |
---|
1124 | | - for (i = 0; i < NR_CPUS; i++) { |
---|
1125 | | - DHD_LB_STATS_CLR(dhd->napi_percpu_run_cnt[i]); |
---|
1126 | | - DHD_LB_STATS_CLR(dhd->rxc_percpu_run_cnt[i]); |
---|
1127 | | - DHD_LB_STATS_CLR(dhd->txc_percpu_run_cnt[i]); |
---|
1128 | | - |
---|
1129 | | - DHD_LB_STATS_CLR(dhd->cpu_online_cnt[i]); |
---|
1130 | | - DHD_LB_STATS_CLR(dhd->cpu_offline_cnt[i]); |
---|
1131 | | - } |
---|
1132 | | - |
---|
1133 | | - for (i = 0; i < NR_CPUS; i++) { |
---|
1134 | | - for (j = 0; j < HIST_BIN_SIZE; j++) { |
---|
1135 | | - DHD_LB_STATS_CLR(dhd->napi_rx_hist[i][j]); |
---|
1136 | | - DHD_LB_STATS_CLR(dhd->txc_hist[i][j]); |
---|
1137 | | - DHD_LB_STATS_CLR(dhd->rxc_hist[i][j]); |
---|
1138 | | - } |
---|
1139 | | - } |
---|
1140 | | - |
---|
1141 | | - return; |
---|
1142 | | -} |
---|
1143 | | - |
---|
1144 | | -static void dhd_lb_stats_dump_histo( |
---|
1145 | | - struct bcmstrbuf *strbuf, uint32 (*hist)[HIST_BIN_SIZE]) |
---|
1146 | | -{ |
---|
1147 | | - int i, j; |
---|
1148 | | - uint32 per_cpu_total[NR_CPUS] = {0}; |
---|
1149 | | - uint32 total = 0; |
---|
1150 | | - |
---|
1151 | | - bcm_bprintf(strbuf, "CPU: \t\t"); |
---|
1152 | | - for (i = 0; i < num_possible_cpus(); i++) |
---|
1153 | | - bcm_bprintf(strbuf, "%d\t", i); |
---|
1154 | | - bcm_bprintf(strbuf, "\nBin\n"); |
---|
1155 | | - |
---|
1156 | | - for (i = 0; i < HIST_BIN_SIZE; i++) { |
---|
1157 | | - bcm_bprintf(strbuf, "%d:\t\t", 1<<(i+1)); |
---|
1158 | | - for (j = 0; j < num_possible_cpus(); j++) { |
---|
1159 | | - bcm_bprintf(strbuf, "%d\t", hist[j][i]); |
---|
1160 | | - } |
---|
1161 | | - bcm_bprintf(strbuf, "\n"); |
---|
1162 | | - } |
---|
1163 | | - bcm_bprintf(strbuf, "Per CPU Total \t"); |
---|
1164 | | - total = 0; |
---|
1165 | | - for (i = 0; i < num_possible_cpus(); i++) { |
---|
1166 | | - for (j = 0; j < HIST_BIN_SIZE; j++) { |
---|
1167 | | - per_cpu_total[i] += (hist[i][j] * (1<<(j+1))); |
---|
1168 | | - } |
---|
1169 | | - bcm_bprintf(strbuf, "%d\t", per_cpu_total[i]); |
---|
1170 | | - total += per_cpu_total[i]; |
---|
1171 | | - } |
---|
1172 | | - bcm_bprintf(strbuf, "\nTotal\t\t%d \n", total); |
---|
1173 | | - |
---|
1174 | | - return; |
---|
1175 | | -} |
---|
1176 | | - |
---|
1177 | | -static inline void dhd_lb_stats_dump_cpu_array(struct bcmstrbuf *strbuf, uint32 *p) |
---|
1178 | | -{ |
---|
1179 | | - int i; |
---|
1180 | | - |
---|
1181 | | - bcm_bprintf(strbuf, "CPU: \t"); |
---|
1182 | | - for (i = 0; i < num_possible_cpus(); i++) |
---|
1183 | | - bcm_bprintf(strbuf, "%d\t", i); |
---|
1184 | | - bcm_bprintf(strbuf, "\n"); |
---|
1185 | | - |
---|
1186 | | - bcm_bprintf(strbuf, "Val: \t"); |
---|
1187 | | - for (i = 0; i < num_possible_cpus(); i++) |
---|
1188 | | - bcm_bprintf(strbuf, "%u\t", *(p+i)); |
---|
1189 | | - bcm_bprintf(strbuf, "\n"); |
---|
1190 | | - return; |
---|
1191 | | -} |
---|
1192 | | - |
---|
1193 | | -void dhd_lb_stats_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) |
---|
1194 | | -{ |
---|
1195 | | - dhd_info_t *dhd; |
---|
1196 | | - |
---|
1197 | | - if (dhdp == NULL || strbuf == NULL) { |
---|
1198 | | - DHD_ERROR(("%s(): Invalid argument dhdp %p strbuf %p \n", |
---|
1199 | | - __FUNCTION__, dhdp, strbuf)); |
---|
1200 | | - return; |
---|
1201 | | - } |
---|
1202 | | - |
---|
1203 | | - dhd = dhdp->info; |
---|
1204 | | - if (dhd == NULL) { |
---|
1205 | | - DHD_ERROR(("%s(): DHD pointer is NULL \n", __FUNCTION__)); |
---|
1206 | | - return; |
---|
1207 | | - } |
---|
1208 | | - |
---|
1209 | | - bcm_bprintf(strbuf, "\ncpu_online_cnt:\n"); |
---|
1210 | | - dhd_lb_stats_dump_cpu_array(strbuf, dhd->cpu_online_cnt); |
---|
1211 | | - |
---|
1212 | | - bcm_bprintf(strbuf, "cpu_offline_cnt:\n"); |
---|
1213 | | - dhd_lb_stats_dump_cpu_array(strbuf, dhd->cpu_offline_cnt); |
---|
1214 | | - |
---|
1215 | | - bcm_bprintf(strbuf, "\nsched_cnt: dhd_dpc %u napi %u rxc %u txc %u\n", |
---|
1216 | | - dhd->dhd_dpc_cnt, dhd->napi_sched_cnt, dhd->rxc_sched_cnt, |
---|
1217 | | - dhd->txc_sched_cnt); |
---|
1218 | | -#ifdef DHD_LB_RXP |
---|
1219 | | - bcm_bprintf(strbuf, "napi_percpu_run_cnt:\n"); |
---|
1220 | | - dhd_lb_stats_dump_cpu_array(strbuf, dhd->napi_percpu_run_cnt); |
---|
1221 | | - bcm_bprintf(strbuf, "\nNAPI Packets Received Histogram:\n"); |
---|
1222 | | - dhd_lb_stats_dump_histo(strbuf, dhd->napi_rx_hist); |
---|
| 637 | +#if defined(DHD_LB_RXP) |
---|
| 638 | +static int dhd_napi_weight = 32; |
---|
| 639 | +module_param(dhd_napi_weight, int, 0644); |
---|
1223 | 640 | #endif /* DHD_LB_RXP */ |
---|
1224 | 641 | |
---|
1225 | | -#ifdef DHD_LB_RXC |
---|
1226 | | - bcm_bprintf(strbuf, "rxc_percpu_run_cnt:\n"); |
---|
1227 | | - dhd_lb_stats_dump_cpu_array(strbuf, dhd->rxc_percpu_run_cnt); |
---|
1228 | | - bcm_bprintf(strbuf, "\nRX Completions (Buffer Post) Histogram:\n"); |
---|
1229 | | - dhd_lb_stats_dump_histo(strbuf, dhd->rxc_hist); |
---|
1230 | | -#endif /* DHD_LB_RXC */ |
---|
| 642 | +#ifdef PCIE_FULL_DONGLE |
---|
| 643 | +extern int h2d_max_txpost; |
---|
| 644 | +module_param(h2d_max_txpost, int, 0644); |
---|
1231 | 645 | |
---|
| 646 | +extern uint dma_ring_indices; |
---|
| 647 | +module_param(dma_ring_indices, uint, 0644); |
---|
1232 | 648 | |
---|
1233 | | -#ifdef DHD_LB_TXC |
---|
1234 | | - bcm_bprintf(strbuf, "txc_percpu_run_cnt:\n"); |
---|
1235 | | - dhd_lb_stats_dump_cpu_array(strbuf, dhd->txc_percpu_run_cnt); |
---|
1236 | | - bcm_bprintf(strbuf, "\nTX Completions (Buffer Free) Histogram:\n"); |
---|
1237 | | - dhd_lb_stats_dump_histo(strbuf, dhd->txc_hist); |
---|
1238 | | -#endif /* DHD_LB_TXC */ |
---|
1239 | | -} |
---|
| 649 | +extern bool h2d_phase; |
---|
| 650 | +module_param(h2d_phase, bool, 0644); |
---|
| 651 | +extern bool force_trap_bad_h2d_phase; |
---|
| 652 | +module_param(force_trap_bad_h2d_phase, bool, 0644); |
---|
| 653 | +#endif /* PCIE_FULL_DONGLE */ |
---|
1240 | 654 | |
---|
1241 | | -static void dhd_lb_stats_update_histo(uint32 *bin, uint32 count) |
---|
| 655 | +#ifdef FORCE_TPOWERON |
---|
| 656 | +/* |
---|
| 657 | + * On Fire's reference platform, coming out of L1.2, |
---|
| 658 | + * there is a constant delay of 45us between CLKREQ# and stable REFCLK |
---|
| 659 | + * Due to this delay, with tPowerOn < 50 |
---|
| 660 | + * there is a chance of the refclk sense to trigger on noise. |
---|
| 661 | + * |
---|
| 662 | + * 0x29 when written to L1SSControl2 translates to 50us. |
---|
| 663 | + */ |
---|
| 664 | +#define FORCE_TPOWERON_50US 0x29 |
---|
| 665 | +uint32 tpoweron_scale = FORCE_TPOWERON_50US; /* default 50us */ |
---|
| 666 | +module_param(tpoweron_scale, uint, 0644); |
---|
| 667 | +#endif /* FORCE_TPOWERON */ |
---|
| 668 | + |
---|
| 669 | +#ifdef SHOW_LOGTRACE |
---|
| 670 | +#if defined(CUSTOMER_HW4_DEBUG) |
---|
| 671 | +static char *logstrs_path = PLATFORM_PATH"logstrs.bin"; |
---|
| 672 | +char *st_str_file_path = PLATFORM_PATH"rtecdc.bin"; |
---|
| 673 | +static char *map_file_path = PLATFORM_PATH"rtecdc.map"; |
---|
| 674 | +static char *rom_st_str_file_path = PLATFORM_PATH"roml.bin"; |
---|
| 675 | +static char *rom_map_file_path = PLATFORM_PATH"roml.map"; |
---|
| 676 | +#elif defined(CUSTOMER_HW2) || defined(BOARD_HIKEY) |
---|
| 677 | +static char *logstrs_path = "/data/misc/wifi/logstrs.bin"; |
---|
| 678 | +char *st_str_file_path = "/data/misc/wifi/rtecdc.bin"; |
---|
| 679 | +static char *map_file_path = "/data/misc/wifi/rtecdc.map"; |
---|
| 680 | +static char *rom_st_str_file_path = "/data/misc/wifi/roml.bin"; |
---|
| 681 | +static char *rom_map_file_path = "/data/misc/wifi/roml.map"; |
---|
| 682 | +#elif defined(OEM_ANDROID) /* For Brix KK Live Image */ |
---|
| 683 | +static char *logstrs_path = "/installmedia/logstrs.bin"; |
---|
| 684 | +char *st_str_file_path = "/installmedia/rtecdc.bin"; |
---|
| 685 | +static char *map_file_path = "/installmedia/rtecdc.map"; |
---|
| 686 | +static char *rom_st_str_file_path = "/installmedia/roml.bin"; |
---|
| 687 | +static char *rom_map_file_path = "/installmedia/roml.map"; |
---|
| 688 | +#else /* For Linux platforms */ |
---|
| 689 | +static char *logstrs_path = "/root/logstrs.bin"; |
---|
| 690 | +char *st_str_file_path = "/root/rtecdc.bin"; |
---|
| 691 | +static char *map_file_path = "/root/rtecdc.map"; |
---|
| 692 | +static char *rom_st_str_file_path = "/root/roml.bin"; |
---|
| 693 | +static char *rom_map_file_path = "/root/roml.map"; |
---|
| 694 | +#endif /* CUSTOMER_HW4_DEBUG || CUSTOMER_HW2 || BOARD_HIKEY */ |
---|
| 695 | +static char *ram_file_str = "rtecdc"; |
---|
| 696 | +static char *rom_file_str = "roml"; |
---|
| 697 | + |
---|
| 698 | +module_param(logstrs_path, charp, S_IRUGO); |
---|
| 699 | +module_param(st_str_file_path, charp, S_IRUGO); |
---|
| 700 | +module_param(map_file_path, charp, S_IRUGO); |
---|
| 701 | +module_param(rom_st_str_file_path, charp, S_IRUGO); |
---|
| 702 | +module_param(rom_map_file_path, charp, S_IRUGO); |
---|
| 703 | + |
---|
| 704 | +static int dhd_init_logstrs_array(osl_t *osh, dhd_event_log_t *temp); |
---|
| 705 | +static int dhd_read_map(osl_t *osh, char *fname, uint32 *ramstart, uint32 *rodata_start, |
---|
| 706 | + uint32 *rodata_end); |
---|
| 707 | +static int dhd_init_static_strs_array(osl_t *osh, dhd_event_log_t *temp, char *str_file, |
---|
| 708 | + char *map_file); |
---|
| 709 | +#endif /* SHOW_LOGTRACE */ |
---|
| 710 | + |
---|
| 711 | +#ifdef BCMSDIO |
---|
| 712 | +#define DHD_IF_ROLE(pub, idx) ((pub)->info->iflist[idx]->role) |
---|
| 713 | +#define DHD_IF_ROLE_AP(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_AP) |
---|
| 714 | +#define DHD_IF_ROLE_STA(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_STA) |
---|
| 715 | +#define DHD_IF_ROLE_P2PGO(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_P2P_GO) |
---|
| 716 | + |
---|
| 717 | +void dhd_set_role(dhd_pub_t *dhdp, int role, int bssidx) |
---|
1242 | 718 | { |
---|
1243 | | - uint32 bin_power; |
---|
1244 | | - uint32 *p = NULL; |
---|
1245 | | - |
---|
1246 | | - bin_power = next_larger_power2(count); |
---|
1247 | | - |
---|
1248 | | - switch (bin_power) { |
---|
1249 | | - case 0: break; |
---|
1250 | | - case 1: /* Fall through intentionally */ |
---|
1251 | | - case 2: p = bin + 0; break; |
---|
1252 | | - case 4: p = bin + 1; break; |
---|
1253 | | - case 8: p = bin + 2; break; |
---|
1254 | | - case 16: p = bin + 3; break; |
---|
1255 | | - case 32: p = bin + 4; break; |
---|
1256 | | - case 64: p = bin + 5; break; |
---|
1257 | | - case 128: p = bin + 6; break; |
---|
1258 | | - default : p = bin + 7; break; |
---|
1259 | | - } |
---|
1260 | | - if (p) |
---|
1261 | | - *p = *p + 1; |
---|
1262 | | - return; |
---|
| 719 | + int ifidx = dhd_bssidx2idx(dhdp, bssidx); |
---|
| 720 | + DHD_TRACE(("dhd_set_role ifidx %d role %d\n", ifidx, role)); |
---|
| 721 | + dhdp->info->iflist[ifidx]->role = role; |
---|
1263 | 722 | } |
---|
| 723 | +#endif /* BCMSDIO */ |
---|
1264 | 724 | |
---|
1265 | | -extern void dhd_lb_stats_update_napi_histo(dhd_pub_t *dhdp, uint32 count) |
---|
1266 | | -{ |
---|
1267 | | - int cpu; |
---|
1268 | | - dhd_info_t *dhd = dhdp->info; |
---|
1269 | | - |
---|
1270 | | - cpu = get_cpu(); |
---|
1271 | | - put_cpu(); |
---|
1272 | | - dhd_lb_stats_update_histo(&dhd->napi_rx_hist[cpu][0], count); |
---|
1273 | | - |
---|
1274 | | - return; |
---|
1275 | | -} |
---|
1276 | | - |
---|
1277 | | -extern void dhd_lb_stats_update_txc_histo(dhd_pub_t *dhdp, uint32 count) |
---|
1278 | | -{ |
---|
1279 | | - int cpu; |
---|
1280 | | - dhd_info_t *dhd = dhdp->info; |
---|
1281 | | - |
---|
1282 | | - cpu = get_cpu(); |
---|
1283 | | - put_cpu(); |
---|
1284 | | - dhd_lb_stats_update_histo(&dhd->txc_hist[cpu][0], count); |
---|
1285 | | - |
---|
1286 | | - return; |
---|
1287 | | -} |
---|
1288 | | - |
---|
1289 | | -extern void dhd_lb_stats_update_rxc_histo(dhd_pub_t *dhdp, uint32 count) |
---|
1290 | | -{ |
---|
1291 | | - int cpu; |
---|
1292 | | - dhd_info_t *dhd = dhdp->info; |
---|
1293 | | - |
---|
1294 | | - cpu = get_cpu(); |
---|
1295 | | - put_cpu(); |
---|
1296 | | - dhd_lb_stats_update_histo(&dhd->rxc_hist[cpu][0], count); |
---|
1297 | | - |
---|
1298 | | - return; |
---|
1299 | | -} |
---|
1300 | | - |
---|
1301 | | -extern void dhd_lb_stats_txc_percpu_cnt_incr(dhd_pub_t *dhdp) |
---|
1302 | | -{ |
---|
1303 | | - dhd_info_t *dhd = dhdp->info; |
---|
1304 | | - DHD_LB_STATS_PERCPU_ARR_INCR(dhd->txc_percpu_run_cnt); |
---|
1305 | | -} |
---|
1306 | | - |
---|
1307 | | -extern void dhd_lb_stats_rxc_percpu_cnt_incr(dhd_pub_t *dhdp) |
---|
1308 | | -{ |
---|
1309 | | - dhd_info_t *dhd = dhdp->info; |
---|
1310 | | - DHD_LB_STATS_PERCPU_ARR_INCR(dhd->rxc_percpu_run_cnt); |
---|
1311 | | -} |
---|
1312 | | - |
---|
1313 | | -#endif /* DHD_LB_STATS */ |
---|
1314 | | -#endif /* DHD_LB */ |
---|
1315 | | - |
---|
1316 | | - |
---|
| 725 | +#ifdef USE_WFA_CERT_CONF |
---|
| 726 | +int g_frameburst = 1; |
---|
| 727 | +#endif /* USE_WFA_CERT_CONF */ |
---|
1317 | 728 | |
---|
1318 | 729 | static int dhd_get_pend_8021x_cnt(dhd_info_t *dhd); |
---|
1319 | 730 | |
---|
.. | .. |
---|
1322 | 733 | #define DHD_PERIM_LOCK_TRY(unit, flag) do { /* noop */ } while (0) |
---|
1323 | 734 | #define DHD_PERIM_UNLOCK_TRY(unit, flag) do { /* noop */ } while (0) |
---|
1324 | 735 | |
---|
1325 | | -#ifdef PCIE_FULL_DONGLE |
---|
1326 | | -#if defined(BCM_GMAC3) |
---|
1327 | | -#define DHD_IF_STA_LIST_LOCK_INIT(ifp) do { /* noop */ } while (0) |
---|
1328 | | -#define DHD_IF_STA_LIST_LOCK(ifp, flags) ({ BCM_REFERENCE(flags); }) |
---|
1329 | | -#define DHD_IF_STA_LIST_UNLOCK(ifp, flags) ({ BCM_REFERENCE(flags); }) |
---|
1330 | | - |
---|
1331 | | -#if defined(DHD_IGMP_UCQUERY) || defined(DHD_UCAST_UPNP) |
---|
1332 | | -#define DHD_IF_WMF_UCFORWARD_LOCK(dhd, ifp, slist) ({ BCM_REFERENCE(slist); &(ifp)->sta_list; }) |
---|
1333 | | -#define DHD_IF_WMF_UCFORWARD_UNLOCK(dhd, slist) ({ BCM_REFERENCE(slist); }) |
---|
1334 | | -#endif /* DHD_IGMP_UCQUERY || DHD_UCAST_UPNP */ |
---|
1335 | | - |
---|
1336 | | -#else /* ! BCM_GMAC3 */ |
---|
1337 | 736 | #define DHD_IF_STA_LIST_LOCK_INIT(ifp) spin_lock_init(&(ifp)->sta_list_lock) |
---|
1338 | 737 | #define DHD_IF_STA_LIST_LOCK(ifp, flags) \ |
---|
1339 | 738 | spin_lock_irqsave(&(ifp)->sta_list_lock, (flags)) |
---|
.. | .. |
---|
1348 | 747 | #define DHD_IF_WMF_UCFORWARD_UNLOCK(dhd, slist) ({ dhd_sta_list_snapshot_free(dhd, slist); }) |
---|
1349 | 748 | #endif /* DHD_IGMP_UCQUERY || DHD_UCAST_UPNP */ |
---|
1350 | 749 | |
---|
1351 | | -#endif /* ! BCM_GMAC3 */ |
---|
1352 | | -#endif /* PCIE_FULL_DONGLE */ |
---|
1353 | | - |
---|
1354 | 750 | /* Control fw roaming */ |
---|
| 751 | +#ifdef BCMCCX |
---|
1355 | 752 | uint dhd_roam_disable = 0; |
---|
| 753 | +#else |
---|
| 754 | +#ifdef OEM_ANDROID |
---|
| 755 | +uint dhd_roam_disable = 0; |
---|
| 756 | +#else |
---|
| 757 | +uint dhd_roam_disable = 1; |
---|
| 758 | +#endif // endif |
---|
| 759 | +#endif /* BCMCCX */ |
---|
1356 | 760 | |
---|
1357 | 761 | #ifdef BCMDBGFS |
---|
1358 | | -extern int dhd_dbg_init(dhd_pub_t *dhdp); |
---|
1359 | | -extern void dhd_dbg_remove(void); |
---|
1360 | | -#endif |
---|
| 762 | +extern void dhd_dbgfs_init(dhd_pub_t *dhdp); |
---|
| 763 | +extern void dhd_dbgfs_remove(void); |
---|
| 764 | +#endif // endif |
---|
| 765 | + |
---|
| 766 | +static uint pcie_txs_metadata_enable = 0; /* Enable TX status metadta report */ |
---|
| 767 | +module_param(pcie_txs_metadata_enable, int, 0); |
---|
1361 | 768 | |
---|
1362 | 769 | /* Control radio state */ |
---|
1363 | 770 | uint dhd_radio_up = 1; |
---|
.. | .. |
---|
1366 | 773 | char iface_name[IFNAMSIZ] = {'\0'}; |
---|
1367 | 774 | module_param_string(iface_name, iface_name, IFNAMSIZ, 0); |
---|
1368 | 775 | |
---|
| 776 | +#ifdef WL_VIF_SUPPORT |
---|
| 777 | +/* Virtual inteface name */ |
---|
| 778 | +char vif_name[IFNAMSIZ] = "wlan"; |
---|
| 779 | +module_param_string(vif_name, vif_name, IFNAMSIZ, 0); |
---|
| 780 | + |
---|
| 781 | +int vif_num = 0; |
---|
| 782 | +module_param(vif_num, int, 0); |
---|
| 783 | +#endif /* WL_VIF_SUPPORT */ |
---|
| 784 | + |
---|
1369 | 785 | /* The following are specific to the SDIO dongle */ |
---|
1370 | 786 | |
---|
1371 | 787 | /* IOCTL response timeout */ |
---|
1372 | 788 | int dhd_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT; |
---|
| 789 | + |
---|
| 790 | +/* DS Exit response timeout */ |
---|
| 791 | +int ds_exit_timeout_msec = DS_EXIT_TIMEOUT; |
---|
1373 | 792 | |
---|
1374 | 793 | /* Idle timeout for backplane clock */ |
---|
1375 | 794 | int dhd_idletime = DHD_IDLETIME_TICKS; |
---|
.. | .. |
---|
1400 | 819 | |
---|
1401 | 820 | #endif /* BCMSDIO */ |
---|
1402 | 821 | |
---|
1403 | | - |
---|
1404 | 822 | #ifdef SDTEST |
---|
1405 | 823 | /* Echo packet generator (pkts/s) */ |
---|
1406 | 824 | uint dhd_pktgen = 0; |
---|
.. | .. |
---|
1411 | 829 | module_param(dhd_pktgen_len, uint, 0); |
---|
1412 | 830 | #endif /* SDTEST */ |
---|
1413 | 831 | |
---|
| 832 | +#if defined(BCMSUP_4WAY_HANDSHAKE) |
---|
| 833 | +/* Use in dongle supplicant for 4-way handshake */ |
---|
| 834 | +#if defined(WLFBT) || defined(WL_ENABLE_IDSUP) |
---|
| 835 | +/* Enable idsup by default (if supported in fw) */ |
---|
| 836 | +uint dhd_use_idsup = 1; |
---|
| 837 | +#else |
---|
| 838 | +uint dhd_use_idsup = 0; |
---|
| 839 | +#endif /* WLFBT || WL_ENABLE_IDSUP */ |
---|
| 840 | +module_param(dhd_use_idsup, uint, 0); |
---|
| 841 | +#endif /* BCMSUP_4WAY_HANDSHAKE */ |
---|
1414 | 842 | |
---|
1415 | | - |
---|
1416 | | -#ifndef BCMDBUS |
---|
| 843 | +#if (defined(OEM_ANDROID) && !defined(BCMQT)) |
---|
1417 | 844 | /* Allow delayed firmware download for debug purpose */ |
---|
1418 | 845 | int allow_delay_fwdl = FALSE; |
---|
| 846 | +#else |
---|
| 847 | +int allow_delay_fwdl = TRUE; |
---|
| 848 | +#endif // endif |
---|
1419 | 849 | module_param(allow_delay_fwdl, int, 0); |
---|
1420 | | -#endif /* !BCMDBUS */ |
---|
1421 | 850 | |
---|
1422 | | -/* Flag to indicate whether FW download has succeeded */ |
---|
1423 | | -bool dhd_fw_downloaded = FALSE; |
---|
| 851 | +#ifdef ECOUNTER_PERIODIC_DISABLE |
---|
| 852 | +uint enable_ecounter = FALSE; |
---|
| 853 | +#else |
---|
| 854 | +uint enable_ecounter = TRUE; |
---|
| 855 | +#endif // endif |
---|
| 856 | +module_param(enable_ecounter, uint, 0); |
---|
| 857 | + |
---|
| 858 | +/* TCM verification flag */ |
---|
| 859 | +uint dhd_tcm_test_enable = FALSE; |
---|
| 860 | +module_param(dhd_tcm_test_enable, uint, 0644); |
---|
| 861 | + |
---|
| 862 | +/* WAR to avoid system hang during FW trap */ |
---|
| 863 | +#ifdef DHD_FW_COREDUMP |
---|
| 864 | +uint disable_bug_on = FALSE; |
---|
| 865 | +module_param(disable_bug_on, uint, 0); |
---|
| 866 | +#endif /* DHD_FW_COREDUMP */ |
---|
1424 | 867 | |
---|
1425 | 868 | extern char dhd_version[]; |
---|
| 869 | +extern char fw_version[]; |
---|
| 870 | +extern char clm_version[]; |
---|
1426 | 871 | |
---|
1427 | 872 | int dhd_net_bus_devreset(struct net_device *dev, uint8 flag); |
---|
1428 | 873 | static void dhd_net_if_lock_local(dhd_info_t *dhd); |
---|
.. | .. |
---|
1430 | 875 | static void dhd_suspend_lock(dhd_pub_t *dhdp); |
---|
1431 | 876 | static void dhd_suspend_unlock(dhd_pub_t *dhdp); |
---|
1432 | 877 | |
---|
1433 | | -#ifdef WLMEDIA_HTSF |
---|
1434 | | -void htsf_update(dhd_info_t *dhd, void *data); |
---|
1435 | | -tsf_t prev_tsf, cur_tsf; |
---|
1436 | | - |
---|
1437 | | -uint32 dhd_get_htsf(dhd_info_t *dhd, int ifidx); |
---|
1438 | | -static int dhd_ioctl_htsf_get(dhd_info_t *dhd, int ifidx); |
---|
1439 | | -static void dhd_dump_latency(void); |
---|
1440 | | -static void dhd_htsf_addtxts(dhd_pub_t *dhdp, void *pktbuf); |
---|
1441 | | -static void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf); |
---|
1442 | | -static void dhd_dump_htsfhisto(histo_t *his, char *s); |
---|
1443 | | -#endif /* WLMEDIA_HTSF */ |
---|
1444 | | - |
---|
| 878 | +#ifdef DHD_MONITOR_INTERFACE |
---|
1445 | 879 | /* Monitor interface */ |
---|
1446 | 880 | int dhd_monitor_init(void *dhd_pub); |
---|
1447 | 881 | int dhd_monitor_uninit(void); |
---|
| 882 | +#endif /* DHD_MONITOR_INTERFACE */ |
---|
1448 | 883 | |
---|
| 884 | +#ifdef DHD_PM_CONTROL_FROM_FILE |
---|
| 885 | +bool g_pm_control; |
---|
| 886 | +#ifdef DHD_EXPORT_CNTL_FILE |
---|
| 887 | +int pmmode_val; |
---|
| 888 | +#endif /* DHD_EXPORT_CNTL_FILE */ |
---|
| 889 | +void sec_control_pm(dhd_pub_t *dhd, uint *); |
---|
| 890 | +#endif /* DHD_PM_CONTROL_FROM_FILE */ |
---|
1449 | 891 | |
---|
1450 | 892 | #if defined(WL_WIRELESS_EXT) |
---|
1451 | 893 | struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); |
---|
1452 | 894 | #endif /* defined(WL_WIRELESS_EXT) */ |
---|
1453 | 895 | |
---|
1454 | | -#ifndef BCMDBUS |
---|
1455 | 896 | static void dhd_dpc(ulong data); |
---|
1456 | | -#endif |
---|
1457 | 897 | /* forward decl */ |
---|
1458 | 898 | extern int dhd_wait_pend8021x(struct net_device *dev); |
---|
1459 | 899 | void dhd_os_wd_timer_extend(void *bus, bool extend); |
---|
.. | .. |
---|
1465 | 905 | static int dhd_toe_get(dhd_info_t *dhd, int idx, uint32 *toe_ol); |
---|
1466 | 906 | static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol); |
---|
1467 | 907 | #endif /* TOE */ |
---|
1468 | | -#ifdef BCMDBUS |
---|
1469 | | -int dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf); |
---|
1470 | | -#endif |
---|
1471 | 908 | |
---|
1472 | | -static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, uint16 pktlen, |
---|
1473 | | - wl_event_msg_t *event_ptr, void **data_ptr); |
---|
| 909 | +static int dhd_wl_host_event(dhd_info_t *dhd, int ifidx, void *pktdata, uint16 pktlen, |
---|
| 910 | + wl_event_msg_t *event_ptr, void **data_ptr); |
---|
1474 | 911 | |
---|
1475 | 912 | #if defined(CONFIG_PM_SLEEP) |
---|
1476 | 913 | static int dhd_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored) |
---|
1477 | 914 | { |
---|
1478 | 915 | int ret = NOTIFY_DONE; |
---|
1479 | 916 | bool suspend = FALSE; |
---|
| 917 | + |
---|
| 918 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 919 | +#pragma GCC diagnostic push |
---|
| 920 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 921 | +#endif // endif |
---|
1480 | 922 | dhd_info_t *dhdinfo = (dhd_info_t*)container_of(nfb, struct dhd_info, pm_notifier); |
---|
| 923 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 924 | +#pragma GCC diagnostic pop |
---|
| 925 | +#endif // endif |
---|
1481 | 926 | |
---|
1482 | 927 | BCM_REFERENCE(dhdinfo); |
---|
| 928 | + BCM_REFERENCE(suspend); |
---|
1483 | 929 | |
---|
1484 | 930 | switch (action) { |
---|
1485 | 931 | case PM_HIBERNATION_PREPARE: |
---|
.. | .. |
---|
1493 | 939 | break; |
---|
1494 | 940 | } |
---|
1495 | 941 | |
---|
1496 | | -#if defined(SUPPORT_P2P_GO_PS) |
---|
1497 | | -#ifdef PROP_TXSTATUS |
---|
| 942 | +#if defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) |
---|
1498 | 943 | if (suspend) { |
---|
1499 | 944 | DHD_OS_WAKE_LOCK_WAIVE(&dhdinfo->pub); |
---|
1500 | 945 | dhd_wlfc_suspend(&dhdinfo->pub); |
---|
1501 | 946 | DHD_OS_WAKE_LOCK_RESTORE(&dhdinfo->pub); |
---|
1502 | | - } else |
---|
| 947 | + } else { |
---|
1503 | 948 | dhd_wlfc_resume(&dhdinfo->pub); |
---|
1504 | | -#endif |
---|
1505 | | -#endif /* defined(SUPPORT_P2P_GO_PS) */ |
---|
| 949 | + } |
---|
| 950 | +#endif /* defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) */ |
---|
1506 | 951 | |
---|
1507 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ |
---|
1508 | | - KERNEL_VERSION(2, 6, 39)) |
---|
1509 | 952 | dhd_mmc_suspend = suspend; |
---|
1510 | 953 | smp_mb(); |
---|
1511 | | -#endif |
---|
1512 | 954 | |
---|
1513 | 955 | return ret; |
---|
1514 | 956 | } |
---|
.. | .. |
---|
1527 | 969 | static void dhd_os_rxflock(dhd_pub_t *pub); |
---|
1528 | 970 | static void dhd_os_rxfunlock(dhd_pub_t *pub); |
---|
1529 | 971 | |
---|
| 972 | +#if defined(DHD_H2D_LOG_TIME_SYNC) |
---|
| 973 | +static void |
---|
| 974 | +dhd_deferred_work_rte_log_time_sync(void *handle, void *event_info, u8 event); |
---|
| 975 | +#endif /* DHD_H2D_LOG_TIME_SYNC */ |
---|
| 976 | + |
---|
1530 | 977 | /** priv_link is the link between netdev and the dhdif and dhd_info structs. */ |
---|
1531 | 978 | typedef struct dhd_dev_priv { |
---|
1532 | 979 | dhd_info_t * dhd; /* cached pointer to dhd_info in netdevice priv */ |
---|
.. | .. |
---|
1542 | 989 | #define DHD_DEV_IFIDX(dev) (((dhd_dev_priv_t *)DEV_PRIV(dev))->ifidx) |
---|
1543 | 990 | #define DHD_DEV_LKUP(dev) (((dhd_dev_priv_t *)DEV_PRIV(dev))->lkup) |
---|
1544 | 991 | |
---|
| 992 | +#if defined(DHD_OF_SUPPORT) |
---|
| 993 | +extern int dhd_wlan_init(void); |
---|
| 994 | +#endif /* defined(DHD_OF_SUPPORT) */ |
---|
1545 | 995 | /** Clear the dhd net_device's private structure. */ |
---|
1546 | 996 | static inline void |
---|
1547 | 997 | dhd_dev_priv_clear(struct net_device * dev) |
---|
.. | .. |
---|
1568 | 1018 | dev_priv->ifidx = ifidx; |
---|
1569 | 1019 | } |
---|
1570 | 1020 | |
---|
1571 | | -#ifdef PCIE_FULL_DONGLE |
---|
| 1021 | +/* Return interface pointer */ |
---|
| 1022 | +struct dhd_if * dhd_get_ifp(dhd_pub_t *dhdp, uint32 ifidx) |
---|
| 1023 | +{ |
---|
| 1024 | + ASSERT(ifidx < DHD_MAX_IFS); |
---|
| 1025 | + |
---|
| 1026 | + if (!dhdp || !dhdp->info || ifidx >= DHD_MAX_IFS) |
---|
| 1027 | + return NULL; |
---|
| 1028 | + |
---|
| 1029 | + return dhdp->info->iflist[ifidx]; |
---|
| 1030 | +} |
---|
1572 | 1031 | |
---|
1573 | 1032 | /** Dummy objects are defined with state representing bad|down. |
---|
1574 | 1033 | * Performance gains from reducing branch conditionals, instruction parallelism, |
---|
.. | .. |
---|
1579 | 1038 | |
---|
1580 | 1039 | /* Dummy dhd_info object */ |
---|
1581 | 1040 | dhd_info_t dhd_info_null = { |
---|
1582 | | -#if defined(BCM_GMAC3) |
---|
1583 | | - .fwdh = FWDER_NULL, |
---|
1584 | | -#endif |
---|
1585 | 1041 | .pub = { |
---|
1586 | 1042 | .info = &dhd_info_null, |
---|
1587 | 1043 | #ifdef DHDTCPACK_SUPPRESS |
---|
1588 | 1044 | .tcpack_sup_mode = TCPACK_SUP_REPLACE, |
---|
1589 | 1045 | #endif /* DHDTCPACK_SUPPRESS */ |
---|
1590 | | -#if defined(TRAFFIC_MGMT_DWM) |
---|
1591 | | - .dhd_tm_dwm_tbl = { .dhd_dwm_enabled = TRUE }, |
---|
1592 | | -#endif |
---|
1593 | 1046 | .up = FALSE, |
---|
1594 | 1047 | .busstate = DHD_BUS_DOWN |
---|
1595 | 1048 | } |
---|
.. | .. |
---|
1605 | 1058 | |
---|
1606 | 1059 | /* Dummy dhd_if object */ |
---|
1607 | 1060 | dhd_if_t dhd_if_null = { |
---|
1608 | | -#if defined(BCM_GMAC3) |
---|
1609 | | - .fwdh = FWDER_NULL, |
---|
1610 | | -#endif |
---|
1611 | 1061 | #ifdef WMF |
---|
1612 | 1062 | .wmf = { .wmf_enable = TRUE }, |
---|
1613 | | -#endif |
---|
| 1063 | +#endif // endif |
---|
1614 | 1064 | .info = DHD_INFO_NULL, |
---|
1615 | 1065 | .net = DHD_NET_DEV_NULL, |
---|
1616 | 1066 | .idx = DHD_BAD_IF |
---|
.. | .. |
---|
1620 | 1070 | #define DHD_STA_NULL ((dhd_sta_t *)NULL) |
---|
1621 | 1071 | |
---|
1622 | 1072 | /** Interface STA list management. */ |
---|
1623 | | - |
---|
1624 | | -/** Fetch the dhd_if object, given the interface index in the dhd. */ |
---|
1625 | | -static inline dhd_if_t *dhd_get_ifp(dhd_pub_t *dhdp, uint32 ifidx); |
---|
1626 | 1073 | |
---|
1627 | 1074 | /** Alloc/Free a dhd_sta object from the dhd instances' sta_pool. */ |
---|
1628 | 1075 | static void dhd_sta_free(dhd_pub_t *pub, dhd_sta_t *sta); |
---|
.. | .. |
---|
1638 | 1085 | /* Clear the pool of dhd_sta_t objects for built-in type driver */ |
---|
1639 | 1086 | static void dhd_sta_pool_clear(dhd_pub_t *dhdp, int max_sta); |
---|
1640 | 1087 | |
---|
1641 | | - |
---|
1642 | | -/* Return interface pointer */ |
---|
1643 | | -static inline dhd_if_t *dhd_get_ifp(dhd_pub_t *dhdp, uint32 ifidx) |
---|
1644 | | -{ |
---|
1645 | | - ASSERT(ifidx < DHD_MAX_IFS); |
---|
1646 | | - |
---|
1647 | | - if (ifidx >= DHD_MAX_IFS) |
---|
1648 | | - return NULL; |
---|
1649 | | - |
---|
1650 | | - return dhdp->info->iflist[ifidx]; |
---|
1651 | | -} |
---|
1652 | | - |
---|
1653 | 1088 | /** Reset a dhd_sta object and free into the dhd pool. */ |
---|
1654 | 1089 | static void |
---|
1655 | 1090 | dhd_sta_free(dhd_pub_t * dhdp, dhd_sta_t * sta) |
---|
1656 | 1091 | { |
---|
| 1092 | +#ifdef PCIE_FULL_DONGLE |
---|
1657 | 1093 | int prio; |
---|
| 1094 | +#endif // endif |
---|
1658 | 1095 | |
---|
1659 | 1096 | ASSERT((sta != DHD_STA_NULL) && (sta->idx != ID16_INVALID)); |
---|
1660 | 1097 | |
---|
1661 | 1098 | ASSERT((dhdp->staid_allocator != NULL) && (dhdp->sta_pool != NULL)); |
---|
1662 | 1099 | |
---|
| 1100 | +#ifdef PCIE_FULL_DONGLE |
---|
1663 | 1101 | /* |
---|
1664 | 1102 | * Flush and free all packets in all flowring's queues belonging to sta. |
---|
1665 | 1103 | * Packets in flow ring will be flushed later. |
---|
.. | .. |
---|
1669 | 1107 | |
---|
1670 | 1108 | if (flowid != FLOWID_INVALID) { |
---|
1671 | 1109 | unsigned long flags; |
---|
1672 | | - flow_queue_t * queue = dhd_flow_queue(dhdp, flowid); |
---|
1673 | 1110 | flow_ring_node_t * flow_ring_node; |
---|
1674 | 1111 | |
---|
1675 | 1112 | #ifdef DHDTCPACK_SUPPRESS |
---|
.. | .. |
---|
1680 | 1117 | #endif /* DHDTCPACK_SUPPRESS */ |
---|
1681 | 1118 | |
---|
1682 | 1119 | flow_ring_node = dhd_flow_ring_node(dhdp, flowid); |
---|
1683 | | - DHD_FLOWRING_LOCK(flow_ring_node->lock, flags); |
---|
1684 | | - flow_ring_node->status = FLOW_RING_STATUS_STA_FREEING; |
---|
| 1120 | + if (flow_ring_node) { |
---|
| 1121 | + flow_queue_t *queue = &flow_ring_node->queue; |
---|
1685 | 1122 | |
---|
1686 | | - if (!DHD_FLOW_QUEUE_EMPTY(queue)) { |
---|
1687 | | - void * pkt; |
---|
1688 | | - while ((pkt = dhd_flow_queue_dequeue(dhdp, queue)) != NULL) { |
---|
1689 | | - PKTFREE(dhdp->osh, pkt, TRUE); |
---|
| 1123 | + DHD_FLOWRING_LOCK(flow_ring_node->lock, flags); |
---|
| 1124 | + flow_ring_node->status = FLOW_RING_STATUS_STA_FREEING; |
---|
| 1125 | + |
---|
| 1126 | + if (!DHD_FLOW_QUEUE_EMPTY(queue)) { |
---|
| 1127 | + void * pkt; |
---|
| 1128 | + while ((pkt = dhd_flow_queue_dequeue(dhdp, queue)) != |
---|
| 1129 | + NULL) { |
---|
| 1130 | + PKTFREE(dhdp->osh, pkt, TRUE); |
---|
| 1131 | + } |
---|
1690 | 1132 | } |
---|
1691 | | - } |
---|
1692 | 1133 | |
---|
1693 | | - DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags); |
---|
1694 | | - ASSERT(DHD_FLOW_QUEUE_EMPTY(queue)); |
---|
| 1134 | + DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags); |
---|
| 1135 | + ASSERT(DHD_FLOW_QUEUE_EMPTY(queue)); |
---|
| 1136 | + } |
---|
1695 | 1137 | } |
---|
1696 | 1138 | |
---|
1697 | 1139 | sta->flowid[prio] = FLOWID_INVALID; |
---|
1698 | 1140 | } |
---|
| 1141 | +#endif /* PCIE_FULL_DONGLE */ |
---|
1699 | 1142 | |
---|
1700 | 1143 | id16_map_free(dhdp->staid_allocator, sta->idx); |
---|
1701 | 1144 | DHD_CUMM_CTR_INIT(&sta->cumm_ctr); |
---|
.. | .. |
---|
1743 | 1186 | unsigned long flags; |
---|
1744 | 1187 | |
---|
1745 | 1188 | DHD_IF_STA_LIST_LOCK(ifp, flags); |
---|
1746 | | - |
---|
| 1189 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 1190 | +#pragma GCC diagnostic push |
---|
| 1191 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 1192 | +#endif // endif |
---|
1747 | 1193 | list_for_each_entry_safe(sta, next, &ifp->sta_list, list) { |
---|
1748 | | -#if defined(BCM_GMAC3) |
---|
1749 | | - if (ifp->fwdh) { |
---|
1750 | | - /* Remove sta from WOFA forwarder. */ |
---|
1751 | | - fwder_deassoc(ifp->fwdh, (uint16 *)(sta->ea.octet), (uintptr_t)sta); |
---|
1752 | | - } |
---|
1753 | | -#endif /* BCM_GMAC3 */ |
---|
1754 | 1194 | list_del(&sta->list); |
---|
1755 | 1195 | dhd_sta_free(&ifp->info->pub, sta); |
---|
1756 | 1196 | } |
---|
1757 | | - |
---|
| 1197 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 1198 | +#pragma GCC diagnostic pop |
---|
| 1199 | +#endif // endif |
---|
1758 | 1200 | DHD_IF_STA_LIST_UNLOCK(ifp, flags); |
---|
1759 | 1201 | |
---|
1760 | 1202 | return; |
---|
.. | .. |
---|
1764 | 1206 | static void |
---|
1765 | 1207 | dhd_if_flush_sta(dhd_if_t * ifp) |
---|
1766 | 1208 | { |
---|
1767 | | -#if defined(BCM_GMAC3) |
---|
1768 | | - |
---|
1769 | | - if (ifp && (ifp->fwdh != FWDER_NULL)) { |
---|
1770 | | - dhd_sta_t *sta, *next; |
---|
1771 | | - unsigned long flags; |
---|
1772 | | - |
---|
1773 | | - DHD_IF_STA_LIST_LOCK(ifp, flags); |
---|
1774 | | - |
---|
1775 | | - list_for_each_entry_safe(sta, next, &ifp->sta_list, list) { |
---|
1776 | | - /* Remove any sta entry from WOFA forwarder. */ |
---|
1777 | | - fwder_flush(ifp->fwdh, (uintptr_t)sta); |
---|
1778 | | - } |
---|
1779 | | - |
---|
1780 | | - DHD_IF_STA_LIST_UNLOCK(ifp, flags); |
---|
1781 | | - } |
---|
1782 | | -#endif /* BCM_GMAC3 */ |
---|
1783 | 1209 | } |
---|
1784 | 1210 | |
---|
1785 | 1211 | /** Construct a pool of dhd_sta_t objects to be used by interfaces. */ |
---|
1786 | 1212 | static int |
---|
1787 | 1213 | dhd_sta_pool_init(dhd_pub_t *dhdp, int max_sta) |
---|
1788 | 1214 | { |
---|
1789 | | - int idx, prio, sta_pool_memsz; |
---|
| 1215 | + int idx, sta_pool_memsz; |
---|
| 1216 | +#ifdef PCIE_FULL_DONGLE |
---|
| 1217 | + int prio; |
---|
| 1218 | +#endif /* PCIE_FULL_DONGLE */ |
---|
1790 | 1219 | dhd_sta_t * sta; |
---|
1791 | 1220 | dhd_sta_pool_t * sta_pool; |
---|
1792 | 1221 | void * staid_allocator; |
---|
.. | .. |
---|
1820 | 1249 | sta->idx = id16_map_alloc(staid_allocator); |
---|
1821 | 1250 | ASSERT(sta->idx <= max_sta); |
---|
1822 | 1251 | } |
---|
| 1252 | + |
---|
1823 | 1253 | /* Now place them into the pre-allocated free pool. */ |
---|
1824 | 1254 | for (idx = 1; idx <= max_sta; idx++) { |
---|
1825 | 1255 | sta = &sta_pool[idx]; |
---|
| 1256 | +#ifdef PCIE_FULL_DONGLE |
---|
1826 | 1257 | for (prio = 0; prio < (int)NUMPRIO; prio++) { |
---|
1827 | 1258 | sta->flowid[prio] = FLOWID_INVALID; /* Flow rings do not exist */ |
---|
1828 | 1259 | } |
---|
| 1260 | +#endif /* PCIE_FULL_DONGLE */ |
---|
1829 | 1261 | dhd_sta_free(dhdp, sta); |
---|
1830 | 1262 | } |
---|
1831 | 1263 | |
---|
.. | .. |
---|
1859 | 1291 | static void |
---|
1860 | 1292 | dhd_sta_pool_clear(dhd_pub_t *dhdp, int max_sta) |
---|
1861 | 1293 | { |
---|
1862 | | - int idx, prio, sta_pool_memsz; |
---|
| 1294 | + int idx, sta_pool_memsz; |
---|
| 1295 | +#ifdef PCIE_FULL_DONGLE |
---|
| 1296 | + int prio; |
---|
| 1297 | +#endif /* PCIE_FULL_DONGLE */ |
---|
1863 | 1298 | dhd_sta_t * sta; |
---|
1864 | 1299 | dhd_sta_pool_t * sta_pool; |
---|
1865 | 1300 | void *staid_allocator; |
---|
.. | .. |
---|
1898 | 1333 | /* Now place them into the pre-allocated free pool. */ |
---|
1899 | 1334 | for (idx = 1; idx <= max_sta; idx++) { |
---|
1900 | 1335 | sta = &sta_pool[idx]; |
---|
| 1336 | +#ifdef PCIE_FULL_DONGLE |
---|
1901 | 1337 | for (prio = 0; prio < (int)NUMPRIO; prio++) { |
---|
1902 | 1338 | sta->flowid[prio] = FLOWID_INVALID; /* Flow rings do not exist */ |
---|
1903 | 1339 | } |
---|
| 1340 | +#endif /* PCIE_FULL_DONGLE */ |
---|
1904 | 1341 | dhd_sta_free(dhdp, sta); |
---|
1905 | 1342 | } |
---|
1906 | 1343 | } |
---|
.. | .. |
---|
1919 | 1356 | return DHD_STA_NULL; |
---|
1920 | 1357 | |
---|
1921 | 1358 | DHD_IF_STA_LIST_LOCK(ifp, flags); |
---|
1922 | | - |
---|
| 1359 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 1360 | +#pragma GCC diagnostic push |
---|
| 1361 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 1362 | +#endif // endif |
---|
1923 | 1363 | list_for_each_entry(sta, &ifp->sta_list, list) { |
---|
1924 | 1364 | if (!memcmp(sta->ea.octet, ea, ETHER_ADDR_LEN)) { |
---|
| 1365 | + DHD_INFO(("%s: Found STA " MACDBG "\n", |
---|
| 1366 | + __FUNCTION__, MAC2STRDBG((char *)ea))); |
---|
1925 | 1367 | DHD_IF_STA_LIST_UNLOCK(ifp, flags); |
---|
1926 | 1368 | return sta; |
---|
1927 | 1369 | } |
---|
1928 | 1370 | } |
---|
1929 | | - |
---|
| 1371 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 1372 | +#pragma GCC diagnostic pop |
---|
| 1373 | +#endif // endif |
---|
1930 | 1374 | DHD_IF_STA_LIST_UNLOCK(ifp, flags); |
---|
1931 | 1375 | |
---|
1932 | 1376 | return DHD_STA_NULL; |
---|
.. | .. |
---|
1945 | 1389 | if (ifp == NULL) |
---|
1946 | 1390 | return DHD_STA_NULL; |
---|
1947 | 1391 | |
---|
| 1392 | + if (!memcmp(ifp->net->dev_addr, ea, ETHER_ADDR_LEN)) { |
---|
| 1393 | + DHD_ERROR(("%s: Serious FAILURE, receive own MAC %pM !!\n", __FUNCTION__, ea)); |
---|
| 1394 | + return DHD_STA_NULL; |
---|
| 1395 | + } |
---|
| 1396 | + |
---|
1948 | 1397 | sta = dhd_sta_alloc((dhd_pub_t *)pub); |
---|
1949 | 1398 | if (sta == DHD_STA_NULL) { |
---|
1950 | 1399 | DHD_ERROR(("%s: Alloc failed\n", __FUNCTION__)); |
---|
.. | .. |
---|
1956 | 1405 | /* link the sta and the dhd interface */ |
---|
1957 | 1406 | sta->ifp = ifp; |
---|
1958 | 1407 | sta->ifidx = ifidx; |
---|
1959 | | -#ifdef DHD_WMF |
---|
1960 | | - sta->psta_prim = NULL; |
---|
1961 | | -#endif |
---|
1962 | 1408 | INIT_LIST_HEAD(&sta->list); |
---|
1963 | 1409 | |
---|
1964 | 1410 | DHD_IF_STA_LIST_LOCK(ifp, flags); |
---|
1965 | 1411 | |
---|
1966 | 1412 | list_add_tail(&sta->list, &ifp->sta_list); |
---|
1967 | 1413 | |
---|
1968 | | -#if defined(BCM_GMAC3) |
---|
1969 | | - if (ifp->fwdh) { |
---|
1970 | | - ASSERT(ISALIGNED(ea, 2)); |
---|
1971 | | - /* Add sta to WOFA forwarder. */ |
---|
1972 | | - fwder_reassoc(ifp->fwdh, (uint16 *)ea, (uintptr_t)sta); |
---|
1973 | | - } |
---|
1974 | | -#endif /* BCM_GMAC3 */ |
---|
| 1414 | + DHD_ERROR(("%s: Adding STA " MACDBG "\n", |
---|
| 1415 | + __FUNCTION__, MAC2STRDBG((char *)ea))); |
---|
1975 | 1416 | |
---|
1976 | 1417 | DHD_IF_STA_LIST_UNLOCK(ifp, flags); |
---|
1977 | 1418 | |
---|
1978 | 1419 | return sta; |
---|
| 1420 | +} |
---|
| 1421 | + |
---|
| 1422 | +/** Delete all STAs from the interface's STA list. */ |
---|
| 1423 | +void |
---|
| 1424 | +dhd_del_all_sta(void *pub, int ifidx) |
---|
| 1425 | +{ |
---|
| 1426 | + dhd_sta_t *sta, *next; |
---|
| 1427 | + dhd_if_t *ifp; |
---|
| 1428 | + unsigned long flags; |
---|
| 1429 | + |
---|
| 1430 | + ifp = dhd_get_ifp((dhd_pub_t *)pub, ifidx); |
---|
| 1431 | + if (ifp == NULL) |
---|
| 1432 | + return; |
---|
| 1433 | + |
---|
| 1434 | + DHD_IF_STA_LIST_LOCK(ifp, flags); |
---|
| 1435 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 1436 | +#pragma GCC diagnostic push |
---|
| 1437 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 1438 | +#endif // endif |
---|
| 1439 | + list_for_each_entry_safe(sta, next, &ifp->sta_list, list) { |
---|
| 1440 | + |
---|
| 1441 | + list_del(&sta->list); |
---|
| 1442 | + dhd_sta_free(&ifp->info->pub, sta); |
---|
| 1443 | +#ifdef DHD_L2_FILTER |
---|
| 1444 | + if (ifp->parp_enable) { |
---|
| 1445 | + /* clear Proxy ARP cache of specific Ethernet Address */ |
---|
| 1446 | + bcm_l2_filter_arp_table_update(((dhd_pub_t*)pub)->osh, |
---|
| 1447 | + ifp->phnd_arp_table, FALSE, |
---|
| 1448 | + sta->ea.octet, FALSE, ((dhd_pub_t*)pub)->tickcnt); |
---|
| 1449 | + } |
---|
| 1450 | +#endif /* DHD_L2_FILTER */ |
---|
| 1451 | + } |
---|
| 1452 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 1453 | +#pragma GCC diagnostic pop |
---|
| 1454 | +#endif // endif |
---|
| 1455 | + DHD_IF_STA_LIST_UNLOCK(ifp, flags); |
---|
| 1456 | + |
---|
| 1457 | + return; |
---|
1979 | 1458 | } |
---|
1980 | 1459 | |
---|
1981 | 1460 | /** Delete STA from the interface's STA list. */ |
---|
.. | .. |
---|
1992 | 1471 | return; |
---|
1993 | 1472 | |
---|
1994 | 1473 | DHD_IF_STA_LIST_LOCK(ifp, flags); |
---|
1995 | | - |
---|
| 1474 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 1475 | +#pragma GCC diagnostic push |
---|
| 1476 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 1477 | +#endif // endif |
---|
1996 | 1478 | list_for_each_entry_safe(sta, next, &ifp->sta_list, list) { |
---|
1997 | 1479 | if (!memcmp(sta->ea.octet, ea, ETHER_ADDR_LEN)) { |
---|
1998 | | -#if defined(BCM_GMAC3) |
---|
1999 | | - if (ifp->fwdh) { /* Found a sta, remove from WOFA forwarder. */ |
---|
2000 | | - ASSERT(ISALIGNED(ea, 2)); |
---|
2001 | | - fwder_deassoc(ifp->fwdh, (uint16 *)ea, (uintptr_t)sta); |
---|
2002 | | - } |
---|
2003 | | -#endif /* BCM_GMAC3 */ |
---|
| 1480 | + DHD_ERROR(("%s: Deleting STA " MACDBG "\n", |
---|
| 1481 | + __FUNCTION__, MAC2STRDBG(sta->ea.octet))); |
---|
2004 | 1482 | list_del(&sta->list); |
---|
2005 | 1483 | dhd_sta_free(&ifp->info->pub, sta); |
---|
2006 | 1484 | } |
---|
2007 | 1485 | } |
---|
2008 | | - |
---|
| 1486 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 1487 | +#pragma GCC diagnostic pop |
---|
| 1488 | +#endif // endif |
---|
2009 | 1489 | DHD_IF_STA_LIST_UNLOCK(ifp, flags); |
---|
2010 | 1490 | #ifdef DHD_L2_FILTER |
---|
2011 | 1491 | if (ifp->parp_enable) { |
---|
.. | .. |
---|
2034 | 1514 | } |
---|
2035 | 1515 | |
---|
2036 | 1516 | #if defined(DHD_IGMP_UCQUERY) || defined(DHD_UCAST_UPNP) |
---|
2037 | | -#if !defined(BCM_GMAC3) |
---|
2038 | 1517 | static struct list_head * |
---|
2039 | 1518 | dhd_sta_list_snapshot(dhd_info_t *dhd, dhd_if_t *ifp, struct list_head *snapshot_list) |
---|
2040 | 1519 | { |
---|
.. | .. |
---|
2074 | 1553 | MFREE(dhd->pub.osh, sta, sizeof(dhd_sta_t)); |
---|
2075 | 1554 | } |
---|
2076 | 1555 | } |
---|
2077 | | -#endif /* !BCM_GMAC3 */ |
---|
2078 | 1556 | #endif /* DHD_IGMP_UCQUERY || DHD_UCAST_UPNP */ |
---|
2079 | 1557 | |
---|
2080 | | -#else |
---|
2081 | | -static inline void dhd_if_flush_sta(dhd_if_t * ifp) { } |
---|
2082 | | -static inline void dhd_if_del_sta_list(dhd_if_t *ifp) {} |
---|
2083 | | -static inline int dhd_sta_pool_init(dhd_pub_t *dhdp, int max_sta) { return BCME_OK; } |
---|
2084 | | -static inline void dhd_sta_pool_fini(dhd_pub_t *dhdp, int max_sta) {} |
---|
2085 | | -static inline void dhd_sta_pool_clear(dhd_pub_t *dhdp, int max_sta) {} |
---|
2086 | | -dhd_sta_t *dhd_findadd_sta(void *pub, int ifidx, void *ea) { return NULL; } |
---|
2087 | | -void dhd_del_sta(void *pub, int ifidx, void *ea) {} |
---|
2088 | | -#endif /* PCIE_FULL_DONGLE */ |
---|
2089 | | - |
---|
2090 | | - |
---|
2091 | | -#if defined(DHD_LB) |
---|
2092 | | - |
---|
2093 | | -#if defined(DHD_LB_TXC) || defined(DHD_LB_RXC) |
---|
2094 | | -/** |
---|
2095 | | - * dhd_tasklet_schedule - Function that runs in IPI context of the destination |
---|
2096 | | - * CPU and schedules a tasklet. |
---|
2097 | | - * @tasklet: opaque pointer to the tasklet |
---|
2098 | | - */ |
---|
2099 | | -static INLINE void |
---|
2100 | | -dhd_tasklet_schedule(void *tasklet) |
---|
2101 | | -{ |
---|
2102 | | - tasklet_schedule((struct tasklet_struct *)tasklet); |
---|
2103 | | -} |
---|
2104 | | - |
---|
2105 | | -/** |
---|
2106 | | - * dhd_tasklet_schedule_on - Executes the passed takslet in a given CPU |
---|
2107 | | - * @tasklet: tasklet to be scheduled |
---|
2108 | | - * @on_cpu: cpu core id |
---|
2109 | | - * |
---|
2110 | | - * If the requested cpu is online, then an IPI is sent to this cpu via the |
---|
2111 | | - * smp_call_function_single with no wait and the tasklet_schedule function |
---|
2112 | | - * will be invoked to schedule the specified tasklet on the requested CPU. |
---|
2113 | | - */ |
---|
2114 | | -static void |
---|
2115 | | -dhd_tasklet_schedule_on(struct tasklet_struct *tasklet, int on_cpu) |
---|
2116 | | -{ |
---|
2117 | | - const int wait = 0; |
---|
2118 | | - smp_call_function_single(on_cpu, |
---|
2119 | | - dhd_tasklet_schedule, (void *)tasklet, wait); |
---|
2120 | | -} |
---|
2121 | | -#endif /* DHD_LB_TXC || DHD_LB_RXC */ |
---|
2122 | | - |
---|
2123 | | - |
---|
2124 | | -#if defined(DHD_LB_TXC) |
---|
2125 | | -/** |
---|
2126 | | - * dhd_lb_tx_compl_dispatch - load balance by dispatching the tx_compl_tasklet |
---|
2127 | | - * on another cpu. The tx_compl_tasklet will take care of DMA unmapping and |
---|
2128 | | - * freeing the packets placed in the tx_compl workq |
---|
2129 | | - */ |
---|
| 1558 | +#if defined(DNGL_AXI_ERROR_LOGGING) && defined(DHD_USE_WQ_FOR_DNGL_AXI_ERROR) |
---|
2130 | 1559 | void |
---|
2131 | | -dhd_lb_tx_compl_dispatch(dhd_pub_t *dhdp) |
---|
| 1560 | +dhd_axi_error_dispatch(dhd_pub_t *dhdp) |
---|
2132 | 1561 | { |
---|
2133 | 1562 | dhd_info_t *dhd = dhdp->info; |
---|
2134 | | - int curr_cpu, on_cpu; |
---|
2135 | | - |
---|
2136 | | - if (dhd->rx_napi_netdev == NULL) { |
---|
2137 | | - DHD_ERROR(("%s: dhd->rx_napi_netdev is NULL\n", __FUNCTION__)); |
---|
2138 | | - return; |
---|
2139 | | - } |
---|
2140 | | - |
---|
2141 | | - DHD_LB_STATS_INCR(dhd->txc_sched_cnt); |
---|
2142 | | - /* |
---|
2143 | | - * If the destination CPU is NOT online or is same as current CPU |
---|
2144 | | - * no need to schedule the work |
---|
2145 | | - */ |
---|
2146 | | - curr_cpu = get_cpu(); |
---|
2147 | | - put_cpu(); |
---|
2148 | | - |
---|
2149 | | - on_cpu = atomic_read(&dhd->tx_compl_cpu); |
---|
2150 | | - |
---|
2151 | | - if ((on_cpu == curr_cpu) || (!cpu_online(on_cpu))) { |
---|
2152 | | - dhd_tasklet_schedule(&dhd->tx_compl_tasklet); |
---|
2153 | | - } else { |
---|
2154 | | - schedule_work(&dhd->tx_compl_dispatcher_work); |
---|
2155 | | - } |
---|
| 1563 | + schedule_work(&dhd->axi_error_dispatcher_work); |
---|
2156 | 1564 | } |
---|
2157 | 1565 | |
---|
2158 | | -static void dhd_tx_compl_dispatcher_fn(struct work_struct * work) |
---|
| 1566 | +static void dhd_axi_error_dispatcher_fn(struct work_struct * work) |
---|
2159 | 1567 | { |
---|
2160 | 1568 | struct dhd_info *dhd = |
---|
2161 | | - container_of(work, struct dhd_info, tx_compl_dispatcher_work); |
---|
2162 | | - int cpu; |
---|
2163 | | - |
---|
2164 | | - get_online_cpus(); |
---|
2165 | | - cpu = atomic_read(&dhd->tx_compl_cpu); |
---|
2166 | | - if (!cpu_online(cpu)) |
---|
2167 | | - dhd_tasklet_schedule(&dhd->tx_compl_tasklet); |
---|
2168 | | - else |
---|
2169 | | - dhd_tasklet_schedule_on(&dhd->tx_compl_tasklet, cpu); |
---|
2170 | | - put_online_cpus(); |
---|
| 1569 | + container_of(work, struct dhd_info, axi_error_dispatcher_work); |
---|
| 1570 | + dhd_axi_error(&dhd->pub); |
---|
2171 | 1571 | } |
---|
2172 | | - |
---|
2173 | | -#endif /* DHD_LB_TXC */ |
---|
2174 | | - |
---|
2175 | | - |
---|
2176 | | -#if defined(DHD_LB_RXC) |
---|
2177 | | -/** |
---|
2178 | | - * dhd_lb_rx_compl_dispatch - load balance by dispatching the rx_compl_tasklet |
---|
2179 | | - * on another cpu. The rx_compl_tasklet will take care of reposting rx buffers |
---|
2180 | | - * in the H2D RxBuffer Post common ring, by using the recycled pktids that were |
---|
2181 | | - * placed in the rx_compl workq. |
---|
2182 | | - * |
---|
2183 | | - * @dhdp: pointer to dhd_pub object |
---|
2184 | | - */ |
---|
2185 | | -void |
---|
2186 | | -dhd_lb_rx_compl_dispatch(dhd_pub_t *dhdp) |
---|
2187 | | -{ |
---|
2188 | | - dhd_info_t *dhd = dhdp->info; |
---|
2189 | | - int curr_cpu, on_cpu; |
---|
2190 | | - |
---|
2191 | | - if (dhd->rx_napi_netdev == NULL) { |
---|
2192 | | - DHD_ERROR(("%s: dhd->rx_napi_netdev is NULL\n", __FUNCTION__)); |
---|
2193 | | - return; |
---|
2194 | | - } |
---|
2195 | | - |
---|
2196 | | - DHD_LB_STATS_INCR(dhd->rxc_sched_cnt); |
---|
2197 | | - /* |
---|
2198 | | - * If the destination CPU is NOT online or is same as current CPU |
---|
2199 | | - * no need to schedule the work |
---|
2200 | | - */ |
---|
2201 | | - curr_cpu = get_cpu(); |
---|
2202 | | - put_cpu(); |
---|
2203 | | - |
---|
2204 | | - on_cpu = atomic_read(&dhd->rx_compl_cpu); |
---|
2205 | | - |
---|
2206 | | - if ((on_cpu == curr_cpu) || (!cpu_online(on_cpu))) { |
---|
2207 | | - dhd_tasklet_schedule(&dhd->rx_compl_tasklet); |
---|
2208 | | - } else { |
---|
2209 | | - schedule_work(&dhd->rx_compl_dispatcher_work); |
---|
2210 | | - } |
---|
2211 | | -} |
---|
2212 | | - |
---|
2213 | | -static void dhd_rx_compl_dispatcher_fn(struct work_struct * work) |
---|
2214 | | -{ |
---|
2215 | | - struct dhd_info *dhd = |
---|
2216 | | - container_of(work, struct dhd_info, rx_compl_dispatcher_work); |
---|
2217 | | - int cpu; |
---|
2218 | | - |
---|
2219 | | - get_online_cpus(); |
---|
2220 | | - cpu = atomic_read(&dhd->tx_compl_cpu); |
---|
2221 | | - if (!cpu_online(cpu)) |
---|
2222 | | - dhd_tasklet_schedule(&dhd->rx_compl_tasklet); |
---|
2223 | | - else |
---|
2224 | | - dhd_tasklet_schedule_on(&dhd->rx_compl_tasklet, cpu); |
---|
2225 | | - put_online_cpus(); |
---|
2226 | | -} |
---|
2227 | | - |
---|
2228 | | -#endif /* DHD_LB_RXC */ |
---|
2229 | | - |
---|
2230 | | - |
---|
2231 | | -#if defined(DHD_LB_RXP) |
---|
2232 | | -/** |
---|
2233 | | - * dhd_napi_poll - Load balance napi poll function to process received |
---|
2234 | | - * packets and send up the network stack using netif_receive_skb() |
---|
2235 | | - * |
---|
2236 | | - * @napi: napi object in which context this poll function is invoked |
---|
2237 | | - * @budget: number of packets to be processed. |
---|
2238 | | - * |
---|
2239 | | - * Fetch the dhd_info given the rx_napi_struct. Move all packets from the |
---|
2240 | | - * rx_napi_queue into a local rx_process_queue (lock and queue move and unlock). |
---|
2241 | | - * Dequeue each packet from head of rx_process_queue, fetch the ifid from the |
---|
2242 | | - * packet tag and sendup. |
---|
2243 | | - */ |
---|
2244 | | -static int |
---|
2245 | | -dhd_napi_poll(struct napi_struct *napi, int budget) |
---|
2246 | | -{ |
---|
2247 | | - int ifid; |
---|
2248 | | - const int pkt_count = 1; |
---|
2249 | | - const int chan = 0; |
---|
2250 | | - struct sk_buff * skb; |
---|
2251 | | - unsigned long flags; |
---|
2252 | | - struct dhd_info *dhd; |
---|
2253 | | - int processed = 0; |
---|
2254 | | - struct sk_buff_head rx_process_queue; |
---|
2255 | | - |
---|
2256 | | - dhd = container_of(napi, struct dhd_info, rx_napi_struct); |
---|
2257 | | - DHD_INFO(("%s napi_queue<%d> budget<%d>\n", |
---|
2258 | | - __FUNCTION__, skb_queue_len(&dhd->rx_napi_queue), budget)); |
---|
2259 | | - |
---|
2260 | | - __skb_queue_head_init(&rx_process_queue); |
---|
2261 | | - |
---|
2262 | | - /* extract the entire rx_napi_queue into local rx_process_queue */ |
---|
2263 | | - spin_lock_irqsave(&dhd->rx_napi_queue.lock, flags); |
---|
2264 | | - skb_queue_splice_tail_init(&dhd->rx_napi_queue, &rx_process_queue); |
---|
2265 | | - spin_unlock_irqrestore(&dhd->rx_napi_queue.lock, flags); |
---|
2266 | | - |
---|
2267 | | - while ((skb = __skb_dequeue(&rx_process_queue)) != NULL) { |
---|
2268 | | - OSL_PREFETCH(skb->data); |
---|
2269 | | - |
---|
2270 | | - ifid = DHD_PKTTAG_IFID((dhd_pkttag_fr_t *)PKTTAG(skb)); |
---|
2271 | | - |
---|
2272 | | - DHD_INFO(("%s dhd_rx_frame pkt<%p> ifid<%d>\n", |
---|
2273 | | - __FUNCTION__, skb, ifid)); |
---|
2274 | | - |
---|
2275 | | - dhd_rx_frame(&dhd->pub, ifid, skb, pkt_count, chan); |
---|
2276 | | - processed++; |
---|
2277 | | - } |
---|
2278 | | - |
---|
2279 | | - DHD_LB_STATS_UPDATE_NAPI_HISTO(&dhd->pub, processed); |
---|
2280 | | - |
---|
2281 | | - DHD_INFO(("%s processed %d\n", __FUNCTION__, processed)); |
---|
2282 | | - napi_complete(napi); |
---|
2283 | | - |
---|
2284 | | - return budget - 1; |
---|
2285 | | -} |
---|
2286 | | - |
---|
2287 | | -/** |
---|
2288 | | - * dhd_napi_schedule - Place the napi struct into the current cpus softnet napi |
---|
2289 | | - * poll list. This function may be invoked via the smp_call_function_single |
---|
2290 | | - * from a remote CPU. |
---|
2291 | | - * |
---|
2292 | | - * This function will essentially invoke __raise_softirq_irqoff(NET_RX_SOFTIRQ) |
---|
2293 | | - * after the napi_struct is added to the softnet data's poll_list |
---|
2294 | | - * |
---|
2295 | | - * @info: pointer to a dhd_info struct |
---|
2296 | | - */ |
---|
2297 | | -static void |
---|
2298 | | -dhd_napi_schedule(void *info) |
---|
2299 | | -{ |
---|
2300 | | - dhd_info_t *dhd = (dhd_info_t *)info; |
---|
2301 | | - |
---|
2302 | | - DHD_INFO(("%s rx_napi_struct<%p> on cpu<%d>\n", |
---|
2303 | | - __FUNCTION__, &dhd->rx_napi_struct, atomic_read(&dhd->rx_napi_cpu))); |
---|
2304 | | - |
---|
2305 | | - /* add napi_struct to softnet data poll list and raise NET_RX_SOFTIRQ */ |
---|
2306 | | - if (napi_schedule_prep(&dhd->rx_napi_struct)) { |
---|
2307 | | - __napi_schedule(&dhd->rx_napi_struct); |
---|
2308 | | - DHD_LB_STATS_PERCPU_ARR_INCR(dhd->napi_percpu_run_cnt); |
---|
2309 | | - } |
---|
2310 | | - |
---|
2311 | | - /* |
---|
2312 | | - * If the rx_napi_struct was already running, then we let it complete |
---|
2313 | | - * processing all its packets. The rx_napi_struct may only run on one |
---|
2314 | | - * core at a time, to avoid out-of-order handling. |
---|
2315 | | - */ |
---|
2316 | | -} |
---|
2317 | | - |
---|
2318 | | -/** |
---|
2319 | | - * dhd_napi_schedule_on - API to schedule on a desired CPU core a NET_RX_SOFTIRQ |
---|
2320 | | - * action after placing the dhd's rx_process napi object in the the remote CPU's |
---|
2321 | | - * softnet data's poll_list. |
---|
2322 | | - * |
---|
2323 | | - * @dhd: dhd_info which has the rx_process napi object |
---|
2324 | | - * @on_cpu: desired remote CPU id |
---|
2325 | | - */ |
---|
2326 | | -static INLINE int |
---|
2327 | | -dhd_napi_schedule_on(dhd_info_t *dhd, int on_cpu) |
---|
2328 | | -{ |
---|
2329 | | - int wait = 0; /* asynchronous IPI */ |
---|
2330 | | - |
---|
2331 | | - DHD_INFO(("%s dhd<%p> napi<%p> on_cpu<%d>\n", |
---|
2332 | | - __FUNCTION__, dhd, &dhd->rx_napi_struct, on_cpu)); |
---|
2333 | | - |
---|
2334 | | - if (smp_call_function_single(on_cpu, dhd_napi_schedule, dhd, wait)) { |
---|
2335 | | - DHD_ERROR(("%s smp_call_function_single on_cpu<%d> failed\n", |
---|
2336 | | - __FUNCTION__, on_cpu)); |
---|
2337 | | - } |
---|
2338 | | - |
---|
2339 | | - DHD_LB_STATS_INCR(dhd->napi_sched_cnt); |
---|
2340 | | - |
---|
2341 | | - return 0; |
---|
2342 | | -} |
---|
2343 | | - |
---|
2344 | | -/* |
---|
2345 | | - * Call get_online_cpus/put_online_cpus around dhd_napi_schedule_on |
---|
2346 | | - * Why should we do this? |
---|
2347 | | - * The candidacy algorithm is run from the call back function |
---|
2348 | | - * registered to CPU hotplug notifier. This call back happens from Worker |
---|
2349 | | - * context. The dhd_napi_schedule_on is also from worker context. |
---|
2350 | | - * Note that both of this can run on two different CPUs at the same time. |
---|
2351 | | - * So we can possibly have a window where a given CPUn is being brought |
---|
2352 | | - * down from CPUm while we try to run a function on CPUn. |
---|
2353 | | - * To prevent this its better have the whole code to execute an SMP |
---|
2354 | | - * function under get_online_cpus. |
---|
2355 | | - * This function call ensures that hotplug mechanism does not kick-in |
---|
2356 | | - * until we are done dealing with online CPUs |
---|
2357 | | - * If the hotplug worker is already running, no worries because the |
---|
2358 | | - * candidacy algo would then reflect the same in dhd->rx_napi_cpu. |
---|
2359 | | - * |
---|
2360 | | - * The below mentioned code structure is proposed in |
---|
2361 | | - * https://www.kernel.org/doc/Documentation/cpu-hotplug.txt |
---|
2362 | | - * for the question |
---|
2363 | | - * Q: I need to ensure that a particular cpu is not removed when there is some |
---|
2364 | | - * work specific to this cpu is in progress |
---|
2365 | | - * |
---|
2366 | | - * According to the documentation calling get_online_cpus is NOT required, if |
---|
2367 | | - * we are running from tasklet context. Since dhd_rx_napi_dispatcher_fn can |
---|
2368 | | - * run from Work Queue context we have to call these functions |
---|
2369 | | - */ |
---|
2370 | | -static void dhd_rx_napi_dispatcher_fn(struct work_struct * work) |
---|
2371 | | -{ |
---|
2372 | | - struct dhd_info *dhd = |
---|
2373 | | - container_of(work, struct dhd_info, rx_napi_dispatcher_work); |
---|
2374 | | - int cpu; |
---|
2375 | | - |
---|
2376 | | - get_online_cpus(); |
---|
2377 | | - cpu = atomic_read(&dhd->rx_napi_cpu); |
---|
2378 | | - if (!cpu_online(cpu)) |
---|
2379 | | - dhd_napi_schedule(dhd); |
---|
2380 | | - else |
---|
2381 | | - dhd_napi_schedule_on(dhd, cpu); |
---|
2382 | | - put_online_cpus(); |
---|
2383 | | -} |
---|
2384 | | - |
---|
2385 | | -/** |
---|
2386 | | - * dhd_lb_rx_napi_dispatch - load balance by dispatching the rx_napi_struct |
---|
2387 | | - * to run on another CPU. The rx_napi_struct's poll function will retrieve all |
---|
2388 | | - * the packets enqueued into the rx_napi_queue and sendup. |
---|
2389 | | - * The producer's rx packet queue is appended to the rx_napi_queue before |
---|
2390 | | - * dispatching the rx_napi_struct. |
---|
2391 | | - */ |
---|
2392 | | -void |
---|
2393 | | -dhd_lb_rx_napi_dispatch(dhd_pub_t *dhdp) |
---|
2394 | | -{ |
---|
2395 | | - unsigned long flags; |
---|
2396 | | - dhd_info_t *dhd = dhdp->info; |
---|
2397 | | - int curr_cpu; |
---|
2398 | | - int on_cpu; |
---|
2399 | | - |
---|
2400 | | - if (dhd->rx_napi_netdev == NULL) { |
---|
2401 | | - DHD_ERROR(("%s: dhd->rx_napi_netdev is NULL\n", __FUNCTION__)); |
---|
2402 | | - return; |
---|
2403 | | - } |
---|
2404 | | - |
---|
2405 | | - DHD_INFO(("%s append napi_queue<%d> pend_queue<%d>\n", __FUNCTION__, |
---|
2406 | | - skb_queue_len(&dhd->rx_napi_queue), skb_queue_len(&dhd->rx_pend_queue))); |
---|
2407 | | - |
---|
2408 | | - /* append the producer's queue of packets to the napi's rx process queue */ |
---|
2409 | | - spin_lock_irqsave(&dhd->rx_napi_queue.lock, flags); |
---|
2410 | | - skb_queue_splice_tail_init(&dhd->rx_pend_queue, &dhd->rx_napi_queue); |
---|
2411 | | - spin_unlock_irqrestore(&dhd->rx_napi_queue.lock, flags); |
---|
2412 | | - |
---|
2413 | | - /* |
---|
2414 | | - * If the destination CPU is NOT online or is same as current CPU |
---|
2415 | | - * no need to schedule the work |
---|
2416 | | - */ |
---|
2417 | | - curr_cpu = get_cpu(); |
---|
2418 | | - put_cpu(); |
---|
2419 | | - |
---|
2420 | | - on_cpu = atomic_read(&dhd->rx_napi_cpu); |
---|
2421 | | - |
---|
2422 | | - if ((on_cpu == curr_cpu) || (!cpu_online(on_cpu))) { |
---|
2423 | | - dhd_napi_schedule(dhd); |
---|
2424 | | - } else { |
---|
2425 | | - schedule_work(&dhd->rx_napi_dispatcher_work); |
---|
2426 | | - } |
---|
2427 | | -} |
---|
2428 | | - |
---|
2429 | | -/** |
---|
2430 | | - * dhd_lb_rx_pkt_enqueue - Enqueue the packet into the producer's queue |
---|
2431 | | - */ |
---|
2432 | | -void |
---|
2433 | | -dhd_lb_rx_pkt_enqueue(dhd_pub_t *dhdp, void *pkt, int ifidx) |
---|
2434 | | -{ |
---|
2435 | | - dhd_info_t *dhd = dhdp->info; |
---|
2436 | | - |
---|
2437 | | - DHD_INFO(("%s enqueue pkt<%p> ifidx<%d> pend_queue<%d>\n", __FUNCTION__, |
---|
2438 | | - pkt, ifidx, skb_queue_len(&dhd->rx_pend_queue))); |
---|
2439 | | - DHD_PKTTAG_SET_IFID((dhd_pkttag_fr_t *)PKTTAG(pkt), ifidx); |
---|
2440 | | - __skb_queue_tail(&dhd->rx_pend_queue, pkt); |
---|
2441 | | -} |
---|
2442 | | -#endif /* DHD_LB_RXP */ |
---|
2443 | | - |
---|
2444 | | -#endif /* DHD_LB */ |
---|
2445 | | - |
---|
| 1572 | +#endif /* DNGL_AXI_ERROR_LOGGING && DHD_USE_WQ_FOR_DNGL_AXI_ERROR */ |
---|
2446 | 1573 | |
---|
2447 | 1574 | /** Returns dhd iflist index corresponding the the bssidx provided by apps */ |
---|
2448 | 1575 | int dhd_bssidx2idx(dhd_pub_t *dhdp, uint32 bssidx) |
---|
.. | .. |
---|
2481 | 1608 | if (dhdp->skbbuf[store_idx] != NULL) { |
---|
2482 | 1609 | /* Make sure the previous packets are processed */ |
---|
2483 | 1610 | dhd_os_rxfunlock(dhdp); |
---|
2484 | | -#ifdef RXF_DEQUEUE_ON_BUSY |
---|
2485 | | - DHD_TRACE(("dhd_rxf_enqueue: pktbuf not consumed %p, store idx %d sent idx %d\n", |
---|
2486 | | - skb, store_idx, sent_idx)); |
---|
2487 | | - return BCME_BUSY; |
---|
2488 | | -#else /* RXF_DEQUEUE_ON_BUSY */ |
---|
2489 | 1611 | DHD_ERROR(("dhd_rxf_enqueue: pktbuf not consumed %p, store idx %d sent idx %d\n", |
---|
2490 | 1612 | skb, store_idx, sent_idx)); |
---|
2491 | 1613 | /* removed msleep here, should use wait_event_timeout if we |
---|
.. | .. |
---|
2493 | 1615 | */ |
---|
2494 | 1616 | #if defined(WAIT_DEQUEUE) |
---|
2495 | 1617 | OSL_SLEEP(1); |
---|
2496 | | -#endif |
---|
| 1618 | +#endif // endif |
---|
2497 | 1619 | return BCME_ERROR; |
---|
2498 | | -#endif /* RXF_DEQUEUE_ON_BUSY */ |
---|
2499 | 1620 | } |
---|
2500 | 1621 | DHD_TRACE(("dhd_rxf_enqueue: Store SKB %p. idx %d -> %d\n", |
---|
2501 | 1622 | skb, store_idx, (store_idx + 1) & (MAXSKBPEND - 1))); |
---|
.. | .. |
---|
2538 | 1659 | |
---|
2539 | 1660 | int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost) |
---|
2540 | 1661 | { |
---|
2541 | | - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
2542 | | - |
---|
2543 | 1662 | if (prepost) { /* pre process */ |
---|
2544 | | - dhd_read_macaddr(dhd); |
---|
| 1663 | + dhd_read_cis(dhdp); |
---|
| 1664 | + dhd_check_module_cid(dhdp); |
---|
| 1665 | + dhd_check_module_mac(dhdp); |
---|
| 1666 | + dhd_set_macaddr_from_file(dhdp); |
---|
2545 | 1667 | } else { /* post process */ |
---|
2546 | | - dhd_write_macaddr(&dhd->pub.mac); |
---|
| 1668 | + dhd_write_macaddr(&dhdp->mac); |
---|
| 1669 | + dhd_clear_cis(dhdp); |
---|
2547 | 1670 | } |
---|
2548 | 1671 | |
---|
2549 | 1672 | return 0; |
---|
2550 | 1673 | } |
---|
2551 | 1674 | |
---|
2552 | | -#if defined(PKT_FILTER_SUPPORT) && !defined(GAN_LITE_NAT_KEEPALIVE_FILTER) |
---|
| 1675 | +#if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT) && defined(DHD_FW_COREDUMP) |
---|
| 1676 | +static int dhd_wait_for_file_dump(dhd_pub_t *dhdp) |
---|
| 1677 | +{ |
---|
| 1678 | + struct net_device *primary_ndev; |
---|
| 1679 | + struct bcm_cfg80211 *cfg; |
---|
| 1680 | + unsigned long flags = 0; |
---|
| 1681 | + primary_ndev = dhd_linux_get_primary_netdev(dhdp); |
---|
| 1682 | + |
---|
| 1683 | + if (!primary_ndev) { |
---|
| 1684 | + DHD_ERROR(("%s: Cannot find primary netdev\n", __FUNCTION__)); |
---|
| 1685 | + return BCME_ERROR; |
---|
| 1686 | + } |
---|
| 1687 | + cfg = wl_get_cfg(primary_ndev); |
---|
| 1688 | + |
---|
| 1689 | + if (!cfg) { |
---|
| 1690 | + DHD_ERROR(("%s: Cannot find cfg\n", __FUNCTION__)); |
---|
| 1691 | + return BCME_ERROR; |
---|
| 1692 | + } |
---|
| 1693 | + |
---|
| 1694 | + DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 1695 | + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp)) { |
---|
| 1696 | + DHD_BUS_BUSY_CLEAR_IN_HALDUMP(dhdp); |
---|
| 1697 | + dhd_os_busbusy_wake(dhdp); |
---|
| 1698 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 1699 | + DHD_ERROR(("%s: bus is down! can't collect log dump. \n", __FUNCTION__)); |
---|
| 1700 | + return BCME_ERROR; |
---|
| 1701 | + } |
---|
| 1702 | + DHD_BUS_BUSY_SET_IN_HALDUMP(dhdp); |
---|
| 1703 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 1704 | + |
---|
| 1705 | + DHD_OS_WAKE_LOCK(dhdp); |
---|
| 1706 | + /* check for hal started and only then send event if not clear dump state here */ |
---|
| 1707 | + if (wl_cfg80211_is_hal_started(cfg)) { |
---|
| 1708 | + int timeleft = 0; |
---|
| 1709 | + |
---|
| 1710 | + DHD_ERROR(("[DUMP] %s: HAL started. send urgent event\n", __FUNCTION__)); |
---|
| 1711 | + dhd_dbg_send_urgent_evt(dhdp, NULL, 0); |
---|
| 1712 | + |
---|
| 1713 | + DHD_ERROR(("%s: wait to clear dhd_bus_busy_state: 0x%x\n", |
---|
| 1714 | + __FUNCTION__, dhdp->dhd_bus_busy_state)); |
---|
| 1715 | + timeleft = dhd_os_busbusy_wait_bitmask(dhdp, |
---|
| 1716 | + &dhdp->dhd_bus_busy_state, DHD_BUS_BUSY_IN_HALDUMP, 0); |
---|
| 1717 | + if ((dhdp->dhd_bus_busy_state & DHD_BUS_BUSY_IN_HALDUMP) != 0) { |
---|
| 1718 | + DHD_ERROR(("%s: Timed out dhd_bus_busy_state=0x%x\n", |
---|
| 1719 | + __FUNCTION__, dhdp->dhd_bus_busy_state)); |
---|
| 1720 | + } |
---|
| 1721 | + } else { |
---|
| 1722 | + DHD_ERROR(("[DUMP] %s: HAL Not started. skip urgent event\n", __FUNCTION__)); |
---|
| 1723 | + } |
---|
| 1724 | + DHD_OS_WAKE_UNLOCK(dhdp); |
---|
| 1725 | + /* In case of dhd_os_busbusy_wait_bitmask() timeout, |
---|
| 1726 | + * hal dump bit will not be cleared. Hence clearing it here. |
---|
| 1727 | + */ |
---|
| 1728 | + DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 1729 | + DHD_BUS_BUSY_CLEAR_IN_HALDUMP(dhdp); |
---|
| 1730 | + dhd_os_busbusy_wake(dhdp); |
---|
| 1731 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 1732 | + |
---|
| 1733 | + return BCME_OK; |
---|
| 1734 | +} |
---|
| 1735 | +#endif /* WL_CFG80211 && DHD_FILE_DUMP_EVENT && DHD_FW_CORE_DUMP */ |
---|
| 1736 | + |
---|
| 1737 | +#ifdef PKT_FILTER_SUPPORT |
---|
| 1738 | +#ifndef GAN_LITE_NAT_KEEPALIVE_FILTER |
---|
2553 | 1739 | static bool |
---|
2554 | | -_turn_on_arp_filter(dhd_pub_t *dhd, int op_mode) |
---|
| 1740 | +_turn_on_arp_filter(dhd_pub_t *dhd, int op_mode_param) |
---|
2555 | 1741 | { |
---|
2556 | 1742 | bool _apply = FALSE; |
---|
2557 | 1743 | /* In case of IBSS mode, apply arp pkt filter */ |
---|
2558 | | - if (op_mode & DHD_FLAG_IBSS_MODE) { |
---|
| 1744 | + if (op_mode_param & DHD_FLAG_IBSS_MODE) { |
---|
2559 | 1745 | _apply = TRUE; |
---|
2560 | 1746 | goto exit; |
---|
2561 | 1747 | } |
---|
2562 | | -#ifndef STBLINUX |
---|
2563 | 1748 | /* In case of P2P GO or GC, apply pkt filter to pass arp pkt to host */ |
---|
2564 | | - if ((dhd->arp_version == 1) && |
---|
2565 | | - (op_mode & (DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE))) { |
---|
| 1749 | + if (op_mode_param & (DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE)) { |
---|
2566 | 1750 | _apply = TRUE; |
---|
2567 | 1751 | goto exit; |
---|
2568 | 1752 | } |
---|
2569 | | -#endif /* STBLINUX */ |
---|
| 1753 | + |
---|
2570 | 1754 | exit: |
---|
2571 | 1755 | return _apply; |
---|
2572 | 1756 | } |
---|
2573 | | -#endif /* PKT_FILTER_SUPPORT && !GAN_LITE_NAT_KEEPALIVE_FILTER */ |
---|
| 1757 | +#endif /* !GAN_LITE_NAT_KEEPALIVE_FILTER */ |
---|
2574 | 1758 | |
---|
2575 | | -void dhd_set_packet_filter(dhd_pub_t *dhd) |
---|
| 1759 | +void |
---|
| 1760 | +dhd_set_packet_filter(dhd_pub_t *dhd) |
---|
2576 | 1761 | { |
---|
2577 | | -#ifdef PKT_FILTER_SUPPORT |
---|
2578 | 1762 | int i; |
---|
2579 | 1763 | |
---|
2580 | 1764 | DHD_TRACE(("%s: enter\n", __FUNCTION__)); |
---|
.. | .. |
---|
2583 | 1767 | dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]); |
---|
2584 | 1768 | } |
---|
2585 | 1769 | } |
---|
2586 | | -#endif /* PKT_FILTER_SUPPORT */ |
---|
2587 | 1770 | } |
---|
2588 | 1771 | |
---|
2589 | | -void dhd_enable_packet_filter(int value, dhd_pub_t *dhd) |
---|
| 1772 | +void |
---|
| 1773 | +dhd_enable_packet_filter(int value, dhd_pub_t *dhd) |
---|
2590 | 1774 | { |
---|
2591 | | -#ifdef PKT_FILTER_SUPPORT |
---|
2592 | 1775 | int i; |
---|
2593 | 1776 | |
---|
2594 | | - DHD_TRACE(("%s: enter, value = %d\n", __FUNCTION__, value)); |
---|
| 1777 | + DHD_ERROR(("%s: enter, value = %d\n", __FUNCTION__, value)); |
---|
| 1778 | + if ((dhd->op_mode & DHD_FLAG_HOSTAP_MODE) && value) { |
---|
| 1779 | + DHD_ERROR(("%s: DHD_FLAG_HOSTAP_MODE\n", __FUNCTION__)); |
---|
| 1780 | + return; |
---|
| 1781 | + } |
---|
2595 | 1782 | /* 1 - Enable packet filter, only allow unicast packet to send up */ |
---|
2596 | 1783 | /* 0 - Disable packet filter */ |
---|
2597 | 1784 | if (dhd_pkt_filter_enable && (!value || |
---|
.. | .. |
---|
2611 | 1798 | value, dhd_master_mode); |
---|
2612 | 1799 | } |
---|
2613 | 1800 | } |
---|
2614 | | -#endif /* PKT_FILTER_SUPPORT */ |
---|
2615 | 1801 | } |
---|
| 1802 | + |
---|
| 1803 | +int |
---|
| 1804 | +dhd_packet_filter_add_remove(dhd_pub_t *dhdp, int add_remove, int num) |
---|
| 1805 | +{ |
---|
| 1806 | + char *filterp = NULL; |
---|
| 1807 | + int filter_id = 0; |
---|
| 1808 | + |
---|
| 1809 | + switch (num) { |
---|
| 1810 | + case DHD_BROADCAST_FILTER_NUM: |
---|
| 1811 | + filterp = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF"; |
---|
| 1812 | + filter_id = 101; |
---|
| 1813 | + break; |
---|
| 1814 | + case DHD_MULTICAST4_FILTER_NUM: |
---|
| 1815 | + filter_id = 102; |
---|
| 1816 | + if (FW_SUPPORTED((dhdp), pf6)) { |
---|
| 1817 | + if (dhdp->pktfilter[num] != NULL) { |
---|
| 1818 | + dhd_pktfilter_offload_delete(dhdp, filter_id); |
---|
| 1819 | + dhdp->pktfilter[num] = NULL; |
---|
| 1820 | + } |
---|
| 1821 | + if (!add_remove) { |
---|
| 1822 | + filterp = DISCARD_IPV4_MCAST; |
---|
| 1823 | + add_remove = 1; |
---|
| 1824 | + break; |
---|
| 1825 | + } |
---|
| 1826 | + } |
---|
| 1827 | + filterp = "102 0 0 0 0xFFFFFF 0x01005E"; |
---|
| 1828 | + break; |
---|
| 1829 | + case DHD_MULTICAST6_FILTER_NUM: |
---|
| 1830 | + filter_id = 103; |
---|
| 1831 | + if (FW_SUPPORTED((dhdp), pf6)) { |
---|
| 1832 | + if (dhdp->pktfilter[num] != NULL) { |
---|
| 1833 | + dhd_pktfilter_offload_delete(dhdp, filter_id); |
---|
| 1834 | + dhdp->pktfilter[num] = NULL; |
---|
| 1835 | + } |
---|
| 1836 | + if (!add_remove) { |
---|
| 1837 | + filterp = DISCARD_IPV6_MCAST; |
---|
| 1838 | + add_remove = 1; |
---|
| 1839 | + break; |
---|
| 1840 | + } |
---|
| 1841 | + } |
---|
| 1842 | + filterp = "103 0 0 0 0xFFFF 0x3333"; |
---|
| 1843 | + break; |
---|
| 1844 | + case DHD_MDNS_FILTER_NUM: |
---|
| 1845 | + filterp = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB"; |
---|
| 1846 | + filter_id = 104; |
---|
| 1847 | + break; |
---|
| 1848 | + case DHD_ARP_FILTER_NUM: |
---|
| 1849 | + filterp = "105 0 0 12 0xFFFF 0x0806"; |
---|
| 1850 | + filter_id = 105; |
---|
| 1851 | + break; |
---|
| 1852 | + case DHD_BROADCAST_ARP_FILTER_NUM: |
---|
| 1853 | + filterp = "106 0 0 0 0xFFFFFFFFFFFF0000000000000806" |
---|
| 1854 | + " 0xFFFFFFFFFFFF0000000000000806"; |
---|
| 1855 | + filter_id = 106; |
---|
| 1856 | + break; |
---|
| 1857 | + default: |
---|
| 1858 | + return -EINVAL; |
---|
| 1859 | + } |
---|
| 1860 | + |
---|
| 1861 | + /* Add filter */ |
---|
| 1862 | + if (add_remove) { |
---|
| 1863 | + dhdp->pktfilter[num] = filterp; |
---|
| 1864 | + dhd_pktfilter_offload_set(dhdp, dhdp->pktfilter[num]); |
---|
| 1865 | + } else { /* Delete filter */ |
---|
| 1866 | + if (dhdp->pktfilter[num]) { |
---|
| 1867 | + dhd_pktfilter_offload_delete(dhdp, filter_id); |
---|
| 1868 | + dhdp->pktfilter[num] = NULL; |
---|
| 1869 | + } |
---|
| 1870 | + } |
---|
| 1871 | + |
---|
| 1872 | + return 0; |
---|
| 1873 | +} |
---|
| 1874 | +#endif /* PKT_FILTER_SUPPORT */ |
---|
2616 | 1875 | |
---|
2617 | 1876 | static int dhd_set_suspend(int value, dhd_pub_t *dhd) |
---|
2618 | 1877 | { |
---|
.. | .. |
---|
2621 | 1880 | #endif /* SUPPORT_PM2_ONLY */ |
---|
2622 | 1881 | /* wl_pkt_filter_enable_t enable_parm; */ |
---|
2623 | 1882 | int bcn_li_dtim = 0; /* Default bcn_li_dtim in resume mode is 0 */ |
---|
| 1883 | + int ret = 0; |
---|
| 1884 | +#ifdef DHD_USE_EARLYSUSPEND |
---|
2624 | 1885 | #ifdef CUSTOM_BCN_TIMEOUT_IN_SUSPEND |
---|
2625 | 1886 | int bcn_timeout = 0; |
---|
2626 | 1887 | #endif /* CUSTOM_BCN_TIMEOUT_IN_SUSPEND */ |
---|
2627 | 1888 | #ifdef CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND |
---|
2628 | | - int roam_time_thresh = 0; /* (ms) */ |
---|
| 1889 | + int roam_time_thresh = 0; /* (ms) */ |
---|
2629 | 1890 | #endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */ |
---|
2630 | 1891 | #ifndef ENABLE_FW_ROAM_SUSPEND |
---|
2631 | 1892 | uint roamvar = 1; |
---|
2632 | 1893 | #endif /* ENABLE_FW_ROAM_SUSPEND */ |
---|
| 1894 | +#ifdef ENABLE_BCN_LI_BCN_WAKEUP |
---|
| 1895 | + int bcn_li_bcn = 1; |
---|
| 1896 | +#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ |
---|
2633 | 1897 | uint nd_ra_filter = 0; |
---|
2634 | | - int ret = 0; |
---|
2635 | | - |
---|
| 1898 | +#ifdef ENABLE_IPMCAST_FILTER |
---|
| 1899 | + int ipmcast_l2filter; |
---|
| 1900 | +#endif /* ENABLE_IPMCAST_FILTER */ |
---|
| 1901 | +#ifdef CUSTOM_EVENT_PM_WAKE |
---|
| 1902 | + uint32 pm_awake_thresh = CUSTOM_EVENT_PM_WAKE; |
---|
| 1903 | +#endif /* CUSTOM_EVENT_PM_WAKE */ |
---|
| 1904 | +#endif /* DHD_USE_EARLYSUSPEND */ |
---|
| 1905 | +#ifdef PASS_ALL_MCAST_PKTS |
---|
| 1906 | + struct dhd_info *dhdinfo; |
---|
| 1907 | + uint32 allmulti; |
---|
| 1908 | + uint i; |
---|
| 1909 | +#endif /* PASS_ALL_MCAST_PKTS */ |
---|
2636 | 1910 | #ifdef DYNAMIC_SWOOB_DURATION |
---|
2637 | 1911 | #ifndef CUSTOM_INTR_WIDTH |
---|
2638 | 1912 | #define CUSTOM_INTR_WIDTH 100 |
---|
2639 | 1913 | int intr_width = 0; |
---|
2640 | 1914 | #endif /* CUSTOM_INTR_WIDTH */ |
---|
2641 | 1915 | #endif /* DYNAMIC_SWOOB_DURATION */ |
---|
| 1916 | + |
---|
| 1917 | +#if defined(OEM_ANDROID) && defined(BCMPCIE) |
---|
| 1918 | + int lpas = 0; |
---|
| 1919 | + int dtim_period = 0; |
---|
| 1920 | + int bcn_interval = 0; |
---|
| 1921 | + int bcn_to_dly = 0; |
---|
| 1922 | +#if defined(CUSTOM_BCN_TIMEOUT_IN_SUSPEND) && defined(DHD_USE_EARLYSUSPEND) |
---|
| 1923 | + bcn_timeout = CUSTOM_BCN_TIMEOUT_SETTING; |
---|
| 1924 | +#else |
---|
| 1925 | + int bcn_timeout = CUSTOM_BCN_TIMEOUT_SETTING; |
---|
| 1926 | +#endif /* CUSTOM_BCN_TIMEOUT_IN_SUSPEND && DHD_USE_EARLYSUSPEND */ |
---|
| 1927 | +#endif /* OEM_ANDROID && BCMPCIE */ |
---|
| 1928 | + |
---|
2642 | 1929 | if (!dhd) |
---|
2643 | 1930 | return -ENODEV; |
---|
2644 | 1931 | |
---|
| 1932 | +#ifdef PASS_ALL_MCAST_PKTS |
---|
| 1933 | + dhdinfo = dhd->info; |
---|
| 1934 | +#endif /* PASS_ALL_MCAST_PKTS */ |
---|
2645 | 1935 | |
---|
2646 | 1936 | DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n", |
---|
2647 | 1937 | __FUNCTION__, value, dhd->in_suspend)); |
---|
.. | .. |
---|
2657 | 1947 | if (value && dhd->in_suspend) { |
---|
2658 | 1948 | #ifdef PKT_FILTER_SUPPORT |
---|
2659 | 1949 | dhd->early_suspended = 1; |
---|
2660 | | -#endif |
---|
| 1950 | +#endif // endif |
---|
2661 | 1951 | /* Kernel suspended */ |
---|
2662 | 1952 | DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__)); |
---|
2663 | 1953 | |
---|
.. | .. |
---|
2666 | 1956 | sizeof(power_mode), TRUE, 0); |
---|
2667 | 1957 | #endif /* SUPPORT_PM2_ONLY */ |
---|
2668 | 1958 | |
---|
2669 | | -#ifdef WL_VIRTUAL_APSTA |
---|
2670 | | - /* Softap shouldn't enable packet filter in STA+SoftAP mode */ |
---|
2671 | | - if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) |
---|
2672 | | -#endif /* WL_VIRTUAL_APSTA */ |
---|
2673 | | - { |
---|
2674 | | - /* Enable packet filter, |
---|
2675 | | - * only allow unicast packet to send up |
---|
2676 | | - */ |
---|
2677 | | - dhd_enable_packet_filter(1, dhd); |
---|
| 1959 | +#ifdef PKT_FILTER_SUPPORT |
---|
| 1960 | + /* Enable packet filter, |
---|
| 1961 | + * only allow unicast packet to send up |
---|
| 1962 | + */ |
---|
| 1963 | + dhd_enable_packet_filter(1, dhd); |
---|
| 1964 | +#ifdef APF |
---|
| 1965 | + dhd_dev_apf_enable_filter(dhd_linux_get_primary_netdev(dhd)); |
---|
| 1966 | +#endif /* APF */ |
---|
| 1967 | +#endif /* PKT_FILTER_SUPPORT */ |
---|
| 1968 | +#ifdef ARP_OFFLOAD_SUPPORT |
---|
| 1969 | + dhd_arp_offload_enable(dhd, TRUE); |
---|
| 1970 | +#endif /* ARP_OFFLOAD_SUPPORT */ |
---|
| 1971 | + |
---|
| 1972 | +#ifdef PASS_ALL_MCAST_PKTS |
---|
| 1973 | + allmulti = 0; |
---|
| 1974 | + for (i = 0; i < DHD_MAX_IFS; i++) { |
---|
| 1975 | + if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net) { |
---|
| 1976 | + ret = dhd_iovar(dhd, i, "allmulti", |
---|
| 1977 | + (char *)&allmulti, |
---|
| 1978 | + sizeof(allmulti), |
---|
| 1979 | + NULL, 0, TRUE); |
---|
| 1980 | + if (ret < 0) { |
---|
| 1981 | + DHD_ERROR(("%s allmulti failed %d\n", |
---|
| 1982 | + __FUNCTION__, ret)); |
---|
| 1983 | + } |
---|
| 1984 | + } |
---|
2678 | 1985 | } |
---|
| 1986 | +#endif /* PASS_ALL_MCAST_PKTS */ |
---|
2679 | 1987 | |
---|
2680 | 1988 | /* If DTIM skip is set up as default, force it to wake |
---|
2681 | 1989 | * each third DTIM for better power savings. Note that |
---|
.. | .. |
---|
2687 | 1995 | bcn_li_dtim = 0; |
---|
2688 | 1996 | } else |
---|
2689 | 1997 | #endif /* WLTDLS */ |
---|
| 1998 | +#if defined(OEM_ANDROID) && defined(BCMPCIE) |
---|
| 1999 | + bcn_li_dtim = dhd_get_suspend_bcn_li_dtim(dhd, &dtim_period, |
---|
| 2000 | + &bcn_interval); |
---|
| 2001 | + ret = dhd_iovar(dhd, 0, "bcn_li_dtim", (char *)&bcn_li_dtim, |
---|
| 2002 | + sizeof(bcn_li_dtim), NULL, 0, TRUE); |
---|
| 2003 | + if (ret < 0) { |
---|
| 2004 | + DHD_ERROR(("%s bcn_li_dtim failed %d\n", |
---|
| 2005 | + __FUNCTION__, ret)); |
---|
| 2006 | + } |
---|
| 2007 | + if ((bcn_li_dtim * dtim_period * bcn_interval) >= |
---|
| 2008 | + MIN_DTIM_FOR_ROAM_THRES_EXTEND) { |
---|
| 2009 | + /* |
---|
| 2010 | + * Increase max roaming threshold from 2 secs to 8 secs |
---|
| 2011 | + * the real roam threshold is MIN(max_roam_threshold, |
---|
| 2012 | + * bcn_timeout/2) |
---|
| 2013 | + */ |
---|
| 2014 | + lpas = 1; |
---|
| 2015 | + ret = dhd_iovar(dhd, 0, "lpas", (char *)&lpas, sizeof(lpas), |
---|
| 2016 | + NULL, 0, TRUE); |
---|
| 2017 | + if (ret < 0) { |
---|
| 2018 | + DHD_ERROR(("%s lpas failed %d\n", __FUNCTION__, |
---|
| 2019 | + ret)); |
---|
| 2020 | + } |
---|
| 2021 | + bcn_to_dly = 1; |
---|
| 2022 | + /* |
---|
| 2023 | + * if bcn_to_dly is 1, the real roam threshold is |
---|
| 2024 | + * MIN(max_roam_threshold, bcn_timeout -1); |
---|
| 2025 | + * notify link down event after roaming procedure complete |
---|
| 2026 | + * if we hit bcn_timeout while we are in roaming progress. |
---|
| 2027 | + */ |
---|
| 2028 | + ret = dhd_iovar(dhd, 0, "bcn_to_dly", (char *)&bcn_to_dly, |
---|
| 2029 | + sizeof(bcn_to_dly), NULL, 0, TRUE); |
---|
| 2030 | + if (ret < 0) { |
---|
| 2031 | + DHD_ERROR(("%s bcn_to_dly failed %d\n", |
---|
| 2032 | + __FUNCTION__, ret)); |
---|
| 2033 | + } |
---|
| 2034 | + /* Increase beacon timeout to 6 secs or use bigger one */ |
---|
| 2035 | + bcn_timeout = max(bcn_timeout, BCN_TIMEOUT_IN_SUSPEND); |
---|
| 2036 | + ret = dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, |
---|
| 2037 | + sizeof(bcn_timeout), NULL, 0, TRUE); |
---|
| 2038 | + if (ret < 0) { |
---|
| 2039 | + DHD_ERROR(("%s bcn_timeout failed %d\n", |
---|
| 2040 | + __FUNCTION__, ret)); |
---|
| 2041 | + } |
---|
| 2042 | + } |
---|
| 2043 | +#else |
---|
2690 | 2044 | bcn_li_dtim = dhd_get_suspend_bcn_li_dtim(dhd); |
---|
2691 | 2045 | if (dhd_iovar(dhd, 0, "bcn_li_dtim", (char *)&bcn_li_dtim, |
---|
2692 | 2046 | sizeof(bcn_li_dtim), NULL, 0, TRUE) < 0) |
---|
2693 | | - DHD_ERROR(("%s: set dtim failed\n", __FUNCTION__)); |
---|
| 2047 | + DHD_ERROR(("%s: set dtim failed\n", __FUNCTION__)); |
---|
| 2048 | +#endif /* OEM_ANDROID && BCMPCIE */ |
---|
| 2049 | +#ifdef WL_CFG80211 |
---|
| 2050 | + /* Disable cfg80211 feature events during suspend */ |
---|
| 2051 | + ret = wl_cfg80211_config_suspend_events( |
---|
| 2052 | + dhd_linux_get_primary_netdev(dhd), FALSE); |
---|
| 2053 | + if (ret < 0) { |
---|
| 2054 | + DHD_ERROR(("failed to disable events (%d)\n", ret)); |
---|
| 2055 | + } |
---|
| 2056 | +#endif /* WL_CFG80211 */ |
---|
| 2057 | +#ifdef DHD_USE_EARLYSUSPEND |
---|
2694 | 2058 | #ifdef CUSTOM_BCN_TIMEOUT_IN_SUSPEND |
---|
2695 | 2059 | bcn_timeout = CUSTOM_BCN_TIMEOUT_IN_SUSPEND; |
---|
2696 | | - dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, |
---|
| 2060 | + ret = dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, |
---|
2697 | 2061 | sizeof(bcn_timeout), NULL, 0, TRUE); |
---|
| 2062 | + if (ret < 0) { |
---|
| 2063 | + DHD_ERROR(("%s bcn_timeout failed %d\n", __FUNCTION__, |
---|
| 2064 | + ret)); |
---|
| 2065 | + } |
---|
2698 | 2066 | #endif /* CUSTOM_BCN_TIMEOUT_IN_SUSPEND */ |
---|
2699 | 2067 | #ifdef CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND |
---|
2700 | 2068 | roam_time_thresh = CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND; |
---|
2701 | | - dhd_iovar(dhd, 0, "roam_time_thresh", (char *)&roam_time_thresh, |
---|
| 2069 | + ret = dhd_iovar(dhd, 0, "roam_time_thresh", |
---|
| 2070 | + (char *)&roam_time_thresh, |
---|
2702 | 2071 | sizeof(roam_time_thresh), NULL, 0, TRUE); |
---|
| 2072 | + if (ret < 0) { |
---|
| 2073 | + DHD_ERROR(("%s roam_time_thresh failed %d\n", |
---|
| 2074 | + __FUNCTION__, ret)); |
---|
| 2075 | + } |
---|
2703 | 2076 | #endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */ |
---|
2704 | 2077 | #ifndef ENABLE_FW_ROAM_SUSPEND |
---|
2705 | 2078 | /* Disable firmware roaming during suspend */ |
---|
2706 | | - dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, sizeof(roamvar), |
---|
2707 | | - NULL, 0, TRUE); |
---|
| 2079 | + ret = dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, |
---|
| 2080 | + sizeof(roamvar), NULL, 0, TRUE); |
---|
| 2081 | + if (ret < 0) { |
---|
| 2082 | + DHD_ERROR(("%s roam_off failed %d\n", |
---|
| 2083 | + __FUNCTION__, ret)); |
---|
| 2084 | + } |
---|
2708 | 2085 | #endif /* ENABLE_FW_ROAM_SUSPEND */ |
---|
| 2086 | +#ifdef ENABLE_BCN_LI_BCN_WAKEUP |
---|
| 2087 | + if (bcn_li_dtim) { |
---|
| 2088 | + bcn_li_bcn = 0; |
---|
| 2089 | + } |
---|
| 2090 | + ret = dhd_iovar(dhd, 0, "bcn_li_bcn", (char *)&bcn_li_bcn, |
---|
| 2091 | + sizeof(bcn_li_bcn), NULL, 0, TRUE); |
---|
| 2092 | + if (ret < 0) { |
---|
| 2093 | + DHD_ERROR(("%s bcn_li_bcn failed %d\n", __FUNCTION__, ret)); |
---|
| 2094 | + } |
---|
| 2095 | +#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ |
---|
| 2096 | +#if defined(WL_CFG80211) && defined(WL_BCNRECV) |
---|
| 2097 | + ret = wl_android_bcnrecv_suspend(dhd_linux_get_primary_netdev(dhd)); |
---|
| 2098 | + if (ret != BCME_OK) { |
---|
| 2099 | + DHD_ERROR(("failed to stop beacon recv event on" |
---|
| 2100 | + " suspend state (%d)\n", ret)); |
---|
| 2101 | + } |
---|
| 2102 | +#endif /* WL_CFG80211 && WL_BCNRECV */ |
---|
| 2103 | +#ifdef NDO_CONFIG_SUPPORT |
---|
| 2104 | + if (dhd->ndo_enable) { |
---|
| 2105 | + if (!dhd->ndo_host_ip_overflow) { |
---|
| 2106 | + /* enable ND offload on suspend */ |
---|
| 2107 | + ret = dhd_ndo_enable(dhd, TRUE); |
---|
| 2108 | + if (ret < 0) { |
---|
| 2109 | + DHD_ERROR(("%s: failed to enable NDO\n", |
---|
| 2110 | + __FUNCTION__)); |
---|
| 2111 | + } |
---|
| 2112 | + } else { |
---|
| 2113 | + DHD_INFO(("%s: NDO disabled on suspend due to" |
---|
| 2114 | + "HW capacity\n", __FUNCTION__)); |
---|
| 2115 | + } |
---|
| 2116 | + } |
---|
| 2117 | +#endif /* NDO_CONFIG_SUPPORT */ |
---|
| 2118 | +#ifndef APF |
---|
2709 | 2119 | if (FW_SUPPORTED(dhd, ndoe)) { |
---|
| 2120 | +#else |
---|
| 2121 | + if (FW_SUPPORTED(dhd, ndoe) && !FW_SUPPORTED(dhd, apf)) { |
---|
| 2122 | +#endif /* APF */ |
---|
2710 | 2123 | /* enable IPv6 RA filter in firmware during suspend */ |
---|
2711 | 2124 | nd_ra_filter = 1; |
---|
2712 | 2125 | ret = dhd_iovar(dhd, 0, "nd_ra_filter_enable", |
---|
.. | .. |
---|
2717 | 2130 | ret)); |
---|
2718 | 2131 | } |
---|
2719 | 2132 | dhd_os_suppress_logging(dhd, TRUE); |
---|
| 2133 | +#ifdef ENABLE_IPMCAST_FILTER |
---|
| 2134 | + ipmcast_l2filter = 1; |
---|
| 2135 | + ret = dhd_iovar(dhd, 0, "ipmcast_l2filter", |
---|
| 2136 | + (char *)&ipmcast_l2filter, sizeof(ipmcast_l2filter), |
---|
| 2137 | + NULL, 0, TRUE); |
---|
| 2138 | + if (ret < 0) { |
---|
| 2139 | + DHD_ERROR(("failed to set ipmcast_l2filter (%d)\n", ret)); |
---|
| 2140 | + } |
---|
| 2141 | +#endif /* ENABLE_IPMCAST_FILTER */ |
---|
2720 | 2142 | #ifdef DYNAMIC_SWOOB_DURATION |
---|
2721 | 2143 | intr_width = CUSTOM_INTR_WIDTH; |
---|
2722 | 2144 | ret = dhd_iovar(dhd, 0, "bus:intr_width", (char *)&intr_width, |
---|
.. | .. |
---|
2725 | 2147 | DHD_ERROR(("failed to set intr_width (%d)\n", ret)); |
---|
2726 | 2148 | } |
---|
2727 | 2149 | #endif /* DYNAMIC_SWOOB_DURATION */ |
---|
| 2150 | +#ifdef CUSTOM_EVENT_PM_WAKE |
---|
| 2151 | + pm_awake_thresh = CUSTOM_EVENT_PM_WAKE * 4; |
---|
| 2152 | + ret = dhd_iovar(dhd, 0, "const_awake_thresh", |
---|
| 2153 | + (char *)&pm_awake_thresh, |
---|
| 2154 | + sizeof(pm_awake_thresh), NULL, 0, TRUE); |
---|
| 2155 | + if (ret < 0) { |
---|
| 2156 | + DHD_ERROR(("%s set const_awake_thresh failed %d\n", |
---|
| 2157 | + __FUNCTION__, ret)); |
---|
| 2158 | + } |
---|
| 2159 | +#endif /* CUSTOM_EVENT_PM_WAKE */ |
---|
| 2160 | +#ifdef CONFIG_SILENT_ROAM |
---|
| 2161 | + if (!dhd->sroamed) { |
---|
| 2162 | + ret = dhd_sroam_set_mon(dhd, TRUE); |
---|
| 2163 | + if (ret < 0) { |
---|
| 2164 | + DHD_ERROR(("%s set sroam failed %d\n", |
---|
| 2165 | + __FUNCTION__, ret)); |
---|
| 2166 | + } |
---|
| 2167 | + } |
---|
| 2168 | + dhd->sroamed = FALSE; |
---|
| 2169 | +#endif /* CONFIG_SILENT_ROAM */ |
---|
| 2170 | +#endif /* DHD_USE_EARLYSUSPEND */ |
---|
2728 | 2171 | } else { |
---|
2729 | 2172 | #ifdef PKT_FILTER_SUPPORT |
---|
2730 | 2173 | dhd->early_suspended = 0; |
---|
2731 | | -#endif |
---|
| 2174 | +#endif // endif |
---|
2732 | 2175 | /* Kernel resumed */ |
---|
2733 | 2176 | DHD_ERROR(("%s: Remove extra suspend setting \n", __FUNCTION__)); |
---|
2734 | 2177 | #ifdef DYNAMIC_SWOOB_DURATION |
---|
.. | .. |
---|
2744 | 2187 | dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, |
---|
2745 | 2188 | sizeof(power_mode), TRUE, 0); |
---|
2746 | 2189 | #endif /* SUPPORT_PM2_ONLY */ |
---|
| 2190 | +#if defined(WL_CFG80211) && defined(WL_BCNRECV) |
---|
| 2191 | + ret = wl_android_bcnrecv_resume(dhd_linux_get_primary_netdev(dhd)); |
---|
| 2192 | + if (ret != BCME_OK) { |
---|
| 2193 | + DHD_ERROR(("failed to resume beacon recv state (%d)\n", |
---|
| 2194 | + ret)); |
---|
| 2195 | + } |
---|
| 2196 | +#endif /* WL_CF80211 && WL_BCNRECV */ |
---|
| 2197 | +#ifdef ARP_OFFLOAD_SUPPORT |
---|
| 2198 | + dhd_arp_offload_enable(dhd, FALSE); |
---|
| 2199 | +#endif /* ARP_OFFLOAD_SUPPORT */ |
---|
2747 | 2200 | #ifdef PKT_FILTER_SUPPORT |
---|
2748 | 2201 | /* disable pkt filter */ |
---|
2749 | 2202 | dhd_enable_packet_filter(0, dhd); |
---|
| 2203 | +#ifdef APF |
---|
| 2204 | + dhd_dev_apf_disable_filter(dhd_linux_get_primary_netdev(dhd)); |
---|
| 2205 | +#endif /* APF */ |
---|
2750 | 2206 | #endif /* PKT_FILTER_SUPPORT */ |
---|
2751 | | - |
---|
2752 | | - /* restore pre-suspend setting for dtim_skip */ |
---|
2753 | | - dhd_iovar(dhd, 0, "bcn_li_dtim", (char *)&bcn_li_dtim, |
---|
| 2207 | +#ifdef PASS_ALL_MCAST_PKTS |
---|
| 2208 | + allmulti = 1; |
---|
| 2209 | + for (i = 0; i < DHD_MAX_IFS; i++) { |
---|
| 2210 | + if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net) |
---|
| 2211 | + ret = dhd_iovar(dhd, i, "allmulti", |
---|
| 2212 | + (char *)&allmulti, |
---|
| 2213 | + sizeof(allmulti), NULL, |
---|
| 2214 | + 0, TRUE); |
---|
| 2215 | + if (ret < 0) { |
---|
| 2216 | + DHD_ERROR(("%s: allmulti failed:%d\n", |
---|
| 2217 | + __FUNCTION__, ret)); |
---|
| 2218 | + } |
---|
| 2219 | + } |
---|
| 2220 | +#endif /* PASS_ALL_MCAST_PKTS */ |
---|
| 2221 | +#if defined(OEM_ANDROID) && defined(BCMPCIE) |
---|
| 2222 | + /* restore pre-suspend setting */ |
---|
| 2223 | + ret = dhd_iovar(dhd, 0, "bcn_li_dtim", (char *)&bcn_li_dtim, |
---|
2754 | 2224 | sizeof(bcn_li_dtim), NULL, 0, TRUE); |
---|
| 2225 | + if (ret < 0) { |
---|
| 2226 | + DHD_ERROR(("%s:bcn_li_ditm failed:%d\n", |
---|
| 2227 | + __FUNCTION__, ret)); |
---|
| 2228 | + } |
---|
| 2229 | + ret = dhd_iovar(dhd, 0, "lpas", (char *)&lpas, sizeof(lpas), NULL, |
---|
| 2230 | + 0, TRUE); |
---|
| 2231 | + if (ret < 0) { |
---|
| 2232 | + DHD_ERROR(("%s:lpas failed:%d\n", __FUNCTION__, ret)); |
---|
| 2233 | + } |
---|
| 2234 | + ret = dhd_iovar(dhd, 0, "bcn_to_dly", (char *)&bcn_to_dly, |
---|
| 2235 | + sizeof(bcn_to_dly), NULL, 0, TRUE); |
---|
| 2236 | + if (ret < 0) { |
---|
| 2237 | + DHD_ERROR(("%s:bcn_to_dly failed:%d\n", __FUNCTION__, ret)); |
---|
| 2238 | + } |
---|
| 2239 | + ret = dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, |
---|
| 2240 | + sizeof(bcn_timeout), NULL, 0, TRUE); |
---|
| 2241 | + if (ret < 0) { |
---|
| 2242 | + DHD_ERROR(("%s:bcn_timeout failed:%d\n", |
---|
| 2243 | + __FUNCTION__, ret)); |
---|
| 2244 | + } |
---|
| 2245 | +#else |
---|
| 2246 | + /* restore pre-suspend setting for dtim_skip */ |
---|
| 2247 | + ret = dhd_iovar(dhd, 0, "bcn_li_dtim", (char *)&bcn_li_dtim, |
---|
| 2248 | + sizeof(bcn_li_dtim), NULL, 0, TRUE); |
---|
| 2249 | + if (ret < 0) { |
---|
| 2250 | + DHD_ERROR(("%s:bcn_li_ditm fail:%d\n", __FUNCTION__, ret)); |
---|
| 2251 | + } |
---|
| 2252 | +#endif /* OEM_ANDROID && BCMPCIE */ |
---|
| 2253 | +#ifdef DHD_USE_EARLYSUSPEND |
---|
2755 | 2254 | #ifdef CUSTOM_BCN_TIMEOUT_IN_SUSPEND |
---|
2756 | 2255 | bcn_timeout = CUSTOM_BCN_TIMEOUT; |
---|
2757 | | - dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, |
---|
| 2256 | + ret = dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, |
---|
2758 | 2257 | sizeof(bcn_timeout), NULL, 0, TRUE); |
---|
| 2258 | + if (ret < 0) { |
---|
| 2259 | + DHD_ERROR(("%s:bcn_timeout failed:%d\n", |
---|
| 2260 | + __FUNCTION__, ret)); |
---|
| 2261 | + } |
---|
2759 | 2262 | #endif /* CUSTOM_BCN_TIMEOUT_IN_SUSPEND */ |
---|
2760 | 2263 | #ifdef CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND |
---|
2761 | 2264 | roam_time_thresh = 2000; |
---|
2762 | | - dhd_iovar(dhd, 0, "roam_time_thresh", (char *)&roam_time_thresh, |
---|
| 2265 | + ret = dhd_iovar(dhd, 0, "roam_time_thresh", |
---|
| 2266 | + (char *)&roam_time_thresh, |
---|
2763 | 2267 | sizeof(roam_time_thresh), NULL, 0, TRUE); |
---|
| 2268 | + if (ret < 0) { |
---|
| 2269 | + DHD_ERROR(("%s:roam_time_thresh failed:%d\n", |
---|
| 2270 | + __FUNCTION__, ret)); |
---|
| 2271 | + } |
---|
| 2272 | + |
---|
2764 | 2273 | #endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */ |
---|
2765 | 2274 | #ifndef ENABLE_FW_ROAM_SUSPEND |
---|
2766 | 2275 | roamvar = dhd_roam_disable; |
---|
2767 | | - dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, sizeof(roamvar), |
---|
2768 | | - NULL, 0, TRUE); |
---|
| 2276 | + ret = dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, |
---|
| 2277 | + sizeof(roamvar), NULL, 0, TRUE); |
---|
| 2278 | + if (ret < 0) { |
---|
| 2279 | + DHD_ERROR(("%s: roam_off fail:%d\n", __FUNCTION__, ret)); |
---|
| 2280 | + } |
---|
2769 | 2281 | #endif /* ENABLE_FW_ROAM_SUSPEND */ |
---|
| 2282 | +#ifdef ENABLE_BCN_LI_BCN_WAKEUP |
---|
| 2283 | + ret = dhd_iovar(dhd, 0, "bcn_li_bcn", (char *)&bcn_li_bcn, |
---|
| 2284 | + sizeof(bcn_li_bcn), NULL, 0, TRUE); |
---|
| 2285 | + if (ret < 0) { |
---|
| 2286 | + DHD_ERROR(("%s: bcn_li_bcn failed:%d\n", |
---|
| 2287 | + __FUNCTION__, ret)); |
---|
| 2288 | + } |
---|
| 2289 | +#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ |
---|
| 2290 | +#ifdef NDO_CONFIG_SUPPORT |
---|
| 2291 | + if (dhd->ndo_enable) { |
---|
| 2292 | + /* Disable ND offload on resume */ |
---|
| 2293 | + ret = dhd_ndo_enable(dhd, FALSE); |
---|
| 2294 | + if (ret < 0) { |
---|
| 2295 | + DHD_ERROR(("%s: failed to disable NDO\n", |
---|
| 2296 | + __FUNCTION__)); |
---|
| 2297 | + } |
---|
| 2298 | + } |
---|
| 2299 | +#endif /* NDO_CONFIG_SUPPORT */ |
---|
| 2300 | +#ifndef APF |
---|
2770 | 2301 | if (FW_SUPPORTED(dhd, ndoe)) { |
---|
| 2302 | +#else |
---|
| 2303 | + if (FW_SUPPORTED(dhd, ndoe) && !FW_SUPPORTED(dhd, apf)) { |
---|
| 2304 | +#endif /* APF */ |
---|
2771 | 2305 | /* disable IPv6 RA filter in firmware during suspend */ |
---|
2772 | 2306 | nd_ra_filter = 0; |
---|
2773 | 2307 | ret = dhd_iovar(dhd, 0, "nd_ra_filter_enable", |
---|
2774 | 2308 | (char *)&nd_ra_filter, sizeof(nd_ra_filter), |
---|
2775 | 2309 | NULL, 0, TRUE); |
---|
2776 | | - if (ret < 0) |
---|
2777 | | - DHD_ERROR(("nd_ra_filter: %d\n", ret)); |
---|
| 2310 | + if (ret < 0) { |
---|
| 2311 | + DHD_ERROR(("failed to set nd_ra_filter (%d)\n", |
---|
| 2312 | + ret)); |
---|
| 2313 | + } |
---|
2778 | 2314 | } |
---|
2779 | 2315 | dhd_os_suppress_logging(dhd, FALSE); |
---|
| 2316 | +#ifdef ENABLE_IPMCAST_FILTER |
---|
| 2317 | + ipmcast_l2filter = 0; |
---|
| 2318 | + ret = dhd_iovar(dhd, 0, "ipmcast_l2filter", |
---|
| 2319 | + (char *)&ipmcast_l2filter, sizeof(ipmcast_l2filter), |
---|
| 2320 | + NULL, 0, TRUE); |
---|
| 2321 | + if (ret < 0) { |
---|
| 2322 | + DHD_ERROR(("failed to clear ipmcast_l2filter ret:%d", ret)); |
---|
| 2323 | + } |
---|
| 2324 | +#endif /* ENABLE_IPMCAST_FILTER */ |
---|
| 2325 | +#ifdef CUSTOM_EVENT_PM_WAKE |
---|
| 2326 | + ret = dhd_iovar(dhd, 0, "const_awake_thresh", |
---|
| 2327 | + (char *)&pm_awake_thresh, |
---|
| 2328 | + sizeof(pm_awake_thresh), NULL, 0, TRUE); |
---|
| 2329 | + if (ret < 0) { |
---|
| 2330 | + DHD_ERROR(("%s set const_awake_thresh failed %d\n", |
---|
| 2331 | + __FUNCTION__, ret)); |
---|
| 2332 | + } |
---|
| 2333 | +#endif /* CUSTOM_EVENT_PM_WAKE */ |
---|
| 2334 | +#ifdef CONFIG_SILENT_ROAM |
---|
| 2335 | + ret = dhd_sroam_set_mon(dhd, FALSE); |
---|
| 2336 | + if (ret < 0) { |
---|
| 2337 | + DHD_ERROR(("%s set sroam failed %d\n", __FUNCTION__, ret)); |
---|
| 2338 | + } |
---|
| 2339 | +#endif /* CONFIG_SILENT_ROAM */ |
---|
| 2340 | +#endif /* DHD_USE_EARLYSUSPEND */ |
---|
| 2341 | +#ifdef WL_CFG80211 |
---|
| 2342 | + /* Enable cfg80211 feature events during resume */ |
---|
| 2343 | + ret = wl_cfg80211_config_suspend_events( |
---|
| 2344 | + dhd_linux_get_primary_netdev(dhd), TRUE); |
---|
| 2345 | + if (ret < 0) { |
---|
| 2346 | + DHD_ERROR(("failed to enable events (%d)\n", ret)); |
---|
| 2347 | + } |
---|
| 2348 | +#endif /* WL_CFG80211 */ |
---|
| 2349 | +#ifdef DHD_LB_IRQSET |
---|
| 2350 | + dhd_irq_set_affinity(dhd, dhd->info->cpumask_primary); |
---|
| 2351 | +#endif /* DHD_LB_IRQSET */ |
---|
2780 | 2352 | } |
---|
2781 | 2353 | } |
---|
2782 | 2354 | dhd_suspend_unlock(dhd); |
---|
.. | .. |
---|
2867 | 2439 | if (tmo->increment > tmo->tick) |
---|
2868 | 2440 | tmo->increment = tmo->tick; |
---|
2869 | 2441 | } else { |
---|
2870 | | - wait_queue_head_t delay_wait; |
---|
2871 | | - DECLARE_WAITQUEUE(wait, current); |
---|
2872 | | - init_waitqueue_head(&delay_wait); |
---|
2873 | | - add_wait_queue(&delay_wait, &wait); |
---|
2874 | | - set_current_state(TASK_INTERRUPTIBLE); |
---|
2875 | | - (void)schedule_timeout(1); |
---|
2876 | | - remove_wait_queue(&delay_wait, &wait); |
---|
2877 | | - set_current_state(TASK_RUNNING); |
---|
| 2442 | + /* |
---|
| 2443 | + * OSL_SLEEP() is corresponding to usleep_range(). In non-atomic |
---|
| 2444 | + * context where the exact wakeup time is flexible, it would be good |
---|
| 2445 | + * to use usleep_range() instead of udelay(). It takes a few advantages |
---|
| 2446 | + * such as improving responsiveness and reducing power. |
---|
| 2447 | + */ |
---|
| 2448 | + OSL_SLEEP(jiffies_to_msecs(1)); |
---|
2878 | 2449 | } |
---|
2879 | 2450 | |
---|
2880 | 2451 | return 0; |
---|
.. | .. |
---|
2968 | 2539 | return NULL; |
---|
2969 | 2540 | } |
---|
2970 | 2541 | |
---|
2971 | | -#ifdef BCMDBUS |
---|
2972 | | -#define DBUS_NRXQ 50 |
---|
2973 | | -#define DBUS_NTXQ 100 |
---|
2974 | | - |
---|
2975 | | -static void |
---|
2976 | | -dhd_dbus_send_complete(void *handle, void *info, int status) |
---|
2977 | | -{ |
---|
2978 | | - dhd_info_t *dhd = (dhd_info_t *)handle; |
---|
2979 | | - void *pkt = info; |
---|
2980 | | - |
---|
2981 | | - if ((dhd == NULL) || (pkt == NULL)) |
---|
2982 | | - return; |
---|
2983 | | - |
---|
2984 | | - if (status == DBUS_OK) { |
---|
2985 | | - dhd->pub.dstats.tx_packets++; |
---|
2986 | | - } else { |
---|
2987 | | - DHD_ERROR(("TX error=%d\n", status)); |
---|
2988 | | - dhd->pub.dstats.tx_errors++; |
---|
2989 | | - } |
---|
2990 | | -#ifdef PROP_TXSTATUS |
---|
2991 | | - if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt)) && |
---|
2992 | | - (dhd_wlfc_txcomplete(&dhd->pub, pkt, status == 0) != WLFC_UNSUPPORTED)) { |
---|
2993 | | - return; |
---|
2994 | | - } |
---|
2995 | | -#endif /* PROP_TXSTATUS */ |
---|
2996 | | - PKTFREE(dhd->pub.osh, pkt, TRUE); |
---|
2997 | | -} |
---|
2998 | | - |
---|
2999 | | -static void |
---|
3000 | | -dhd_dbus_recv_pkt(void *handle, void *pkt) |
---|
3001 | | -{ |
---|
3002 | | - uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN]; |
---|
3003 | | - uint reorder_info_len; |
---|
3004 | | - uint pkt_count; |
---|
3005 | | - dhd_info_t *dhd = (dhd_info_t *)handle; |
---|
3006 | | - int ifidx = 0; |
---|
3007 | | - |
---|
3008 | | - if (dhd == NULL) |
---|
3009 | | - return; |
---|
3010 | | - |
---|
3011 | | - /* If the protocol uses a data header, check and remove it */ |
---|
3012 | | - if (dhd_prot_hdrpull(&dhd->pub, &ifidx, pkt, reorder_info_buf, |
---|
3013 | | - &reorder_info_len) != 0) { |
---|
3014 | | - DHD_ERROR(("rx protocol error\n")); |
---|
3015 | | - PKTFREE(dhd->pub.osh, pkt, FALSE); |
---|
3016 | | - dhd->pub.rx_errors++; |
---|
3017 | | - return; |
---|
3018 | | - } |
---|
3019 | | - |
---|
3020 | | - if (reorder_info_len) { |
---|
3021 | | - /* Reordering info from the firmware */ |
---|
3022 | | - dhd_process_pkt_reorder_info(&dhd->pub, reorder_info_buf, reorder_info_len, |
---|
3023 | | - &pkt, &pkt_count); |
---|
3024 | | - if (pkt_count == 0) |
---|
3025 | | - return; |
---|
3026 | | - } |
---|
3027 | | - else { |
---|
3028 | | - pkt_count = 1; |
---|
3029 | | - } |
---|
3030 | | - dhd_rx_frame(&dhd->pub, ifidx, pkt, pkt_count, 0); |
---|
3031 | | -} |
---|
3032 | | - |
---|
3033 | | -static void |
---|
3034 | | -dhd_dbus_recv_buf(void *handle, uint8 *buf, int len) |
---|
3035 | | -{ |
---|
3036 | | - dhd_info_t *dhd = (dhd_info_t *)handle; |
---|
3037 | | - void *pkt; |
---|
3038 | | - |
---|
3039 | | - if (dhd == NULL) |
---|
3040 | | - return; |
---|
3041 | | - |
---|
3042 | | - if ((pkt = PKTGET(dhd->pub.osh, len, FALSE)) == NULL) { |
---|
3043 | | - DHD_ERROR(("PKTGET (rx) failed=%d\n", len)); |
---|
3044 | | - return; |
---|
3045 | | - } |
---|
3046 | | - |
---|
3047 | | - bcopy(buf, PKTDATA(dhd->pub.osh, pkt), len); |
---|
3048 | | - dhd_dbus_recv_pkt(dhd, pkt); |
---|
3049 | | -} |
---|
3050 | | - |
---|
3051 | | -static void |
---|
3052 | | -dhd_dbus_txflowcontrol(void *handle, bool onoff) |
---|
3053 | | -{ |
---|
3054 | | - dhd_info_t *dhd = (dhd_info_t *)handle; |
---|
3055 | | - bool wlfc_enabled = FALSE; |
---|
3056 | | - |
---|
3057 | | - if (dhd == NULL) |
---|
3058 | | - return; |
---|
3059 | | - |
---|
3060 | | -#ifdef PROP_TXSTATUS |
---|
3061 | | - wlfc_enabled = (dhd_wlfc_flowcontrol(&dhd->pub, onoff, !onoff) != WLFC_UNSUPPORTED); |
---|
3062 | | -#endif |
---|
3063 | | - |
---|
3064 | | - if (!wlfc_enabled) { |
---|
3065 | | - dhd_txflowcontrol(&dhd->pub, ALL_INTERFACES, onoff); |
---|
3066 | | - } |
---|
3067 | | -} |
---|
3068 | | - |
---|
3069 | | -static void |
---|
3070 | | -dhd_dbus_errhandler(void *handle, int err) |
---|
3071 | | -{ |
---|
3072 | | -} |
---|
3073 | | - |
---|
3074 | | -static void |
---|
3075 | | -dhd_dbus_ctl_complete(void *handle, int type, int status) |
---|
3076 | | -{ |
---|
3077 | | - dhd_info_t *dhd = (dhd_info_t *)handle; |
---|
3078 | | - |
---|
3079 | | - if (dhd == NULL) |
---|
3080 | | - return; |
---|
3081 | | - |
---|
3082 | | - if (type == DBUS_CBCTL_READ) { |
---|
3083 | | - if (status == DBUS_OK) |
---|
3084 | | - dhd->pub.rx_ctlpkts++; |
---|
3085 | | - else |
---|
3086 | | - dhd->pub.rx_ctlerrs++; |
---|
3087 | | - } else if (type == DBUS_CBCTL_WRITE) { |
---|
3088 | | - if (status == DBUS_OK) |
---|
3089 | | - dhd->pub.tx_ctlpkts++; |
---|
3090 | | - else |
---|
3091 | | - dhd->pub.tx_ctlerrs++; |
---|
3092 | | - } |
---|
3093 | | - |
---|
3094 | | - dhd_prot_ctl_complete(&dhd->pub); |
---|
3095 | | -} |
---|
3096 | | - |
---|
3097 | | -static void |
---|
3098 | | -dhd_dbus_state_change(void *handle, int state) |
---|
3099 | | -{ |
---|
3100 | | - dhd_info_t *dhd = (dhd_info_t *)handle; |
---|
3101 | | - |
---|
3102 | | - if (dhd == NULL) |
---|
3103 | | - return; |
---|
3104 | | - |
---|
3105 | | - switch (state) { |
---|
3106 | | - |
---|
3107 | | - case DBUS_STATE_DL_NEEDED: |
---|
3108 | | -#if defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) |
---|
3109 | | -#if defined(BCMDBUS) |
---|
3110 | | - DHD_TRACE(("%s: firmware request\n", __FUNCTION__)); |
---|
3111 | | - up(&dhd->fw_download_lock); |
---|
3112 | | -#endif /* BCMDBUS */ |
---|
3113 | | -#else |
---|
3114 | | - DHD_ERROR(("%s: firmware request cannot be handled\n", __FUNCTION__)); |
---|
3115 | | -#endif /* defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) */ |
---|
3116 | | - break; |
---|
3117 | | - case DBUS_STATE_DOWN: |
---|
3118 | | - DHD_TRACE(("%s: DBUS is down\n", __FUNCTION__)); |
---|
3119 | | - dhd->pub.busstate = DHD_BUS_DOWN; |
---|
3120 | | - break; |
---|
3121 | | - case DBUS_STATE_UP: |
---|
3122 | | - DHD_TRACE(("%s: DBUS is up\n", __FUNCTION__)); |
---|
3123 | | - dhd->pub.busstate = DHD_BUS_DATA; |
---|
3124 | | - break; |
---|
3125 | | - default: |
---|
3126 | | - break; |
---|
3127 | | - } |
---|
3128 | | - |
---|
3129 | | - DHD_TRACE(("%s: DBUS current state=%d\n", __FUNCTION__, state)); |
---|
3130 | | -} |
---|
3131 | | - |
---|
3132 | | -static void * |
---|
3133 | | -dhd_dbus_pktget(void *handle, uint len, bool send) |
---|
3134 | | -{ |
---|
3135 | | - dhd_info_t *dhd = (dhd_info_t *)handle; |
---|
3136 | | - void *p = NULL; |
---|
3137 | | - |
---|
3138 | | - if (dhd == NULL) |
---|
3139 | | - return NULL; |
---|
3140 | | - |
---|
3141 | | - if (send == TRUE) { |
---|
3142 | | - dhd_os_sdlock_txq(&dhd->pub); |
---|
3143 | | - p = PKTGET(dhd->pub.osh, len, TRUE); |
---|
3144 | | - dhd_os_sdunlock_txq(&dhd->pub); |
---|
3145 | | - } else { |
---|
3146 | | - dhd_os_sdlock_rxq(&dhd->pub); |
---|
3147 | | - p = PKTGET(dhd->pub.osh, len, FALSE); |
---|
3148 | | - dhd_os_sdunlock_rxq(&dhd->pub); |
---|
3149 | | - } |
---|
3150 | | - |
---|
3151 | | - return p; |
---|
3152 | | -} |
---|
3153 | | - |
---|
3154 | | -static void |
---|
3155 | | -dhd_dbus_pktfree(void *handle, void *p, bool send) |
---|
3156 | | -{ |
---|
3157 | | - dhd_info_t *dhd = (dhd_info_t *)handle; |
---|
3158 | | - |
---|
3159 | | - if (dhd == NULL) |
---|
3160 | | - return; |
---|
3161 | | - |
---|
3162 | | - if (send == TRUE) { |
---|
3163 | | -#ifdef PROP_TXSTATUS |
---|
3164 | | - if (DHD_PKTTAG_WLFCPKT(PKTTAG(p)) && |
---|
3165 | | - (dhd_wlfc_txcomplete(&dhd->pub, p, FALSE) != WLFC_UNSUPPORTED)) { |
---|
3166 | | - return; |
---|
3167 | | - } |
---|
3168 | | -#endif /* PROP_TXSTATUS */ |
---|
3169 | | - |
---|
3170 | | - dhd_os_sdlock_txq(&dhd->pub); |
---|
3171 | | - PKTFREE(dhd->pub.osh, p, TRUE); |
---|
3172 | | - dhd_os_sdunlock_txq(&dhd->pub); |
---|
3173 | | - } else { |
---|
3174 | | - dhd_os_sdlock_rxq(&dhd->pub); |
---|
3175 | | - PKTFREE(dhd->pub.osh, p, FALSE); |
---|
3176 | | - dhd_os_sdunlock_rxq(&dhd->pub); |
---|
3177 | | - } |
---|
3178 | | -} |
---|
3179 | | - |
---|
3180 | | -#ifdef BCM_FD_AGGR |
---|
3181 | | - |
---|
3182 | | -static void |
---|
3183 | | -dbus_rpcth_tx_complete(void *ctx, void *pktbuf, int status) |
---|
3184 | | -{ |
---|
3185 | | - dhd_info_t *dhd = (dhd_info_t *)ctx; |
---|
3186 | | - void *tmp; |
---|
3187 | | - |
---|
3188 | | - while (pktbuf && dhd) { |
---|
3189 | | - tmp = PKTNEXT(dhd->pub.osh, pktbuf); |
---|
3190 | | - PKTSETNEXT(dhd->pub.osh, pktbuf, NULL); |
---|
3191 | | - dhd_dbus_send_complete(ctx, pktbuf, status); |
---|
3192 | | - pktbuf = tmp; |
---|
3193 | | - } |
---|
3194 | | -} |
---|
3195 | | -static void |
---|
3196 | | -dbus_rpcth_rx_pkt(void *context, rpc_buf_t *rpc_buf) |
---|
3197 | | -{ |
---|
3198 | | - dhd_dbus_recv_pkt(context, rpc_buf); |
---|
3199 | | -} |
---|
3200 | | - |
---|
3201 | | -static void |
---|
3202 | | -dbus_rpcth_rx_aggrpkt(void *context, void *rpc_buf) |
---|
3203 | | -{ |
---|
3204 | | - dhd_info_t *dhd = (dhd_info_t *)context; |
---|
3205 | | - |
---|
3206 | | - if (dhd == NULL) |
---|
3207 | | - return; |
---|
3208 | | - |
---|
3209 | | - /* all the de-aggregated packets are delivered back to function dbus_rpcth_rx_pkt() |
---|
3210 | | - * as cloned packets |
---|
3211 | | - */ |
---|
3212 | | - bcm_rpc_dbus_recv_aggrpkt(dhd->rpc_th, rpc_buf, |
---|
3213 | | - bcm_rpc_buf_len_get(dhd->rpc_th, rpc_buf)); |
---|
3214 | | - |
---|
3215 | | - /* free the original packet */ |
---|
3216 | | - dhd_dbus_pktfree(context, rpc_buf, FALSE); |
---|
3217 | | -} |
---|
3218 | | - |
---|
3219 | | -static void |
---|
3220 | | -dbus_rpcth_rx_aggrbuf(void *context, uint8 *buf, int len) |
---|
3221 | | -{ |
---|
3222 | | - dhd_info_t *dhd = (dhd_info_t *)context; |
---|
3223 | | - |
---|
3224 | | - if (dhd == NULL) |
---|
3225 | | - return; |
---|
3226 | | - |
---|
3227 | | - if (dhd->fdaggr & BCM_FDAGGR_D2H_ENABLED) { |
---|
3228 | | - bcm_rpc_dbus_recv_aggrbuf(dhd->rpc_th, buf, len); |
---|
3229 | | - } |
---|
3230 | | - else { |
---|
3231 | | - dhd_dbus_recv_buf(context, buf, len); |
---|
3232 | | - } |
---|
3233 | | - |
---|
3234 | | -} |
---|
3235 | | - |
---|
3236 | | -static void |
---|
3237 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) |
---|
3238 | | -dhd_rpcth_watchdog(struct timer_list *t) |
---|
3239 | | -{ |
---|
3240 | | - dhd_info_t *dhd = from_timer(dhd, t, rpcth_timer); |
---|
3241 | | -#else |
---|
3242 | | -dhd_rpcth_watchdog(ulong data) |
---|
3243 | | -{ |
---|
3244 | | - dhd_info_t *dhd = (dhd_info_t *)data; |
---|
3245 | | -#endif |
---|
3246 | | - |
---|
3247 | | - if (dhd->pub.dongle_reset) { |
---|
3248 | | - return; |
---|
3249 | | - } |
---|
3250 | | - |
---|
3251 | | - dhd->rpcth_timer_active = FALSE; |
---|
3252 | | - /* release packets in the aggregation queue */ |
---|
3253 | | - bcm_rpc_tp_watchdog(dhd->rpc_th); |
---|
3254 | | -} |
---|
3255 | | - |
---|
3256 | | -static int |
---|
3257 | | -dhd_fdaggr_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len) |
---|
3258 | | -{ |
---|
3259 | | - int bcmerror = 0; |
---|
3260 | | - void *rpc_th; |
---|
3261 | | - |
---|
3262 | | - rpc_th = dhd_pub->info->rpc_th; |
---|
3263 | | - |
---|
3264 | | - if (!strcmp("rpc_agg", ioc->buf)) { |
---|
3265 | | - uint32 rpc_agg; |
---|
3266 | | - uint32 rpc_agg_host; |
---|
3267 | | - uint32 rpc_agg_dngl; |
---|
3268 | | - |
---|
3269 | | - if (ioc->set) { |
---|
3270 | | - memcpy(&rpc_agg, ioc->buf + strlen("rpc_agg") + 1, sizeof(uint32)); |
---|
3271 | | - rpc_agg_host = rpc_agg & BCM_RPC_TP_HOST_AGG_MASK; |
---|
3272 | | - if (rpc_agg_host) |
---|
3273 | | - bcm_rpc_tp_agg_set(rpc_th, rpc_agg_host, TRUE); |
---|
3274 | | - else |
---|
3275 | | - bcm_rpc_tp_agg_set(rpc_th, BCM_RPC_TP_HOST_AGG_MASK, FALSE); |
---|
3276 | | - bcmerror = dhd_wl_ioctl(dhd_pub, ifindex, ioc, buf, len); |
---|
3277 | | - if (bcmerror < 0) { |
---|
3278 | | - DHD_ERROR(("usb aggregation not supported\n")); |
---|
3279 | | - } else { |
---|
3280 | | - dhd_pub->info->fdaggr = 0; |
---|
3281 | | - if (rpc_agg & BCM_RPC_TP_HOST_AGG_MASK) |
---|
3282 | | - dhd_pub->info->fdaggr |= BCM_FDAGGR_H2D_ENABLED; |
---|
3283 | | - if (rpc_agg & BCM_RPC_TP_DNGL_AGG_MASK) |
---|
3284 | | - dhd_pub->info->fdaggr |= BCM_FDAGGR_D2H_ENABLED; |
---|
3285 | | - } |
---|
3286 | | - } else { |
---|
3287 | | - rpc_agg_host = bcm_rpc_tp_agg_get(rpc_th); |
---|
3288 | | - bcmerror = dhd_wl_ioctl(dhd_pub, ifindex, ioc, buf, len); |
---|
3289 | | - if (!bcmerror) { |
---|
3290 | | - memcpy(&rpc_agg_dngl, buf, sizeof(uint32)); |
---|
3291 | | - rpc_agg = (rpc_agg_host & BCM_RPC_TP_HOST_AGG_MASK) | |
---|
3292 | | - (rpc_agg_dngl & BCM_RPC_TP_DNGL_AGG_MASK); |
---|
3293 | | - memcpy(buf, &rpc_agg, sizeof(uint32)); |
---|
3294 | | - } |
---|
3295 | | - } |
---|
3296 | | - } else if (!strcmp("rpc_host_agglimit", ioc->buf)) { |
---|
3297 | | - uint8 sf; |
---|
3298 | | - uint16 bytes; |
---|
3299 | | - uint32 agglimit; |
---|
3300 | | - |
---|
3301 | | - if (ioc->set) { |
---|
3302 | | - memcpy(&agglimit, ioc->buf + strlen("rpc_host_agglimit") + 1, |
---|
3303 | | - sizeof(uint32)); |
---|
3304 | | - sf = agglimit >> 16; |
---|
3305 | | - bytes = agglimit & 0xFFFF; |
---|
3306 | | - bcm_rpc_tp_agg_limit_set(rpc_th, sf, bytes); |
---|
3307 | | - } else { |
---|
3308 | | - bcm_rpc_tp_agg_limit_get(rpc_th, &sf, &bytes); |
---|
3309 | | - agglimit = (uint32)((sf << 16) + bytes); |
---|
3310 | | - memcpy(buf, &agglimit, sizeof(uint32)); |
---|
3311 | | - } |
---|
3312 | | - |
---|
3313 | | - } else { |
---|
3314 | | - bcmerror = dhd_wl_ioctl(dhd_pub, ifindex, ioc, buf, len); |
---|
3315 | | - } |
---|
3316 | | - return bcmerror; |
---|
3317 | | -} |
---|
3318 | | -#endif /* BCM_FD_AGGR */ |
---|
3319 | | - |
---|
3320 | | -static dbus_callbacks_t dhd_dbus_cbs = { |
---|
3321 | | -#ifdef BCM_FD_AGGR |
---|
3322 | | - dbus_rpcth_tx_complete, |
---|
3323 | | - dbus_rpcth_rx_aggrbuf, |
---|
3324 | | - dbus_rpcth_rx_aggrpkt, |
---|
3325 | | -#else |
---|
3326 | | - dhd_dbus_send_complete, |
---|
3327 | | - dhd_dbus_recv_buf, |
---|
3328 | | - dhd_dbus_recv_pkt, |
---|
3329 | | -#endif |
---|
3330 | | - dhd_dbus_txflowcontrol, |
---|
3331 | | - dhd_dbus_errhandler, |
---|
3332 | | - dhd_dbus_ctl_complete, |
---|
3333 | | - dhd_dbus_state_change, |
---|
3334 | | - dhd_dbus_pktget, |
---|
3335 | | - dhd_dbus_pktfree |
---|
3336 | | -}; |
---|
3337 | | - |
---|
3338 | | -void |
---|
3339 | | -dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) |
---|
3340 | | -{ |
---|
3341 | | - bcm_bprintf(strbuf, "Bus USB\n"); |
---|
3342 | | -} |
---|
3343 | | - |
---|
3344 | | -void |
---|
3345 | | -dhd_bus_clearcounts(dhd_pub_t *dhdp) |
---|
3346 | | -{ |
---|
3347 | | -} |
---|
3348 | | - |
---|
3349 | | -bool |
---|
3350 | | -dhd_bus_dpc(struct dhd_bus *bus) |
---|
3351 | | -{ |
---|
3352 | | - return FALSE; |
---|
3353 | | -} |
---|
3354 | | - |
---|
3355 | | -int |
---|
3356 | | -dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf) |
---|
3357 | | -{ |
---|
3358 | | - |
---|
3359 | | - if (dhdp->txoff) |
---|
3360 | | - return BCME_EPERM; |
---|
3361 | | -#ifdef BCM_FD_AGGR |
---|
3362 | | - if (((dhd_info_t *)(dhdp->info))->fdaggr & BCM_FDAGGR_H2D_ENABLED) |
---|
3363 | | - |
---|
3364 | | - { |
---|
3365 | | - dhd_info_t *dhd; |
---|
3366 | | - int ret; |
---|
3367 | | - dhd = (dhd_info_t *)(dhdp->info); |
---|
3368 | | - ret = bcm_rpc_tp_buf_send(dhd->rpc_th, pktbuf); |
---|
3369 | | - if (dhd->rpcth_timer_active == FALSE) { |
---|
3370 | | - dhd->rpcth_timer_active = TRUE; |
---|
3371 | | - mod_timer(&dhd->rpcth_timer, jiffies + BCM_RPC_TP_HOST_TMOUT * HZ / 1000); |
---|
3372 | | - } |
---|
3373 | | - return ret; |
---|
3374 | | - } else |
---|
3375 | | -#endif /* BCM_FD_AGGR */ |
---|
3376 | | - return dbus_send_txdata(dhdp->dbus, pktbuf); |
---|
3377 | | -} |
---|
3378 | | - |
---|
3379 | | -#endif /* BCMDBUS */ |
---|
3380 | | - |
---|
3381 | 2542 | static void |
---|
3382 | 2543 | _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) |
---|
3383 | 2544 | { |
---|
3384 | 2545 | struct net_device *dev; |
---|
3385 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) |
---|
3386 | 2546 | struct netdev_hw_addr *ha; |
---|
3387 | | -#else |
---|
3388 | | - struct dev_mc_list *mclist; |
---|
3389 | | -#endif |
---|
3390 | 2547 | uint32 allmulti, cnt; |
---|
3391 | 2548 | |
---|
3392 | 2549 | wl_ioctl_t ioc; |
---|
.. | .. |
---|
3394 | 2551 | uint buflen; |
---|
3395 | 2552 | int ret; |
---|
3396 | 2553 | |
---|
| 2554 | +#ifdef MCAST_LIST_ACCUMULATION |
---|
| 2555 | + int i; |
---|
| 2556 | + uint32 cnt_iface[DHD_MAX_IFS]; |
---|
| 2557 | + cnt = 0; |
---|
| 2558 | + allmulti = 0; |
---|
| 2559 | + |
---|
| 2560 | + for (i = 0; i < DHD_MAX_IFS; i++) { |
---|
| 2561 | + if (dhd->iflist[i]) { |
---|
| 2562 | + dev = dhd->iflist[i]->net; |
---|
| 2563 | + if (!dev) |
---|
| 2564 | + continue; |
---|
| 2565 | + netif_addr_lock_bh(dev); |
---|
| 2566 | + cnt_iface[i] = netdev_mc_count(dev); |
---|
| 2567 | + cnt += cnt_iface[i]; |
---|
| 2568 | + netif_addr_unlock_bh(dev); |
---|
| 2569 | + |
---|
| 2570 | + /* Determine initial value of allmulti flag */ |
---|
| 2571 | + allmulti |= (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE; |
---|
| 2572 | + } |
---|
| 2573 | + } |
---|
| 2574 | +#else /* !MCAST_LIST_ACCUMULATION */ |
---|
3397 | 2575 | if (!dhd->iflist[ifidx]) { |
---|
3398 | 2576 | DHD_ERROR(("%s : dhd->iflist[%d] was NULL\n", __FUNCTION__, ifidx)); |
---|
3399 | 2577 | return; |
---|
.. | .. |
---|
3401 | 2579 | dev = dhd->iflist[ifidx]->net; |
---|
3402 | 2580 | if (!dev) |
---|
3403 | 2581 | return; |
---|
3404 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) |
---|
3405 | 2582 | netif_addr_lock_bh(dev); |
---|
3406 | | -#endif /* LINUX >= 2.6.27 */ |
---|
3407 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) |
---|
3408 | 2583 | cnt = netdev_mc_count(dev); |
---|
3409 | | -#else |
---|
3410 | | - cnt = dev->mc_count; |
---|
3411 | | -#endif /* LINUX >= 2.6.35 */ |
---|
3412 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) |
---|
3413 | 2584 | netif_addr_unlock_bh(dev); |
---|
3414 | | -#endif /* LINUX >= 2.6.27 */ |
---|
3415 | 2585 | |
---|
3416 | 2586 | /* Determine initial value of allmulti flag */ |
---|
3417 | 2587 | allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE; |
---|
| 2588 | +#endif /* MCAST_LIST_ACCUMULATION */ |
---|
3418 | 2589 | |
---|
| 2590 | +#ifdef PASS_ALL_MCAST_PKTS |
---|
| 2591 | +#ifdef PKT_FILTER_SUPPORT |
---|
| 2592 | + if (!dhd->pub.early_suspended) |
---|
| 2593 | +#endif /* PKT_FILTER_SUPPORT */ |
---|
| 2594 | + allmulti = TRUE; |
---|
| 2595 | +#endif /* PASS_ALL_MCAST_PKTS */ |
---|
3419 | 2596 | |
---|
3420 | 2597 | /* Send down the multicast list first. */ |
---|
3421 | | - |
---|
3422 | 2598 | |
---|
3423 | 2599 | buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETHER_ADDR_LEN); |
---|
3424 | 2600 | if (!(bufp = buf = MALLOC(dhd->pub.osh, buflen))) { |
---|
.. | .. |
---|
3435 | 2611 | memcpy(bufp, &cnt, sizeof(cnt)); |
---|
3436 | 2612 | bufp += sizeof(cnt); |
---|
3437 | 2613 | |
---|
3438 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) |
---|
| 2614 | +#ifdef MCAST_LIST_ACCUMULATION |
---|
| 2615 | + for (i = 0; i < DHD_MAX_IFS; i++) { |
---|
| 2616 | + if (dhd->iflist[i]) { |
---|
| 2617 | + DHD_TRACE(("_dhd_set_multicast_list: ifidx %d\n", i)); |
---|
| 2618 | + dev = dhd->iflist[i]->net; |
---|
| 2619 | + |
---|
| 2620 | + netif_addr_lock_bh(dev); |
---|
| 2621 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 2622 | +#pragma GCC diagnostic push |
---|
| 2623 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 2624 | +#endif // endif |
---|
| 2625 | + netdev_for_each_mc_addr(ha, dev) { |
---|
| 2626 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 2627 | +#pragma GCC diagnostic pop |
---|
| 2628 | +#endif // endif |
---|
| 2629 | + if (!cnt_iface[i]) |
---|
| 2630 | + break; |
---|
| 2631 | + memcpy(bufp, ha->addr, ETHER_ADDR_LEN); |
---|
| 2632 | + bufp += ETHER_ADDR_LEN; |
---|
| 2633 | + DHD_TRACE(("_dhd_set_multicast_list: cnt " |
---|
| 2634 | + "%d " MACDBG "\n", |
---|
| 2635 | + cnt_iface[i], MAC2STRDBG(ha->addr))); |
---|
| 2636 | + cnt_iface[i]--; |
---|
| 2637 | + } |
---|
| 2638 | + netif_addr_unlock_bh(dev); |
---|
| 2639 | + } |
---|
| 2640 | + } |
---|
| 2641 | +#else /* !MCAST_LIST_ACCUMULATION */ |
---|
3439 | 2642 | netif_addr_lock_bh(dev); |
---|
3440 | | -#endif /* LINUX >= 2.6.27 */ |
---|
3441 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) |
---|
| 2643 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 2644 | +#pragma GCC diagnostic push |
---|
| 2645 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 2646 | +#endif // endif |
---|
3442 | 2647 | netdev_for_each_mc_addr(ha, dev) { |
---|
3443 | 2648 | if (!cnt) |
---|
3444 | 2649 | break; |
---|
.. | .. |
---|
3446 | 2651 | bufp += ETHER_ADDR_LEN; |
---|
3447 | 2652 | cnt--; |
---|
3448 | 2653 | } |
---|
3449 | | -#else /* LINUX < 2.6.35 */ |
---|
3450 | | - for (mclist = dev->mc_list; (mclist && (cnt > 0)); |
---|
3451 | | - cnt--, mclist = mclist->next) { |
---|
3452 | | - memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN); |
---|
3453 | | - bufp += ETHER_ADDR_LEN; |
---|
3454 | | - } |
---|
3455 | | -#endif /* LINUX >= 2.6.35 */ |
---|
3456 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) |
---|
| 2654 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 2655 | +#pragma GCC diagnostic pop |
---|
| 2656 | +#endif // endif |
---|
3457 | 2657 | netif_addr_unlock_bh(dev); |
---|
3458 | | -#endif /* LINUX >= 2.6.27 */ |
---|
| 2658 | +#endif /* MCAST_LIST_ACCUMULATION */ |
---|
3459 | 2659 | |
---|
3460 | 2660 | memset(&ioc, 0, sizeof(ioc)); |
---|
3461 | 2661 | ioc.cmd = WLC_SET_VAR; |
---|
.. | .. |
---|
3487 | 2687 | |
---|
3488 | 2688 | /* Finally, pick up the PROMISC flag as well, like the NIC driver does */ |
---|
3489 | 2689 | |
---|
| 2690 | +#ifdef MCAST_LIST_ACCUMULATION |
---|
| 2691 | + allmulti = 0; |
---|
| 2692 | + for (i = 0; i < DHD_MAX_IFS; i++) { |
---|
| 2693 | + if (dhd->iflist[i]) { |
---|
| 2694 | + dev = dhd->iflist[i]->net; |
---|
| 2695 | + allmulti |= (dev->flags & IFF_PROMISC) ? TRUE : FALSE; |
---|
| 2696 | + } |
---|
| 2697 | + } |
---|
| 2698 | +#else |
---|
3490 | 2699 | allmulti = (dev->flags & IFF_PROMISC) ? TRUE : FALSE; |
---|
| 2700 | +#endif /* MCAST_LIST_ACCUMULATION */ |
---|
3491 | 2701 | |
---|
3492 | 2702 | allmulti = htol32(allmulti); |
---|
3493 | 2703 | |
---|
.. | .. |
---|
3525 | 2735 | #ifdef SOFTAP |
---|
3526 | 2736 | extern struct net_device *ap_net_dev; |
---|
3527 | 2737 | extern tsk_ctl_t ap_eth_ctl; /* ap netdev heper thread ctl */ |
---|
3528 | | -#endif |
---|
3529 | | - |
---|
3530 | | -#ifdef DHD_WMF |
---|
3531 | | -void dhd_update_psta_interface_for_sta(dhd_pub_t* dhdp, char* ifname, void* ea, |
---|
3532 | | - void* event_data) |
---|
3533 | | -{ |
---|
3534 | | - struct wl_psta_primary_intf_event *psta_prim_event = |
---|
3535 | | - (struct wl_psta_primary_intf_event*)event_data; |
---|
3536 | | - dhd_sta_t *psta_interface = NULL; |
---|
3537 | | - dhd_sta_t *sta = NULL; |
---|
3538 | | - uint8 ifindex; |
---|
3539 | | - ASSERT(ifname); |
---|
3540 | | - ASSERT(psta_prim_event); |
---|
3541 | | - ASSERT(ea); |
---|
3542 | | - |
---|
3543 | | - ifindex = (uint8)dhd_ifname2idx(dhdp->info, ifname); |
---|
3544 | | - sta = dhd_find_sta(dhdp, ifindex, ea); |
---|
3545 | | - if (sta != NULL) { |
---|
3546 | | - psta_interface = dhd_find_sta(dhdp, ifindex, |
---|
3547 | | - (void *)(psta_prim_event->prim_ea.octet)); |
---|
3548 | | - if (psta_interface != NULL) { |
---|
3549 | | - sta->psta_prim = psta_interface; |
---|
3550 | | - } |
---|
3551 | | - } |
---|
3552 | | -} |
---|
3553 | | - |
---|
3554 | | -/* Get wmf_psta_disable configuration configuration */ |
---|
3555 | | -int dhd_get_wmf_psta_disable(dhd_pub_t *dhdp, uint32 idx) |
---|
3556 | | -{ |
---|
3557 | | - dhd_info_t *dhd = dhdp->info; |
---|
3558 | | - dhd_if_t *ifp; |
---|
3559 | | - ASSERT(idx < DHD_MAX_IFS); |
---|
3560 | | - ifp = dhd->iflist[idx]; |
---|
3561 | | - return ifp->wmf_psta_disable; |
---|
3562 | | -} |
---|
3563 | | - |
---|
3564 | | -/* Set wmf_psta_disable configuration configuration */ |
---|
3565 | | -int dhd_set_wmf_psta_disable(dhd_pub_t *dhdp, uint32 idx, int val) |
---|
3566 | | -{ |
---|
3567 | | - dhd_info_t *dhd = dhdp->info; |
---|
3568 | | - dhd_if_t *ifp; |
---|
3569 | | - ASSERT(idx < DHD_MAX_IFS); |
---|
3570 | | - ifp = dhd->iflist[idx]; |
---|
3571 | | - ifp->wmf_psta_disable = val; |
---|
3572 | | - return 0; |
---|
3573 | | -} |
---|
3574 | | -#endif /* DHD_WMF */ |
---|
| 2738 | +#endif // endif |
---|
3575 | 2739 | |
---|
3576 | 2740 | #ifdef DHD_PSTA |
---|
3577 | 2741 | /* Get psta/psr configuration configuration */ |
---|
.. | .. |
---|
3603 | 2767 | if ( |
---|
3604 | 2768 | #ifdef DHD_L2_FILTER |
---|
3605 | 2769 | (ifp->block_ping) || |
---|
3606 | | -#endif |
---|
| 2770 | +#endif // endif |
---|
3607 | 2771 | #ifdef DHD_WET |
---|
3608 | 2772 | (dhd->wet_mode) || |
---|
3609 | | -#endif |
---|
| 2773 | +#endif // endif |
---|
3610 | 2774 | #ifdef DHD_MCAST_REGEN |
---|
3611 | 2775 | (ifp->mcast_regen_bss_enable) || |
---|
3612 | | -#endif |
---|
| 2776 | +#endif // endif |
---|
3613 | 2777 | FALSE) { |
---|
3614 | 2778 | ifp->rx_pkt_chainable = FALSE; |
---|
3615 | 2779 | } |
---|
.. | .. |
---|
3629 | 2793 | { |
---|
3630 | 2794 | dhd_info_t *dhd = dhdp->info; |
---|
3631 | 2795 | dhd->wet_mode = val; |
---|
3632 | | - |
---|
3633 | | - /* disable rx_pkt_chainable stae for dhd interface, if WET is enabled */ |
---|
3634 | 2796 | dhd_update_rx_pkt_chainable_state(dhdp, 0); |
---|
3635 | 2797 | return 0; |
---|
3636 | 2798 | } |
---|
3637 | 2799 | #endif /* DHD_WET */ |
---|
3638 | 2800 | |
---|
3639 | | -#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 11, 0)) |
---|
| 2801 | +#if defined(WL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) |
---|
3640 | 2802 | int32 dhd_role_to_nl80211_iftype(int32 role) |
---|
3641 | 2803 | { |
---|
3642 | 2804 | switch (role) { |
---|
.. | .. |
---|
3651 | 2813 | case WLC_E_IF_ROLE_P2P_CLIENT: |
---|
3652 | 2814 | return NL80211_IFTYPE_P2P_CLIENT; |
---|
3653 | 2815 | case WLC_E_IF_ROLE_IBSS: |
---|
| 2816 | + case WLC_E_IF_ROLE_NAN: |
---|
3654 | 2817 | return NL80211_IFTYPE_ADHOC; |
---|
3655 | 2818 | default: |
---|
3656 | 2819 | return NL80211_IFTYPE_UNSPECIFIED; |
---|
3657 | 2820 | } |
---|
3658 | 2821 | } |
---|
3659 | | -#endif /* OEM_ANDROID && (LINUX_VERSION_CODE > KERNEL_VERSION(3, 11, 0)) */ |
---|
| 2822 | +#endif /* WL_CFG80211 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ |
---|
3660 | 2823 | |
---|
3661 | 2824 | static void |
---|
3662 | 2825 | dhd_ifadd_event_handler(void *handle, void *event_info, u8 event) |
---|
3663 | 2826 | { |
---|
3664 | 2827 | dhd_info_t *dhd = handle; |
---|
3665 | 2828 | dhd_if_event_t *if_event = event_info; |
---|
3666 | | - struct net_device *ndev; |
---|
3667 | 2829 | int ifidx, bssidx; |
---|
3668 | 2830 | int ret; |
---|
3669 | | -#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 11, 0)) |
---|
3670 | | - struct wireless_dev *vwdev, *primary_wdev; |
---|
3671 | | - struct net_device *primary_ndev; |
---|
3672 | | -#endif /* OEM_ANDROID && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) */ |
---|
| 2831 | +#if defined(WL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) |
---|
| 2832 | + struct wl_if_event_info info; |
---|
| 2833 | +#else |
---|
| 2834 | + struct net_device *ndev; |
---|
| 2835 | +#endif /* WL_CFG80211 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ |
---|
3673 | 2836 | |
---|
| 2837 | + BCM_REFERENCE(ret); |
---|
3674 | 2838 | if (event != DHD_WQ_WORK_IF_ADD) { |
---|
3675 | 2839 | DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); |
---|
3676 | 2840 | return; |
---|
.. | .. |
---|
3694 | 2858 | bssidx = if_event->event.bssidx; |
---|
3695 | 2859 | DHD_TRACE(("%s: registering if with ifidx %d\n", __FUNCTION__, ifidx)); |
---|
3696 | 2860 | |
---|
| 2861 | +#if defined(WL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) |
---|
| 2862 | + if (if_event->event.ifidx > 0) { |
---|
| 2863 | + u8 *mac_addr; |
---|
| 2864 | + bzero(&info, sizeof(info)); |
---|
| 2865 | + info.ifidx = ifidx; |
---|
| 2866 | + info.bssidx = bssidx; |
---|
| 2867 | + info.role = if_event->event.role; |
---|
| 2868 | + strncpy(info.name, if_event->name, IFNAMSIZ); |
---|
| 2869 | + if (is_valid_ether_addr(if_event->mac)) { |
---|
| 2870 | + mac_addr = if_event->mac; |
---|
| 2871 | + } else { |
---|
| 2872 | + mac_addr = NULL; |
---|
| 2873 | + } |
---|
| 2874 | + |
---|
| 2875 | + if (wl_cfg80211_post_ifcreate(dhd->pub.info->iflist[0]->net, |
---|
| 2876 | + &info, mac_addr, NULL, true) == NULL) { |
---|
| 2877 | + /* Do the post interface create ops */ |
---|
| 2878 | + DHD_ERROR(("Post ifcreate ops failed. Returning \n")); |
---|
| 2879 | + goto done; |
---|
| 2880 | + } |
---|
| 2881 | + } |
---|
| 2882 | +#else |
---|
3697 | 2883 | /* This path is for non-android case */ |
---|
3698 | 2884 | /* The interface name in host and in event msg are same */ |
---|
3699 | 2885 | /* if name in event msg is used to create dongle if list on host */ |
---|
.. | .. |
---|
3704 | 2890 | goto done; |
---|
3705 | 2891 | } |
---|
3706 | 2892 | |
---|
3707 | | -#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 11, 0)) |
---|
3708 | | - vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL); |
---|
3709 | | - if (unlikely(!vwdev)) { |
---|
3710 | | - DHD_ERROR(("Could not allocate wireless device\n")); |
---|
3711 | | - goto done; |
---|
3712 | | - } |
---|
3713 | | - primary_ndev = dhd->pub.info->iflist[0]->net; |
---|
3714 | | - primary_wdev = ndev_to_wdev(primary_ndev); |
---|
3715 | | - vwdev->wiphy = primary_wdev->wiphy; |
---|
3716 | | - vwdev->iftype = dhd_role_to_nl80211_iftype(if_event->event.role); |
---|
3717 | | - vwdev->netdev = ndev; |
---|
3718 | | - ndev->ieee80211_ptr = vwdev; |
---|
3719 | | - SET_NETDEV_DEV(ndev, wiphy_dev(vwdev->wiphy)); |
---|
3720 | | - DHD_ERROR(("virtual interface(%s) is created\n", if_event->name)); |
---|
3721 | | -#endif /* OEM_ANDROID && (LINUX_VERSION_CODE > KERNEL_VERSION(3, 11, 0)) */ |
---|
3722 | | - |
---|
3723 | 2893 | DHD_PERIM_UNLOCK(&dhd->pub); |
---|
3724 | 2894 | ret = dhd_register_if(&dhd->pub, ifidx, TRUE); |
---|
3725 | 2895 | DHD_PERIM_LOCK(&dhd->pub); |
---|
.. | .. |
---|
3728 | 2898 | dhd_remove_if(&dhd->pub, ifidx, TRUE); |
---|
3729 | 2899 | goto done; |
---|
3730 | 2900 | } |
---|
| 2901 | +#endif /* WL_CFG80211 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ |
---|
| 2902 | + |
---|
3731 | 2903 | #ifndef PCIE_FULL_DONGLE |
---|
3732 | 2904 | /* Turn on AP isolation in the firmware for interfaces operating in AP mode */ |
---|
3733 | 2905 | if (FW_SUPPORTED((&dhd->pub), ap) && (if_event->event.role != WLC_E_IF_ROLE_STA)) { |
---|
.. | .. |
---|
3756 | 2928 | int ifidx; |
---|
3757 | 2929 | dhd_if_event_t *if_event = event_info; |
---|
3758 | 2930 | |
---|
3759 | | - |
---|
3760 | 2931 | if (event != DHD_WQ_WORK_IF_DEL) { |
---|
3761 | 2932 | DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); |
---|
3762 | 2933 | return; |
---|
.. | .. |
---|
3780 | 2951 | DHD_TRACE(("Removing interface with idx %d\n", ifidx)); |
---|
3781 | 2952 | |
---|
3782 | 2953 | DHD_PERIM_UNLOCK(&dhd->pub); |
---|
| 2954 | + if (!dhd->pub.info->iflist[ifidx]) { |
---|
| 2955 | + /* No matching netdev found */ |
---|
| 2956 | + DHD_ERROR(("Netdev not found! Do nothing.\n")); |
---|
| 2957 | + goto done; |
---|
| 2958 | + } |
---|
| 2959 | +#if defined(WL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) |
---|
| 2960 | + if (if_event->event.ifidx > 0) { |
---|
| 2961 | + /* Do the post interface del ops */ |
---|
| 2962 | + if (wl_cfg80211_post_ifdel(dhd->pub.info->iflist[ifidx]->net, |
---|
| 2963 | + true, if_event->event.ifidx) != 0) { |
---|
| 2964 | + DHD_TRACE(("Post ifdel ops failed. Returning \n")); |
---|
| 2965 | + goto done; |
---|
| 2966 | + } |
---|
| 2967 | + } |
---|
| 2968 | +#else |
---|
| 2969 | + /* For non-cfg80211 drivers */ |
---|
3783 | 2970 | dhd_remove_if(&dhd->pub, ifidx, TRUE); |
---|
| 2971 | +#endif /* WL_CFG80211 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ |
---|
| 2972 | + |
---|
| 2973 | +done: |
---|
3784 | 2974 | DHD_PERIM_LOCK(&dhd->pub); |
---|
3785 | | - |
---|
3786 | 2975 | MFREE(dhd->pub.osh, if_event, sizeof(dhd_if_event_t)); |
---|
3787 | | - |
---|
3788 | 2976 | DHD_PERIM_UNLOCK(&dhd->pub); |
---|
3789 | 2977 | DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
3790 | 2978 | dhd_net_if_unlock_local(dhd); |
---|
3791 | 2979 | } |
---|
3792 | 2980 | |
---|
| 2981 | +#ifndef DHD_DIRECT_SET_MAC |
---|
3793 | 2982 | static void |
---|
3794 | 2983 | dhd_set_mac_addr_handler(void *handle, void *event_info, u8 event) |
---|
3795 | 2984 | { |
---|
.. | .. |
---|
3842 | 3031 | DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
3843 | 3032 | dhd_net_if_unlock_local(dhd); |
---|
3844 | 3033 | } |
---|
| 3034 | +#endif /* DHD_DIRECT_SET_MAC */ |
---|
3845 | 3035 | |
---|
3846 | 3036 | static void |
---|
3847 | 3037 | dhd_set_mcast_list_handler(void *handle, void *event_info, u8 event) |
---|
3848 | 3038 | { |
---|
3849 | 3039 | dhd_info_t *dhd = handle; |
---|
3850 | | - dhd_if_t *ifp = event_info; |
---|
3851 | | - int ifidx; |
---|
| 3040 | + int ifidx = (int)((long int)event_info); |
---|
| 3041 | + dhd_if_t *ifp = NULL; |
---|
3852 | 3042 | |
---|
3853 | 3043 | if (event != DHD_WQ_WORK_SET_MCAST_LIST) { |
---|
3854 | 3044 | DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); |
---|
.. | .. |
---|
3863 | 3053 | dhd_net_if_lock_local(dhd); |
---|
3864 | 3054 | DHD_OS_WAKE_LOCK(&dhd->pub); |
---|
3865 | 3055 | DHD_PERIM_LOCK(&dhd->pub); |
---|
| 3056 | + |
---|
| 3057 | + ifp = dhd->iflist[ifidx]; |
---|
| 3058 | + |
---|
| 3059 | + if (ifp == NULL || !dhd->pub.up) { |
---|
| 3060 | + DHD_ERROR(("%s: interface info not available/down \n", __FUNCTION__)); |
---|
| 3061 | + goto done; |
---|
| 3062 | + } |
---|
3866 | 3063 | |
---|
3867 | 3064 | #ifdef SOFTAP |
---|
3868 | 3065 | { |
---|
.. | .. |
---|
3881 | 3078 | } |
---|
3882 | 3079 | #endif /* SOFTAP */ |
---|
3883 | 3080 | |
---|
3884 | | - if (ifp == NULL || !dhd->pub.up) { |
---|
3885 | | - DHD_ERROR(("%s: interface info not available/down \n", __FUNCTION__)); |
---|
3886 | | - goto done; |
---|
3887 | | - } |
---|
3888 | | - |
---|
3889 | 3081 | ifidx = ifp->idx; |
---|
3890 | 3082 | |
---|
| 3083 | +#ifdef MCAST_LIST_ACCUMULATION |
---|
| 3084 | + ifidx = 0; |
---|
| 3085 | +#endif /* MCAST_LIST_ACCUMULATION */ |
---|
3891 | 3086 | |
---|
3892 | 3087 | _dhd_set_multicast_list(dhd, ifidx); |
---|
3893 | 3088 | DHD_INFO(("%s: set multicast list for if %d\n", __FUNCTION__, ifidx)); |
---|
.. | .. |
---|
3918 | 3113 | memcpy(dhdif->mac_addr, sa->sa_data, ETHER_ADDR_LEN); |
---|
3919 | 3114 | dhdif->set_macaddress = TRUE; |
---|
3920 | 3115 | dhd_net_if_unlock_local(dhd); |
---|
| 3116 | +#ifdef DHD_DIRECT_SET_MAC |
---|
| 3117 | + /* It needs to update new mac address on this context */ |
---|
| 3118 | + ret = _dhd_set_mac_address(dhd, ifidx, dhdif->mac_addr); |
---|
| 3119 | + dhdif->set_macaddress = FALSE; |
---|
| 3120 | +#else |
---|
3921 | 3121 | dhd_deferred_schedule_work(dhd->dhd_deferred_wq, (void *)dhdif, DHD_WQ_WORK_SET_MAC, |
---|
3922 | | - dhd_set_mac_addr_handler, DHD_WORK_PRIORITY_LOW); |
---|
| 3122 | + dhd_set_mac_addr_handler, DHD_WQ_WORK_PRIORITY_LOW); |
---|
| 3123 | +#endif // endif |
---|
3923 | 3124 | return ret; |
---|
3924 | 3125 | } |
---|
3925 | 3126 | |
---|
.. | .. |
---|
3934 | 3135 | return; |
---|
3935 | 3136 | |
---|
3936 | 3137 | dhd->iflist[ifidx]->set_multicast = TRUE; |
---|
3937 | | - dhd_deferred_schedule_work(dhd->dhd_deferred_wq, (void *)dhd->iflist[ifidx], |
---|
3938 | | - DHD_WQ_WORK_SET_MCAST_LIST, dhd_set_mcast_list_handler, DHD_WORK_PRIORITY_LOW); |
---|
| 3138 | + dhd_deferred_schedule_work(dhd->dhd_deferred_wq, (void *)((long int)ifidx), |
---|
| 3139 | + DHD_WQ_WORK_SET_MCAST_LIST, dhd_set_mcast_list_handler, DHD_WQ_WORK_PRIORITY_LOW); |
---|
3939 | 3140 | } |
---|
| 3141 | + |
---|
| 3142 | +#ifdef DHD_UCODE_DOWNLOAD |
---|
| 3143 | +/* Get ucode path */ |
---|
| 3144 | +char * |
---|
| 3145 | +dhd_get_ucode_path(dhd_pub_t *dhdp) |
---|
| 3146 | +{ |
---|
| 3147 | + dhd_info_t *dhd = dhdp->info; |
---|
| 3148 | + return dhd->uc_path; |
---|
| 3149 | +} |
---|
| 3150 | +#endif /* DHD_UCODE_DOWNLOAD */ |
---|
3940 | 3151 | |
---|
3941 | 3152 | #ifdef PROP_TXSTATUS |
---|
3942 | 3153 | int |
---|
.. | .. |
---|
3944 | 3155 | { |
---|
3945 | 3156 | dhd_info_t *di = (dhd_info_t *)(pub->info); |
---|
3946 | 3157 | ASSERT(di != NULL); |
---|
3947 | | -#ifdef BCMDBUS |
---|
3948 | | - spin_lock_irqsave(&di->wlfc_spinlock, di->wlfc_lock_flags); |
---|
3949 | | -#else |
---|
3950 | 3158 | spin_lock_bh(&di->wlfc_spinlock); |
---|
3951 | | -#endif |
---|
3952 | 3159 | return 1; |
---|
3953 | 3160 | } |
---|
3954 | 3161 | |
---|
.. | .. |
---|
3958 | 3165 | dhd_info_t *di = (dhd_info_t *)(pub->info); |
---|
3959 | 3166 | |
---|
3960 | 3167 | ASSERT(di != NULL); |
---|
3961 | | -#ifdef BCMDBUS |
---|
3962 | | - spin_unlock_irqrestore(&di->wlfc_spinlock, di->wlfc_lock_flags); |
---|
3963 | | -#else |
---|
3964 | 3168 | spin_unlock_bh(&di->wlfc_spinlock); |
---|
3965 | | -#endif |
---|
3966 | 3169 | return 1; |
---|
3967 | 3170 | } |
---|
3968 | 3171 | |
---|
3969 | 3172 | #endif /* PROP_TXSTATUS */ |
---|
3970 | | - |
---|
3971 | | -#if defined(DHD_8021X_DUMP) |
---|
3972 | | -void |
---|
3973 | | -dhd_tx_dump(osl_t *osh, void *pkt) |
---|
3974 | | -{ |
---|
3975 | | - uint8 *dump_data; |
---|
3976 | | - uint16 protocol; |
---|
3977 | | - |
---|
3978 | | - dump_data = PKTDATA(osh, pkt); |
---|
3979 | | - protocol = (dump_data[12] << 8) | dump_data[13]; |
---|
3980 | | - |
---|
3981 | | - if (protocol == ETHER_TYPE_802_1X) { |
---|
3982 | | - DHD_ERROR(("ETHER_TYPE_802_1X [TX]: ver %d, type %d, replay %d\n", |
---|
3983 | | - dump_data[14], dump_data[15], dump_data[30])); |
---|
3984 | | - } |
---|
3985 | | -} |
---|
3986 | | -#endif /* DHD_8021X_DUMP */ |
---|
3987 | 3173 | |
---|
3988 | 3174 | /* This routine do not support Packet chain feature, Currently tested for |
---|
3989 | 3175 | * proxy arp feature |
---|
.. | .. |
---|
3999 | 3185 | |
---|
4000 | 3186 | ifp = dhdp->info->iflist[ifidx]; |
---|
4001 | 3187 | skb->dev = ifp->net; |
---|
4002 | | -#if defined(BCM_GMAC3) |
---|
4003 | | - /* Forwarder capable interfaces use WOFA based forwarding */ |
---|
4004 | | - if (ifp->fwdh) { |
---|
4005 | | - struct ether_header *eh = (struct ether_header *)PKTDATA(dhdp->osh, p); |
---|
4006 | | - uint16 * da = (uint16 *)(eh->ether_dhost); |
---|
4007 | | - uintptr_t wofa_data; |
---|
4008 | | - ASSERT(ISALIGNED(da, 2)); |
---|
4009 | | - |
---|
4010 | | - wofa_data = fwder_lookup(ifp->fwdh->mate, da, ifp->idx); |
---|
4011 | | - if (wofa_data == WOFA_DATA_INVALID) { /* Unknown MAC address */ |
---|
4012 | | - if (fwder_transmit(ifp->fwdh, skb, 1, skb->dev) == FWDER_SUCCESS) { |
---|
4013 | | - return BCME_OK; |
---|
4014 | | - } |
---|
4015 | | - } |
---|
4016 | | - PKTFRMNATIVE(dhdp->osh, p); |
---|
4017 | | - PKTFREE(dhdp->osh, p, FALSE); |
---|
4018 | | - return BCME_OK; |
---|
4019 | | - } |
---|
4020 | | -#endif /* BCM_GMAC3 */ |
---|
4021 | 3188 | |
---|
4022 | 3189 | skb->protocol = eth_type_trans(skb, skb->dev); |
---|
4023 | 3190 | |
---|
.. | .. |
---|
4042 | 3209 | */ |
---|
4043 | 3210 | bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, |
---|
4044 | 3211 | __FUNCTION__, __LINE__); |
---|
4045 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) |
---|
4046 | 3212 | netif_rx_ni(skb); |
---|
4047 | | -#else |
---|
4048 | | - ulong flags; |
---|
4049 | | - netif_rx(skb); |
---|
4050 | | - local_irq_save(flags); |
---|
4051 | | - RAISE_RX_SOFTIRQ(); |
---|
4052 | | - local_irq_restore(flags); |
---|
4053 | | -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ |
---|
4054 | 3213 | } |
---|
4055 | 3214 | } |
---|
4056 | 3215 | |
---|
.. | .. |
---|
4066 | 3225 | int ret = BCME_OK; |
---|
4067 | 3226 | dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); |
---|
4068 | 3227 | struct ether_header *eh = NULL; |
---|
| 3228 | + bool pkt_ether_type_802_1x = FALSE; |
---|
| 3229 | + uint8 pkt_flow_prio; |
---|
| 3230 | + |
---|
4069 | 3231 | #if defined(DHD_L2_FILTER) |
---|
4070 | 3232 | dhd_if_t *ifp = dhd_get_ifp(dhdp, ifidx); |
---|
4071 | | -#endif |
---|
| 3233 | +#endif // endif |
---|
4072 | 3234 | |
---|
4073 | 3235 | /* Reject if down */ |
---|
4074 | 3236 | if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN)) { |
---|
.. | .. |
---|
4080 | 3242 | #ifdef PCIE_FULL_DONGLE |
---|
4081 | 3243 | if (dhdp->busstate == DHD_BUS_SUSPEND) { |
---|
4082 | 3244 | DHD_ERROR(("%s : pcie is still in suspend state!!\n", __FUNCTION__)); |
---|
4083 | | - PKTFREE(dhdp->osh, pktbuf, TRUE); |
---|
4084 | | - return -EBUSY; |
---|
| 3245 | + PKTCFREE(dhdp->osh, pktbuf, TRUE); |
---|
| 3246 | + return NETDEV_TX_BUSY; |
---|
4085 | 3247 | } |
---|
4086 | 3248 | #endif /* PCIE_FULL_DONGLE */ |
---|
| 3249 | + |
---|
| 3250 | + /* Reject if pktlen > MAX_MTU_SZ */ |
---|
| 3251 | + if (PKTLEN(dhdp->osh, pktbuf) > MAX_MTU_SZ) { |
---|
| 3252 | + /* free the packet here since the caller won't */ |
---|
| 3253 | + dhdp->tx_big_packets++; |
---|
| 3254 | + PKTCFREE(dhdp->osh, pktbuf, TRUE); |
---|
| 3255 | + return BCME_ERROR; |
---|
| 3256 | + } |
---|
4087 | 3257 | |
---|
4088 | 3258 | #ifdef DHD_L2_FILTER |
---|
4089 | 3259 | /* if dhcp_unicast is enabled, we need to convert the */ |
---|
.. | .. |
---|
4131 | 3301 | if (ETHER_ISMULTI(eh->ether_dhost)) |
---|
4132 | 3302 | dhdp->tx_multicast++; |
---|
4133 | 3303 | if (ntoh16(eh->ether_type) == ETHER_TYPE_802_1X) { |
---|
| 3304 | +#ifdef DHD_LOSSLESS_ROAMING |
---|
| 3305 | + uint8 prio = (uint8)PKTPRIO(pktbuf); |
---|
| 3306 | + |
---|
| 3307 | + /* back up 802.1x's priority */ |
---|
| 3308 | + dhdp->prio_8021x = prio; |
---|
| 3309 | +#endif /* DHD_LOSSLESS_ROAMING */ |
---|
| 3310 | + pkt_ether_type_802_1x = TRUE; |
---|
4134 | 3311 | DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED); |
---|
4135 | 3312 | atomic_inc(&dhd->pend_8021x_cnt); |
---|
| 3313 | +#if defined(WL_CFG80211) && defined(WL_WPS_SYNC) |
---|
| 3314 | + wl_handle_wps_states(dhd_idx2net(dhdp, ifidx), |
---|
| 3315 | + pktdata, PKTLEN(dhdp->osh, pktbuf), TRUE); |
---|
| 3316 | +#endif /* WL_CFG80211 && WL_WPS_SYNC */ |
---|
4136 | 3317 | } |
---|
4137 | | -#ifdef DHD_DHCP_DUMP |
---|
4138 | | - if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) { |
---|
4139 | | - dhd_dhcp_dump(pktdata, TRUE); |
---|
4140 | | - dhd_tcp_dump(dhd_ifname(dhdp, ifidx), pktdata, TRUE); |
---|
4141 | | - } |
---|
4142 | | -#endif /* DHD_DHCP_DUMP */ |
---|
| 3318 | + dhd_dump_pkt(dhdp, ifidx, pktdata, |
---|
| 3319 | + (uint32)PKTLEN(dhdp->osh, pktbuf), TRUE, NULL, NULL); |
---|
4143 | 3320 | } else { |
---|
4144 | | - PKTCFREE(dhdp->osh, pktbuf, TRUE); |
---|
4145 | | - return BCME_ERROR; |
---|
| 3321 | + PKTCFREE(dhdp->osh, pktbuf, TRUE); |
---|
| 3322 | + return BCME_ERROR; |
---|
4146 | 3323 | } |
---|
4147 | 3324 | |
---|
4148 | 3325 | { |
---|
4149 | 3326 | /* Look into the packet and update the packet priority */ |
---|
4150 | 3327 | #ifndef PKTPRIO_OVERRIDE |
---|
4151 | 3328 | if (PKTPRIO(pktbuf) == 0) |
---|
4152 | | -#endif |
---|
| 3329 | +#endif /* !PKTPRIO_OVERRIDE */ |
---|
4153 | 3330 | { |
---|
4154 | 3331 | #if defined(QOS_MAP_SET) |
---|
4155 | | - pktsetprio_qms(pktbuf, wl_get_up_table(), FALSE); |
---|
| 3332 | + pktsetprio_qms(pktbuf, wl_get_up_table(dhdp, ifidx), FALSE); |
---|
4156 | 3333 | #else |
---|
4157 | 3334 | pktsetprio(pktbuf, FALSE); |
---|
4158 | 3335 | #endif /* QOS_MAP_SET */ |
---|
4159 | 3336 | } |
---|
| 3337 | +#ifndef PKTPRIO_OVERRIDE |
---|
| 3338 | + else { |
---|
| 3339 | + /* Some protocols like OZMO use priority values from 256..263. |
---|
| 3340 | + * these are magic values to indicate a specific 802.1d priority. |
---|
| 3341 | + * make sure that priority field is in range of 0..7 |
---|
| 3342 | + */ |
---|
| 3343 | + PKTSETPRIO(pktbuf, PKTPRIO(pktbuf) & 0x7); |
---|
| 3344 | + } |
---|
| 3345 | +#endif /* !PKTPRIO_OVERRIDE */ |
---|
4160 | 3346 | } |
---|
4161 | 3347 | |
---|
| 3348 | + BCM_REFERENCE(pkt_ether_type_802_1x); |
---|
| 3349 | + BCM_REFERENCE(pkt_flow_prio); |
---|
4162 | 3350 | |
---|
4163 | | -#if defined(TRAFFIC_MGMT_DWM) |
---|
4164 | | - traffic_mgmt_pkt_set_prio(dhdp, pktbuf); |
---|
4165 | | - |
---|
4166 | | -#ifdef BCM_GMAC3 |
---|
4167 | | - DHD_PKT_SET_DATAOFF(pktbuf, 0); |
---|
4168 | | -#endif /* BCM_GMAC3 */ |
---|
4169 | | -#endif |
---|
| 3351 | +#ifdef SUPPORT_SET_TID |
---|
| 3352 | + dhd_set_tid_based_on_uid(dhdp, pktbuf); |
---|
| 3353 | +#endif /* SUPPORT_SET_TID */ |
---|
4170 | 3354 | |
---|
4171 | 3355 | #ifdef PCIE_FULL_DONGLE |
---|
4172 | 3356 | /* |
---|
.. | .. |
---|
4174 | 3358 | * available, allocate a unique flowid and add a flowring entry. |
---|
4175 | 3359 | * The found or newly created flowid is placed into the pktbuf's tag. |
---|
4176 | 3360 | */ |
---|
4177 | | - ret = dhd_flowid_update(dhdp, ifidx, dhdp->flow_prio_map[(PKTPRIO(pktbuf))], pktbuf); |
---|
| 3361 | + |
---|
| 3362 | +#ifdef DHD_LOSSLESS_ROAMING |
---|
| 3363 | + /* For LLR override and use flowring with prio 7 for 802.1x packets */ |
---|
| 3364 | + if (pkt_ether_type_802_1x) { |
---|
| 3365 | + pkt_flow_prio = PRIO_8021D_NC; |
---|
| 3366 | + } else |
---|
| 3367 | +#endif /* DHD_LOSSLESS_ROAMING */ |
---|
| 3368 | + { |
---|
| 3369 | + pkt_flow_prio = dhdp->flow_prio_map[(PKTPRIO(pktbuf))]; |
---|
| 3370 | + } |
---|
| 3371 | + |
---|
| 3372 | + ret = dhd_flowid_update(dhdp, ifidx, pkt_flow_prio, pktbuf); |
---|
4178 | 3373 | if (ret != BCME_OK) { |
---|
| 3374 | + if (ntoh16(eh->ether_type) == ETHER_TYPE_802_1X) { |
---|
| 3375 | + atomic_dec(&dhd->pend_8021x_cnt); |
---|
| 3376 | + } |
---|
4179 | 3377 | PKTCFREE(dhd->pub.osh, pktbuf, TRUE); |
---|
4180 | 3378 | return ret; |
---|
4181 | 3379 | } |
---|
4182 | | -#endif |
---|
| 3380 | +#endif /* PCIE_FULL_DONGLE */ |
---|
4183 | 3381 | |
---|
4184 | 3382 | #ifdef PROP_TXSTATUS |
---|
4185 | 3383 | if (dhd_wlfc_is_supported(dhdp)) { |
---|
.. | .. |
---|
4203 | 3401 | } |
---|
4204 | 3402 | |
---|
4205 | 3403 | /* Use bus module to send data frame */ |
---|
4206 | | -#ifdef WLMEDIA_HTSF |
---|
4207 | | - dhd_htsf_addtxts(dhdp, pktbuf); |
---|
4208 | | -#endif |
---|
4209 | | -#if defined(DHD_8021X_DUMP) |
---|
4210 | | - dhd_tx_dump(dhdp->osh, pktbuf); |
---|
4211 | | -#endif |
---|
4212 | | -#ifdef BCMDBUS |
---|
4213 | | -#ifdef PROP_TXSTATUS |
---|
4214 | | - if (dhd_wlfc_commit_packets(dhdp, (f_commitpkt_t)dhd_dbus_txdata, |
---|
4215 | | - dhdp, pktbuf, TRUE) == WLFC_UNSUPPORTED) { |
---|
4216 | | - /* non-proptxstatus way */ |
---|
4217 | | - ret = dhd_dbus_txdata(dhdp, pktbuf); |
---|
4218 | | - } |
---|
4219 | | -#else |
---|
4220 | | - ret = dhd_dbus_txdata(dhdp, pktbuf); |
---|
4221 | | -#endif /* PROP_TXSTATUS */ |
---|
4222 | | - if (ret) |
---|
4223 | | - PKTCFREE(dhdp->osh, pktbuf, TRUE); |
---|
4224 | | -#else |
---|
4225 | 3404 | #ifdef PROP_TXSTATUS |
---|
4226 | 3405 | { |
---|
4227 | 3406 | if (dhd_wlfc_commit_packets(dhdp, (f_commitpkt_t)dhd_bus_txdata, |
---|
.. | .. |
---|
4242 | 3421 | #endif /* BCMPCIE */ |
---|
4243 | 3422 | #endif /* PROP_TXSTATUS */ |
---|
4244 | 3423 | |
---|
4245 | | -#endif /* BCMDBUS */ |
---|
4246 | | - |
---|
4247 | 3424 | return ret; |
---|
4248 | 3425 | } |
---|
4249 | 3426 | |
---|
.. | .. |
---|
4252 | 3429 | { |
---|
4253 | 3430 | int ret = 0; |
---|
4254 | 3431 | unsigned long flags; |
---|
| 3432 | + dhd_if_t *ifp; |
---|
4255 | 3433 | |
---|
4256 | 3434 | DHD_GENERAL_LOCK(dhdp, flags); |
---|
4257 | | - if (dhdp->busstate == DHD_BUS_DOWN || |
---|
4258 | | - dhdp->busstate == DHD_BUS_DOWN_IN_PROGRESS) { |
---|
| 3435 | + ifp = dhd_get_ifp(dhdp, ifidx); |
---|
| 3436 | + if (!ifp || ifp->del_in_progress) { |
---|
| 3437 | + DHD_ERROR(("%s: ifp:%p del_in_progress:%d\n", |
---|
| 3438 | + __FUNCTION__, ifp, ifp ? ifp->del_in_progress : 0)); |
---|
| 3439 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 3440 | + PKTCFREE(dhdp->osh, pktbuf, TRUE); |
---|
| 3441 | + return -ENODEV; |
---|
| 3442 | + } |
---|
| 3443 | + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp)) { |
---|
4259 | 3444 | DHD_ERROR(("%s: returning as busstate=%d\n", |
---|
4260 | 3445 | __FUNCTION__, dhdp->busstate)); |
---|
4261 | 3446 | DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
4262 | 3447 | PKTCFREE(dhdp->osh, pktbuf, TRUE); |
---|
4263 | 3448 | return -ENODEV; |
---|
4264 | 3449 | } |
---|
4265 | | - dhdp->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_SEND_PKT; |
---|
| 3450 | + DHD_IF_SET_TX_ACTIVE(ifp, DHD_TX_SEND_PKT); |
---|
| 3451 | + DHD_BUS_BUSY_SET_IN_SEND_PKT(dhdp); |
---|
| 3452 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 3453 | + |
---|
| 3454 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 3455 | + if (dhdpcie_runtime_bus_wake(dhdp, FALSE, __builtin_return_address(0))) { |
---|
| 3456 | + DHD_ERROR(("%s : pcie is still in suspend state!!\n", __FUNCTION__)); |
---|
| 3457 | + PKTCFREE(dhdp->osh, pktbuf, TRUE); |
---|
| 3458 | + ret = -EBUSY; |
---|
| 3459 | + goto exit; |
---|
| 3460 | + } |
---|
| 3461 | +#endif /* DHD_PCIE_RUNTIMEPM */ |
---|
| 3462 | + |
---|
| 3463 | + DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 3464 | + if (DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(dhdp)) { |
---|
| 3465 | + DHD_ERROR(("%s: bus is in suspend(%d) or suspending(0x%x) state!!\n", |
---|
| 3466 | + __FUNCTION__, dhdp->busstate, dhdp->dhd_bus_busy_state)); |
---|
| 3467 | + DHD_BUS_BUSY_CLEAR_IN_SEND_PKT(dhdp); |
---|
| 3468 | + DHD_IF_CLR_TX_ACTIVE(ifp, DHD_TX_SEND_PKT); |
---|
| 3469 | + dhd_os_tx_completion_wake(dhdp); |
---|
| 3470 | + dhd_os_busbusy_wake(dhdp); |
---|
| 3471 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 3472 | + PKTCFREE(dhdp->osh, pktbuf, TRUE); |
---|
| 3473 | + return -ENODEV; |
---|
| 3474 | + } |
---|
4266 | 3475 | DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
4267 | 3476 | |
---|
4268 | 3477 | ret = __dhd_sendpkt(dhdp, ifidx, pktbuf); |
---|
4269 | 3478 | |
---|
| 3479 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 3480 | +exit: |
---|
| 3481 | +#endif // endif |
---|
4270 | 3482 | DHD_GENERAL_LOCK(dhdp, flags); |
---|
4271 | | - dhdp->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_SEND_PKT; |
---|
| 3483 | + DHD_BUS_BUSY_CLEAR_IN_SEND_PKT(dhdp); |
---|
| 3484 | + DHD_IF_CLR_TX_ACTIVE(ifp, DHD_TX_SEND_PKT); |
---|
| 3485 | + dhd_os_tx_completion_wake(dhdp); |
---|
| 3486 | + dhd_os_busbusy_wake(dhdp); |
---|
4272 | 3487 | DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
4273 | 3488 | return ret; |
---|
4274 | 3489 | } |
---|
4275 | 3490 | |
---|
| 3491 | +#ifndef DHD_MONITOR_INTERFACE |
---|
| 3492 | +static |
---|
| 3493 | +#endif /* DHD_MONITOR_INTERFACE */ |
---|
| 3494 | +#ifdef CFI_CHECK |
---|
| 3495 | +netdev_tx_t BCMFASTPATH |
---|
| 3496 | +#else /* CFI_CHECK */ |
---|
4276 | 3497 | int BCMFASTPATH |
---|
| 3498 | +#endif /* CFI_CHECK */ |
---|
4277 | 3499 | dhd_start_xmit(struct sk_buff *skb, struct net_device *net) |
---|
4278 | 3500 | { |
---|
4279 | 3501 | int ret; |
---|
.. | .. |
---|
4283 | 3505 | dhd_if_t *ifp = NULL; |
---|
4284 | 3506 | int ifidx; |
---|
4285 | 3507 | unsigned long flags; |
---|
4286 | | -#ifdef WLMEDIA_HTSF |
---|
4287 | | - uint8 htsfdlystat_sz = dhd->pub.htsfdlystat_sz; |
---|
4288 | | -#else |
---|
4289 | 3508 | uint8 htsfdlystat_sz = 0; |
---|
4290 | | -#endif |
---|
4291 | | -#ifdef DHD_WMF |
---|
4292 | | - struct ether_header *eh; |
---|
4293 | | - uint8 *iph; |
---|
4294 | | -#endif /* DHD_WMF */ |
---|
4295 | 3509 | |
---|
4296 | 3510 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
4297 | 3511 | |
---|
4298 | | - DHD_GENERAL_LOCK(&dhd->pub, flags); |
---|
| 3512 | + if (dhd_query_bus_erros(&dhd->pub)) { |
---|
| 3513 | +#ifdef CFI_CHECK |
---|
| 3514 | + return NETDEV_TX_BUSY; |
---|
| 3515 | +#else |
---|
| 3516 | + return -ENODEV; |
---|
| 3517 | +#endif /* CFI_CHECK */ |
---|
| 3518 | + } |
---|
4299 | 3519 | |
---|
4300 | | - if (dhd->pub.busstate == DHD_BUS_SUSPEND) { |
---|
4301 | | - DHD_ERROR(("%s : pcie is still in suspend state!!\n", __FUNCTION__)); |
---|
4302 | | - dev_kfree_skb(skb); |
---|
4303 | | - ifp = DHD_DEV_IFP(net); |
---|
4304 | | - ifp->stats.tx_dropped++; |
---|
4305 | | - dhd->pub.tx_dropped++; |
---|
| 3520 | + DHD_GENERAL_LOCK(&dhd->pub, flags); |
---|
| 3521 | + DHD_BUS_BUSY_SET_IN_TX(&dhd->pub); |
---|
| 3522 | + DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
| 3523 | + |
---|
| 3524 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 3525 | + if (dhdpcie_runtime_bus_wake(&dhd->pub, FALSE, dhd_start_xmit)) { |
---|
| 3526 | + /* In order to avoid pkt loss. Return NETDEV_TX_BUSY until run-time resumed. */ |
---|
| 3527 | + /* stop the network queue temporarily until resume done */ |
---|
| 3528 | + DHD_GENERAL_LOCK(&dhd->pub, flags); |
---|
| 3529 | + if (!dhdpcie_is_resume_done(&dhd->pub)) { |
---|
| 3530 | + dhd_bus_stop_queue(dhd->pub.bus); |
---|
| 3531 | + } |
---|
| 3532 | + DHD_BUS_BUSY_CLEAR_IN_TX(&dhd->pub); |
---|
| 3533 | + dhd_os_busbusy_wake(&dhd->pub); |
---|
4306 | 3534 | DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
4307 | | - return -EBUSY; |
---|
| 3535 | + return NETDEV_TX_BUSY; |
---|
| 3536 | + } |
---|
| 3537 | +#endif /* DHD_PCIE_RUNTIMEPM */ |
---|
| 3538 | + |
---|
| 3539 | + DHD_GENERAL_LOCK(&dhd->pub, flags); |
---|
| 3540 | + if (DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(&dhd->pub)) { |
---|
| 3541 | + DHD_ERROR(("%s: bus is in suspend(%d) or suspending(0x%x) state!!\n", |
---|
| 3542 | + __FUNCTION__, dhd->pub.busstate, dhd->pub.dhd_bus_busy_state)); |
---|
| 3543 | + DHD_BUS_BUSY_CLEAR_IN_TX(&dhd->pub); |
---|
| 3544 | +#ifdef PCIE_FULL_DONGLE |
---|
| 3545 | + /* Stop tx queues if suspend is in progress */ |
---|
| 3546 | + if (DHD_BUS_CHECK_ANY_SUSPEND_IN_PROGRESS(&dhd->pub)) { |
---|
| 3547 | + dhd_bus_stop_queue(dhd->pub.bus); |
---|
| 3548 | + } |
---|
| 3549 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 3550 | + dhd_os_busbusy_wake(&dhd->pub); |
---|
| 3551 | + DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
| 3552 | + return NETDEV_TX_BUSY; |
---|
4308 | 3553 | } |
---|
4309 | 3554 | |
---|
4310 | 3555 | DHD_OS_WAKE_LOCK(&dhd->pub); |
---|
4311 | 3556 | DHD_PERIM_LOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken); |
---|
4312 | 3557 | |
---|
| 3558 | +#if defined(DHD_HANG_SEND_UP_TEST) |
---|
| 3559 | + if (dhd->pub.req_hang_type == HANG_REASON_BUS_DOWN) { |
---|
| 3560 | + DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__)); |
---|
| 3561 | + dhd->pub.busstate = DHD_BUS_DOWN; |
---|
| 3562 | + } |
---|
| 3563 | +#endif /* DHD_HANG_SEND_UP_TEST */ |
---|
| 3564 | + |
---|
4313 | 3565 | /* Reject if down */ |
---|
4314 | | - if (dhd->pub.hang_was_sent || dhd->pub.busstate == DHD_BUS_DOWN || |
---|
4315 | | - dhd->pub.busstate == DHD_BUS_DOWN_IN_PROGRESS) { |
---|
| 3566 | + if (dhd->pub.hang_was_sent || DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(&dhd->pub)) { |
---|
4316 | 3567 | DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d \n", |
---|
4317 | 3568 | __FUNCTION__, dhd->pub.up, dhd->pub.busstate)); |
---|
4318 | 3569 | netif_stop_queue(net); |
---|
| 3570 | +#if defined(OEM_ANDROID) |
---|
4319 | 3571 | /* Send Event when bus down detected during data session */ |
---|
4320 | | - if (dhd->pub.up) { |
---|
| 3572 | + if (dhd->pub.up && !dhd->pub.hang_was_sent) { |
---|
4321 | 3573 | DHD_ERROR(("%s: Event HANG sent up\n", __FUNCTION__)); |
---|
| 3574 | + dhd->pub.hang_reason = HANG_REASON_BUS_DOWN; |
---|
4322 | 3575 | net_os_send_hang_message(net); |
---|
4323 | 3576 | } |
---|
| 3577 | +#endif /* OEM_ANDROID */ |
---|
| 3578 | + DHD_BUS_BUSY_CLEAR_IN_TX(&dhd->pub); |
---|
| 3579 | + dhd_os_busbusy_wake(&dhd->pub); |
---|
4324 | 3580 | DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
4325 | 3581 | DHD_PERIM_UNLOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken); |
---|
4326 | 3582 | DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
4327 | | -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)) |
---|
4328 | | - return -ENODEV; |
---|
4329 | | -#else |
---|
4330 | 3583 | return NETDEV_TX_BUSY; |
---|
4331 | | -#endif |
---|
4332 | 3584 | } |
---|
4333 | 3585 | |
---|
4334 | 3586 | ifp = DHD_DEV_IFP(net); |
---|
4335 | 3587 | ifidx = DHD_DEV_IFIDX(net); |
---|
4336 | | - BUZZZ_LOG(START_XMIT_BGN, 2, (uint32)ifidx, (uintptr)skb); |
---|
4337 | | - |
---|
4338 | | - if (ifidx == DHD_BAD_IF) { |
---|
4339 | | - DHD_ERROR(("%s: bad ifidx %d\n", __FUNCTION__, ifidx)); |
---|
| 3588 | + if (!ifp || (ifidx == DHD_BAD_IF) || |
---|
| 3589 | + ifp->del_in_progress) { |
---|
| 3590 | + DHD_ERROR(("%s: ifidx %d ifp:%p del_in_progress:%d\n", |
---|
| 3591 | + __FUNCTION__, ifidx, ifp, (ifp ? ifp->del_in_progress : 0))); |
---|
4340 | 3592 | netif_stop_queue(net); |
---|
| 3593 | + DHD_BUS_BUSY_CLEAR_IN_TX(&dhd->pub); |
---|
| 3594 | + dhd_os_busbusy_wake(&dhd->pub); |
---|
| 3595 | + DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
4341 | 3596 | DHD_PERIM_UNLOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken); |
---|
4342 | 3597 | DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
4343 | | -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)) |
---|
4344 | | - return -ENODEV; |
---|
4345 | | -#else |
---|
4346 | 3598 | return NETDEV_TX_BUSY; |
---|
4347 | | -#endif |
---|
4348 | 3599 | } |
---|
4349 | 3600 | |
---|
4350 | | - dhd->pub.dhd_bus_busy_state |= DHD_BUS_BUSY_IN_TX; |
---|
| 3601 | + DHD_IF_SET_TX_ACTIVE(ifp, DHD_TX_START_XMIT); |
---|
4351 | 3602 | DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
4352 | 3603 | |
---|
4353 | 3604 | ASSERT(ifidx == dhd_net2idx(dhd, net)); |
---|
.. | .. |
---|
4397 | 3648 | goto done; |
---|
4398 | 3649 | } |
---|
4399 | 3650 | |
---|
4400 | | -#if defined(WLMEDIA_HTSF) |
---|
4401 | | - if (htsfdlystat_sz && PKTLEN(dhd->pub.osh, pktbuf) >= ETHER_ADDR_LEN) { |
---|
4402 | | - uint8 *pktdata = (uint8 *)PKTDATA(dhd->pub.osh, pktbuf); |
---|
4403 | | - struct ether_header *eh = (struct ether_header *)pktdata; |
---|
4404 | | - |
---|
4405 | | - if (!ETHER_ISMULTI(eh->ether_dhost) && |
---|
4406 | | - (ntoh16(eh->ether_type) == ETHER_TYPE_IP)) { |
---|
4407 | | - eh->ether_type = hton16(ETHER_TYPE_BRCM_PKTDLYSTATS); |
---|
4408 | | - } |
---|
4409 | | - } |
---|
4410 | | -#endif |
---|
4411 | 3651 | #ifdef DHD_WET |
---|
4412 | 3652 | /* wet related packet proto manipulation should be done in DHD |
---|
4413 | | - * since dongle doesn't have complete payload |
---|
| 3653 | + since dongle doesn't have complete payload |
---|
4414 | 3654 | */ |
---|
4415 | 3655 | if (WET_ENABLED(&dhd->pub) && |
---|
4416 | 3656 | (dhd_wet_send_proc(dhd->pub.wet_info, pktbuf, &pktbuf) < 0)) { |
---|
.. | .. |
---|
4422 | 3662 | } |
---|
4423 | 3663 | #endif /* DHD_WET */ |
---|
4424 | 3664 | |
---|
4425 | | -#ifdef DHD_WMF |
---|
4426 | | - eh = (struct ether_header *)PKTDATA(dhd->pub.osh, pktbuf); |
---|
4427 | | - iph = (uint8 *)eh + ETHER_HDR_LEN; |
---|
4428 | | - |
---|
4429 | | - /* WMF processing for multicast packets |
---|
4430 | | - * Only IPv4 packets are handled |
---|
4431 | | - */ |
---|
4432 | | - if (ifp->wmf.wmf_enable && (ntoh16(eh->ether_type) == ETHER_TYPE_IP) && |
---|
4433 | | - (IP_VER(iph) == IP_VER_4) && (ETHER_ISMULTI(eh->ether_dhost) || |
---|
4434 | | - ((IPV4_PROT(iph) == IP_PROT_IGMP) && dhd->pub.wmf_ucast_igmp))) { |
---|
4435 | | -#if defined(DHD_IGMP_UCQUERY) || defined(DHD_UCAST_UPNP) |
---|
4436 | | - void *sdu_clone; |
---|
4437 | | - bool ucast_convert = FALSE; |
---|
4438 | | -#ifdef DHD_UCAST_UPNP |
---|
4439 | | - uint32 dest_ip; |
---|
4440 | | - |
---|
4441 | | - dest_ip = ntoh32(*((uint32 *)(iph + IPV4_DEST_IP_OFFSET))); |
---|
4442 | | - ucast_convert = dhd->pub.wmf_ucast_upnp && MCAST_ADDR_UPNP_SSDP(dest_ip); |
---|
4443 | | -#endif /* DHD_UCAST_UPNP */ |
---|
4444 | | -#ifdef DHD_IGMP_UCQUERY |
---|
4445 | | - ucast_convert |= dhd->pub.wmf_ucast_igmp_query && |
---|
4446 | | - (IPV4_PROT(iph) == IP_PROT_IGMP) && |
---|
4447 | | - (*(iph + IPV4_HLEN(iph)) == IGMPV2_HOST_MEMBERSHIP_QUERY); |
---|
4448 | | -#endif /* DHD_IGMP_UCQUERY */ |
---|
4449 | | - if (ucast_convert) { |
---|
4450 | | - dhd_sta_t *sta; |
---|
4451 | | - unsigned long flags; |
---|
4452 | | - struct list_head snapshot_list; |
---|
4453 | | - struct list_head *wmf_ucforward_list; |
---|
4454 | | - |
---|
4455 | | - ret = NETDEV_TX_OK; |
---|
4456 | | - |
---|
4457 | | - /* For non BCM_GMAC3 platform we need a snapshot sta_list to |
---|
4458 | | - * resolve double DHD_IF_STA_LIST_LOCK call deadlock issue. |
---|
4459 | | - */ |
---|
4460 | | - wmf_ucforward_list = DHD_IF_WMF_UCFORWARD_LOCK(dhd, ifp, &snapshot_list); |
---|
4461 | | - |
---|
4462 | | - /* Convert upnp/igmp query to unicast for each assoc STA */ |
---|
4463 | | - list_for_each_entry(sta, wmf_ucforward_list, list) { |
---|
4464 | | - /* Skip sending to proxy interfaces of proxySTA */ |
---|
4465 | | - if (sta->psta_prim != NULL && !ifp->wmf_psta_disable) { |
---|
4466 | | - continue; |
---|
4467 | | - } |
---|
4468 | | - if ((sdu_clone = PKTDUP(dhd->pub.osh, pktbuf)) == NULL) { |
---|
4469 | | - ret = WMF_NOP; |
---|
4470 | | - break; |
---|
4471 | | - } |
---|
4472 | | - dhd_wmf_forward(ifp->wmf.wmfh, sdu_clone, 0, sta, 1); |
---|
4473 | | - } |
---|
4474 | | - DHD_IF_WMF_UCFORWARD_UNLOCK(dhd, wmf_ucforward_list); |
---|
4475 | | - |
---|
4476 | | - DHD_GENERAL_LOCK(&dhd->pub, flags); |
---|
4477 | | - dhd->pub.dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_TX; |
---|
4478 | | - dhd_os_busbusy_wake(&dhd->pub); |
---|
4479 | | - DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
4480 | | - DHD_PERIM_UNLOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken); |
---|
4481 | | - DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
4482 | | - |
---|
4483 | | - if (ret == NETDEV_TX_OK) |
---|
4484 | | - PKTFREE(dhd->pub.osh, pktbuf, TRUE); |
---|
4485 | | - |
---|
4486 | | - return ret; |
---|
4487 | | - } else |
---|
4488 | | -#endif /* defined(DHD_IGMP_UCQUERY) || defined(DHD_UCAST_UPNP) */ |
---|
4489 | | - { |
---|
4490 | | - /* There will be no STA info if the packet is coming from LAN host |
---|
4491 | | - * Pass as NULL |
---|
4492 | | - */ |
---|
4493 | | - ret = dhd_wmf_packets_handle(&dhd->pub, pktbuf, NULL, ifidx, 0); |
---|
4494 | | - switch (ret) { |
---|
4495 | | - case WMF_TAKEN: |
---|
4496 | | - case WMF_DROP: |
---|
4497 | | - /* Either taken by WMF or we should drop it. |
---|
4498 | | - * Exiting send path |
---|
4499 | | - */ |
---|
4500 | | - |
---|
4501 | | - DHD_GENERAL_LOCK(&dhd->pub, flags); |
---|
4502 | | - dhd->pub.dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_TX; |
---|
4503 | | - dhd_os_busbusy_wake(&dhd->pub); |
---|
4504 | | - DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
4505 | | - DHD_PERIM_UNLOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken); |
---|
4506 | | - DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
4507 | | - return NETDEV_TX_OK; |
---|
4508 | | - default: |
---|
4509 | | - /* Continue the transmit path */ |
---|
4510 | | - break; |
---|
4511 | | - } |
---|
4512 | | - } |
---|
4513 | | - } |
---|
4514 | | -#endif /* DHD_WMF */ |
---|
4515 | 3665 | #ifdef DHD_PSTA |
---|
4516 | 3666 | /* PSR related packet proto manipulation should be done in DHD |
---|
4517 | 3667 | * since dongle doesn't have complete payload |
---|
4518 | 3668 | */ |
---|
4519 | | - if (PSR_ENABLED(&dhd->pub) && (dhd_psta_proc(&dhd->pub, |
---|
4520 | | - ifidx, &pktbuf, TRUE) < 0)) { |
---|
| 3669 | + if (PSR_ENABLED(&dhd->pub) && |
---|
| 3670 | + (dhd_psta_proc(&dhd->pub, ifidx, &pktbuf, TRUE) < 0)) { |
---|
| 3671 | + |
---|
4521 | 3672 | DHD_ERROR(("%s:%s: psta send proc failed\n", __FUNCTION__, |
---|
4522 | 3673 | dhd_ifname(&dhd->pub, ifidx))); |
---|
4523 | 3674 | } |
---|
4524 | 3675 | #endif /* DHD_PSTA */ |
---|
| 3676 | +#ifdef CONFIG_ARCH_MSM |
---|
| 3677 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0) |
---|
| 3678 | + if (skb->sk) { |
---|
| 3679 | + sk_pacing_shift_update(skb->sk, 8); |
---|
| 3680 | + } |
---|
| 3681 | +#endif /* LINUX_VERSION_CODE >= 4.16.0 */ |
---|
| 3682 | +#endif /* CONFIG_ARCH_MSM */ |
---|
| 3683 | +#ifdef DHDTCPSYNC_FLOOD_BLK |
---|
| 3684 | + if (dhd_tcpdata_get_flag(&dhd->pub, pktbuf) == FLAG_SYNCACK) { |
---|
| 3685 | + ifp->tsyncack_txed ++; |
---|
| 3686 | + } |
---|
| 3687 | +#endif /* DHDTCPSYNC_FLOOD_BLK */ |
---|
4525 | 3688 | |
---|
4526 | 3689 | #ifdef DHDTCPACK_SUPPRESS |
---|
4527 | 3690 | if (dhd->pub.tcpack_sup_mode == TCPACK_SUP_HOLD) { |
---|
.. | .. |
---|
4538 | 3701 | } |
---|
4539 | 3702 | } |
---|
4540 | 3703 | #endif /* DHDTCPACK_SUPPRESS */ |
---|
4541 | | -#ifdef HOST_FLAG |
---|
4542 | | - if (hostsleep) { |
---|
4543 | | - printf("%s (%d): hostsleep = %d, tx_dropped = %lu\n",__FUNCTION__, __LINE__, |
---|
4544 | | - hostsleep, ifp->stats.tx_dropped); |
---|
4545 | | - PKTFREE(dhd->pub.osh, pktbuf, TRUE); |
---|
4546 | | - ret = BCME_TXFAIL; |
---|
4547 | | - goto done; |
---|
4548 | | - } |
---|
4549 | | -#endif |
---|
4550 | 3704 | |
---|
| 3705 | + /* |
---|
| 3706 | + * If Load Balance is enabled queue the packet |
---|
| 3707 | + * else send directly from here. |
---|
| 3708 | + */ |
---|
| 3709 | +#if defined(DHD_LB_TXP) |
---|
| 3710 | + ret = dhd_lb_sendpkt(dhd, net, ifidx, pktbuf); |
---|
| 3711 | +#else |
---|
4551 | 3712 | ret = __dhd_sendpkt(&dhd->pub, ifidx, pktbuf); |
---|
| 3713 | +#endif // endif |
---|
4552 | 3714 | |
---|
4553 | 3715 | done: |
---|
4554 | 3716 | if (ret) { |
---|
4555 | 3717 | ifp->stats.tx_dropped++; |
---|
4556 | 3718 | dhd->pub.tx_dropped++; |
---|
4557 | 3719 | } else { |
---|
4558 | | - |
---|
4559 | 3720 | #ifdef PROP_TXSTATUS |
---|
4560 | 3721 | /* tx_packets counter can counted only when wlfc is disabled */ |
---|
4561 | 3722 | if (!dhd_wlfc_is_supported(&dhd->pub)) |
---|
4562 | | -#endif |
---|
| 3723 | +#endif // endif |
---|
4563 | 3724 | { |
---|
4564 | 3725 | dhd->pub.tx_packets++; |
---|
4565 | 3726 | ifp->stats.tx_packets++; |
---|
.. | .. |
---|
4567 | 3728 | } |
---|
4568 | 3729 | } |
---|
4569 | 3730 | |
---|
4570 | | - |
---|
4571 | 3731 | DHD_GENERAL_LOCK(&dhd->pub, flags); |
---|
4572 | | - dhd->pub.dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_TX; |
---|
| 3732 | + DHD_BUS_BUSY_CLEAR_IN_TX(&dhd->pub); |
---|
| 3733 | + DHD_IF_CLR_TX_ACTIVE(ifp, DHD_TX_START_XMIT); |
---|
| 3734 | + dhd_os_tx_completion_wake(&dhd->pub); |
---|
4573 | 3735 | dhd_os_busbusy_wake(&dhd->pub); |
---|
4574 | 3736 | DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
4575 | 3737 | DHD_PERIM_UNLOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken); |
---|
4576 | 3738 | DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
4577 | | - |
---|
4578 | | - BUZZZ_LOG(START_XMIT_END, 0); |
---|
4579 | | - |
---|
4580 | 3739 | /* Return ok: we always eat the packet */ |
---|
4581 | | -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)) |
---|
4582 | | - return 0; |
---|
4583 | | -#else |
---|
4584 | 3740 | return NETDEV_TX_OK; |
---|
4585 | | -#endif |
---|
4586 | 3741 | } |
---|
4587 | 3742 | |
---|
| 3743 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 3744 | +void dhd_rx_wq_wakeup(struct work_struct *ptr) |
---|
| 3745 | +{ |
---|
| 3746 | + struct dhd_rx_tx_work *work; |
---|
| 3747 | + struct dhd_pub * pub; |
---|
| 3748 | + |
---|
| 3749 | + work = container_of(ptr, struct dhd_rx_tx_work, work); |
---|
| 3750 | + |
---|
| 3751 | + pub = work->pub; |
---|
| 3752 | + |
---|
| 3753 | + DHD_RPM(("%s: ENTER. \n", __FUNCTION__)); |
---|
| 3754 | + |
---|
| 3755 | + if (atomic_read(&pub->block_bus) || pub->busstate == DHD_BUS_DOWN) { |
---|
| 3756 | + return; |
---|
| 3757 | + } |
---|
| 3758 | + |
---|
| 3759 | + DHD_OS_WAKE_LOCK(pub); |
---|
| 3760 | + if (pm_runtime_get_sync(dhd_bus_to_dev(pub->bus)) >= 0) { |
---|
| 3761 | + |
---|
| 3762 | + // do nothing but wakeup the bus. |
---|
| 3763 | + pm_runtime_mark_last_busy(dhd_bus_to_dev(pub->bus)); |
---|
| 3764 | + pm_runtime_put_autosuspend(dhd_bus_to_dev(pub->bus)); |
---|
| 3765 | + } |
---|
| 3766 | + DHD_OS_WAKE_UNLOCK(pub); |
---|
| 3767 | + kfree(work); |
---|
| 3768 | +} |
---|
| 3769 | + |
---|
| 3770 | +void dhd_start_xmit_wq_adapter(struct work_struct *ptr) |
---|
| 3771 | +{ |
---|
| 3772 | + struct dhd_rx_tx_work *work; |
---|
| 3773 | + int ret; |
---|
| 3774 | + dhd_info_t *dhd; |
---|
| 3775 | + struct dhd_bus * bus; |
---|
| 3776 | + |
---|
| 3777 | + work = container_of(ptr, struct dhd_rx_tx_work, work); |
---|
| 3778 | + |
---|
| 3779 | + dhd = DHD_DEV_INFO(work->net); |
---|
| 3780 | + |
---|
| 3781 | + bus = dhd->pub.bus; |
---|
| 3782 | + |
---|
| 3783 | + if (atomic_read(&dhd->pub.block_bus)) { |
---|
| 3784 | + kfree_skb(work->skb); |
---|
| 3785 | + kfree(work); |
---|
| 3786 | + dhd_netif_start_queue(bus); |
---|
| 3787 | + return; |
---|
| 3788 | + } |
---|
| 3789 | + |
---|
| 3790 | + if (pm_runtime_get_sync(dhd_bus_to_dev(bus)) >= 0) { |
---|
| 3791 | + ret = dhd_start_xmit(work->skb, work->net); |
---|
| 3792 | + pm_runtime_mark_last_busy(dhd_bus_to_dev(bus)); |
---|
| 3793 | + pm_runtime_put_autosuspend(dhd_bus_to_dev(bus)); |
---|
| 3794 | + } |
---|
| 3795 | + kfree(work); |
---|
| 3796 | + dhd_netif_start_queue(bus); |
---|
| 3797 | + |
---|
| 3798 | + if (ret) |
---|
| 3799 | + netdev_err(work->net, |
---|
| 3800 | + "error: dhd_start_xmit():%d\n", ret); |
---|
| 3801 | +} |
---|
| 3802 | + |
---|
| 3803 | +#ifdef CFI_CHECK |
---|
| 3804 | +netdev_tx_t BCMFASTPATH |
---|
| 3805 | +#else |
---|
| 3806 | +int BCMFASTPATH |
---|
| 3807 | +#endif /* CFI_CHECK */ |
---|
| 3808 | +dhd_start_xmit_wrapper(struct sk_buff *skb, struct net_device *net) |
---|
| 3809 | +{ |
---|
| 3810 | + struct dhd_rx_tx_work *start_xmit_work; |
---|
| 3811 | + int ret; |
---|
| 3812 | + dhd_info_t *dhd = DHD_DEV_INFO(net); |
---|
| 3813 | + |
---|
| 3814 | + if (dhd->pub.busstate == DHD_BUS_SUSPEND) { |
---|
| 3815 | + DHD_RPM(("%s: wakeup the bus using workqueue.\n", __FUNCTION__)); |
---|
| 3816 | + |
---|
| 3817 | + dhd_netif_stop_queue(dhd->pub.bus); |
---|
| 3818 | + |
---|
| 3819 | + start_xmit_work = (struct dhd_rx_tx_work*) |
---|
| 3820 | + kmalloc(sizeof(*start_xmit_work), GFP_ATOMIC); |
---|
| 3821 | + |
---|
| 3822 | + if (!start_xmit_work) { |
---|
| 3823 | + netdev_err(net, |
---|
| 3824 | + "error: failed to alloc start_xmit_work\n"); |
---|
| 3825 | +#ifdef CFI_CHECK |
---|
| 3826 | + ret = NETDEV_TX_BUSY; |
---|
| 3827 | +#else |
---|
| 3828 | + ret = -ENOMEM; |
---|
| 3829 | +#endif /* CFI_CHECK */ |
---|
| 3830 | + goto exit; |
---|
| 3831 | + } |
---|
| 3832 | + |
---|
| 3833 | + INIT_WORK(&start_xmit_work->work, dhd_start_xmit_wq_adapter); |
---|
| 3834 | + start_xmit_work->skb = skb; |
---|
| 3835 | + start_xmit_work->net = net; |
---|
| 3836 | + queue_work(dhd->tx_wq, &start_xmit_work->work); |
---|
| 3837 | +#ifdef CFI_CHECK |
---|
| 3838 | + ret = NETDEV_TX_OK; |
---|
| 3839 | +#else |
---|
| 3840 | + ret = NET_XMIT_SUCCESS; |
---|
| 3841 | +#endif /* CFI_CHECK */ |
---|
| 3842 | + |
---|
| 3843 | + } else if (dhd->pub.busstate == DHD_BUS_DATA) { |
---|
| 3844 | + ret = dhd_start_xmit(skb, net); |
---|
| 3845 | + } else { |
---|
| 3846 | + /* when bus is down */ |
---|
| 3847 | +#ifdef CFI_CHECK |
---|
| 3848 | + ret = NETDEV_TX_BUSY; |
---|
| 3849 | +#else |
---|
| 3850 | + ret = -ENODEV; |
---|
| 3851 | +#endif /* CFI_CHECK */ |
---|
| 3852 | + } |
---|
| 3853 | + |
---|
| 3854 | +exit: |
---|
| 3855 | + return ret; |
---|
| 3856 | +} |
---|
| 3857 | + |
---|
| 3858 | +void |
---|
| 3859 | +dhd_bus_wakeup_work(dhd_pub_t *dhdp) |
---|
| 3860 | +{ |
---|
| 3861 | + struct dhd_rx_tx_work *rx_work; |
---|
| 3862 | + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
| 3863 | + |
---|
| 3864 | + rx_work = kmalloc(sizeof(*rx_work), GFP_ATOMIC); |
---|
| 3865 | + if (!rx_work) { |
---|
| 3866 | + DHD_ERROR(("%s: start_rx_work alloc error. \n", __FUNCTION__)); |
---|
| 3867 | + return; |
---|
| 3868 | + } |
---|
| 3869 | + |
---|
| 3870 | + INIT_WORK(&rx_work->work, dhd_rx_wq_wakeup); |
---|
| 3871 | + rx_work->pub = dhdp; |
---|
| 3872 | + queue_work(dhd->rx_wq, &rx_work->work); |
---|
| 3873 | + |
---|
| 3874 | +} |
---|
| 3875 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
| 3876 | + |
---|
| 3877 | +static void |
---|
| 3878 | +__dhd_txflowcontrol(dhd_pub_t *dhdp, struct net_device *net, bool state) |
---|
| 3879 | +{ |
---|
| 3880 | + |
---|
| 3881 | + if ((state == ON) && (dhdp->txoff == FALSE)) { |
---|
| 3882 | + netif_stop_queue(net); |
---|
| 3883 | + dhd_prot_update_pktid_txq_stop_cnt(dhdp); |
---|
| 3884 | + } else if (state == ON) { |
---|
| 3885 | + DHD_ERROR(("%s: Netif Queue has already stopped\n", __FUNCTION__)); |
---|
| 3886 | + } |
---|
| 3887 | + if ((state == OFF) && (dhdp->txoff == TRUE)) { |
---|
| 3888 | + netif_wake_queue(net); |
---|
| 3889 | + dhd_prot_update_pktid_txq_start_cnt(dhdp); |
---|
| 3890 | + } else if (state == OFF) { |
---|
| 3891 | + DHD_ERROR(("%s: Netif Queue has already started\n", __FUNCTION__)); |
---|
| 3892 | + } |
---|
| 3893 | +} |
---|
4588 | 3894 | |
---|
4589 | 3895 | void |
---|
4590 | 3896 | dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool state) |
---|
.. | .. |
---|
4602 | 3908 | if ((dhdp->dequeue_prec_map == 1 << PRIO_8021D_NC) && state == ON) { |
---|
4603 | 3909 | return; |
---|
4604 | 3910 | } |
---|
4605 | | -#endif |
---|
| 3911 | +#endif // endif |
---|
4606 | 3912 | |
---|
4607 | 3913 | if (ifidx == ALL_INTERFACES) { |
---|
4608 | | - /* Flow control on all active interfaces */ |
---|
4609 | | - dhdp->txoff = state; |
---|
4610 | 3914 | for (i = 0; i < DHD_MAX_IFS; i++) { |
---|
4611 | 3915 | if (dhd->iflist[i]) { |
---|
4612 | 3916 | net = dhd->iflist[i]->net; |
---|
4613 | | - if (state == ON) |
---|
4614 | | - netif_stop_queue(net); |
---|
4615 | | - else |
---|
4616 | | - netif_wake_queue(net); |
---|
| 3917 | + __dhd_txflowcontrol(dhdp, net, state); |
---|
4617 | 3918 | } |
---|
4618 | 3919 | } |
---|
4619 | 3920 | } else { |
---|
4620 | 3921 | if (dhd->iflist[ifidx]) { |
---|
4621 | 3922 | net = dhd->iflist[ifidx]->net; |
---|
4622 | | - if (state == ON) |
---|
4623 | | - netif_stop_queue(net); |
---|
4624 | | - else |
---|
4625 | | - netif_wake_queue(net); |
---|
| 3923 | + __dhd_txflowcontrol(dhdp, net, state); |
---|
4626 | 3924 | } |
---|
4627 | 3925 | } |
---|
4628 | | -} |
---|
4629 | | - |
---|
4630 | | -#ifdef DHD_RX_DUMP |
---|
4631 | | -typedef struct { |
---|
4632 | | - uint16 type; |
---|
4633 | | - const char *str; |
---|
4634 | | -} PKTTYPE_INFO; |
---|
4635 | | - |
---|
4636 | | -static const PKTTYPE_INFO packet_type_info[] = |
---|
4637 | | -{ |
---|
4638 | | - { ETHER_TYPE_IP, "IP" }, |
---|
4639 | | - { ETHER_TYPE_ARP, "ARP" }, |
---|
4640 | | - { ETHER_TYPE_BRCM, "BRCM" }, |
---|
4641 | | - { ETHER_TYPE_802_1X, "802.1X" }, |
---|
4642 | | - { ETHER_TYPE_WAI, "WAPI" }, |
---|
4643 | | - { 0, ""} |
---|
4644 | | -}; |
---|
4645 | | - |
---|
4646 | | -static const char *_get_packet_type_str(uint16 type) |
---|
4647 | | -{ |
---|
4648 | | - int i; |
---|
4649 | | - int n = sizeof(packet_type_info)/sizeof(packet_type_info[1]) - 1; |
---|
4650 | | - |
---|
4651 | | - for (i = 0; i < n; i++) { |
---|
4652 | | - if (packet_type_info[i].type == type) |
---|
4653 | | - return packet_type_info[i].str; |
---|
4654 | | - } |
---|
4655 | | - |
---|
4656 | | - return packet_type_info[n].str; |
---|
4657 | | -} |
---|
4658 | | -#endif /* DHD_RX_DUMP */ |
---|
4659 | | - |
---|
4660 | | - |
---|
4661 | | -#ifdef DHD_WMF |
---|
4662 | | -bool |
---|
4663 | | -dhd_is_rxthread_enabled(dhd_pub_t *dhdp) |
---|
4664 | | -{ |
---|
4665 | | - dhd_info_t *dhd = dhdp->info; |
---|
4666 | | - |
---|
4667 | | - return dhd->rxthread_enabled; |
---|
4668 | | -} |
---|
4669 | | -#endif /* DHD_WMF */ |
---|
4670 | | - |
---|
4671 | | -void |
---|
4672 | | -dhd_rx_mon_pkt(dhd_pub_t *dhdp, void *pkt, int ifidx) |
---|
4673 | | -{ |
---|
4674 | | - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
4675 | | - struct sk_buff *skb; |
---|
4676 | | - |
---|
4677 | | - skb = PKTTONATIVE(dhdp->osh, pkt); |
---|
4678 | | - |
---|
4679 | | - if (dhd->monitor_type && dhd->monitor_dev) |
---|
4680 | | - skb->dev = dhd->monitor_dev; |
---|
4681 | | - else { |
---|
4682 | | - PKTFREE(dhdp->osh, pkt, FALSE); |
---|
4683 | | - return; |
---|
4684 | | - } |
---|
4685 | | - |
---|
4686 | | - skb->protocol = eth_type_trans(skb, skb->dev); |
---|
4687 | | - |
---|
4688 | | - if (in_interrupt()) { |
---|
4689 | | - bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, |
---|
4690 | | - __FUNCTION__, __LINE__); |
---|
4691 | | - DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
4692 | | - netif_rx(skb); |
---|
4693 | | - DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
4694 | | - } else { |
---|
4695 | | - /* If the receive is not processed inside an ISR, |
---|
4696 | | - * the softirqd must be woken explicitly to service |
---|
4697 | | - * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled |
---|
4698 | | - * by netif_rx_ni(), but in earlier kernels, we need |
---|
4699 | | - * to do it manually. |
---|
4700 | | - */ |
---|
4701 | | - bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, |
---|
4702 | | - __FUNCTION__, __LINE__); |
---|
4703 | | - |
---|
4704 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) |
---|
4705 | | - DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
4706 | | - netif_rx_ni(skb); |
---|
4707 | | - DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
4708 | | -#else |
---|
4709 | | - ulong flags; |
---|
4710 | | - DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
4711 | | - netif_rx(skb); |
---|
4712 | | - DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
4713 | | - local_irq_save(flags); |
---|
4714 | | - RAISE_RX_SOFTIRQ(); |
---|
4715 | | - local_irq_restore(flags); |
---|
4716 | | -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ |
---|
4717 | | - } |
---|
| 3926 | + dhdp->txoff = state; |
---|
4718 | 3927 | } |
---|
4719 | 3928 | |
---|
4720 | 3929 | #ifdef DHD_MCAST_REGEN |
---|
.. | .. |
---|
4753 | 3962 | } |
---|
4754 | 3963 | #endif /* MCAST_REGEN */ |
---|
4755 | 3964 | |
---|
| 3965 | +#ifdef SHOW_LOGTRACE |
---|
| 3966 | +static void |
---|
| 3967 | +dhd_netif_rx_ni(struct sk_buff * skb) |
---|
| 3968 | +{ |
---|
| 3969 | + /* Do not call netif_recieve_skb as this workqueue scheduler is |
---|
| 3970 | + * not from NAPI Also as we are not in INTR context, do not call |
---|
| 3971 | + * netif_rx, instead call netif_rx_ni (for kerenl >= 2.6) which |
---|
| 3972 | + * does netif_rx, disables irq, raise NET_IF_RX softirq and |
---|
| 3973 | + * enables interrupts back |
---|
| 3974 | + */ |
---|
| 3975 | + netif_rx_ni(skb); |
---|
| 3976 | +} |
---|
| 3977 | + |
---|
| 3978 | +static int |
---|
| 3979 | +dhd_event_logtrace_pkt_process(dhd_pub_t *dhdp, struct sk_buff * skb) |
---|
| 3980 | +{ |
---|
| 3981 | + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
| 3982 | + int ret = BCME_OK; |
---|
| 3983 | + uint datalen; |
---|
| 3984 | + bcm_event_msg_u_t evu; |
---|
| 3985 | + void *data = NULL; |
---|
| 3986 | + void *pktdata = NULL; |
---|
| 3987 | + bcm_event_t *pvt_data; |
---|
| 3988 | + uint pktlen; |
---|
| 3989 | + |
---|
| 3990 | + DHD_TRACE(("%s:Enter\n", __FUNCTION__)); |
---|
| 3991 | + |
---|
| 3992 | + /* In dhd_rx_frame, header is stripped using skb_pull |
---|
| 3993 | + * of size ETH_HLEN, so adjust pktlen accordingly |
---|
| 3994 | + */ |
---|
| 3995 | + pktlen = skb->len + ETH_HLEN; |
---|
| 3996 | + |
---|
| 3997 | + pktdata = (void *)skb_mac_header(skb); |
---|
| 3998 | + ret = wl_host_event_get_data(pktdata, pktlen, &evu); |
---|
| 3999 | + |
---|
| 4000 | + if (ret != BCME_OK) { |
---|
| 4001 | + DHD_ERROR(("%s: wl_host_event_get_data err = %d\n", |
---|
| 4002 | + __FUNCTION__, ret)); |
---|
| 4003 | + goto exit; |
---|
| 4004 | + } |
---|
| 4005 | + |
---|
| 4006 | + datalen = ntoh32(evu.event.datalen); |
---|
| 4007 | + |
---|
| 4008 | + pvt_data = (bcm_event_t *)pktdata; |
---|
| 4009 | + data = &pvt_data[1]; |
---|
| 4010 | + |
---|
| 4011 | + dhd_dbg_trace_evnt_handler(dhdp, data, &dhd->event_data, datalen); |
---|
| 4012 | + |
---|
| 4013 | +exit: |
---|
| 4014 | + return ret; |
---|
| 4015 | +} |
---|
| 4016 | + |
---|
| 4017 | +/* |
---|
| 4018 | + * dhd_event_logtrace_process_items processes |
---|
| 4019 | + * each skb from evt_trace_queue. |
---|
| 4020 | + * Returns TRUE if more packets to be processed |
---|
| 4021 | + * else returns FALSE |
---|
| 4022 | + */ |
---|
| 4023 | + |
---|
| 4024 | +static int |
---|
| 4025 | +dhd_event_logtrace_process_items(dhd_info_t *dhd) |
---|
| 4026 | +{ |
---|
| 4027 | + dhd_pub_t *dhdp; |
---|
| 4028 | + struct sk_buff *skb; |
---|
| 4029 | + uint32 qlen; |
---|
| 4030 | + uint32 process_len; |
---|
| 4031 | + |
---|
| 4032 | + if (!dhd) { |
---|
| 4033 | + DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); |
---|
| 4034 | + return 0; |
---|
| 4035 | + } |
---|
| 4036 | + |
---|
| 4037 | + dhdp = &dhd->pub; |
---|
| 4038 | + |
---|
| 4039 | + if (!dhdp) { |
---|
| 4040 | + DHD_ERROR(("%s: dhd pub is null \n", __FUNCTION__)); |
---|
| 4041 | + return 0; |
---|
| 4042 | + } |
---|
| 4043 | + |
---|
| 4044 | + qlen = skb_queue_len(&dhd->evt_trace_queue); |
---|
| 4045 | + process_len = MIN(qlen, DHD_EVENT_LOGTRACE_BOUND); |
---|
| 4046 | + |
---|
| 4047 | + /* Run while loop till bound is reached or skb queue is empty */ |
---|
| 4048 | + while (process_len--) { |
---|
| 4049 | + int ifid = 0; |
---|
| 4050 | + skb = skb_dequeue(&dhd->evt_trace_queue); |
---|
| 4051 | + if (skb == NULL) { |
---|
| 4052 | + DHD_ERROR(("%s: skb is NULL, which is not valid case\n", |
---|
| 4053 | + __FUNCTION__)); |
---|
| 4054 | + break; |
---|
| 4055 | + } |
---|
| 4056 | + BCM_REFERENCE(ifid); |
---|
| 4057 | +#ifdef PCIE_FULL_DONGLE |
---|
| 4058 | + /* Check if pkt is from INFO ring or WLC_E_TRACE */ |
---|
| 4059 | + ifid = DHD_PKTTAG_IFID((dhd_pkttag_fr_t *)PKTTAG(skb)); |
---|
| 4060 | + if (ifid == DHD_DUMMY_INFO_IF) { |
---|
| 4061 | + /* Process logtrace from info rings */ |
---|
| 4062 | + dhd_event_logtrace_infobuf_pkt_process(dhdp, skb, &dhd->event_data); |
---|
| 4063 | + } else |
---|
| 4064 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 4065 | + { |
---|
| 4066 | + /* Processing WLC_E_TRACE case OR non PCIE PCIE_FULL_DONGLE case */ |
---|
| 4067 | + dhd_event_logtrace_pkt_process(dhdp, skb); |
---|
| 4068 | + } |
---|
| 4069 | + |
---|
| 4070 | + /* Dummy sleep so that scheduler kicks in after processing any logprints */ |
---|
| 4071 | + OSL_SLEEP(0); |
---|
| 4072 | + |
---|
| 4073 | + /* Send packet up if logtrace_pkt_sendup is TRUE */ |
---|
| 4074 | + if (dhdp->logtrace_pkt_sendup) { |
---|
| 4075 | +#ifdef DHD_USE_STATIC_CTRLBUF |
---|
| 4076 | + /* If bufs are allocated via static buf pool |
---|
| 4077 | + * and logtrace_pkt_sendup enabled, make a copy, |
---|
| 4078 | + * free the local one and send the copy up. |
---|
| 4079 | + */ |
---|
| 4080 | + void *npkt = PKTDUP(dhdp->osh, skb); |
---|
| 4081 | + /* Clone event and send it up */ |
---|
| 4082 | + PKTFREE_STATIC(dhdp->osh, skb, FALSE); |
---|
| 4083 | + if (npkt) { |
---|
| 4084 | + skb = npkt; |
---|
| 4085 | + } else { |
---|
| 4086 | + DHD_ERROR(("skb clone failed. dropping logtrace pkt.\n")); |
---|
| 4087 | + /* Packet is already freed, go to next packet */ |
---|
| 4088 | + continue; |
---|
| 4089 | + } |
---|
| 4090 | +#endif /* DHD_USE_STATIC_CTRLBUF */ |
---|
| 4091 | +#ifdef PCIE_FULL_DONGLE |
---|
| 4092 | + /* For infobuf packets as if is DHD_DUMMY_INFO_IF, |
---|
| 4093 | + * to send skb to network layer, assign skb->dev with |
---|
| 4094 | + * Primary interface n/w device |
---|
| 4095 | + */ |
---|
| 4096 | + if (ifid == DHD_DUMMY_INFO_IF) { |
---|
| 4097 | + skb = PKTTONATIVE(dhdp->osh, skb); |
---|
| 4098 | + skb->dev = dhd->iflist[0]->net; |
---|
| 4099 | + } |
---|
| 4100 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 4101 | + /* Send pkt UP */ |
---|
| 4102 | + dhd_netif_rx_ni(skb); |
---|
| 4103 | + } else { |
---|
| 4104 | + /* Don't send up. Free up the packet. */ |
---|
| 4105 | +#ifdef DHD_USE_STATIC_CTRLBUF |
---|
| 4106 | + PKTFREE_STATIC(dhdp->osh, skb, FALSE); |
---|
| 4107 | +#else |
---|
| 4108 | + PKTFREE(dhdp->osh, skb, FALSE); |
---|
| 4109 | +#endif /* DHD_USE_STATIC_CTRLBUF */ |
---|
| 4110 | + } |
---|
| 4111 | + } |
---|
| 4112 | + |
---|
| 4113 | + /* Reschedule if more packets to be processed */ |
---|
| 4114 | + return (qlen >= DHD_EVENT_LOGTRACE_BOUND); |
---|
| 4115 | +} |
---|
| 4116 | + |
---|
| 4117 | +#ifdef DHD_USE_KTHREAD_FOR_LOGTRACE |
---|
| 4118 | +static int |
---|
| 4119 | +dhd_logtrace_thread(void *data) |
---|
| 4120 | +{ |
---|
| 4121 | + tsk_ctl_t *tsk = (tsk_ctl_t *)data; |
---|
| 4122 | + dhd_info_t *dhd = (dhd_info_t *)tsk->parent; |
---|
| 4123 | + dhd_pub_t *dhdp = (dhd_pub_t *)&dhd->pub; |
---|
| 4124 | + int ret; |
---|
| 4125 | + |
---|
| 4126 | + while (1) { |
---|
| 4127 | + dhdp->logtrace_thr_ts.entry_time = OSL_LOCALTIME_NS(); |
---|
| 4128 | + if (!binary_sema_down(tsk)) { |
---|
| 4129 | + dhdp->logtrace_thr_ts.sem_down_time = OSL_LOCALTIME_NS(); |
---|
| 4130 | + SMP_RD_BARRIER_DEPENDS(); |
---|
| 4131 | + if (dhd->pub.dongle_reset == FALSE) { |
---|
| 4132 | + do { |
---|
| 4133 | + /* Check terminated before processing the items */ |
---|
| 4134 | + if (tsk->terminated) { |
---|
| 4135 | + DHD_ERROR(("%s: task terminated\n", __FUNCTION__)); |
---|
| 4136 | + goto exit; |
---|
| 4137 | + } |
---|
| 4138 | +#ifdef EWP_EDL |
---|
| 4139 | + /* check if EDL is being used */ |
---|
| 4140 | + if (dhd->pub.dongle_edl_support) { |
---|
| 4141 | + ret = dhd_prot_process_edl_complete(&dhd->pub, |
---|
| 4142 | + &dhd->event_data); |
---|
| 4143 | + } else { |
---|
| 4144 | + ret = dhd_event_logtrace_process_items(dhd); |
---|
| 4145 | + } |
---|
| 4146 | +#else |
---|
| 4147 | + ret = dhd_event_logtrace_process_items(dhd); |
---|
| 4148 | +#endif /* EWP_EDL */ |
---|
| 4149 | + /* if ret > 0, bound has reached so to be fair to other |
---|
| 4150 | + * processes need to yield the scheduler. |
---|
| 4151 | + * The comment above yield()'s definition says: |
---|
| 4152 | + * If you want to use yield() to wait for something, |
---|
| 4153 | + * use wait_event(). |
---|
| 4154 | + * If you want to use yield() to be 'nice' for others, |
---|
| 4155 | + * use cond_resched(). |
---|
| 4156 | + * If you still want to use yield(), do not! |
---|
| 4157 | + */ |
---|
| 4158 | + if (ret > 0) { |
---|
| 4159 | + cond_resched(); |
---|
| 4160 | + OSL_SLEEP(DHD_EVENT_LOGTRACE_RESCHEDULE_DELAY_MS); |
---|
| 4161 | + } else if (ret < 0) { |
---|
| 4162 | + DHD_ERROR(("%s: ERROR should not reach here\n", |
---|
| 4163 | + __FUNCTION__)); |
---|
| 4164 | + } |
---|
| 4165 | + } while (ret > 0); |
---|
| 4166 | + } |
---|
| 4167 | + if (tsk->flush_ind) { |
---|
| 4168 | + DHD_ERROR(("%s: flushed\n", __FUNCTION__)); |
---|
| 4169 | + dhdp->logtrace_thr_ts.flush_time = OSL_LOCALTIME_NS(); |
---|
| 4170 | + tsk->flush_ind = 0; |
---|
| 4171 | + complete(&tsk->flushed); |
---|
| 4172 | + } |
---|
| 4173 | + } else { |
---|
| 4174 | + DHD_ERROR(("%s: unexpted break\n", __FUNCTION__)); |
---|
| 4175 | + dhdp->logtrace_thr_ts.unexpected_break_time = OSL_LOCALTIME_NS(); |
---|
| 4176 | + break; |
---|
| 4177 | + } |
---|
| 4178 | + } |
---|
| 4179 | +exit: |
---|
| 4180 | + complete_and_exit(&tsk->completed, 0); |
---|
| 4181 | + dhdp->logtrace_thr_ts.complete_time = OSL_LOCALTIME_NS(); |
---|
| 4182 | +} |
---|
| 4183 | +#else |
---|
| 4184 | +static void |
---|
| 4185 | +dhd_event_logtrace_process(struct work_struct * work) |
---|
| 4186 | +{ |
---|
| 4187 | + int ret = 0; |
---|
| 4188 | +/* Ignore compiler warnings due to -Werror=cast-qual */ |
---|
| 4189 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 4190 | +#pragma GCC diagnostic push |
---|
| 4191 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 4192 | +#endif // endif |
---|
| 4193 | + struct delayed_work *dw = to_delayed_work(work); |
---|
| 4194 | + struct dhd_info *dhd = |
---|
| 4195 | + container_of(dw, struct dhd_info, event_log_dispatcher_work); |
---|
| 4196 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 4197 | +#pragma GCC diagnostic pop |
---|
| 4198 | +#endif // endif |
---|
| 4199 | +#ifdef EWP_EDL |
---|
| 4200 | + if (dhd->pub.dongle_edl_support) { |
---|
| 4201 | + ret = dhd_prot_process_edl_complete(&dhd->pub, &dhd->event_data); |
---|
| 4202 | + } else { |
---|
| 4203 | + ret = dhd_event_logtrace_process_items(dhd); |
---|
| 4204 | + } |
---|
| 4205 | +#else |
---|
| 4206 | + ret = dhd_event_logtrace_process_items(dhd); |
---|
| 4207 | +#endif /* EWP_EDL */ |
---|
| 4208 | + |
---|
| 4209 | + if (ret > 0) { |
---|
| 4210 | + schedule_delayed_work(&(dhd)->event_log_dispatcher_work, |
---|
| 4211 | + msecs_to_jiffies(DHD_EVENT_LOGTRACE_RESCHEDULE_DELAY_MS)); |
---|
| 4212 | + } |
---|
| 4213 | + |
---|
| 4214 | + return; |
---|
| 4215 | +} |
---|
| 4216 | +#endif /* DHD_USE_KTHREAD_FOR_LOGTRACE */ |
---|
| 4217 | + |
---|
| 4218 | +void |
---|
| 4219 | +dhd_schedule_logtrace(void *dhd_info) |
---|
| 4220 | +{ |
---|
| 4221 | + dhd_info_t *dhd = (dhd_info_t *)dhd_info; |
---|
| 4222 | + |
---|
| 4223 | +#ifdef DHD_USE_KTHREAD_FOR_LOGTRACE |
---|
| 4224 | + if (dhd->thr_logtrace_ctl.thr_pid >= 0) { |
---|
| 4225 | + binary_sema_up(&dhd->thr_logtrace_ctl); |
---|
| 4226 | + } else { |
---|
| 4227 | + DHD_ERROR(("%s: thr_logtrace_ctl(%ld) not inited\n", __FUNCTION__, |
---|
| 4228 | + dhd->thr_logtrace_ctl.thr_pid)); |
---|
| 4229 | + } |
---|
| 4230 | +#else |
---|
| 4231 | + schedule_delayed_work(&dhd->event_log_dispatcher_work, 0); |
---|
| 4232 | +#endif /* DHD_USE_KTHREAD_FOR_LOGTRACE */ |
---|
| 4233 | + return; |
---|
| 4234 | +} |
---|
| 4235 | + |
---|
| 4236 | +void |
---|
| 4237 | +dhd_cancel_logtrace_process_sync(dhd_info_t *dhd) |
---|
| 4238 | +{ |
---|
| 4239 | +#ifdef DHD_USE_KTHREAD_FOR_LOGTRACE |
---|
| 4240 | + if (dhd->thr_logtrace_ctl.thr_pid >= 0) { |
---|
| 4241 | + PROC_STOP_USING_BINARY_SEMA(&dhd->thr_logtrace_ctl); |
---|
| 4242 | + } else { |
---|
| 4243 | + DHD_ERROR(("%s: thr_logtrace_ctl(%ld) not inited\n", __FUNCTION__, |
---|
| 4244 | + dhd->thr_logtrace_ctl.thr_pid)); |
---|
| 4245 | + } |
---|
| 4246 | +#else |
---|
| 4247 | + cancel_delayed_work_sync(&dhd->event_log_dispatcher_work); |
---|
| 4248 | +#endif /* DHD_USE_KTHREAD_FOR_LOGTRACE */ |
---|
| 4249 | +} |
---|
| 4250 | + |
---|
| 4251 | +void |
---|
| 4252 | +dhd_flush_logtrace_process(dhd_info_t *dhd) |
---|
| 4253 | +{ |
---|
| 4254 | +#ifdef DHD_USE_KTHREAD_FOR_LOGTRACE |
---|
| 4255 | + if (dhd->thr_logtrace_ctl.thr_pid >= 0) { |
---|
| 4256 | + PROC_FLUSH_USING_BINARY_SEMA(&dhd->thr_logtrace_ctl); |
---|
| 4257 | + } else { |
---|
| 4258 | + DHD_ERROR(("%s: thr_logtrace_ctl(%ld) not inited\n", __FUNCTION__, |
---|
| 4259 | + dhd->thr_logtrace_ctl.thr_pid)); |
---|
| 4260 | + } |
---|
| 4261 | +#else |
---|
| 4262 | + flush_delayed_work(&dhd->event_log_dispatcher_work); |
---|
| 4263 | +#endif /* DHD_USE_KTHREAD_FOR_LOGTRACE */ |
---|
| 4264 | +} |
---|
| 4265 | + |
---|
| 4266 | +int |
---|
| 4267 | +dhd_init_logtrace_process(dhd_info_t *dhd) |
---|
| 4268 | +{ |
---|
| 4269 | +#ifdef DHD_USE_KTHREAD_FOR_LOGTRACE |
---|
| 4270 | + dhd->thr_logtrace_ctl.thr_pid = DHD_PID_KT_INVALID; |
---|
| 4271 | + PROC_START(dhd_logtrace_thread, dhd, &dhd->thr_logtrace_ctl, 0, "dhd_logtrace_thread"); |
---|
| 4272 | + if (dhd->thr_logtrace_ctl.thr_pid < 0) { |
---|
| 4273 | + DHD_ERROR(("%s: init logtrace process failed\n", __FUNCTION__)); |
---|
| 4274 | + return BCME_ERROR; |
---|
| 4275 | + } else { |
---|
| 4276 | + DHD_ERROR(("%s: thr_logtrace_ctl(%ld) succedded\n", __FUNCTION__, |
---|
| 4277 | + dhd->thr_logtrace_ctl.thr_pid)); |
---|
| 4278 | + } |
---|
| 4279 | +#else |
---|
| 4280 | + INIT_DELAYED_WORK(&dhd->event_log_dispatcher_work, dhd_event_logtrace_process); |
---|
| 4281 | +#endif /* DHD_USE_KTHREAD_FOR_LOGTRACE */ |
---|
| 4282 | + return BCME_OK; |
---|
| 4283 | +} |
---|
| 4284 | + |
---|
| 4285 | +int |
---|
| 4286 | +dhd_reinit_logtrace_process(dhd_info_t *dhd) |
---|
| 4287 | +{ |
---|
| 4288 | +#ifdef DHD_USE_KTHREAD_FOR_LOGTRACE |
---|
| 4289 | + /* Re-init only if PROC_STOP from dhd_stop was called |
---|
| 4290 | + * which can be checked via thr_pid |
---|
| 4291 | + */ |
---|
| 4292 | + if (dhd->thr_logtrace_ctl.thr_pid < 0) { |
---|
| 4293 | + PROC_START(dhd_logtrace_thread, dhd, &dhd->thr_logtrace_ctl, |
---|
| 4294 | + 0, "dhd_logtrace_thread"); |
---|
| 4295 | + if (dhd->thr_logtrace_ctl.thr_pid < 0) { |
---|
| 4296 | + DHD_ERROR(("%s: reinit logtrace process failed\n", __FUNCTION__)); |
---|
| 4297 | + return BCME_ERROR; |
---|
| 4298 | + } else { |
---|
| 4299 | + DHD_ERROR(("%s: thr_logtrace_ctl(%ld) succedded\n", __FUNCTION__, |
---|
| 4300 | + dhd->thr_logtrace_ctl.thr_pid)); |
---|
| 4301 | + } |
---|
| 4302 | + } |
---|
| 4303 | +#else |
---|
| 4304 | + /* No need to re-init for WQ as calcel_delayed_work_sync will |
---|
| 4305 | + * will not delete the WQ |
---|
| 4306 | + */ |
---|
| 4307 | +#endif /* DHD_USE_KTHREAD_FOR_LOGTRACE */ |
---|
| 4308 | + return BCME_OK; |
---|
| 4309 | +} |
---|
| 4310 | + |
---|
| 4311 | +void |
---|
| 4312 | +dhd_event_logtrace_enqueue(dhd_pub_t *dhdp, int ifidx, void *pktbuf) |
---|
| 4313 | +{ |
---|
| 4314 | + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
| 4315 | + |
---|
| 4316 | +#ifdef PCIE_FULL_DONGLE |
---|
| 4317 | + /* Add ifidx in the PKTTAG */ |
---|
| 4318 | + DHD_PKTTAG_SET_IFID((dhd_pkttag_fr_t *)PKTTAG(pktbuf), ifidx); |
---|
| 4319 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 4320 | + skb_queue_tail(&dhd->evt_trace_queue, pktbuf); |
---|
| 4321 | + |
---|
| 4322 | + dhd_schedule_logtrace(dhd); |
---|
| 4323 | +} |
---|
| 4324 | + |
---|
| 4325 | +void |
---|
| 4326 | +dhd_event_logtrace_flush_queue(dhd_pub_t *dhdp) |
---|
| 4327 | +{ |
---|
| 4328 | + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
| 4329 | + struct sk_buff *skb; |
---|
| 4330 | + |
---|
| 4331 | + while ((skb = skb_dequeue(&dhd->evt_trace_queue)) != NULL) { |
---|
| 4332 | +#ifdef DHD_USE_STATIC_CTRLBUF |
---|
| 4333 | + PKTFREE_STATIC(dhdp->osh, skb, FALSE); |
---|
| 4334 | +#else |
---|
| 4335 | + PKTFREE(dhdp->osh, skb, FALSE); |
---|
| 4336 | +#endif /* DHD_USE_STATIC_CTRLBUF */ |
---|
| 4337 | + } |
---|
| 4338 | +} |
---|
| 4339 | + |
---|
| 4340 | +#ifdef BCMPCIE |
---|
| 4341 | +void |
---|
| 4342 | +dhd_sendup_info_buf(dhd_pub_t *dhdp, uint8 *msg) |
---|
| 4343 | +{ |
---|
| 4344 | + struct sk_buff *skb = NULL; |
---|
| 4345 | + uint32 pktsize = 0; |
---|
| 4346 | + void *pkt = NULL; |
---|
| 4347 | + info_buf_payload_hdr_t *infobuf = NULL; |
---|
| 4348 | + dhd_info_t *dhd = dhdp->info; |
---|
| 4349 | + uint8 *pktdata = NULL; |
---|
| 4350 | + |
---|
| 4351 | + if (!msg) |
---|
| 4352 | + return; |
---|
| 4353 | + |
---|
| 4354 | + /* msg = |infobuf_ver(u32)|info_buf_payload_hdr_t|msgtrace_hdr_t|<var len data>| */ |
---|
| 4355 | + infobuf = (info_buf_payload_hdr_t *)(msg + sizeof(uint32)); |
---|
| 4356 | + pktsize = (uint32)(ltoh16(infobuf->length) + sizeof(info_buf_payload_hdr_t) + |
---|
| 4357 | + sizeof(uint32)); |
---|
| 4358 | + pkt = PKTGET(dhdp->osh, pktsize, FALSE); |
---|
| 4359 | + if (!pkt) { |
---|
| 4360 | + DHD_ERROR(("%s: skb alloc failed ! not sending event log up.\n", __FUNCTION__)); |
---|
| 4361 | + } else { |
---|
| 4362 | + PKTSETLEN(dhdp->osh, pkt, pktsize); |
---|
| 4363 | + pktdata = PKTDATA(dhdp->osh, pkt); |
---|
| 4364 | + memcpy(pktdata, msg, pktsize); |
---|
| 4365 | + /* For infobuf packets assign skb->dev with |
---|
| 4366 | + * Primary interface n/w device |
---|
| 4367 | + */ |
---|
| 4368 | + skb = PKTTONATIVE(dhdp->osh, pkt); |
---|
| 4369 | + skb->dev = dhd->iflist[0]->net; |
---|
| 4370 | + /* Send pkt UP */ |
---|
| 4371 | + dhd_netif_rx_ni(skb); |
---|
| 4372 | + } |
---|
| 4373 | +} |
---|
| 4374 | +#endif /* BCMPCIE */ |
---|
| 4375 | +#endif /* SHOW_LOGTRACE */ |
---|
| 4376 | + |
---|
4756 | 4377 | /** Called when a frame is received by the dongle on interface 'ifidx' */ |
---|
4757 | 4378 | void |
---|
4758 | 4379 | dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) |
---|
.. | .. |
---|
4765 | 4386 | int i; |
---|
4766 | 4387 | dhd_if_t *ifp; |
---|
4767 | 4388 | wl_event_msg_t event; |
---|
| 4389 | +#if (defined(OEM_ANDROID) || defined(OEM_EMBEDDED_LINUX)) |
---|
4768 | 4390 | int tout_rx = 0; |
---|
4769 | 4391 | int tout_ctrl = 0; |
---|
| 4392 | +#endif /* OEM_ANDROID || OEM_EMBEDDED_LINUX */ |
---|
4770 | 4393 | void *skbhead = NULL; |
---|
4771 | 4394 | void *skbprev = NULL; |
---|
4772 | 4395 | uint16 protocol; |
---|
4773 | | -#if defined(DHD_RX_DUMP) || defined(DHD_8021X_DUMP) |
---|
4774 | | - char *dump_data; |
---|
4775 | | -#endif /* DHD_RX_DUMP || DHD_8021X_DUMP */ |
---|
| 4396 | + unsigned char *dump_data; |
---|
4776 | 4397 | #ifdef DHD_MCAST_REGEN |
---|
4777 | 4398 | uint8 interface_role; |
---|
4778 | 4399 | if_flow_lkup_t *if_flow_lkup; |
---|
4779 | 4400 | unsigned long flags; |
---|
4780 | | -#endif |
---|
| 4401 | +#endif // endif |
---|
| 4402 | +#ifdef DHD_WAKE_STATUS |
---|
| 4403 | + int pkt_wake = 0; |
---|
| 4404 | + wake_counts_t *wcp = NULL; |
---|
| 4405 | +#endif /* DHD_WAKE_STATUS */ |
---|
4781 | 4406 | |
---|
4782 | 4407 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
| 4408 | + BCM_REFERENCE(dump_data); |
---|
4783 | 4409 | |
---|
4784 | 4410 | for (i = 0; pktbuf && i < numpkt; i++, pktbuf = pnext) { |
---|
4785 | 4411 | struct ether_header *eh; |
---|
.. | .. |
---|
4787 | 4413 | pnext = PKTNEXT(dhdp->osh, pktbuf); |
---|
4788 | 4414 | PKTSETNEXT(dhdp->osh, pktbuf, NULL); |
---|
4789 | 4415 | |
---|
| 4416 | + /* info ring "debug" data, which is not a 802.3 frame, is sent/hacked with a |
---|
| 4417 | + * special ifidx of DHD_DUMMY_INFO_IF. This is just internal to dhd to get the data |
---|
| 4418 | + * from dhd_msgbuf.c:dhd_prot_infobuf_cmplt_process() to here (dhd_rx_frame). |
---|
| 4419 | + */ |
---|
| 4420 | + if (ifidx == DHD_DUMMY_INFO_IF) { |
---|
| 4421 | + /* Event msg printing is called from dhd_rx_frame which is in Tasklet |
---|
| 4422 | + * context in case of PCIe FD, in case of other bus this will be from |
---|
| 4423 | + * DPC context. If we get bunch of events from Dongle then printing all |
---|
| 4424 | + * of them from Tasklet/DPC context that too in data path is costly. |
---|
| 4425 | + * Also in the new Dongle SW(4359, 4355 onwards) console prints too come as |
---|
| 4426 | + * events with type WLC_E_TRACE. |
---|
| 4427 | + * We'll print this console logs from the WorkQueue context by enqueing SKB |
---|
| 4428 | + * here and Dequeuing will be done in WorkQueue and will be freed only if |
---|
| 4429 | + * logtrace_pkt_sendup is TRUE |
---|
| 4430 | + */ |
---|
| 4431 | +#ifdef SHOW_LOGTRACE |
---|
| 4432 | + dhd_event_logtrace_enqueue(dhdp, ifidx, pktbuf); |
---|
| 4433 | +#else /* !SHOW_LOGTRACE */ |
---|
| 4434 | + /* If SHOW_LOGTRACE not defined and ifidx is DHD_DUMMY_INFO_IF, |
---|
| 4435 | + * free the PKT here itself |
---|
| 4436 | + */ |
---|
| 4437 | +#ifdef DHD_USE_STATIC_CTRLBUF |
---|
| 4438 | + PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); |
---|
| 4439 | +#else |
---|
| 4440 | + PKTFREE(dhdp->osh, pktbuf, FALSE); |
---|
| 4441 | +#endif /* DHD_USE_STATIC_CTRLBUF */ |
---|
| 4442 | +#endif /* SHOW_LOGTRACE */ |
---|
| 4443 | + continue; |
---|
| 4444 | + } |
---|
| 4445 | +#ifdef DHD_WAKE_STATUS |
---|
| 4446 | + pkt_wake = dhd_bus_get_bus_wake(dhdp); |
---|
| 4447 | + wcp = dhd_bus_get_wakecount(dhdp); |
---|
| 4448 | + if (wcp == NULL) { |
---|
| 4449 | + /* If wakeinfo count buffer is null do not update wake count values */ |
---|
| 4450 | + pkt_wake = 0; |
---|
| 4451 | + } |
---|
| 4452 | +#endif /* DHD_WAKE_STATUS */ |
---|
| 4453 | + |
---|
| 4454 | + eh = (struct ether_header *)PKTDATA(dhdp->osh, pktbuf); |
---|
| 4455 | + |
---|
| 4456 | + if (ifidx >= DHD_MAX_IFS) { |
---|
| 4457 | + DHD_ERROR(("%s: ifidx(%d) Out of bound. drop packet\n", |
---|
| 4458 | + __FUNCTION__, ifidx)); |
---|
| 4459 | + if (ntoh16(eh->ether_type) == ETHER_TYPE_BRCM) { |
---|
| 4460 | +#ifdef DHD_USE_STATIC_CTRLBUF |
---|
| 4461 | + PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); |
---|
| 4462 | +#else |
---|
| 4463 | + PKTFREE(dhdp->osh, pktbuf, FALSE); |
---|
| 4464 | +#endif /* DHD_USE_STATIC_CTRLBUF */ |
---|
| 4465 | + } else { |
---|
| 4466 | + PKTCFREE(dhdp->osh, pktbuf, FALSE); |
---|
| 4467 | + } |
---|
| 4468 | + continue; |
---|
| 4469 | + } |
---|
| 4470 | + |
---|
4790 | 4471 | ifp = dhd->iflist[ifidx]; |
---|
4791 | 4472 | if (ifp == NULL) { |
---|
4792 | 4473 | DHD_ERROR(("%s: ifp is NULL. drop packet\n", |
---|
4793 | 4474 | __FUNCTION__)); |
---|
4794 | | - PKTCFREE(dhdp->osh, pktbuf, FALSE); |
---|
| 4475 | + if (ntoh16(eh->ether_type) == ETHER_TYPE_BRCM) { |
---|
| 4476 | +#ifdef DHD_USE_STATIC_CTRLBUF |
---|
| 4477 | + PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); |
---|
| 4478 | +#else |
---|
| 4479 | + PKTFREE(dhdp->osh, pktbuf, FALSE); |
---|
| 4480 | +#endif /* DHD_USE_STATIC_CTRLBUF */ |
---|
| 4481 | + } else { |
---|
| 4482 | + PKTCFREE(dhdp->osh, pktbuf, FALSE); |
---|
| 4483 | + } |
---|
4795 | 4484 | continue; |
---|
4796 | 4485 | } |
---|
4797 | | - |
---|
4798 | | - eh = (struct ether_header *)PKTDATA(dhdp->osh, pktbuf); |
---|
4799 | 4486 | |
---|
4800 | 4487 | /* Dropping only data packets before registering net device to avoid kernel panic */ |
---|
4801 | 4488 | #ifndef PROP_TXSTATUS_VSDB |
---|
4802 | 4489 | if ((!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) && |
---|
4803 | | - (ntoh16(eh->ether_type) != ETHER_TYPE_BRCM)) { |
---|
| 4490 | + (ntoh16(eh->ether_type) != ETHER_TYPE_BRCM)) |
---|
4804 | 4491 | #else |
---|
4805 | 4492 | if ((!ifp->net || ifp->net->reg_state != NETREG_REGISTERED || !dhd->pub.up) && |
---|
4806 | | - (ntoh16(eh->ether_type) != ETHER_TYPE_BRCM)) { |
---|
| 4493 | + (ntoh16(eh->ether_type) != ETHER_TYPE_BRCM)) |
---|
4807 | 4494 | #endif /* PROP_TXSTATUS_VSDB */ |
---|
| 4495 | + { |
---|
4808 | 4496 | DHD_ERROR(("%s: net device is NOT registered yet. drop packet\n", |
---|
4809 | 4497 | __FUNCTION__)); |
---|
4810 | 4498 | PKTCFREE(dhdp->osh, pktbuf, FALSE); |
---|
4811 | 4499 | continue; |
---|
4812 | 4500 | } |
---|
4813 | | - |
---|
4814 | 4501 | |
---|
4815 | 4502 | #ifdef PROP_TXSTATUS |
---|
4816 | 4503 | if (dhd_wlfc_is_header_only_pkt(dhdp, pktbuf)) { |
---|
.. | .. |
---|
4821 | 4508 | PKTCFREE(dhdp->osh, pktbuf, FALSE); |
---|
4822 | 4509 | continue; |
---|
4823 | 4510 | } |
---|
4824 | | -#endif |
---|
| 4511 | +#endif // endif |
---|
4825 | 4512 | #ifdef DHD_L2_FILTER |
---|
4826 | 4513 | /* If block_ping is enabled drop the ping packet */ |
---|
4827 | 4514 | if (ifp->block_ping) { |
---|
.. | .. |
---|
4844 | 4531 | */ |
---|
4845 | 4532 | if (ret == BCME_OK) { |
---|
4846 | 4533 | PKTCFREE(dhdp->osh, pktbuf, TRUE); |
---|
| 4534 | + continue; |
---|
| 4535 | + } |
---|
| 4536 | + } |
---|
| 4537 | + if (ifp->block_tdls) { |
---|
| 4538 | + if (bcm_l2_filter_block_tdls(dhdp->osh, pktbuf) == BCME_OK) { |
---|
| 4539 | + PKTCFREE(dhdp->osh, pktbuf, FALSE); |
---|
4847 | 4540 | continue; |
---|
4848 | 4541 | } |
---|
4849 | 4542 | } |
---|
.. | .. |
---|
4878 | 4571 | } |
---|
4879 | 4572 | #endif /* MCAST_REGEN */ |
---|
4880 | 4573 | |
---|
4881 | | -#ifdef DHD_WMF |
---|
4882 | | - /* WMF processing for multicast packets */ |
---|
4883 | | - if (ifp->wmf.wmf_enable && (ETHER_ISMULTI(eh->ether_dhost))) { |
---|
4884 | | - dhd_sta_t *sta; |
---|
4885 | | - int ret; |
---|
4886 | | - |
---|
4887 | | - sta = dhd_find_sta(dhdp, ifidx, (void *)eh->ether_shost); |
---|
4888 | | - ret = dhd_wmf_packets_handle(dhdp, pktbuf, sta, ifidx, 1); |
---|
4889 | | - switch (ret) { |
---|
4890 | | - case WMF_TAKEN: |
---|
4891 | | - /* The packet is taken by WMF. Continue to next iteration */ |
---|
4892 | | - continue; |
---|
4893 | | - case WMF_DROP: |
---|
4894 | | - /* Packet DROP decision by WMF. Toss it */ |
---|
4895 | | - DHD_ERROR(("%s: WMF decides to drop packet\n", |
---|
4896 | | - __FUNCTION__)); |
---|
4897 | | - PKTCFREE(dhdp->osh, pktbuf, FALSE); |
---|
4898 | | - continue; |
---|
4899 | | - default: |
---|
4900 | | - /* Continue the transmit path */ |
---|
4901 | | - break; |
---|
| 4574 | +#ifdef DHDTCPSYNC_FLOOD_BLK |
---|
| 4575 | + if (dhd_tcpdata_get_flag(dhdp, pktbuf) == FLAG_SYNC) { |
---|
| 4576 | + int delta_sec; |
---|
| 4577 | + int delta_sync; |
---|
| 4578 | + int sync_per_sec; |
---|
| 4579 | + u64 curr_time = DIV_U64_BY_U32(OSL_LOCALTIME_NS(), NSEC_PER_SEC); |
---|
| 4580 | + ifp->tsync_rcvd ++; |
---|
| 4581 | + delta_sync = ifp->tsync_rcvd - ifp->tsyncack_txed; |
---|
| 4582 | + delta_sec = curr_time - ifp->last_sync; |
---|
| 4583 | + if (delta_sec > 1) { |
---|
| 4584 | + sync_per_sec = delta_sync/delta_sec; |
---|
| 4585 | + if (sync_per_sec > TCP_SYNC_FLOOD_LIMIT) { |
---|
| 4586 | + schedule_work(&ifp->blk_tsfl_work); |
---|
| 4587 | + DHD_ERROR(("ifx %d TCP SYNC Flood attack suspected! " |
---|
| 4588 | + "sync recvied %d pkt/sec \n", |
---|
| 4589 | + ifidx, sync_per_sec)); |
---|
| 4590 | + } |
---|
| 4591 | + dhd_reset_tcpsync_info_by_ifp(ifp); |
---|
4902 | 4592 | } |
---|
| 4593 | + |
---|
4903 | 4594 | } |
---|
4904 | | -#endif /* DHD_WMF */ |
---|
| 4595 | +#endif /* DHDTCPSYNC_FLOOD_BLK */ |
---|
4905 | 4596 | |
---|
4906 | 4597 | #ifdef DHDTCPACK_SUPPRESS |
---|
4907 | 4598 | dhd_tcpdata_info_get(dhdp, pktbuf); |
---|
4908 | | -#endif |
---|
| 4599 | +#endif // endif |
---|
4909 | 4600 | skb = PKTTONATIVE(dhdp->osh, pktbuf); |
---|
4910 | 4601 | |
---|
4911 | 4602 | ASSERT(ifp); |
---|
4912 | 4603 | skb->dev = ifp->net; |
---|
4913 | | - |
---|
4914 | 4604 | #ifdef DHD_WET |
---|
4915 | 4605 | /* wet related packet proto manipulation should be done in DHD |
---|
4916 | 4606 | * since dongle doesn't have complete payload |
---|
.. | .. |
---|
4923 | 4613 | #endif /* DHD_WET */ |
---|
4924 | 4614 | |
---|
4925 | 4615 | #ifdef DHD_PSTA |
---|
4926 | | - if (PSR_ENABLED(dhdp) && (dhd_psta_proc(dhdp, ifidx, &pktbuf, FALSE) < 0)) { |
---|
4927 | | - DHD_ERROR(("%s:%s: psta recv proc failed\n", __FUNCTION__, |
---|
4928 | | - dhd_ifname(dhdp, ifidx))); |
---|
| 4616 | + if (PSR_ENABLED(dhdp) && |
---|
| 4617 | + (dhd_psta_proc(dhdp, ifidx, &pktbuf, FALSE) < 0)) { |
---|
| 4618 | + DHD_ERROR(("%s:%s: psta recv proc failed\n", __FUNCTION__, |
---|
| 4619 | + dhd_ifname(dhdp, ifidx))); |
---|
4929 | 4620 | } |
---|
4930 | 4621 | #endif /* DHD_PSTA */ |
---|
4931 | 4622 | |
---|
4932 | | -#ifdef PCIE_FULL_DONGLE |
---|
4933 | | - if ((DHD_IF_ROLE_AP(dhdp, ifidx) || DHD_IF_ROLE_P2PGO(dhdp, ifidx)) && |
---|
4934 | | - (!ifp->ap_isolate)) { |
---|
4935 | | - eh = (struct ether_header *)PKTDATA(dhdp->osh, pktbuf); |
---|
4936 | | - if (ETHER_ISUCAST(eh->ether_dhost)) { |
---|
4937 | | - if (dhd_find_sta(dhdp, ifidx, (void *)eh->ether_dhost)) { |
---|
4938 | | - dhd_sendpkt(dhdp, ifidx, pktbuf); |
---|
4939 | | - continue; |
---|
| 4623 | + DHD_TRACE(("\nAp isolate in dhd is %d\n", ifp->ap_isolate)); |
---|
| 4624 | + if (ifidx >= 0 && dhdp != NULL && dhdp->info != NULL && |
---|
| 4625 | + dhdp->info->iflist[ifidx] != NULL) { |
---|
| 4626 | + if ((DHD_IF_ROLE_AP(dhdp, ifidx) || DHD_IF_ROLE_P2PGO(dhdp, ifidx)) && |
---|
| 4627 | + (!ifp->ap_isolate)) { |
---|
| 4628 | + DHD_TRACE(("%s: MACADDR: " MACDBG " ifidx %d\n", |
---|
| 4629 | + __FUNCTION__, |
---|
| 4630 | + MAC2STRDBG(dhdp->info->iflist[ifidx]->mac_addr), |
---|
| 4631 | + ifidx)); |
---|
| 4632 | + DHD_TRACE(("%s: DEST: " MACDBG " ifidx %d\n", |
---|
| 4633 | + __FUNCTION__, MAC2STRDBG(eh->ether_dhost), ifidx)); |
---|
| 4634 | + eh = (struct ether_header *)PKTDATA(dhdp->osh, pktbuf); |
---|
| 4635 | + if (ETHER_ISUCAST(eh->ether_dhost)) { |
---|
| 4636 | + if (dhd_find_sta(dhdp, ifidx, (void *)eh->ether_dhost)) { |
---|
| 4637 | + DHD_TRACE(("\nPacket not for us send down\n")); |
---|
| 4638 | + dhd_sendpkt(dhdp, ifidx, pktbuf); |
---|
| 4639 | + continue; |
---|
| 4640 | + } |
---|
| 4641 | + } else { |
---|
| 4642 | + void *npktbuf = PKTDUP(dhdp->osh, pktbuf); |
---|
| 4643 | + if (npktbuf) { |
---|
| 4644 | + DHD_TRACE(("\ncalling bcmc dhd_sendpkt" |
---|
| 4645 | + "and send dup up\n")); |
---|
| 4646 | + dhd_sendpkt(dhdp, ifidx, npktbuf); |
---|
| 4647 | + } |
---|
4940 | 4648 | } |
---|
4941 | | - } else { |
---|
4942 | | - void *npktbuf = PKTDUP(dhdp->osh, pktbuf); |
---|
4943 | | - if (npktbuf) |
---|
4944 | | - dhd_sendpkt(dhdp, ifidx, npktbuf); |
---|
4945 | 4649 | } |
---|
4946 | 4650 | } |
---|
4947 | | -#endif /* PCIE_FULL_DONGLE */ |
---|
4948 | 4651 | |
---|
| 4652 | +#ifdef DHD_POST_EAPOL_M1_AFTER_ROAM_EVT |
---|
| 4653 | + if (IS_STA_IFACE(ndev_to_wdev(ifp->net)) && |
---|
| 4654 | + (ifp->recv_reassoc_evt == TRUE) && (ifp->post_roam_evt == FALSE) && |
---|
| 4655 | + (dhd_is_4way_msg((char *)(skb->data)) == EAPOL_4WAY_M1)) { |
---|
| 4656 | + DHD_ERROR(("%s: Reassoc is in progress. " |
---|
| 4657 | + "Drop EAPOL M1 frame\n", __FUNCTION__)); |
---|
| 4658 | + PKTFREE(dhdp->osh, pktbuf, FALSE); |
---|
| 4659 | + continue; |
---|
| 4660 | + } |
---|
| 4661 | +#endif /* DHD_POST_EAPOL_M1_AFTER_ROAM_EVT */ |
---|
4949 | 4662 | /* Get the protocol, maintain skb around eth_type_trans() |
---|
4950 | 4663 | * The main reason for this hack is for the limitation of |
---|
4951 | 4664 | * Linux 2.4 where 'eth_type_trans' uses the 'net->hard_header_len' |
---|
.. | .. |
---|
4957 | 4670 | */ |
---|
4958 | 4671 | eth = skb->data; |
---|
4959 | 4672 | len = skb->len; |
---|
4960 | | - |
---|
4961 | | -#if defined(DHD_RX_DUMP) || defined(DHD_8021X_DUMP) || defined(DHD_DHCP_DUMP) |
---|
4962 | 4673 | dump_data = skb->data; |
---|
4963 | | -#endif /* DHD_RX_DUMP || DHD_8021X_DUMP || DHD_DHCP_DUMP */ |
---|
4964 | | - |
---|
4965 | 4674 | protocol = (skb->data[12] << 8) | skb->data[13]; |
---|
| 4675 | + |
---|
4966 | 4676 | if (protocol == ETHER_TYPE_802_1X) { |
---|
4967 | 4677 | DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED); |
---|
4968 | | -#ifdef DHD_8021X_DUMP |
---|
4969 | | - DHD_ERROR(("ETHER_TYPE_802_1X [RX]: " |
---|
4970 | | - "ver %d, type %d, replay %d\n", |
---|
4971 | | - dump_data[14], dump_data[15], |
---|
4972 | | - dump_data[30])); |
---|
4973 | | -#endif /* DHD_8021X_DUMP */ |
---|
4974 | | - } |
---|
4975 | | - |
---|
4976 | | -#ifdef DHD_DHCP_DUMP |
---|
4977 | | - if (protocol != ETHER_TYPE_BRCM && protocol == ETHER_TYPE_IP) { |
---|
4978 | | - dhd_dhcp_dump(dump_data, FALSE); |
---|
4979 | | - dhd_tcp_dump(dhd_ifname(dhdp, ifidx), dump_data, FALSE); |
---|
4980 | | - } |
---|
4981 | | -#endif /* DHD_DHCP_DUMP */ |
---|
4982 | | -#if defined(DHD_RX_DUMP) |
---|
4983 | | - DHD_ERROR(("RX DUMP - %s\n", _get_packet_type_str(protocol))); |
---|
4984 | | - if (protocol != ETHER_TYPE_BRCM) { |
---|
4985 | | - if (dump_data[0] == 0xFF) { |
---|
4986 | | - DHD_ERROR(("%s: BROADCAST\n", __FUNCTION__)); |
---|
4987 | | - |
---|
4988 | | - if ((dump_data[12] == 8) && |
---|
4989 | | - (dump_data[13] == 6)) { |
---|
4990 | | - DHD_ERROR(("%s: ARP %d\n", |
---|
4991 | | - __FUNCTION__, dump_data[0x15])); |
---|
4992 | | - } |
---|
4993 | | - } else if (dump_data[0] & 1) { |
---|
4994 | | - DHD_ERROR(("%s: MULTICAST: " MACDBG "\n", |
---|
4995 | | - __FUNCTION__, MAC2STRDBG(dump_data))); |
---|
| 4678 | +#if defined(WL_CFG80211) && defined(WL_WPS_SYNC) |
---|
| 4679 | + wl_handle_wps_states(ifp->net, dump_data, len, FALSE); |
---|
| 4680 | +#endif /* WL_CFG80211 && WL_WPS_SYNC */ |
---|
| 4681 | +#ifdef DHD_4WAYM4_FAIL_DISCONNECT |
---|
| 4682 | + if (dhd_is_4way_msg((uint8 *)(skb->data)) == EAPOL_4WAY_M3) { |
---|
| 4683 | + OSL_ATOMIC_SET(dhdp->osh, &ifp->m4state, M3_RXED); |
---|
4996 | 4684 | } |
---|
4997 | | -#ifdef DHD_RX_FULL_DUMP |
---|
4998 | | - { |
---|
4999 | | - int k; |
---|
5000 | | - for (k = 0; k < skb->len; k++) { |
---|
5001 | | - DHD_ERROR(("%02X ", dump_data[k])); |
---|
5002 | | - if ((k & 15) == 15) |
---|
5003 | | - DHD_ERROR(("\n")); |
---|
5004 | | - } |
---|
5005 | | - DHD_ERROR(("\n")); |
---|
5006 | | - } |
---|
5007 | | -#endif /* DHD_RX_FULL_DUMP */ |
---|
| 4685 | +#endif /* DHD_4WAYM4_FAIL_DISCONNECT */ |
---|
5008 | 4686 | } |
---|
5009 | | -#endif /* DHD_RX_DUMP */ |
---|
| 4687 | + dhd_rx_pkt_dump(dhdp, ifidx, dump_data, len); |
---|
| 4688 | + dhd_dump_pkt(dhdp, ifidx, dump_data, len, FALSE, NULL, NULL); |
---|
| 4689 | + |
---|
| 4690 | +#if defined(DHD_WAKE_STATUS) && defined(DHD_WAKEPKT_DUMP) |
---|
| 4691 | + if (pkt_wake) { |
---|
| 4692 | + prhex("[wakepkt_dump]", (char*)dump_data, MIN(len, 32)); |
---|
| 4693 | + } |
---|
| 4694 | +#endif /* DHD_WAKE_STATUS && DHD_WAKEPKT_DUMP */ |
---|
5010 | 4695 | |
---|
5011 | 4696 | skb->protocol = eth_type_trans(skb, skb->dev); |
---|
5012 | 4697 | |
---|
.. | .. |
---|
5018 | 4703 | skb->data = eth; |
---|
5019 | 4704 | skb->len = len; |
---|
5020 | 4705 | |
---|
5021 | | -#ifdef WLMEDIA_HTSF |
---|
5022 | | - dhd_htsf_addrxts(dhdp, pktbuf); |
---|
5023 | | -#endif |
---|
| 4706 | + DHD_DBG_PKT_MON_RX(dhdp, skb); |
---|
| 4707 | +#ifdef DHD_PKT_LOGGING |
---|
| 4708 | + DHD_PKTLOG_RX(dhdp, skb); |
---|
| 4709 | +#endif /* DHD_PKT_LOGGING */ |
---|
5024 | 4710 | /* Strip header, count, deliver upward */ |
---|
5025 | 4711 | skb_pull(skb, ETH_HLEN); |
---|
5026 | 4712 | |
---|
.. | .. |
---|
5028 | 4714 | memset(&event, 0, sizeof(event)); |
---|
5029 | 4715 | |
---|
5030 | 4716 | if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) { |
---|
5031 | | - dhd_wl_host_event(dhd, &ifidx, |
---|
5032 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) |
---|
5033 | | - skb_mac_header(skb), |
---|
| 4717 | + bcm_event_msg_u_t evu; |
---|
| 4718 | + int ret_event, event_type; |
---|
| 4719 | + void *pkt_data = skb_mac_header(skb); |
---|
| 4720 | + |
---|
| 4721 | + ret_event = wl_host_event_get_data(pkt_data, len, &evu); |
---|
| 4722 | + |
---|
| 4723 | + if (ret_event != BCME_OK) { |
---|
| 4724 | + DHD_ERROR(("%s: wl_host_event_get_data err = %d\n", |
---|
| 4725 | + __FUNCTION__, ret_event)); |
---|
| 4726 | +#ifdef DHD_USE_STATIC_CTRLBUF |
---|
| 4727 | + PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); |
---|
5034 | 4728 | #else |
---|
5035 | | - skb->mac.raw, |
---|
5036 | | -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) */ |
---|
5037 | | - len, &event, &data); |
---|
| 4729 | + PKTFREE(dhdp->osh, pktbuf, FALSE); |
---|
| 4730 | +#endif // endif |
---|
| 4731 | + continue; |
---|
| 4732 | + } |
---|
| 4733 | + |
---|
| 4734 | + memcpy(&event, &evu.event, sizeof(wl_event_msg_t)); |
---|
| 4735 | + event_type = ntoh32_ua((void *)&event.event_type); |
---|
| 4736 | +#ifdef SHOW_LOGTRACE |
---|
| 4737 | + /* Event msg printing is called from dhd_rx_frame which is in Tasklet |
---|
| 4738 | + * context in case of PCIe FD, in case of other bus this will be from |
---|
| 4739 | + * DPC context. If we get bunch of events from Dongle then printing all |
---|
| 4740 | + * of them from Tasklet/DPC context that too in data path is costly. |
---|
| 4741 | + * Also in the new Dongle SW(4359, 4355 onwards) console prints too come as |
---|
| 4742 | + * events with type WLC_E_TRACE. |
---|
| 4743 | + * We'll print this console logs from the WorkQueue context by enqueing SKB |
---|
| 4744 | + * here and Dequeuing will be done in WorkQueue and will be freed only if |
---|
| 4745 | + * logtrace_pkt_sendup is true |
---|
| 4746 | + */ |
---|
| 4747 | + if (event_type == WLC_E_TRACE) { |
---|
| 4748 | + DHD_TRACE(("%s: WLC_E_TRACE\n", __FUNCTION__)); |
---|
| 4749 | + dhd_event_logtrace_enqueue(dhdp, ifidx, pktbuf); |
---|
| 4750 | + continue; |
---|
| 4751 | + } |
---|
| 4752 | +#endif /* SHOW_LOGTRACE */ |
---|
| 4753 | + |
---|
| 4754 | + ret_event = dhd_wl_host_event(dhd, ifidx, pkt_data, len, &event, &data); |
---|
5038 | 4755 | |
---|
5039 | 4756 | wl_event_to_host_order(&event); |
---|
| 4757 | +#if (defined(OEM_ANDROID) || defined(OEM_EMBEDDED_LINUX)) |
---|
5040 | 4758 | if (!tout_ctrl) |
---|
5041 | 4759 | tout_ctrl = DHD_PACKET_TIMEOUT_MS; |
---|
| 4760 | +#endif /* (defined(OEM_ANDROID) || defined(OEM_EMBEDDED_LINUX)) */ |
---|
5042 | 4761 | |
---|
5043 | | -#if defined(PNO_SUPPORT) |
---|
5044 | | - if (event.event_type == WLC_E_PFN_NET_FOUND) { |
---|
| 4762 | +#if (defined(OEM_ANDROID) && defined(PNO_SUPPORT)) |
---|
| 4763 | + if (event_type == WLC_E_PFN_NET_FOUND) { |
---|
5045 | 4764 | /* enforce custom wake lock to garantee that Kernel not suspended */ |
---|
5046 | 4765 | tout_ctrl = CUSTOM_PNO_EVENT_LOCK_xTIME * DHD_PACKET_TIMEOUT_MS; |
---|
5047 | 4766 | } |
---|
5048 | 4767 | #endif /* PNO_SUPPORT */ |
---|
5049 | | - if (DHD_DBG_BCNRX_ON()) { |
---|
5050 | | - if (event.event_type == WLC_E_BCNRX_MSG) { |
---|
5051 | | - prhex("Received beacon packet:", data, event.datalen); |
---|
5052 | | - } |
---|
5053 | | - } |
---|
5054 | | - |
---|
5055 | 4768 | if (numpkt != 1) { |
---|
5056 | | - DHD_ERROR(("%s: Got BRCM event packet in a chained packet.\n", |
---|
| 4769 | + DHD_TRACE(("%s: Got BRCM event packet in a chained packet.\n", |
---|
5057 | 4770 | __FUNCTION__)); |
---|
5058 | 4771 | } |
---|
5059 | | -#ifdef DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT |
---|
| 4772 | + |
---|
| 4773 | +#ifdef DHD_WAKE_STATUS |
---|
| 4774 | + if (unlikely(pkt_wake)) { |
---|
| 4775 | +#ifdef DHD_WAKE_EVENT_STATUS |
---|
| 4776 | + if (event.event_type < WLC_E_LAST) { |
---|
| 4777 | + wcp->rc_event[event.event_type]++; |
---|
| 4778 | + wcp->rcwake++; |
---|
| 4779 | + pkt_wake = 0; |
---|
| 4780 | + } |
---|
| 4781 | +#endif /* DHD_WAKE_EVENT_STATUS */ |
---|
| 4782 | + } |
---|
| 4783 | +#endif /* DHD_WAKE_STATUS */ |
---|
| 4784 | + |
---|
| 4785 | + /* For delete virtual interface event, wl_host_event returns positive |
---|
| 4786 | + * i/f index, do not proceed. just free the pkt. |
---|
| 4787 | + */ |
---|
| 4788 | + if ((event_type == WLC_E_IF) && (ret_event > 0)) { |
---|
| 4789 | + DHD_ERROR(("%s: interface is deleted. Free event packet\n", |
---|
| 4790 | + __FUNCTION__)); |
---|
5060 | 4791 | #ifdef DHD_USE_STATIC_CTRLBUF |
---|
5061 | | - PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); |
---|
| 4792 | + PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); |
---|
5062 | 4793 | #else |
---|
5063 | | - PKTFREE(dhdp->osh, pktbuf, FALSE); |
---|
5064 | | -#endif /* DHD_USE_STATIC_CTRLBUF */ |
---|
5065 | | - continue; |
---|
5066 | | -#else |
---|
| 4794 | + PKTFREE(dhdp->osh, pktbuf, FALSE); |
---|
| 4795 | +#endif // endif |
---|
| 4796 | + continue; |
---|
| 4797 | + } |
---|
| 4798 | + |
---|
5067 | 4799 | /* |
---|
5068 | 4800 | * For the event packets, there is a possibility |
---|
5069 | 4801 | * of ifidx getting modifed.Thus update the ifp |
---|
.. | .. |
---|
5072 | 4804 | ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]); |
---|
5073 | 4805 | ifp = dhd->iflist[ifidx]; |
---|
5074 | 4806 | #ifndef PROP_TXSTATUS_VSDB |
---|
5075 | | - if (!(ifp && ifp->net && (ifp->net->reg_state == NETREG_REGISTERED))) { |
---|
| 4807 | + if (!(ifp && ifp->net && (ifp->net->reg_state == NETREG_REGISTERED))) |
---|
5076 | 4808 | #else |
---|
5077 | 4809 | if (!(ifp && ifp->net && (ifp->net->reg_state == NETREG_REGISTERED) && |
---|
5078 | | - dhd->pub.up)) { |
---|
| 4810 | + dhd->pub.up)) |
---|
5079 | 4811 | #endif /* PROP_TXSTATUS_VSDB */ |
---|
| 4812 | + { |
---|
5080 | 4813 | DHD_ERROR(("%s: net device is NOT registered. drop event packet\n", |
---|
5081 | 4814 | __FUNCTION__)); |
---|
| 4815 | +#ifdef DHD_USE_STATIC_CTRLBUF |
---|
| 4816 | + PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); |
---|
| 4817 | +#else |
---|
5082 | 4818 | PKTFREE(dhdp->osh, pktbuf, FALSE); |
---|
| 4819 | +#endif // endif |
---|
5083 | 4820 | continue; |
---|
5084 | 4821 | } |
---|
5085 | | -#endif /* DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT */ |
---|
| 4822 | + |
---|
| 4823 | + if (dhdp->wl_event_enabled) { |
---|
| 4824 | +#ifdef DHD_USE_STATIC_CTRLBUF |
---|
| 4825 | + /* If event bufs are allocated via static buf pool |
---|
| 4826 | + * and wl events are enabled, make a copy, free the |
---|
| 4827 | + * local one and send the copy up. |
---|
| 4828 | + */ |
---|
| 4829 | + void *npkt = PKTDUP(dhdp->osh, skb); |
---|
| 4830 | + /* Clone event and send it up */ |
---|
| 4831 | + PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); |
---|
| 4832 | + if (npkt) { |
---|
| 4833 | + skb = npkt; |
---|
| 4834 | + } else { |
---|
| 4835 | + DHD_ERROR(("skb clone failed. dropping event.\n")); |
---|
| 4836 | + continue; |
---|
| 4837 | + } |
---|
| 4838 | +#endif /* DHD_USE_STATIC_CTRLBUF */ |
---|
| 4839 | + } else { |
---|
| 4840 | + /* If event enabled not explictly set, drop events */ |
---|
| 4841 | +#ifdef DHD_USE_STATIC_CTRLBUF |
---|
| 4842 | + PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); |
---|
| 4843 | +#else |
---|
| 4844 | + PKTFREE(dhdp->osh, pktbuf, FALSE); |
---|
| 4845 | +#endif /* DHD_USE_STATIC_CTRLBUF */ |
---|
| 4846 | + continue; |
---|
| 4847 | + } |
---|
5086 | 4848 | } else { |
---|
| 4849 | +#if (defined(OEM_ANDROID) || defined(OEM_EMBEDDED_LINUX)) |
---|
5087 | 4850 | tout_rx = DHD_PACKET_TIMEOUT_MS; |
---|
| 4851 | +#endif /* OEM_ANDROID || OEM_EMBEDDED_LINUX */ |
---|
5088 | 4852 | |
---|
5089 | 4853 | #ifdef PROP_TXSTATUS |
---|
5090 | 4854 | dhd_wlfc_save_rxpath_ac_time(dhdp, (uint8)PKTPRIO(skb)); |
---|
5091 | 4855 | #endif /* PROP_TXSTATUS */ |
---|
| 4856 | + |
---|
| 4857 | +#ifdef DHD_WAKE_STATUS |
---|
| 4858 | + if (unlikely(pkt_wake)) { |
---|
| 4859 | + wcp->rxwake++; |
---|
| 4860 | +#ifdef DHD_WAKE_RX_STATUS |
---|
| 4861 | +#define ETHER_ICMP6_HEADER 20 |
---|
| 4862 | +#define ETHER_IPV6_SADDR (ETHER_ICMP6_HEADER + 2) |
---|
| 4863 | +#define ETHER_IPV6_DAADR (ETHER_IPV6_SADDR + IPV6_ADDR_LEN) |
---|
| 4864 | +#define ETHER_ICMPV6_TYPE (ETHER_IPV6_DAADR + IPV6_ADDR_LEN) |
---|
| 4865 | + |
---|
| 4866 | + if (ntoh16(skb->protocol) == ETHER_TYPE_ARP) /* ARP */ |
---|
| 4867 | + wcp->rx_arp++; |
---|
| 4868 | + if (dump_data[0] == 0xFF) { /* Broadcast */ |
---|
| 4869 | + wcp->rx_bcast++; |
---|
| 4870 | + } else if (dump_data[0] & 0x01) { /* Multicast */ |
---|
| 4871 | + wcp->rx_mcast++; |
---|
| 4872 | + if (ntoh16(skb->protocol) == ETHER_TYPE_IPV6) { |
---|
| 4873 | + wcp->rx_multi_ipv6++; |
---|
| 4874 | + if ((skb->len > ETHER_ICMP6_HEADER) && |
---|
| 4875 | + (dump_data[ETHER_ICMP6_HEADER] == IPPROTO_ICMPV6)) { |
---|
| 4876 | + wcp->rx_icmpv6++; |
---|
| 4877 | + if (skb->len > ETHER_ICMPV6_TYPE) { |
---|
| 4878 | + switch (dump_data[ETHER_ICMPV6_TYPE]) { |
---|
| 4879 | + case NDISC_ROUTER_ADVERTISEMENT: |
---|
| 4880 | + wcp->rx_icmpv6_ra++; |
---|
| 4881 | + break; |
---|
| 4882 | + case NDISC_NEIGHBOUR_ADVERTISEMENT: |
---|
| 4883 | + wcp->rx_icmpv6_na++; |
---|
| 4884 | + break; |
---|
| 4885 | + case NDISC_NEIGHBOUR_SOLICITATION: |
---|
| 4886 | + wcp->rx_icmpv6_ns++; |
---|
| 4887 | + break; |
---|
| 4888 | + } |
---|
| 4889 | + } |
---|
| 4890 | + } |
---|
| 4891 | + } else if (dump_data[2] == 0x5E) { |
---|
| 4892 | + wcp->rx_multi_ipv4++; |
---|
| 4893 | + } else { |
---|
| 4894 | + wcp->rx_multi_other++; |
---|
| 4895 | + } |
---|
| 4896 | + } else { /* Unicast */ |
---|
| 4897 | + wcp->rx_ucast++; |
---|
| 4898 | + } |
---|
| 4899 | +#undef ETHER_ICMP6_HEADER |
---|
| 4900 | +#undef ETHER_IPV6_SADDR |
---|
| 4901 | +#undef ETHER_IPV6_DAADR |
---|
| 4902 | +#undef ETHER_ICMPV6_TYPE |
---|
| 4903 | +#endif /* DHD_WAKE_RX_STATUS */ |
---|
| 4904 | + pkt_wake = 0; |
---|
| 4905 | + } |
---|
| 4906 | +#endif /* DHD_WAKE_STATUS */ |
---|
5092 | 4907 | } |
---|
5093 | 4908 | |
---|
5094 | | -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)) |
---|
5095 | | - /* It is useless for network stack any more, and we do not use it */ |
---|
5096 | | - if (ifp->net) |
---|
5097 | | - ifp->net->last_rx = jiffies; |
---|
5098 | | -#endif |
---|
| 4909 | +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) |
---|
| 4910 | + ifp->net->last_rx = jiffies; |
---|
| 4911 | +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) */ |
---|
5099 | 4912 | |
---|
5100 | 4913 | if (ntoh16(skb->protocol) != ETHER_TYPE_BRCM) { |
---|
5101 | 4914 | dhdp->dstats.rx_bytes += skb->len; |
---|
.. | .. |
---|
5108 | 4921 | bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, |
---|
5109 | 4922 | __FUNCTION__, __LINE__); |
---|
5110 | 4923 | DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
5111 | | -#if defined(DHD_LB) && defined(DHD_LB_RXP) |
---|
| 4924 | +#if defined(DHD_LB_RXP) |
---|
5112 | 4925 | netif_receive_skb(skb); |
---|
5113 | | -#else |
---|
| 4926 | +#else /* !defined(DHD_LB_RXP) */ |
---|
5114 | 4927 | netif_rx(skb); |
---|
5115 | | -#endif /* !defined(DHD_LB) && !defined(DHD_LB_RXP) */ |
---|
| 4928 | +#endif /* !defined(DHD_LB_RXP) */ |
---|
5116 | 4929 | DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
5117 | 4930 | } else { |
---|
5118 | 4931 | if (dhd->rxthread_enabled) { |
---|
.. | .. |
---|
5132 | 4945 | bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, |
---|
5133 | 4946 | __FUNCTION__, __LINE__); |
---|
5134 | 4947 | |
---|
5135 | | -#if defined(DHD_LB) && defined(DHD_LB_RXP) |
---|
| 4948 | +#if defined(ARGOS_NOTIFY_CB) |
---|
| 4949 | + argos_register_notifier_deinit(); |
---|
| 4950 | +#endif // endif |
---|
| 4951 | +#if defined(BCMPCIE) && defined(DHDTCPACK_SUPPRESS) |
---|
| 4952 | + dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF); |
---|
| 4953 | +#endif /* BCMPCIE && DHDTCPACK_SUPPRESS */ |
---|
5136 | 4954 | DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
| 4955 | +#if defined(DHD_LB_RXP) |
---|
5137 | 4956 | netif_receive_skb(skb); |
---|
5138 | | - DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
5139 | | -#else |
---|
5140 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) |
---|
5141 | | - DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
| 4957 | +#else /* !defined(DHD_LB_RXP) */ |
---|
5142 | 4958 | netif_rx_ni(skb); |
---|
| 4959 | +#endif /* defined(DHD_LB_RXP) */ |
---|
5143 | 4960 | DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
5144 | | -#else |
---|
5145 | | - ulong flags; |
---|
5146 | | - DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
5147 | | - netif_rx(skb); |
---|
5148 | | - DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
5149 | | - local_irq_save(flags); |
---|
5150 | | - RAISE_RX_SOFTIRQ(); |
---|
5151 | | - local_irq_restore(flags); |
---|
5152 | | -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ |
---|
5153 | | -#endif /* !defined(DHD_LB) && !defined(DHD_LB_RXP) */ |
---|
5154 | 4961 | } |
---|
5155 | 4962 | } |
---|
5156 | 4963 | } |
---|
.. | .. |
---|
5158 | 4965 | if (dhd->rxthread_enabled && skbhead) |
---|
5159 | 4966 | dhd_sched_rxf(dhdp, skbhead); |
---|
5160 | 4967 | |
---|
| 4968 | +#if (defined(OEM_ANDROID) || defined(OEM_EMBEDDED_LINUX)) |
---|
5161 | 4969 | DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(dhdp, tout_rx); |
---|
5162 | 4970 | DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, tout_ctrl); |
---|
| 4971 | +#endif /* OEM_ANDROID || OEM_EMBEDDED_LINUX */ |
---|
5163 | 4972 | } |
---|
5164 | 4973 | |
---|
5165 | 4974 | void |
---|
.. | .. |
---|
5181 | 4990 | eh = (struct ether_header *)PKTDATA(dhdp->osh, txp); |
---|
5182 | 4991 | type = ntoh16(eh->ether_type); |
---|
5183 | 4992 | |
---|
5184 | | - if ((type == ETHER_TYPE_802_1X) && (dhd_get_pend_8021x_cnt(dhd) > 0)) |
---|
| 4993 | + if (type == ETHER_TYPE_802_1X) { |
---|
5185 | 4994 | atomic_dec(&dhd->pend_8021x_cnt); |
---|
| 4995 | + } |
---|
5186 | 4996 | |
---|
5187 | 4997 | #ifdef PROP_TXSTATUS |
---|
5188 | 4998 | if (dhdp->wlfc_state && (dhdp->proptxstatus_mode != WLFC_FCMODE_NONE)) { |
---|
.. | .. |
---|
5198 | 5008 | } |
---|
5199 | 5009 | } |
---|
5200 | 5010 | } |
---|
5201 | | -#endif |
---|
| 5011 | +#endif // endif |
---|
5202 | 5012 | } |
---|
5203 | 5013 | |
---|
5204 | 5014 | static struct net_device_stats * |
---|
.. | .. |
---|
5206 | 5016 | { |
---|
5207 | 5017 | dhd_info_t *dhd = DHD_DEV_INFO(net); |
---|
5208 | 5018 | dhd_if_t *ifp; |
---|
5209 | | - int ifidx; |
---|
5210 | 5019 | |
---|
5211 | 5020 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
5212 | 5021 | |
---|
5213 | | - ifidx = dhd_net2idx(dhd, net); |
---|
5214 | | - if (ifidx == DHD_BAD_IF) { |
---|
5215 | | - DHD_ERROR(("%s: BAD_IF\n", __FUNCTION__)); |
---|
5216 | | - |
---|
5217 | | - memset(&net->stats, 0, sizeof(net->stats)); |
---|
5218 | | - return &net->stats; |
---|
| 5022 | + if (!dhd) { |
---|
| 5023 | + DHD_ERROR(("%s : dhd is NULL\n", __FUNCTION__)); |
---|
| 5024 | + goto error; |
---|
5219 | 5025 | } |
---|
5220 | 5026 | |
---|
5221 | | - ifp = dhd->iflist[ifidx]; |
---|
5222 | | - ASSERT(dhd && ifp); |
---|
| 5027 | + ifp = dhd_get_ifp_by_ndev(&dhd->pub, net); |
---|
| 5028 | + if (!ifp) { |
---|
| 5029 | + /* return empty stats */ |
---|
| 5030 | + DHD_ERROR(("%s: BAD_IF\n", __FUNCTION__)); |
---|
| 5031 | + goto error; |
---|
| 5032 | + } |
---|
5223 | 5033 | |
---|
5224 | 5034 | if (dhd->pub.up) { |
---|
5225 | 5035 | /* Use the protocol to get dongle stats */ |
---|
5226 | 5036 | dhd_prot_dstats(&dhd->pub); |
---|
5227 | 5037 | } |
---|
5228 | 5038 | return &ifp->stats; |
---|
| 5039 | + |
---|
| 5040 | +error: |
---|
| 5041 | + memset(&net->stats, 0, sizeof(net->stats)); |
---|
| 5042 | + return &net->stats; |
---|
5229 | 5043 | } |
---|
5230 | 5044 | |
---|
5231 | | -#ifndef BCMDBUS |
---|
5232 | 5045 | static int |
---|
5233 | 5046 | dhd_watchdog_thread(void *data) |
---|
5234 | 5047 | { |
---|
.. | .. |
---|
5249 | 5062 | unsigned long flags; |
---|
5250 | 5063 | unsigned long jiffies_at_start = jiffies; |
---|
5251 | 5064 | unsigned long time_lapse; |
---|
5252 | | - |
---|
| 5065 | +#ifdef BCMPCIE |
---|
5253 | 5066 | DHD_OS_WD_WAKE_LOCK(&dhd->pub); |
---|
| 5067 | +#endif /* BCMPCIE */ |
---|
| 5068 | + |
---|
5254 | 5069 | SMP_RD_BARRIER_DEPENDS(); |
---|
5255 | 5070 | if (tsk->terminated) { |
---|
| 5071 | +#ifdef BCMPCIE |
---|
| 5072 | + DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); |
---|
| 5073 | +#endif /* BCMPCIE */ |
---|
5256 | 5074 | break; |
---|
5257 | 5075 | } |
---|
5258 | 5076 | |
---|
.. | .. |
---|
5277 | 5095 | } |
---|
5278 | 5096 | DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
5279 | 5097 | } |
---|
| 5098 | +#ifdef BCMPCIE |
---|
5280 | 5099 | DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); |
---|
| 5100 | +#endif /* BCMPCIE */ |
---|
5281 | 5101 | } else { |
---|
5282 | 5102 | break; |
---|
5283 | 5103 | } |
---|
.. | .. |
---|
5286 | 5106 | complete_and_exit(&tsk->completed, 0); |
---|
5287 | 5107 | } |
---|
5288 | 5108 | |
---|
5289 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) |
---|
5290 | | -static void dhd_watchdog(struct timer_list *t) |
---|
5291 | | -{ |
---|
5292 | | - dhd_info_t *dhd = from_timer(dhd, t, timer); |
---|
5293 | | -#else |
---|
5294 | 5109 | static void dhd_watchdog(ulong data) |
---|
5295 | 5110 | { |
---|
5296 | 5111 | dhd_info_t *dhd = (dhd_info_t *)data; |
---|
5297 | | -#endif |
---|
5298 | 5112 | unsigned long flags; |
---|
5299 | 5113 | |
---|
5300 | 5114 | if (dhd->pub.dongle_reset) { |
---|
5301 | | - return; |
---|
5302 | | - } |
---|
5303 | | - |
---|
5304 | | - if (dhd->pub.busstate == DHD_BUS_SUSPEND) { |
---|
5305 | | - DHD_ERROR(("%s wd while suspend in progress \n", __FUNCTION__)); |
---|
5306 | 5115 | return; |
---|
5307 | 5116 | } |
---|
5308 | 5117 | |
---|
.. | .. |
---|
5311 | 5120 | return; |
---|
5312 | 5121 | } |
---|
5313 | 5122 | |
---|
| 5123 | +#ifdef BCMPCIE |
---|
5314 | 5124 | DHD_OS_WD_WAKE_LOCK(&dhd->pub); |
---|
| 5125 | +#endif /* BCMPCIE */ |
---|
5315 | 5126 | /* Call the bus module watchdog */ |
---|
5316 | 5127 | dhd_bus_watchdog(&dhd->pub); |
---|
5317 | 5128 | |
---|
.. | .. |
---|
5326 | 5137 | if (dhd->wd_timer_valid) |
---|
5327 | 5138 | mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms)); |
---|
5328 | 5139 | DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
| 5140 | +#ifdef BCMPCIE |
---|
5329 | 5141 | DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); |
---|
| 5142 | +#endif /* BCMPCIE */ |
---|
5330 | 5143 | } |
---|
| 5144 | + |
---|
| 5145 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 5146 | +static int |
---|
| 5147 | +dhd_rpm_state_thread(void *data) |
---|
| 5148 | +{ |
---|
| 5149 | + tsk_ctl_t *tsk = (tsk_ctl_t *)data; |
---|
| 5150 | + dhd_info_t *dhd = (dhd_info_t *)tsk->parent; |
---|
| 5151 | + |
---|
| 5152 | + while (1) { |
---|
| 5153 | + if (down_interruptible (&tsk->sema) == 0) { |
---|
| 5154 | + unsigned long flags; |
---|
| 5155 | + unsigned long jiffies_at_start = jiffies; |
---|
| 5156 | + unsigned long time_lapse; |
---|
| 5157 | + |
---|
| 5158 | + SMP_RD_BARRIER_DEPENDS(); |
---|
| 5159 | + if (tsk->terminated) { |
---|
| 5160 | + break; |
---|
| 5161 | + } |
---|
| 5162 | + |
---|
| 5163 | + if (dhd->pub.dongle_reset == FALSE) { |
---|
| 5164 | + DHD_TIMER(("%s:\n", __FUNCTION__)); |
---|
| 5165 | + if (dhd->pub.up) { |
---|
| 5166 | + dhd_runtimepm_state(&dhd->pub); |
---|
| 5167 | + } |
---|
| 5168 | + |
---|
| 5169 | + DHD_GENERAL_LOCK(&dhd->pub, flags); |
---|
| 5170 | + time_lapse = jiffies - jiffies_at_start; |
---|
| 5171 | + |
---|
| 5172 | + /* Reschedule the watchdog */ |
---|
| 5173 | + if (dhd->rpm_timer_valid) { |
---|
| 5174 | + mod_timer(&dhd->rpm_timer, |
---|
| 5175 | + jiffies + |
---|
| 5176 | + msecs_to_jiffies(dhd_runtimepm_ms) - |
---|
| 5177 | + min(msecs_to_jiffies(dhd_runtimepm_ms), |
---|
| 5178 | + time_lapse)); |
---|
| 5179 | + } |
---|
| 5180 | + DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
| 5181 | + } |
---|
| 5182 | + } else { |
---|
| 5183 | + break; |
---|
| 5184 | + } |
---|
| 5185 | + } |
---|
| 5186 | + |
---|
| 5187 | + complete_and_exit(&tsk->completed, 0); |
---|
| 5188 | +} |
---|
| 5189 | + |
---|
| 5190 | +static void dhd_runtimepm(ulong data) |
---|
| 5191 | +{ |
---|
| 5192 | + dhd_info_t *dhd = (dhd_info_t *)data; |
---|
| 5193 | + |
---|
| 5194 | + if (dhd->pub.dongle_reset) { |
---|
| 5195 | + return; |
---|
| 5196 | + } |
---|
| 5197 | + |
---|
| 5198 | + if (dhd->thr_rpm_ctl.thr_pid >= 0) { |
---|
| 5199 | + up(&dhd->thr_rpm_ctl.sema); |
---|
| 5200 | + return; |
---|
| 5201 | + } |
---|
| 5202 | +} |
---|
| 5203 | + |
---|
| 5204 | +void dhd_runtime_pm_disable(dhd_pub_t *dhdp) |
---|
| 5205 | +{ |
---|
| 5206 | + dhd_os_runtimepm_timer(dhdp, 0); |
---|
| 5207 | + dhdpcie_runtime_bus_wake(dhdp, CAN_SLEEP(), __builtin_return_address(0)); |
---|
| 5208 | +} |
---|
| 5209 | + |
---|
| 5210 | +void dhd_runtime_pm_enable(dhd_pub_t *dhdp) |
---|
| 5211 | +{ |
---|
| 5212 | + /* Enable Runtime PM except for MFG Mode */ |
---|
| 5213 | + if (!(dhdp->op_mode & DHD_FLAG_MFG_MODE)) { |
---|
| 5214 | + if (dhd_get_idletime(dhdp)) { |
---|
| 5215 | + dhd_os_runtimepm_timer(dhdp, dhd_runtimepm_ms); |
---|
| 5216 | + } |
---|
| 5217 | + } |
---|
| 5218 | +} |
---|
| 5219 | + |
---|
| 5220 | +#endif /* DHD_PCIE_RUNTIMEPM */ |
---|
5331 | 5221 | |
---|
5332 | 5222 | #ifdef ENABLE_ADAPTIVE_SCHED |
---|
5333 | 5223 | static void |
---|
.. | .. |
---|
5381 | 5271 | |
---|
5382 | 5272 | #ifdef CUSTOM_DPC_CPUCORE |
---|
5383 | 5273 | set_cpus_allowed_ptr(current, cpumask_of(CUSTOM_DPC_CPUCORE)); |
---|
5384 | | -#endif |
---|
| 5274 | +#endif // endif |
---|
5385 | 5275 | #ifdef CUSTOM_SET_CPUCORE |
---|
5386 | 5276 | dhd->pub.current_dpc = current; |
---|
5387 | 5277 | #endif /* CUSTOM_SET_CPUCORE */ |
---|
.. | .. |
---|
5398 | 5288 | |
---|
5399 | 5289 | /* Call bus dpc unless it indicated down (then clean stop) */ |
---|
5400 | 5290 | if (dhd->pub.busstate != DHD_BUS_DOWN) { |
---|
5401 | | -/* |
---|
5402 | | - * Enable this to prevent CPU loading too high on some platforms |
---|
5403 | | - */ |
---|
5404 | | -#if defined(CUSTOMER_IPCAM) |
---|
| 5291 | +#ifdef DEBUG_DPC_THREAD_WATCHDOG |
---|
5405 | 5292 | int resched_cnt = 0; |
---|
5406 | | -#endif |
---|
| 5293 | +#endif /* DEBUG_DPC_THREAD_WATCHDOG */ |
---|
5407 | 5294 | dhd_os_wd_timer_extend(&dhd->pub, TRUE); |
---|
5408 | 5295 | while (dhd_bus_dpc(dhd->pub.bus)) { |
---|
5409 | 5296 | /* process all data */ |
---|
5410 | | -#if defined(CUSTOMER_IPCAM) |
---|
| 5297 | +#ifdef DEBUG_DPC_THREAD_WATCHDOG |
---|
5411 | 5298 | resched_cnt++; |
---|
5412 | 5299 | if (resched_cnt > MAX_RESCHED_CNT) { |
---|
5413 | 5300 | DHD_INFO(("%s Calling msleep to" |
---|
5414 | 5301 | "let other processes run. \n", |
---|
5415 | 5302 | __FUNCTION__)); |
---|
5416 | | -#ifndef CUSTOMER_IPCAM |
---|
5417 | 5303 | dhd->pub.dhd_bug_on = true; |
---|
5418 | | -#endif |
---|
5419 | 5304 | resched_cnt = 0; |
---|
5420 | 5305 | OSL_SLEEP(1); |
---|
5421 | 5306 | } |
---|
5422 | | -#endif |
---|
| 5307 | +#endif /* DEBUG_DPC_THREAD_WATCHDOG */ |
---|
5423 | 5308 | } |
---|
5424 | 5309 | dhd_os_wd_timer_extend(&dhd->pub, FALSE); |
---|
5425 | 5310 | DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
5426 | | - |
---|
5427 | 5311 | } else { |
---|
5428 | 5312 | if (dhd->pub.up) |
---|
5429 | 5313 | dhd_bus_stop(dhd->pub.bus, TRUE); |
---|
.. | .. |
---|
5444 | 5328 | #if defined(WAIT_DEQUEUE) |
---|
5445 | 5329 | #define RXF_WATCHDOG_TIME 250 /* BARK_TIME(1000) / */ |
---|
5446 | 5330 | ulong watchdogTime = OSL_SYSUPTIME(); /* msec */ |
---|
5447 | | -#endif |
---|
| 5331 | +#endif // endif |
---|
5448 | 5332 | dhd_pub_t *pub = &dhd->pub; |
---|
5449 | 5333 | |
---|
5450 | 5334 | /* This thread doesn't need any user-level access, |
---|
.. | .. |
---|
5457 | 5341 | setScheduler(current, SCHED_FIFO, ¶m); |
---|
5458 | 5342 | } |
---|
5459 | 5343 | |
---|
5460 | | - DAEMONIZE("dhd_rxf"); |
---|
5461 | | - /* DHD_OS_WAKE_LOCK is called in dhd_sched_dpc[dhd_linux.c] down below */ |
---|
5462 | | - |
---|
5463 | | - /* signal: thread has started */ |
---|
5464 | | - complete(&tsk->completed); |
---|
5465 | 5344 | #ifdef CUSTOM_SET_CPUCORE |
---|
5466 | 5345 | dhd->pub.current_rxf = current; |
---|
5467 | 5346 | #endif /* CUSTOM_SET_CPUCORE */ |
---|
.. | .. |
---|
5469 | 5348 | while (1) { |
---|
5470 | 5349 | if (down_interruptible(&tsk->sema) == 0) { |
---|
5471 | 5350 | void *skb; |
---|
5472 | | -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) |
---|
5473 | | - ulong flags; |
---|
5474 | | -#endif |
---|
5475 | 5351 | #ifdef ENABLE_ADAPTIVE_SCHED |
---|
5476 | 5352 | dhd_sched_policy(dhd_rxf_prio); |
---|
5477 | 5353 | #endif /* ENABLE_ADAPTIVE_SCHED */ |
---|
.. | .. |
---|
5491 | 5367 | PKTSETNEXT(pub->osh, skb, NULL); |
---|
5492 | 5368 | bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, |
---|
5493 | 5369 | __FUNCTION__, __LINE__); |
---|
5494 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) |
---|
5495 | 5370 | netif_rx_ni(skb); |
---|
5496 | | -#else |
---|
5497 | | - netif_rx(skb); |
---|
5498 | | - local_irq_save(flags); |
---|
5499 | | - RAISE_RX_SOFTIRQ(); |
---|
5500 | | - local_irq_restore(flags); |
---|
5501 | | - |
---|
5502 | | -#endif |
---|
5503 | 5371 | skb = skbnext; |
---|
5504 | 5372 | } |
---|
5505 | 5373 | #if defined(WAIT_DEQUEUE) |
---|
.. | .. |
---|
5507 | 5375 | OSL_SLEEP(1); |
---|
5508 | 5376 | watchdogTime = OSL_SYSUPTIME(); |
---|
5509 | 5377 | } |
---|
5510 | | -#endif |
---|
| 5378 | +#endif // endif |
---|
5511 | 5379 | |
---|
5512 | 5380 | DHD_OS_WAKE_UNLOCK(pub); |
---|
5513 | 5381 | } else { |
---|
.. | .. |
---|
5520 | 5388 | #ifdef BCMPCIE |
---|
5521 | 5389 | void dhd_dpc_enable(dhd_pub_t *dhdp) |
---|
5522 | 5390 | { |
---|
| 5391 | +#if defined(DHD_LB_RXP) || defined(DHD_LB_TXP) |
---|
5523 | 5392 | dhd_info_t *dhd; |
---|
5524 | 5393 | |
---|
5525 | 5394 | if (!dhdp || !dhdp->info) |
---|
5526 | 5395 | return; |
---|
5527 | 5396 | dhd = dhdp->info; |
---|
| 5397 | +#endif /* DHD_LB_RXP || DHD_LB_TXP */ |
---|
5528 | 5398 | |
---|
5529 | | -#ifdef DHD_LB |
---|
5530 | 5399 | #ifdef DHD_LB_RXP |
---|
5531 | 5400 | __skb_queue_head_init(&dhd->rx_pend_queue); |
---|
5532 | 5401 | #endif /* DHD_LB_RXP */ |
---|
5533 | | -#ifdef DHD_LB_TXC |
---|
5534 | | - if (atomic_read(&dhd->tx_compl_tasklet.count) == 1) |
---|
5535 | | - tasklet_enable(&dhd->tx_compl_tasklet); |
---|
5536 | | -#endif /* DHD_LB_TXC */ |
---|
5537 | | -#ifdef DHD_LB_RXC |
---|
5538 | | - if (atomic_read(&dhd->rx_compl_tasklet.count) == 1) |
---|
5539 | | - tasklet_enable(&dhd->rx_compl_tasklet); |
---|
5540 | | -#endif /* DHD_LB_RXC */ |
---|
5541 | | -#endif /* DHD_LB */ |
---|
5542 | | - if (atomic_read(&dhd->tasklet.count) == 1) |
---|
5543 | | - tasklet_enable(&dhd->tasklet); |
---|
| 5402 | + |
---|
| 5403 | +#ifdef DHD_LB_TXP |
---|
| 5404 | + skb_queue_head_init(&dhd->tx_pend_queue); |
---|
| 5405 | +#endif /* DHD_LB_TXP */ |
---|
5544 | 5406 | } |
---|
5545 | 5407 | #endif /* BCMPCIE */ |
---|
5546 | | - |
---|
5547 | 5408 | |
---|
5548 | 5409 | #ifdef BCMPCIE |
---|
5549 | 5410 | void |
---|
.. | .. |
---|
5562 | 5423 | } |
---|
5563 | 5424 | |
---|
5564 | 5425 | if (dhd->thr_dpc_ctl.thr_pid < 0) { |
---|
5565 | | - tasklet_disable(&dhd->tasklet); |
---|
5566 | 5426 | tasklet_kill(&dhd->tasklet); |
---|
5567 | 5427 | DHD_ERROR(("%s: tasklet disabled\n", __FUNCTION__)); |
---|
5568 | 5428 | } |
---|
5569 | | -#if defined(DHD_LB) |
---|
| 5429 | + |
---|
| 5430 | +#ifdef DHD_LB |
---|
5570 | 5431 | #ifdef DHD_LB_RXP |
---|
| 5432 | + cancel_work_sync(&dhd->rx_napi_dispatcher_work); |
---|
5571 | 5433 | __skb_queue_purge(&dhd->rx_pend_queue); |
---|
5572 | 5434 | #endif /* DHD_LB_RXP */ |
---|
| 5435 | +#ifdef DHD_LB_TXP |
---|
| 5436 | + cancel_work_sync(&dhd->tx_dispatcher_work); |
---|
| 5437 | + skb_queue_purge(&dhd->tx_pend_queue); |
---|
| 5438 | +#endif /* DHD_LB_TXP */ |
---|
| 5439 | + |
---|
5573 | 5440 | /* Kill the Load Balancing Tasklets */ |
---|
5574 | 5441 | #if defined(DHD_LB_TXC) |
---|
5575 | | - tasklet_disable(&dhd->tx_compl_tasklet); |
---|
5576 | 5442 | tasklet_kill(&dhd->tx_compl_tasklet); |
---|
5577 | 5443 | #endif /* DHD_LB_TXC */ |
---|
5578 | 5444 | #if defined(DHD_LB_RXC) |
---|
5579 | | - tasklet_disable(&dhd->rx_compl_tasklet); |
---|
5580 | 5445 | tasklet_kill(&dhd->rx_compl_tasklet); |
---|
5581 | 5446 | #endif /* DHD_LB_RXC */ |
---|
| 5447 | +#if defined(DHD_LB_TXP) |
---|
| 5448 | + tasklet_kill(&dhd->tx_tasklet); |
---|
| 5449 | +#endif /* DHD_LB_TXP */ |
---|
5582 | 5450 | #endif /* DHD_LB */ |
---|
| 5451 | +} |
---|
| 5452 | + |
---|
| 5453 | +void |
---|
| 5454 | +dhd_dpc_tasklet_kill(dhd_pub_t *dhdp) |
---|
| 5455 | +{ |
---|
| 5456 | + dhd_info_t *dhd; |
---|
| 5457 | + |
---|
| 5458 | + if (!dhdp) { |
---|
| 5459 | + return; |
---|
| 5460 | + } |
---|
| 5461 | + |
---|
| 5462 | + dhd = dhdp->info; |
---|
| 5463 | + |
---|
| 5464 | + if (!dhd) { |
---|
| 5465 | + return; |
---|
| 5466 | + } |
---|
| 5467 | + |
---|
| 5468 | + if (dhd->thr_dpc_ctl.thr_pid < 0) { |
---|
| 5469 | + tasklet_kill(&dhd->tasklet); |
---|
| 5470 | + } |
---|
5583 | 5471 | } |
---|
5584 | 5472 | #endif /* BCMPCIE */ |
---|
5585 | 5473 | |
---|
.. | .. |
---|
5589 | 5477 | dhd_info_t *dhd; |
---|
5590 | 5478 | |
---|
5591 | 5479 | dhd = (dhd_info_t *)data; |
---|
5592 | | - DHD_OS_WAKE_LOCK(&dhd->pub); |
---|
5593 | 5480 | |
---|
5594 | 5481 | /* this (tasklet) can be scheduled in dhd_sched_dpc[dhd_linux.c] |
---|
5595 | 5482 | * down below , wake lock is set, |
---|
.. | .. |
---|
5597 | 5484 | */ |
---|
5598 | 5485 | /* Call bus dpc unless it indicated down (then clean stop) */ |
---|
5599 | 5486 | if (dhd->pub.busstate != DHD_BUS_DOWN) { |
---|
| 5487 | +#if defined(DHD_LB_STATS) && defined(PCIE_FULL_DONGLE) |
---|
| 5488 | + DHD_LB_STATS_INCR(dhd->dhd_dpc_cnt); |
---|
| 5489 | +#endif /* DHD_LB_STATS && PCIE_FULL_DONGLE */ |
---|
5600 | 5490 | if (dhd_bus_dpc(dhd->pub.bus)) { |
---|
5601 | | - DHD_LB_STATS_INCR(dhd->dhd_dpc_cnt); |
---|
5602 | 5491 | tasklet_schedule(&dhd->tasklet); |
---|
5603 | 5492 | } |
---|
5604 | 5493 | } else { |
---|
5605 | 5494 | dhd_bus_stop(dhd->pub.bus, TRUE); |
---|
5606 | 5495 | } |
---|
5607 | | - DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
5608 | 5496 | } |
---|
5609 | 5497 | |
---|
5610 | 5498 | void |
---|
.. | .. |
---|
5622 | 5510 | } |
---|
5623 | 5511 | return; |
---|
5624 | 5512 | } else { |
---|
5625 | | - if (!test_bit(TASKLET_STATE_SCHED, &dhd->tasklet.state)) { |
---|
5626 | | - DHD_OS_WAKE_LOCK(dhdp); |
---|
5627 | | - } |
---|
| 5513 | + dhd_bus_set_dpc_sched_time(dhdp); |
---|
5628 | 5514 | tasklet_schedule(&dhd->tasklet); |
---|
5629 | | - DHD_OS_WAKE_UNLOCK(dhdp); |
---|
5630 | 5515 | } |
---|
5631 | 5516 | } |
---|
5632 | | -#endif /* BCMDBUS */ |
---|
5633 | 5517 | |
---|
5634 | 5518 | static void |
---|
5635 | 5519 | dhd_sched_rxf(dhd_pub_t *dhdp, void *skb) |
---|
5636 | 5520 | { |
---|
5637 | 5521 | dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
5638 | | -#ifdef RXF_DEQUEUE_ON_BUSY |
---|
5639 | | - int ret = BCME_OK; |
---|
5640 | | - int retry = 2; |
---|
5641 | | -#endif /* RXF_DEQUEUE_ON_BUSY */ |
---|
5642 | 5522 | |
---|
5643 | 5523 | DHD_OS_WAKE_LOCK(dhdp); |
---|
5644 | 5524 | |
---|
5645 | 5525 | DHD_TRACE(("dhd_sched_rxf: Enter\n")); |
---|
5646 | | -#ifdef RXF_DEQUEUE_ON_BUSY |
---|
5647 | | - do { |
---|
5648 | | - ret = dhd_rxf_enqueue(dhdp, skb); |
---|
5649 | | - if (ret == BCME_OK || ret == BCME_ERROR) |
---|
5650 | | - break; |
---|
5651 | | - else |
---|
5652 | | - OSL_SLEEP(50); /* waiting for dequeueing */ |
---|
5653 | | - } while (retry-- > 0); |
---|
5654 | | - |
---|
5655 | | - if (retry <= 0 && ret == BCME_BUSY) { |
---|
5656 | | - void *skbp = skb; |
---|
5657 | | - |
---|
5658 | | - while (skbp) { |
---|
5659 | | - void *skbnext = PKTNEXT(dhdp->osh, skbp); |
---|
5660 | | - PKTSETNEXT(dhdp->osh, skbp, NULL); |
---|
5661 | | - bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, |
---|
5662 | | - __FUNCTION__, __LINE__); |
---|
5663 | | - netif_rx_ni(skbp); |
---|
5664 | | - skbp = skbnext; |
---|
5665 | | - } |
---|
5666 | | - DHD_ERROR(("send skb to kernel backlog without rxf_thread\n")); |
---|
5667 | | - } else { |
---|
5668 | | - if (dhd->thr_rxf_ctl.thr_pid >= 0) { |
---|
5669 | | - up(&dhd->thr_rxf_ctl.sema); |
---|
5670 | | - } |
---|
5671 | | - } |
---|
5672 | | -#else /* RXF_DEQUEUE_ON_BUSY */ |
---|
5673 | 5526 | do { |
---|
5674 | 5527 | if (dhd_rxf_enqueue(dhdp, skb) == BCME_OK) |
---|
5675 | 5528 | break; |
---|
.. | .. |
---|
5678 | 5531 | up(&dhd->thr_rxf_ctl.sema); |
---|
5679 | 5532 | } |
---|
5680 | 5533 | return; |
---|
5681 | | -#endif /* RXF_DEQUEUE_ON_BUSY */ |
---|
5682 | 5534 | } |
---|
5683 | 5535 | |
---|
5684 | 5536 | #if defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) |
---|
5685 | | -#if defined(BCMDBUS) |
---|
5686 | | -static int |
---|
5687 | | -fw_download_thread_func(void *data) |
---|
5688 | | -{ |
---|
5689 | | - dhd_info_t *dhd = (dhd_info_t *)data; |
---|
5690 | | - int ret; |
---|
5691 | | - |
---|
5692 | | - while (1) { |
---|
5693 | | - /* Wait for start trigger */ |
---|
5694 | | - if (down_interruptible(&dhd->fw_download_lock) != 0) |
---|
5695 | | - return -ERESTARTSYS; |
---|
5696 | | - |
---|
5697 | | - if (kthread_should_stop()) |
---|
5698 | | - break; |
---|
5699 | | - |
---|
5700 | | - DHD_TRACE(("%s: initiating firmware check and download\n", __FUNCTION__)); |
---|
5701 | | - if (dbus_download_firmware(dhd->pub.dbus) == DBUS_OK) { |
---|
5702 | | - if ((ret = dbus_up(dhd->pub.dbus)) == 0) { |
---|
5703 | | -#ifdef PROP_TXSTATUS |
---|
5704 | | - /* Need to deinitialise WLFC to allow re-initialisation later. */ |
---|
5705 | | - dhd_wlfc_deinit(&dhd->pub); |
---|
5706 | | -#endif /* PROP_TXSTATUS */ |
---|
5707 | | - /* Resynchronise with the dongle. This also re-initialises WLFC. */ |
---|
5708 | | - if ((ret = dhd_sync_with_dongle(&dhd->pub)) < 0) { |
---|
5709 | | - DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); |
---|
5710 | | - } |
---|
5711 | | - } |
---|
5712 | | - } |
---|
5713 | | - } |
---|
5714 | | - |
---|
5715 | | - return 0; |
---|
5716 | | -} |
---|
5717 | | -#endif /* BCMDBUS */ |
---|
5718 | 5537 | #endif /* defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) */ |
---|
5719 | 5538 | |
---|
5720 | 5539 | #ifdef TOE |
---|
.. | .. |
---|
5797 | 5616 | } |
---|
5798 | 5617 | #endif /* WL_CFG80211 && NUM_SCB_MAX_PROBE */ |
---|
5799 | 5618 | |
---|
5800 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) |
---|
5801 | 5619 | static void |
---|
5802 | 5620 | dhd_ethtool_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) |
---|
5803 | 5621 | { |
---|
.. | .. |
---|
5810 | 5628 | struct ethtool_ops dhd_ethtool_ops = { |
---|
5811 | 5629 | .get_drvinfo = dhd_ethtool_get_drvinfo |
---|
5812 | 5630 | }; |
---|
5813 | | -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ |
---|
5814 | 5631 | |
---|
5815 | | - |
---|
5816 | | -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) |
---|
5817 | 5632 | static int |
---|
5818 | 5633 | dhd_ethtool(dhd_info_t *dhd, void *uaddr) |
---|
5819 | 5634 | { |
---|
.. | .. |
---|
5824 | 5639 | struct ethtool_value edata; |
---|
5825 | 5640 | uint32 toe_cmpnt, csum_dir; |
---|
5826 | 5641 | int ret; |
---|
5827 | | -#endif |
---|
| 5642 | +#endif // endif |
---|
5828 | 5643 | |
---|
5829 | 5644 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
5830 | 5645 | |
---|
.. | .. |
---|
5923 | 5738 | |
---|
5924 | 5739 | return 0; |
---|
5925 | 5740 | } |
---|
5926 | | -#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ |
---|
5927 | 5741 | |
---|
5928 | 5742 | static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) |
---|
5929 | 5743 | { |
---|
5930 | | - dhd_info_t *dhd; |
---|
5931 | | -#ifdef DHD_FW_COREDUMP |
---|
5932 | | - int dump_len = 0; |
---|
5933 | | -#endif /* DHD_FW_COREDUMP */ |
---|
5934 | | - |
---|
| 5744 | +#if defined(OEM_ANDROID) |
---|
5935 | 5745 | if (!dhdp) { |
---|
5936 | 5746 | DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__)); |
---|
5937 | 5747 | return FALSE; |
---|
.. | .. |
---|
5940 | 5750 | if (!dhdp->up) |
---|
5941 | 5751 | return FALSE; |
---|
5942 | 5752 | |
---|
5943 | | - dhd = (dhd_info_t *)dhdp->info; |
---|
5944 | | -#if (!defined(BCMDBUS) && !defined(BCMPCIE)) |
---|
5945 | | - if (dhd->thr_dpc_ctl.thr_pid < 0) { |
---|
| 5753 | +#if !defined(BCMPCIE) |
---|
| 5754 | + if (dhdp->info->thr_dpc_ctl.thr_pid < 0) { |
---|
5946 | 5755 | DHD_ERROR(("%s : skipped due to negative pid - unloading?\n", __FUNCTION__)); |
---|
5947 | 5756 | return FALSE; |
---|
5948 | 5757 | } |
---|
5949 | | -#endif /* BCMDBUS */ |
---|
5950 | | -#ifdef DHD_FW_COREDUMP |
---|
5951 | | - if (error == -ETIMEDOUT && dhdp->busstate != DHD_BUS_DOWN) { |
---|
5952 | | - if (dhd_os_socram_dump(net, &dump_len) == BCME_OK) { |
---|
5953 | | - dhd_dbg_send_urgent_evt(dhdp, NULL, 0); |
---|
5954 | | - } |
---|
5955 | | - } |
---|
5956 | | -#endif /* DHD_FW_COREDUMP */ |
---|
| 5758 | +#endif // endif |
---|
| 5759 | + |
---|
5957 | 5760 | if ((error == -ETIMEDOUT) || (error == -EREMOTEIO) || |
---|
5958 | 5761 | ((dhdp->busstate == DHD_BUS_DOWN) && (!dhdp->dongle_reset))) { |
---|
5959 | 5762 | #ifdef BCMPCIE |
---|
.. | .. |
---|
5964 | 5767 | DHD_ERROR(("%s: Event HANG send up due to re=%d te=%d e=%d s=%d\n", __FUNCTION__, |
---|
5965 | 5768 | dhdp->rxcnt_timeout, dhdp->txcnt_timeout, error, dhdp->busstate)); |
---|
5966 | 5769 | #endif /* BCMPCIE */ |
---|
| 5770 | + if (dhdp->hang_reason == 0) { |
---|
| 5771 | + if (dhdp->dongle_trap_occured) { |
---|
| 5772 | + dhdp->hang_reason = HANG_REASON_DONGLE_TRAP; |
---|
| 5773 | +#ifdef BCMPCIE |
---|
| 5774 | + } else if (dhdp->d3ackcnt_timeout) { |
---|
| 5775 | + dhdp->hang_reason = dhdp->is_sched_error ? |
---|
| 5776 | + HANG_REASON_D3_ACK_TIMEOUT_SCHED_ERROR : |
---|
| 5777 | + HANG_REASON_D3_ACK_TIMEOUT; |
---|
| 5778 | +#endif /* BCMPCIE */ |
---|
| 5779 | + } else { |
---|
| 5780 | + dhdp->hang_reason = dhdp->is_sched_error ? |
---|
| 5781 | + HANG_REASON_IOCTL_RESP_TIMEOUT_SCHED_ERROR : |
---|
| 5782 | + HANG_REASON_IOCTL_RESP_TIMEOUT; |
---|
| 5783 | + } |
---|
| 5784 | + } |
---|
5967 | 5785 | net_os_send_hang_message(net); |
---|
5968 | 5786 | return TRUE; |
---|
5969 | 5787 | } |
---|
| 5788 | +#endif /* OEM_ANDROID */ |
---|
5970 | 5789 | return FALSE; |
---|
5971 | 5790 | } |
---|
| 5791 | + |
---|
| 5792 | +#ifdef WL_MONITOR |
---|
| 5793 | +bool |
---|
| 5794 | +dhd_monitor_enabled(dhd_pub_t *dhd, int ifidx) |
---|
| 5795 | +{ |
---|
| 5796 | + return (dhd->info->monitor_type != 0); |
---|
| 5797 | +} |
---|
| 5798 | + |
---|
| 5799 | +void |
---|
| 5800 | +dhd_rx_mon_pkt(dhd_pub_t *dhdp, host_rxbuf_cmpl_t* msg, void *pkt, int ifidx) |
---|
| 5801 | +{ |
---|
| 5802 | + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
| 5803 | + { |
---|
| 5804 | + uint8 amsdu_flag = (msg->flags & BCMPCIE_PKT_FLAGS_MONITOR_MASK) >> |
---|
| 5805 | + BCMPCIE_PKT_FLAGS_MONITOR_SHIFT; |
---|
| 5806 | + switch (amsdu_flag) { |
---|
| 5807 | + case BCMPCIE_PKT_FLAGS_MONITOR_NO_AMSDU: |
---|
| 5808 | + default: |
---|
| 5809 | + if (!dhd->monitor_skb) { |
---|
| 5810 | + if ((dhd->monitor_skb = PKTTONATIVE(dhdp->osh, pkt)) |
---|
| 5811 | + == NULL) |
---|
| 5812 | + return; |
---|
| 5813 | + } |
---|
| 5814 | + if (dhd->monitor_type && dhd->monitor_dev) |
---|
| 5815 | + dhd->monitor_skb->dev = dhd->monitor_dev; |
---|
| 5816 | + else { |
---|
| 5817 | + PKTFREE(dhdp->osh, pkt, FALSE); |
---|
| 5818 | + dhd->monitor_skb = NULL; |
---|
| 5819 | + return; |
---|
| 5820 | + } |
---|
| 5821 | + dhd->monitor_skb->protocol = |
---|
| 5822 | + eth_type_trans(dhd->monitor_skb, dhd->monitor_skb->dev); |
---|
| 5823 | + dhd->monitor_len = 0; |
---|
| 5824 | + break; |
---|
| 5825 | + |
---|
| 5826 | + case BCMPCIE_PKT_FLAGS_MONITOR_FIRST_PKT: |
---|
| 5827 | + if (!dhd->monitor_skb) { |
---|
| 5828 | + if ((dhd->monitor_skb = dev_alloc_skb(MAX_MON_PKT_SIZE)) |
---|
| 5829 | + == NULL) |
---|
| 5830 | + return; |
---|
| 5831 | + dhd->monitor_len = 0; |
---|
| 5832 | + } |
---|
| 5833 | + if (dhd->monitor_type && dhd->monitor_dev) |
---|
| 5834 | + dhd->monitor_skb->dev = dhd->monitor_dev; |
---|
| 5835 | + else { |
---|
| 5836 | + PKTFREE(dhdp->osh, pkt, FALSE); |
---|
| 5837 | + dev_kfree_skb(dhd->monitor_skb); |
---|
| 5838 | + return; |
---|
| 5839 | + } |
---|
| 5840 | + memcpy(PKTDATA(dhdp->osh, dhd->monitor_skb), |
---|
| 5841 | + PKTDATA(dhdp->osh, pkt), PKTLEN(dhdp->osh, pkt)); |
---|
| 5842 | + dhd->monitor_len = PKTLEN(dhdp->osh, pkt); |
---|
| 5843 | + PKTFREE(dhdp->osh, pkt, FALSE); |
---|
| 5844 | + return; |
---|
| 5845 | + |
---|
| 5846 | + case BCMPCIE_PKT_FLAGS_MONITOR_INTER_PKT: |
---|
| 5847 | + memcpy(PKTDATA(dhdp->osh, dhd->monitor_skb) + dhd->monitor_len, |
---|
| 5848 | + PKTDATA(dhdp->osh, pkt), PKTLEN(dhdp->osh, pkt)); |
---|
| 5849 | + dhd->monitor_len += PKTLEN(dhdp->osh, pkt); |
---|
| 5850 | + PKTFREE(dhdp->osh, pkt, FALSE); |
---|
| 5851 | + return; |
---|
| 5852 | + |
---|
| 5853 | + case BCMPCIE_PKT_FLAGS_MONITOR_LAST_PKT: |
---|
| 5854 | + memcpy(PKTDATA(dhdp->osh, dhd->monitor_skb) + dhd->monitor_len, |
---|
| 5855 | + PKTDATA(dhdp->osh, pkt), PKTLEN(dhdp->osh, pkt)); |
---|
| 5856 | + dhd->monitor_len += PKTLEN(dhdp->osh, pkt); |
---|
| 5857 | + PKTFREE(dhdp->osh, pkt, FALSE); |
---|
| 5858 | + skb_put(dhd->monitor_skb, dhd->monitor_len); |
---|
| 5859 | + dhd->monitor_skb->protocol = |
---|
| 5860 | + eth_type_trans(dhd->monitor_skb, dhd->monitor_skb->dev); |
---|
| 5861 | + dhd->monitor_len = 0; |
---|
| 5862 | + break; |
---|
| 5863 | + } |
---|
| 5864 | + } |
---|
| 5865 | + |
---|
| 5866 | + if (in_interrupt()) { |
---|
| 5867 | + bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, |
---|
| 5868 | + __FUNCTION__, __LINE__); |
---|
| 5869 | + DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
| 5870 | + netif_rx(dhd->monitor_skb); |
---|
| 5871 | + DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
| 5872 | + } else { |
---|
| 5873 | + /* If the receive is not processed inside an ISR, |
---|
| 5874 | + * the softirqd must be woken explicitly to service |
---|
| 5875 | + * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled |
---|
| 5876 | + * by netif_rx_ni(), but in earlier kernels, we need |
---|
| 5877 | + * to do it manually. |
---|
| 5878 | + */ |
---|
| 5879 | + bcm_object_trace_opr(dhd->monitor_skb, BCM_OBJDBG_REMOVE, |
---|
| 5880 | + __FUNCTION__, __LINE__); |
---|
| 5881 | + |
---|
| 5882 | + DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
| 5883 | + netif_rx_ni(dhd->monitor_skb); |
---|
| 5884 | + DHD_PERIM_LOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); |
---|
| 5885 | + } |
---|
| 5886 | + |
---|
| 5887 | + dhd->monitor_skb = NULL; |
---|
| 5888 | +} |
---|
| 5889 | + |
---|
| 5890 | +typedef struct dhd_mon_dev_priv { |
---|
| 5891 | + struct net_device_stats stats; |
---|
| 5892 | +} dhd_mon_dev_priv_t; |
---|
| 5893 | + |
---|
| 5894 | +#define DHD_MON_DEV_PRIV_SIZE (sizeof(dhd_mon_dev_priv_t)) |
---|
| 5895 | +#define DHD_MON_DEV_PRIV(dev) ((dhd_mon_dev_priv_t *)DEV_PRIV(dev)) |
---|
| 5896 | +#define DHD_MON_DEV_STATS(dev) (((dhd_mon_dev_priv_t *)DEV_PRIV(dev))->stats) |
---|
| 5897 | + |
---|
| 5898 | +#ifdef CFI_CHECK |
---|
| 5899 | +static netdev_tx_t |
---|
| 5900 | +#else |
---|
| 5901 | +static int |
---|
| 5902 | +#endif /* CFI_CHECK */ |
---|
| 5903 | +dhd_monitor_start(struct sk_buff *skb, struct net_device *dev) |
---|
| 5904 | +{ |
---|
| 5905 | + PKTFREE(NULL, skb, FALSE); |
---|
| 5906 | +#ifdef CFI_CHECK |
---|
| 5907 | + return NETDEV_TX_OK; |
---|
| 5908 | +#else |
---|
| 5909 | + return 0; |
---|
| 5910 | +#endif /* CFI_CHECK */ |
---|
| 5911 | +} |
---|
| 5912 | + |
---|
| 5913 | +static int |
---|
| 5914 | +dhd_monitor_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
---|
| 5915 | +{ |
---|
| 5916 | + return 0; |
---|
| 5917 | +} |
---|
| 5918 | + |
---|
| 5919 | +static struct net_device_stats* |
---|
| 5920 | +dhd_monitor_get_stats(struct net_device *dev) |
---|
| 5921 | +{ |
---|
| 5922 | + return &DHD_MON_DEV_STATS(dev); |
---|
| 5923 | +} |
---|
| 5924 | + |
---|
| 5925 | +static const struct net_device_ops netdev_monitor_ops = |
---|
| 5926 | +{ |
---|
| 5927 | + .ndo_start_xmit = dhd_monitor_start, |
---|
| 5928 | + .ndo_get_stats = dhd_monitor_get_stats, |
---|
| 5929 | + .ndo_do_ioctl = dhd_monitor_ioctl |
---|
| 5930 | +}; |
---|
| 5931 | + |
---|
| 5932 | +static void |
---|
| 5933 | +dhd_add_monitor_if(dhd_info_t *dhd) |
---|
| 5934 | +{ |
---|
| 5935 | + struct net_device *dev; |
---|
| 5936 | + char *devname; |
---|
| 5937 | + uint32 scan_suppress = FALSE; |
---|
| 5938 | + int ret = BCME_OK; |
---|
| 5939 | + |
---|
| 5940 | + if (!dhd) { |
---|
| 5941 | + DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); |
---|
| 5942 | + return; |
---|
| 5943 | + } |
---|
| 5944 | + |
---|
| 5945 | + if (dhd->monitor_dev) { |
---|
| 5946 | + DHD_ERROR(("%s: monitor i/f already exists", __FUNCTION__)); |
---|
| 5947 | + return; |
---|
| 5948 | + } |
---|
| 5949 | + |
---|
| 5950 | + dev = alloc_etherdev(DHD_MON_DEV_PRIV_SIZE); |
---|
| 5951 | + if (!dev) { |
---|
| 5952 | + DHD_ERROR(("%s: alloc wlif failed\n", __FUNCTION__)); |
---|
| 5953 | + return; |
---|
| 5954 | + } |
---|
| 5955 | + |
---|
| 5956 | + devname = "radiotap"; |
---|
| 5957 | + |
---|
| 5958 | + snprintf(dev->name, sizeof(dev->name), "%s%u", devname, dhd->unit); |
---|
| 5959 | + |
---|
| 5960 | +#ifndef ARPHRD_IEEE80211_PRISM /* From Linux 2.4.18 */ |
---|
| 5961 | +#define ARPHRD_IEEE80211_PRISM 802 |
---|
| 5962 | +#endif // endif |
---|
| 5963 | + |
---|
| 5964 | +#ifndef ARPHRD_IEEE80211_RADIOTAP |
---|
| 5965 | +#define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */ |
---|
| 5966 | +#endif /* ARPHRD_IEEE80211_RADIOTAP */ |
---|
| 5967 | + |
---|
| 5968 | + dev->type = ARPHRD_IEEE80211_RADIOTAP; |
---|
| 5969 | + |
---|
| 5970 | + dev->netdev_ops = &netdev_monitor_ops; |
---|
| 5971 | + |
---|
| 5972 | + if (register_netdevice(dev)) { |
---|
| 5973 | + DHD_ERROR(("%s, register_netdev failed for %s\n", |
---|
| 5974 | + __FUNCTION__, dev->name)); |
---|
| 5975 | + free_netdev(dev); |
---|
| 5976 | + return; |
---|
| 5977 | + } |
---|
| 5978 | + |
---|
| 5979 | + if (FW_SUPPORTED((&dhd->pub), monitor)) { |
---|
| 5980 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 5981 | + /* Disable RuntimePM in monitor mode */ |
---|
| 5982 | + DHD_DISABLE_RUNTIME_PM(&dhd->pub); |
---|
| 5983 | + DHD_ERROR(("%s : disable runtime PM in monitor mode\n", __FUNCTION__)); |
---|
| 5984 | +#endif /* DHD_PCIE_RUNTIME_PM */ |
---|
| 5985 | + scan_suppress = TRUE; |
---|
| 5986 | + /* Set the SCAN SUPPRESS Flag in the firmware to disable scan in Monitor mode */ |
---|
| 5987 | + ret = dhd_iovar(&dhd->pub, 0, "scansuppress", (char *)&scan_suppress, |
---|
| 5988 | + sizeof(scan_suppress), NULL, 0, TRUE); |
---|
| 5989 | + if (ret < 0) { |
---|
| 5990 | + DHD_ERROR(("%s: scansuppress set failed, ret=%d\n", __FUNCTION__, ret)); |
---|
| 5991 | + } |
---|
| 5992 | + } |
---|
| 5993 | + |
---|
| 5994 | + dhd->monitor_dev = dev; |
---|
| 5995 | +} |
---|
| 5996 | + |
---|
| 5997 | +static void |
---|
| 5998 | +dhd_del_monitor_if(dhd_info_t *dhd) |
---|
| 5999 | +{ |
---|
| 6000 | + int ret = BCME_OK; |
---|
| 6001 | + uint32 scan_suppress = FALSE; |
---|
| 6002 | + |
---|
| 6003 | + if (!dhd) { |
---|
| 6004 | + DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); |
---|
| 6005 | + return; |
---|
| 6006 | + } |
---|
| 6007 | + |
---|
| 6008 | + if (!dhd->monitor_dev) { |
---|
| 6009 | + DHD_ERROR(("%s: monitor i/f doesn't exist", __FUNCTION__)); |
---|
| 6010 | + return; |
---|
| 6011 | + } |
---|
| 6012 | + |
---|
| 6013 | + if (FW_SUPPORTED((&dhd->pub), monitor)) { |
---|
| 6014 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 6015 | + /* Enable RuntimePM */ |
---|
| 6016 | + DHD_ENABLE_RUNTIME_PM(&dhd->pub); |
---|
| 6017 | + DHD_ERROR(("%s : enabled runtime PM\n", __FUNCTION__)); |
---|
| 6018 | +#endif /* DHD_PCIE_RUNTIME_PM */ |
---|
| 6019 | + scan_suppress = FALSE; |
---|
| 6020 | + /* Unset the SCAN SUPPRESS Flag in the firmware to enable scan */ |
---|
| 6021 | + ret = dhd_iovar(&dhd->pub, 0, "scansuppress", (char *)&scan_suppress, |
---|
| 6022 | + sizeof(scan_suppress), NULL, 0, TRUE); |
---|
| 6023 | + if (ret < 0) { |
---|
| 6024 | + DHD_ERROR(("%s: scansuppress set failed, ret=%d\n", __FUNCTION__, ret)); |
---|
| 6025 | + } |
---|
| 6026 | + } |
---|
| 6027 | + |
---|
| 6028 | + if (dhd->monitor_dev) { |
---|
| 6029 | + if (dhd->monitor_dev->reg_state == NETREG_UNINITIALIZED) { |
---|
| 6030 | + free_netdev(dhd->monitor_dev); |
---|
| 6031 | + } else { |
---|
| 6032 | + unregister_netdevice(dhd->monitor_dev); |
---|
| 6033 | + } |
---|
| 6034 | + dhd->monitor_dev = NULL; |
---|
| 6035 | + } |
---|
| 6036 | +} |
---|
| 6037 | + |
---|
| 6038 | +static void |
---|
| 6039 | +dhd_set_monitor(dhd_pub_t *pub, int ifidx, int val) |
---|
| 6040 | +{ |
---|
| 6041 | + dhd_info_t *dhd = pub->info; |
---|
| 6042 | + |
---|
| 6043 | + DHD_TRACE(("%s: val %d\n", __FUNCTION__, val)); |
---|
| 6044 | + |
---|
| 6045 | + dhd_net_if_lock_local(dhd); |
---|
| 6046 | + if (!val) { |
---|
| 6047 | + /* Delete monitor */ |
---|
| 6048 | + dhd_del_monitor_if(dhd); |
---|
| 6049 | + } else { |
---|
| 6050 | + /* Add monitor */ |
---|
| 6051 | + dhd_add_monitor_if(dhd); |
---|
| 6052 | + } |
---|
| 6053 | + dhd->monitor_type = val; |
---|
| 6054 | + dhd_net_if_unlock_local(dhd); |
---|
| 6055 | +} |
---|
| 6056 | +#endif /* WL_MONITOR */ |
---|
| 6057 | + |
---|
| 6058 | +#if defined(DHD_H2D_LOG_TIME_SYNC) |
---|
| 6059 | +/* |
---|
| 6060 | + * Helper function: |
---|
| 6061 | + * Used for RTE console message time syncing with Host printk |
---|
| 6062 | + */ |
---|
| 6063 | +void dhd_h2d_log_time_sync_deferred_wq_schedule(dhd_pub_t *dhdp) |
---|
| 6064 | +{ |
---|
| 6065 | + dhd_info_t *info = dhdp->info; |
---|
| 6066 | + |
---|
| 6067 | + /* Ideally the "state" should be always TRUE */ |
---|
| 6068 | + dhd_deferred_schedule_work(info->dhd_deferred_wq, NULL, |
---|
| 6069 | + DHD_WQ_WORK_H2D_CONSOLE_TIME_STAMP_MATCH, |
---|
| 6070 | + dhd_deferred_work_rte_log_time_sync, |
---|
| 6071 | + DHD_WQ_WORK_PRIORITY_LOW); |
---|
| 6072 | +} |
---|
| 6073 | + |
---|
| 6074 | +void |
---|
| 6075 | +dhd_deferred_work_rte_log_time_sync(void *handle, void *event_info, u8 event) |
---|
| 6076 | +{ |
---|
| 6077 | + dhd_info_t *dhd_info = handle; |
---|
| 6078 | + dhd_pub_t *dhd; |
---|
| 6079 | + |
---|
| 6080 | + if (event != DHD_WQ_WORK_H2D_CONSOLE_TIME_STAMP_MATCH) { |
---|
| 6081 | + DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); |
---|
| 6082 | + return; |
---|
| 6083 | + } |
---|
| 6084 | + |
---|
| 6085 | + if (!dhd_info) { |
---|
| 6086 | + DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); |
---|
| 6087 | + return; |
---|
| 6088 | + } |
---|
| 6089 | + |
---|
| 6090 | + dhd = &dhd_info->pub; |
---|
| 6091 | + |
---|
| 6092 | + /* |
---|
| 6093 | + * Function to send IOVAR for console timesyncing |
---|
| 6094 | + * between Host and Dongle. |
---|
| 6095 | + * If the IOVAR fails, |
---|
| 6096 | + * 1. dhd_rte_time_sync_ms is set to 0 and |
---|
| 6097 | + * 2. HOST Dongle console time sync will *not* happen. |
---|
| 6098 | + */ |
---|
| 6099 | + dhd_h2d_log_time_sync(dhd); |
---|
| 6100 | +} |
---|
| 6101 | +#endif /* DHD_H2D_LOG_TIME_SYNC */ |
---|
5972 | 6102 | |
---|
5973 | 6103 | int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, dhd_ioctl_t *ioc, void *data_buf) |
---|
5974 | 6104 | { |
---|
.. | .. |
---|
5979 | 6109 | net = dhd_idx2net(pub, ifidx); |
---|
5980 | 6110 | if (!net) { |
---|
5981 | 6111 | bcmerror = BCME_BADARG; |
---|
5982 | | - goto done; |
---|
| 6112 | + /* |
---|
| 6113 | + * The netdev pointer is bad means the DHD can't communicate |
---|
| 6114 | + * to higher layers, so just return from here |
---|
| 6115 | + */ |
---|
| 6116 | + return bcmerror; |
---|
5983 | 6117 | } |
---|
5984 | | - |
---|
5985 | | - if (data_buf) |
---|
5986 | | - buflen = MIN(ioc->len, DHD_IOCTL_MAXLEN); |
---|
5987 | 6118 | |
---|
5988 | 6119 | /* check for local dhd ioctl and handle it */ |
---|
5989 | 6120 | if (ioc->driver == DHD_IOCTL_MAGIC) { |
---|
| 6121 | + /* This is a DHD IOVAR, truncate buflen to DHD_IOCTL_MAXLEN */ |
---|
| 6122 | + if (data_buf) |
---|
| 6123 | + buflen = MIN(ioc->len, DHD_IOCTL_MAXLEN); |
---|
5990 | 6124 | bcmerror = dhd_ioctl((void *)pub, ioc, data_buf, buflen); |
---|
5991 | 6125 | if (bcmerror) |
---|
5992 | 6126 | pub->bcmerror = bcmerror; |
---|
5993 | 6127 | goto done; |
---|
5994 | 6128 | } |
---|
5995 | 6129 | |
---|
5996 | | -#ifndef BCMDBUS |
---|
| 6130 | + /* This is a WL IOVAR, truncate buflen to WLC_IOCTL_MAXLEN */ |
---|
| 6131 | + if (data_buf) |
---|
| 6132 | + buflen = MIN(ioc->len, WLC_IOCTL_MAXLEN); |
---|
| 6133 | + |
---|
5997 | 6134 | /* send to dongle (must be up, and wl). */ |
---|
5998 | 6135 | if (pub->busstate == DHD_BUS_DOWN || pub->busstate == DHD_BUS_LOAD) { |
---|
5999 | | - if (allow_delay_fwdl) { |
---|
6000 | | - int ret = dhd_bus_start(pub); |
---|
| 6136 | + if ((!pub->dongle_trap_occured) && allow_delay_fwdl) { |
---|
| 6137 | + int ret; |
---|
| 6138 | + if (atomic_read(&exit_in_progress)) { |
---|
| 6139 | + DHD_ERROR(("%s module exit in progress\n", __func__)); |
---|
| 6140 | + bcmerror = BCME_DONGLE_DOWN; |
---|
| 6141 | + goto done; |
---|
| 6142 | + } |
---|
| 6143 | + ret = dhd_bus_start(pub); |
---|
6001 | 6144 | if (ret != 0) { |
---|
6002 | 6145 | DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); |
---|
6003 | 6146 | bcmerror = BCME_DONGLE_DOWN; |
---|
.. | .. |
---|
6013 | 6156 | bcmerror = BCME_DONGLE_DOWN; |
---|
6014 | 6157 | goto done; |
---|
6015 | 6158 | } |
---|
6016 | | -#endif /* BCMDBUS */ |
---|
6017 | 6159 | |
---|
6018 | 6160 | /* |
---|
6019 | 6161 | * Flush the TX queue if required for proper message serialization: |
---|
.. | .. |
---|
6030 | 6172 | ioc->cmd == WLC_DISASSOC) |
---|
6031 | 6173 | dhd_wait_pend8021x(net); |
---|
6032 | 6174 | |
---|
6033 | | -#ifdef WLMEDIA_HTSF |
---|
6034 | | - if (data_buf) { |
---|
6035 | | - /* short cut wl ioctl calls here */ |
---|
6036 | | - if (strcmp("htsf", data_buf) == 0) { |
---|
6037 | | - dhd_ioctl_htsf_get(dhd, 0); |
---|
6038 | | - return BCME_OK; |
---|
6039 | | - } |
---|
6040 | | - |
---|
6041 | | - if (strcmp("htsflate", data_buf) == 0) { |
---|
6042 | | - if (ioc->set) { |
---|
6043 | | - memset(ts, 0, sizeof(tstamp_t)*TSMAX); |
---|
6044 | | - memset(&maxdelayts, 0, sizeof(tstamp_t)); |
---|
6045 | | - maxdelay = 0; |
---|
6046 | | - tspktcnt = 0; |
---|
6047 | | - maxdelaypktno = 0; |
---|
6048 | | - memset(&vi_d1.bin, 0, sizeof(uint32)*NUMBIN); |
---|
6049 | | - memset(&vi_d2.bin, 0, sizeof(uint32)*NUMBIN); |
---|
6050 | | - memset(&vi_d3.bin, 0, sizeof(uint32)*NUMBIN); |
---|
6051 | | - memset(&vi_d4.bin, 0, sizeof(uint32)*NUMBIN); |
---|
6052 | | - } else { |
---|
6053 | | - dhd_dump_latency(); |
---|
6054 | | - } |
---|
6055 | | - return BCME_OK; |
---|
6056 | | - } |
---|
6057 | | - if (strcmp("htsfclear", data_buf) == 0) { |
---|
6058 | | - memset(&vi_d1.bin, 0, sizeof(uint32)*NUMBIN); |
---|
6059 | | - memset(&vi_d2.bin, 0, sizeof(uint32)*NUMBIN); |
---|
6060 | | - memset(&vi_d3.bin, 0, sizeof(uint32)*NUMBIN); |
---|
6061 | | - memset(&vi_d4.bin, 0, sizeof(uint32)*NUMBIN); |
---|
6062 | | - htsf_seqnum = 0; |
---|
6063 | | - return BCME_OK; |
---|
6064 | | - } |
---|
6065 | | - if (strcmp("htsfhis", data_buf) == 0) { |
---|
6066 | | - dhd_dump_htsfhisto(&vi_d1, "H to D"); |
---|
6067 | | - dhd_dump_htsfhisto(&vi_d2, "D to D"); |
---|
6068 | | - dhd_dump_htsfhisto(&vi_d3, "D to H"); |
---|
6069 | | - dhd_dump_htsfhisto(&vi_d4, "H to H"); |
---|
6070 | | - return BCME_OK; |
---|
6071 | | - } |
---|
6072 | | - if (strcmp("tsport", data_buf) == 0) { |
---|
6073 | | - if (ioc->set) { |
---|
6074 | | - memcpy(&tsport, data_buf + 7, 4); |
---|
6075 | | - } else { |
---|
6076 | | - DHD_ERROR(("current timestamp port: %d \n", tsport)); |
---|
6077 | | - } |
---|
6078 | | - return BCME_OK; |
---|
6079 | | - } |
---|
6080 | | - } |
---|
6081 | | -#endif /* WLMEDIA_HTSF */ |
---|
6082 | | - |
---|
6083 | 6175 | if ((ioc->cmd == WLC_SET_VAR || ioc->cmd == WLC_GET_VAR) && |
---|
6084 | 6176 | data_buf != NULL && strncmp("rpc_", data_buf, 4) == 0) { |
---|
6085 | | -#ifdef BCM_FD_AGGR |
---|
6086 | | - bcmerror = dhd_fdaggr_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, data_buf, buflen); |
---|
6087 | | -#else |
---|
6088 | 6177 | bcmerror = BCME_UNSUPPORTED; |
---|
6089 | | -#endif |
---|
6090 | 6178 | goto done; |
---|
6091 | 6179 | } |
---|
| 6180 | + |
---|
6092 | 6181 | bcmerror = dhd_wl_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, data_buf, buflen); |
---|
6093 | 6182 | |
---|
| 6183 | +#ifdef WL_MONITOR |
---|
6094 | 6184 | /* Intercept monitor ioctl here, add/del monitor if */ |
---|
6095 | 6185 | if (bcmerror == BCME_OK && ioc->cmd == WLC_SET_MONITOR) { |
---|
6096 | | - dhd_set_monitor(pub, ifidx, *(int32*)data_buf); |
---|
| 6186 | + int val = 0; |
---|
| 6187 | + if (data_buf != NULL && buflen != 0) { |
---|
| 6188 | + if (buflen >= 4) { |
---|
| 6189 | + val = *(int*)data_buf; |
---|
| 6190 | + } else if (buflen >= 2) { |
---|
| 6191 | + val = *(short*)data_buf; |
---|
| 6192 | + } else { |
---|
| 6193 | + val = *(char*)data_buf; |
---|
| 6194 | + } |
---|
| 6195 | + } |
---|
| 6196 | + dhd_set_monitor(pub, ifidx, val); |
---|
6097 | 6197 | } |
---|
| 6198 | +#endif /* WL_MONITOR */ |
---|
6098 | 6199 | |
---|
6099 | 6200 | done: |
---|
| 6201 | +#if defined(OEM_ANDROID) |
---|
6100 | 6202 | dhd_check_hang(net, pub, bcmerror); |
---|
| 6203 | +#endif /* OEM_ANDROID */ |
---|
6101 | 6204 | |
---|
6102 | 6205 | return bcmerror; |
---|
6103 | 6206 | } |
---|
6104 | 6207 | |
---|
| 6208 | +/** |
---|
| 6209 | + * Called by the OS (optionally via a wrapper function). |
---|
| 6210 | + * @param net Linux per dongle instance |
---|
| 6211 | + * @param ifr Linux request structure |
---|
| 6212 | + * @param cmd e.g. SIOCETHTOOL |
---|
| 6213 | + */ |
---|
6105 | 6214 | static int |
---|
6106 | 6215 | dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) |
---|
6107 | 6216 | { |
---|
6108 | 6217 | dhd_info_t *dhd = DHD_DEV_INFO(net); |
---|
6109 | 6218 | dhd_ioctl_t ioc; |
---|
| 6219 | + int bcmerror = 0; |
---|
6110 | 6220 | int ifidx; |
---|
6111 | 6221 | int ret; |
---|
6112 | | - void *local_buf = NULL; |
---|
| 6222 | + void *local_buf = NULL; /**< buffer in kernel space */ |
---|
| 6223 | + void __user *ioc_buf_user = NULL; /**< buffer in user space */ |
---|
6113 | 6224 | u16 buflen = 0; |
---|
| 6225 | + |
---|
| 6226 | +#ifdef ENABLE_INSMOD_NO_FW_LOAD |
---|
| 6227 | + allow_delay_fwdl = 1; |
---|
| 6228 | +#endif /* ENABLE_INSMOD_NO_FW_LOAD */ |
---|
| 6229 | + if (atomic_read(&exit_in_progress)) { |
---|
| 6230 | + DHD_ERROR(("%s module exit in progress\n", __func__)); |
---|
| 6231 | + bcmerror = BCME_DONGLE_DOWN; |
---|
| 6232 | + return OSL_ERROR(bcmerror); |
---|
| 6233 | + } |
---|
6114 | 6234 | |
---|
6115 | 6235 | DHD_OS_WAKE_LOCK(&dhd->pub); |
---|
6116 | 6236 | DHD_PERIM_LOCK(&dhd->pub); |
---|
6117 | 6237 | |
---|
| 6238 | +#if defined(OEM_ANDROID) |
---|
| 6239 | +#ifndef ENABLE_INSMOD_NO_FW_LOAD |
---|
6118 | 6240 | /* Interface up check for built-in type */ |
---|
6119 | 6241 | if (!dhd_download_fw_on_driverload && dhd->pub.up == FALSE) { |
---|
6120 | 6242 | DHD_TRACE(("%s: Interface is down \n", __FUNCTION__)); |
---|
6121 | | - ret = BCME_NOTUP; |
---|
6122 | | - goto exit; |
---|
| 6243 | + DHD_PERIM_UNLOCK(&dhd->pub); |
---|
| 6244 | + DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
| 6245 | + return OSL_ERROR(BCME_NOTUP); |
---|
6123 | 6246 | } |
---|
6124 | | - |
---|
6125 | | - /* send to dongle only if we are not waiting for reload already */ |
---|
6126 | | - if (dhd->pub.hang_was_sent) { |
---|
6127 | | - DHD_TRACE(("%s: HANG was sent up earlier\n", __FUNCTION__)); |
---|
6128 | | - DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS); |
---|
6129 | | - ret = BCME_DONGLE_DOWN; |
---|
6130 | | - goto exit; |
---|
6131 | | - } |
---|
| 6247 | +#endif /* ENABLE_INSMOD_NO_FW_LOAD */ |
---|
| 6248 | +#endif /* (OEM_ANDROID) */ |
---|
6132 | 6249 | |
---|
6133 | 6250 | ifidx = dhd_net2idx(dhd, net); |
---|
6134 | 6251 | DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd)); |
---|
6135 | 6252 | |
---|
| 6253 | +#if defined(WL_STATIC_IF) |
---|
| 6254 | + /* skip for static ndev when it is down */ |
---|
| 6255 | + if (dhd_is_static_ndev(&dhd->pub, net) && !(net->flags & IFF_UP)) { |
---|
| 6256 | + DHD_PERIM_UNLOCK(&dhd->pub); |
---|
| 6257 | + DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
| 6258 | + return -1; |
---|
| 6259 | + } |
---|
| 6260 | +#endif /* WL_STATIC_iF */ |
---|
| 6261 | + |
---|
6136 | 6262 | if (ifidx == DHD_BAD_IF) { |
---|
6137 | 6263 | DHD_ERROR(("%s: BAD IF\n", __FUNCTION__)); |
---|
6138 | | - ret = -1; |
---|
6139 | | - goto exit; |
---|
| 6264 | + DHD_PERIM_UNLOCK(&dhd->pub); |
---|
| 6265 | + DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
| 6266 | + return -1; |
---|
6140 | 6267 | } |
---|
6141 | 6268 | |
---|
6142 | 6269 | #if defined(WL_WIRELESS_EXT) |
---|
.. | .. |
---|
6144 | 6271 | if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { |
---|
6145 | 6272 | /* may recurse, do NOT lock */ |
---|
6146 | 6273 | ret = wl_iw_ioctl(net, ifr, cmd); |
---|
6147 | | - goto exit; |
---|
| 6274 | + DHD_PERIM_UNLOCK(&dhd->pub); |
---|
| 6275 | + DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
| 6276 | + return ret; |
---|
6148 | 6277 | } |
---|
6149 | 6278 | #endif /* defined(WL_WIRELESS_EXT) */ |
---|
6150 | 6279 | |
---|
6151 | | -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) |
---|
6152 | 6280 | if (cmd == SIOCETHTOOL) { |
---|
6153 | 6281 | ret = dhd_ethtool(dhd, (void*)ifr->ifr_data); |
---|
6154 | | - goto exit; |
---|
| 6282 | + DHD_PERIM_UNLOCK(&dhd->pub); |
---|
| 6283 | + DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
| 6284 | + return ret; |
---|
6155 | 6285 | } |
---|
6156 | | -#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ |
---|
6157 | 6286 | |
---|
| 6287 | +#if defined(OEM_ANDROID) |
---|
6158 | 6288 | if (cmd == SIOCDEVPRIVATE+1) { |
---|
6159 | | - ret = wl_android_priv_cmd(net, ifr, cmd); |
---|
| 6289 | + ret = wl_android_priv_cmd(net, ifr); |
---|
6160 | 6290 | dhd_check_hang(net, &dhd->pub, ret); |
---|
6161 | | - goto exit; |
---|
| 6291 | + DHD_PERIM_UNLOCK(&dhd->pub); |
---|
| 6292 | + DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
| 6293 | + return ret; |
---|
6162 | 6294 | } |
---|
| 6295 | + |
---|
| 6296 | +#endif /* OEM_ANDROID */ |
---|
6163 | 6297 | |
---|
6164 | 6298 | if (cmd != SIOCDEVPRIVATE) { |
---|
6165 | | - ret = -EOPNOTSUPP; |
---|
6166 | | - goto exit; |
---|
| 6299 | + DHD_PERIM_UNLOCK(&dhd->pub); |
---|
| 6300 | + DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
| 6301 | + return -EOPNOTSUPP; |
---|
6167 | 6302 | } |
---|
6168 | 6303 | |
---|
6169 | 6304 | memset(&ioc, 0, sizeof(ioc)); |
---|
6170 | 6305 | |
---|
6171 | | -#ifdef CONFIG_COMPAT |
---|
6172 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) |
---|
6173 | | - if (in_compat_syscall()) { |
---|
6174 | | -#else |
---|
6175 | | - if (is_compat_task()) { |
---|
6176 | | -#endif |
---|
6177 | | - compat_wl_ioctl_t compat_ioc; |
---|
6178 | | - if (copy_from_user(&compat_ioc, ifr->ifr_data, sizeof(compat_wl_ioctl_t))) { |
---|
6179 | | - ret = BCME_BADADDR; |
---|
6180 | | - goto done; |
---|
6181 | | - } |
---|
6182 | | - ioc.cmd = compat_ioc.cmd; |
---|
6183 | | - ioc.buf = compat_ptr(compat_ioc.buf); |
---|
6184 | | - ioc.len = compat_ioc.len; |
---|
6185 | | - ioc.set = compat_ioc.set; |
---|
6186 | | - ioc.used = compat_ioc.used; |
---|
6187 | | - ioc.needed = compat_ioc.needed; |
---|
6188 | | - /* To differentiate between wl and dhd read 4 more byes */ |
---|
6189 | | - if ((copy_from_user(&ioc.driver, (char *)ifr->ifr_data + sizeof(compat_wl_ioctl_t), |
---|
6190 | | - sizeof(uint)) != 0)) { |
---|
6191 | | - ret = BCME_BADADDR; |
---|
6192 | | - goto done; |
---|
6193 | | - } |
---|
6194 | | - } else |
---|
6195 | | -#endif /* CONFIG_COMPAT */ |
---|
6196 | 6306 | { |
---|
6197 | 6307 | /* Copy the ioc control structure part of ioctl request */ |
---|
6198 | 6308 | if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) { |
---|
6199 | | - ret = BCME_BADADDR; |
---|
| 6309 | + bcmerror = BCME_BADADDR; |
---|
6200 | 6310 | goto done; |
---|
6201 | 6311 | } |
---|
6202 | 6312 | |
---|
6203 | 6313 | /* To differentiate between wl and dhd read 4 more byes */ |
---|
6204 | 6314 | if ((copy_from_user(&ioc.driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t), |
---|
6205 | 6315 | sizeof(uint)) != 0)) { |
---|
6206 | | - ret = BCME_BADADDR; |
---|
| 6316 | + bcmerror = BCME_BADADDR; |
---|
6207 | 6317 | goto done; |
---|
6208 | 6318 | } |
---|
6209 | 6319 | } |
---|
6210 | 6320 | |
---|
6211 | 6321 | if (!capable(CAP_NET_ADMIN)) { |
---|
6212 | | - ret = BCME_EPERM; |
---|
| 6322 | + bcmerror = BCME_EPERM; |
---|
6213 | 6323 | goto done; |
---|
6214 | 6324 | } |
---|
| 6325 | + |
---|
| 6326 | + /* Take backup of ioc.buf and restore later */ |
---|
| 6327 | + ioc_buf_user = ioc.buf; |
---|
6215 | 6328 | |
---|
6216 | 6329 | if (ioc.len > 0) { |
---|
6217 | 6330 | buflen = MIN(ioc.len, DHD_IOCTL_MAXLEN); |
---|
6218 | 6331 | if (!(local_buf = MALLOC(dhd->pub.osh, buflen+1))) { |
---|
6219 | | - ret = BCME_NOMEM; |
---|
| 6332 | + bcmerror = BCME_NOMEM; |
---|
6220 | 6333 | goto done; |
---|
6221 | 6334 | } |
---|
6222 | 6335 | |
---|
6223 | 6336 | DHD_PERIM_UNLOCK(&dhd->pub); |
---|
6224 | 6337 | if (copy_from_user(local_buf, ioc.buf, buflen)) { |
---|
6225 | 6338 | DHD_PERIM_LOCK(&dhd->pub); |
---|
6226 | | - ret = BCME_BADADDR; |
---|
| 6339 | + bcmerror = BCME_BADADDR; |
---|
6227 | 6340 | goto done; |
---|
6228 | 6341 | } |
---|
6229 | 6342 | DHD_PERIM_LOCK(&dhd->pub); |
---|
6230 | 6343 | |
---|
6231 | | - *(char *)(local_buf + buflen) = '\0'; |
---|
| 6344 | + *((char *)local_buf + buflen) = '\0'; |
---|
| 6345 | + |
---|
| 6346 | + /* For some platforms accessing userspace memory |
---|
| 6347 | + * of ioc.buf is causing kernel panic, so to avoid that |
---|
| 6348 | + * make ioc.buf pointing to kernel space memory local_buf |
---|
| 6349 | + */ |
---|
| 6350 | + ioc.buf = local_buf; |
---|
6232 | 6351 | } |
---|
6233 | 6352 | |
---|
6234 | | - ret = dhd_ioctl_process(&dhd->pub, ifidx, &ioc, local_buf); |
---|
| 6353 | +#if defined(OEM_ANDROID) |
---|
| 6354 | + /* Skip all the non DHD iovars (wl iovars) after f/w hang */ |
---|
| 6355 | + if (ioc.driver != DHD_IOCTL_MAGIC && dhd->pub.hang_was_sent) { |
---|
| 6356 | + DHD_TRACE(("%s: HANG was sent up earlier\n", __FUNCTION__)); |
---|
| 6357 | + DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS); |
---|
| 6358 | + bcmerror = BCME_DONGLE_DOWN; |
---|
| 6359 | + goto done; |
---|
| 6360 | + } |
---|
| 6361 | +#endif /* OEM_ANDROID */ |
---|
6235 | 6362 | |
---|
6236 | | - if (!ret && buflen && local_buf && ioc.buf) { |
---|
| 6363 | + bcmerror = dhd_ioctl_process(&dhd->pub, ifidx, &ioc, local_buf); |
---|
| 6364 | + |
---|
| 6365 | + /* Restore back userspace pointer to ioc.buf */ |
---|
| 6366 | + ioc.buf = ioc_buf_user; |
---|
| 6367 | + |
---|
| 6368 | + if (!bcmerror && buflen && local_buf && ioc.buf) { |
---|
6237 | 6369 | DHD_PERIM_UNLOCK(&dhd->pub); |
---|
6238 | 6370 | if (copy_to_user(ioc.buf, local_buf, buflen)) |
---|
6239 | | - ret = -EFAULT; |
---|
| 6371 | + bcmerror = -EFAULT; |
---|
6240 | 6372 | DHD_PERIM_LOCK(&dhd->pub); |
---|
6241 | 6373 | } |
---|
6242 | 6374 | |
---|
.. | .. |
---|
6244 | 6376 | if (local_buf) |
---|
6245 | 6377 | MFREE(dhd->pub.osh, local_buf, buflen+1); |
---|
6246 | 6378 | |
---|
6247 | | -exit: |
---|
6248 | 6379 | DHD_PERIM_UNLOCK(&dhd->pub); |
---|
6249 | 6380 | DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
6250 | 6381 | |
---|
6251 | | - return OSL_ERROR(ret); |
---|
| 6382 | + return OSL_ERROR(bcmerror); |
---|
6252 | 6383 | } |
---|
6253 | 6384 | |
---|
| 6385 | +#if defined(WL_CFG80211) && defined(SUPPORT_DEEP_SLEEP) |
---|
| 6386 | +/* Flags to indicate if we distingish power off policy when |
---|
| 6387 | + * user set the memu "Keep Wi-Fi on during sleep" to "Never" |
---|
| 6388 | + */ |
---|
| 6389 | +int trigger_deep_sleep = 0; |
---|
| 6390 | +#endif /* WL_CFG80211 && SUPPORT_DEEP_SLEEP */ |
---|
6254 | 6391 | |
---|
| 6392 | +#ifdef FIX_CPU_MIN_CLOCK |
---|
| 6393 | +static int dhd_init_cpufreq_fix(dhd_info_t *dhd) |
---|
| 6394 | +{ |
---|
| 6395 | + if (dhd) { |
---|
| 6396 | +#if defined(OEM_ANDROID) |
---|
| 6397 | + mutex_init(&dhd->cpufreq_fix); |
---|
| 6398 | +#endif // endif |
---|
| 6399 | + dhd->cpufreq_fix_status = FALSE; |
---|
| 6400 | + } |
---|
| 6401 | + return 0; |
---|
| 6402 | +} |
---|
| 6403 | + |
---|
| 6404 | +static void dhd_fix_cpu_freq(dhd_info_t *dhd) |
---|
| 6405 | +{ |
---|
| 6406 | +#if defined(OEM_ANDROID) |
---|
| 6407 | + mutex_lock(&dhd->cpufreq_fix); |
---|
| 6408 | +#endif // endif |
---|
| 6409 | + if (dhd && !dhd->cpufreq_fix_status) { |
---|
| 6410 | + pm_qos_add_request(&dhd->dhd_cpu_qos, PM_QOS_CPU_FREQ_MIN, 300000); |
---|
| 6411 | +#ifdef FIX_BUS_MIN_CLOCK |
---|
| 6412 | + pm_qos_add_request(&dhd->dhd_bus_qos, PM_QOS_BUS_THROUGHPUT, 400000); |
---|
| 6413 | +#endif /* FIX_BUS_MIN_CLOCK */ |
---|
| 6414 | + DHD_ERROR(("pm_qos_add_requests called\n")); |
---|
| 6415 | + |
---|
| 6416 | + dhd->cpufreq_fix_status = TRUE; |
---|
| 6417 | + } |
---|
| 6418 | +#if defined(OEM_ANDROID) |
---|
| 6419 | + mutex_unlock(&dhd->cpufreq_fix); |
---|
| 6420 | +#endif // endif |
---|
| 6421 | +} |
---|
| 6422 | + |
---|
| 6423 | +static void dhd_rollback_cpu_freq(dhd_info_t *dhd) |
---|
| 6424 | +{ |
---|
| 6425 | +#if defined(OEM_ANDROID) |
---|
| 6426 | + mutex_lock(&dhd ->cpufreq_fix); |
---|
| 6427 | +#endif // endif |
---|
| 6428 | + if (dhd && dhd->cpufreq_fix_status != TRUE) { |
---|
| 6429 | +#if defined(OEM_ANDROID) |
---|
| 6430 | + mutex_unlock(&dhd->cpufreq_fix); |
---|
| 6431 | +#endif // endif |
---|
| 6432 | + return; |
---|
| 6433 | + } |
---|
| 6434 | + |
---|
| 6435 | + pm_qos_remove_request(&dhd->dhd_cpu_qos); |
---|
| 6436 | +#ifdef FIX_BUS_MIN_CLOCK |
---|
| 6437 | + pm_qos_remove_request(&dhd->dhd_bus_qos); |
---|
| 6438 | +#endif /* FIX_BUS_MIN_CLOCK */ |
---|
| 6439 | + DHD_ERROR(("pm_qos_add_requests called\n")); |
---|
| 6440 | + |
---|
| 6441 | + dhd->cpufreq_fix_status = FALSE; |
---|
| 6442 | +#if defined(OEM_ANDROID) |
---|
| 6443 | + mutex_unlock(&dhd->cpufreq_fix); |
---|
| 6444 | +#endif // endif |
---|
| 6445 | +} |
---|
| 6446 | +#endif /* FIX_CPU_MIN_CLOCK */ |
---|
| 6447 | + |
---|
| 6448 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 6449 | +static int |
---|
| 6450 | +dhd_ioctl_entry_wrapper(struct net_device *net, struct ifreq *ifr, int cmd) |
---|
| 6451 | +{ |
---|
| 6452 | + int error; |
---|
| 6453 | + dhd_info_t *dhd = DHD_DEV_INFO(net); |
---|
| 6454 | + |
---|
| 6455 | + if (atomic_read(&dhd->pub.block_bus)) |
---|
| 6456 | + return -EHOSTDOWN; |
---|
| 6457 | + |
---|
| 6458 | + if (pm_runtime_get_sync(dhd_bus_to_dev(dhd->pub.bus)) < 0) |
---|
| 6459 | + return BCME_ERROR; |
---|
| 6460 | + |
---|
| 6461 | + error = dhd_ioctl_entry(net, ifr, cmd); |
---|
| 6462 | + |
---|
| 6463 | + pm_runtime_mark_last_busy(dhd_bus_to_dev(dhd->pub.bus)); |
---|
| 6464 | + pm_runtime_put_autosuspend(dhd_bus_to_dev(dhd->pub.bus)); |
---|
| 6465 | + |
---|
| 6466 | + return error; |
---|
| 6467 | +} |
---|
| 6468 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
| 6469 | + |
---|
| 6470 | +#if defined(BT_OVER_SDIO) |
---|
| 6471 | + |
---|
| 6472 | +void |
---|
| 6473 | +dhdsdio_bus_usr_cnt_inc(dhd_pub_t *dhdp) |
---|
| 6474 | +{ |
---|
| 6475 | + dhdp->info->bus_user_count++; |
---|
| 6476 | +} |
---|
| 6477 | + |
---|
| 6478 | +void |
---|
| 6479 | +dhdsdio_bus_usr_cnt_dec(dhd_pub_t *dhdp) |
---|
| 6480 | +{ |
---|
| 6481 | + dhdp->info->bus_user_count--; |
---|
| 6482 | +} |
---|
| 6483 | + |
---|
| 6484 | +/* Return values: |
---|
| 6485 | + * Success: Returns 0 |
---|
| 6486 | + * Failure: Returns -1 or errono code |
---|
| 6487 | + */ |
---|
| 6488 | +int |
---|
| 6489 | +dhd_bus_get(wlan_bt_handle_t handle, bus_owner_t owner) |
---|
| 6490 | +{ |
---|
| 6491 | + dhd_pub_t *dhdp = (dhd_pub_t *)handle; |
---|
| 6492 | + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
| 6493 | + int ret = 0; |
---|
| 6494 | + |
---|
| 6495 | + mutex_lock(&dhd->bus_user_lock); |
---|
| 6496 | + ++dhd->bus_user_count; |
---|
| 6497 | + if (dhd->bus_user_count < 0) { |
---|
| 6498 | + DHD_ERROR(("%s(): bus_user_count is negative, which is invalid\n", __FUNCTION__)); |
---|
| 6499 | + ret = -1; |
---|
| 6500 | + goto exit; |
---|
| 6501 | + } |
---|
| 6502 | + |
---|
| 6503 | + if (dhd->bus_user_count == 1) { |
---|
| 6504 | + |
---|
| 6505 | + dhd->pub.hang_was_sent = 0; |
---|
| 6506 | + |
---|
| 6507 | + /* First user, turn on WL_REG, start the bus */ |
---|
| 6508 | + DHD_ERROR(("%s(): First user Turn On WL_REG & start the bus", __FUNCTION__)); |
---|
| 6509 | + |
---|
| 6510 | + if (!wifi_platform_set_power(dhd->adapter, TRUE, WIFI_TURNON_DELAY)) { |
---|
| 6511 | + /* Enable F1 */ |
---|
| 6512 | + ret = dhd_bus_resume(dhdp, 0); |
---|
| 6513 | + if (ret) { |
---|
| 6514 | + DHD_ERROR(("%s(): Failed to enable F1, err=%d\n", |
---|
| 6515 | + __FUNCTION__, ret)); |
---|
| 6516 | + goto exit; |
---|
| 6517 | + } |
---|
| 6518 | + } |
---|
| 6519 | + |
---|
| 6520 | + dhd_update_fw_nv_path(dhd); |
---|
| 6521 | + /* update firmware and nvram path to sdio bus */ |
---|
| 6522 | + dhd_bus_update_fw_nv_path(dhd->pub.bus, |
---|
| 6523 | + dhd->fw_path, dhd->nv_path); |
---|
| 6524 | + /* download the firmware, Enable F2 */ |
---|
| 6525 | + /* TODO: Should be done only in case of FW switch */ |
---|
| 6526 | + ret = dhd_bus_devreset(dhdp, FALSE); |
---|
| 6527 | + dhd_bus_resume(dhdp, 1); |
---|
| 6528 | + if (!ret) { |
---|
| 6529 | + if (dhd_sync_with_dongle(&dhd->pub) < 0) { |
---|
| 6530 | + DHD_ERROR(("%s(): Sync with dongle failed!!\n", __FUNCTION__)); |
---|
| 6531 | + ret = -EFAULT; |
---|
| 6532 | + } |
---|
| 6533 | + } else { |
---|
| 6534 | + DHD_ERROR(("%s(): Failed to download, err=%d\n", __FUNCTION__, ret)); |
---|
| 6535 | + } |
---|
| 6536 | + } else { |
---|
| 6537 | + DHD_ERROR(("%s(): BUS is already acquired, just increase the count %d \r\n", |
---|
| 6538 | + __FUNCTION__, dhd->bus_user_count)); |
---|
| 6539 | + } |
---|
| 6540 | +exit: |
---|
| 6541 | + mutex_unlock(&dhd->bus_user_lock); |
---|
| 6542 | + return ret; |
---|
| 6543 | +} |
---|
| 6544 | +EXPORT_SYMBOL(dhd_bus_get); |
---|
| 6545 | + |
---|
| 6546 | +/* Return values: |
---|
| 6547 | + * Success: Returns 0 |
---|
| 6548 | + * Failure: Returns -1 or errono code |
---|
| 6549 | + */ |
---|
| 6550 | +int |
---|
| 6551 | +dhd_bus_put(wlan_bt_handle_t handle, bus_owner_t owner) |
---|
| 6552 | +{ |
---|
| 6553 | + dhd_pub_t *dhdp = (dhd_pub_t *)handle; |
---|
| 6554 | + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
| 6555 | + int ret = 0; |
---|
| 6556 | + BCM_REFERENCE(owner); |
---|
| 6557 | + |
---|
| 6558 | + mutex_lock(&dhd->bus_user_lock); |
---|
| 6559 | + --dhd->bus_user_count; |
---|
| 6560 | + if (dhd->bus_user_count < 0) { |
---|
| 6561 | + DHD_ERROR(("%s(): bus_user_count is negative, which is invalid\n", __FUNCTION__)); |
---|
| 6562 | + dhd->bus_user_count = 0; |
---|
| 6563 | + ret = -1; |
---|
| 6564 | + goto exit; |
---|
| 6565 | + } |
---|
| 6566 | + |
---|
| 6567 | + if (dhd->bus_user_count == 0) { |
---|
| 6568 | + /* Last user, stop the bus and turn Off WL_REG */ |
---|
| 6569 | + DHD_ERROR(("%s(): There are no owners left Trunf Off WL_REG & stop the bus \r\n", |
---|
| 6570 | + __FUNCTION__)); |
---|
| 6571 | +#ifdef PROP_TXSTATUS |
---|
| 6572 | + if (dhd->pub.wlfc_enabled) { |
---|
| 6573 | + dhd_wlfc_deinit(&dhd->pub); |
---|
| 6574 | + } |
---|
| 6575 | +#endif /* PROP_TXSTATUS */ |
---|
| 6576 | +#ifdef PNO_SUPPORT |
---|
| 6577 | + if (dhd->pub.pno_state) { |
---|
| 6578 | + dhd_pno_deinit(&dhd->pub); |
---|
| 6579 | + } |
---|
| 6580 | +#endif /* PNO_SUPPORT */ |
---|
| 6581 | +#ifdef RTT_SUPPORT |
---|
| 6582 | + if (dhd->pub.rtt_state) { |
---|
| 6583 | + dhd_rtt_deinit(&dhd->pub); |
---|
| 6584 | + } |
---|
| 6585 | +#endif /* RTT_SUPPORT */ |
---|
| 6586 | + ret = dhd_bus_devreset(dhdp, TRUE); |
---|
| 6587 | + if (!ret) { |
---|
| 6588 | + dhd_bus_suspend(dhdp); |
---|
| 6589 | + wifi_platform_set_power(dhd->adapter, FALSE, WIFI_TURNOFF_DELAY); |
---|
| 6590 | + } |
---|
| 6591 | + } else { |
---|
| 6592 | + DHD_ERROR(("%s(): Other owners using bus, decrease the count %d \r\n", |
---|
| 6593 | + __FUNCTION__, dhd->bus_user_count)); |
---|
| 6594 | + } |
---|
| 6595 | +exit: |
---|
| 6596 | + mutex_unlock(&dhd->bus_user_lock); |
---|
| 6597 | + return ret; |
---|
| 6598 | +} |
---|
| 6599 | +EXPORT_SYMBOL(dhd_bus_put); |
---|
| 6600 | + |
---|
| 6601 | +int |
---|
| 6602 | +dhd_net_bus_get(struct net_device *dev) |
---|
| 6603 | +{ |
---|
| 6604 | + dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 6605 | + return dhd_bus_get(&dhd->pub, WLAN_MODULE); |
---|
| 6606 | +} |
---|
| 6607 | + |
---|
| 6608 | +int |
---|
| 6609 | +dhd_net_bus_put(struct net_device *dev) |
---|
| 6610 | +{ |
---|
| 6611 | + dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 6612 | + return dhd_bus_put(&dhd->pub, WLAN_MODULE); |
---|
| 6613 | +} |
---|
| 6614 | + |
---|
| 6615 | +/* |
---|
| 6616 | + * Function to enable the Bus Clock |
---|
| 6617 | + * Returns BCME_OK on success and BCME_xxx on failure |
---|
| 6618 | + * |
---|
| 6619 | + * This function is not callable from non-sleepable context |
---|
| 6620 | + */ |
---|
| 6621 | +int dhd_bus_clk_enable(wlan_bt_handle_t handle, bus_owner_t owner) |
---|
| 6622 | +{ |
---|
| 6623 | + dhd_pub_t *dhdp = (dhd_pub_t *)handle; |
---|
| 6624 | + |
---|
| 6625 | + int ret; |
---|
| 6626 | + |
---|
| 6627 | + dhd_os_sdlock(dhdp); |
---|
| 6628 | + /* |
---|
| 6629 | + * The second argument is TRUE, that means, we expect |
---|
| 6630 | + * the function to "wait" until the clocks are really |
---|
| 6631 | + * available |
---|
| 6632 | + */ |
---|
| 6633 | + ret = __dhdsdio_clk_enable(dhdp->bus, owner, TRUE); |
---|
| 6634 | + dhd_os_sdunlock(dhdp); |
---|
| 6635 | + |
---|
| 6636 | + return ret; |
---|
| 6637 | +} |
---|
| 6638 | +EXPORT_SYMBOL(dhd_bus_clk_enable); |
---|
| 6639 | + |
---|
| 6640 | +/* |
---|
| 6641 | + * Function to disable the Bus Clock |
---|
| 6642 | + * Returns BCME_OK on success and BCME_xxx on failure |
---|
| 6643 | + * |
---|
| 6644 | + * This function is not callable from non-sleepable context |
---|
| 6645 | + */ |
---|
| 6646 | +int dhd_bus_clk_disable(wlan_bt_handle_t handle, bus_owner_t owner) |
---|
| 6647 | +{ |
---|
| 6648 | + dhd_pub_t *dhdp = (dhd_pub_t *)handle; |
---|
| 6649 | + |
---|
| 6650 | + int ret; |
---|
| 6651 | + |
---|
| 6652 | + dhd_os_sdlock(dhdp); |
---|
| 6653 | + /* |
---|
| 6654 | + * The second argument is TRUE, that means, we expect |
---|
| 6655 | + * the function to "wait" until the clocks are really |
---|
| 6656 | + * disabled |
---|
| 6657 | + */ |
---|
| 6658 | + ret = __dhdsdio_clk_disable(dhdp->bus, owner, TRUE); |
---|
| 6659 | + dhd_os_sdunlock(dhdp); |
---|
| 6660 | + |
---|
| 6661 | + return ret; |
---|
| 6662 | +} |
---|
| 6663 | +EXPORT_SYMBOL(dhd_bus_clk_disable); |
---|
| 6664 | + |
---|
| 6665 | +/* |
---|
| 6666 | + * Function to reset bt_use_count counter to zero. |
---|
| 6667 | + * |
---|
| 6668 | + * This function is not callable from non-sleepable context |
---|
| 6669 | + */ |
---|
| 6670 | +void dhd_bus_reset_bt_use_count(wlan_bt_handle_t handle) |
---|
| 6671 | +{ |
---|
| 6672 | + dhd_pub_t *dhdp = (dhd_pub_t *)handle; |
---|
| 6673 | + |
---|
| 6674 | + /* take the lock and reset bt use count */ |
---|
| 6675 | + dhd_os_sdlock(dhdp); |
---|
| 6676 | + dhdsdio_reset_bt_use_count(dhdp->bus); |
---|
| 6677 | + dhd_os_sdunlock(dhdp); |
---|
| 6678 | +} |
---|
| 6679 | +EXPORT_SYMBOL(dhd_bus_reset_bt_use_count); |
---|
| 6680 | + |
---|
| 6681 | +void dhd_bus_retry_hang_recovery(wlan_bt_handle_t handle) |
---|
| 6682 | +{ |
---|
| 6683 | + dhd_pub_t *dhdp = (dhd_pub_t *)handle; |
---|
| 6684 | + dhd_info_t *dhd = (dhd_info_t*)dhdp->info; |
---|
| 6685 | + |
---|
| 6686 | + dhdp->hang_was_sent = 0; |
---|
| 6687 | + |
---|
| 6688 | + dhd_os_send_hang_message(&dhd->pub); |
---|
| 6689 | +} |
---|
| 6690 | +EXPORT_SYMBOL(dhd_bus_retry_hang_recovery); |
---|
| 6691 | + |
---|
| 6692 | +#endif /* BT_OVER_SDIO */ |
---|
6255 | 6693 | |
---|
6256 | 6694 | static int |
---|
6257 | 6695 | dhd_stop(struct net_device *net) |
---|
6258 | 6696 | { |
---|
6259 | 6697 | int ifidx = 0; |
---|
6260 | | -#ifdef WL_CFG80211 |
---|
| 6698 | + bool skip_reset = false; |
---|
| 6699 | +#if defined(WL_CFG80211) |
---|
6261 | 6700 | unsigned long flags = 0; |
---|
6262 | | -#endif |
---|
| 6701 | +#ifdef WL_STATIC_IF |
---|
| 6702 | + struct bcm_cfg80211 *cfg = wl_get_cfg(net); |
---|
| 6703 | +#endif /* WL_STATIC_IF */ |
---|
| 6704 | +#endif /* WL_CFG80211 */ |
---|
6263 | 6705 | dhd_info_t *dhd = DHD_DEV_INFO(net); |
---|
6264 | 6706 | DHD_OS_WAKE_LOCK(&dhd->pub); |
---|
6265 | 6707 | DHD_PERIM_LOCK(&dhd->pub); |
---|
.. | .. |
---|
6271 | 6713 | dhd->pub.d3ackcnt_timeout = 0; |
---|
6272 | 6714 | #endif /* BCMPCIE */ |
---|
6273 | 6715 | |
---|
| 6716 | + mutex_lock(&dhd->pub.ndev_op_sync); |
---|
| 6717 | + |
---|
6274 | 6718 | if (dhd->pub.up == 0) { |
---|
6275 | 6719 | goto exit; |
---|
6276 | 6720 | } |
---|
| 6721 | +#if defined(DHD_HANG_SEND_UP_TEST) |
---|
| 6722 | + if (dhd->pub.req_hang_type) { |
---|
| 6723 | + DHD_ERROR(("%s, Clear HANG test request 0x%x\n", |
---|
| 6724 | + __FUNCTION__, dhd->pub.req_hang_type)); |
---|
| 6725 | + dhd->pub.req_hang_type = 0; |
---|
| 6726 | + } |
---|
| 6727 | +#endif /* DHD_HANG_SEND_UP_TEST */ |
---|
6277 | 6728 | |
---|
6278 | 6729 | dhd_if_flush_sta(DHD_DEV_IFP(net)); |
---|
6279 | 6730 | |
---|
| 6731 | +#ifdef FIX_CPU_MIN_CLOCK |
---|
| 6732 | + if (dhd_get_fw_mode(dhd) == DHD_FLAG_HOSTAP_MODE) |
---|
| 6733 | + dhd_rollback_cpu_freq(dhd); |
---|
| 6734 | +#endif /* FIX_CPU_MIN_CLOCK */ |
---|
6280 | 6735 | |
---|
6281 | 6736 | ifidx = dhd_net2idx(dhd, net); |
---|
6282 | 6737 | BCM_REFERENCE(ifidx); |
---|
6283 | 6738 | |
---|
6284 | | - /* Set state and stop OS transmissions */ |
---|
6285 | | - netif_stop_queue(net); |
---|
| 6739 | + DHD_ERROR(("%s: ######### dhd_stop called for ifidx=%d #########\n", __FUNCTION__, ifidx)); |
---|
| 6740 | + |
---|
| 6741 | +#if defined(WL_STATIC_IF) && defined(WL_CFG80211) |
---|
| 6742 | + /* If static if is operational, don't reset the chip */ |
---|
| 6743 | + if (static_if_ndev_get_state(cfg, net) == NDEV_STATE_FW_IF_CREATED) { |
---|
| 6744 | + DHD_ERROR(("static if operational. skip chip reset.\n")); |
---|
| 6745 | + skip_reset = true; |
---|
| 6746 | + wl_cfg80211_sta_ifdown(net); |
---|
| 6747 | + goto exit; |
---|
| 6748 | + } |
---|
| 6749 | +#endif /* WL_STATIC_IF && WL_CFG80211 */ |
---|
| 6750 | + |
---|
| 6751 | +#if defined(WL_VIF_SUPPORT) |
---|
| 6752 | + if (vif_num > 0) { |
---|
| 6753 | + DHD_ERROR(("virtual if operational. skip chip reset.\n")); |
---|
| 6754 | + skip_reset = true; |
---|
| 6755 | + wl_cfg80211_sta_ifdown(net); |
---|
| 6756 | + goto exit; |
---|
| 6757 | + } |
---|
| 6758 | +#endif /* WL_VIF_SUPPORT */ |
---|
| 6759 | + |
---|
| 6760 | + DHD_ERROR(("%s: making dhdpub up FALSE\n", __FUNCTION__)); |
---|
6286 | 6761 | #ifdef WL_CFG80211 |
---|
| 6762 | + |
---|
| 6763 | + /* Disable Runtime PM before interface down */ |
---|
| 6764 | + DHD_DISABLE_RUNTIME_PM(&dhd->pub); |
---|
| 6765 | + |
---|
6287 | 6766 | spin_lock_irqsave(&dhd->pub.up_lock, flags); |
---|
6288 | 6767 | dhd->pub.up = 0; |
---|
6289 | 6768 | spin_unlock_irqrestore(&dhd->pub.up_lock, flags); |
---|
6290 | 6769 | #else |
---|
6291 | 6770 | dhd->pub.up = 0; |
---|
6292 | | -#endif |
---|
| 6771 | +#endif /* WL_CFG80211 */ |
---|
6293 | 6772 | |
---|
6294 | 6773 | #ifdef WL_CFG80211 |
---|
6295 | 6774 | if (ifidx == 0) { |
---|
6296 | 6775 | dhd_if_t *ifp; |
---|
6297 | | - wl_cfg80211_down(NULL); |
---|
| 6776 | + wl_cfg80211_down(net); |
---|
6298 | 6777 | |
---|
6299 | 6778 | ifp = dhd->iflist[0]; |
---|
6300 | | - ASSERT(ifp && ifp->net); |
---|
6301 | 6779 | /* |
---|
6302 | 6780 | * For CFG80211: Clean up all the left over virtual interfaces |
---|
6303 | 6781 | * when the primary Interface is brought down. [ifconfig wlan0 down] |
---|
6304 | 6782 | */ |
---|
6305 | 6783 | if (!dhd_download_fw_on_driverload) { |
---|
| 6784 | + DHD_STATLOG_CTRL(&dhd->pub, ST(WLAN_POWER_OFF), ifidx, 0); |
---|
6306 | 6785 | if ((dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) && |
---|
6307 | 6786 | (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) { |
---|
6308 | 6787 | int i; |
---|
6309 | | - |
---|
6310 | 6788 | #ifdef WL_CFG80211_P2P_DEV_IF |
---|
6311 | | - wl_cfg80211_del_p2p_wdev(); |
---|
| 6789 | + wl_cfg80211_del_p2p_wdev(net); |
---|
6312 | 6790 | #endif /* WL_CFG80211_P2P_DEV_IF */ |
---|
| 6791 | +#ifdef DHD_4WAYM4_FAIL_DISCONNECT |
---|
| 6792 | + dhd_cleanup_m4_state_work(&dhd->pub, ifidx); |
---|
| 6793 | +#endif /* DHD_4WAYM4_FAIL_DISCONNECT */ |
---|
| 6794 | +#ifdef DHD_PKTDUMP_ROAM |
---|
| 6795 | + dhd_dump_pkt_clear(&dhd->pub); |
---|
| 6796 | +#endif /* DHD_PKTDUMP_ROAM */ |
---|
6313 | 6797 | |
---|
6314 | 6798 | dhd_net_if_lock_local(dhd); |
---|
6315 | 6799 | for (i = 1; i < DHD_MAX_IFS; i++) |
---|
.. | .. |
---|
6318 | 6802 | if (ifp && ifp->net) { |
---|
6319 | 6803 | dhd_if_del_sta_list(ifp); |
---|
6320 | 6804 | } |
---|
6321 | | - |
---|
6322 | 6805 | #ifdef ARP_OFFLOAD_SUPPORT |
---|
6323 | 6806 | if (dhd_inetaddr_notifier_registered) { |
---|
6324 | 6807 | dhd_inetaddr_notifier_registered = FALSE; |
---|
6325 | 6808 | unregister_inetaddr_notifier(&dhd_inetaddr_notifier); |
---|
6326 | 6809 | } |
---|
6327 | 6810 | #endif /* ARP_OFFLOAD_SUPPORT */ |
---|
6328 | | -#if defined(CONFIG_IPV6) |
---|
| 6811 | +#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT) |
---|
6329 | 6812 | if (dhd_inet6addr_notifier_registered) { |
---|
6330 | 6813 | dhd_inet6addr_notifier_registered = FALSE; |
---|
6331 | 6814 | unregister_inet6addr_notifier(&dhd_inet6addr_notifier); |
---|
6332 | 6815 | } |
---|
6333 | | -#endif /* OEM_ANDROID && CONFIG_IPV6 */ |
---|
| 6816 | +#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */ |
---|
6334 | 6817 | dhd_net_if_unlock_local(dhd); |
---|
6335 | 6818 | } |
---|
6336 | | - //remove this to prevent dev_close get stuck in dhd_hang_process |
---|
6337 | | - //cancel_work_sync(dhd->dhd_deferred_wq); |
---|
6338 | | -#if defined(DHD_LB) && defined(DHD_LB_RXP) |
---|
| 6819 | + cancel_work_sync(dhd->dhd_deferred_wq); |
---|
| 6820 | + |
---|
| 6821 | +#ifdef SHOW_LOGTRACE |
---|
| 6822 | + /* Wait till event logs work/kthread finishes */ |
---|
| 6823 | + dhd_cancel_logtrace_process_sync(dhd); |
---|
| 6824 | +#endif /* SHOW_LOGTRACE */ |
---|
| 6825 | + |
---|
| 6826 | +#if defined(DHD_LB_RXP) |
---|
6339 | 6827 | __skb_queue_purge(&dhd->rx_pend_queue); |
---|
6340 | | -#endif /* DHD_LB && DHD_LB_RXP */ |
---|
| 6828 | +#endif /* DHD_LB_RXP */ |
---|
| 6829 | + |
---|
| 6830 | +#if defined(DHD_LB_TXP) |
---|
| 6831 | + skb_queue_purge(&dhd->tx_pend_queue); |
---|
| 6832 | +#endif /* DHD_LB_TXP */ |
---|
6341 | 6833 | } |
---|
6342 | 6834 | |
---|
6343 | | -#if defined(BCMPCIE) && defined(DHDTCPACK_SUPPRESS) |
---|
| 6835 | +#if defined(ARGOS_NOTIFY_CB) |
---|
| 6836 | + argos_register_notifier_deinit(); |
---|
| 6837 | +#endif // endif |
---|
| 6838 | +#ifdef DHDTCPACK_SUPPRESS |
---|
6344 | 6839 | dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF); |
---|
6345 | | -#endif /* BCMPCIE && DHDTCPACK_SUPPRESS */ |
---|
6346 | | -#if defined(DHD_LB) && defined(DHD_LB_RXP) |
---|
6347 | | - if (ifp->net == dhd->rx_napi_netdev) { |
---|
| 6840 | +#endif /* DHDTCPACK_SUPPRESS */ |
---|
| 6841 | +#if defined(DHD_LB_RXP) |
---|
| 6842 | + if (ifp && ifp->net == dhd->rx_napi_netdev) { |
---|
6348 | 6843 | DHD_INFO(("%s napi<%p> disabled ifp->net<%p,%s>\n", |
---|
6349 | 6844 | __FUNCTION__, &dhd->rx_napi_struct, net, net->name)); |
---|
6350 | 6845 | skb_queue_purge(&dhd->rx_napi_queue); |
---|
.. | .. |
---|
6352 | 6847 | netif_napi_del(&dhd->rx_napi_struct); |
---|
6353 | 6848 | dhd->rx_napi_netdev = NULL; |
---|
6354 | 6849 | } |
---|
6355 | | -#endif /* DHD_LB && DHD_LB_RXP */ |
---|
6356 | | - |
---|
| 6850 | +#endif /* DHD_LB_RXP */ |
---|
6357 | 6851 | } |
---|
6358 | 6852 | #endif /* WL_CFG80211 */ |
---|
6359 | 6853 | |
---|
| 6854 | + DHD_SSSR_DUMP_DEINIT(&dhd->pub); |
---|
| 6855 | + |
---|
6360 | 6856 | #ifdef PROP_TXSTATUS |
---|
6361 | 6857 | dhd_wlfc_cleanup(&dhd->pub, NULL, 0); |
---|
6362 | | -#endif |
---|
| 6858 | +#endif // endif |
---|
| 6859 | +#ifdef SHOW_LOGTRACE |
---|
| 6860 | + if (!dhd_download_fw_on_driverload) { |
---|
| 6861 | + /* Release the skbs from queue for WLC_E_TRACE event */ |
---|
| 6862 | + dhd_event_logtrace_flush_queue(&dhd->pub); |
---|
| 6863 | + if (dhd->dhd_state & DHD_ATTACH_LOGTRACE_INIT) { |
---|
| 6864 | + if (dhd->event_data.fmts) { |
---|
| 6865 | + MFREE(dhd->pub.osh, dhd->event_data.fmts, |
---|
| 6866 | + dhd->event_data.fmts_size); |
---|
| 6867 | + dhd->event_data.fmts = NULL; |
---|
| 6868 | + } |
---|
| 6869 | + if (dhd->event_data.raw_fmts) { |
---|
| 6870 | + MFREE(dhd->pub.osh, dhd->event_data.raw_fmts, |
---|
| 6871 | + dhd->event_data.raw_fmts_size); |
---|
| 6872 | + dhd->event_data.raw_fmts = NULL; |
---|
| 6873 | + } |
---|
| 6874 | + if (dhd->event_data.raw_sstr) { |
---|
| 6875 | + MFREE(dhd->pub.osh, dhd->event_data.raw_sstr, |
---|
| 6876 | + dhd->event_data.raw_sstr_size); |
---|
| 6877 | + dhd->event_data.raw_sstr = NULL; |
---|
| 6878 | + } |
---|
| 6879 | + if (dhd->event_data.rom_raw_sstr) { |
---|
| 6880 | + MFREE(dhd->pub.osh, dhd->event_data.rom_raw_sstr, |
---|
| 6881 | + dhd->event_data.rom_raw_sstr_size); |
---|
| 6882 | + dhd->event_data.rom_raw_sstr = NULL; |
---|
| 6883 | + } |
---|
| 6884 | + dhd->dhd_state &= ~DHD_ATTACH_LOGTRACE_INIT; |
---|
| 6885 | + } |
---|
| 6886 | + } |
---|
| 6887 | +#endif /* SHOW_LOGTRACE */ |
---|
| 6888 | +#ifdef APF |
---|
| 6889 | + dhd_dev_apf_delete_filter(net); |
---|
| 6890 | +#endif /* APF */ |
---|
| 6891 | + |
---|
6363 | 6892 | /* Stop the protocol module */ |
---|
6364 | 6893 | dhd_prot_stop(&dhd->pub); |
---|
6365 | 6894 | |
---|
6366 | 6895 | OLD_MOD_DEC_USE_COUNT; |
---|
6367 | 6896 | exit: |
---|
6368 | | -#if defined(WL_CFG80211) |
---|
6369 | | - if (ifidx == 0 && !dhd_download_fw_on_driverload) |
---|
| 6897 | + if (skip_reset == false) { |
---|
| 6898 | +#if defined(WL_CFG80211) && defined(OEM_ANDROID) |
---|
| 6899 | + if (ifidx == 0 && !dhd_download_fw_on_driverload) { |
---|
| 6900 | +#if defined(BT_OVER_SDIO) |
---|
| 6901 | + dhd_bus_put(&dhd->pub, WLAN_MODULE); |
---|
| 6902 | + wl_android_set_wifi_on_flag(FALSE); |
---|
| 6903 | +#else |
---|
6370 | 6904 | wl_android_wifi_off(net, TRUE); |
---|
6371 | | -#endif |
---|
6372 | | - dhd->pub.hang_was_sent = 0; |
---|
| 6905 | +#endif /* BT_OVER_SDIO */ |
---|
| 6906 | + } |
---|
| 6907 | +#ifdef SUPPORT_DEEP_SLEEP |
---|
| 6908 | + else { |
---|
| 6909 | + /* CSP#505233: Flags to indicate if we distingish |
---|
| 6910 | + * power off policy when user set the memu |
---|
| 6911 | + * "Keep Wi-Fi on during sleep" to "Never" |
---|
| 6912 | + */ |
---|
| 6913 | + if (trigger_deep_sleep) { |
---|
| 6914 | + dhd_deepsleep(net, 1); |
---|
| 6915 | + trigger_deep_sleep = 0; |
---|
| 6916 | + } |
---|
| 6917 | + } |
---|
| 6918 | +#endif /* SUPPORT_DEEP_SLEEP */ |
---|
| 6919 | +#endif /* defined(WL_CFG80211) && defined(OEM_ANDROID) */ |
---|
| 6920 | + dhd->pub.hang_was_sent = 0; |
---|
| 6921 | + dhd->pub.hang_was_pending = 0; |
---|
6373 | 6922 | |
---|
6374 | | - /* Clear country spec for for built-in type driver */ |
---|
6375 | | - if (!dhd_download_fw_on_driverload) { |
---|
6376 | | - dhd->pub.dhd_cspec.country_abbrev[0] = 0x00; |
---|
6377 | | - dhd->pub.dhd_cspec.rev = 0; |
---|
6378 | | - dhd->pub.dhd_cspec.ccode[0] = 0x00; |
---|
6379 | | - } |
---|
| 6923 | + /* Clear country spec for for built-in type driver */ |
---|
| 6924 | + if (!dhd_download_fw_on_driverload) { |
---|
| 6925 | + dhd->pub.dhd_cspec.country_abbrev[0] = 0x00; |
---|
| 6926 | + dhd->pub.dhd_cspec.rev = 0; |
---|
| 6927 | + dhd->pub.dhd_cspec.ccode[0] = 0x00; |
---|
| 6928 | + } |
---|
6380 | 6929 | |
---|
6381 | 6930 | #ifdef BCMDBGFS |
---|
6382 | | - dhd_dbg_remove(); |
---|
6383 | | -#endif |
---|
| 6931 | + dhd_dbgfs_remove(); |
---|
| 6932 | +#endif // endif |
---|
| 6933 | + } |
---|
6384 | 6934 | |
---|
6385 | 6935 | DHD_PERIM_UNLOCK(&dhd->pub); |
---|
6386 | 6936 | DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
6387 | 6937 | |
---|
6388 | 6938 | /* Destroy wakelock */ |
---|
6389 | 6939 | if (!dhd_download_fw_on_driverload && |
---|
6390 | | - (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) { |
---|
| 6940 | + (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) && |
---|
| 6941 | + (skip_reset == false)) { |
---|
6391 | 6942 | DHD_OS_WAKE_LOCK_DESTROY(dhd); |
---|
6392 | 6943 | dhd->dhd_state &= ~DHD_ATTACH_STATE_WAKELOCKS_INIT; |
---|
6393 | 6944 | } |
---|
6394 | | - printf("%s: Exit\n", __FUNCTION__); |
---|
6395 | 6945 | |
---|
| 6946 | + mutex_unlock(&dhd->pub.ndev_op_sync); |
---|
6396 | 6947 | return 0; |
---|
6397 | 6948 | } |
---|
6398 | 6949 | |
---|
6399 | | -#if defined(WL_CFG80211) && defined(USE_INITIAL_SHORT_DWELL_TIME) |
---|
| 6950 | +#if defined(OEM_ANDROID) && defined(WL_CFG80211) && (defined(USE_INITIAL_2G_SCAN) || \ |
---|
| 6951 | + defined(USE_INITIAL_SHORT_DWELL_TIME)) |
---|
6400 | 6952 | extern bool g_first_broadcast_scan; |
---|
6401 | | -#endif |
---|
| 6953 | +#endif /* OEM_ANDROID && WL_CFG80211 && (USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME) */ |
---|
6402 | 6954 | |
---|
6403 | 6955 | #ifdef WL11U |
---|
6404 | 6956 | static int dhd_interworking_enable(dhd_pub_t *dhd) |
---|
.. | .. |
---|
6411 | 6963 | DHD_ERROR(("%s: enableing interworking failed, ret=%d\n", __FUNCTION__, ret)); |
---|
6412 | 6964 | } |
---|
6413 | 6965 | |
---|
6414 | | - if (ret == BCME_OK) { |
---|
6415 | | - /* basic capabilities for HS20 REL2 */ |
---|
6416 | | - uint32 cap = WL_WNM_BSSTRANS | WL_WNM_NOTIF; |
---|
6417 | | - ret = dhd_iovar(dhd, 0, "wnm", (char *)&cap, sizeof(cap), NULL, 0, TRUE); |
---|
6418 | | - if (ret < 0) { |
---|
6419 | | - DHD_ERROR(("%s: failed to set WNM info, ret=%d\n", __FUNCTION__, ret)); |
---|
6420 | | - } |
---|
6421 | | - } |
---|
6422 | | - |
---|
6423 | 6966 | return ret; |
---|
6424 | 6967 | } |
---|
6425 | 6968 | #endif /* WL11u */ |
---|
.. | .. |
---|
6430 | 6973 | dhd_info_t *dhd = DHD_DEV_INFO(net); |
---|
6431 | 6974 | #ifdef TOE |
---|
6432 | 6975 | uint32 toe_ol; |
---|
6433 | | -#endif |
---|
6434 | | -#ifdef BCM_FD_AGGR |
---|
6435 | | - char iovbuf[WLC_IOCTL_SMLEN]; |
---|
6436 | | - dbus_config_t config; |
---|
6437 | | - uint32 agglimit = 0; |
---|
6438 | | - uint32 rpc_agg = BCM_RPC_TP_DNGL_AGG_DPC; /* host aggr not enabled yet */ |
---|
6439 | | -#endif /* BCM_FD_AGGR */ |
---|
| 6976 | +#endif // endif |
---|
6440 | 6977 | int ifidx; |
---|
6441 | 6978 | int32 ret = 0; |
---|
6442 | 6979 | |
---|
6443 | | - if (!dhd_download_fw_on_driverload && !dhd_driver_init_done) { |
---|
6444 | | - DHD_ERROR(("%s: WLAN driver is not initialized\n", __FUNCTION__)); |
---|
6445 | | - return -1; |
---|
| 6980 | +#if defined(PREVENT_REOPEN_DURING_HANG) |
---|
| 6981 | + /* WAR : to prevent calling dhd_open abnormally in quick succession after hang event */ |
---|
| 6982 | + if (dhd->pub.hang_was_sent == 1) { |
---|
| 6983 | + DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__)); |
---|
| 6984 | + /* Force to bring down WLAN interface in case dhd_stop() is not called |
---|
| 6985 | + * from the upper layer when HANG event is triggered. |
---|
| 6986 | + */ |
---|
| 6987 | + if (!dhd_download_fw_on_driverload && dhd->pub.up == 1) { |
---|
| 6988 | + DHD_ERROR(("%s: WLAN interface is not brought down\n", __FUNCTION__)); |
---|
| 6989 | + dhd_stop(net); |
---|
| 6990 | + } else { |
---|
| 6991 | + return -1; |
---|
| 6992 | + } |
---|
| 6993 | + } |
---|
| 6994 | +#endif /* PREVENT_REOPEN_DURING_HANG */ |
---|
| 6995 | + |
---|
| 6996 | + mutex_lock(&dhd->pub.ndev_op_sync); |
---|
| 6997 | + |
---|
| 6998 | + if (dhd->pub.up == 1) { |
---|
| 6999 | + /* already up */ |
---|
| 7000 | + DHD_ERROR(("Primary net_device is already up \n")); |
---|
| 7001 | + mutex_unlock(&dhd->pub.ndev_op_sync); |
---|
| 7002 | + return BCME_OK; |
---|
6446 | 7003 | } |
---|
6447 | 7004 | |
---|
6448 | 7005 | if (!dhd_download_fw_on_driverload) { |
---|
| 7006 | + if (!dhd_driver_init_done) { |
---|
| 7007 | + DHD_ERROR(("%s: WLAN driver is not initialized\n", __FUNCTION__)); |
---|
| 7008 | + mutex_unlock(&dhd->pub.ndev_op_sync); |
---|
| 7009 | + return -1; |
---|
| 7010 | + } |
---|
| 7011 | + /* Init wakelock */ |
---|
6449 | 7012 | if (!(dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) { |
---|
6450 | 7013 | DHD_OS_WAKE_LOCK_INIT(dhd); |
---|
6451 | 7014 | dhd->dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT; |
---|
6452 | 7015 | } |
---|
| 7016 | + |
---|
| 7017 | +#ifdef SHOW_LOGTRACE |
---|
| 7018 | + skb_queue_head_init(&dhd->evt_trace_queue); |
---|
| 7019 | + |
---|
| 7020 | + if (!(dhd->dhd_state & DHD_ATTACH_LOGTRACE_INIT)) { |
---|
| 7021 | + ret = dhd_init_logstrs_array(dhd->pub.osh, &dhd->event_data); |
---|
| 7022 | + if (ret == BCME_OK) { |
---|
| 7023 | + dhd_init_static_strs_array(dhd->pub.osh, &dhd->event_data, |
---|
| 7024 | + st_str_file_path, map_file_path); |
---|
| 7025 | + dhd_init_static_strs_array(dhd->pub.osh, &dhd->event_data, |
---|
| 7026 | + rom_st_str_file_path, rom_map_file_path); |
---|
| 7027 | + dhd->dhd_state |= DHD_ATTACH_LOGTRACE_INIT; |
---|
| 7028 | + } |
---|
| 7029 | + } |
---|
| 7030 | +#endif /* SHOW_LOGTRACE */ |
---|
6453 | 7031 | } |
---|
| 7032 | + |
---|
| 7033 | +#if defined(MULTIPLE_SUPPLICANT) |
---|
| 7034 | +#if defined(OEM_ANDROID) && defined(BCMSDIO) |
---|
| 7035 | + if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) { |
---|
| 7036 | + DHD_ERROR(("%s : dhd_open: call dev open before insmod complete!\n", __FUNCTION__)); |
---|
| 7037 | + } |
---|
| 7038 | + mutex_lock(&_dhd_sdio_mutex_lock_); |
---|
| 7039 | +#endif // endif |
---|
| 7040 | +#endif /* MULTIPLE_SUPPLICANT */ |
---|
6454 | 7041 | |
---|
6455 | 7042 | DHD_OS_WAKE_LOCK(&dhd->pub); |
---|
6456 | 7043 | DHD_PERIM_LOCK(&dhd->pub); |
---|
6457 | 7044 | dhd->pub.dongle_trap_occured = 0; |
---|
6458 | 7045 | dhd->pub.hang_was_sent = 0; |
---|
| 7046 | + dhd->pub.hang_was_pending = 0; |
---|
| 7047 | + dhd->pub.hang_reason = 0; |
---|
| 7048 | + dhd->pub.iovar_timeout_occured = 0; |
---|
| 7049 | +#ifdef PCIE_FULL_DONGLE |
---|
| 7050 | + dhd->pub.d3ack_timeout_occured = 0; |
---|
| 7051 | + dhd->pub.livelock_occured = 0; |
---|
| 7052 | + dhd->pub.pktid_audit_failed = 0; |
---|
| 7053 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 7054 | + dhd->pub.iface_op_failed = 0; |
---|
| 7055 | + dhd->pub.scan_timeout_occurred = 0; |
---|
| 7056 | + dhd->pub.scan_busy_occurred = 0; |
---|
| 7057 | + dhd->pub.smmu_fault_occurred = 0; |
---|
| 7058 | + |
---|
6459 | 7059 | #ifdef DHD_LOSSLESS_ROAMING |
---|
6460 | 7060 | dhd->pub.dequeue_prec_map = ALLPRIO; |
---|
6461 | | -#endif |
---|
6462 | | -#if !defined(WL_CFG80211) |
---|
| 7061 | +#endif // endif |
---|
| 7062 | + |
---|
| 7063 | +#if defined(OEM_ANDROID) && !defined(WL_CFG80211) |
---|
6463 | 7064 | /* |
---|
6464 | 7065 | * Force start if ifconfig_up gets called before START command |
---|
6465 | 7066 | * We keep WEXT's wl_control_wl_start to provide backward compatibility |
---|
.. | .. |
---|
6472 | 7073 | goto exit; |
---|
6473 | 7074 | } |
---|
6474 | 7075 | |
---|
6475 | | -#endif |
---|
| 7076 | +#endif /* defined(OEM_ANDROID) && !defined(WL_CFG80211) */ |
---|
6476 | 7077 | |
---|
6477 | 7078 | ifidx = dhd_net2idx(dhd, net); |
---|
6478 | 7079 | DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); |
---|
.. | .. |
---|
6491 | 7092 | |
---|
6492 | 7093 | if (ifidx == 0) { |
---|
6493 | 7094 | atomic_set(&dhd->pend_8021x_cnt, 0); |
---|
6494 | | -#if defined(WL_CFG80211) |
---|
| 7095 | +#if defined(WL_CFG80211) && defined(OEM_ANDROID) |
---|
6495 | 7096 | if (!dhd_download_fw_on_driverload) { |
---|
6496 | 7097 | DHD_ERROR(("\n%s\n", dhd_version)); |
---|
6497 | | -#if defined(USE_INITIAL_SHORT_DWELL_TIME) |
---|
| 7098 | + DHD_STATLOG_CTRL(&dhd->pub, ST(WLAN_POWER_ON), ifidx, 0); |
---|
| 7099 | +#if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME) |
---|
6498 | 7100 | g_first_broadcast_scan = TRUE; |
---|
6499 | | -#endif |
---|
| 7101 | +#endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */ |
---|
| 7102 | +#ifdef SHOW_LOGTRACE |
---|
| 7103 | + /* dhd_cancel_logtrace_process_sync is called in dhd_stop |
---|
| 7104 | + * for built-in models. Need to start logtrace kthread before |
---|
| 7105 | + * calling wifi on, because once wifi is on, EDL will be in action |
---|
| 7106 | + * any moment, and if kthread is not active, FW event logs will |
---|
| 7107 | + * not be available |
---|
| 7108 | + */ |
---|
| 7109 | + if (dhd_reinit_logtrace_process(dhd) != BCME_OK) { |
---|
| 7110 | + goto exit; |
---|
| 7111 | + } |
---|
| 7112 | +#endif /* SHOW_LOGTRACE */ |
---|
| 7113 | +#if defined(BT_OVER_SDIO) |
---|
| 7114 | + ret = dhd_bus_get(&dhd->pub, WLAN_MODULE); |
---|
| 7115 | + wl_android_set_wifi_on_flag(TRUE); |
---|
| 7116 | +#else |
---|
6500 | 7117 | ret = wl_android_wifi_on(net); |
---|
| 7118 | +#endif /* BT_OVER_SDIO */ |
---|
6501 | 7119 | if (ret != 0) { |
---|
6502 | 7120 | DHD_ERROR(("%s : wl_android_wifi_on failed (%d)\n", |
---|
6503 | 7121 | __FUNCTION__, ret)); |
---|
.. | .. |
---|
6505 | 7123 | goto exit; |
---|
6506 | 7124 | } |
---|
6507 | 7125 | } |
---|
6508 | | -#endif |
---|
| 7126 | +#ifdef SUPPORT_DEEP_SLEEP |
---|
| 7127 | + else { |
---|
| 7128 | + /* Flags to indicate if we distingish |
---|
| 7129 | + * power off policy when user set the memu |
---|
| 7130 | + * "Keep Wi-Fi on during sleep" to "Never" |
---|
| 7131 | + */ |
---|
| 7132 | + if (trigger_deep_sleep) { |
---|
| 7133 | +#if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME) |
---|
| 7134 | + g_first_broadcast_scan = TRUE; |
---|
| 7135 | +#endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */ |
---|
| 7136 | + dhd_deepsleep(net, 0); |
---|
| 7137 | + trigger_deep_sleep = 0; |
---|
| 7138 | + } |
---|
| 7139 | + } |
---|
| 7140 | +#endif /* SUPPORT_DEEP_SLEEP */ |
---|
| 7141 | +#ifdef FIX_CPU_MIN_CLOCK |
---|
| 7142 | + if (dhd_get_fw_mode(dhd) == DHD_FLAG_HOSTAP_MODE) { |
---|
| 7143 | + dhd_init_cpufreq_fix(dhd); |
---|
| 7144 | + dhd_fix_cpu_freq(dhd); |
---|
| 7145 | + } |
---|
| 7146 | +#endif /* FIX_CPU_MIN_CLOCK */ |
---|
| 7147 | +#endif /* defined(WL_CFG80211) && defined(OEM_ANDROID) */ |
---|
6509 | 7148 | |
---|
6510 | 7149 | if (dhd->pub.busstate != DHD_BUS_DATA) { |
---|
6511 | 7150 | |
---|
6512 | | -#ifndef BCMDBUS |
---|
6513 | 7151 | /* try to bring up bus */ |
---|
6514 | 7152 | DHD_PERIM_UNLOCK(&dhd->pub); |
---|
| 7153 | + |
---|
| 7154 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 7155 | + if (pm_runtime_get_sync(dhd_bus_to_dev(dhd->pub.bus)) >= 0) { |
---|
| 7156 | + ret = dhd_bus_start(&dhd->pub); |
---|
| 7157 | + pm_runtime_mark_last_busy(dhd_bus_to_dev(dhd->pub.bus)); |
---|
| 7158 | + pm_runtime_put_autosuspend(dhd_bus_to_dev(dhd->pub.bus)); |
---|
| 7159 | + } |
---|
| 7160 | +#else |
---|
6515 | 7161 | ret = dhd_bus_start(&dhd->pub); |
---|
| 7162 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
| 7163 | + |
---|
6516 | 7164 | DHD_PERIM_LOCK(&dhd->pub); |
---|
6517 | 7165 | if (ret) { |
---|
6518 | 7166 | DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); |
---|
6519 | 7167 | ret = -1; |
---|
6520 | 7168 | goto exit; |
---|
6521 | 7169 | } |
---|
6522 | | -#else /* BCMDBUS */ |
---|
6523 | | - if ((ret = dbus_up(dhd->pub.dbus)) != 0) { |
---|
6524 | | - goto exit; |
---|
6525 | | - } else { |
---|
6526 | | - dhd->pub.busstate = DHD_BUS_DATA; |
---|
6527 | | - } |
---|
6528 | | - |
---|
6529 | | - if ((ret = dhd_sync_with_dongle(&dhd->pub)) < 0) { |
---|
6530 | | - DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); |
---|
6531 | | - goto exit; |
---|
6532 | | - } |
---|
6533 | | -#endif /* BCMDBUS */ |
---|
6534 | 7170 | |
---|
6535 | 7171 | } |
---|
6536 | 7172 | |
---|
6537 | | -#ifdef BCM_FD_AGGR |
---|
6538 | | - config.config_id = DBUS_CONFIG_ID_AGGR_LIMIT; |
---|
6539 | | - |
---|
6540 | | - |
---|
6541 | | - memset(iovbuf, 0, sizeof(iovbuf)); |
---|
6542 | | - if (!dhd_iovar(&dhd->pub, ifidx, "rpc_dngl_agglimit", NULL, 0, |
---|
6543 | | - (char *)iovbuf, sizeof(iovbuf), FALSE)) { |
---|
6544 | | - agglimit = *(uint32 *)iovbuf; |
---|
6545 | | - config.aggr_param.maxrxsf = agglimit >> BCM_RPC_TP_AGG_SF_SHIFT; |
---|
6546 | | - config.aggr_param.maxrxsize = agglimit & BCM_RPC_TP_AGG_BYTES_MASK; |
---|
6547 | | - DHD_ERROR(("rpc_dngl_agglimit %x : sf_limit %d bytes_limit %d\n", |
---|
6548 | | - agglimit, config.aggr_param.maxrxsf, config.aggr_param.maxrxsize)); |
---|
6549 | | - if (bcm_rpc_tp_set_config(dhd->pub.info->rpc_th, &config)) { |
---|
6550 | | - DHD_ERROR(("set tx/rx queue size and buffersize failed\n")); |
---|
6551 | | - } |
---|
6552 | | - } else { |
---|
6553 | | - DHD_ERROR(("get rpc_dngl_agglimit failed\n")); |
---|
6554 | | - rpc_agg &= ~BCM_RPC_TP_DNGL_AGG_DPC; |
---|
| 7173 | +#ifdef BT_OVER_SDIO |
---|
| 7174 | + if (dhd->pub.is_bt_recovery_required) { |
---|
| 7175 | + DHD_ERROR(("%s: Send Hang Notification 2 to BT\n", __FUNCTION__)); |
---|
| 7176 | + bcmsdh_btsdio_process_dhd_hang_notification(TRUE); |
---|
6555 | 7177 | } |
---|
6556 | | - |
---|
6557 | | - /* Set aggregation for TX */ |
---|
6558 | | - bcm_rpc_tp_agg_set(dhd->pub.info->rpc_th, BCM_RPC_TP_HOST_AGG_MASK, |
---|
6559 | | - rpc_agg & BCM_RPC_TP_HOST_AGG_MASK); |
---|
6560 | | - |
---|
6561 | | - /* Set aggregation for RX */ |
---|
6562 | | - if (!dhd_iovar(&dhd->pub, ifidx, "rpc_agg", (char *)&rpc_agg, sizeof(rpc_agg), |
---|
6563 | | - NULL, 0, TRUE)) { |
---|
6564 | | - dhd->pub.info->fdaggr = 0; |
---|
6565 | | - if (rpc_agg & BCM_RPC_TP_HOST_AGG_MASK) |
---|
6566 | | - dhd->pub.info->fdaggr |= BCM_FDAGGR_H2D_ENABLED; |
---|
6567 | | - if (rpc_agg & BCM_RPC_TP_DNGL_AGG_MASK) |
---|
6568 | | - dhd->pub.info->fdaggr |= BCM_FDAGGR_D2H_ENABLED; |
---|
6569 | | - } else { |
---|
6570 | | - DHD_ERROR(("%s(): Setting RX aggregation failed %d\n", __FUNCTION__, ret)); |
---|
6571 | | - } |
---|
6572 | | -#endif /* BCM_FD_AGGR */ |
---|
| 7178 | + dhd->pub.is_bt_recovery_required = FALSE; |
---|
| 7179 | +#endif // endif |
---|
6573 | 7180 | |
---|
6574 | 7181 | /* dhd_sync_with_dongle has been called in dhd_bus_start or wl_android_wifi_on */ |
---|
6575 | 7182 | memcpy(net->dev_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN); |
---|
.. | .. |
---|
6583 | 7190 | } |
---|
6584 | 7191 | #endif /* TOE */ |
---|
6585 | 7192 | |
---|
| 7193 | +#if defined(DHD_LB_RXP) |
---|
| 7194 | + __skb_queue_head_init(&dhd->rx_pend_queue); |
---|
| 7195 | + if (dhd->rx_napi_netdev == NULL) { |
---|
| 7196 | + dhd->rx_napi_netdev = dhd->iflist[ifidx]->net; |
---|
| 7197 | + memset(&dhd->rx_napi_struct, 0, sizeof(struct napi_struct)); |
---|
| 7198 | + netif_napi_add(dhd->rx_napi_netdev, &dhd->rx_napi_struct, |
---|
| 7199 | + dhd_napi_poll, dhd_napi_weight); |
---|
| 7200 | + DHD_INFO(("%s napi<%p> enabled ifp->net<%p,%s>\n", |
---|
| 7201 | + __FUNCTION__, &dhd->rx_napi_struct, net, net->name)); |
---|
| 7202 | + napi_enable(&dhd->rx_napi_struct); |
---|
| 7203 | + DHD_INFO(("%s load balance init rx_napi_struct\n", __FUNCTION__)); |
---|
| 7204 | + skb_queue_head_init(&dhd->rx_napi_queue); |
---|
| 7205 | + } /* rx_napi_netdev == NULL */ |
---|
| 7206 | +#endif /* DHD_LB_RXP */ |
---|
| 7207 | + |
---|
| 7208 | +#if defined(DHD_LB_TXP) |
---|
| 7209 | + /* Use the variant that uses locks */ |
---|
| 7210 | + skb_queue_head_init(&dhd->tx_pend_queue); |
---|
| 7211 | +#endif /* DHD_LB_TXP */ |
---|
| 7212 | + |
---|
6586 | 7213 | #if defined(WL_CFG80211) |
---|
6587 | | - if (unlikely(wl_cfg80211_up(NULL))) { |
---|
| 7214 | + if (unlikely(wl_cfg80211_up(net))) { |
---|
6588 | 7215 | DHD_ERROR(("%s: failed to bring up cfg80211\n", __FUNCTION__)); |
---|
6589 | 7216 | ret = -1; |
---|
6590 | 7217 | goto exit; |
---|
.. | .. |
---|
6597 | 7224 | register_inetaddr_notifier(&dhd_inetaddr_notifier); |
---|
6598 | 7225 | } |
---|
6599 | 7226 | #endif /* ARP_OFFLOAD_SUPPORT */ |
---|
6600 | | -#if defined(CONFIG_IPV6) |
---|
| 7227 | +#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT) |
---|
6601 | 7228 | if (!dhd_inet6addr_notifier_registered) { |
---|
6602 | 7229 | dhd_inet6addr_notifier_registered = TRUE; |
---|
6603 | 7230 | register_inet6addr_notifier(&dhd_inet6addr_notifier); |
---|
6604 | 7231 | } |
---|
6605 | | -#endif /* OEM_ANDROID && CONFIG_IPV6 */ |
---|
6606 | | -#ifdef DHD_LB |
---|
6607 | | - DHD_LB_STATS_INIT(&dhd->pub); |
---|
6608 | | -#ifdef DHD_LB_RXP |
---|
6609 | | - __skb_queue_head_init(&dhd->rx_pend_queue); |
---|
6610 | | -#endif /* DHD_LB_RXP */ |
---|
6611 | | -#endif /* DHD_LB */ |
---|
| 7232 | +#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */ |
---|
6612 | 7233 | } |
---|
6613 | 7234 | |
---|
| 7235 | +#if defined(DHD_CONTROL_PCIE_ASPM_WIFI_TURNON) |
---|
| 7236 | + dhd_bus_aspm_enable_rc_ep(dhd->pub.bus, TRUE); |
---|
| 7237 | +#endif /* DHD_CONTROL_PCIE_ASPM_WIFI_TURNON */ |
---|
| 7238 | +#if defined(DHD_CONTROL_PCIE_CPUCORE_WIFI_TURNON) |
---|
| 7239 | + dhd_irq_set_affinity(&dhd->pub, cpumask_of(0)); |
---|
| 7240 | +#endif /* DHD_CONTROL_PCIE_CPUCORE_WIFI_TURNON */ |
---|
| 7241 | +#ifdef DHD_LB_IRQSET |
---|
| 7242 | + dhd_irq_set_affinity(&dhd->pub, dhd->cpumask_primary); |
---|
| 7243 | +#endif /* DHD_LB_IRQSET */ |
---|
| 7244 | +#if defined(ARGOS_NOTIFY_CB) |
---|
| 7245 | + argos_register_notifier_init(net); |
---|
| 7246 | +#endif // endif |
---|
6614 | 7247 | #if defined(BCMPCIE) && defined(DHDTCPACK_SUPPRESS) |
---|
6615 | 7248 | #if defined(SET_RPS_CPUS) |
---|
6616 | 7249 | dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF); |
---|
6617 | 7250 | #else |
---|
6618 | | - dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_HOLD); |
---|
6619 | | -#endif |
---|
| 7251 | + dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF); |
---|
| 7252 | +#endif // endif |
---|
6620 | 7253 | #endif /* BCMPCIE && DHDTCPACK_SUPPRESS */ |
---|
6621 | | -#if defined(DHD_LB) && defined(DHD_LB_RXP) |
---|
6622 | | - if (dhd->rx_napi_netdev == NULL) { |
---|
6623 | | - dhd->rx_napi_netdev = dhd->iflist[ifidx]->net; |
---|
6624 | | - memset(&dhd->rx_napi_struct, 0, sizeof(struct napi_struct)); |
---|
6625 | | - netif_napi_add(dhd->rx_napi_netdev, &dhd->rx_napi_struct, |
---|
6626 | | - dhd_napi_poll, dhd_napi_weight); |
---|
6627 | | - DHD_INFO(("%s napi<%p> enabled ifp->net<%p,%s>\n", |
---|
6628 | | - __FUNCTION__, &dhd->rx_napi_struct, net, net->name)); |
---|
6629 | | - napi_enable(&dhd->rx_napi_struct); |
---|
6630 | | - DHD_INFO(("%s load balance init rx_napi_struct\n", __FUNCTION__)); |
---|
6631 | | - skb_queue_head_init(&dhd->rx_napi_queue); |
---|
6632 | | - } |
---|
6633 | | -#endif /* DHD_LB && DHD_LB_RXP */ |
---|
6634 | 7254 | #if defined(NUM_SCB_MAX_PROBE) |
---|
6635 | 7255 | dhd_set_scb_probe(&dhd->pub); |
---|
6636 | 7256 | #endif /* NUM_SCB_MAX_PROBE */ |
---|
6637 | 7257 | #endif /* WL_CFG80211 */ |
---|
6638 | 7258 | } |
---|
6639 | 7259 | |
---|
6640 | | - /* Allow transmit calls */ |
---|
6641 | | - netif_start_queue(net); |
---|
6642 | 7260 | dhd->pub.up = 1; |
---|
| 7261 | + |
---|
| 7262 | + if (wl_event_enable) { |
---|
| 7263 | + /* For wl utility to receive events */ |
---|
| 7264 | + dhd->pub.wl_event_enabled = true; |
---|
| 7265 | + } else { |
---|
| 7266 | + dhd->pub.wl_event_enabled = false; |
---|
| 7267 | + } |
---|
| 7268 | + |
---|
| 7269 | + if (logtrace_pkt_sendup) { |
---|
| 7270 | + /* For any deamon to recieve logtrace */ |
---|
| 7271 | + dhd->pub.logtrace_pkt_sendup = true; |
---|
| 7272 | + } else { |
---|
| 7273 | + dhd->pub.logtrace_pkt_sendup = false; |
---|
| 7274 | + } |
---|
6643 | 7275 | |
---|
6644 | 7276 | OLD_MOD_INC_USE_COUNT; |
---|
6645 | 7277 | |
---|
6646 | 7278 | #ifdef BCMDBGFS |
---|
6647 | | - dhd_dbg_init(&dhd->pub); |
---|
6648 | | -#endif |
---|
| 7279 | + dhd_dbgfs_init(&dhd->pub); |
---|
| 7280 | +#endif // endif |
---|
6649 | 7281 | |
---|
6650 | 7282 | exit: |
---|
| 7283 | + mutex_unlock(&dhd->pub.ndev_op_sync); |
---|
6651 | 7284 | if (ret) { |
---|
6652 | 7285 | dhd_stop(net); |
---|
6653 | 7286 | } |
---|
.. | .. |
---|
6655 | 7288 | DHD_PERIM_UNLOCK(&dhd->pub); |
---|
6656 | 7289 | DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
6657 | 7290 | |
---|
| 7291 | +#if defined(MULTIPLE_SUPPLICANT) |
---|
| 7292 | +#if defined(OEM_ANDROID) && defined(BCMSDIO) |
---|
| 7293 | + mutex_unlock(&_dhd_sdio_mutex_lock_); |
---|
| 7294 | +#endif // endif |
---|
| 7295 | +#endif /* MULTIPLE_SUPPLICANT */ |
---|
6658 | 7296 | |
---|
6659 | 7297 | return ret; |
---|
6660 | 7298 | } |
---|
| 7299 | + |
---|
| 7300 | +/* |
---|
| 7301 | + * ndo_start handler for primary ndev |
---|
| 7302 | + */ |
---|
| 7303 | +static int |
---|
| 7304 | +dhd_pri_open(struct net_device *net) |
---|
| 7305 | +{ |
---|
| 7306 | + s32 ret; |
---|
| 7307 | + |
---|
| 7308 | + ret = dhd_open(net); |
---|
| 7309 | + if (unlikely(ret)) { |
---|
| 7310 | + DHD_ERROR(("Failed to open primary dev ret %d\n", ret)); |
---|
| 7311 | + return ret; |
---|
| 7312 | + } |
---|
| 7313 | + |
---|
| 7314 | + /* Allow transmit calls */ |
---|
| 7315 | + netif_start_queue(net); |
---|
| 7316 | + DHD_ERROR(("[%s] tx queue started\n", net->name)); |
---|
| 7317 | + return ret; |
---|
| 7318 | +} |
---|
| 7319 | + |
---|
| 7320 | +/* |
---|
| 7321 | + * ndo_stop handler for primary ndev |
---|
| 7322 | + */ |
---|
| 7323 | +static int |
---|
| 7324 | +dhd_pri_stop(struct net_device *net) |
---|
| 7325 | +{ |
---|
| 7326 | + s32 ret; |
---|
| 7327 | + |
---|
| 7328 | + /* stop tx queue */ |
---|
| 7329 | + netif_stop_queue(net); |
---|
| 7330 | + DHD_ERROR(("[%s] tx queue stopped\n", net->name)); |
---|
| 7331 | + |
---|
| 7332 | + ret = dhd_stop(net); |
---|
| 7333 | + if (unlikely(ret)) { |
---|
| 7334 | + DHD_ERROR(("dhd_stop failed: %d\n", ret)); |
---|
| 7335 | + return ret; |
---|
| 7336 | + } |
---|
| 7337 | + |
---|
| 7338 | + return ret; |
---|
| 7339 | +} |
---|
| 7340 | + |
---|
| 7341 | +#if defined(WL_STATIC_IF) && defined(WL_CFG80211) |
---|
| 7342 | +/* |
---|
| 7343 | + * For static I/Fs, the firmware interface init |
---|
| 7344 | + * is done from the IFF_UP context. |
---|
| 7345 | + */ |
---|
| 7346 | +static int |
---|
| 7347 | +dhd_static_if_open(struct net_device *net) |
---|
| 7348 | +{ |
---|
| 7349 | + s32 ret = 0; |
---|
| 7350 | + struct bcm_cfg80211 *cfg; |
---|
| 7351 | + struct net_device *primary_netdev = NULL; |
---|
| 7352 | + |
---|
| 7353 | + cfg = wl_get_cfg(net); |
---|
| 7354 | + primary_netdev = bcmcfg_to_prmry_ndev(cfg); |
---|
| 7355 | + |
---|
| 7356 | + if (!is_static_iface(cfg, net)) { |
---|
| 7357 | + DHD_TRACE(("non-static interface (%s)..do nothing \n", net->name)); |
---|
| 7358 | + ret = BCME_OK; |
---|
| 7359 | + goto done; |
---|
| 7360 | + } |
---|
| 7361 | + |
---|
| 7362 | + DHD_INFO(("[%s][STATIC_IF] Enter \n", net->name)); |
---|
| 7363 | + /* Ensure fw is initialized. If it is already initialized, |
---|
| 7364 | + * dhd_open will return success. |
---|
| 7365 | + */ |
---|
| 7366 | + ret = dhd_open(primary_netdev); |
---|
| 7367 | + if (unlikely(ret)) { |
---|
| 7368 | + DHD_ERROR(("Failed to open primary dev ret %d\n", ret)); |
---|
| 7369 | + goto done; |
---|
| 7370 | + } |
---|
| 7371 | + |
---|
| 7372 | + ret = wl_cfg80211_static_if_open(net); |
---|
| 7373 | + if (!ret) { |
---|
| 7374 | + /* Allow transmit calls */ |
---|
| 7375 | + netif_start_queue(net); |
---|
| 7376 | + } |
---|
| 7377 | +done: |
---|
| 7378 | + return ret; |
---|
| 7379 | +} |
---|
| 7380 | + |
---|
| 7381 | +static int |
---|
| 7382 | +dhd_static_if_stop(struct net_device *net) |
---|
| 7383 | +{ |
---|
| 7384 | + struct bcm_cfg80211 *cfg; |
---|
| 7385 | + struct net_device *primary_netdev = NULL; |
---|
| 7386 | + int ret = BCME_OK; |
---|
| 7387 | + dhd_info_t *dhd = DHD_DEV_INFO(net); |
---|
| 7388 | + |
---|
| 7389 | + DHD_INFO(("[%s][STATIC_IF] Enter \n", net->name)); |
---|
| 7390 | + |
---|
| 7391 | + /* Ensure queue is disabled */ |
---|
| 7392 | + netif_tx_disable(net); |
---|
| 7393 | + |
---|
| 7394 | + cfg = wl_get_cfg(net); |
---|
| 7395 | + if (!is_static_iface(cfg, net)) { |
---|
| 7396 | + DHD_TRACE(("non-static interface (%s)..do nothing \n", net->name)); |
---|
| 7397 | + return BCME_OK; |
---|
| 7398 | + } |
---|
| 7399 | + |
---|
| 7400 | + ret = wl_cfg80211_static_if_close(net); |
---|
| 7401 | + |
---|
| 7402 | + if (dhd->pub.up == 0) { |
---|
| 7403 | + /* If fw is down, return */ |
---|
| 7404 | + DHD_ERROR(("fw down\n")); |
---|
| 7405 | + return BCME_OK; |
---|
| 7406 | + } |
---|
| 7407 | + /* If STA iface is not in operational, invoke dhd_close from this |
---|
| 7408 | + * context. |
---|
| 7409 | + */ |
---|
| 7410 | + primary_netdev = bcmcfg_to_prmry_ndev(cfg); |
---|
| 7411 | + if (!(primary_netdev->flags & IFF_UP)) { |
---|
| 7412 | + ret = dhd_stop(primary_netdev); |
---|
| 7413 | + } else { |
---|
| 7414 | + DHD_ERROR(("Skipped dhd_stop, as sta is operational\n")); |
---|
| 7415 | + } |
---|
| 7416 | + |
---|
| 7417 | + return ret; |
---|
| 7418 | +} |
---|
| 7419 | +#endif /* WL_STATIC_IF && WL_CF80211 */ |
---|
6661 | 7420 | |
---|
6662 | 7421 | int dhd_do_driver_init(struct net_device *net) |
---|
6663 | 7422 | { |
---|
.. | .. |
---|
6668 | 7427 | return -EINVAL; |
---|
6669 | 7428 | } |
---|
6670 | 7429 | |
---|
| 7430 | +#ifdef MULTIPLE_SUPPLICANT |
---|
| 7431 | +#if defined(OEM_ANDROID) && defined(BCMSDIO) |
---|
| 7432 | + if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) { |
---|
| 7433 | + DHD_ERROR(("%s : dhdsdio_probe is already running!\n", __FUNCTION__)); |
---|
| 7434 | + return 0; |
---|
| 7435 | + } |
---|
| 7436 | +#endif /* OEM_ANDROID & BCMSDIO */ |
---|
| 7437 | +#endif /* MULTIPLE_SUPPLICANT */ |
---|
6671 | 7438 | |
---|
6672 | 7439 | /* && defined(OEM_ANDROID) && defined(BCMSDIO) */ |
---|
6673 | 7440 | dhd = DHD_DEV_INFO(net); |
---|
.. | .. |
---|
6692 | 7459 | { |
---|
6693 | 7460 | |
---|
6694 | 7461 | #ifdef WL_CFG80211 |
---|
6695 | | - if (wl_cfg80211_notify_ifadd(ifevent->ifidx, name, mac, ifevent->bssidx) == BCME_OK) |
---|
| 7462 | + if (wl_cfg80211_notify_ifadd(dhd_linux_get_primary_netdev(&dhdinfo->pub), |
---|
| 7463 | + ifevent->ifidx, name, mac, ifevent->bssidx, ifevent->role) == BCME_OK) |
---|
6696 | 7464 | return BCME_OK; |
---|
6697 | | -#endif |
---|
| 7465 | +#endif // endif |
---|
6698 | 7466 | |
---|
6699 | 7467 | /* handle IF event caused by wl commands, SoftAP, WEXT and |
---|
6700 | 7468 | * anything else. This has to be done asynchronously otherwise |
---|
.. | .. |
---|
6714 | 7482 | strncpy(if_event->name, name, IFNAMSIZ); |
---|
6715 | 7483 | if_event->name[IFNAMSIZ - 1] = '\0'; |
---|
6716 | 7484 | dhd_deferred_schedule_work(dhdinfo->dhd_deferred_wq, (void *)if_event, |
---|
6717 | | - DHD_WQ_WORK_IF_ADD, dhd_ifadd_event_handler, DHD_WORK_PRIORITY_LOW); |
---|
| 7485 | + DHD_WQ_WORK_IF_ADD, dhd_ifadd_event_handler, DHD_WQ_WORK_PRIORITY_LOW); |
---|
6718 | 7486 | } |
---|
6719 | 7487 | |
---|
6720 | 7488 | return BCME_OK; |
---|
.. | .. |
---|
6726 | 7494 | dhd_if_event_t *if_event; |
---|
6727 | 7495 | |
---|
6728 | 7496 | #ifdef WL_CFG80211 |
---|
6729 | | - if (wl_cfg80211_notify_ifdel(ifevent->ifidx, name, mac, ifevent->bssidx) == BCME_OK) |
---|
| 7497 | + if (wl_cfg80211_notify_ifdel(dhd_linux_get_primary_netdev(&dhdinfo->pub), |
---|
| 7498 | + ifevent->ifidx, name, mac, ifevent->bssidx) == BCME_OK) |
---|
6730 | 7499 | return BCME_OK; |
---|
6731 | 7500 | #endif /* WL_CFG80211 */ |
---|
6732 | 7501 | |
---|
.. | .. |
---|
6744 | 7513 | strncpy(if_event->name, name, IFNAMSIZ); |
---|
6745 | 7514 | if_event->name[IFNAMSIZ - 1] = '\0'; |
---|
6746 | 7515 | dhd_deferred_schedule_work(dhdinfo->dhd_deferred_wq, (void *)if_event, DHD_WQ_WORK_IF_DEL, |
---|
6747 | | - dhd_ifdel_event_handler, DHD_WORK_PRIORITY_LOW); |
---|
| 7516 | + dhd_ifdel_event_handler, DHD_WQ_WORK_PRIORITY_LOW); |
---|
6748 | 7517 | |
---|
6749 | 7518 | return BCME_OK; |
---|
6750 | 7519 | } |
---|
| 7520 | + |
---|
| 7521 | +int |
---|
| 7522 | +dhd_event_ifchange(dhd_info_t *dhdinfo, wl_event_data_if_t *ifevent, char *name, uint8 *mac) |
---|
| 7523 | +{ |
---|
| 7524 | +#ifdef WL_CFG80211 |
---|
| 7525 | + wl_cfg80211_notify_ifchange(dhd_linux_get_primary_netdev(&dhdinfo->pub), |
---|
| 7526 | + ifevent->ifidx, name, mac, ifevent->bssidx); |
---|
| 7527 | +#endif /* WL_CFG80211 */ |
---|
| 7528 | + return BCME_OK; |
---|
| 7529 | +} |
---|
| 7530 | + |
---|
| 7531 | +#ifdef WL_NATOE |
---|
| 7532 | +/* Handler to update natoe info and bind with new subscriptions if there is change in config */ |
---|
| 7533 | +static void |
---|
| 7534 | +dhd_natoe_ct_event_hanlder(void *handle, void *event_info, u8 event) |
---|
| 7535 | +{ |
---|
| 7536 | + dhd_info_t *dhd = handle; |
---|
| 7537 | + wl_event_data_natoe_t *natoe = event_info; |
---|
| 7538 | + dhd_nfct_info_t *nfct = dhd->pub.nfct; |
---|
| 7539 | + |
---|
| 7540 | + if (event != DHD_WQ_WORK_NATOE_EVENT) { |
---|
| 7541 | + DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); |
---|
| 7542 | + return; |
---|
| 7543 | + } |
---|
| 7544 | + |
---|
| 7545 | + if (!dhd) { |
---|
| 7546 | + DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); |
---|
| 7547 | + return; |
---|
| 7548 | + } |
---|
| 7549 | + if (natoe->natoe_active && natoe->sta_ip && natoe->start_port && natoe->end_port && |
---|
| 7550 | + (natoe->start_port < natoe->end_port)) { |
---|
| 7551 | + /* Rebind subscriptions to start receiving notifications from groups */ |
---|
| 7552 | + if (dhd_ct_nl_bind(nfct, nfct->subscriptions) < 0) { |
---|
| 7553 | + dhd_ct_close(nfct); |
---|
| 7554 | + } |
---|
| 7555 | + dhd_ct_send_dump_req(nfct); |
---|
| 7556 | + } else if (!natoe->natoe_active) { |
---|
| 7557 | + /* Rebind subscriptions to stop receiving notifications from groups */ |
---|
| 7558 | + if (dhd_ct_nl_bind(nfct, CT_NULL_SUBSCRIPTION) < 0) { |
---|
| 7559 | + dhd_ct_close(nfct); |
---|
| 7560 | + } |
---|
| 7561 | + } |
---|
| 7562 | +} |
---|
| 7563 | + |
---|
| 7564 | +/* As NATOE enable/disbale event is received, we have to bind with new NL subscriptions. |
---|
| 7565 | + * Scheduling workq to switch from tasklet context as bind call may sleep in handler |
---|
| 7566 | + */ |
---|
| 7567 | +int |
---|
| 7568 | +dhd_natoe_ct_event(dhd_pub_t *dhd, char *data) |
---|
| 7569 | +{ |
---|
| 7570 | + wl_event_data_natoe_t *event_data = (wl_event_data_natoe_t *)data; |
---|
| 7571 | + |
---|
| 7572 | + if (dhd->nfct) { |
---|
| 7573 | + wl_event_data_natoe_t *natoe = dhd->nfct->natoe_info; |
---|
| 7574 | + uint8 prev_enable = natoe->natoe_active; |
---|
| 7575 | + |
---|
| 7576 | + spin_lock_bh(&dhd->nfct_lock); |
---|
| 7577 | + memcpy(natoe, event_data, sizeof(*event_data)); |
---|
| 7578 | + spin_unlock_bh(&dhd->nfct_lock); |
---|
| 7579 | + |
---|
| 7580 | + if (prev_enable != event_data->natoe_active) { |
---|
| 7581 | + dhd_deferred_schedule_work(dhd->info->dhd_deferred_wq, |
---|
| 7582 | + (void *)natoe, DHD_WQ_WORK_NATOE_EVENT, |
---|
| 7583 | + dhd_natoe_ct_event_hanlder, DHD_WQ_WORK_PRIORITY_LOW); |
---|
| 7584 | + } |
---|
| 7585 | + return BCME_OK; |
---|
| 7586 | + } |
---|
| 7587 | + DHD_ERROR(("%s ERROR NFCT is not enabled \n", __FUNCTION__)); |
---|
| 7588 | + return BCME_ERROR; |
---|
| 7589 | +} |
---|
| 7590 | + |
---|
| 7591 | +/* Handler to send natoe ioctl to dongle */ |
---|
| 7592 | +static void |
---|
| 7593 | +dhd_natoe_ct_ioctl_handler(void *handle, void *event_info, uint8 event) |
---|
| 7594 | +{ |
---|
| 7595 | + dhd_info_t *dhd = handle; |
---|
| 7596 | + dhd_ct_ioc_t *ct_ioc = event_info; |
---|
| 7597 | + |
---|
| 7598 | + if (event != DHD_WQ_WORK_NATOE_IOCTL) { |
---|
| 7599 | + DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); |
---|
| 7600 | + return; |
---|
| 7601 | + } |
---|
| 7602 | + |
---|
| 7603 | + if (!dhd) { |
---|
| 7604 | + DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); |
---|
| 7605 | + return; |
---|
| 7606 | + } |
---|
| 7607 | + |
---|
| 7608 | + if (dhd_natoe_prep_send_exception_port_ioctl(&dhd->pub, ct_ioc) < 0) { |
---|
| 7609 | + DHD_ERROR(("%s: Error in sending NATOE IOCTL \n", __FUNCTION__)); |
---|
| 7610 | + } |
---|
| 7611 | +} |
---|
| 7612 | + |
---|
| 7613 | +/* When Netlink message contains port collision info, the info must be sent to dongle FW |
---|
| 7614 | + * For that we have to switch context from softirq/tasklet by scheduling workq for natoe_ct ioctl |
---|
| 7615 | + */ |
---|
| 7616 | +void |
---|
| 7617 | +dhd_natoe_ct_ioctl_schedule_work(dhd_pub_t *dhd, dhd_ct_ioc_t *ioc) |
---|
| 7618 | +{ |
---|
| 7619 | + |
---|
| 7620 | + dhd_deferred_schedule_work(dhd->info->dhd_deferred_wq, (void *)ioc, |
---|
| 7621 | + DHD_WQ_WORK_NATOE_IOCTL, dhd_natoe_ct_ioctl_handler, |
---|
| 7622 | + DHD_WQ_WORK_PRIORITY_HIGH); |
---|
| 7623 | +} |
---|
| 7624 | +#endif /* WL_NATOE */ |
---|
| 7625 | + |
---|
| 7626 | +/* This API maps ndev to ifp inclusive of static IFs */ |
---|
| 7627 | +static dhd_if_t * |
---|
| 7628 | +dhd_get_ifp_by_ndev(dhd_pub_t *dhdp, struct net_device *ndev) |
---|
| 7629 | +{ |
---|
| 7630 | + dhd_if_t *ifp = NULL; |
---|
| 7631 | +#ifdef WL_STATIC_IF |
---|
| 7632 | + u32 ifidx = (DHD_MAX_IFS + DHD_MAX_STATIC_IFS - 1); |
---|
| 7633 | +#else |
---|
| 7634 | + u32 ifidx = (DHD_MAX_IFS - 1); |
---|
| 7635 | +#endif /* WL_STATIC_IF */ |
---|
| 7636 | + |
---|
| 7637 | + dhd_info_t *dhdinfo = (dhd_info_t *)dhdp->info; |
---|
| 7638 | + do { |
---|
| 7639 | + ifp = dhdinfo->iflist[ifidx]; |
---|
| 7640 | + if (ifp && (ifp->net == ndev)) { |
---|
| 7641 | + DHD_TRACE(("match found for %s. ifidx:%d\n", |
---|
| 7642 | + ndev->name, ifidx)); |
---|
| 7643 | + return ifp; |
---|
| 7644 | + } |
---|
| 7645 | + } while (ifidx--); |
---|
| 7646 | + |
---|
| 7647 | + DHD_ERROR(("no entry found for %s\n", ndev->name)); |
---|
| 7648 | + return NULL; |
---|
| 7649 | +} |
---|
| 7650 | + |
---|
| 7651 | +bool |
---|
| 7652 | +dhd_is_static_ndev(dhd_pub_t *dhdp, struct net_device *ndev) |
---|
| 7653 | +{ |
---|
| 7654 | + dhd_if_t *ifp = NULL; |
---|
| 7655 | + |
---|
| 7656 | + if (!dhdp || !ndev) { |
---|
| 7657 | + DHD_ERROR(("wrong input\n")); |
---|
| 7658 | + ASSERT(0); |
---|
| 7659 | + return false; |
---|
| 7660 | + } |
---|
| 7661 | + |
---|
| 7662 | + ifp = dhd_get_ifp_by_ndev(dhdp, ndev); |
---|
| 7663 | + return (ifp && (ifp->static_if == true)); |
---|
| 7664 | +} |
---|
| 7665 | + |
---|
| 7666 | +#ifdef WL_STATIC_IF |
---|
| 7667 | +/* In some cases, while registering I/F, the actual ifidx, bssidx and dngl_name |
---|
| 7668 | + * are not known. For e.g: static i/f case. This function lets to update it once |
---|
| 7669 | + * it is known. |
---|
| 7670 | + */ |
---|
| 7671 | +s32 |
---|
| 7672 | +dhd_update_iflist_info(dhd_pub_t *dhdp, struct net_device *ndev, int ifidx, |
---|
| 7673 | + uint8 *mac, uint8 bssidx, const char *dngl_name, int if_state) |
---|
| 7674 | +{ |
---|
| 7675 | + dhd_info_t *dhdinfo = (dhd_info_t *)dhdp->info; |
---|
| 7676 | + dhd_if_t *ifp, *ifp_new; |
---|
| 7677 | + s32 cur_idx; |
---|
| 7678 | + dhd_dev_priv_t * dev_priv; |
---|
| 7679 | + |
---|
| 7680 | + DHD_TRACE(("[STATIC_IF] update ifinfo for state:%d ifidx:%d\n", |
---|
| 7681 | + if_state, ifidx)); |
---|
| 7682 | + |
---|
| 7683 | + ASSERT(dhdinfo && (ifidx < (DHD_MAX_IFS + DHD_MAX_STATIC_IFS))); |
---|
| 7684 | + |
---|
| 7685 | + if ((ifp = dhd_get_ifp_by_ndev(dhdp, ndev)) == NULL) { |
---|
| 7686 | + return -ENODEV; |
---|
| 7687 | + } |
---|
| 7688 | + cur_idx = ifp->idx; |
---|
| 7689 | + |
---|
| 7690 | + if (if_state == NDEV_STATE_OS_IF_CREATED) { |
---|
| 7691 | + /* mark static if */ |
---|
| 7692 | + ifp->static_if = TRUE; |
---|
| 7693 | + return BCME_OK; |
---|
| 7694 | + } |
---|
| 7695 | + |
---|
| 7696 | + ifp_new = dhdinfo->iflist[ifidx]; |
---|
| 7697 | + if (ifp_new && (ifp_new != ifp)) { |
---|
| 7698 | + /* There should be only one entry for a given ifidx. */ |
---|
| 7699 | + DHD_ERROR(("ifp ptr already present for ifidx:%d\n", ifidx)); |
---|
| 7700 | + ASSERT(0); |
---|
| 7701 | + dhdp->hang_reason = HANG_REASON_IFACE_ADD_FAILURE; |
---|
| 7702 | + net_os_send_hang_message(ifp->net); |
---|
| 7703 | + return -EINVAL; |
---|
| 7704 | + } |
---|
| 7705 | + |
---|
| 7706 | + /* For static if delete case, cleanup the if before ifidx update */ |
---|
| 7707 | + if ((if_state == NDEV_STATE_FW_IF_DELETED) || |
---|
| 7708 | + (if_state == NDEV_STATE_FW_IF_FAILED)) { |
---|
| 7709 | + dhd_cleanup_if(ifp->net); |
---|
| 7710 | + dev_priv = DHD_DEV_PRIV(ndev); |
---|
| 7711 | + dev_priv->ifidx = ifidx; |
---|
| 7712 | + } |
---|
| 7713 | + |
---|
| 7714 | + /* update the iflist ifidx slot with cached info */ |
---|
| 7715 | + dhdinfo->iflist[ifidx] = ifp; |
---|
| 7716 | + dhdinfo->iflist[cur_idx] = NULL; |
---|
| 7717 | + |
---|
| 7718 | + /* update the values */ |
---|
| 7719 | + ifp->idx = ifidx; |
---|
| 7720 | + ifp->bssidx = bssidx; |
---|
| 7721 | + |
---|
| 7722 | + if (if_state == NDEV_STATE_FW_IF_CREATED) { |
---|
| 7723 | + dhd_dev_priv_save(ndev, dhdinfo, ifp, ifidx); |
---|
| 7724 | + /* initialize the dongle provided if name */ |
---|
| 7725 | + if (dngl_name) { |
---|
| 7726 | + strlcpy(ifp->dngl_name, dngl_name, IFNAMSIZ); |
---|
| 7727 | + } else if (ndev->name[0] != '\0') { |
---|
| 7728 | + strlcpy(ifp->dngl_name, ndev->name, IFNAMSIZ); |
---|
| 7729 | + } |
---|
| 7730 | + if (mac != NULL) { |
---|
| 7731 | + (void)memcpy_s(&ifp->mac_addr, ETHER_ADDR_LEN, mac, ETHER_ADDR_LEN); |
---|
| 7732 | + } |
---|
| 7733 | + } |
---|
| 7734 | + DHD_INFO(("[STATIC_IF] ifp ptr updated for ifidx:%d curidx:%d if_state:%d\n", |
---|
| 7735 | + ifidx, cur_idx, if_state)); |
---|
| 7736 | + return BCME_OK; |
---|
| 7737 | +} |
---|
| 7738 | +#endif /* WL_STATIC_IF */ |
---|
6751 | 7739 | |
---|
6752 | 7740 | /* unregister and free the existing net_device interface (if any) in iflist and |
---|
6753 | 7741 | * allocate a new one. the slot is reused. this function does NOT register the |
---|
6754 | 7742 | * new interface to linux kernel. dhd_register_if does the job |
---|
6755 | 7743 | */ |
---|
6756 | 7744 | struct net_device* |
---|
6757 | | -dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, char *name, |
---|
6758 | | - uint8 *mac, uint8 bssidx, bool need_rtnl_lock, char *dngl_name) |
---|
| 7745 | +dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, const char *name, |
---|
| 7746 | + uint8 *mac, uint8 bssidx, bool need_rtnl_lock, const char *dngl_name) |
---|
6759 | 7747 | { |
---|
6760 | 7748 | dhd_info_t *dhdinfo = (dhd_info_t *)dhdpub->info; |
---|
6761 | 7749 | dhd_if_t *ifp; |
---|
6762 | 7750 | |
---|
6763 | | - ASSERT(dhdinfo && (ifidx < DHD_MAX_IFS)); |
---|
| 7751 | + ASSERT(dhdinfo && (ifidx < (DHD_MAX_IFS + DHD_MAX_STATIC_IFS))); |
---|
| 7752 | + |
---|
6764 | 7753 | ifp = dhdinfo->iflist[ifidx]; |
---|
6765 | 7754 | |
---|
6766 | 7755 | if (ifp != NULL) { |
---|
6767 | 7756 | if (ifp->net != NULL) { |
---|
6768 | | - DHD_ERROR(("%s: free existing IF %s\n", __FUNCTION__, ifp->net->name)); |
---|
| 7757 | + DHD_ERROR(("%s: free existing IF %s ifidx:%d \n", |
---|
| 7758 | + __FUNCTION__, ifp->net->name, ifidx)); |
---|
| 7759 | + |
---|
| 7760 | + if (ifidx == 0) { |
---|
| 7761 | + /* For primary ifidx (0), there shouldn't be |
---|
| 7762 | + * any netdev present already. |
---|
| 7763 | + */ |
---|
| 7764 | + DHD_ERROR(("Primary ifidx populated already\n")); |
---|
| 7765 | + ASSERT(0); |
---|
| 7766 | + return NULL; |
---|
| 7767 | + } |
---|
6769 | 7768 | |
---|
6770 | 7769 | dhd_dev_priv_clear(ifp->net); /* clear net_device private */ |
---|
6771 | 7770 | |
---|
.. | .. |
---|
6797 | 7796 | ifp->bssidx = bssidx; |
---|
6798 | 7797 | #ifdef DHD_MCAST_REGEN |
---|
6799 | 7798 | ifp->mcast_regen_bss_enable = FALSE; |
---|
6800 | | -#endif |
---|
| 7799 | +#endif // endif |
---|
6801 | 7800 | /* set to TRUE rx_pkt_chainable at alloc time */ |
---|
6802 | 7801 | ifp->rx_pkt_chainable = TRUE; |
---|
6803 | 7802 | |
---|
.. | .. |
---|
6819 | 7818 | ifp->net->name[IFNAMSIZ - 1] = '\0'; |
---|
6820 | 7819 | } |
---|
6821 | 7820 | |
---|
| 7821 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 9)) |
---|
| 7822 | +#define IFP_NET_DESTRUCTOR ifp->net->priv_destructor |
---|
| 7823 | +#else |
---|
| 7824 | +#define IFP_NET_DESTRUCTOR ifp->net->destructor |
---|
| 7825 | +#endif // endif |
---|
| 7826 | + |
---|
6822 | 7827 | #ifdef WL_CFG80211 |
---|
6823 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) |
---|
6824 | 7828 | if (ifidx == 0) { |
---|
6825 | | - ifp->net->priv_destructor = free_netdev; |
---|
| 7829 | + IFP_NET_DESTRUCTOR = free_netdev; |
---|
6826 | 7830 | } else { |
---|
6827 | | - ifp->net->priv_destructor = dhd_netdev_free; |
---|
| 7831 | + IFP_NET_DESTRUCTOR = dhd_netdev_free; |
---|
6828 | 7832 | } |
---|
6829 | 7833 | #else |
---|
6830 | | - if (ifidx == 0) |
---|
6831 | | - ifp->net->destructor = free_netdev; |
---|
6832 | | - else |
---|
6833 | | - ifp->net->destructor = dhd_netdev_free; |
---|
6834 | | -#endif |
---|
6835 | | -#else |
---|
6836 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) |
---|
6837 | | - ifp->net->priv_destructor = free_netdev; |
---|
6838 | | -#else |
---|
6839 | | - ifp->net->destructor = free_netdev; |
---|
6840 | | -#endif |
---|
| 7834 | + IFP_NET_DESTRUCTOR = free_netdev; |
---|
6841 | 7835 | #endif /* WL_CFG80211 */ |
---|
6842 | 7836 | strncpy(ifp->name, ifp->net->name, IFNAMSIZ); |
---|
6843 | 7837 | ifp->name[IFNAMSIZ - 1] = '\0'; |
---|
6844 | 7838 | dhdinfo->iflist[ifidx] = ifp; |
---|
6845 | 7839 | |
---|
6846 | | -/* initialize the dongle provided if name */ |
---|
6847 | | - if (dngl_name) |
---|
| 7840 | + /* initialize the dongle provided if name */ |
---|
| 7841 | + if (dngl_name) { |
---|
6848 | 7842 | strncpy(ifp->dngl_name, dngl_name, IFNAMSIZ); |
---|
6849 | | - else |
---|
| 7843 | + } else if (name) { |
---|
6850 | 7844 | strncpy(ifp->dngl_name, name, IFNAMSIZ); |
---|
| 7845 | + } |
---|
6851 | 7846 | |
---|
6852 | | -#ifdef PCIE_FULL_DONGLE |
---|
6853 | 7847 | /* Initialize STA info list */ |
---|
6854 | 7848 | INIT_LIST_HEAD(&ifp->sta_list); |
---|
6855 | 7849 | DHD_IF_STA_LIST_LOCK_INIT(ifp); |
---|
6856 | | -#endif /* PCIE_FULL_DONGLE */ |
---|
6857 | 7850 | |
---|
6858 | 7851 | #ifdef DHD_L2_FILTER |
---|
6859 | 7852 | ifp->phnd_arp_table = init_l2_filter_arp_table(dhdpub->osh); |
---|
6860 | 7853 | ifp->parp_allnode = TRUE; |
---|
6861 | 7854 | #endif /* DHD_L2_FILTER */ |
---|
6862 | 7855 | |
---|
6863 | | - |
---|
6864 | 7856 | DHD_CUMM_CTR_INIT(&ifp->cumm_ctr); |
---|
| 7857 | + |
---|
| 7858 | +#ifdef DHD_4WAYM4_FAIL_DISCONNECT |
---|
| 7859 | + INIT_DELAYED_WORK(&ifp->m4state_work, dhd_m4_state_handler); |
---|
| 7860 | +#endif /* DHD_4WAYM4_FAIL_DISCONNECT */ |
---|
| 7861 | + |
---|
| 7862 | +#ifdef DHD_POST_EAPOL_M1_AFTER_ROAM_EVT |
---|
| 7863 | + ifp->recv_reassoc_evt = FALSE; |
---|
| 7864 | + ifp->post_roam_evt = FALSE; |
---|
| 7865 | +#endif /* DHD_POST_EAPOL_M1_AFTER_ROAM_EVT */ |
---|
| 7866 | + |
---|
| 7867 | +#ifdef DHDTCPSYNC_FLOOD_BLK |
---|
| 7868 | + INIT_WORK(&ifp->blk_tsfl_work, dhd_blk_tsfl_handler); |
---|
| 7869 | + dhd_reset_tcpsync_info_by_ifp(ifp); |
---|
| 7870 | +#endif /* DHDTCPSYNC_FLOOD_BLK */ |
---|
6865 | 7871 | |
---|
6866 | 7872 | return ifp->net; |
---|
6867 | 7873 | |
---|
6868 | 7874 | fail: |
---|
6869 | | - |
---|
6870 | 7875 | if (ifp != NULL) { |
---|
6871 | 7876 | if (ifp->net != NULL) { |
---|
| 7877 | +#if defined(DHD_LB_RXP) && defined(PCIE_FULL_DONGLE) |
---|
| 7878 | + if (ifp->net == dhdinfo->rx_napi_netdev) { |
---|
| 7879 | + napi_disable(&dhdinfo->rx_napi_struct); |
---|
| 7880 | + netif_napi_del(&dhdinfo->rx_napi_struct); |
---|
| 7881 | + skb_queue_purge(&dhdinfo->rx_napi_queue); |
---|
| 7882 | + dhdinfo->rx_napi_netdev = NULL; |
---|
| 7883 | + } |
---|
| 7884 | +#endif /* DHD_LB_RXP && PCIE_FULL_DONGLE */ |
---|
6872 | 7885 | dhd_dev_priv_clear(ifp->net); |
---|
6873 | 7886 | free_netdev(ifp->net); |
---|
6874 | 7887 | ifp->net = NULL; |
---|
.. | .. |
---|
6881 | 7894 | return NULL; |
---|
6882 | 7895 | } |
---|
6883 | 7896 | |
---|
| 7897 | +static void |
---|
| 7898 | +dhd_cleanup_ifp(dhd_pub_t *dhdp, dhd_if_t *ifp) |
---|
| 7899 | +{ |
---|
| 7900 | +#ifdef PCIE_FULL_DONGLE |
---|
| 7901 | + s32 ifidx = 0; |
---|
| 7902 | + if_flow_lkup_t *if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; |
---|
| 7903 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 7904 | + |
---|
| 7905 | + if (ifp != NULL) { |
---|
| 7906 | + if ((ifp->idx < 0) || (ifp->idx >= DHD_MAX_IFS)) { |
---|
| 7907 | + DHD_ERROR(("Wrong idx:%d \n", ifp->idx)); |
---|
| 7908 | + ASSERT(0); |
---|
| 7909 | + return; |
---|
| 7910 | + } |
---|
| 7911 | +#ifdef DHD_L2_FILTER |
---|
| 7912 | + bcm_l2_filter_arp_table_update(dhdpub->osh, ifp->phnd_arp_table, TRUE, |
---|
| 7913 | + NULL, FALSE, dhdpub->tickcnt); |
---|
| 7914 | + deinit_l2_filter_arp_table(dhdpub->osh, ifp->phnd_arp_table); |
---|
| 7915 | + ifp->phnd_arp_table = NULL; |
---|
| 7916 | +#endif /* DHD_L2_FILTER */ |
---|
| 7917 | + |
---|
| 7918 | + dhd_if_del_sta_list(ifp); |
---|
| 7919 | +#ifdef PCIE_FULL_DONGLE |
---|
| 7920 | + /* Delete flowrings of virtual interface */ |
---|
| 7921 | + ifidx = ifp->idx; |
---|
| 7922 | + if ((ifidx != 0) && (if_flow_lkup[ifidx].role != WLC_E_IF_ROLE_AP)) { |
---|
| 7923 | + dhd_flow_rings_delete(dhdp, ifidx); |
---|
| 7924 | + } |
---|
| 7925 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 7926 | + } |
---|
| 7927 | +} |
---|
| 7928 | + |
---|
| 7929 | +void |
---|
| 7930 | +dhd_cleanup_if(struct net_device *net) |
---|
| 7931 | +{ |
---|
| 7932 | + dhd_info_t *dhdinfo = DHD_DEV_INFO(net); |
---|
| 7933 | + dhd_pub_t *dhdp = &dhdinfo->pub; |
---|
| 7934 | + dhd_if_t *ifp; |
---|
| 7935 | + |
---|
| 7936 | + if (!(ifp = dhd_get_ifp_by_ndev(dhdp, net)) || |
---|
| 7937 | + (ifp->idx >= DHD_MAX_IFS)) { |
---|
| 7938 | + DHD_ERROR(("Wrong ifidx: %p, %d\n", ifp, ifp ? ifp->idx : -1)); |
---|
| 7939 | + ASSERT(0); |
---|
| 7940 | + return; |
---|
| 7941 | + } |
---|
| 7942 | + |
---|
| 7943 | + dhd_cleanup_ifp(dhdp, ifp); |
---|
| 7944 | +} |
---|
| 7945 | + |
---|
6884 | 7946 | /* unregister and free the the net_device interface associated with the indexed |
---|
6885 | 7947 | * slot, also free the slot memory and set the slot pointer to NULL |
---|
6886 | 7948 | */ |
---|
| 7949 | +#define DHD_TX_COMPLETION_TIMEOUT 5000 |
---|
6887 | 7950 | int |
---|
6888 | 7951 | dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock) |
---|
6889 | 7952 | { |
---|
6890 | 7953 | dhd_info_t *dhdinfo = (dhd_info_t *)dhdpub->info; |
---|
6891 | 7954 | dhd_if_t *ifp; |
---|
6892 | | -#ifdef PCIE_FULL_DONGLE |
---|
6893 | | - if_flow_lkup_t *if_flow_lkup = (if_flow_lkup_t *)dhdpub->if_flow_lkup; |
---|
6894 | | -#endif /* PCIE_FULL_DONGLE */ |
---|
| 7955 | + unsigned long flags; |
---|
| 7956 | + long timeout; |
---|
6895 | 7957 | |
---|
6896 | 7958 | ifp = dhdinfo->iflist[ifidx]; |
---|
6897 | 7959 | |
---|
6898 | 7960 | if (ifp != NULL) { |
---|
| 7961 | +#ifdef DHD_4WAYM4_FAIL_DISCONNECT |
---|
| 7962 | + cancel_delayed_work_sync(&ifp->m4state_work); |
---|
| 7963 | +#endif /* DHD_4WAYM4_FAIL_DISCONNECT */ |
---|
| 7964 | + |
---|
| 7965 | +#ifdef DHDTCPSYNC_FLOOD_BLK |
---|
| 7966 | + cancel_work_sync(&ifp->blk_tsfl_work); |
---|
| 7967 | +#endif /* DHDTCPSYNC_FLOOD_BLK */ |
---|
| 7968 | + |
---|
| 7969 | +#ifdef WL_STATIC_IF |
---|
| 7970 | + /* static IF will be handled in detach */ |
---|
| 7971 | + if (ifp->static_if) { |
---|
| 7972 | + DHD_TRACE(("Skip del iface for static interface\n")); |
---|
| 7973 | + return BCME_OK; |
---|
| 7974 | + } |
---|
| 7975 | +#endif /* WL_STATIC_IF */ |
---|
6899 | 7976 | if (ifp->net != NULL) { |
---|
6900 | 7977 | DHD_ERROR(("deleting interface '%s' idx %d\n", ifp->net->name, ifp->idx)); |
---|
6901 | 7978 | |
---|
| 7979 | + DHD_GENERAL_LOCK(dhdpub, flags); |
---|
| 7980 | + ifp->del_in_progress = true; |
---|
| 7981 | + DHD_GENERAL_UNLOCK(dhdpub, flags); |
---|
| 7982 | + |
---|
| 7983 | + /* If TX is in progress, hold the if del */ |
---|
| 7984 | + if (DHD_IF_IS_TX_ACTIVE(ifp)) { |
---|
| 7985 | + DHD_INFO(("TX in progress. Wait for it to be complete.")); |
---|
| 7986 | + timeout = wait_event_timeout(dhdpub->tx_completion_wait, |
---|
| 7987 | + ((ifp->tx_paths_active & DHD_TX_CONTEXT_MASK) == 0), |
---|
| 7988 | + msecs_to_jiffies(DHD_TX_COMPLETION_TIMEOUT)); |
---|
| 7989 | + if (!timeout) { |
---|
| 7990 | + /* Tx completion timeout. Attempt proceeding ahead */ |
---|
| 7991 | + DHD_ERROR(("Tx completion timed out!\n")); |
---|
| 7992 | + ASSERT(0); |
---|
| 7993 | + } |
---|
| 7994 | + } else { |
---|
| 7995 | + DHD_TRACE(("No outstanding TX!\n")); |
---|
| 7996 | + } |
---|
| 7997 | + dhdinfo->iflist[ifidx] = NULL; |
---|
6902 | 7998 | /* in unregister_netdev case, the interface gets freed by net->destructor |
---|
6903 | 7999 | * (which is set to free_netdev) |
---|
6904 | 8000 | */ |
---|
.. | .. |
---|
6907 | 8003 | } else { |
---|
6908 | 8004 | netif_tx_disable(ifp->net); |
---|
6909 | 8005 | |
---|
6910 | | - |
---|
6911 | | - |
---|
6912 | 8006 | #if defined(SET_RPS_CPUS) |
---|
6913 | 8007 | custom_rps_map_clear(ifp->net->_rx); |
---|
6914 | 8008 | #endif /* SET_RPS_CPUS */ |
---|
.. | .. |
---|
6916 | 8010 | #if (defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE)) |
---|
6917 | 8011 | dhd_tcpack_suppress_set(dhdpub, TCPACK_SUP_OFF); |
---|
6918 | 8012 | #endif /* DHDTCPACK_SUPPRESS && BCMPCIE */ |
---|
6919 | | -#endif |
---|
| 8013 | +#endif // endif |
---|
6920 | 8014 | if (need_rtnl_lock) |
---|
6921 | 8015 | unregister_netdev(ifp->net); |
---|
6922 | 8016 | else |
---|
6923 | 8017 | unregister_netdevice(ifp->net); |
---|
6924 | 8018 | } |
---|
6925 | 8019 | ifp->net = NULL; |
---|
| 8020 | + DHD_GENERAL_LOCK(dhdpub, flags); |
---|
| 8021 | + ifp->del_in_progress = false; |
---|
| 8022 | + DHD_GENERAL_UNLOCK(dhdpub, flags); |
---|
6926 | 8023 | } |
---|
6927 | | -#ifdef DHD_WMF |
---|
6928 | | - dhd_wmf_cleanup(dhdpub, ifidx); |
---|
6929 | | -#endif /* DHD_WMF */ |
---|
6930 | | -#ifdef DHD_L2_FILTER |
---|
6931 | | - bcm_l2_filter_arp_table_update(dhdpub->osh, ifp->phnd_arp_table, TRUE, |
---|
6932 | | - NULL, FALSE, dhdpub->tickcnt); |
---|
6933 | | - deinit_l2_filter_arp_table(dhdpub->osh, ifp->phnd_arp_table); |
---|
6934 | | - ifp->phnd_arp_table = NULL; |
---|
6935 | | -#endif /* DHD_L2_FILTER */ |
---|
6936 | | - |
---|
6937 | | - |
---|
6938 | | - dhd_if_del_sta_list(ifp); |
---|
6939 | | -#ifdef PCIE_FULL_DONGLE |
---|
6940 | | - /* Delete flowrings of WDS interface */ |
---|
6941 | | - if (if_flow_lkup[ifidx].role == WLC_E_IF_ROLE_WDS) { |
---|
6942 | | - dhd_flow_rings_delete(dhdpub, ifidx); |
---|
6943 | | - } |
---|
6944 | | -#endif /* PCIE_FULL_DONGLE */ |
---|
| 8024 | + dhd_cleanup_ifp(dhdpub, ifp); |
---|
6945 | 8025 | DHD_CUMM_CTR_INIT(&ifp->cumm_ctr); |
---|
6946 | 8026 | |
---|
6947 | | - dhdinfo->iflist[ifidx] = NULL; |
---|
6948 | 8027 | MFREE(dhdinfo->pub.osh, ifp, sizeof(*ifp)); |
---|
6949 | | - |
---|
| 8028 | + ifp = NULL; |
---|
6950 | 8029 | } |
---|
6951 | 8030 | |
---|
6952 | 8031 | return BCME_OK; |
---|
6953 | 8032 | } |
---|
6954 | 8033 | |
---|
6955 | | - |
---|
6956 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) |
---|
6957 | 8034 | static struct net_device_ops dhd_ops_pri = { |
---|
6958 | | - .ndo_open = dhd_open, |
---|
6959 | | - .ndo_stop = dhd_stop, |
---|
| 8035 | + .ndo_open = dhd_pri_open, |
---|
| 8036 | + .ndo_stop = dhd_pri_stop, |
---|
6960 | 8037 | .ndo_get_stats = dhd_get_stats, |
---|
| 8038 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 8039 | + .ndo_do_ioctl = dhd_ioctl_entry_wrapper, |
---|
| 8040 | + .ndo_start_xmit = dhd_start_xmit_wrapper, |
---|
| 8041 | +#else |
---|
6961 | 8042 | .ndo_do_ioctl = dhd_ioctl_entry, |
---|
6962 | 8043 | .ndo_start_xmit = dhd_start_xmit, |
---|
| 8044 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
6963 | 8045 | .ndo_set_mac_address = dhd_set_mac_address, |
---|
6964 | 8046 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) |
---|
6965 | 8047 | .ndo_set_rx_mode = dhd_set_multicast_list, |
---|
6966 | 8048 | #else |
---|
6967 | 8049 | .ndo_set_multicast_list = dhd_set_multicast_list, |
---|
6968 | | -#endif |
---|
| 8050 | +#endif // endif |
---|
6969 | 8051 | }; |
---|
6970 | 8052 | |
---|
6971 | 8053 | static struct net_device_ops dhd_ops_virt = { |
---|
| 8054 | +#if defined(WL_CFG80211) && defined(WL_STATIC_IF) |
---|
| 8055 | + .ndo_open = dhd_static_if_open, |
---|
| 8056 | + .ndo_stop = dhd_static_if_stop, |
---|
| 8057 | +#endif // endif |
---|
6972 | 8058 | .ndo_get_stats = dhd_get_stats, |
---|
| 8059 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 8060 | + .ndo_do_ioctl = dhd_ioctl_entry_wrapper, |
---|
| 8061 | + .ndo_start_xmit = dhd_start_xmit_wrapper, |
---|
| 8062 | +#else |
---|
6973 | 8063 | .ndo_do_ioctl = dhd_ioctl_entry, |
---|
6974 | 8064 | .ndo_start_xmit = dhd_start_xmit, |
---|
| 8065 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
6975 | 8066 | .ndo_set_mac_address = dhd_set_mac_address, |
---|
6976 | 8067 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) |
---|
6977 | 8068 | .ndo_set_rx_mode = dhd_set_multicast_list, |
---|
6978 | 8069 | #else |
---|
6979 | 8070 | .ndo_set_multicast_list = dhd_set_multicast_list, |
---|
6980 | | -#endif |
---|
| 8071 | +#endif // endif |
---|
6981 | 8072 | }; |
---|
6982 | | -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) */ |
---|
6983 | 8073 | |
---|
6984 | | -#ifdef DEBUGGER |
---|
6985 | | -extern void debugger_init(void *bus_handle); |
---|
6986 | | -#endif |
---|
| 8074 | +int |
---|
| 8075 | +dhd_os_write_file_posn(void *fp, unsigned long *posn, void *buf, |
---|
| 8076 | + unsigned long buflen) |
---|
| 8077 | +{ |
---|
| 8078 | + loff_t wr_posn = *posn; |
---|
6987 | 8079 | |
---|
| 8080 | + if (!fp || !buf || buflen == 0) |
---|
| 8081 | + return -1; |
---|
| 8082 | + |
---|
| 8083 | + if (vfs_write((struct file *)fp, buf, buflen, &wr_posn) < 0) |
---|
| 8084 | + return -1; |
---|
| 8085 | + |
---|
| 8086 | + *posn = wr_posn; |
---|
| 8087 | + return 0; |
---|
| 8088 | +} |
---|
6988 | 8089 | |
---|
6989 | 8090 | #ifdef SHOW_LOGTRACE |
---|
6990 | | -static char *logstrs_path = "/root/logstrs.bin"; |
---|
6991 | | -static char *st_str_file_path = "/root/rtecdc.bin"; |
---|
6992 | | -static char *map_file_path = "/root/rtecdc.map"; |
---|
6993 | | -static char *rom_st_str_file_path = "/root/roml.bin"; |
---|
6994 | | -static char *rom_map_file_path = "/root/roml.map"; |
---|
| 8091 | +int |
---|
| 8092 | +dhd_os_read_file(void *file, char *buf, uint32 size) |
---|
| 8093 | +{ |
---|
| 8094 | + struct file *filep = (struct file *)file; |
---|
6995 | 8095 | |
---|
6996 | | -#define BYTES_AHEAD_NUM 11 /* address in map file is before these many bytes */ |
---|
6997 | | -#define READ_NUM_BYTES 1000 /* read map file each time this No. of bytes */ |
---|
6998 | | -#define GO_BACK_FILE_POS_NUM_BYTES 100 /* set file pos back to cur pos */ |
---|
6999 | | -static char *ramstart_str = "text_start"; /* string in mapfile has addr ramstart */ |
---|
7000 | | -static char *rodata_start_str = "rodata_start"; /* string in mapfile has addr rodata start */ |
---|
7001 | | -static char *rodata_end_str = "rodata_end"; /* string in mapfile has addr rodata end */ |
---|
7002 | | -static char *ram_file_str = "rtecdc"; |
---|
7003 | | -static char *rom_file_str = "roml"; |
---|
7004 | | -#define RAMSTART_BIT 0x01 |
---|
7005 | | -#define RDSTART_BIT 0x02 |
---|
7006 | | -#define RDEND_BIT 0x04 |
---|
7007 | | -#define ALL_MAP_VAL (RAMSTART_BIT | RDSTART_BIT | RDEND_BIT) |
---|
| 8096 | + if (!file || !buf) |
---|
| 8097 | + return -1; |
---|
7008 | 8098 | |
---|
7009 | | -module_param(logstrs_path, charp, S_IRUGO); |
---|
7010 | | -module_param(st_str_file_path, charp, S_IRUGO); |
---|
7011 | | -module_param(map_file_path, charp, S_IRUGO); |
---|
7012 | | -module_param(rom_st_str_file_path, charp, S_IRUGO); |
---|
7013 | | -module_param(rom_map_file_path, charp, S_IRUGO); |
---|
| 8099 | + return vfs_read(filep, buf, size, &filep->f_pos); |
---|
| 8100 | +} |
---|
7014 | 8101 | |
---|
7015 | | -static void |
---|
7016 | | -dhd_init_logstrs_array(dhd_event_log_t *temp) |
---|
| 8102 | +int |
---|
| 8103 | +dhd_os_seek_file(void *file, int64 offset) |
---|
| 8104 | +{ |
---|
| 8105 | + struct file *filep = (struct file *)file; |
---|
| 8106 | + if (!file) |
---|
| 8107 | + return -1; |
---|
| 8108 | + |
---|
| 8109 | + /* offset can be -ve */ |
---|
| 8110 | + filep->f_pos = filep->f_pos + offset; |
---|
| 8111 | + |
---|
| 8112 | + return 0; |
---|
| 8113 | +} |
---|
| 8114 | + |
---|
| 8115 | +static int |
---|
| 8116 | +dhd_init_logstrs_array(osl_t *osh, dhd_event_log_t *temp) |
---|
7017 | 8117 | { |
---|
7018 | 8118 | struct file *filep = NULL; |
---|
| 8119 | +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)) |
---|
7019 | 8120 | struct kstat stat; |
---|
| 8121 | + int error = 0; |
---|
| 8122 | +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) */ |
---|
| 8123 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
7020 | 8124 | mm_segment_t fs; |
---|
| 8125 | +#endif /* KERNEL_DS && USER_DS */ |
---|
7021 | 8126 | char *raw_fmts = NULL; |
---|
7022 | 8127 | int logstrs_size = 0; |
---|
7023 | 8128 | |
---|
7024 | | - logstr_header_t *hdr = NULL; |
---|
7025 | | - uint32 *lognums = NULL; |
---|
7026 | | - char *logstrs = NULL; |
---|
7027 | | - int ram_index = 0; |
---|
7028 | | - char **fmts; |
---|
7029 | | - int num_fmts = 0; |
---|
7030 | | - uint32 i = 0; |
---|
7031 | | - int error = 0; |
---|
7032 | | - |
---|
| 8129 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
7033 | 8130 | fs = get_fs(); |
---|
7034 | 8131 | set_fs(KERNEL_DS); |
---|
| 8132 | +#endif /* KERNEL_DS && USER_DS */ |
---|
7035 | 8133 | |
---|
7036 | 8134 | filep = filp_open(logstrs_path, O_RDONLY, 0); |
---|
7037 | 8135 | |
---|
7038 | 8136 | if (IS_ERR(filep)) { |
---|
7039 | | - DHD_ERROR(("%s: Failed to open the file %s \n", __FUNCTION__, logstrs_path)); |
---|
| 8137 | + DHD_ERROR_NO_HW4(("%s: Failed to open the file %s \n", __FUNCTION__, logstrs_path)); |
---|
7040 | 8138 | goto fail; |
---|
7041 | 8139 | } |
---|
| 8140 | +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)) |
---|
7042 | 8141 | error = vfs_stat(logstrs_path, &stat); |
---|
7043 | 8142 | if (error) { |
---|
7044 | | - DHD_ERROR(("%s: Failed to stat file %s \n", __FUNCTION__, logstrs_path)); |
---|
| 8143 | + DHD_ERROR_NO_HW4(("%s: Failed to stat file %s \n", __FUNCTION__, logstrs_path)); |
---|
7045 | 8144 | goto fail; |
---|
7046 | 8145 | } |
---|
7047 | 8146 | logstrs_size = (int) stat.size; |
---|
| 8147 | +#else |
---|
| 8148 | + logstrs_size = i_size_read(file_inode(filep)); |
---|
| 8149 | +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) */ |
---|
| 8150 | + if (logstrs_size == 0) { |
---|
| 8151 | + DHD_ERROR(("%s: return as logstrs_size is 0\n", __FUNCTION__)); |
---|
| 8152 | + goto fail1; |
---|
| 8153 | + } |
---|
7048 | 8154 | |
---|
7049 | | - raw_fmts = kmalloc(logstrs_size, GFP_KERNEL); |
---|
| 8155 | + raw_fmts = MALLOC(osh, logstrs_size); |
---|
7050 | 8156 | if (raw_fmts == NULL) { |
---|
7051 | 8157 | DHD_ERROR(("%s: Failed to allocate memory \n", __FUNCTION__)); |
---|
7052 | 8158 | goto fail; |
---|
7053 | 8159 | } |
---|
| 8160 | + |
---|
7054 | 8161 | if (vfs_read(filep, raw_fmts, logstrs_size, &filep->f_pos) != logstrs_size) { |
---|
7055 | | - DHD_ERROR(("%s: Failed to read file %s", __FUNCTION__, logstrs_path)); |
---|
| 8162 | + DHD_ERROR_NO_HW4(("%s: Failed to read file %s\n", __FUNCTION__, logstrs_path)); |
---|
7056 | 8163 | goto fail; |
---|
7057 | 8164 | } |
---|
7058 | 8165 | |
---|
7059 | | - /* Remember header from the logstrs.bin file */ |
---|
7060 | | - hdr = (logstr_header_t *) (raw_fmts + logstrs_size - |
---|
7061 | | - sizeof(logstr_header_t)); |
---|
7062 | | - |
---|
7063 | | - if (hdr->log_magic == LOGSTRS_MAGIC) { |
---|
7064 | | - /* |
---|
7065 | | - * logstrs.bin start with header. |
---|
7066 | | - */ |
---|
7067 | | - num_fmts = hdr->rom_logstrs_offset / sizeof(uint32); |
---|
7068 | | - ram_index = (hdr->ram_lognums_offset - |
---|
7069 | | - hdr->rom_lognums_offset) / sizeof(uint32); |
---|
7070 | | - lognums = (uint32 *) &raw_fmts[hdr->rom_lognums_offset]; |
---|
7071 | | - logstrs = (char *) &raw_fmts[hdr->rom_logstrs_offset]; |
---|
7072 | | - } else { |
---|
7073 | | - /* |
---|
7074 | | - * Legacy logstrs.bin format without header. |
---|
7075 | | - */ |
---|
7076 | | - num_fmts = *((uint32 *) (raw_fmts)) / sizeof(uint32); |
---|
7077 | | - if (num_fmts == 0) { |
---|
7078 | | - /* Legacy ROM/RAM logstrs.bin format: |
---|
7079 | | - * - ROM 'lognums' section |
---|
7080 | | - * - RAM 'lognums' section |
---|
7081 | | - * - ROM 'logstrs' section. |
---|
7082 | | - * - RAM 'logstrs' section. |
---|
7083 | | - * |
---|
7084 | | - * 'lognums' is an array of indexes for the strings in the |
---|
7085 | | - * 'logstrs' section. The first uint32 is 0 (index of first |
---|
7086 | | - * string in ROM 'logstrs' section). |
---|
7087 | | - * |
---|
7088 | | - * The 4324b5 is the only ROM that uses this legacy format. Use the |
---|
7089 | | - * fixed number of ROM fmtnums to find the start of the RAM |
---|
7090 | | - * 'lognums' section. Use the fixed first ROM string ("Con\n") to |
---|
7091 | | - * find the ROM 'logstrs' section. |
---|
7092 | | - */ |
---|
7093 | | - #define NUM_4324B5_ROM_FMTS 186 |
---|
7094 | | - #define FIRST_4324B5_ROM_LOGSTR "Con\n" |
---|
7095 | | - ram_index = NUM_4324B5_ROM_FMTS; |
---|
7096 | | - lognums = (uint32 *) raw_fmts; |
---|
7097 | | - num_fmts = ram_index; |
---|
7098 | | - logstrs = (char *) &raw_fmts[num_fmts << 2]; |
---|
7099 | | - while (strncmp(FIRST_4324B5_ROM_LOGSTR, logstrs, 4)) { |
---|
7100 | | - num_fmts++; |
---|
7101 | | - logstrs = (char *) &raw_fmts[num_fmts << 2]; |
---|
7102 | | - } |
---|
7103 | | - } else { |
---|
7104 | | - /* Legacy RAM-only logstrs.bin format: |
---|
7105 | | - * - RAM 'lognums' section |
---|
7106 | | - * - RAM 'logstrs' section. |
---|
7107 | | - * |
---|
7108 | | - * 'lognums' is an array of indexes for the strings in the |
---|
7109 | | - * 'logstrs' section. The first uint32 is an index to the |
---|
7110 | | - * start of 'logstrs'. Therefore, if this index is divided |
---|
7111 | | - * by 'sizeof(uint32)' it provides the number of logstr |
---|
7112 | | - * entries. |
---|
7113 | | - */ |
---|
7114 | | - ram_index = 0; |
---|
7115 | | - lognums = (uint32 *) raw_fmts; |
---|
7116 | | - logstrs = (char *) &raw_fmts[num_fmts << 2]; |
---|
7117 | | - } |
---|
7118 | | - } |
---|
7119 | | - fmts = kmalloc(num_fmts * sizeof(char *), GFP_KERNEL); |
---|
7120 | | - if (fmts == NULL) { |
---|
7121 | | - DHD_ERROR(("Failed to allocate fmts memory")); |
---|
7122 | | - goto fail; |
---|
| 8166 | + if (dhd_parse_logstrs_file(osh, raw_fmts, logstrs_size, temp) |
---|
| 8167 | + == BCME_OK) { |
---|
| 8168 | + filp_close(filep, NULL); |
---|
| 8169 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 8170 | + set_fs(fs); |
---|
| 8171 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 8172 | + return BCME_OK; |
---|
7123 | 8173 | } |
---|
7124 | 8174 | |
---|
7125 | | - for (i = 0; i < num_fmts; i++) { |
---|
7126 | | - /* ROM lognums index into logstrs using 'rom_logstrs_offset' as a base |
---|
7127 | | - * (they are 0-indexed relative to 'rom_logstrs_offset'). |
---|
7128 | | - * |
---|
7129 | | - * RAM lognums are already indexed to point to the correct RAM logstrs (they |
---|
7130 | | - * are 0-indexed relative to the start of the logstrs.bin file). |
---|
7131 | | - */ |
---|
7132 | | - if (i == ram_index) { |
---|
7133 | | - logstrs = raw_fmts; |
---|
7134 | | - } |
---|
7135 | | - fmts[i] = &logstrs[lognums[i]]; |
---|
7136 | | - } |
---|
7137 | | - temp->fmts = fmts; |
---|
7138 | | - temp->raw_fmts = raw_fmts; |
---|
7139 | | - temp->num_fmts = num_fmts; |
---|
7140 | | - filp_close(filep, NULL); |
---|
7141 | | - set_fs(fs); |
---|
7142 | | - return; |
---|
7143 | 8175 | fail: |
---|
7144 | 8176 | if (raw_fmts) { |
---|
7145 | | - kfree(raw_fmts); |
---|
| 8177 | + MFREE(osh, raw_fmts, logstrs_size); |
---|
7146 | 8178 | raw_fmts = NULL; |
---|
7147 | 8179 | } |
---|
| 8180 | + |
---|
| 8181 | +fail1: |
---|
7148 | 8182 | if (!IS_ERR(filep)) |
---|
7149 | 8183 | filp_close(filep, NULL); |
---|
| 8184 | + |
---|
| 8185 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
7150 | 8186 | set_fs(fs); |
---|
| 8187 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 8188 | + |
---|
7151 | 8189 | temp->fmts = NULL; |
---|
7152 | | - return; |
---|
| 8190 | + return BCME_ERROR; |
---|
7153 | 8191 | } |
---|
7154 | 8192 | |
---|
7155 | 8193 | static int |
---|
7156 | | -dhd_read_map(char *fname, uint32 *ramstart, uint32 *rodata_start, |
---|
7157 | | - uint32 *rodata_end) |
---|
| 8194 | +dhd_read_map(osl_t *osh, char *fname, uint32 *ramstart, uint32 *rodata_start, |
---|
| 8195 | + uint32 *rodata_end) |
---|
7158 | 8196 | { |
---|
7159 | 8197 | struct file *filep = NULL; |
---|
| 8198 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
7160 | 8199 | mm_segment_t fs; |
---|
7161 | | - char *raw_fmts = NULL; |
---|
7162 | | - uint32 read_size = READ_NUM_BYTES; |
---|
7163 | | - int error = 0; |
---|
7164 | | - char * cptr = NULL; |
---|
7165 | | - char c; |
---|
7166 | | - uint8 count = 0; |
---|
| 8200 | +#endif /* KERNEL_DS && USER_DS */ |
---|
7167 | 8201 | |
---|
7168 | | - *ramstart = 0; |
---|
7169 | | - *rodata_start = 0; |
---|
7170 | | - *rodata_end = 0; |
---|
| 8202 | + int err = BCME_ERROR; |
---|
7171 | 8203 | |
---|
7172 | 8204 | if (fname == NULL) { |
---|
7173 | 8205 | DHD_ERROR(("%s: ERROR fname is NULL \n", __FUNCTION__)); |
---|
7174 | 8206 | return BCME_ERROR; |
---|
7175 | 8207 | } |
---|
7176 | 8208 | |
---|
| 8209 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
7177 | 8210 | fs = get_fs(); |
---|
7178 | 8211 | set_fs(KERNEL_DS); |
---|
| 8212 | +#endif /* KERNEL_DS && USER_DS */ |
---|
7179 | 8213 | |
---|
7180 | 8214 | filep = filp_open(fname, O_RDONLY, 0); |
---|
7181 | 8215 | if (IS_ERR(filep)) { |
---|
7182 | | - DHD_ERROR(("%s: Failed to open %s \n", __FUNCTION__, fname)); |
---|
| 8216 | + DHD_ERROR_NO_HW4(("%s: Failed to open %s \n", __FUNCTION__, fname)); |
---|
7183 | 8217 | goto fail; |
---|
7184 | 8218 | } |
---|
7185 | 8219 | |
---|
7186 | | - /* Allocate 1 byte more than read_size to terminate it with NULL */ |
---|
7187 | | - raw_fmts = kmalloc(read_size + 1, GFP_KERNEL); |
---|
7188 | | - if (raw_fmts == NULL) { |
---|
7189 | | - DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n", __FUNCTION__)); |
---|
| 8220 | + if ((err = dhd_parse_map_file(osh, filep, ramstart, |
---|
| 8221 | + rodata_start, rodata_end)) < 0) |
---|
7190 | 8222 | goto fail; |
---|
7191 | | - } |
---|
7192 | | - |
---|
7193 | | - /* read ram start, rodata_start and rodata_end values from map file */ |
---|
7194 | | - |
---|
7195 | | - while (count != ALL_MAP_VAL) |
---|
7196 | | - { |
---|
7197 | | - error = vfs_read(filep, raw_fmts, read_size, (&filep->f_pos)); |
---|
7198 | | - if (error < 0) { |
---|
7199 | | - DHD_ERROR(("%s: read failed %s err:%d \n", __FUNCTION__, |
---|
7200 | | - map_file_path, error)); |
---|
7201 | | - goto fail; |
---|
7202 | | - } |
---|
7203 | | - |
---|
7204 | | - if (error < read_size) { |
---|
7205 | | - /* |
---|
7206 | | - * since we reset file pos back to earlier pos by |
---|
7207 | | - * GO_BACK_FILE_POS_NUM_BYTES bytes we won't reach EOF. |
---|
7208 | | - * So if ret value is less than read_size, reached EOF don't read further |
---|
7209 | | - */ |
---|
7210 | | - break; |
---|
7211 | | - } |
---|
7212 | | - /* End raw_fmts with NULL as strstr expects NULL terminated strings */ |
---|
7213 | | - raw_fmts[read_size] = '\0'; |
---|
7214 | | - |
---|
7215 | | - /* Get ramstart address */ |
---|
7216 | | - if ((cptr = strstr(raw_fmts, ramstart_str))) { |
---|
7217 | | - cptr = cptr - BYTES_AHEAD_NUM; |
---|
7218 | | - sscanf(cptr, "%x %c text_start", ramstart, &c); |
---|
7219 | | - count |= RAMSTART_BIT; |
---|
7220 | | - } |
---|
7221 | | - |
---|
7222 | | - /* Get ram rodata start address */ |
---|
7223 | | - if ((cptr = strstr(raw_fmts, rodata_start_str))) { |
---|
7224 | | - cptr = cptr - BYTES_AHEAD_NUM; |
---|
7225 | | - sscanf(cptr, "%x %c rodata_start", rodata_start, &c); |
---|
7226 | | - count |= RDSTART_BIT; |
---|
7227 | | - } |
---|
7228 | | - |
---|
7229 | | - /* Get ram rodata end address */ |
---|
7230 | | - if ((cptr = strstr(raw_fmts, rodata_end_str))) { |
---|
7231 | | - cptr = cptr - BYTES_AHEAD_NUM; |
---|
7232 | | - sscanf(cptr, "%x %c rodata_end", rodata_end, &c); |
---|
7233 | | - count |= RDEND_BIT; |
---|
7234 | | - } |
---|
7235 | | - memset(raw_fmts, 0, read_size); |
---|
7236 | | - /* |
---|
7237 | | - * go back to predefined NUM of bytes so that we won't miss |
---|
7238 | | - * the string and addr even if it comes as splited in next read. |
---|
7239 | | - */ |
---|
7240 | | - filep->f_pos = filep->f_pos - GO_BACK_FILE_POS_NUM_BYTES; |
---|
7241 | | - } |
---|
7242 | | - |
---|
7243 | | - DHD_ERROR(("---ramstart: 0x%x, rodata_start: 0x%x, rodata_end:0x%x\n", |
---|
7244 | | - *ramstart, *rodata_start, *rodata_end)); |
---|
7245 | | - |
---|
7246 | | - DHD_ERROR(("readmap over \n")); |
---|
7247 | 8223 | |
---|
7248 | 8224 | fail: |
---|
7249 | | - if (raw_fmts) { |
---|
7250 | | - kfree(raw_fmts); |
---|
7251 | | - raw_fmts = NULL; |
---|
7252 | | - } |
---|
7253 | 8225 | if (!IS_ERR(filep)) |
---|
7254 | 8226 | filp_close(filep, NULL); |
---|
7255 | 8227 | |
---|
| 8228 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
7256 | 8229 | set_fs(fs); |
---|
7257 | | - if (count == ALL_MAP_VAL) { |
---|
7258 | | - return BCME_OK; |
---|
7259 | | - } |
---|
7260 | | - DHD_ERROR(("readmap error 0X%x \n", count)); |
---|
7261 | | - return BCME_ERROR; |
---|
| 8230 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 8231 | + |
---|
| 8232 | + return err; |
---|
7262 | 8233 | } |
---|
7263 | 8234 | |
---|
7264 | | -static void |
---|
7265 | | -dhd_init_static_strs_array(dhd_event_log_t *temp, char *str_file, char *map_file) |
---|
| 8235 | +static int |
---|
| 8236 | +dhd_init_static_strs_array(osl_t *osh, dhd_event_log_t *temp, char *str_file, char *map_file) |
---|
7266 | 8237 | { |
---|
7267 | 8238 | struct file *filep = NULL; |
---|
| 8239 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
7268 | 8240 | mm_segment_t fs; |
---|
| 8241 | +#endif /* KERNEL_DS && USER_DS */ |
---|
7269 | 8242 | char *raw_fmts = NULL; |
---|
7270 | 8243 | uint32 logstrs_size = 0; |
---|
7271 | | - |
---|
7272 | 8244 | int error = 0; |
---|
7273 | 8245 | uint32 ramstart = 0; |
---|
7274 | 8246 | uint32 rodata_start = 0; |
---|
7275 | 8247 | uint32 rodata_end = 0; |
---|
7276 | 8248 | uint32 logfilebase = 0; |
---|
7277 | 8249 | |
---|
7278 | | - error = dhd_read_map(map_file, &ramstart, &rodata_start, &rodata_end); |
---|
7279 | | - if (error == BCME_ERROR) { |
---|
| 8250 | + error = dhd_read_map(osh, map_file, &ramstart, &rodata_start, &rodata_end); |
---|
| 8251 | + if (error != BCME_OK) { |
---|
7280 | 8252 | DHD_ERROR(("readmap Error!! \n")); |
---|
7281 | 8253 | /* don't do event log parsing in actual case */ |
---|
7282 | | - temp->raw_sstr = NULL; |
---|
7283 | | - return; |
---|
| 8254 | + if (strstr(str_file, ram_file_str) != NULL) { |
---|
| 8255 | + temp->raw_sstr = NULL; |
---|
| 8256 | + } else if (strstr(str_file, rom_file_str) != NULL) { |
---|
| 8257 | + temp->rom_raw_sstr = NULL; |
---|
| 8258 | + } |
---|
| 8259 | + return error; |
---|
7284 | 8260 | } |
---|
7285 | 8261 | DHD_ERROR(("ramstart: 0x%x, rodata_start: 0x%x, rodata_end:0x%x\n", |
---|
7286 | 8262 | ramstart, rodata_start, rodata_end)); |
---|
7287 | 8263 | |
---|
| 8264 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
7288 | 8265 | fs = get_fs(); |
---|
7289 | 8266 | set_fs(KERNEL_DS); |
---|
| 8267 | +#endif /* KERNEL_DS && USER_DS */ |
---|
7290 | 8268 | |
---|
7291 | 8269 | filep = filp_open(str_file, O_RDONLY, 0); |
---|
7292 | 8270 | if (IS_ERR(filep)) { |
---|
.. | .. |
---|
7294 | 8272 | goto fail; |
---|
7295 | 8273 | } |
---|
7296 | 8274 | |
---|
7297 | | - /* Full file size is huge. Just read required part */ |
---|
7298 | | - logstrs_size = rodata_end - rodata_start; |
---|
| 8275 | + if (TRUE) { |
---|
| 8276 | + /* Full file size is huge. Just read required part */ |
---|
| 8277 | + logstrs_size = rodata_end - rodata_start; |
---|
| 8278 | + logfilebase = rodata_start - ramstart; |
---|
| 8279 | + } |
---|
7299 | 8280 | |
---|
7300 | | - raw_fmts = kmalloc(logstrs_size, GFP_KERNEL); |
---|
| 8281 | + if (logstrs_size == 0) { |
---|
| 8282 | + DHD_ERROR(("%s: return as logstrs_size is 0\n", __FUNCTION__)); |
---|
| 8283 | + goto fail1; |
---|
| 8284 | + } |
---|
| 8285 | + |
---|
| 8286 | + raw_fmts = MALLOC(osh, logstrs_size); |
---|
7301 | 8287 | if (raw_fmts == NULL) { |
---|
7302 | 8288 | DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n", __FUNCTION__)); |
---|
7303 | 8289 | goto fail; |
---|
7304 | 8290 | } |
---|
7305 | 8291 | |
---|
7306 | | - logfilebase = rodata_start - ramstart; |
---|
7307 | | - |
---|
7308 | | - error = generic_file_llseek(filep, logfilebase, SEEK_SET); |
---|
7309 | | - if (error < 0) { |
---|
7310 | | - DHD_ERROR(("%s: %s llseek failed %d \n", __FUNCTION__, str_file, error)); |
---|
7311 | | - goto fail; |
---|
| 8292 | + if (TRUE) { |
---|
| 8293 | + error = generic_file_llseek(filep, logfilebase, SEEK_SET); |
---|
| 8294 | + if (error < 0) { |
---|
| 8295 | + DHD_ERROR(("%s: %s llseek failed %d \n", __FUNCTION__, str_file, error)); |
---|
| 8296 | + goto fail; |
---|
| 8297 | + } |
---|
7312 | 8298 | } |
---|
7313 | 8299 | |
---|
7314 | 8300 | error = vfs_read(filep, raw_fmts, logstrs_size, (&filep->f_pos)); |
---|
.. | .. |
---|
7319 | 8305 | |
---|
7320 | 8306 | if (strstr(str_file, ram_file_str) != NULL) { |
---|
7321 | 8307 | temp->raw_sstr = raw_fmts; |
---|
7322 | | - temp->ramstart = ramstart; |
---|
| 8308 | + temp->raw_sstr_size = logstrs_size; |
---|
7323 | 8309 | temp->rodata_start = rodata_start; |
---|
7324 | 8310 | temp->rodata_end = rodata_end; |
---|
7325 | 8311 | } else if (strstr(str_file, rom_file_str) != NULL) { |
---|
7326 | 8312 | temp->rom_raw_sstr = raw_fmts; |
---|
7327 | | - temp->rom_ramstart = ramstart; |
---|
| 8313 | + temp->rom_raw_sstr_size = logstrs_size; |
---|
7328 | 8314 | temp->rom_rodata_start = rodata_start; |
---|
7329 | 8315 | temp->rom_rodata_end = rodata_end; |
---|
7330 | 8316 | } |
---|
7331 | 8317 | |
---|
7332 | 8318 | filp_close(filep, NULL); |
---|
| 8319 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
7333 | 8320 | set_fs(fs); |
---|
| 8321 | +#endif /* KERNEL_DS && USER_DS */ |
---|
7334 | 8322 | |
---|
7335 | | - return; |
---|
| 8323 | + return BCME_OK; |
---|
| 8324 | + |
---|
7336 | 8325 | fail: |
---|
7337 | 8326 | if (raw_fmts) { |
---|
7338 | | - kfree(raw_fmts); |
---|
| 8327 | + MFREE(osh, raw_fmts, logstrs_size); |
---|
7339 | 8328 | raw_fmts = NULL; |
---|
7340 | 8329 | } |
---|
| 8330 | + |
---|
| 8331 | +fail1: |
---|
7341 | 8332 | if (!IS_ERR(filep)) |
---|
7342 | 8333 | filp_close(filep, NULL); |
---|
| 8334 | + |
---|
| 8335 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
7343 | 8336 | set_fs(fs); |
---|
| 8337 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 8338 | + |
---|
7344 | 8339 | if (strstr(str_file, ram_file_str) != NULL) { |
---|
7345 | 8340 | temp->raw_sstr = NULL; |
---|
7346 | 8341 | } else if (strstr(str_file, rom_file_str) != NULL) { |
---|
7347 | 8342 | temp->rom_raw_sstr = NULL; |
---|
7348 | 8343 | } |
---|
7349 | | - return; |
---|
7350 | | -} |
---|
| 8344 | + |
---|
| 8345 | + return error; |
---|
| 8346 | +} /* dhd_init_static_strs_array */ |
---|
7351 | 8347 | |
---|
7352 | 8348 | #endif /* SHOW_LOGTRACE */ |
---|
7353 | | -#ifdef DHD_LB |
---|
7354 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) |
---|
7355 | 8349 | |
---|
7356 | | -static enum cpuhp_state dhd_cpuhp_online_state; |
---|
| 8350 | +#ifdef DHD_ERPOM |
---|
| 8351 | +uint enable_erpom = 0; |
---|
| 8352 | +module_param(enable_erpom, int, 0); |
---|
7357 | 8353 | |
---|
7358 | | -static int |
---|
7359 | | -dhd_cpuhp_init(osl_t *osh, dhd_info_t *dhd) |
---|
| 8354 | +int |
---|
| 8355 | +dhd_wlan_power_off_handler(void *handler, unsigned char reason) |
---|
7360 | 8356 | { |
---|
7361 | | - int ret = 0; |
---|
| 8357 | + dhd_pub_t *dhdp = (dhd_pub_t *)handler; |
---|
| 8358 | + bool dongle_isolation = dhdp->dongle_isolation; |
---|
7362 | 8359 | |
---|
7363 | | - ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "net/wireless/dhd:online", |
---|
7364 | | - dhd_cpuhp_online, dhd_cpuhp_dead); |
---|
7365 | | - if (ret < 0) { |
---|
7366 | | - DHD_ERROR(("%s(): cpuhp_setup_state_multi() online failed, ret=%d\n", |
---|
7367 | | - __FUNCTION__, ret)); |
---|
7368 | | - return ret; |
---|
| 8360 | + DHD_ERROR(("%s: WLAN DHD cleanup reason: %d\n", __FUNCTION__, reason)); |
---|
| 8361 | + |
---|
| 8362 | + if ((reason == BY_BT_DUE_TO_BT) || (reason == BY_BT_DUE_TO_WLAN)) { |
---|
| 8363 | +#if defined(DHD_FW_COREDUMP) |
---|
| 8364 | + /* save core dump to a file */ |
---|
| 8365 | + if (dhdp->memdump_enabled) { |
---|
| 8366 | +#ifdef DHD_SSSR_DUMP |
---|
| 8367 | + dhdp->collect_sssr = TRUE; |
---|
| 8368 | +#endif /* DHD_SSSR_DUMP */ |
---|
| 8369 | + dhdp->memdump_type = DUMP_TYPE_DUE_TO_BT; |
---|
| 8370 | + dhd_bus_mem_dump(dhdp); |
---|
| 8371 | + } |
---|
| 8372 | +#endif /* DHD_FW_COREDUMP */ |
---|
7369 | 8373 | } |
---|
7370 | | - dhd_cpuhp_online_state = ret; |
---|
7371 | | - cpuhp_state_add_instance_nocalls(dhd_cpuhp_online_state, |
---|
7372 | | - &dhd->node_online); |
---|
7373 | | - return ret; |
---|
| 8374 | + |
---|
| 8375 | + /* pause data on all the interfaces */ |
---|
| 8376 | + dhd_bus_stop_queue(dhdp->bus); |
---|
| 8377 | + |
---|
| 8378 | + /* Devreset function will perform FLR again, to avoid it set dongle_isolation */ |
---|
| 8379 | + dhdp->dongle_isolation = TRUE; |
---|
| 8380 | + dhd_bus_devreset(dhdp, 1); /* DHD structure cleanup */ |
---|
| 8381 | + dhdp->dongle_isolation = dongle_isolation; /* Restore the old value */ |
---|
| 8382 | + return 0; |
---|
7374 | 8383 | } |
---|
7375 | | -#endif |
---|
7376 | | -#endif |
---|
7377 | 8384 | |
---|
| 8385 | +int |
---|
| 8386 | +dhd_wlan_power_on_handler(void *handler, unsigned char reason) |
---|
| 8387 | +{ |
---|
| 8388 | + dhd_pub_t *dhdp = (dhd_pub_t *)handler; |
---|
| 8389 | + bool dongle_isolation = dhdp->dongle_isolation; |
---|
7378 | 8390 | |
---|
| 8391 | + DHD_ERROR(("%s: WLAN DHD re-init reason: %d\n", __FUNCTION__, reason)); |
---|
| 8392 | + /* Devreset function will perform FLR again, to avoid it set dongle_isolation */ |
---|
| 8393 | + dhdp->dongle_isolation = TRUE; |
---|
| 8394 | + dhd_bus_devreset(dhdp, 0); /* DHD structure re-init */ |
---|
| 8395 | + dhdp->dongle_isolation = dongle_isolation; /* Restore the old value */ |
---|
| 8396 | + /* resume data on all the interfaces */ |
---|
| 8397 | + dhd_bus_start_queue(dhdp->bus); |
---|
| 8398 | + return 0; |
---|
| 8399 | + |
---|
| 8400 | +} |
---|
| 8401 | + |
---|
| 8402 | +#endif /* DHD_ERPOM */ |
---|
| 8403 | + |
---|
| 8404 | +/** Called once for each hardware (dongle) instance that this DHD manages */ |
---|
7379 | 8405 | dhd_pub_t * |
---|
7380 | 8406 | dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) |
---|
7381 | 8407 | { |
---|
.. | .. |
---|
7385 | 8411 | uint32 bus_type = -1; |
---|
7386 | 8412 | uint32 bus_num = -1; |
---|
7387 | 8413 | uint32 slot_num = -1; |
---|
| 8414 | +#ifdef SHOW_LOGTRACE |
---|
| 8415 | + int ret; |
---|
| 8416 | +#endif /* SHOW_LOGTRACE */ |
---|
| 8417 | +#ifdef DHD_ERPOM |
---|
| 8418 | + pom_func_handler_t *pom_handler; |
---|
| 8419 | +#endif /* DHD_ERPOM */ |
---|
7388 | 8420 | wifi_adapter_info_t *adapter = NULL; |
---|
7389 | 8421 | |
---|
7390 | 8422 | dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT; |
---|
7391 | 8423 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
7392 | 8424 | |
---|
7393 | | -#ifdef STBLINUX |
---|
7394 | | - DHD_ERROR(("%s\n", driver_target)); |
---|
7395 | | -#endif /* STBLINUX */ |
---|
| 8425 | +#ifdef PCIE_FULL_DONGLE |
---|
| 8426 | + ASSERT(sizeof(dhd_pkttag_fd_t) <= OSL_PKTTAG_SZ); |
---|
| 8427 | + ASSERT(sizeof(dhd_pkttag_fr_t) <= OSL_PKTTAG_SZ); |
---|
| 8428 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 8429 | + |
---|
7396 | 8430 | /* will implement get_ids for DBUS later */ |
---|
7397 | | -#if !defined(BCMDBUS) && defined(BCMSDIO) |
---|
| 8431 | +#if defined(BCMSDIO) |
---|
7398 | 8432 | dhd_bus_get_ids(bus, &bus_type, &bus_num, &slot_num); |
---|
7399 | | -#endif /* !defined(BCMDBUS) && defined(BCMSDIO) */ |
---|
| 8433 | +#endif // endif |
---|
7400 | 8434 | adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num); |
---|
7401 | 8435 | |
---|
7402 | 8436 | /* Allocate primary dhd_info */ |
---|
.. | .. |
---|
7405 | 8439 | dhd = MALLOC(osh, sizeof(dhd_info_t)); |
---|
7406 | 8440 | if (dhd == NULL) { |
---|
7407 | 8441 | DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__)); |
---|
7408 | | - goto fail; |
---|
| 8442 | + goto dhd_null_flag; |
---|
7409 | 8443 | } |
---|
7410 | 8444 | } |
---|
7411 | 8445 | memset(dhd, 0, sizeof(dhd_info_t)); |
---|
7412 | 8446 | dhd_state |= DHD_ATTACH_STATE_DHD_ALLOC; |
---|
7413 | 8447 | |
---|
| 8448 | +#ifdef SHOW_LOGTRACE |
---|
| 8449 | + /* Create ring proc entries */ |
---|
| 8450 | + dhd_dbg_ring_proc_create(&dhd->pub); |
---|
| 8451 | + |
---|
| 8452 | + if (dhd_init_logtrace_process(dhd) != BCME_OK) { |
---|
| 8453 | + goto fail; |
---|
| 8454 | + } |
---|
| 8455 | +#endif /* SHOW_LOGTRACE */ |
---|
| 8456 | + |
---|
7414 | 8457 | dhd->unit = dhd_found + instance_base; /* do not increment dhd_found, yet */ |
---|
7415 | 8458 | |
---|
7416 | 8459 | dhd->pub.osh = osh; |
---|
| 8460 | +#ifdef DUMP_IOCTL_IOV_LIST |
---|
| 8461 | + dll_init(&(dhd->pub.dump_iovlist_head)); |
---|
| 8462 | +#endif /* DUMP_IOCTL_IOV_LIST */ |
---|
| 8463 | + dhd->pub.dhd_console_ms = dhd_console_ms; /* assigns default value */ |
---|
7417 | 8464 | dhd->adapter = adapter; |
---|
| 8465 | +#ifdef BT_OVER_SDIO |
---|
| 8466 | + dhd->pub.is_bt_recovery_required = FALSE; |
---|
| 8467 | + mutex_init(&dhd->bus_user_lock); |
---|
| 8468 | +#endif /* BT_OVER_SDIO */ |
---|
| 8469 | + |
---|
| 8470 | + g_dhd_pub = &dhd->pub; |
---|
| 8471 | + |
---|
| 8472 | +#ifdef DHD_DEBUG |
---|
| 8473 | + dll_init(&(dhd->pub.mw_list_head)); |
---|
| 8474 | +#endif /* DHD_DEBUG */ |
---|
7418 | 8475 | |
---|
7419 | 8476 | #ifdef GET_CUSTOM_MAC_ENABLE |
---|
7420 | 8477 | wifi_platform_get_mac_addr(dhd->adapter, dhd->pub.mac.octet); |
---|
.. | .. |
---|
7428 | 8485 | dhd->pub.dhd_cspec.country_abbrev, &dhd->pub.dhd_cspec, |
---|
7429 | 8486 | dhd->pub.dhd_cflags); |
---|
7430 | 8487 | #endif /* CUSTOM_COUNTRY_CODE */ |
---|
7431 | | -#ifndef BCMDBUS |
---|
7432 | 8488 | dhd->thr_dpc_ctl.thr_pid = DHD_PID_KT_TL_INVALID; |
---|
7433 | 8489 | dhd->thr_wdt_ctl.thr_pid = DHD_PID_KT_INVALID; |
---|
7434 | | - |
---|
7435 | 8490 | #ifdef DHD_WET |
---|
7436 | 8491 | dhd->pub.wet_info = dhd_get_wet_info(&dhd->pub); |
---|
7437 | | -#endif |
---|
7438 | | - |
---|
| 8492 | +#endif /* DHD_WET */ |
---|
7439 | 8493 | /* Initialize thread based operation and lock */ |
---|
7440 | 8494 | sema_init(&dhd->sdsem, 1); |
---|
7441 | 8495 | |
---|
.. | .. |
---|
7444 | 8498 | * solution |
---|
7445 | 8499 | */ |
---|
7446 | 8500 | dhd_update_fw_nv_path(dhd); |
---|
7447 | | -#endif /* BCMDBUS */ |
---|
| 8501 | + dhd->pub.pcie_txs_metadata_enable = pcie_txs_metadata_enable; |
---|
7448 | 8502 | |
---|
7449 | 8503 | /* Link to info module */ |
---|
7450 | 8504 | dhd->pub.info = dhd; |
---|
7451 | 8505 | |
---|
7452 | | - |
---|
7453 | 8506 | /* Link to bus module */ |
---|
7454 | 8507 | dhd->pub.bus = bus; |
---|
7455 | 8508 | dhd->pub.hdrlen = bus_hdrlen; |
---|
| 8509 | + dhd->pub.txoff = FALSE; |
---|
7456 | 8510 | |
---|
7457 | 8511 | /* Set network interface name if it was provided as module parameter */ |
---|
7458 | 8512 | if (iface_name[0]) { |
---|
.. | .. |
---|
7463 | 8517 | len = strlen(if_name); |
---|
7464 | 8518 | ch = if_name[len - 1]; |
---|
7465 | 8519 | if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2)) |
---|
7466 | | - strcat(if_name, "%d"); |
---|
| 8520 | + strncat(if_name, "%d", 2); |
---|
7467 | 8521 | } |
---|
7468 | 8522 | |
---|
7469 | 8523 | /* Passing NULL to dngl_name to ensure host gets if_name in dngl_name member */ |
---|
.. | .. |
---|
7471 | 8525 | if (net == NULL) { |
---|
7472 | 8526 | goto fail; |
---|
7473 | 8527 | } |
---|
7474 | | - |
---|
| 8528 | + mutex_init(&dhd->pub.ndev_op_sync); |
---|
7475 | 8529 | |
---|
7476 | 8530 | dhd_state |= DHD_ATTACH_STATE_ADD_IF; |
---|
7477 | 8531 | #ifdef DHD_L2_FILTER |
---|
7478 | 8532 | /* initialize the l2_filter_cnt */ |
---|
7479 | 8533 | dhd->pub.l2_filter_cnt = 0; |
---|
7480 | | -#endif |
---|
7481 | | -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) |
---|
7482 | | - net->open = NULL; |
---|
7483 | | -#else |
---|
| 8534 | +#endif // endif |
---|
7484 | 8535 | net->netdev_ops = NULL; |
---|
7485 | | -#endif |
---|
7486 | 8536 | |
---|
| 8537 | + mutex_init(&dhd->dhd_iovar_mutex); |
---|
7487 | 8538 | sema_init(&dhd->proto_sem, 1); |
---|
7488 | 8539 | #ifdef DHD_ULP |
---|
7489 | 8540 | if (!(dhd_ulp_init(osh, &dhd->pub))) |
---|
7490 | 8541 | goto fail; |
---|
7491 | 8542 | #endif /* DHD_ULP */ |
---|
| 8543 | + |
---|
| 8544 | +#if defined(DHD_HANG_SEND_UP_TEST) |
---|
| 8545 | + dhd->pub.req_hang_type = 0; |
---|
| 8546 | +#endif /* DHD_HANG_SEND_UP_TEST */ |
---|
7492 | 8547 | |
---|
7493 | 8548 | #ifdef PROP_TXSTATUS |
---|
7494 | 8549 | spin_lock_init(&dhd->wlfc_spinlock); |
---|
.. | .. |
---|
7514 | 8569 | init_waitqueue_head(&dhd->d3ack_wait); |
---|
7515 | 8570 | init_waitqueue_head(&dhd->ctrl_wait); |
---|
7516 | 8571 | init_waitqueue_head(&dhd->dhd_bus_busy_state_wait); |
---|
| 8572 | + init_waitqueue_head(&dhd->dmaxfer_wait); |
---|
| 8573 | + init_waitqueue_head(&dhd->pub.tx_completion_wait); |
---|
7517 | 8574 | dhd->pub.dhd_bus_busy_state = 0; |
---|
7518 | | - |
---|
7519 | 8575 | /* Initialize the spinlocks */ |
---|
7520 | 8576 | spin_lock_init(&dhd->sdlock); |
---|
7521 | 8577 | spin_lock_init(&dhd->txqlock); |
---|
7522 | 8578 | spin_lock_init(&dhd->dhd_lock); |
---|
7523 | 8579 | spin_lock_init(&dhd->rxf_lock); |
---|
| 8580 | +#ifdef WLTDLS |
---|
| 8581 | + spin_lock_init(&dhd->pub.tdls_lock); |
---|
| 8582 | +#endif /* WLTDLS */ |
---|
7524 | 8583 | #if defined(RXFRAME_THREAD) |
---|
7525 | 8584 | dhd->rxthread_enabled = TRUE; |
---|
7526 | 8585 | #endif /* defined(RXFRAME_THREAD) */ |
---|
.. | .. |
---|
7531 | 8590 | |
---|
7532 | 8591 | /* Initialize Wakelock stuff */ |
---|
7533 | 8592 | spin_lock_init(&dhd->wakelock_spinlock); |
---|
7534 | | - dhd->wakelock_counter = 0; |
---|
7535 | | - dhd->wakelock_wd_counter = 0; |
---|
7536 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
7537 | | - wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); |
---|
7538 | | - wake_lock_init(&dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake"); |
---|
| 8593 | + spin_lock_init(&dhd->wakelock_evt_spinlock); |
---|
7539 | 8594 | DHD_OS_WAKE_LOCK_INIT(dhd); |
---|
7540 | | -#endif |
---|
7541 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) |
---|
| 8595 | + dhd->wakelock_counter = 0; |
---|
| 8596 | + /* wakelocks prevent a system from going into a low power state */ |
---|
| 8597 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
| 8598 | + wake_lock_init(&dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake"); |
---|
| 8599 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
| 8600 | + |
---|
| 8601 | +#if defined(OEM_ANDROID) |
---|
7542 | 8602 | mutex_init(&dhd->dhd_net_if_mutex); |
---|
7543 | 8603 | mutex_init(&dhd->dhd_suspend_mutex); |
---|
7544 | | -#endif |
---|
| 8604 | +#if defined(PKT_FILTER_SUPPORT) && defined(APF) |
---|
| 8605 | + mutex_init(&dhd->dhd_apf_mutex); |
---|
| 8606 | +#endif /* PKT_FILTER_SUPPORT && APF */ |
---|
| 8607 | +#endif /* defined(OEM_ANDROID) */ |
---|
7545 | 8608 | dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT; |
---|
7546 | 8609 | |
---|
7547 | 8610 | /* Attach and link in the protocol */ |
---|
.. | .. |
---|
7559 | 8622 | goto fail; |
---|
7560 | 8623 | } |
---|
7561 | 8624 | |
---|
| 8625 | +#ifdef DHD_MONITOR_INTERFACE |
---|
7562 | 8626 | dhd_monitor_init(&dhd->pub); |
---|
| 8627 | +#endif /* DHD_MONITOR_INTERFACE */ |
---|
7563 | 8628 | dhd_state |= DHD_ATTACH_STATE_CFG80211; |
---|
7564 | | -#endif |
---|
| 8629 | +#endif /* WL_CFG80211 */ |
---|
| 8630 | + |
---|
7565 | 8631 | #if defined(WL_WIRELESS_EXT) |
---|
7566 | 8632 | /* Attach and link in the iw */ |
---|
7567 | 8633 | if (!(dhd_state & DHD_ATTACH_STATE_CFG80211)) { |
---|
.. | .. |
---|
7574 | 8640 | #endif /* defined(WL_WIRELESS_EXT) */ |
---|
7575 | 8641 | |
---|
7576 | 8642 | #ifdef SHOW_LOGTRACE |
---|
7577 | | - dhd_init_logstrs_array(&dhd->event_data); |
---|
7578 | | - dhd_init_static_strs_array(&dhd->event_data, st_str_file_path, map_file_path); |
---|
7579 | | - dhd_init_static_strs_array(&dhd->event_data, rom_st_str_file_path, rom_map_file_path); |
---|
| 8643 | + ret = dhd_init_logstrs_array(osh, &dhd->event_data); |
---|
| 8644 | + if (ret == BCME_OK) { |
---|
| 8645 | + dhd_init_static_strs_array(osh, &dhd->event_data, st_str_file_path, map_file_path); |
---|
| 8646 | + dhd_init_static_strs_array(osh, &dhd->event_data, rom_st_str_file_path, |
---|
| 8647 | + rom_map_file_path); |
---|
| 8648 | + dhd_state |= DHD_ATTACH_LOGTRACE_INIT; |
---|
| 8649 | + } |
---|
| 8650 | +#endif /* SHOW_LOGTRACE */ |
---|
7580 | 8651 | |
---|
| 8652 | +#ifdef DEBUGABILITY |
---|
7581 | 8653 | /* attach debug if support */ |
---|
7582 | 8654 | if (dhd_os_dbg_attach(&dhd->pub)) { |
---|
7583 | 8655 | DHD_ERROR(("%s debug module attach failed\n", __FUNCTION__)); |
---|
7584 | 8656 | goto fail; |
---|
7585 | 8657 | } |
---|
| 8658 | +#if defined(SHOW_LOGTRACE) && defined(DBG_RING_LOG_INIT_DEFAULT) |
---|
| 8659 | + /* enable verbose ring to support dump_trace_buf */ |
---|
| 8660 | + dhd_os_start_logging(&dhd->pub, FW_VERBOSE_RING_NAME, 3, 0, 0, 0); |
---|
7586 | 8661 | #endif /* SHOW_LOGTRACE */ |
---|
7587 | 8662 | |
---|
| 8663 | +#ifdef DBG_PKT_MON |
---|
| 8664 | + dhd->pub.dbg->pkt_mon_lock = dhd_os_spin_lock_init(dhd->pub.osh); |
---|
| 8665 | +#ifdef DBG_PKT_MON_INIT_DEFAULT |
---|
| 8666 | + dhd_os_dbg_attach_pkt_monitor(&dhd->pub); |
---|
| 8667 | +#endif /* DBG_PKT_MON_INIT_DEFAULT */ |
---|
| 8668 | +#endif /* DBG_PKT_MON */ |
---|
| 8669 | +#endif /* DEBUGABILITY */ |
---|
| 8670 | + |
---|
| 8671 | +#ifdef DHD_STATUS_LOGGING |
---|
| 8672 | + dhd->pub.statlog = dhd_attach_statlog(&dhd->pub, MAX_STATLOG_ITEM, |
---|
| 8673 | + MAX_STATLOG_REQ_ITEM, STATLOG_LOGBUF_LEN); |
---|
| 8674 | + if (dhd->pub.statlog == NULL) { |
---|
| 8675 | + DHD_ERROR(("%s: alloc statlog failed\n", __FUNCTION__)); |
---|
| 8676 | + } |
---|
| 8677 | +#endif /* DHD_STATUS_LOGGING */ |
---|
| 8678 | + |
---|
| 8679 | +#ifdef DHD_LOG_DUMP |
---|
| 8680 | + dhd_log_dump_init(&dhd->pub); |
---|
| 8681 | +#endif /* DHD_LOG_DUMP */ |
---|
| 8682 | +#ifdef DHD_PKTDUMP_ROAM |
---|
| 8683 | + dhd_dump_pkt_init(&dhd->pub); |
---|
| 8684 | +#endif /* DHD_PKTDUMP_ROAM */ |
---|
| 8685 | +#ifdef DHD_PKT_LOGGING |
---|
| 8686 | + dhd_os_attach_pktlog(&dhd->pub); |
---|
| 8687 | +#endif /* DHD_PKT_LOGGING */ |
---|
| 8688 | + |
---|
| 8689 | +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT |
---|
| 8690 | + dhd->pub.hang_info = MALLOCZ(osh, VENDOR_SEND_HANG_EXT_INFO_LEN); |
---|
| 8691 | + if (dhd->pub.hang_info == NULL) { |
---|
| 8692 | + DHD_ERROR(("%s: alloc hang_info failed\n", __FUNCTION__)); |
---|
| 8693 | + } |
---|
| 8694 | +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ |
---|
7588 | 8695 | if (dhd_sta_pool_init(&dhd->pub, DHD_MAX_STA) != BCME_OK) { |
---|
7589 | 8696 | DHD_ERROR(("%s: Initializing %u sta\n", __FUNCTION__, DHD_MAX_STA)); |
---|
7590 | 8697 | goto fail; |
---|
7591 | 8698 | } |
---|
7592 | 8699 | |
---|
7593 | | - |
---|
7594 | | -#ifndef BCMDBUS |
---|
| 8700 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 8701 | + dhd->tx_wq = alloc_workqueue("bcmdhd-tx-wq", WQ_HIGHPRI | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); |
---|
| 8702 | + if (!dhd->tx_wq) { |
---|
| 8703 | + DHD_ERROR(("%s: alloc_workqueue(bcmdhd-tx-wq) failed\n", __FUNCTION__)); |
---|
| 8704 | + goto fail; |
---|
| 8705 | + } |
---|
| 8706 | + dhd->rx_wq = alloc_workqueue("bcmdhd-rx-wq", WQ_HIGHPRI | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); |
---|
| 8707 | + if (!dhd->rx_wq) { |
---|
| 8708 | + DHD_ERROR(("%s: alloc_workqueue(bcmdhd-rx-wq) failed\n", __FUNCTION__)); |
---|
| 8709 | + destroy_workqueue(dhd->tx_wq); |
---|
| 8710 | + dhd->tx_wq = NULL; |
---|
| 8711 | + goto fail; |
---|
| 8712 | + } |
---|
| 8713 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
7595 | 8714 | |
---|
7596 | 8715 | /* Set up the watchdog timer */ |
---|
7597 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) |
---|
7598 | | - timer_setup(&dhd->timer, dhd_watchdog, 0); |
---|
7599 | | -#else |
---|
7600 | | - init_timer(&dhd->timer); |
---|
7601 | | - dhd->timer.data = (ulong)dhd; |
---|
7602 | | - dhd->timer.function = dhd_watchdog; |
---|
7603 | | -#endif |
---|
| 8716 | + init_timer_compat(&dhd->timer, dhd_watchdog, dhd); |
---|
7604 | 8717 | dhd->default_wd_interval = dhd_watchdog_ms; |
---|
7605 | 8718 | |
---|
7606 | 8719 | if (dhd_watchdog_prio >= 0) { |
---|
7607 | 8720 | /* Initialize watchdog thread */ |
---|
7608 | 8721 | PROC_START(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0, "dhd_watchdog_thread"); |
---|
| 8722 | + if (dhd->thr_wdt_ctl.thr_pid < 0) { |
---|
| 8723 | + goto fail; |
---|
| 8724 | + } |
---|
7609 | 8725 | |
---|
7610 | 8726 | } else { |
---|
7611 | 8727 | dhd->thr_wdt_ctl.thr_pid = -1; |
---|
7612 | 8728 | } |
---|
7613 | 8729 | |
---|
7614 | | -#ifdef DEBUGGER |
---|
7615 | | - debugger_init((void *) bus); |
---|
7616 | | -#endif |
---|
| 8730 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 8731 | + /* Setup up the runtime PM Idlecount timer */ |
---|
| 8732 | + init_timer_compat(&dhd->rpm_timer, dhd_runtimepm, dhd); |
---|
| 8733 | + dhd->rpm_timer_valid = FALSE; |
---|
| 8734 | + |
---|
| 8735 | + dhd->thr_rpm_ctl.thr_pid = DHD_PID_KT_INVALID; |
---|
| 8736 | + PROC_START(dhd_rpm_state_thread, dhd, &dhd->thr_rpm_ctl, 0, "dhd_rpm_state_thread"); |
---|
| 8737 | + if (dhd->thr_rpm_ctl.thr_pid < 0) { |
---|
| 8738 | + goto fail; |
---|
| 8739 | + } |
---|
| 8740 | +#endif /* DHD_PCIE_RUNTIMEPM */ |
---|
| 8741 | + |
---|
| 8742 | +#ifdef SHOW_LOGTRACE |
---|
| 8743 | + skb_queue_head_init(&dhd->evt_trace_queue); |
---|
| 8744 | +#endif /* SHOW_LOGTRACE */ |
---|
7617 | 8745 | |
---|
7618 | 8746 | /* Set up the bottom half handler */ |
---|
7619 | 8747 | if (dhd_dpc_prio >= 0) { |
---|
7620 | 8748 | /* Initialize DPC thread */ |
---|
7621 | 8749 | PROC_START(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0, "dhd_dpc"); |
---|
| 8750 | + if (dhd->thr_dpc_ctl.thr_pid < 0) { |
---|
| 8751 | + goto fail; |
---|
| 8752 | + } |
---|
7622 | 8753 | } else { |
---|
7623 | 8754 | /* use tasklet for dpc */ |
---|
7624 | 8755 | tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd); |
---|
.. | .. |
---|
7629 | 8760 | bzero(&dhd->pub.skbbuf[0], sizeof(void *) * MAXSKBPEND); |
---|
7630 | 8761 | /* Initialize RXF thread */ |
---|
7631 | 8762 | PROC_START(dhd_rxf_thread, dhd, &dhd->thr_rxf_ctl, 0, "dhd_rxf"); |
---|
| 8763 | + if (dhd->thr_rxf_ctl.thr_pid < 0) { |
---|
| 8764 | + goto fail; |
---|
| 8765 | + } |
---|
7632 | 8766 | } |
---|
7633 | | -#endif /* BCMDBUS */ |
---|
7634 | 8767 | |
---|
7635 | 8768 | dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED; |
---|
7636 | 8769 | |
---|
.. | .. |
---|
7660 | 8793 | } |
---|
7661 | 8794 | #endif /* ARP_OFFLOAD_SUPPORT */ |
---|
7662 | 8795 | |
---|
7663 | | -#if defined(CONFIG_IPV6) |
---|
| 8796 | +#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT) |
---|
7664 | 8797 | if (!dhd_inet6addr_notifier_registered) { |
---|
7665 | 8798 | dhd_inet6addr_notifier_registered = TRUE; |
---|
7666 | 8799 | register_inet6addr_notifier(&dhd_inet6addr_notifier); |
---|
7667 | 8800 | } |
---|
7668 | | -#endif /* OEM_ANDROID && CONFIG_IPV6 */ |
---|
| 8801 | +#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */ |
---|
7669 | 8802 | dhd->dhd_deferred_wq = dhd_deferred_work_init((void *)dhd); |
---|
| 8803 | +#if defined(OEM_ANDROID) |
---|
| 8804 | + INIT_WORK(&dhd->dhd_hang_process_work, dhd_hang_process); |
---|
| 8805 | +#endif /* #if OEM_ANDROID */ |
---|
7670 | 8806 | #ifdef DEBUG_CPU_FREQ |
---|
7671 | 8807 | dhd->new_freq = alloc_percpu(int); |
---|
7672 | 8808 | dhd->freq_trans.notifier_call = dhd_cpufreq_notifier; |
---|
7673 | 8809 | cpufreq_register_notifier(&dhd->freq_trans, CPUFREQ_TRANSITION_NOTIFIER); |
---|
7674 | | -#endif |
---|
| 8810 | +#endif // endif |
---|
7675 | 8811 | #ifdef DHDTCPACK_SUPPRESS |
---|
7676 | 8812 | #ifdef BCMSDIO |
---|
7677 | 8813 | dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_DELAYTX); |
---|
.. | .. |
---|
7683 | 8819 | #endif /* DHDTCPACK_SUPPRESS */ |
---|
7684 | 8820 | |
---|
7685 | 8821 | #if defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) |
---|
7686 | | -#if defined(BCMDBUS) |
---|
7687 | | - sema_init(&dhd->fw_download_lock, 0); |
---|
7688 | | - dhd->fw_download_task = kthread_run(fw_download_thread_func, dhd, "fwdl-thread"); |
---|
7689 | | -#endif /* BCMDBUS */ |
---|
7690 | 8822 | #endif /* defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) */ |
---|
7691 | | - |
---|
7692 | | - dhd_state |= DHD_ATTACH_STATE_DONE; |
---|
7693 | | - dhd->dhd_state = dhd_state; |
---|
7694 | | - |
---|
7695 | | - dhd_found++; |
---|
7696 | 8823 | |
---|
7697 | 8824 | #ifdef DHD_DEBUG_PAGEALLOC |
---|
7698 | 8825 | register_page_corrupt_cb(dhd_page_corrupt_cb, &dhd->pub); |
---|
7699 | 8826 | #endif /* DHD_DEBUG_PAGEALLOC */ |
---|
7700 | 8827 | |
---|
7701 | 8828 | #if defined(DHD_LB) |
---|
7702 | | - DHD_ERROR(("DHD LOAD BALANCING Enabled\n")); |
---|
7703 | 8829 | |
---|
7704 | 8830 | dhd_lb_set_default_cpus(dhd); |
---|
| 8831 | + DHD_LB_STATS_INIT(&dhd->pub); |
---|
7705 | 8832 | |
---|
7706 | 8833 | /* Initialize the CPU Masks */ |
---|
7707 | | - if (dhd_cpumasks_init(dhd) == 0) { |
---|
7708 | | - |
---|
| 8834 | + if (dhd_cpumasks_init(dhd) == 0) { |
---|
7709 | 8835 | /* Now we have the current CPU maps, run through candidacy */ |
---|
7710 | 8836 | dhd_select_cpu_candidacy(dhd); |
---|
7711 | 8837 | |
---|
7712 | | - /* |
---|
7713 | | - * If we are able to initialize CPU masks, lets register to the |
---|
7714 | | - * CPU Hotplug framework to change the CPU for each job dynamically |
---|
7715 | | - * using candidacy algorithm. |
---|
7716 | | - */ |
---|
7717 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) |
---|
7718 | | - dhd_cpuhp_init(osh, dhd); |
---|
7719 | | -#else |
---|
7720 | | - dhd->cpu_notifier.notifier_call = dhd_cpu_callback; |
---|
7721 | | - register_cpu_notifier(&dhd->cpu_notifier); /* Register a callback */ |
---|
7722 | | -#endif |
---|
| 8838 | + /* Register the call backs to CPU Hotplug sub-system */ |
---|
| 8839 | + dhd_register_cpuhp_callback(dhd); |
---|
| 8840 | + |
---|
7723 | 8841 | } else { |
---|
7724 | 8842 | /* |
---|
7725 | | - * We are unable to initialize CPU masks, so candidacy algorithm |
---|
7726 | | - * won't run, but still Load Balancing will be honoured based |
---|
7727 | | - * on the CPUs allocated for a given job statically during init |
---|
7728 | | - */ |
---|
7729 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) |
---|
7730 | | -#else |
---|
| 8843 | + * We are unable to initialize CPU masks, so candidacy algorithm |
---|
| 8844 | + * won't run, but still Load Balancing will be honoured based |
---|
| 8845 | + * on the CPUs allocated for a given job statically during init |
---|
| 8846 | + */ |
---|
7731 | 8847 | dhd->cpu_notifier.notifier_call = NULL; |
---|
7732 | | - DHD_ERROR(("%s(): dhd_cpumasks_init failed CPUs for JOB would be static\n", |
---|
| 8848 | + DHD_ERROR(("%s():dhd_cpumasks_init failed CPUs for JOB would be static\n", |
---|
7733 | 8849 | __FUNCTION__)); |
---|
7734 | | -#endif |
---|
7735 | 8850 | } |
---|
7736 | 8851 | |
---|
| 8852 | +#ifdef DHD_LB_TXP |
---|
| 8853 | +#ifdef DHD_LB_TXP_DEFAULT_ENAB |
---|
| 8854 | + /* Trun ON the feature by default */ |
---|
| 8855 | + atomic_set(&dhd->lb_txp_active, 1); |
---|
| 8856 | +#else |
---|
| 8857 | + /* Trun OFF the feature by default */ |
---|
| 8858 | + atomic_set(&dhd->lb_txp_active, 0); |
---|
| 8859 | +#endif /* DHD_LB_TXP_DEFAULT_ENAB */ |
---|
| 8860 | +#endif /* DHD_LB_TXP */ |
---|
7737 | 8861 | |
---|
7738 | | - DHD_LB_STATS_INIT(&dhd->pub); |
---|
| 8862 | +#ifdef DHD_LB_RXP |
---|
| 8863 | + /* Trun ON the feature by default */ |
---|
| 8864 | + atomic_set(&dhd->lb_rxp_active, 1); |
---|
| 8865 | +#endif /* DHD_LB_RXP */ |
---|
7739 | 8866 | |
---|
7740 | 8867 | /* Initialize the Load Balancing Tasklets and Napi object */ |
---|
7741 | 8868 | #if defined(DHD_LB_TXC) |
---|
.. | .. |
---|
7744 | 8871 | INIT_WORK(&dhd->tx_compl_dispatcher_work, dhd_tx_compl_dispatcher_fn); |
---|
7745 | 8872 | DHD_INFO(("%s load balance init tx_compl_tasklet\n", __FUNCTION__)); |
---|
7746 | 8873 | #endif /* DHD_LB_TXC */ |
---|
7747 | | - |
---|
7748 | 8874 | #if defined(DHD_LB_RXC) |
---|
7749 | 8875 | tasklet_init(&dhd->rx_compl_tasklet, |
---|
7750 | 8876 | dhd_lb_rx_compl_handler, (ulong)(&dhd->pub)); |
---|
.. | .. |
---|
7753 | 8879 | #endif /* DHD_LB_RXC */ |
---|
7754 | 8880 | |
---|
7755 | 8881 | #if defined(DHD_LB_RXP) |
---|
7756 | | - __skb_queue_head_init(&dhd->rx_pend_queue); |
---|
| 8882 | + __skb_queue_head_init(&dhd->rx_pend_queue); |
---|
7757 | 8883 | skb_queue_head_init(&dhd->rx_napi_queue); |
---|
7758 | | - |
---|
7759 | 8884 | /* Initialize the work that dispatches NAPI job to a given core */ |
---|
7760 | 8885 | INIT_WORK(&dhd->rx_napi_dispatcher_work, dhd_rx_napi_dispatcher_fn); |
---|
7761 | 8886 | DHD_INFO(("%s load balance init rx_napi_queue\n", __FUNCTION__)); |
---|
7762 | 8887 | #endif /* DHD_LB_RXP */ |
---|
7763 | 8888 | |
---|
| 8889 | +#if defined(DHD_LB_TXP) |
---|
| 8890 | + INIT_WORK(&dhd->tx_dispatcher_work, dhd_tx_dispatcher_work); |
---|
| 8891 | + skb_queue_head_init(&dhd->tx_pend_queue); |
---|
| 8892 | + /* Initialize the work that dispatches TX job to a given core */ |
---|
| 8893 | + tasklet_init(&dhd->tx_tasklet, |
---|
| 8894 | + dhd_lb_tx_handler, (ulong)(dhd)); |
---|
| 8895 | + DHD_INFO(("%s load balance init tx_pend_queue\n", __FUNCTION__)); |
---|
| 8896 | +#endif /* DHD_LB_TXP */ |
---|
| 8897 | + |
---|
| 8898 | + dhd_state |= DHD_ATTACH_STATE_LB_ATTACH_DONE; |
---|
7764 | 8899 | #endif /* DHD_LB */ |
---|
| 8900 | + |
---|
| 8901 | +#if defined(DNGL_AXI_ERROR_LOGGING) && defined(DHD_USE_WQ_FOR_DNGL_AXI_ERROR) |
---|
| 8902 | + INIT_WORK(&dhd->axi_error_dispatcher_work, dhd_axi_error_dispatcher_fn); |
---|
| 8903 | +#endif /* DNGL_AXI_ERROR_LOGGING && DHD_USE_WQ_FOR_DNGL_AXI_ERROR */ |
---|
| 8904 | + |
---|
| 8905 | +#if defined(BCMPCIE) |
---|
| 8906 | + dhd->pub.extended_trap_data = MALLOCZ(osh, BCMPCIE_EXT_TRAP_DATA_MAXLEN); |
---|
| 8907 | + if (dhd->pub.extended_trap_data == NULL) { |
---|
| 8908 | + DHD_ERROR(("%s: Failed to alloc extended_trap_data\n", __FUNCTION__)); |
---|
| 8909 | + } |
---|
| 8910 | +#ifdef DNGL_AXI_ERROR_LOGGING |
---|
| 8911 | + dhd->pub.axi_err_dump = MALLOCZ(osh, sizeof(dhd_axi_error_dump_t)); |
---|
| 8912 | + if (dhd->pub.axi_err_dump == NULL) { |
---|
| 8913 | + DHD_ERROR(("%s: Failed to alloc axi_err_dump\n", __FUNCTION__)); |
---|
| 8914 | + } |
---|
| 8915 | +#endif /* DNGL_AXI_ERROR_LOGGING */ |
---|
| 8916 | +#endif /* BCMPCIE && ETD */ |
---|
| 8917 | + |
---|
| 8918 | + DHD_SSSR_MEMPOOL_INIT(&dhd->pub); |
---|
| 8919 | + |
---|
| 8920 | +#ifdef EWP_EDL |
---|
| 8921 | + if (host_edl_support) { |
---|
| 8922 | + if (DHD_EDL_MEM_INIT(&dhd->pub) != BCME_OK) { |
---|
| 8923 | + host_edl_support = FALSE; |
---|
| 8924 | + } |
---|
| 8925 | + } |
---|
| 8926 | +#endif /* EWP_EDL */ |
---|
| 8927 | + |
---|
| 8928 | + (void)dhd_sysfs_init(dhd); |
---|
| 8929 | + |
---|
| 8930 | +#ifdef WL_NATOE |
---|
| 8931 | + /* Open Netlink socket for NF_CONNTRACK notifications */ |
---|
| 8932 | + dhd->pub.nfct = dhd_ct_open(&dhd->pub, NFNL_SUBSYS_CTNETLINK | NFNL_SUBSYS_CTNETLINK_EXP, |
---|
| 8933 | + CT_ALL); |
---|
| 8934 | +#endif /* WL_NATOE */ |
---|
| 8935 | + |
---|
| 8936 | + dhd_state |= DHD_ATTACH_STATE_DONE; |
---|
| 8937 | + dhd->dhd_state = dhd_state; |
---|
| 8938 | + |
---|
| 8939 | + dhd_found++; |
---|
| 8940 | + |
---|
| 8941 | +#ifdef DHD_DUMP_MNGR |
---|
| 8942 | + dhd->pub.dump_file_manage = |
---|
| 8943 | + (dhd_dump_file_manage_t *)MALLOCZ(dhd->pub.osh, sizeof(dhd_dump_file_manage_t)); |
---|
| 8944 | + if (unlikely(!dhd->pub.dump_file_manage)) { |
---|
| 8945 | + DHD_ERROR(("%s(): could not allocate memory for - " |
---|
| 8946 | + "dhd_dump_file_manage_t\n", __FUNCTION__)); |
---|
| 8947 | + } |
---|
| 8948 | +#endif /* DHD_DUMP_MNGR */ |
---|
| 8949 | +#ifdef DHD_FW_COREDUMP |
---|
| 8950 | + /* Set memdump default values */ |
---|
| 8951 | +#ifdef CUSTOMER_HW4_DEBUG |
---|
| 8952 | + dhd->pub.memdump_enabled = DUMP_DISABLED; |
---|
| 8953 | +#elif defined(OEM_ANDROID) |
---|
| 8954 | + dhd->pub.memdump_enabled = DUMP_MEMFILE_BUGON; |
---|
| 8955 | +#else |
---|
| 8956 | + dhd->pub.memdump_enabled = DUMP_MEMFILE; |
---|
| 8957 | +#endif /* CUSTOMER_HW4_DEBUG */ |
---|
| 8958 | + /* Check the memdump capability */ |
---|
| 8959 | + dhd_get_memdump_info(&dhd->pub); |
---|
| 8960 | +#endif /* DHD_FW_COREDUMP */ |
---|
| 8961 | + |
---|
| 8962 | +#ifdef DHD_ERPOM |
---|
| 8963 | + if (enable_erpom) { |
---|
| 8964 | + pom_handler = &dhd->pub.pom_wlan_handler; |
---|
| 8965 | + pom_handler->func_id = WLAN_FUNC_ID; |
---|
| 8966 | + pom_handler->handler = (void *)g_dhd_pub; |
---|
| 8967 | + pom_handler->power_off = dhd_wlan_power_off_handler; |
---|
| 8968 | + pom_handler->power_on = dhd_wlan_power_on_handler; |
---|
| 8969 | + |
---|
| 8970 | + dhd->pub.pom_func_register = NULL; |
---|
| 8971 | + dhd->pub.pom_func_deregister = NULL; |
---|
| 8972 | + dhd->pub.pom_toggle_reg_on = NULL; |
---|
| 8973 | + |
---|
| 8974 | + dhd->pub.pom_func_register = symbol_get(pom_func_register); |
---|
| 8975 | + dhd->pub.pom_func_deregister = symbol_get(pom_func_deregister); |
---|
| 8976 | + dhd->pub.pom_toggle_reg_on = symbol_get(pom_toggle_reg_on); |
---|
| 8977 | + |
---|
| 8978 | + symbol_put(pom_func_register); |
---|
| 8979 | + symbol_put(pom_func_deregister); |
---|
| 8980 | + symbol_put(pom_toggle_reg_on); |
---|
| 8981 | + |
---|
| 8982 | + if (!dhd->pub.pom_func_register || |
---|
| 8983 | + !dhd->pub.pom_func_deregister || |
---|
| 8984 | + !dhd->pub.pom_toggle_reg_on) { |
---|
| 8985 | + DHD_ERROR(("%s, enable_erpom enabled through module parameter but " |
---|
| 8986 | + "POM is not loaded\n", __FUNCTION__)); |
---|
| 8987 | + ASSERT(0); |
---|
| 8988 | + goto fail; |
---|
| 8989 | + } |
---|
| 8990 | + dhd->pub.pom_func_register(pom_handler); |
---|
| 8991 | + dhd->pub.enable_erpom = TRUE; |
---|
| 8992 | + |
---|
| 8993 | + } |
---|
| 8994 | +#endif /* DHD_ERPOM */ |
---|
7765 | 8995 | return &dhd->pub; |
---|
7766 | 8996 | |
---|
7767 | 8997 | fail: |
---|
.. | .. |
---|
7773 | 9003 | dhd_free(&dhd->pub); |
---|
7774 | 9004 | } |
---|
7775 | 9005 | |
---|
| 9006 | +dhd_null_flag: |
---|
7776 | 9007 | return NULL; |
---|
7777 | 9008 | } |
---|
7778 | 9009 | |
---|
.. | .. |
---|
7790 | 9021 | return DHD_FLAG_STA_MODE; |
---|
7791 | 9022 | } |
---|
7792 | 9023 | |
---|
7793 | | -#ifndef BCMDBUS |
---|
| 9024 | +int dhd_bus_get_fw_mode(dhd_pub_t *dhdp) |
---|
| 9025 | +{ |
---|
| 9026 | + return dhd_get_fw_mode(dhdp->info); |
---|
| 9027 | +} |
---|
| 9028 | + |
---|
| 9029 | +extern char * nvram_get(const char *name); |
---|
| 9030 | + |
---|
7794 | 9031 | |
---|
7795 | 9032 | int cis_chipvendor = 0; |
---|
7796 | 9033 | unsigned short cis_device = 0; |
---|
.. | .. |
---|
7804 | 9041 | #define FW_CYW43438 "fw_cyw43438.bin" |
---|
7805 | 9042 | #define FW_CYW43455 "fw_cyw43455.bin" |
---|
7806 | 9043 | #define FW_CYW4354 "fw_cyw4354.bin" |
---|
| 9044 | +#define FW_CYW4373 "cyfmac4373-sdio.bin" |
---|
7807 | 9045 | |
---|
7808 | 9046 | #define NVRAM_CYW43364 "nvram_azw432.txt" |
---|
7809 | 9047 | #define NVRAM_CYW43438 "nvram_azw372.txt" |
---|
7810 | 9048 | #define NVRAM_CYW43455 "nvram_azw256.txt" |
---|
7811 | 9049 | #define NVRAM_CYW4354 "nvram_azw235.txt" |
---|
| 9050 | +#define NVRAM_CYW4373 "brcmfmac4373-sdio.txt" |
---|
7812 | 9051 | |
---|
7813 | 9052 | bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo) |
---|
7814 | 9053 | { |
---|
.. | .. |
---|
7816 | 9055 | int nv_len; |
---|
7817 | 9056 | const char *fw = NULL; |
---|
7818 | 9057 | const char *nv = NULL; |
---|
| 9058 | +#ifdef DHD_UCODE_DOWNLOAD |
---|
| 9059 | + int uc_len; |
---|
| 9060 | + const char *uc = NULL; |
---|
| 9061 | +#endif /* DHD_UCODE_DOWNLOAD */ |
---|
7819 | 9062 | wifi_adapter_info_t *adapter = dhdinfo->adapter; |
---|
7820 | | - |
---|
| 9063 | + int fw_path_len = sizeof(dhdinfo->fw_path); |
---|
| 9064 | + int nv_path_len = sizeof(dhdinfo->nv_path); |
---|
7821 | 9065 | |
---|
7822 | 9066 | /* Update firmware and nvram path. The path may be from adapter info or module parameter |
---|
7823 | 9067 | * The path from adapter info is used for initialization only (as it won't change). |
---|
.. | .. |
---|
7832 | 9076 | /* set default firmware and nvram path for built-in type driver */ |
---|
7833 | 9077 | if (!dhd_download_fw_on_driverload) { |
---|
7834 | 9078 | #ifdef CONFIG_BCMDHD_FW_PATH |
---|
7835 | | - fw = CONFIG_BCMDHD_FW_PATH; |
---|
| 9079 | + fw = VENDOR_PATH CONFIG_BCMDHD_FW_PATH; |
---|
7836 | 9080 | #endif /* CONFIG_BCMDHD_FW_PATH */ |
---|
7837 | 9081 | #ifdef CONFIG_BCMDHD_NVRAM_PATH |
---|
7838 | | - nv = CONFIG_BCMDHD_NVRAM_PATH; |
---|
| 9082 | + nv = VENDOR_PATH CONFIG_BCMDHD_NVRAM_PATH; |
---|
7839 | 9083 | #endif /* CONFIG_BCMDHD_NVRAM_PATH */ |
---|
7840 | 9084 | } |
---|
7841 | 9085 | |
---|
.. | .. |
---|
7843 | 9087 | if (dhdinfo->fw_path[0] == '\0') { |
---|
7844 | 9088 | if (adapter && adapter->fw_path && adapter->fw_path[0] != '\0') |
---|
7845 | 9089 | fw = adapter->fw_path; |
---|
7846 | | - |
---|
7847 | 9090 | } |
---|
7848 | 9091 | if (dhdinfo->nv_path[0] == '\0') { |
---|
7849 | 9092 | if (adapter && adapter->nv_path && adapter->nv_path[0] != '\0') |
---|
.. | .. |
---|
7856 | 9099 | */ |
---|
7857 | 9100 | if (firmware_path[0] != '\0') |
---|
7858 | 9101 | fw = firmware_path; |
---|
| 9102 | + |
---|
7859 | 9103 | if (nvram_path[0] != '\0') |
---|
7860 | 9104 | nv = nvram_path; |
---|
7861 | 9105 | |
---|
7862 | | - if (cis_device == BCM43455_CHIP_ID && cis_chipvendor == 0x81) { |
---|
| 9106 | + |
---|
| 9107 | +if (cis_device == BCM43455_CHIP_ID && cis_chipvendor == 0x81) { |
---|
7863 | 9108 | sprintf(fw_path, "%s%s", DEFAULT_BCMDHD_FW_PATH, FW_CYW43455); |
---|
7864 | 9109 | sprintf(nv_path, "%s%s", DEFAULT_BCMDHD_NVRAM_PATH, NVRAM_CYW43455); |
---|
7865 | 9110 | DHD_ERROR(("Adding CYW43455 firmware and NVRAM path by CIS\n" |
---|
.. | .. |
---|
7895 | 9140 | fw = fw_path; |
---|
7896 | 9141 | nv = nv_path; |
---|
7897 | 9142 | } |
---|
| 9143 | + else if (cis_device == BCM4373_CHIP_ID){ |
---|
| 9144 | + sprintf(fw_path, "%s%s", DEFAULT_BCMDHD_FW_PATH, FW_CYW4373); |
---|
| 9145 | + sprintf(nv_path, "%s%s", DEFAULT_BCMDHD_NVRAM_PATH, NVRAM_CYW4373); |
---|
| 9146 | + DHD_ERROR(("Adding CYW4373 firmware and NVRAM path by CIS\n" |
---|
| 9147 | + "\tfirmware path: %s\n" |
---|
| 9148 | + "\tNVRAM path: %s\n", fw_path, nv_path)); |
---|
| 9149 | + fw = fw_path; |
---|
| 9150 | + nv = nv_path; |
---|
| 9151 | + } |
---|
| 9152 | + |
---|
| 9153 | +#ifdef DHD_UCODE_DOWNLOAD |
---|
| 9154 | + if (ucode_path[0] != '\0') |
---|
| 9155 | + uc = ucode_path; |
---|
| 9156 | +#endif /* DHD_UCODE_DOWNLOAD */ |
---|
7898 | 9157 | |
---|
7899 | 9158 | if (fw && fw[0] != '\0') { |
---|
7900 | 9159 | fw_len = strlen(fw); |
---|
7901 | | - if (fw_len >= sizeof(dhdinfo->fw_path)) { |
---|
| 9160 | + if (fw_len >= fw_path_len) { |
---|
7902 | 9161 | DHD_ERROR(("fw path len exceeds max len of dhdinfo->fw_path\n")); |
---|
7903 | 9162 | return FALSE; |
---|
7904 | 9163 | } |
---|
7905 | | - strncpy(dhdinfo->fw_path, fw, sizeof(dhdinfo->fw_path)); |
---|
| 9164 | + strncpy(dhdinfo->fw_path, fw, fw_path_len); |
---|
7906 | 9165 | if (dhdinfo->fw_path[fw_len-1] == '\n') |
---|
7907 | 9166 | dhdinfo->fw_path[fw_len-1] = '\0'; |
---|
7908 | 9167 | } |
---|
7909 | 9168 | if (nv && nv[0] != '\0') { |
---|
7910 | 9169 | nv_len = strlen(nv); |
---|
7911 | | - if (nv_len >= sizeof(dhdinfo->nv_path)) { |
---|
| 9170 | + if (nv_len >= nv_path_len) { |
---|
7912 | 9171 | DHD_ERROR(("nvram path len exceeds max len of dhdinfo->nv_path\n")); |
---|
7913 | 9172 | return FALSE; |
---|
7914 | 9173 | } |
---|
7915 | | - strncpy(dhdinfo->nv_path, nv, sizeof(dhdinfo->nv_path)); |
---|
| 9174 | + memset(dhdinfo->nv_path, 0, nv_path_len); |
---|
| 9175 | + strncpy(dhdinfo->nv_path, nv, nv_path_len); |
---|
| 9176 | + dhdinfo->nv_path[nv_len] = '\0'; |
---|
| 9177 | +#ifdef DHD_USE_SINGLE_NVRAM_FILE |
---|
| 9178 | + /* Remove "_net" or "_mfg" tag from current nvram path */ |
---|
| 9179 | + { |
---|
| 9180 | + char *nvram_tag = "nvram_"; |
---|
| 9181 | + char *ext_tag = ".txt"; |
---|
| 9182 | + char *sp_nvram = strnstr(dhdinfo->nv_path, nvram_tag, nv_path_len); |
---|
| 9183 | + bool valid_buf = sp_nvram && ((uint32)(sp_nvram + strlen(nvram_tag) + |
---|
| 9184 | + strlen(ext_tag) - dhdinfo->nv_path) <= nv_path_len); |
---|
| 9185 | + if (valid_buf) { |
---|
| 9186 | + char *sp = sp_nvram + strlen(nvram_tag) - 1; |
---|
| 9187 | + uint32 padding_size = (uint32)(dhdinfo->nv_path + |
---|
| 9188 | + nv_path_len - sp); |
---|
| 9189 | + memset(sp, 0, padding_size); |
---|
| 9190 | + strncat(dhdinfo->nv_path, ext_tag, strlen(ext_tag)); |
---|
| 9191 | + nv_len = strlen(dhdinfo->nv_path); |
---|
| 9192 | + DHD_INFO(("%s: new nvram path = %s\n", |
---|
| 9193 | + __FUNCTION__, dhdinfo->nv_path)); |
---|
| 9194 | + } else if (sp_nvram) { |
---|
| 9195 | + DHD_ERROR(("%s: buffer space for nvram path is not enough\n", |
---|
| 9196 | + __FUNCTION__)); |
---|
| 9197 | + return FALSE; |
---|
| 9198 | + } else { |
---|
| 9199 | + DHD_ERROR(("%s: Couldn't find the nvram tag. current" |
---|
| 9200 | + " nvram path = %s\n", __FUNCTION__, dhdinfo->nv_path)); |
---|
| 9201 | + } |
---|
| 9202 | + } |
---|
| 9203 | +#endif /* DHD_USE_SINGLE_NVRAM_FILE */ |
---|
7916 | 9204 | if (dhdinfo->nv_path[nv_len-1] == '\n') |
---|
7917 | 9205 | dhdinfo->nv_path[nv_len-1] = '\0'; |
---|
7918 | 9206 | } |
---|
| 9207 | +#ifdef DHD_UCODE_DOWNLOAD |
---|
| 9208 | + if (uc && uc[0] != '\0') { |
---|
| 9209 | + uc_len = strlen(uc); |
---|
| 9210 | + if (uc_len >= sizeof(dhdinfo->uc_path)) { |
---|
| 9211 | + DHD_ERROR(("uc path len exceeds max len of dhdinfo->uc_path\n")); |
---|
| 9212 | + return FALSE; |
---|
| 9213 | + } |
---|
| 9214 | + strncpy(dhdinfo->uc_path, uc, sizeof(dhdinfo->uc_path)); |
---|
| 9215 | + if (dhdinfo->uc_path[uc_len-1] == '\n') |
---|
| 9216 | + dhdinfo->uc_path[uc_len-1] = '\0'; |
---|
| 9217 | + } |
---|
| 9218 | +#endif /* DHD_UCODE_DOWNLOAD */ |
---|
7919 | 9219 | |
---|
7920 | 9220 | /* clear the path in module parameter */ |
---|
7921 | | - firmware_path[0] = '\0'; |
---|
7922 | | - nvram_path[0] = '\0'; |
---|
| 9221 | + if (dhd_download_fw_on_driverload) { |
---|
| 9222 | + firmware_path[0] = '\0'; |
---|
| 9223 | + nvram_path[0] = '\0'; |
---|
| 9224 | + } |
---|
| 9225 | +#ifdef DHD_UCODE_DOWNLOAD |
---|
| 9226 | + ucode_path[0] = '\0'; |
---|
| 9227 | + DHD_ERROR(("ucode path: %s\n", dhdinfo->uc_path)); |
---|
| 9228 | +#endif /* DHD_UCODE_DOWNLOAD */ |
---|
7923 | 9229 | |
---|
7924 | | -#ifndef BCMEMBEDIMAGE |
---|
7925 | 9230 | /* fw_path and nv_path are not mandatory for BCMEMBEDIMAGE */ |
---|
7926 | 9231 | if (dhdinfo->fw_path[0] == '\0') { |
---|
7927 | 9232 | DHD_ERROR(("firmware path not found\n")); |
---|
.. | .. |
---|
7931 | 9236 | DHD_ERROR(("nvram path not found\n")); |
---|
7932 | 9237 | return FALSE; |
---|
7933 | 9238 | } |
---|
7934 | | -#endif /* BCMEMBEDIMAGE */ |
---|
7935 | 9239 | |
---|
7936 | 9240 | return TRUE; |
---|
7937 | 9241 | } |
---|
7938 | 9242 | |
---|
| 9243 | +#if defined(BT_OVER_SDIO) |
---|
| 9244 | +extern bool dhd_update_btfw_path(dhd_info_t *dhdinfo, char* btfw_path) |
---|
| 9245 | +{ |
---|
| 9246 | + int fw_len; |
---|
| 9247 | + const char *fw = NULL; |
---|
| 9248 | + wifi_adapter_info_t *adapter = dhdinfo->adapter; |
---|
| 9249 | + |
---|
| 9250 | + /* Update bt firmware path. The path may be from adapter info or module parameter |
---|
| 9251 | + * The path from adapter info is used for initialization only (as it won't change). |
---|
| 9252 | + * |
---|
| 9253 | + * The btfw_path module parameter may be changed by the system at run |
---|
| 9254 | + * time. When it changes we need to copy it to dhdinfo->btfw_path. Also Android private |
---|
| 9255 | + * command may change dhdinfo->btfw_path. As such we need to clear the path info in |
---|
| 9256 | + * module parameter after it is copied. We won't update the path until the module parameter |
---|
| 9257 | + * is changed again (first character is not '\0') |
---|
| 9258 | + */ |
---|
| 9259 | + |
---|
| 9260 | + /* set default firmware and nvram path for built-in type driver */ |
---|
| 9261 | + if (!dhd_download_fw_on_driverload) { |
---|
| 9262 | +#ifdef CONFIG_BCMDHD_BTFW_PATH |
---|
| 9263 | + fw = CONFIG_BCMDHD_BTFW_PATH; |
---|
| 9264 | +#endif /* CONFIG_BCMDHD_FW_PATH */ |
---|
| 9265 | + } |
---|
| 9266 | + |
---|
| 9267 | + /* check if we need to initialize the path */ |
---|
| 9268 | + if (dhdinfo->btfw_path[0] == '\0') { |
---|
| 9269 | + if (adapter && adapter->btfw_path && adapter->btfw_path[0] != '\0') |
---|
| 9270 | + fw = adapter->btfw_path; |
---|
| 9271 | + } |
---|
| 9272 | + |
---|
| 9273 | + /* Use module parameter if it is valid, EVEN IF the path has not been initialized |
---|
| 9274 | + */ |
---|
| 9275 | + if (btfw_path[0] != '\0') |
---|
| 9276 | + fw = btfw_path; |
---|
| 9277 | + |
---|
| 9278 | + if (fw && fw[0] != '\0') { |
---|
| 9279 | + fw_len = strlen(fw); |
---|
| 9280 | + if (fw_len >= sizeof(dhdinfo->btfw_path)) { |
---|
| 9281 | + DHD_ERROR(("fw path len exceeds max len of dhdinfo->btfw_path\n")); |
---|
| 9282 | + return FALSE; |
---|
| 9283 | + } |
---|
| 9284 | + strncpy(dhdinfo->btfw_path, fw, sizeof(dhdinfo->btfw_path)); |
---|
| 9285 | + if (dhdinfo->btfw_path[fw_len-1] == '\n') |
---|
| 9286 | + dhdinfo->btfw_path[fw_len-1] = '\0'; |
---|
| 9287 | + } |
---|
| 9288 | + |
---|
| 9289 | + /* clear the path in module parameter */ |
---|
| 9290 | + btfw_path[0] = '\0'; |
---|
| 9291 | + |
---|
| 9292 | + if (dhdinfo->btfw_path[0] == '\0') { |
---|
| 9293 | + DHD_ERROR(("bt firmware path not found\n")); |
---|
| 9294 | + return FALSE; |
---|
| 9295 | + } |
---|
| 9296 | + |
---|
| 9297 | + return TRUE; |
---|
| 9298 | +} |
---|
| 9299 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
| 9300 | + |
---|
| 9301 | +#ifdef CUSTOMER_HW4_DEBUG |
---|
| 9302 | +bool dhd_validate_chipid(dhd_pub_t *dhdp) |
---|
| 9303 | +{ |
---|
| 9304 | + uint chipid = dhd_bus_chip_id(dhdp); |
---|
| 9305 | + uint config_chipid; |
---|
| 9306 | + |
---|
| 9307 | +#ifdef BCM4375_CHIP |
---|
| 9308 | + config_chipid = BCM4375_CHIP_ID; |
---|
| 9309 | +#elif defined(BCM4361_CHIP) |
---|
| 9310 | + config_chipid = BCM4361_CHIP_ID; |
---|
| 9311 | +#elif defined(BCM4359_CHIP) |
---|
| 9312 | + config_chipid = BCM4359_CHIP_ID; |
---|
| 9313 | +#elif defined(BCM4358_CHIP) |
---|
| 9314 | + config_chipid = BCM4358_CHIP_ID; |
---|
| 9315 | +#elif defined(BCM4354_CHIP) |
---|
| 9316 | + config_chipid = BCM4354_CHIP_ID; |
---|
| 9317 | +#elif defined(BCM4339_CHIP) |
---|
| 9318 | + config_chipid = BCM4339_CHIP_ID; |
---|
| 9319 | +#elif defined(BCM4335_CHIP) |
---|
| 9320 | + config_chipid = BCM4335_CHIP_ID; |
---|
| 9321 | +#elif defined(BCM43430_CHIP) |
---|
| 9322 | + config_chipid = BCM43430_CHIP_ID; |
---|
| 9323 | +#elif defined(BCM43018_CHIP) |
---|
| 9324 | + config_chipid = BCM43018_CHIP_ID; |
---|
| 9325 | +#elif defined(BCM43455_CHIP) |
---|
| 9326 | + config_chipid = BCM4345_CHIP_ID; |
---|
| 9327 | +#elif defined(BCM43454_CHIP) |
---|
| 9328 | + config_chipid = BCM43454_CHIP_ID; |
---|
| 9329 | +#elif defined(BCM43012_CHIP_) |
---|
| 9330 | + config_chipid = BCM43012_CHIP_ID; |
---|
| 9331 | +#else |
---|
| 9332 | + DHD_ERROR(("%s: Unknown chip id, if you use new chipset," |
---|
| 9333 | + " please add CONFIG_BCMXXXX into the Kernel and" |
---|
| 9334 | + " BCMXXXX_CHIP definition into the DHD driver\n", |
---|
| 9335 | + __FUNCTION__)); |
---|
| 9336 | + config_chipid = 0; |
---|
| 9337 | + |
---|
| 9338 | + return FALSE; |
---|
| 9339 | +#endif /* BCM4354_CHIP */ |
---|
| 9340 | + |
---|
| 9341 | +#if defined(BCM4354_CHIP) && defined(SUPPORT_MULTIPLE_REVISION) |
---|
| 9342 | + if (chipid == BCM4350_CHIP_ID && config_chipid == BCM4354_CHIP_ID) { |
---|
| 9343 | + return TRUE; |
---|
| 9344 | + } |
---|
| 9345 | +#endif /* BCM4354_CHIP && SUPPORT_MULTIPLE_REVISION */ |
---|
| 9346 | +#if defined(BCM4358_CHIP) && defined(SUPPORT_MULTIPLE_REVISION) |
---|
| 9347 | + if (chipid == BCM43569_CHIP_ID && config_chipid == BCM4358_CHIP_ID) { |
---|
| 9348 | + return TRUE; |
---|
| 9349 | + } |
---|
| 9350 | +#endif /* BCM4358_CHIP && SUPPORT_MULTIPLE_REVISION */ |
---|
| 9351 | +#if defined(BCM4359_CHIP) |
---|
| 9352 | + if (chipid == BCM4355_CHIP_ID && config_chipid == BCM4359_CHIP_ID) { |
---|
| 9353 | + return TRUE; |
---|
| 9354 | + } |
---|
| 9355 | +#endif /* BCM4359_CHIP */ |
---|
| 9356 | +#if defined(BCM4361_CHIP) |
---|
| 9357 | + if (chipid == BCM4347_CHIP_ID && config_chipid == BCM4361_CHIP_ID) { |
---|
| 9358 | + return TRUE; |
---|
| 9359 | + } |
---|
| 9360 | +#endif /* BCM4361_CHIP */ |
---|
| 9361 | + |
---|
| 9362 | + return config_chipid == chipid; |
---|
| 9363 | +} |
---|
| 9364 | +#endif /* CUSTOMER_HW4_DEBUG */ |
---|
| 9365 | + |
---|
| 9366 | +#if defined(BT_OVER_SDIO) |
---|
| 9367 | +wlan_bt_handle_t dhd_bt_get_pub_hndl(void) |
---|
| 9368 | +{ |
---|
| 9369 | + DHD_ERROR(("%s: g_dhd_pub %p\n", __FUNCTION__, g_dhd_pub)); |
---|
| 9370 | + /* assuming that dhd_pub_t type pointer is available from a global variable */ |
---|
| 9371 | + return (wlan_bt_handle_t) g_dhd_pub; |
---|
| 9372 | +} EXPORT_SYMBOL(dhd_bt_get_pub_hndl); |
---|
| 9373 | + |
---|
| 9374 | +int dhd_download_btfw(wlan_bt_handle_t handle, char* btfw_path) |
---|
| 9375 | +{ |
---|
| 9376 | + int ret = -1; |
---|
| 9377 | + dhd_pub_t *dhdp = (dhd_pub_t *)handle; |
---|
| 9378 | + dhd_info_t *dhd = (dhd_info_t*)dhdp->info; |
---|
| 9379 | + |
---|
| 9380 | + /* Download BT firmware image to the dongle */ |
---|
| 9381 | + if (dhd->pub.busstate == DHD_BUS_DATA && dhd_update_btfw_path(dhd, btfw_path)) { |
---|
| 9382 | + DHD_INFO(("%s: download btfw from: %s\n", __FUNCTION__, dhd->btfw_path)); |
---|
| 9383 | + ret = dhd_bus_download_btfw(dhd->pub.bus, dhd->pub.osh, dhd->btfw_path); |
---|
| 9384 | + if (ret < 0) { |
---|
| 9385 | + DHD_ERROR(("%s: failed to download btfw from: %s\n", |
---|
| 9386 | + __FUNCTION__, dhd->btfw_path)); |
---|
| 9387 | + return ret; |
---|
| 9388 | + } |
---|
| 9389 | + } |
---|
| 9390 | + return ret; |
---|
| 9391 | +} EXPORT_SYMBOL(dhd_download_btfw); |
---|
| 9392 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
7939 | 9393 | |
---|
7940 | 9394 | int |
---|
7941 | 9395 | dhd_bus_start(dhd_pub_t *dhdp) |
---|
.. | .. |
---|
7944 | 9398 | dhd_info_t *dhd = (dhd_info_t*)dhdp->info; |
---|
7945 | 9399 | unsigned long flags; |
---|
7946 | 9400 | |
---|
| 9401 | +#if defined(DHD_DEBUG) && defined(BCMSDIO) |
---|
| 9402 | + int fw_download_start = 0, fw_download_end = 0, f2_sync_start = 0, f2_sync_end = 0; |
---|
| 9403 | +#endif /* DHD_DEBUG && BCMSDIO */ |
---|
7947 | 9404 | ASSERT(dhd); |
---|
7948 | 9405 | |
---|
7949 | 9406 | DHD_TRACE(("Enter %s:\n", __FUNCTION__)); |
---|
| 9407 | + dhdp->dongle_trap_occured = 0; |
---|
| 9408 | +#ifdef DHD_SSSR_DUMP |
---|
| 9409 | + /* Flag to indicate sssr dump is collected */ |
---|
| 9410 | + dhdp->sssr_dump_collected = 0; |
---|
| 9411 | +#endif /* DHD_SSSR_DUMP */ |
---|
| 9412 | + dhdp->iovar_timeout_occured = 0; |
---|
| 9413 | +#ifdef PCIE_FULL_DONGLE |
---|
| 9414 | + dhdp->d3ack_timeout_occured = 0; |
---|
| 9415 | + dhdp->livelock_occured = 0; |
---|
| 9416 | + dhdp->pktid_audit_failed = 0; |
---|
| 9417 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 9418 | + dhd->pub.iface_op_failed = 0; |
---|
| 9419 | + dhd->pub.scan_timeout_occurred = 0; |
---|
| 9420 | + dhd->pub.scan_busy_occurred = 0; |
---|
| 9421 | + /* Clear induced error during initialize */ |
---|
| 9422 | + dhd->pub.dhd_induce_error = DHD_INDUCE_ERROR_CLEAR; |
---|
| 9423 | + |
---|
| 9424 | + /* set default value for now. Will be updated again in dhd_preinit_ioctls() |
---|
| 9425 | + * after querying FW |
---|
| 9426 | + */ |
---|
| 9427 | + dhdp->event_log_max_sets = NUM_EVENT_LOG_SETS; |
---|
| 9428 | + dhdp->event_log_max_sets_queried = FALSE; |
---|
| 9429 | + dhdp->smmu_fault_occurred = 0; |
---|
| 9430 | +#ifdef DNGL_AXI_ERROR_LOGGING |
---|
| 9431 | + dhdp->axi_error = FALSE; |
---|
| 9432 | +#endif /* DNGL_AXI_ERROR_LOGGING */ |
---|
7950 | 9433 | |
---|
7951 | 9434 | DHD_PERIM_LOCK(dhdp); |
---|
7952 | | - |
---|
7953 | 9435 | /* try to download image and nvram to the dongle */ |
---|
7954 | 9436 | if (dhd->pub.busstate == DHD_BUS_DOWN && dhd_update_fw_nv_path(dhd)) { |
---|
| 9437 | + /* Indicate FW Download has not yet done */ |
---|
| 9438 | + dhd->pub.fw_download_status = FW_DOWNLOAD_IN_PROGRESS; |
---|
7955 | 9439 | DHD_INFO(("%s download fw %s, nv %s\n", __FUNCTION__, dhd->fw_path, dhd->nv_path)); |
---|
| 9440 | +#if defined(DHD_DEBUG) && defined(BCMSDIO) |
---|
| 9441 | + fw_download_start = OSL_SYSUPTIME(); |
---|
| 9442 | +#endif /* DHD_DEBUG && BCMSDIO */ |
---|
7956 | 9443 | ret = dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh, |
---|
7957 | 9444 | dhd->fw_path, dhd->nv_path); |
---|
| 9445 | +#if defined(DHD_DEBUG) && defined(BCMSDIO) |
---|
| 9446 | + fw_download_end = OSL_SYSUPTIME(); |
---|
| 9447 | +#endif /* DHD_DEBUG && BCMSDIO */ |
---|
7958 | 9448 | if (ret < 0) { |
---|
7959 | 9449 | DHD_ERROR(("%s: failed to download firmware %s\n", |
---|
7960 | 9450 | __FUNCTION__, dhd->fw_path)); |
---|
.. | .. |
---|
7962 | 9452 | return ret; |
---|
7963 | 9453 | } |
---|
7964 | 9454 | /* Indicate FW Download has succeeded */ |
---|
7965 | | - dhd_fw_downloaded = TRUE; |
---|
| 9455 | + dhd->pub.fw_download_status = FW_DOWNLOAD_DONE; |
---|
7966 | 9456 | } |
---|
7967 | 9457 | if (dhd->pub.busstate != DHD_BUS_LOAD) { |
---|
7968 | 9458 | DHD_PERIM_UNLOCK(dhdp); |
---|
7969 | 9459 | return -ENETDOWN; |
---|
7970 | 9460 | } |
---|
7971 | 9461 | |
---|
| 9462 | +#ifdef BCMSDIO |
---|
7972 | 9463 | dhd_os_sdlock(dhdp); |
---|
| 9464 | +#endif /* BCMSDIO */ |
---|
7973 | 9465 | |
---|
7974 | 9466 | /* Start the watchdog timer */ |
---|
7975 | 9467 | dhd->pub.tickcnt = 0; |
---|
.. | .. |
---|
7979 | 9471 | if ((ret = dhd_bus_init(&dhd->pub, FALSE)) != 0) { |
---|
7980 | 9472 | |
---|
7981 | 9473 | DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret)); |
---|
| 9474 | +#ifdef BCMSDIO |
---|
7982 | 9475 | dhd_os_sdunlock(dhdp); |
---|
| 9476 | +#endif /* BCMSDIO */ |
---|
7983 | 9477 | DHD_PERIM_UNLOCK(dhdp); |
---|
7984 | 9478 | return ret; |
---|
7985 | 9479 | } |
---|
7986 | 9480 | |
---|
| 9481 | + DHD_ENABLE_RUNTIME_PM(&dhd->pub); |
---|
| 9482 | + |
---|
7987 | 9483 | #ifdef DHD_ULP |
---|
7988 | 9484 | dhd_ulp_set_ulp_state(dhdp, DHD_ULP_DISABLED); |
---|
7989 | 9485 | #endif /* DHD_ULP */ |
---|
7990 | | -#if defined(OOB_INTR_ONLY) || defined(BCMPCIE_OOB_HOST_WAKE) |
---|
7991 | | -#if defined(BCMPCIE_OOB_HOST_WAKE) |
---|
7992 | | - dhd_os_sdunlock(dhdp); |
---|
7993 | | -#endif /* BCMPCIE_OOB_HOST_WAKE */ |
---|
| 9486 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) || defined(BCMPCIE_OOB_HOST_WAKE) |
---|
7994 | 9487 | /* Host registration for OOB interrupt */ |
---|
7995 | 9488 | if (dhd_bus_oob_intr_register(dhdp)) { |
---|
7996 | 9489 | /* deactivate timer and wait for the handler to finish */ |
---|
.. | .. |
---|
8000 | 9493 | DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
8001 | 9494 | del_timer_sync(&dhd->timer); |
---|
8002 | 9495 | |
---|
8003 | | - dhd_os_sdunlock(dhdp); |
---|
8004 | 9496 | #endif /* !BCMPCIE_OOB_HOST_WAKE */ |
---|
| 9497 | + DHD_DISABLE_RUNTIME_PM(&dhd->pub); |
---|
8005 | 9498 | DHD_PERIM_UNLOCK(dhdp); |
---|
8006 | 9499 | DHD_ERROR(("%s Host failed to register for OOB\n", __FUNCTION__)); |
---|
| 9500 | + DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); |
---|
8007 | 9501 | return -ENODEV; |
---|
8008 | 9502 | } |
---|
8009 | 9503 | |
---|
8010 | 9504 | #if defined(BCMPCIE_OOB_HOST_WAKE) |
---|
8011 | | - dhd_os_sdlock(dhdp); |
---|
8012 | 9505 | dhd_bus_oob_intr_set(dhdp, TRUE); |
---|
8013 | 9506 | #else |
---|
8014 | 9507 | /* Enable oob at firmware */ |
---|
8015 | 9508 | dhd_enable_oob_intr(dhd->pub.bus, TRUE); |
---|
8016 | 9509 | #endif /* BCMPCIE_OOB_HOST_WAKE */ |
---|
8017 | | -#endif |
---|
| 9510 | +#endif /* OOB_INTR_ONLY || BCMSPI_ANDROID || BCMPCIE_OOB_HOST_WAKE */ |
---|
8018 | 9511 | #ifdef PCIE_FULL_DONGLE |
---|
8019 | 9512 | { |
---|
8020 | 9513 | /* max_h2d_rings includes H2D common rings */ |
---|
.. | .. |
---|
8023 | 9516 | DHD_ERROR(("%s: Initializing %u h2drings\n", __FUNCTION__, |
---|
8024 | 9517 | max_h2d_rings)); |
---|
8025 | 9518 | if ((ret = dhd_flow_rings_init(&dhd->pub, max_h2d_rings)) != BCME_OK) { |
---|
| 9519 | +#ifdef BCMSDIO |
---|
8026 | 9520 | dhd_os_sdunlock(dhdp); |
---|
| 9521 | +#endif /* BCMSDIO */ |
---|
8027 | 9522 | DHD_PERIM_UNLOCK(dhdp); |
---|
8028 | 9523 | return ret; |
---|
8029 | 9524 | } |
---|
.. | .. |
---|
8031 | 9526 | #endif /* PCIE_FULL_DONGLE */ |
---|
8032 | 9527 | |
---|
8033 | 9528 | /* Do protocol initialization necessary for IOCTL/IOVAR */ |
---|
8034 | | -#ifdef PCIE_FULL_DONGLE |
---|
8035 | | - dhd_os_sdunlock(dhdp); |
---|
8036 | | -#endif /* PCIE_FULL_DONGLE */ |
---|
8037 | 9529 | ret = dhd_prot_init(&dhd->pub); |
---|
8038 | 9530 | if (unlikely(ret) != BCME_OK) { |
---|
8039 | 9531 | DHD_PERIM_UNLOCK(dhdp); |
---|
| 9532 | + DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); |
---|
8040 | 9533 | return ret; |
---|
8041 | 9534 | } |
---|
8042 | | -#ifdef PCIE_FULL_DONGLE |
---|
8043 | | - dhd_os_sdlock(dhdp); |
---|
8044 | | -#endif /* PCIE_FULL_DONGLE */ |
---|
8045 | 9535 | |
---|
8046 | 9536 | /* If bus is not ready, can't come up */ |
---|
8047 | 9537 | if (dhd->pub.busstate != DHD_BUS_DATA) { |
---|
.. | .. |
---|
8050 | 9540 | DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
8051 | 9541 | del_timer_sync(&dhd->timer); |
---|
8052 | 9542 | DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__)); |
---|
| 9543 | + DHD_DISABLE_RUNTIME_PM(&dhd->pub); |
---|
| 9544 | +#ifdef BCMSDIO |
---|
8053 | 9545 | dhd_os_sdunlock(dhdp); |
---|
| 9546 | +#endif /* BCMSDIO */ |
---|
8054 | 9547 | DHD_PERIM_UNLOCK(dhdp); |
---|
| 9548 | + DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); |
---|
8055 | 9549 | return -ENODEV; |
---|
8056 | 9550 | } |
---|
8057 | 9551 | |
---|
| 9552 | +#ifdef BCMSDIO |
---|
8058 | 9553 | dhd_os_sdunlock(dhdp); |
---|
8059 | | - |
---|
8060 | | -#ifdef HOST_FLAG |
---|
8061 | | - { |
---|
8062 | | - int enable = 0; |
---|
8063 | | - if (dhd_wl_ioctl_set_intiovar(dhdp, "hostsleep", enable, WLC_SET_VAR, TRUE, 0)) { |
---|
8064 | | - DHD_ERROR(("%s: Failed to set hostsleep 0\n", __FUNCTION__)); |
---|
8065 | | - } |
---|
8066 | | - } |
---|
8067 | | -#endif /* HOST_FLAG */ |
---|
| 9554 | +#endif /* BCMSDIO */ |
---|
8068 | 9555 | |
---|
8069 | 9556 | /* Bus is ready, query any dongle information */ |
---|
| 9557 | +#if defined(DHD_DEBUG) && defined(BCMSDIO) |
---|
| 9558 | + f2_sync_start = OSL_SYSUPTIME(); |
---|
| 9559 | +#endif /* DHD_DEBUG && BCMSDIO */ |
---|
8070 | 9560 | if ((ret = dhd_sync_with_dongle(&dhd->pub)) < 0) { |
---|
8071 | 9561 | DHD_GENERAL_LOCK(&dhd->pub, flags); |
---|
8072 | 9562 | dhd->wd_timer_valid = FALSE; |
---|
8073 | 9563 | DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
8074 | 9564 | del_timer_sync(&dhd->timer); |
---|
8075 | 9565 | DHD_ERROR(("%s failed to sync with dongle\n", __FUNCTION__)); |
---|
| 9566 | + DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); |
---|
8076 | 9567 | DHD_PERIM_UNLOCK(dhdp); |
---|
8077 | 9568 | return ret; |
---|
8078 | 9569 | } |
---|
| 9570 | + |
---|
| 9571 | +#if defined(CONFIG_SOC_EXYNOS8895) || defined(CONFIG_SOC_EXYNOS9810) || \ |
---|
| 9572 | + defined(CONFIG_SOC_EXYNOS9820) |
---|
| 9573 | + DHD_ERROR(("%s: Enable L1ss EP side\n", __FUNCTION__)); |
---|
| 9574 | + exynos_pcie_l1ss_ctrl(1, PCIE_L1SS_CTRL_WIFI); |
---|
| 9575 | +#endif /* CONFIG_SOC_EXYNOS8895 || CONFIG_SOC_EXYNOS9810 || CONFIG_SOC_EXYNOS9820 */ |
---|
| 9576 | + |
---|
| 9577 | +#if defined(DHD_DEBUG) && defined(BCMSDIO) |
---|
| 9578 | + f2_sync_end = OSL_SYSUPTIME(); |
---|
| 9579 | + DHD_ERROR(("Time taken for FW download and F2 ready is: %d msec\n", |
---|
| 9580 | + (fw_download_end - fw_download_start) + (f2_sync_end - f2_sync_start))); |
---|
| 9581 | +#endif /* DHD_DEBUG && BCMSDIO */ |
---|
8079 | 9582 | |
---|
8080 | 9583 | #ifdef ARP_OFFLOAD_SUPPORT |
---|
8081 | 9584 | if (dhd->pend_ipaddr) { |
---|
.. | .. |
---|
8086 | 9589 | } |
---|
8087 | 9590 | #endif /* ARP_OFFLOAD_SUPPORT */ |
---|
8088 | 9591 | |
---|
8089 | | -#if defined(TRAFFIC_MGMT_DWM) |
---|
8090 | | - bzero(&dhd->pub.dhd_tm_dwm_tbl, sizeof(dhd_trf_mgmt_dwm_tbl_t)); |
---|
8091 | | -#endif |
---|
8092 | 9592 | DHD_PERIM_UNLOCK(dhdp); |
---|
| 9593 | + |
---|
8093 | 9594 | return 0; |
---|
8094 | 9595 | } |
---|
8095 | | -#endif /* BCMDBUS */ |
---|
8096 | 9596 | #ifdef WLTDLS |
---|
8097 | 9597 | int _dhd_tdls_enable(dhd_pub_t *dhd, bool tdls_on, bool auto_on, struct ether_addr *mac) |
---|
8098 | 9598 | { |
---|
.. | .. |
---|
8102 | 9602 | uint32 tdls_idle_time = CUSTOM_TDLS_IDLE_MODE_SETTING; |
---|
8103 | 9603 | int32 tdls_rssi_high = CUSTOM_TDLS_RSSI_THRESHOLD_HIGH; |
---|
8104 | 9604 | int32 tdls_rssi_low = CUSTOM_TDLS_RSSI_THRESHOLD_LOW; |
---|
| 9605 | + uint32 tdls_pktcnt_high = CUSTOM_TDLS_PCKTCNT_THRESHOLD_HIGH; |
---|
| 9606 | + uint32 tdls_pktcnt_low = CUSTOM_TDLS_PCKTCNT_THRESHOLD_LOW; |
---|
| 9607 | + |
---|
8105 | 9608 | BCM_REFERENCE(mac); |
---|
8106 | 9609 | if (!FW_SUPPORTED(dhd, tdls)) |
---|
8107 | 9610 | return BCME_ERROR; |
---|
.. | .. |
---|
8143 | 9646 | DHD_ERROR(("%s: tdls_rssi_low failed %d\n", __FUNCTION__, ret)); |
---|
8144 | 9647 | goto exit; |
---|
8145 | 9648 | } |
---|
| 9649 | + ret = dhd_iovar(dhd, 0, "tdls_trigger_pktcnt_high", (char *)&tdls_pktcnt_high, |
---|
| 9650 | + sizeof(tdls_pktcnt_high), NULL, 0, TRUE); |
---|
| 9651 | + if (ret < 0) { |
---|
| 9652 | + DHD_ERROR(("%s: tdls_trigger_pktcnt_high failed %d\n", __FUNCTION__, ret)); |
---|
| 9653 | + goto exit; |
---|
| 9654 | + } |
---|
| 9655 | + ret = dhd_iovar(dhd, 0, "tdls_trigger_pktcnt_low", (char *)&tdls_pktcnt_low, |
---|
| 9656 | + sizeof(tdls_pktcnt_low), NULL, 0, TRUE); |
---|
| 9657 | + if (ret < 0) { |
---|
| 9658 | + DHD_ERROR(("%s: tdls_trigger_pktcnt_low failed %d\n", __FUNCTION__, ret)); |
---|
| 9659 | + goto exit; |
---|
| 9660 | + } |
---|
8146 | 9661 | } |
---|
8147 | 9662 | |
---|
8148 | 9663 | exit: |
---|
.. | .. |
---|
8165 | 9680 | bool auto_on = false; |
---|
8166 | 9681 | uint32 mode = wfd_mode; |
---|
8167 | 9682 | |
---|
| 9683 | +#ifdef ENABLE_TDLS_AUTO_MODE |
---|
| 9684 | + if (wfd_mode) { |
---|
| 9685 | + auto_on = false; |
---|
| 9686 | + } else { |
---|
| 9687 | + auto_on = true; |
---|
| 9688 | + } |
---|
| 9689 | +#else |
---|
8168 | 9690 | auto_on = false; |
---|
| 9691 | +#endif /* ENABLE_TDLS_AUTO_MODE */ |
---|
8169 | 9692 | ret = _dhd_tdls_enable(dhd, false, auto_on, NULL); |
---|
8170 | 9693 | if (ret < 0) { |
---|
8171 | 9694 | DHD_ERROR(("Disable tdls_auto_op failed. %d\n", ret)); |
---|
.. | .. |
---|
8188 | 9711 | return ret; |
---|
8189 | 9712 | } |
---|
8190 | 9713 | #ifdef PCIE_FULL_DONGLE |
---|
8191 | | -void dhd_tdls_update_peer_info(struct net_device *dev, bool connect, uint8 *da) |
---|
| 9714 | +int dhd_tdls_update_peer_info(dhd_pub_t *dhdp, wl_event_msg_t *event) |
---|
8192 | 9715 | { |
---|
8193 | | - dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
8194 | | - dhd_pub_t *dhdp = (dhd_pub_t *)&dhd->pub; |
---|
8195 | | - tdls_peer_node_t *cur = dhdp->peer_tbl.node; |
---|
| 9716 | + dhd_pub_t *dhd_pub = dhdp; |
---|
| 9717 | + tdls_peer_node_t *cur = dhd_pub->peer_tbl.node; |
---|
8196 | 9718 | tdls_peer_node_t *new = NULL, *prev = NULL; |
---|
8197 | | - dhd_if_t *dhdif; |
---|
8198 | | - uint8 sa[ETHER_ADDR_LEN]; |
---|
8199 | | - int ifidx = dhd_net2idx(dhd, dev); |
---|
| 9719 | + int ifindex = dhd_ifname2idx(dhd_pub->info, event->ifname); |
---|
| 9720 | + uint8 *da = (uint8 *)&event->addr.octet[0]; |
---|
| 9721 | + bool connect = FALSE; |
---|
| 9722 | + uint32 reason = ntoh32(event->reason); |
---|
| 9723 | + unsigned long flags; |
---|
8200 | 9724 | |
---|
8201 | | - if (ifidx == DHD_BAD_IF) |
---|
8202 | | - return; |
---|
8203 | | - |
---|
8204 | | - dhdif = dhd->iflist[ifidx]; |
---|
8205 | | - memcpy(sa, dhdif->mac_addr, ETHER_ADDR_LEN); |
---|
| 9725 | + /* No handling needed for peer discovered reason */ |
---|
| 9726 | + if (reason == WLC_E_TDLS_PEER_DISCOVERED) { |
---|
| 9727 | + return BCME_ERROR; |
---|
| 9728 | + } |
---|
| 9729 | + if (reason == WLC_E_TDLS_PEER_CONNECTED) |
---|
| 9730 | + connect = TRUE; |
---|
| 9731 | + else if (reason == WLC_E_TDLS_PEER_DISCONNECTED) |
---|
| 9732 | + connect = FALSE; |
---|
| 9733 | + else |
---|
| 9734 | + { |
---|
| 9735 | + DHD_ERROR(("%s: TDLS Event reason is unknown\n", __FUNCTION__)); |
---|
| 9736 | + return BCME_ERROR; |
---|
| 9737 | + } |
---|
| 9738 | + if (ifindex == DHD_BAD_IF) |
---|
| 9739 | + return BCME_ERROR; |
---|
8206 | 9740 | |
---|
8207 | 9741 | if (connect) { |
---|
8208 | 9742 | while (cur != NULL) { |
---|
8209 | 9743 | if (!memcmp(da, cur->addr, ETHER_ADDR_LEN)) { |
---|
8210 | 9744 | DHD_ERROR(("%s: TDLS Peer exist already %d\n", |
---|
8211 | 9745 | __FUNCTION__, __LINE__)); |
---|
8212 | | - return; |
---|
| 9746 | + return BCME_ERROR; |
---|
8213 | 9747 | } |
---|
8214 | 9748 | cur = cur->next; |
---|
8215 | 9749 | } |
---|
8216 | 9750 | |
---|
8217 | | - new = MALLOC(dhdp->osh, sizeof(tdls_peer_node_t)); |
---|
| 9751 | + new = MALLOC(dhd_pub->osh, sizeof(tdls_peer_node_t)); |
---|
8218 | 9752 | if (new == NULL) { |
---|
8219 | 9753 | DHD_ERROR(("%s: Failed to allocate memory\n", __FUNCTION__)); |
---|
8220 | | - return; |
---|
| 9754 | + return BCME_ERROR; |
---|
8221 | 9755 | } |
---|
8222 | 9756 | memcpy(new->addr, da, ETHER_ADDR_LEN); |
---|
8223 | | - new->next = dhdp->peer_tbl.node; |
---|
8224 | | - dhdp->peer_tbl.node = new; |
---|
8225 | | - dhdp->peer_tbl.tdls_peer_count++; |
---|
| 9757 | + DHD_TDLS_LOCK(&dhdp->tdls_lock, flags); |
---|
| 9758 | + new->next = dhd_pub->peer_tbl.node; |
---|
| 9759 | + dhd_pub->peer_tbl.node = new; |
---|
| 9760 | + dhd_pub->peer_tbl.tdls_peer_count++; |
---|
| 9761 | + DHD_TDLS_UNLOCK(&dhdp->tdls_lock, flags); |
---|
8226 | 9762 | |
---|
8227 | 9763 | } else { |
---|
8228 | 9764 | while (cur != NULL) { |
---|
8229 | 9765 | if (!memcmp(da, cur->addr, ETHER_ADDR_LEN)) { |
---|
8230 | | - dhd_flow_rings_delete_for_peer(dhdp, ifidx, da); |
---|
| 9766 | + dhd_flow_rings_delete_for_peer(dhd_pub, (uint8)ifindex, da); |
---|
| 9767 | + DHD_TDLS_LOCK(&dhdp->tdls_lock, flags); |
---|
8231 | 9768 | if (prev) |
---|
8232 | 9769 | prev->next = cur->next; |
---|
8233 | 9770 | else |
---|
8234 | | - dhdp->peer_tbl.node = cur->next; |
---|
8235 | | - MFREE(dhdp->osh, cur, sizeof(tdls_peer_node_t)); |
---|
8236 | | - dhdp->peer_tbl.tdls_peer_count--; |
---|
8237 | | - return; |
---|
| 9771 | + dhd_pub->peer_tbl.node = cur->next; |
---|
| 9772 | + MFREE(dhd_pub->osh, cur, sizeof(tdls_peer_node_t)); |
---|
| 9773 | + dhd_pub->peer_tbl.tdls_peer_count--; |
---|
| 9774 | + DHD_TDLS_UNLOCK(&dhdp->tdls_lock, flags); |
---|
| 9775 | + return BCME_OK; |
---|
8238 | 9776 | } |
---|
8239 | 9777 | prev = cur; |
---|
8240 | 9778 | cur = cur->next; |
---|
8241 | 9779 | } |
---|
8242 | 9780 | DHD_ERROR(("%s: TDLS Peer Entry Not found\n", __FUNCTION__)); |
---|
8243 | 9781 | } |
---|
| 9782 | + return BCME_OK; |
---|
8244 | 9783 | } |
---|
8245 | 9784 | #endif /* PCIE_FULL_DONGLE */ |
---|
8246 | | -#endif /* BCMDBUS */ |
---|
| 9785 | +#endif // endif |
---|
8247 | 9786 | |
---|
8248 | 9787 | bool dhd_is_concurrent_mode(dhd_pub_t *dhd) |
---|
8249 | 9788 | { |
---|
.. | .. |
---|
8258 | 9797 | else |
---|
8259 | 9798 | return FALSE; |
---|
8260 | 9799 | } |
---|
8261 | | -#if !defined(AP) && defined(WLP2P) |
---|
| 9800 | +#if defined(OEM_ANDROID) && !defined(AP) && defined(WLP2P) |
---|
8262 | 9801 | /* From Android JerryBean release, the concurrent mode is enabled by default and the firmware |
---|
8263 | 9802 | * name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA |
---|
8264 | 9803 | * firmware and accordingly enable concurrent mode (Apply P2P settings). SoftAP firmware |
---|
.. | .. |
---|
8300 | 9839 | if (FW_SUPPORTED(dhd, rsdb)) { |
---|
8301 | 9840 | ret |= DHD_FLAG_RSDB_MODE; |
---|
8302 | 9841 | } |
---|
| 9842 | +#ifdef WL_SUPPORT_MULTIP2P |
---|
8303 | 9843 | if (FW_SUPPORTED(dhd, mp2p)) { |
---|
8304 | 9844 | ret |= DHD_FLAG_MP2P_MODE; |
---|
8305 | 9845 | } |
---|
| 9846 | +#endif /* WL_SUPPORT_MULTIP2P */ |
---|
8306 | 9847 | #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF) |
---|
8307 | | - /* For customer_hw4, although ICS, |
---|
8308 | | - * we still support concurrent mode |
---|
8309 | | - */ |
---|
8310 | 9848 | return ret; |
---|
8311 | 9849 | #else |
---|
8312 | 9850 | return 0; |
---|
8313 | | -#endif |
---|
| 9851 | +#endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */ |
---|
8314 | 9852 | } |
---|
8315 | 9853 | } |
---|
8316 | 9854 | } |
---|
8317 | 9855 | return 0; |
---|
8318 | 9856 | } |
---|
8319 | | -#endif |
---|
| 9857 | +#endif /* defined(OEM_ANDROID) && !defined(AP) && defined(WLP2P) */ |
---|
8320 | 9858 | |
---|
8321 | | -#ifdef SUPPORT_AP_POWERSAVE |
---|
8322 | | -#define RXCHAIN_PWRSAVE_PPS 10 |
---|
8323 | | -#define RXCHAIN_PWRSAVE_QUIET_TIME 10 |
---|
8324 | | -#define RXCHAIN_PWRSAVE_STAS_ASSOC_CHECK 0 |
---|
8325 | | -int dhd_set_ap_powersave(dhd_pub_t *dhdp, int ifidx, int enable) |
---|
| 9859 | +#ifdef WLAIBSS |
---|
| 9860 | +int |
---|
| 9861 | +dhd_preinit_aibss_ioctls(dhd_pub_t *dhd, char *iov_buf_smlen) |
---|
8326 | 9862 | { |
---|
8327 | | - char iovbuf[128]; |
---|
8328 | | - int32 pps = RXCHAIN_PWRSAVE_PPS; |
---|
8329 | | - int32 quiet_time = RXCHAIN_PWRSAVE_QUIET_TIME; |
---|
8330 | | - int32 stas_assoc_check = RXCHAIN_PWRSAVE_STAS_ASSOC_CHECK; |
---|
8331 | | - int ret; |
---|
| 9863 | + int ret = BCME_OK; |
---|
| 9864 | + aibss_bcn_force_config_t bcn_config; |
---|
| 9865 | + uint32 aibss; |
---|
| 9866 | +#ifdef WLAIBSS_PS |
---|
| 9867 | + uint32 aibss_ps; |
---|
| 9868 | + s32 atim; |
---|
| 9869 | +#endif /* WLAIBSS_PS */ |
---|
| 9870 | + int ibss_coalesce; |
---|
8332 | 9871 | |
---|
8333 | | - if (enable) { |
---|
8334 | | - ret = dhd_iovar(dhdp, 0, "rxchain_pwrsave_enable", (char *)&enable, sizeof(enable), |
---|
8335 | | - NULL, 0, TRUE); |
---|
8336 | | - if (ret != BCME_OK) { |
---|
8337 | | - DHD_ERROR(("Failed to enable AP power save")); |
---|
8338 | | - } |
---|
8339 | | - ret = dhd_iovar(dhdp, 0, "rxchain_pwrsave_pps", (char *)&pps, sizeof(pps), NULL, 0, |
---|
8340 | | - TRUE); |
---|
8341 | | - if (ret != BCME_OK) { |
---|
8342 | | - DHD_ERROR(("Failed to set pps")); |
---|
8343 | | - } |
---|
8344 | | - ret = dhd_iovar(dhdp, 0, "rxchain_pwrsave_quiet_time", (char *)&quiet_time, |
---|
8345 | | - sizeof(quiet_time), NULL, 0, TRUE); |
---|
8346 | | - if (ret != BCME_OK) { |
---|
8347 | | - DHD_ERROR(("Failed to set quiet time")); |
---|
8348 | | - } |
---|
8349 | | - ret = dhd_iovar(dhdp., 0, "rxchain_pwrsave_stas_assoc_check", |
---|
8350 | | - (char *)&stas_assoc_check, sizeof(stas_assoc_check), NULL, 0, TRUE); |
---|
8351 | | - if (ret != BCME_OK) { |
---|
8352 | | - DHD_ERROR(("Failed to set stas assoc check")); |
---|
8353 | | - } |
---|
8354 | | - } else { |
---|
8355 | | - ret = dhd_iovar(dhdp, 0, "rxchain_pwrsave_enable", (char *)&enable, sizeof(enable), |
---|
8356 | | - NULL, 0, TRUE); |
---|
8357 | | - if (ret != BCME_OK) { |
---|
8358 | | - DHD_ERROR(("Failed to disable AP power save")); |
---|
| 9872 | + aibss = 1; |
---|
| 9873 | + ret = dhd_iovar(dhd, 0, "aibss", (char *)&aibss, sizeof(aibss), NULL, 0, TRUE); |
---|
| 9874 | + if (ret < 0) { |
---|
| 9875 | + if (ret == BCME_UNSUPPORTED) { |
---|
| 9876 | + DHD_ERROR(("%s aibss is not supported\n", |
---|
| 9877 | + __FUNCTION__)); |
---|
| 9878 | + return BCME_OK; |
---|
| 9879 | + } else { |
---|
| 9880 | + DHD_ERROR(("%s Set aibss to %d failed %d\n", |
---|
| 9881 | + __FUNCTION__, aibss, ret)); |
---|
| 9882 | + return ret; |
---|
8359 | 9883 | } |
---|
8360 | 9884 | } |
---|
8361 | 9885 | |
---|
8362 | | - return 0; |
---|
| 9886 | +#ifdef WLAIBSS_PS |
---|
| 9887 | + aibss_ps = 1; |
---|
| 9888 | + ret = dhd_iovar(dhd, 0, "aibss_ps", (char *)&aibss_ps, sizeof(aibss_ps), NULL, 0, TRUE); |
---|
| 9889 | + if (ret < 0) { |
---|
| 9890 | + DHD_ERROR(("%s Set aibss PS to %d failed %d\n", |
---|
| 9891 | + __FUNCTION__, aibss, ret)); |
---|
| 9892 | + return ret; |
---|
| 9893 | + } |
---|
| 9894 | + |
---|
| 9895 | + atim = 10; |
---|
| 9896 | + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ATIM, |
---|
| 9897 | + (char *)&atim, sizeof(atim), TRUE, 0)) < 0) { |
---|
| 9898 | + DHD_ERROR(("%s Enable custom IBSS ATIM mode failed %d\n", |
---|
| 9899 | + __FUNCTION__, ret)); |
---|
| 9900 | + return ret; |
---|
| 9901 | + } |
---|
| 9902 | +#endif /* WLAIBSS_PS */ |
---|
| 9903 | + |
---|
| 9904 | + memset(&bcn_config, 0, sizeof(bcn_config)); |
---|
| 9905 | + bcn_config.initial_min_bcn_dur = AIBSS_INITIAL_MIN_BCN_DUR; |
---|
| 9906 | + bcn_config.min_bcn_dur = AIBSS_MIN_BCN_DUR; |
---|
| 9907 | + bcn_config.bcn_flood_dur = AIBSS_BCN_FLOOD_DUR; |
---|
| 9908 | + bcn_config.version = AIBSS_BCN_FORCE_CONFIG_VER_0; |
---|
| 9909 | + bcn_config.len = sizeof(bcn_config); |
---|
| 9910 | + |
---|
| 9911 | + ret = dhd_iovar(dhd, 0, "aibss_bcn_force_config", (char *)&bcn_config, |
---|
| 9912 | + sizeof(aibss_bcn_force_config_t), NULL, 0, TRUE); |
---|
| 9913 | + if (ret < 0) { |
---|
| 9914 | + DHD_ERROR(("%s Set aibss_bcn_force_config to %d, %d, %d failed %d\n", |
---|
| 9915 | + __FUNCTION__, AIBSS_INITIAL_MIN_BCN_DUR, AIBSS_MIN_BCN_DUR, |
---|
| 9916 | + AIBSS_BCN_FLOOD_DUR, ret)); |
---|
| 9917 | + return ret; |
---|
| 9918 | + } |
---|
| 9919 | + |
---|
| 9920 | + ibss_coalesce = IBSS_COALESCE_DEFAULT; |
---|
| 9921 | + ret = dhd_iovar(dhd, 0, "ibss_coalesce_allowed", (char *)&ibss_coalesce, |
---|
| 9922 | + sizeof(ibss_coalesce), NULL, 0, TRUE); |
---|
| 9923 | + if (ret < 0) { |
---|
| 9924 | + DHD_ERROR(("%s Set ibss_coalesce_allowed failed %d\n", |
---|
| 9925 | + __FUNCTION__, ret)); |
---|
| 9926 | + return ret; |
---|
| 9927 | + } |
---|
| 9928 | + |
---|
| 9929 | + dhd->op_mode |= DHD_FLAG_IBSS_MODE; |
---|
| 9930 | + return BCME_OK; |
---|
8363 | 9931 | } |
---|
8364 | | -#endif /* SUPPORT_AP_POWERSAVE */ |
---|
| 9932 | +#endif /* WLAIBSS */ |
---|
| 9933 | + |
---|
| 9934 | +#if defined(WLADPS) || defined(WLADPS_PRIVATE_CMD) |
---|
| 9935 | +#ifdef WL_BAM |
---|
| 9936 | +static int |
---|
| 9937 | +dhd_check_adps_bad_ap(dhd_pub_t *dhd) |
---|
| 9938 | +{ |
---|
| 9939 | + struct net_device *ndev; |
---|
| 9940 | + struct bcm_cfg80211 *cfg; |
---|
| 9941 | + struct wl_profile *profile; |
---|
| 9942 | + struct ether_addr bssid; |
---|
| 9943 | + |
---|
| 9944 | + if (!dhd_is_associated(dhd, 0, NULL)) { |
---|
| 9945 | + DHD_ERROR(("%s - not associated\n", __FUNCTION__)); |
---|
| 9946 | + return BCME_OK; |
---|
| 9947 | + } |
---|
| 9948 | + |
---|
| 9949 | + ndev = dhd_linux_get_primary_netdev(dhd); |
---|
| 9950 | + if (!ndev) { |
---|
| 9951 | + DHD_ERROR(("%s: Cannot find primary netdev\n", __FUNCTION__)); |
---|
| 9952 | + return -ENODEV; |
---|
| 9953 | + } |
---|
| 9954 | + |
---|
| 9955 | + cfg = wl_get_cfg(ndev); |
---|
| 9956 | + if (!cfg) { |
---|
| 9957 | + DHD_ERROR(("%s: Cannot find cfg\n", __FUNCTION__)); |
---|
| 9958 | + return -EINVAL; |
---|
| 9959 | + } |
---|
| 9960 | + |
---|
| 9961 | + profile = wl_get_profile_by_netdev(cfg, ndev); |
---|
| 9962 | + memcpy(bssid.octet, profile->bssid, ETHER_ADDR_LEN); |
---|
| 9963 | + if (wl_adps_bad_ap_check(cfg, &bssid)) { |
---|
| 9964 | + if (wl_adps_enabled(cfg, ndev)) { |
---|
| 9965 | + wl_adps_set_suspend(cfg, ndev, ADPS_SUSPEND); |
---|
| 9966 | + } |
---|
| 9967 | + } |
---|
| 9968 | + |
---|
| 9969 | + return BCME_OK; |
---|
| 9970 | +} |
---|
| 9971 | +#endif /* WL_BAM */ |
---|
| 9972 | + |
---|
| 9973 | +int |
---|
| 9974 | +dhd_enable_adps(dhd_pub_t *dhd, uint8 on) |
---|
| 9975 | +{ |
---|
| 9976 | + int i; |
---|
| 9977 | + int len; |
---|
| 9978 | + int ret = BCME_OK; |
---|
| 9979 | + |
---|
| 9980 | + bcm_iov_buf_t *iov_buf = NULL; |
---|
| 9981 | + wl_adps_params_v1_t *data = NULL; |
---|
| 9982 | + |
---|
| 9983 | + len = OFFSETOF(bcm_iov_buf_t, data) + sizeof(*data); |
---|
| 9984 | + iov_buf = MALLOC(dhd->osh, len); |
---|
| 9985 | + if (iov_buf == NULL) { |
---|
| 9986 | + DHD_ERROR(("%s - failed to allocate %d bytes for iov_buf\n", __FUNCTION__, len)); |
---|
| 9987 | + ret = BCME_NOMEM; |
---|
| 9988 | + goto exit; |
---|
| 9989 | + } |
---|
| 9990 | + |
---|
| 9991 | + iov_buf->version = WL_ADPS_IOV_VER; |
---|
| 9992 | + iov_buf->len = sizeof(*data); |
---|
| 9993 | + iov_buf->id = WL_ADPS_IOV_MODE; |
---|
| 9994 | + |
---|
| 9995 | + data = (wl_adps_params_v1_t *)iov_buf->data; |
---|
| 9996 | + data->version = ADPS_SUB_IOV_VERSION_1; |
---|
| 9997 | + data->length = sizeof(*data); |
---|
| 9998 | + data->mode = on; |
---|
| 9999 | + |
---|
| 10000 | + for (i = 1; i <= MAX_BANDS; i++) { |
---|
| 10001 | + data->band = i; |
---|
| 10002 | + ret = dhd_iovar(dhd, 0, "adps", (char *)iov_buf, len, NULL, 0, TRUE); |
---|
| 10003 | + if (ret < 0) { |
---|
| 10004 | + if (ret == BCME_UNSUPPORTED) { |
---|
| 10005 | + DHD_ERROR(("%s adps is not supported\n", __FUNCTION__)); |
---|
| 10006 | + ret = BCME_OK; |
---|
| 10007 | + goto exit; |
---|
| 10008 | + } |
---|
| 10009 | + else { |
---|
| 10010 | + DHD_ERROR(("%s fail to set adps %s for band %d (%d)\n", |
---|
| 10011 | + __FUNCTION__, on ? "On" : "Off", i, ret)); |
---|
| 10012 | + goto exit; |
---|
| 10013 | + } |
---|
| 10014 | + } |
---|
| 10015 | + } |
---|
| 10016 | + |
---|
| 10017 | +#ifdef WL_BAM |
---|
| 10018 | + if (on) { |
---|
| 10019 | + dhd_check_adps_bad_ap(dhd); |
---|
| 10020 | + } |
---|
| 10021 | +#endif /* WL_BAM */ |
---|
| 10022 | + |
---|
| 10023 | +exit: |
---|
| 10024 | + if (iov_buf) { |
---|
| 10025 | + MFREE(dhd->osh, iov_buf, len); |
---|
| 10026 | + iov_buf = NULL; |
---|
| 10027 | + } |
---|
| 10028 | + return ret; |
---|
| 10029 | +} |
---|
| 10030 | +#endif /* WLADPS || WLADPS_PRIVATE_CMD */ |
---|
8365 | 10031 | |
---|
8366 | 10032 | int |
---|
8367 | 10033 | dhd_preinit_ioctls(dhd_pub_t *dhd) |
---|
8368 | 10034 | { |
---|
8369 | 10035 | int ret = 0; |
---|
8370 | 10036 | char eventmask[WL_EVENTING_MASK_LEN]; |
---|
8371 | | - char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ |
---|
| 10037 | + char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ |
---|
8372 | 10038 | uint32 buf_key_b4_m4 = 1; |
---|
8373 | 10039 | uint8 msglen; |
---|
8374 | 10040 | eventmsgs_ext_t *eventmask_msg = NULL; |
---|
| 10041 | + uint32 event_log_max_sets = 0; |
---|
8375 | 10042 | char* iov_buf = NULL; |
---|
8376 | 10043 | int ret2 = 0; |
---|
8377 | | -#if defined(CUSTOM_AMPDU_BA_WSIZE) |
---|
| 10044 | + uint32 wnm_cap = 0; |
---|
| 10045 | +#if defined(BCMSUP_4WAY_HANDSHAKE) |
---|
| 10046 | + uint32 sup_wpa = 1; |
---|
| 10047 | +#endif /* BCMSUP_4WAY_HANDSHAKE */ |
---|
| 10048 | +#if defined(CUSTOM_AMPDU_BA_WSIZE) || (defined(WLAIBSS) && \ |
---|
| 10049 | + defined(CUSTOM_IBSS_AMPDU_BA_WSIZE)) |
---|
8378 | 10050 | uint32 ampdu_ba_wsize = 0; |
---|
8379 | | -#endif |
---|
| 10051 | +#endif /* CUSTOM_AMPDU_BA_WSIZE ||(WLAIBSS && CUSTOM_IBSS_AMPDU_BA_WSIZE) */ |
---|
8380 | 10052 | #if defined(CUSTOM_AMPDU_MPDU) |
---|
8381 | 10053 | int32 ampdu_mpdu = 0; |
---|
8382 | | -#endif |
---|
| 10054 | +#endif // endif |
---|
8383 | 10055 | #if defined(CUSTOM_AMPDU_RELEASE) |
---|
8384 | 10056 | int32 ampdu_release = 0; |
---|
8385 | | -#endif |
---|
| 10057 | +#endif // endif |
---|
8386 | 10058 | #if defined(CUSTOM_AMSDU_AGGSF) |
---|
8387 | 10059 | int32 amsdu_aggsf = 0; |
---|
8388 | | -#endif |
---|
| 10060 | +#endif // endif |
---|
8389 | 10061 | |
---|
8390 | | -#if defined(BCMSDIO) || defined(BCMDBUS) |
---|
| 10062 | +#if defined(BCMSDIO) |
---|
8391 | 10063 | #ifdef PROP_TXSTATUS |
---|
8392 | 10064 | int wlfc_enable = TRUE; |
---|
8393 | 10065 | #ifndef DISABLE_11N |
---|
8394 | 10066 | uint32 hostreorder = 1; |
---|
| 10067 | + uint chipid = 0; |
---|
8395 | 10068 | #endif /* DISABLE_11N */ |
---|
8396 | 10069 | #endif /* PROP_TXSTATUS */ |
---|
8397 | | -#endif /* defined(BCMSDIO) || defined(BCMDBUS) */ |
---|
| 10070 | +#endif // endif |
---|
8398 | 10071 | #ifndef PCIE_FULL_DONGLE |
---|
8399 | 10072 | uint32 wl_ap_isolate; |
---|
8400 | 10073 | #endif /* PCIE_FULL_DONGLE */ |
---|
| 10074 | + uint32 frameburst = CUSTOM_FRAMEBURST_SET; |
---|
| 10075 | + uint wnm_bsstrans_resp = 0; |
---|
| 10076 | +#ifdef SUPPORT_SET_CAC |
---|
| 10077 | + uint32 cac = 1; |
---|
| 10078 | +#endif /* SUPPORT_SET_CAC */ |
---|
| 10079 | +#ifdef DHD_BUS_MEM_ACCESS |
---|
| 10080 | + uint32 enable_memuse = 1; |
---|
| 10081 | +#endif /* DHD_BUS_MEM_ACCESS */ |
---|
8401 | 10082 | |
---|
8402 | | -#if defined(BCMSDIO) || defined(DISABLE_FRAMEBURST) |
---|
8403 | | - /* default frame burst enabled for PCIe, disabled for SDIO dongles and media targets */ |
---|
8404 | | - uint32 frameburst = 0; |
---|
8405 | | -#else |
---|
8406 | | - uint32 frameburst = 1; |
---|
8407 | | -#endif /* BCMSDIO */ |
---|
8408 | | - |
---|
| 10083 | +#ifdef OEM_ANDROID |
---|
8409 | 10084 | #ifdef DHD_ENABLE_LPC |
---|
8410 | 10085 | uint32 lpc = 1; |
---|
8411 | 10086 | #endif /* DHD_ENABLE_LPC */ |
---|
.. | .. |
---|
8414 | 10089 | uint32 dongle_align = DHD_SDALIGN; |
---|
8415 | 10090 | uint32 glom = CUSTOM_GLOM_SETTING; |
---|
8416 | 10091 | #endif /* defined(BCMSDIO) */ |
---|
8417 | | -#if defined(CUSTOMER_HW2) && defined(USE_WL_CREDALL) |
---|
| 10092 | +#if (defined(CUSTOMER_HW2) || defined(BOARD_HIKEY)) && defined(USE_WL_CREDALL) |
---|
8418 | 10093 | uint32 credall = 1; |
---|
8419 | | -#endif |
---|
8420 | | -#if defined(VSDB) || defined(ROAM_ENABLE) |
---|
| 10094 | +#endif // endif |
---|
8421 | 10095 | uint bcn_timeout = CUSTOM_BCN_TIMEOUT; |
---|
8422 | | -#else |
---|
8423 | | - uint bcn_timeout = 4; |
---|
8424 | | -#endif |
---|
| 10096 | + uint scancache_enab = TRUE; |
---|
| 10097 | +#ifdef ENABLE_BCN_LI_BCN_WAKEUP |
---|
| 10098 | + uint32 bcn_li_bcn = 1; |
---|
| 10099 | +#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ |
---|
8425 | 10100 | uint retry_max = CUSTOM_ASSOC_RETRY_MAX; |
---|
8426 | 10101 | #if defined(ARP_OFFLOAD_SUPPORT) |
---|
8427 | | - int arpoe = 1; |
---|
8428 | | -#endif |
---|
| 10102 | + int arpoe = 0; |
---|
| 10103 | +#endif // endif |
---|
8429 | 10104 | int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME; |
---|
8430 | 10105 | int scan_unassoc_time = DHD_SCAN_UNASSOC_ACTIVE_TIME; |
---|
8431 | 10106 | int scan_passive_time = DHD_SCAN_PASSIVE_TIME; |
---|
8432 | 10107 | char buf[WLC_IOCTL_SMLEN]; |
---|
8433 | 10108 | char *ptr; |
---|
8434 | 10109 | uint32 listen_interval = CUSTOM_LISTEN_INTERVAL; /* Default Listen Interval in Beacons */ |
---|
| 10110 | +#if defined(DHD_8021X_DUMP) && defined(SHOW_LOGTRACE) |
---|
| 10111 | + wl_el_tag_params_t *el_tag = NULL; |
---|
| 10112 | +#endif /* DHD_8021X_DUMP */ |
---|
8435 | 10113 | #ifdef ROAM_ENABLE |
---|
8436 | 10114 | uint roamvar = 0; |
---|
8437 | 10115 | int roam_trigger[2] = {CUSTOM_ROAM_TRIGGER_SETTING, WLC_BAND_ALL}; |
---|
8438 | 10116 | int roam_scan_period[2] = {10, WLC_BAND_ALL}; |
---|
8439 | 10117 | int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL}; |
---|
| 10118 | +#ifdef ROAM_AP_ENV_DETECTION |
---|
| 10119 | + int roam_env_mode = AP_ENV_INDETERMINATE; |
---|
| 10120 | +#endif /* ROAM_AP_ENV_DETECTION */ |
---|
8440 | 10121 | #ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC |
---|
8441 | 10122 | int roam_fullscan_period = 60; |
---|
8442 | 10123 | #else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */ |
---|
8443 | 10124 | int roam_fullscan_period = 120; |
---|
8444 | 10125 | #endif /* FULL_ROAMING_SCAN_PERIOD_60_SEC */ |
---|
| 10126 | +#ifdef DISABLE_BCNLOSS_ROAM |
---|
| 10127 | + uint roam_bcnloss_off = 1; |
---|
| 10128 | +#endif /* DISABLE_BCNLOSS_ROAM */ |
---|
8445 | 10129 | #else |
---|
8446 | 10130 | #ifdef DISABLE_BUILTIN_ROAM |
---|
8447 | 10131 | uint roamvar = 1; |
---|
.. | .. |
---|
8450 | 10134 | |
---|
8451 | 10135 | #if defined(SOFTAP) |
---|
8452 | 10136 | uint dtim = 1; |
---|
8453 | | -#endif |
---|
| 10137 | +#endif // endif |
---|
8454 | 10138 | #if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211)) |
---|
8455 | | - uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */ |
---|
8456 | 10139 | struct ether_addr p2p_ea; |
---|
8457 | | -#endif |
---|
| 10140 | +#endif // endif |
---|
| 10141 | +#ifdef BCMCCX |
---|
| 10142 | + uint32 ccx = 1; |
---|
| 10143 | +#endif // endif |
---|
8458 | 10144 | #ifdef SOFTAP_UAPSD_OFF |
---|
8459 | 10145 | uint32 wme_apsd = 0; |
---|
8460 | 10146 | #endif /* SOFTAP_UAPSD_OFF */ |
---|
.. | .. |
---|
8467 | 10153 | #ifdef GET_CUSTOM_MAC_ENABLE |
---|
8468 | 10154 | struct ether_addr ea_addr; |
---|
8469 | 10155 | #endif /* GET_CUSTOM_MAC_ENABLE */ |
---|
| 10156 | +#ifdef OKC_SUPPORT |
---|
| 10157 | + uint32 okc = 1; |
---|
| 10158 | +#endif // endif |
---|
8470 | 10159 | |
---|
8471 | 10160 | #ifdef DISABLE_11N |
---|
8472 | 10161 | uint32 nmode = 0; |
---|
.. | .. |
---|
8478 | 10167 | #ifdef DISABLE_TXBFR |
---|
8479 | 10168 | uint32 txbf_bfr_cap = 0; |
---|
8480 | 10169 | #endif /* DISABLE_TXBFR */ |
---|
| 10170 | +#ifdef AMPDU_VO_ENABLE |
---|
| 10171 | + struct ampdu_tid_control tid; |
---|
| 10172 | +#endif // endif |
---|
8481 | 10173 | #if defined(PROP_TXSTATUS) |
---|
| 10174 | +#ifdef USE_WFA_CERT_CONF |
---|
| 10175 | + uint32 proptx = 0; |
---|
| 10176 | +#endif /* USE_WFA_CERT_CONF */ |
---|
8482 | 10177 | #endif /* PROP_TXSTATUS */ |
---|
| 10178 | +#ifdef DHD_SET_FW_HIGHSPEED |
---|
| 10179 | + uint32 ack_ratio = 250; |
---|
| 10180 | + uint32 ack_ratio_depth = 64; |
---|
| 10181 | +#endif /* DHD_SET_FW_HIGHSPEED */ |
---|
| 10182 | +#if defined(SUPPORT_2G_VHT) || defined(SUPPORT_5G_1024QAM_VHT) |
---|
| 10183 | + uint32 vht_features = 0; /* init to 0, will be set based on each support */ |
---|
| 10184 | +#endif /* SUPPORT_2G_VHT || SUPPORT_5G_1024QAM_VHT */ |
---|
| 10185 | +#ifdef DISABLE_11N_PROPRIETARY_RATES |
---|
| 10186 | + uint32 ht_features = 0; |
---|
| 10187 | +#endif /* DISABLE_11N_PROPRIETARY_RATES */ |
---|
8483 | 10188 | #ifdef CUSTOM_PSPRETEND_THR |
---|
8484 | 10189 | uint32 pspretend_thr = CUSTOM_PSPRETEND_THR; |
---|
8485 | | -#endif |
---|
8486 | | - uint32 rsdb_mode = 0; |
---|
| 10190 | +#endif // endif |
---|
| 10191 | +#ifdef CUSTOM_EVENT_PM_WAKE |
---|
| 10192 | + uint32 pm_awake_thresh = CUSTOM_EVENT_PM_WAKE; |
---|
| 10193 | +#endif /* CUSTOM_EVENT_PM_WAKE */ |
---|
| 10194 | +#ifdef DISABLE_PRUNED_SCAN |
---|
| 10195 | + uint32 scan_features = 0; |
---|
| 10196 | +#endif /* DISABLE_PRUNED_SCAN */ |
---|
| 10197 | +#ifdef BCMPCIE_OOB_HOST_WAKE |
---|
| 10198 | + uint32 hostwake_oob = 0; |
---|
| 10199 | +#endif /* BCMPCIE_OOB_HOST_WAKE */ |
---|
| 10200 | +#ifdef EVENT_LOG_RATE_HC |
---|
| 10201 | + /* threshold number of lines per second */ |
---|
| 10202 | +#define EVENT_LOG_RATE_HC_THRESHOLD 1000 |
---|
| 10203 | + uint32 event_log_rate_hc = EVENT_LOG_RATE_HC_THRESHOLD; |
---|
| 10204 | +#endif /* EVENT_LOG_RATE_HC */ |
---|
| 10205 | +#if defined(WBTEXT) && defined(WBTEXT_BTMDELTA) |
---|
| 10206 | + uint32 btmdelta = WBTEXT_BTMDELTA; |
---|
| 10207 | +#endif /* WBTEXT && WBTEXT_BTMDELTA */ |
---|
| 10208 | + wl_wlc_version_t wlc_ver; |
---|
| 10209 | + |
---|
8487 | 10210 | #ifdef PKT_FILTER_SUPPORT |
---|
8488 | 10211 | dhd_pkt_filter_enable = TRUE; |
---|
| 10212 | +#ifdef APF |
---|
| 10213 | + dhd->apf_set = FALSE; |
---|
| 10214 | +#endif /* APF */ |
---|
8489 | 10215 | #endif /* PKT_FILTER_SUPPORT */ |
---|
8490 | | -#ifdef WLTDLS |
---|
8491 | | - dhd->tdls_enable = FALSE; |
---|
8492 | | - dhd_tdls_set_mode(dhd, false); |
---|
8493 | | -#endif /* WLTDLS */ |
---|
8494 | 10216 | dhd->suspend_bcn_li_dtim = CUSTOM_SUSPEND_BCN_LI_DTIM; |
---|
| 10217 | +#ifdef ENABLE_MAX_DTIM_IN_SUSPEND |
---|
| 10218 | + dhd->max_dtim_enable = TRUE; |
---|
| 10219 | +#else |
---|
| 10220 | + dhd->max_dtim_enable = FALSE; |
---|
| 10221 | +#endif /* ENABLE_MAX_DTIM_IN_SUSPEND */ |
---|
| 10222 | + dhd->disable_dtim_in_suspend = FALSE; |
---|
| 10223 | +#ifdef CUSTOM_SET_OCLOFF |
---|
| 10224 | + dhd->ocl_off = FALSE; |
---|
| 10225 | +#endif /* CUSTOM_SET_OCLOFF */ |
---|
| 10226 | +#ifdef SUPPORT_SET_TID |
---|
| 10227 | + dhd->tid_mode = SET_TID_OFF; |
---|
| 10228 | + dhd->target_uid = 0; |
---|
| 10229 | + dhd->target_tid = 0; |
---|
| 10230 | +#endif /* SUPPORT_SET_TID */ |
---|
8495 | 10231 | DHD_TRACE(("Enter %s\n", __FUNCTION__)); |
---|
8496 | 10232 | dhd->op_mode = 0; |
---|
| 10233 | + |
---|
| 10234 | +#if defined(CUSTOM_COUNTRY_CODE) && (defined(CUSTOMER_HW2) || defined(BOARD_HIKEY)) |
---|
| 10235 | + /* clear AP flags */ |
---|
| 10236 | + dhd->dhd_cflags &= ~WLAN_PLAT_AP_FLAG; |
---|
| 10237 | +#endif /* CUSTOM_COUNTRY_CODE && (CUSTOMER_HW2 || BOARD_HIKEY) */ |
---|
| 10238 | + |
---|
| 10239 | +#ifdef CUSTOMER_HW4_DEBUG |
---|
| 10240 | + if (!dhd_validate_chipid(dhd)) { |
---|
| 10241 | + DHD_ERROR(("%s: CONFIG_BCMXXX and CHIP ID(%x) is mismatched\n", |
---|
| 10242 | + __FUNCTION__, dhd_bus_chip_id(dhd))); |
---|
| 10243 | +#ifndef SUPPORT_MULTIPLE_CHIPS |
---|
| 10244 | + ret = BCME_BADARG; |
---|
| 10245 | + goto done; |
---|
| 10246 | +#endif /* !SUPPORT_MULTIPLE_CHIPS */ |
---|
| 10247 | + } |
---|
| 10248 | +#endif /* CUSTOMER_HW4_DEBUG */ |
---|
| 10249 | + |
---|
| 10250 | + /* query for 'ver' to get version info from firmware */ |
---|
| 10251 | + memset(buf, 0, sizeof(buf)); |
---|
| 10252 | + ptr = buf; |
---|
| 10253 | + ret = dhd_iovar(dhd, 0, "ver", NULL, 0, (char *)&buf, sizeof(buf), FALSE); |
---|
| 10254 | + if (ret < 0) |
---|
| 10255 | + DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret)); |
---|
| 10256 | + else { |
---|
| 10257 | + bcmstrtok(&ptr, "\n", 0); |
---|
| 10258 | + /* Print fw version info */ |
---|
| 10259 | + DHD_ERROR(("Firmware version = %s\n", buf)); |
---|
| 10260 | + strncpy(fw_version, buf, FW_VER_STR_LEN); |
---|
| 10261 | + fw_version[FW_VER_STR_LEN-1] = '\0'; |
---|
| 10262 | +#if defined(BCMSDIO) || defined(BCMPCIE) || defined(BCMSPI) |
---|
| 10263 | + dhd_set_version_info(dhd, buf); |
---|
| 10264 | +#endif /* BCMSDIO || BCMPCIE */ |
---|
| 10265 | + } |
---|
| 10266 | + |
---|
| 10267 | +#ifdef BOARD_HIKEY |
---|
| 10268 | + /* Set op_mode as MFG_MODE if WLTEST is present in "wl ver" */ |
---|
| 10269 | + if (strstr(fw_version, "WLTEST") != NULL) { |
---|
| 10270 | + DHD_ERROR(("%s: wl ver has WLTEST, setting op_mode as DHD_FLAG_MFG_MODE\n", |
---|
| 10271 | + __FUNCTION__)); |
---|
| 10272 | + op_mode = DHD_FLAG_MFG_MODE; |
---|
| 10273 | + } |
---|
| 10274 | +#endif /* BOARD_HIKEY */ |
---|
| 10275 | + |
---|
8497 | 10276 | if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_MFG_MODE) || |
---|
8498 | 10277 | (op_mode == DHD_FLAG_MFG_MODE)) { |
---|
| 10278 | + dhd->op_mode = DHD_FLAG_MFG_MODE; |
---|
| 10279 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 10280 | + /* disable runtimePM by default in MFG mode. */ |
---|
| 10281 | + pm_runtime_disable(dhd_bus_to_dev(dhd->bus)); |
---|
| 10282 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
| 10283 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 10284 | + /* Disable RuntimePM in mfg mode */ |
---|
| 10285 | + DHD_DISABLE_RUNTIME_PM(dhd); |
---|
| 10286 | + DHD_ERROR(("%s : Disable RuntimePM in Manufactring Firmware\n", __FUNCTION__)); |
---|
| 10287 | +#endif /* DHD_PCIE_RUNTIME_PM */ |
---|
8499 | 10288 | /* Check and adjust IOCTL response timeout for Manufactring firmware */ |
---|
8500 | 10289 | dhd_os_set_ioctl_resp_timeout(MFG_IOCTL_RESP_TIMEOUT); |
---|
8501 | 10290 | DHD_ERROR(("%s : Set IOCTL response time for Manufactring Firmware\n", |
---|
.. | .. |
---|
8504 | 10293 | dhd_os_set_ioctl_resp_timeout(IOCTL_RESP_TIMEOUT); |
---|
8505 | 10294 | DHD_INFO(("%s : Set IOCTL response time.\n", __FUNCTION__)); |
---|
8506 | 10295 | } |
---|
| 10296 | +#ifdef BCMPCIE_OOB_HOST_WAKE |
---|
| 10297 | + ret = dhd_iovar(dhd, 0, "bus:hostwake_oob", NULL, 0, (char *)&hostwake_oob, |
---|
| 10298 | + sizeof(hostwake_oob), FALSE); |
---|
| 10299 | + if (ret < 0) { |
---|
| 10300 | + DHD_ERROR(("%s: hostwake_oob IOVAR not present, proceed\n", __FUNCTION__)); |
---|
| 10301 | + } else { |
---|
| 10302 | + if (hostwake_oob == 0) { |
---|
| 10303 | + DHD_ERROR(("%s: hostwake_oob is not enabled in the NVRAM, STOP\n", |
---|
| 10304 | + __FUNCTION__)); |
---|
| 10305 | + ret = BCME_UNSUPPORTED; |
---|
| 10306 | + goto done; |
---|
| 10307 | + } else { |
---|
| 10308 | + DHD_ERROR(("%s: hostwake_oob enabled\n", __FUNCTION__)); |
---|
| 10309 | + } |
---|
| 10310 | + } |
---|
| 10311 | +#endif /* BCMPCIE_OOB_HOST_WAKE */ |
---|
| 10312 | + |
---|
| 10313 | +#ifdef DNGL_AXI_ERROR_LOGGING |
---|
| 10314 | + ret = dhd_iovar(dhd, 0, "axierror_logbuf_addr", NULL, 0, (char *)&dhd->axierror_logbuf_addr, |
---|
| 10315 | + sizeof(dhd->axierror_logbuf_addr), FALSE); |
---|
| 10316 | + if (ret < 0) { |
---|
| 10317 | + DHD_ERROR(("%s: axierror_logbuf_addr IOVAR not present, proceed\n", __FUNCTION__)); |
---|
| 10318 | + dhd->axierror_logbuf_addr = 0; |
---|
| 10319 | + } else { |
---|
| 10320 | + DHD_ERROR(("%s: axierror_logbuf_addr : 0x%x\n", __FUNCTION__, |
---|
| 10321 | + dhd->axierror_logbuf_addr)); |
---|
| 10322 | + } |
---|
| 10323 | +#endif /* DNGL_AXI_ERROR_LOGGING */ |
---|
| 10324 | + |
---|
| 10325 | +#ifdef EVENT_LOG_RATE_HC |
---|
| 10326 | + ret = dhd_iovar(dhd, 0, "event_log_rate_hc", (char *)&event_log_rate_hc, |
---|
| 10327 | + sizeof(event_log_rate_hc), NULL, 0, TRUE); |
---|
| 10328 | + if (ret < 0) { |
---|
| 10329 | + DHD_ERROR(("%s event_log_rate_hc set failed %d\n", __FUNCTION__, ret)); |
---|
| 10330 | + } else { |
---|
| 10331 | + DHD_ERROR(("%s event_log_rate_hc set with threshold:%d\n", __FUNCTION__, |
---|
| 10332 | + event_log_rate_hc)); |
---|
| 10333 | + } |
---|
| 10334 | +#endif /* EVENT_LOG_RATE_HC */ |
---|
| 10335 | + |
---|
8507 | 10336 | #ifdef GET_CUSTOM_MAC_ENABLE |
---|
8508 | 10337 | ret = wifi_platform_get_mac_addr(dhd->info->adapter, ea_addr.octet); |
---|
8509 | 10338 | if (!ret) { |
---|
.. | .. |
---|
8531 | 10360 | } |
---|
8532 | 10361 | #endif /* GET_CUSTOM_MAC_ENABLE */ |
---|
8533 | 10362 | |
---|
| 10363 | + if ((ret = dhd_apply_default_clm(dhd, clm_path)) < 0) { |
---|
| 10364 | + DHD_ERROR(("%s: CLM set failed. Abort initialization.\n", __FUNCTION__)); |
---|
| 10365 | + goto done; |
---|
| 10366 | + } |
---|
| 10367 | + |
---|
8534 | 10368 | /* get a capabilities from firmware */ |
---|
8535 | 10369 | { |
---|
8536 | 10370 | uint32 cap_buf_size = sizeof(dhd->fw_capabilities); |
---|
.. | .. |
---|
8557 | 10391 | dhd->op_mode = DHD_FLAG_HOSTAP_MODE; |
---|
8558 | 10392 | #if defined(ARP_OFFLOAD_SUPPORT) |
---|
8559 | 10393 | arpoe = 0; |
---|
8560 | | -#endif |
---|
| 10394 | +#endif // endif |
---|
8561 | 10395 | #ifdef PKT_FILTER_SUPPORT |
---|
8562 | 10396 | dhd_pkt_filter_enable = FALSE; |
---|
8563 | | -#endif |
---|
| 10397 | +#endif // endif |
---|
8564 | 10398 | #ifdef SET_RANDOM_MAC_SOFTAP |
---|
8565 | 10399 | SRANDOM32((uint)jiffies); |
---|
8566 | 10400 | rand_mac = RANDOM32(); |
---|
.. | .. |
---|
8578 | 10412 | } else |
---|
8579 | 10413 | memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN); |
---|
8580 | 10414 | #endif /* SET_RANDOM_MAC_SOFTAP */ |
---|
8581 | | -#if !defined(AP) && defined(WL_CFG80211) |
---|
8582 | | - /* Turn off MPC in AP mode */ |
---|
8583 | | - ret = dhd_iovar(dhd, 0, "mpc", (char *)&mpc, sizeof(mpc), NULL, 0, TRUE); |
---|
8584 | | - if (ret < 0) { |
---|
8585 | | - DHD_ERROR(("%s mpc for HostAPD failed %d\n", __FUNCTION__, ret)); |
---|
8586 | | - } |
---|
8587 | | -#endif |
---|
8588 | | -#ifdef SUPPORT_AP_POWERSAVE |
---|
8589 | | - dhd_set_ap_powersave(dhd, 0, TRUE); |
---|
8590 | | -#endif /* SUPPORT_AP_POWERSAVE */ |
---|
| 10415 | +#ifdef USE_DYNAMIC_F2_BLKSIZE |
---|
| 10416 | + dhdsdio_func_blocksize(dhd, 2, sd_f2_blocksize); |
---|
| 10417 | +#endif /* USE_DYNAMIC_F2_BLKSIZE */ |
---|
8591 | 10418 | #ifdef SOFTAP_UAPSD_OFF |
---|
8592 | 10419 | ret = dhd_iovar(dhd, 0, "wme_apsd", (char *)&wme_apsd, sizeof(wme_apsd), NULL, 0, |
---|
8593 | 10420 | TRUE); |
---|
.. | .. |
---|
8596 | 10423 | __FUNCTION__, ret)); |
---|
8597 | 10424 | } |
---|
8598 | 10425 | #endif /* SOFTAP_UAPSD_OFF */ |
---|
| 10426 | +#if defined(CUSTOM_COUNTRY_CODE) && (defined(CUSTOMER_HW2) || defined(BOARD_HIKEY)) |
---|
| 10427 | + /* set AP flag for specific country code of SOFTAP */ |
---|
| 10428 | + dhd->dhd_cflags |= WLAN_PLAT_AP_FLAG | WLAN_PLAT_NODFS_FLAG; |
---|
| 10429 | +#endif /* CUSTOM_COUNTRY_CODE && (CUSTOMER_HW2 || BOARD_HIKEY) */ |
---|
8599 | 10430 | } else if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_MFG_MODE) || |
---|
8600 | 10431 | (op_mode == DHD_FLAG_MFG_MODE)) { |
---|
8601 | 10432 | #if defined(ARP_OFFLOAD_SUPPORT) |
---|
.. | .. |
---|
8605 | 10436 | dhd_pkt_filter_enable = FALSE; |
---|
8606 | 10437 | #endif /* PKT_FILTER_SUPPORT */ |
---|
8607 | 10438 | dhd->op_mode = DHD_FLAG_MFG_MODE; |
---|
| 10439 | +#ifdef USE_DYNAMIC_F2_BLKSIZE |
---|
| 10440 | + dhdsdio_func_blocksize(dhd, 2, DYNAMIC_F2_BLKSIZE_FOR_NONLEGACY); |
---|
| 10441 | +#endif /* USE_DYNAMIC_F2_BLKSIZE */ |
---|
| 10442 | +#ifndef CUSTOM_SET_ANTNPM |
---|
| 10443 | +#ifndef IGUANA_LEGACY_CHIPS |
---|
8608 | 10444 | if (FW_SUPPORTED(dhd, rsdb)) { |
---|
8609 | | - rsdb_mode = 0; |
---|
| 10445 | + wl_config_t rsdb_mode; |
---|
| 10446 | + memset(&rsdb_mode, 0, sizeof(rsdb_mode)); |
---|
8610 | 10447 | ret = dhd_iovar(dhd, 0, "rsdb_mode", (char *)&rsdb_mode, sizeof(rsdb_mode), |
---|
8611 | | - NULL, 0, TRUE); |
---|
| 10448 | + NULL, 0, TRUE); |
---|
8612 | 10449 | if (ret < 0) { |
---|
8613 | 10450 | DHD_ERROR(("%s Disable rsdb_mode is failed ret= %d\n", |
---|
8614 | 10451 | __FUNCTION__, ret)); |
---|
8615 | 10452 | } |
---|
8616 | 10453 | } |
---|
| 10454 | +#endif /* IGUANA_LEGACY_CHIPS */ |
---|
| 10455 | +#endif /* !CUSTOM_SET_ANTNPM */ |
---|
8617 | 10456 | } else { |
---|
8618 | 10457 | uint32 concurrent_mode = 0; |
---|
8619 | 10458 | if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_P2P_MODE) || |
---|
8620 | 10459 | (op_mode == DHD_FLAG_P2P_MODE)) { |
---|
8621 | 10460 | #if defined(ARP_OFFLOAD_SUPPORT) |
---|
8622 | 10461 | arpoe = 0; |
---|
8623 | | -#endif |
---|
| 10462 | +#endif // endif |
---|
8624 | 10463 | #ifdef PKT_FILTER_SUPPORT |
---|
8625 | 10464 | dhd_pkt_filter_enable = FALSE; |
---|
8626 | | -#endif |
---|
| 10465 | +#endif // endif |
---|
8627 | 10466 | dhd->op_mode = DHD_FLAG_P2P_MODE; |
---|
8628 | 10467 | } else if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_IBSS_MODE) || |
---|
8629 | 10468 | (op_mode == DHD_FLAG_IBSS_MODE)) { |
---|
8630 | 10469 | dhd->op_mode = DHD_FLAG_IBSS_MODE; |
---|
8631 | 10470 | } else |
---|
8632 | 10471 | dhd->op_mode = DHD_FLAG_STA_MODE; |
---|
8633 | | -#if !defined(AP) && defined(WLP2P) |
---|
| 10472 | +#if defined(OEM_ANDROID) && !defined(AP) && defined(WLP2P) |
---|
8634 | 10473 | if (dhd->op_mode != DHD_FLAG_IBSS_MODE && |
---|
8635 | 10474 | (concurrent_mode = dhd_get_concurrent_capabilites(dhd))) { |
---|
8636 | 10475 | #if defined(ARP_OFFLOAD_SUPPORT) |
---|
8637 | 10476 | arpoe = 1; |
---|
8638 | | -#endif |
---|
| 10477 | +#endif // endif |
---|
8639 | 10478 | dhd->op_mode |= concurrent_mode; |
---|
8640 | 10479 | } |
---|
8641 | 10480 | |
---|
.. | .. |
---|
8651 | 10490 | (char *)&ap_mode, sizeof(ap_mode), TRUE, 0)) < 0) { |
---|
8652 | 10491 | DHD_ERROR(("%s WLC_SET_AP failed %d\n", __FUNCTION__, ret)); |
---|
8653 | 10492 | } |
---|
8654 | | -#endif |
---|
| 10493 | +#endif // endif |
---|
8655 | 10494 | memcpy(&p2p_ea, &dhd->mac, ETHER_ADDR_LEN); |
---|
8656 | 10495 | ETHER_SET_LOCALADDR(&p2p_ea); |
---|
8657 | 10496 | ret = dhd_iovar(dhd, 0, "p2p_da_override", (char *)&p2p_ea, sizeof(p2p_ea), |
---|
.. | .. |
---|
8663 | 10502 | } |
---|
8664 | 10503 | #else |
---|
8665 | 10504 | (void)concurrent_mode; |
---|
8666 | | -#endif |
---|
| 10505 | +#endif /* defined(OEM_ANDROID) && !defined(AP) && defined(WLP2P) */ |
---|
8667 | 10506 | } |
---|
| 10507 | + |
---|
| 10508 | +#ifdef DISABLE_PRUNED_SCAN |
---|
| 10509 | + if (FW_SUPPORTED(dhd, rsdb)) { |
---|
| 10510 | + ret = dhd_iovar(dhd, 0, "scan_features", (char *)&scan_features, |
---|
| 10511 | + sizeof(scan_features), iovbuf, sizeof(iovbuf), FALSE); |
---|
| 10512 | + if (ret < 0) { |
---|
| 10513 | + DHD_ERROR(("%s get scan_features is failed ret=%d\n", |
---|
| 10514 | + __FUNCTION__, ret)); |
---|
| 10515 | + } else { |
---|
| 10516 | + memcpy(&scan_features, iovbuf, 4); |
---|
| 10517 | + scan_features &= ~RSDB_SCAN_DOWNGRADED_CH_PRUNE_ROAM; |
---|
| 10518 | + ret = dhd_iovar(dhd, 0, "scan_features", (char *)&scan_features, |
---|
| 10519 | + sizeof(scan_features), NULL, 0, TRUE); |
---|
| 10520 | + if (ret < 0) { |
---|
| 10521 | + DHD_ERROR(("%s set scan_features is failed ret=%d\n", |
---|
| 10522 | + __FUNCTION__, ret)); |
---|
| 10523 | + } |
---|
| 10524 | + } |
---|
| 10525 | + } |
---|
| 10526 | +#endif /* DISABLE_PRUNED_SCAN */ |
---|
8668 | 10527 | |
---|
8669 | 10528 | DHD_ERROR(("Firmware up: op_mode=0x%04x, MAC="MACDBG"\n", |
---|
8670 | 10529 | dhd->op_mode, MAC2STRDBG(dhd->mac.octet))); |
---|
8671 | | - #if defined(RXFRAME_THREAD) && defined(RXTHREAD_ONLYSTA) |
---|
| 10530 | +#if defined(CUSTOMER_HW2) || defined(BOARD_HIKEY) |
---|
| 10531 | +#if defined(DHD_BLOB_EXISTENCE_CHECK) |
---|
| 10532 | + if (!dhd->is_blob) |
---|
| 10533 | +#endif /* DHD_BLOB_EXISTENCE_CHECK */ |
---|
| 10534 | + { |
---|
| 10535 | + /* get a ccode and revision for the country code */ |
---|
| 10536 | +#if defined(CUSTOM_COUNTRY_CODE) |
---|
| 10537 | + get_customized_country_code(dhd->info->adapter, dhd->dhd_cspec.country_abbrev, |
---|
| 10538 | + &dhd->dhd_cspec, dhd->dhd_cflags); |
---|
| 10539 | +#else |
---|
| 10540 | + get_customized_country_code(dhd->info->adapter, dhd->dhd_cspec.country_abbrev, |
---|
| 10541 | + &dhd->dhd_cspec); |
---|
| 10542 | +#endif /* CUSTOM_COUNTRY_CODE */ |
---|
| 10543 | + } |
---|
| 10544 | +#endif /* CUSTOMER_HW2 || BOARD_HIKEY */ |
---|
| 10545 | + |
---|
| 10546 | +#if defined(RXFRAME_THREAD) && defined(RXTHREAD_ONLYSTA) |
---|
8672 | 10547 | if (dhd->op_mode == DHD_FLAG_HOSTAP_MODE) |
---|
8673 | 10548 | dhd->info->rxthread_enabled = FALSE; |
---|
8674 | 10549 | else |
---|
8675 | 10550 | dhd->info->rxthread_enabled = TRUE; |
---|
8676 | | - #endif |
---|
| 10551 | +#endif // endif |
---|
8677 | 10552 | /* Set Country code */ |
---|
8678 | 10553 | if (dhd->dhd_cspec.ccode[0] != 0) { |
---|
8679 | 10554 | ret = dhd_iovar(dhd, 0, "country", (char *)&dhd->dhd_cspec, sizeof(wl_country_t), |
---|
.. | .. |
---|
8682 | 10557 | DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__)); |
---|
8683 | 10558 | } |
---|
8684 | 10559 | |
---|
8685 | | - |
---|
8686 | 10560 | /* Set Listen Interval */ |
---|
8687 | 10561 | ret = dhd_iovar(dhd, 0, "assoc_listen", (char *)&listen_interval, sizeof(listen_interval), |
---|
8688 | 10562 | NULL, 0, TRUE); |
---|
.. | .. |
---|
8690 | 10564 | DHD_ERROR(("%s assoc_listen failed %d\n", __FUNCTION__, ret)); |
---|
8691 | 10565 | |
---|
8692 | 10566 | #if defined(ROAM_ENABLE) || defined(DISABLE_BUILTIN_ROAM) |
---|
| 10567 | +#ifdef USE_WFA_CERT_CONF |
---|
| 10568 | + if (sec_get_param_wfa_cert(dhd, SET_PARAM_ROAMOFF, &roamvar) == BCME_OK) { |
---|
| 10569 | + DHD_ERROR(("%s: read roam_off param =%d\n", __FUNCTION__, roamvar)); |
---|
| 10570 | + } |
---|
| 10571 | +#endif /* USE_WFA_CERT_CONF */ |
---|
8693 | 10572 | /* Disable built-in roaming to allowed ext supplicant to take care of roaming */ |
---|
8694 | | - dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, sizeof(roamvar), NULL, 0, TRUE); |
---|
| 10573 | + ret = dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, sizeof(roamvar), NULL, 0, TRUE); |
---|
8695 | 10574 | #endif /* ROAM_ENABLE || DISABLE_BUILTIN_ROAM */ |
---|
8696 | 10575 | #if defined(ROAM_ENABLE) |
---|
| 10576 | +#ifdef DISABLE_BCNLOSS_ROAM |
---|
| 10577 | + ret = dhd_iovar(dhd, 0, "roam_bcnloss_off", (char *)&roam_bcnloss_off, |
---|
| 10578 | + sizeof(roam_bcnloss_off), NULL, 0, TRUE); |
---|
| 10579 | +#endif /* DISABLE_BCNLOSS_ROAM */ |
---|
8697 | 10580 | if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger, |
---|
8698 | 10581 | sizeof(roam_trigger), TRUE, 0)) < 0) |
---|
8699 | 10582 | DHD_ERROR(("%s: roam trigger set failed %d\n", __FUNCTION__, ret)); |
---|
.. | .. |
---|
8703 | 10586 | if ((dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, roam_delta, |
---|
8704 | 10587 | sizeof(roam_delta), TRUE, 0)) < 0) |
---|
8705 | 10588 | DHD_ERROR(("%s: roam delta set failed %d\n", __FUNCTION__, ret)); |
---|
8706 | | - if ((ret = dhd_iovar(dhd, 0, "fullroamperiod", (char *)&roam_fullscan_period, |
---|
8707 | | - sizeof(roam_fullscan_period), NULL, 0, TRUE)) < 0) |
---|
| 10589 | + ret = dhd_iovar(dhd, 0, "fullroamperiod", (char *)&roam_fullscan_period, |
---|
| 10590 | + sizeof(roam_fullscan_period), NULL, 0, TRUE); |
---|
| 10591 | + if (ret < 0) |
---|
8708 | 10592 | DHD_ERROR(("%s: roam fullscan period set failed %d\n", __FUNCTION__, ret)); |
---|
| 10593 | +#ifdef ROAM_AP_ENV_DETECTION |
---|
| 10594 | + if (roam_trigger[0] == WL_AUTO_ROAM_TRIGGER) { |
---|
| 10595 | + if (dhd_iovar(dhd, 0, "roam_env_detection", (char *)&roam_env_mode, |
---|
| 10596 | + sizeof(roam_env_mode), NULL, 0, TRUE) == BCME_OK) |
---|
| 10597 | + dhd->roam_env_detection = TRUE; |
---|
| 10598 | + else |
---|
| 10599 | + dhd->roam_env_detection = FALSE; |
---|
| 10600 | + } |
---|
| 10601 | +#endif /* ROAM_AP_ENV_DETECTION */ |
---|
8709 | 10602 | #endif /* ROAM_ENABLE */ |
---|
8710 | 10603 | |
---|
| 10604 | +#ifdef CUSTOM_EVENT_PM_WAKE |
---|
| 10605 | + ret = dhd_iovar(dhd, 0, "const_awake_thresh", (char *)&pm_awake_thresh, |
---|
| 10606 | + sizeof(pm_awake_thresh), NULL, 0, TRUE); |
---|
| 10607 | + if (ret < 0) { |
---|
| 10608 | + DHD_ERROR(("%s set const_awake_thresh failed %d\n", __FUNCTION__, ret)); |
---|
| 10609 | + } |
---|
| 10610 | +#endif /* CUSTOM_EVENT_PM_WAKE */ |
---|
| 10611 | +#ifdef OKC_SUPPORT |
---|
| 10612 | + ret = dhd_iovar(dhd, 0, "okc_enable", (char *)&okc, sizeof(okc), NULL, 0, TRUE); |
---|
| 10613 | +#endif // endif |
---|
| 10614 | +#ifdef BCMCCX |
---|
| 10615 | + ret = dhd_iovar(dhd, 0, "ccx_enable", (char *)&ccx, sizeof(ccx), NULL, 0, TRUE); |
---|
| 10616 | +#endif /* BCMCCX */ |
---|
| 10617 | + |
---|
8711 | 10618 | #ifdef WLTDLS |
---|
8712 | | - /* by default TDLS on and auto mode off */ |
---|
8713 | | - _dhd_tdls_enable(dhd, true, false, NULL); |
---|
| 10619 | + dhd->tdls_enable = FALSE; |
---|
| 10620 | + dhd_tdls_set_mode(dhd, false); |
---|
8714 | 10621 | #endif /* WLTDLS */ |
---|
8715 | 10622 | |
---|
8716 | 10623 | #ifdef DHD_ENABLE_LPC |
---|
.. | .. |
---|
8718 | 10625 | ret = dhd_iovar(dhd, 0, "lpc", (char *)&lpc, sizeof(lpc), NULL, 0, TRUE); |
---|
8719 | 10626 | if (ret < 0) { |
---|
8720 | 10627 | DHD_ERROR(("%s Set lpc failed %d\n", __FUNCTION__, ret)); |
---|
| 10628 | + |
---|
| 10629 | + if (ret == BCME_NOTDOWN) { |
---|
| 10630 | + uint wl_down = 1; |
---|
| 10631 | + ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, |
---|
| 10632 | + (char *)&wl_down, sizeof(wl_down), TRUE, 0); |
---|
| 10633 | + DHD_ERROR(("%s lpc fail WL_DOWN : %d, lpc = %d\n", __FUNCTION__, ret, lpc)); |
---|
| 10634 | + |
---|
| 10635 | + ret = dhd_iovar(dhd, 0, "lpc", (char *)&lpc, sizeof(lpc), NULL, 0, TRUE); |
---|
| 10636 | + DHD_ERROR(("%s Set lpc ret --> %d\n", __FUNCTION__, ret)); |
---|
| 10637 | + } |
---|
8721 | 10638 | } |
---|
8722 | 10639 | #endif /* DHD_ENABLE_LPC */ |
---|
8723 | 10640 | |
---|
| 10641 | +#ifdef WLADPS |
---|
| 10642 | + if (dhd->op_mode & DHD_FLAG_STA_MODE) { |
---|
| 10643 | + if ((ret = dhd_enable_adps(dhd, ADPS_ENABLE)) != BCME_OK) { |
---|
| 10644 | + DHD_ERROR(("%s dhd_enable_adps failed %d\n", |
---|
| 10645 | + __FUNCTION__, ret)); |
---|
| 10646 | + } |
---|
| 10647 | + } |
---|
| 10648 | +#endif /* WLADPS */ |
---|
| 10649 | + |
---|
| 10650 | +#ifdef DHD_PM_CONTROL_FROM_FILE |
---|
| 10651 | + sec_control_pm(dhd, &power_mode); |
---|
| 10652 | +#else |
---|
| 10653 | +#ifndef H2_BRING_UP |
---|
8724 | 10654 | /* Set PowerSave mode */ |
---|
8725 | | - dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0); |
---|
| 10655 | + (void) dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0); |
---|
| 10656 | +#endif // endif |
---|
| 10657 | +#endif /* DHD_PM_CONTROL_FROM_FILE */ |
---|
8726 | 10658 | |
---|
8727 | 10659 | #if defined(BCMSDIO) |
---|
8728 | 10660 | /* Match Host and Dongle rx alignment */ |
---|
8729 | | - dhd_iovar(dhd, 0, "bus:txglomalign", (char *)&dongle_align, sizeof(dongle_align), |
---|
| 10661 | + ret = dhd_iovar(dhd, 0, "bus:txglomalign", (char *)&dongle_align, sizeof(dongle_align), |
---|
8730 | 10662 | NULL, 0, TRUE); |
---|
8731 | 10663 | |
---|
8732 | | -#if defined(CUSTOMER_HW2) && defined(USE_WL_CREDALL) |
---|
| 10664 | +#if (defined(CUSTOMER_HW2) || defined(BOARD_HIKEY))&& defined(USE_WL_CREDALL) |
---|
8733 | 10665 | /* enable credall to reduce the chance of no bus credit happened. */ |
---|
8734 | | - dhd_iovar(dhd, 0, "bus:credall", (char *)&credall, sizeof(credall), NULL, 0, TRUE); |
---|
8735 | | -#endif |
---|
| 10666 | + ret = dhd_iovar(dhd, 0, "bus:credall", (char *)&credall, sizeof(credall), NULL, 0, TRUE); |
---|
| 10667 | +#endif // endif |
---|
8736 | 10668 | |
---|
| 10669 | +#ifdef USE_WFA_CERT_CONF |
---|
| 10670 | + if (sec_get_param_wfa_cert(dhd, SET_PARAM_BUS_TXGLOM_MODE, &glom) == BCME_OK) { |
---|
| 10671 | + DHD_ERROR(("%s, read txglom param =%d\n", __FUNCTION__, glom)); |
---|
| 10672 | + } |
---|
| 10673 | +#endif /* USE_WFA_CERT_CONF */ |
---|
8737 | 10674 | if (glom != DEFAULT_GLOM_VALUE) { |
---|
8738 | 10675 | DHD_INFO(("%s set glom=0x%X\n", __FUNCTION__, glom)); |
---|
8739 | | - dhd_iovar(dhd, 0, "bus:txglom", (char *)&glom, sizeof(glom), NULL, 0, TRUE); |
---|
| 10676 | + ret = dhd_iovar(dhd, 0, "bus:txglom", (char *)&glom, sizeof(glom), NULL, 0, TRUE); |
---|
8740 | 10677 | } |
---|
8741 | 10678 | #endif /* defined(BCMSDIO) */ |
---|
8742 | 10679 | |
---|
8743 | 10680 | /* Setup timeout if Beacons are lost and roam is off to report link down */ |
---|
8744 | | - dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, sizeof(bcn_timeout), NULL, 0, TRUE); |
---|
| 10681 | + ret = dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, sizeof(bcn_timeout), NULL, 0, |
---|
| 10682 | + TRUE); |
---|
| 10683 | + |
---|
8745 | 10684 | /* Setup assoc_retry_max count to reconnect target AP in dongle */ |
---|
8746 | | - dhd_iovar(dhd, 0, "assoc_retry_max", (char *)&retry_max, sizeof(retry_max), NULL, 0, TRUE); |
---|
| 10685 | + ret = dhd_iovar(dhd, 0, "assoc_retry_max", (char *)&retry_max, sizeof(retry_max), NULL, 0, |
---|
| 10686 | + TRUE); |
---|
| 10687 | + |
---|
8747 | 10688 | #if defined(AP) && !defined(WLP2P) |
---|
8748 | | - /* Turn off MPC in AP mode */ |
---|
8749 | | - dhd_iovar(dhd, 0, "mpc", (char *)&mpc, sizeof(mpc), NULL, 0, TRUE); |
---|
8750 | | - dhd_iovar(dhd, 0, "apsta", (char *)&apsta, sizeof(apsta), NULL, 0, TRUE); |
---|
| 10689 | + ret = dhd_iovar(dhd, 0, "apsta", (char *)&apsta, sizeof(apsta), NULL, 0, TRUE); |
---|
| 10690 | + |
---|
8751 | 10691 | #endif /* defined(AP) && !defined(WLP2P) */ |
---|
8752 | 10692 | |
---|
| 10693 | +#ifdef MIMO_ANT_SETTING |
---|
| 10694 | + dhd_sel_ant_from_file(dhd); |
---|
| 10695 | +#endif /* MIMO_ANT_SETTING */ |
---|
8753 | 10696 | |
---|
8754 | | -#if defined(SOFTAP) |
---|
| 10697 | +#if defined(OEM_ANDROID) && defined(SOFTAP) |
---|
8755 | 10698 | if (ap_fw_loaded == TRUE) { |
---|
8756 | 10699 | dhd_wl_ioctl_cmd(dhd, WLC_SET_DTIMPRD, (char *)&dtim, sizeof(dtim), TRUE, 0); |
---|
8757 | 10700 | } |
---|
8758 | | -#endif |
---|
| 10701 | +#endif /* defined(OEM_ANDROID) && defined(SOFTAP) */ |
---|
8759 | 10702 | |
---|
8760 | 10703 | #if defined(KEEP_ALIVE) |
---|
8761 | 10704 | { |
---|
8762 | 10705 | /* Set Keep Alive : be sure to use FW with -keepalive */ |
---|
8763 | 10706 | int res; |
---|
8764 | 10707 | |
---|
8765 | | -#if defined(SOFTAP) |
---|
| 10708 | +#if defined(OEM_ANDROID) && defined(SOFTAP) |
---|
8766 | 10709 | if (ap_fw_loaded == FALSE) |
---|
8767 | | -#endif |
---|
| 10710 | +#endif /* defined(OEM_ANDROID) && defined(SOFTAP) */ |
---|
8768 | 10711 | if (!(dhd->op_mode & |
---|
8769 | 10712 | (DHD_FLAG_HOSTAP_MODE | DHD_FLAG_MFG_MODE))) { |
---|
8770 | 10713 | if ((res = dhd_keep_alive_onoff(dhd)) < 0) |
---|
.. | .. |
---|
8774 | 10717 | } |
---|
8775 | 10718 | #endif /* defined(KEEP_ALIVE) */ |
---|
8776 | 10719 | |
---|
| 10720 | +#ifdef USE_WL_TXBF |
---|
| 10721 | + ret = dhd_iovar(dhd, 0, "txbf", (char *)&txbf, sizeof(txbf), NULL, 0, TRUE); |
---|
| 10722 | + if (ret < 0) |
---|
| 10723 | + DHD_ERROR(("%s Set txbf failed %d\n", __FUNCTION__, ret)); |
---|
| 10724 | + |
---|
| 10725 | +#endif /* USE_WL_TXBF */ |
---|
| 10726 | + |
---|
| 10727 | + ret = dhd_iovar(dhd, 0, "scancache", (char *)&scancache_enab, sizeof(scancache_enab), NULL, |
---|
| 10728 | + 0, TRUE); |
---|
| 10729 | + if (ret < 0) { |
---|
| 10730 | + DHD_ERROR(("%s Set scancache failed %d\n", __FUNCTION__, ret)); |
---|
| 10731 | + } |
---|
| 10732 | + |
---|
| 10733 | +#else /* OEM_ANDROID */ |
---|
| 10734 | + |
---|
8777 | 10735 | if ((ret = dhd_apply_default_clm(dhd, clm_path)) < 0) { |
---|
8778 | 10736 | DHD_ERROR(("%s: CLM set failed. Abort initialization.\n", __FUNCTION__)); |
---|
8779 | 10737 | goto done; |
---|
8780 | 10738 | } |
---|
8781 | 10739 | |
---|
8782 | | -#ifdef USE_WL_TXBF |
---|
8783 | | - if ((ret = dhd_iovar(dhd, 0, "txbf", (char *)&txbf, sizeof(txbf), NULL, 0, TRUE)) < 0) { |
---|
8784 | | - DHD_ERROR(("%s Set txbf failed %d\n", __FUNCTION__, ret)); |
---|
| 10740 | +#if defined(KEEP_ALIVE) |
---|
| 10741 | + if (!(dhd->op_mode & |
---|
| 10742 | + (DHD_FLAG_HOSTAP_MODE | DHD_FLAG_MFG_MODE))) { |
---|
| 10743 | + if ((ret = dhd_keep_alive_onoff(dhd)) < 0) |
---|
| 10744 | + DHD_ERROR(("%s set keeplive failed %d\n", |
---|
| 10745 | + __FUNCTION__, ret)); |
---|
8785 | 10746 | } |
---|
8786 | | -#endif /* USE_WL_TXBF */ |
---|
| 10747 | +#endif // endif |
---|
| 10748 | + |
---|
| 10749 | + /* get a capabilities from firmware */ |
---|
| 10750 | + memset(dhd->fw_capabilities, 0, sizeof(dhd->fw_capabilities)); |
---|
| 10751 | + ret = dhd_iovar(dhd, 0, "cap", NULL, 0, dhd->fw_capabilities, sizeof(dhd->fw_capabilities), |
---|
| 10752 | + FALSE); |
---|
| 10753 | + if (ret < 0) { |
---|
| 10754 | + DHD_ERROR(("%s: Get Capability failed (error=%d)\n", |
---|
| 10755 | + __FUNCTION__, ret)); |
---|
| 10756 | + goto done; |
---|
| 10757 | + } |
---|
| 10758 | +#endif /* OEM_ANDROID */ |
---|
| 10759 | + |
---|
| 10760 | + ret = dhd_iovar(dhd, 0, "event_log_max_sets", NULL, 0, (char *)&event_log_max_sets, |
---|
| 10761 | + sizeof(event_log_max_sets), FALSE); |
---|
| 10762 | + if (ret == BCME_OK) { |
---|
| 10763 | + dhd->event_log_max_sets = event_log_max_sets; |
---|
| 10764 | + } else { |
---|
| 10765 | + dhd->event_log_max_sets = NUM_EVENT_LOG_SETS; |
---|
| 10766 | + } |
---|
| 10767 | + /* Make sure max_sets is set first with wmb and then sets_queried, |
---|
| 10768 | + * this will be used during parsing the logsets in the reverse order. |
---|
| 10769 | + */ |
---|
| 10770 | + OSL_SMP_WMB(); |
---|
| 10771 | + dhd->event_log_max_sets_queried = TRUE; |
---|
| 10772 | + DHD_ERROR(("%s: event_log_max_sets: %d ret: %d\n", |
---|
| 10773 | + __FUNCTION__, dhd->event_log_max_sets, ret)); |
---|
| 10774 | +#ifdef DHD_BUS_MEM_ACCESS |
---|
| 10775 | + ret = dhd_iovar(dhd, 0, "enable_memuse", (char *)&enable_memuse, |
---|
| 10776 | + sizeof(enable_memuse), iovbuf, sizeof(iovbuf), FALSE); |
---|
| 10777 | + if (ret < 0) { |
---|
| 10778 | + DHD_ERROR(("%s: enable_memuse is failed ret=%d\n", |
---|
| 10779 | + __FUNCTION__, ret)); |
---|
| 10780 | + } else { |
---|
| 10781 | + DHD_ERROR(("%s: enable_memuse = %d\n", |
---|
| 10782 | + __FUNCTION__, enable_memuse)); |
---|
| 10783 | + } |
---|
| 10784 | +#endif /* DHD_BUS_MEM_ACCESS */ |
---|
| 10785 | + |
---|
8787 | 10786 | #ifdef DISABLE_TXBFR |
---|
8788 | | - bcm_mkiovar("txbf_bfr_cap", (char *)&txbf_bfr_cap, 4, iovbuf, sizeof(iovbuf)); |
---|
8789 | | - if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, |
---|
8790 | | - sizeof(iovbuf), TRUE, 0)) < 0) { |
---|
| 10787 | + ret = dhd_iovar(dhd, 0, "txbf_bfr_cap", (char *)&txbf_bfr_cap, sizeof(txbf_bfr_cap), NULL, |
---|
| 10788 | + 0, TRUE); |
---|
| 10789 | + if (ret < 0) { |
---|
8791 | 10790 | DHD_ERROR(("%s Clear txbf_bfr_cap failed %d\n", __FUNCTION__, ret)); |
---|
8792 | 10791 | } |
---|
8793 | 10792 | #endif /* DISABLE_TXBFR */ |
---|
| 10793 | + |
---|
| 10794 | +#ifdef USE_WFA_CERT_CONF |
---|
| 10795 | +#ifdef USE_WL_FRAMEBURST |
---|
| 10796 | + if (sec_get_param_wfa_cert(dhd, SET_PARAM_FRAMEBURST, &frameburst) == BCME_OK) { |
---|
| 10797 | + DHD_ERROR(("%s, read frameburst param=%d\n", __FUNCTION__, frameburst)); |
---|
| 10798 | + } |
---|
| 10799 | +#endif /* USE_WL_FRAMEBURST */ |
---|
| 10800 | + g_frameburst = frameburst; |
---|
| 10801 | +#endif /* USE_WFA_CERT_CONF */ |
---|
8794 | 10802 | #ifdef DISABLE_WL_FRAMEBURST_SOFTAP |
---|
8795 | 10803 | /* Disable Framebursting for SofAP */ |
---|
8796 | 10804 | if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { |
---|
8797 | 10805 | frameburst = 0; |
---|
8798 | 10806 | } |
---|
8799 | 10807 | #endif /* DISABLE_WL_FRAMEBURST_SOFTAP */ |
---|
8800 | | -/* Set frameburst to value */ |
---|
| 10808 | + /* Set frameburst to value */ |
---|
8801 | 10809 | if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_FAKEFRAG, (char *)&frameburst, |
---|
8802 | 10810 | sizeof(frameburst), TRUE, 0)) < 0) { |
---|
8803 | 10811 | DHD_INFO(("%s frameburst not supported %d\n", __FUNCTION__, ret)); |
---|
8804 | 10812 | } |
---|
8805 | | -#if defined(CUSTOM_AMPDU_BA_WSIZE) |
---|
| 10813 | +#ifdef DHD_SET_FW_HIGHSPEED |
---|
| 10814 | + /* Set ack_ratio */ |
---|
| 10815 | + ret = dhd_iovar(dhd, 0, "ack_ratio", (char *)&ack_ratio, sizeof(ack_ratio), NULL, 0, TRUE); |
---|
| 10816 | + if (ret < 0) { |
---|
| 10817 | + DHD_ERROR(("%s Set ack_ratio failed %d\n", __FUNCTION__, ret)); |
---|
| 10818 | + } |
---|
| 10819 | + |
---|
| 10820 | + /* Set ack_ratio_depth */ |
---|
| 10821 | + ret = dhd_iovar(dhd, 0, "ack_ratio_depth", (char *)&ack_ratio_depth, |
---|
| 10822 | + sizeof(ack_ratio_depth), NULL, 0, TRUE); |
---|
| 10823 | + if (ret < 0) { |
---|
| 10824 | + DHD_ERROR(("%s Set ack_ratio_depth failed %d\n", __FUNCTION__, ret)); |
---|
| 10825 | + } |
---|
| 10826 | +#endif /* DHD_SET_FW_HIGHSPEED */ |
---|
| 10827 | + |
---|
| 10828 | + iov_buf = (char*)MALLOC(dhd->osh, WLC_IOCTL_SMLEN); |
---|
| 10829 | + if (iov_buf == NULL) { |
---|
| 10830 | + DHD_ERROR(("failed to allocate %d bytes for iov_buf\n", WLC_IOCTL_SMLEN)); |
---|
| 10831 | + ret = BCME_NOMEM; |
---|
| 10832 | + goto done; |
---|
| 10833 | + } |
---|
| 10834 | + |
---|
| 10835 | +#ifdef WLAIBSS |
---|
| 10836 | + /* Apply AIBSS configurations */ |
---|
| 10837 | + if ((ret = dhd_preinit_aibss_ioctls(dhd, iov_buf)) != BCME_OK) { |
---|
| 10838 | + DHD_ERROR(("%s dhd_preinit_aibss_ioctls failed %d\n", |
---|
| 10839 | + __FUNCTION__, ret)); |
---|
| 10840 | + goto done; |
---|
| 10841 | + } |
---|
| 10842 | +#endif /* WLAIBSS */ |
---|
| 10843 | + |
---|
| 10844 | +#if defined(CUSTOM_AMPDU_BA_WSIZE) || (defined(WLAIBSS) && \ |
---|
| 10845 | + defined(CUSTOM_IBSS_AMPDU_BA_WSIZE)) |
---|
8806 | 10846 | /* Set ampdu ba wsize to 64 or 16 */ |
---|
8807 | 10847 | #ifdef CUSTOM_AMPDU_BA_WSIZE |
---|
8808 | 10848 | ampdu_ba_wsize = CUSTOM_AMPDU_BA_WSIZE; |
---|
8809 | | -#endif |
---|
| 10849 | +#endif // endif |
---|
| 10850 | +#if defined(WLAIBSS) && defined(CUSTOM_IBSS_AMPDU_BA_WSIZE) |
---|
| 10851 | + if (dhd->op_mode == DHD_FLAG_IBSS_MODE) |
---|
| 10852 | + ampdu_ba_wsize = CUSTOM_IBSS_AMPDU_BA_WSIZE; |
---|
| 10853 | +#endif /* WLAIBSS && CUSTOM_IBSS_AMPDU_BA_WSIZE */ |
---|
8810 | 10854 | if (ampdu_ba_wsize != 0) { |
---|
8811 | 10855 | ret = dhd_iovar(dhd, 0, "ampdu_ba_wsize", (char *)&du_ba_wsize, |
---|
8812 | 10856 | sizeof(ampdu_ba_wsize), NULL, 0, TRUE); |
---|
.. | .. |
---|
8815 | 10859 | __FUNCTION__, ampdu_ba_wsize, ret)); |
---|
8816 | 10860 | } |
---|
8817 | 10861 | } |
---|
8818 | | -#endif |
---|
8819 | | - |
---|
8820 | | - iov_buf = (char*)kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL); |
---|
8821 | | - if (iov_buf == NULL) { |
---|
8822 | | - DHD_ERROR(("failed to allocate %d bytes for iov_buf\n", WLC_IOCTL_SMLEN)); |
---|
8823 | | - ret = BCME_NOMEM; |
---|
8824 | | - goto done; |
---|
8825 | | - } |
---|
| 10862 | +#endif /* CUSTOM_AMPDU_BA_WSIZE || (WLAIBSS && CUSTOM_IBSS_AMPDU_BA_WSIZE) */ |
---|
8826 | 10863 | |
---|
8827 | 10864 | #if defined(CUSTOM_AMPDU_MPDU) |
---|
8828 | 10865 | ampdu_mpdu = CUSTOM_AMPDU_MPDU; |
---|
.. | .. |
---|
8854 | 10891 | ret = dhd_iovar(dhd, 0, "amsdu_aggsf", (char *)&amsdu_aggsf, sizeof(amsdu_aggsf), |
---|
8855 | 10892 | NULL, 0, TRUE); |
---|
8856 | 10893 | if (ret < 0) { |
---|
8857 | | - DHD_ERROR(("%s Set amsdu_aggsf to %d failed %d\n", |
---|
| 10894 | + DHD_ERROR(("%s Set amsdu_aggsf to %d failed %d\n", |
---|
8858 | 10895 | __FUNCTION__, CUSTOM_AMSDU_AGGSF, ret)); |
---|
8859 | 10896 | } |
---|
8860 | 10897 | } |
---|
8861 | 10898 | #endif /* CUSTOM_AMSDU_AGGSF */ |
---|
8862 | 10899 | |
---|
| 10900 | +#if defined(BCMSUP_4WAY_HANDSHAKE) |
---|
| 10901 | + /* Read 4-way handshake requirements */ |
---|
| 10902 | + if (dhd_use_idsup == 1) { |
---|
| 10903 | + ret = dhd_iovar(dhd, 0, "sup_wpa", (char *)&sup_wpa, sizeof(sup_wpa), |
---|
| 10904 | + (char *)&iovbuf, sizeof(iovbuf), FALSE); |
---|
| 10905 | + /* sup_wpa iovar returns NOTREADY status on some platforms using modularized |
---|
| 10906 | + * in-dongle supplicant. |
---|
| 10907 | + */ |
---|
| 10908 | + if (ret >= 0 || ret == BCME_NOTREADY) |
---|
| 10909 | + dhd->fw_4way_handshake = TRUE; |
---|
| 10910 | + DHD_TRACE(("4-way handshake mode is: %d\n", dhd->fw_4way_handshake)); |
---|
| 10911 | + } |
---|
| 10912 | +#endif /* BCMSUP_4WAY_HANDSHAKE */ |
---|
| 10913 | +#if defined(SUPPORT_2G_VHT) || defined(SUPPORT_5G_1024QAM_VHT) |
---|
| 10914 | + ret = dhd_iovar(dhd, 0, "vht_features", (char *)&vht_features, sizeof(vht_features), |
---|
| 10915 | + NULL, 0, FALSE); |
---|
| 10916 | + if (ret < 0) { |
---|
| 10917 | + DHD_ERROR(("%s vht_features get failed %d\n", __FUNCTION__, ret)); |
---|
| 10918 | + vht_features = 0; |
---|
| 10919 | + } else { |
---|
| 10920 | +#ifdef SUPPORT_2G_VHT |
---|
| 10921 | + vht_features |= 0x3; /* 2G support */ |
---|
| 10922 | +#endif /* SUPPORT_2G_VHT */ |
---|
| 10923 | +#ifdef SUPPORT_5G_1024QAM_VHT |
---|
| 10924 | + vht_features |= 0x6; /* 5G 1024 QAM support */ |
---|
| 10925 | +#endif /* SUPPORT_5G_1024QAM_VHT */ |
---|
| 10926 | + } |
---|
| 10927 | + if (vht_features) { |
---|
| 10928 | + ret = dhd_iovar(dhd, 0, "vht_features", (char *)&vht_features, sizeof(vht_features), |
---|
| 10929 | + NULL, 0, TRUE); |
---|
| 10930 | + if (ret < 0) { |
---|
| 10931 | + DHD_ERROR(("%s vht_features set failed %d\n", __FUNCTION__, ret)); |
---|
| 10932 | + |
---|
| 10933 | + if (ret == BCME_NOTDOWN) { |
---|
| 10934 | + uint wl_down = 1; |
---|
| 10935 | + ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, |
---|
| 10936 | + (char *)&wl_down, sizeof(wl_down), TRUE, 0); |
---|
| 10937 | + DHD_ERROR(("%s vht_features fail WL_DOWN : %d," |
---|
| 10938 | + " vht_features = 0x%x\n", |
---|
| 10939 | + __FUNCTION__, ret, vht_features)); |
---|
| 10940 | + |
---|
| 10941 | + ret = dhd_iovar(dhd, 0, "vht_features", (char *)&vht_features, |
---|
| 10942 | + sizeof(vht_features), NULL, 0, TRUE); |
---|
| 10943 | + |
---|
| 10944 | + DHD_ERROR(("%s vht_features set. ret --> %d\n", __FUNCTION__, ret)); |
---|
| 10945 | + } |
---|
| 10946 | + } |
---|
| 10947 | + } |
---|
| 10948 | +#endif /* SUPPORT_2G_VHT || SUPPORT_5G_1024QAM_VHT */ |
---|
| 10949 | +#ifdef DISABLE_11N_PROPRIETARY_RATES |
---|
| 10950 | + ret = dhd_iovar(dhd, 0, "ht_features", (char *)&ht_features, sizeof(ht_features), NULL, 0, |
---|
| 10951 | + TRUE); |
---|
| 10952 | + if (ret < 0) { |
---|
| 10953 | + DHD_ERROR(("%s ht_features set failed %d\n", __FUNCTION__, ret)); |
---|
| 10954 | + } |
---|
| 10955 | +#endif /* DISABLE_11N_PROPRIETARY_RATES */ |
---|
| 10956 | +#if defined(DISABLE_HE_ENAB) || defined(CUSTOM_CONTROL_HE_ENAB) |
---|
| 10957 | +#if defined(DISABLE_HE_ENAB) |
---|
| 10958 | + control_he_enab = 0; |
---|
| 10959 | +#endif /* DISABLE_HE_ENAB */ |
---|
| 10960 | + dhd_control_he_enab(dhd, control_he_enab); |
---|
| 10961 | +#endif /* DISABLE_HE_ENAB || CUSTOM_CONTROL_HE_ENAB */ |
---|
| 10962 | + |
---|
8863 | 10963 | #ifdef CUSTOM_PSPRETEND_THR |
---|
8864 | 10964 | /* Turn off MPC in AP mode */ |
---|
8865 | | - if ((ret = dhd_iovar(dhd, 0, "pspretend_threshold", (char *)&pspretend_thr, |
---|
8866 | | - sizeof(pspretend_thr), NULL, 0, TRUE)) < 0) { |
---|
| 10965 | + ret = dhd_iovar(dhd, 0, "pspretend_threshold", (char *)&pspretend_thr, |
---|
| 10966 | + sizeof(pspretend_thr), NULL, 0, TRUE); |
---|
| 10967 | + if (ret < 0) { |
---|
8867 | 10968 | DHD_ERROR(("%s pspretend_threshold for HostAPD failed %d\n", |
---|
8868 | 10969 | __FUNCTION__, ret)); |
---|
8869 | 10970 | } |
---|
8870 | | -#endif |
---|
| 10971 | +#endif // endif |
---|
8871 | 10972 | |
---|
8872 | | - if ((ret = dhd_iovar(dhd, 0, "buf_key_b4_m4", (char *)&buf_key_b4_m4, |
---|
8873 | | - sizeof(buf_key_b4_m4), NULL, 0, TRUE)) < 0) { |
---|
| 10973 | + ret = dhd_iovar(dhd, 0, "buf_key_b4_m4", (char *)&buf_key_b4_m4, sizeof(buf_key_b4_m4), |
---|
| 10974 | + NULL, 0, TRUE); |
---|
| 10975 | + if (ret < 0) { |
---|
8874 | 10976 | DHD_ERROR(("%s buf_key_b4_m4 set failed %d\n", __FUNCTION__, ret)); |
---|
8875 | 10977 | } |
---|
| 10978 | +#ifdef SUPPORT_SET_CAC |
---|
| 10979 | + ret = dhd_iovar(dhd, 0, "cac", (char *)&cac, sizeof(cac), NULL, 0, TRUE); |
---|
| 10980 | + if (ret < 0) { |
---|
| 10981 | + DHD_ERROR(("%s Failed to set cac to %d, %d\n", __FUNCTION__, cac, ret)); |
---|
| 10982 | + } |
---|
| 10983 | +#endif /* SUPPORT_SET_CAC */ |
---|
| 10984 | +#ifdef DHD_ULP |
---|
| 10985 | + /* Get the required details from dongle during preinit ioctl */ |
---|
| 10986 | + dhd_ulp_preinit(dhd); |
---|
| 10987 | +#endif /* DHD_ULP */ |
---|
8876 | 10988 | |
---|
8877 | 10989 | /* Read event_msgs mask */ |
---|
8878 | 10990 | ret = dhd_iovar(dhd, 0, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, |
---|
.. | .. |
---|
8881 | 10993 | DHD_ERROR(("%s read Event mask failed %d\n", __FUNCTION__, ret)); |
---|
8882 | 10994 | goto done; |
---|
8883 | 10995 | } |
---|
8884 | | - memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN); |
---|
| 10996 | + bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN); |
---|
8885 | 10997 | |
---|
8886 | 10998 | /* Setup event_msgs */ |
---|
8887 | 10999 | setbit(eventmask, WLC_E_SET_SSID); |
---|
.. | .. |
---|
8906 | 11018 | setbit(eventmask, WLC_E_ASSOC_RESP_IE); |
---|
8907 | 11019 | #ifdef LIMIT_BORROW |
---|
8908 | 11020 | setbit(eventmask, WLC_E_ALLOW_CREDIT_BORROW); |
---|
8909 | | -#endif |
---|
| 11021 | +#endif // endif |
---|
8910 | 11022 | #ifndef WL_CFG80211 |
---|
8911 | 11023 | setbit(eventmask, WLC_E_PMKID_CACHE); |
---|
8912 | 11024 | setbit(eventmask, WLC_E_TXFAIL); |
---|
8913 | | -#endif |
---|
| 11025 | +#endif // endif |
---|
8914 | 11026 | setbit(eventmask, WLC_E_JOIN_START); |
---|
8915 | 11027 | setbit(eventmask, WLC_E_SCAN_COMPLETE); |
---|
8916 | 11028 | #ifdef DHD_DEBUG |
---|
8917 | 11029 | setbit(eventmask, WLC_E_SCAN_CONFIRM_IND); |
---|
8918 | | -#endif |
---|
8919 | | -#ifdef WLMEDIA_HTSF |
---|
8920 | | - setbit(eventmask, WLC_E_HTSFSYNC); |
---|
8921 | | -#endif /* WLMEDIA_HTSF */ |
---|
| 11030 | +#endif // endif |
---|
8922 | 11031 | #ifdef PNO_SUPPORT |
---|
8923 | 11032 | setbit(eventmask, WLC_E_PFN_NET_FOUND); |
---|
8924 | 11033 | setbit(eventmask, WLC_E_PFN_BEST_BATCHING); |
---|
.. | .. |
---|
8926 | 11035 | setbit(eventmask, WLC_E_PFN_BSSID_NET_LOST); |
---|
8927 | 11036 | #endif /* PNO_SUPPORT */ |
---|
8928 | 11037 | /* enable dongle roaming event */ |
---|
| 11038 | +#ifdef WL_CFG80211 |
---|
| 11039 | +#if !defined(ROAM_EVT_DISABLE) |
---|
8929 | 11040 | setbit(eventmask, WLC_E_ROAM); |
---|
| 11041 | +#endif /* !ROAM_EVT_DISABLE */ |
---|
8930 | 11042 | setbit(eventmask, WLC_E_BSSID); |
---|
| 11043 | +#endif /* WL_CFG80211 */ |
---|
| 11044 | +#ifdef BCMCCX |
---|
| 11045 | + setbit(eventmask, WLC_E_ADDTS_IND); |
---|
| 11046 | + setbit(eventmask, WLC_E_DELTS_IND); |
---|
| 11047 | +#endif /* BCMCCX */ |
---|
8931 | 11048 | #ifdef WLTDLS |
---|
8932 | 11049 | setbit(eventmask, WLC_E_TDLS_PEER_EVENT); |
---|
8933 | 11050 | #endif /* WLTDLS */ |
---|
8934 | 11051 | #ifdef RTT_SUPPORT |
---|
8935 | 11052 | setbit(eventmask, WLC_E_PROXD); |
---|
8936 | 11053 | #endif /* RTT_SUPPORT */ |
---|
| 11054 | +#if !defined(WL_CFG80211) && !defined(OEM_ANDROID) |
---|
| 11055 | + setbit(eventmask, WLC_E_ESCAN_RESULT); |
---|
| 11056 | +#endif // endif |
---|
8937 | 11057 | #ifdef WL_CFG80211 |
---|
8938 | 11058 | setbit(eventmask, WLC_E_ESCAN_RESULT); |
---|
| 11059 | + setbit(eventmask, WLC_E_AP_STARTED); |
---|
| 11060 | + setbit(eventmask, WLC_E_ACTION_FRAME_RX); |
---|
8939 | 11061 | if (dhd->op_mode & DHD_FLAG_P2P_MODE) { |
---|
8940 | | - setbit(eventmask, WLC_E_ACTION_FRAME_RX); |
---|
8941 | 11062 | setbit(eventmask, WLC_E_P2P_DISC_LISTEN_COMPLETE); |
---|
8942 | 11063 | } |
---|
8943 | 11064 | #endif /* WL_CFG80211 */ |
---|
| 11065 | +#ifdef WLAIBSS |
---|
| 11066 | + setbit(eventmask, WLC_E_AIBSS_TXFAIL); |
---|
| 11067 | +#endif /* WLAIBSS */ |
---|
| 11068 | + |
---|
| 11069 | +#if defined(SHOW_LOGTRACE) && defined(LOGTRACE_FROM_FILE) |
---|
| 11070 | + if (dhd_logtrace_from_file(dhd)) { |
---|
| 11071 | + setbit(eventmask, WLC_E_TRACE); |
---|
| 11072 | + } else { |
---|
| 11073 | + clrbit(eventmask, WLC_E_TRACE); |
---|
| 11074 | + } |
---|
| 11075 | +#elif defined(SHOW_LOGTRACE) |
---|
8944 | 11076 | setbit(eventmask, WLC_E_TRACE); |
---|
| 11077 | +#else |
---|
| 11078 | + clrbit(eventmask, WLC_E_TRACE); |
---|
| 11079 | +#endif /* defined(SHOW_LOGTRACE) && defined(LOGTRACE_FROM_FILE) */ |
---|
| 11080 | + |
---|
8945 | 11081 | setbit(eventmask, WLC_E_CSA_COMPLETE_IND); |
---|
| 11082 | +#ifdef CUSTOM_EVENT_PM_WAKE |
---|
| 11083 | + setbit(eventmask, WLC_E_EXCESS_PM_WAKE_EVENT); |
---|
| 11084 | +#endif /* CUSTOM_EVENT_PM_WAKE */ |
---|
8946 | 11085 | #ifdef DHD_LOSSLESS_ROAMING |
---|
8947 | 11086 | setbit(eventmask, WLC_E_ROAM_PREP); |
---|
8948 | | -#endif |
---|
8949 | | -#ifdef DHD_WMF |
---|
8950 | | - setbit(eventmask, WLC_E_PSTA_PRIMARY_INTF_IND); |
---|
8951 | | -#endif |
---|
| 11087 | +#endif // endif |
---|
| 11088 | + /* nan events */ |
---|
| 11089 | + setbit(eventmask, WLC_E_NAN); |
---|
8952 | 11090 | #if defined(PCIE_FULL_DONGLE) && defined(DHD_LOSSLESS_ROAMING) |
---|
8953 | 11091 | dhd_update_flow_prio_map(dhd, DHD_FLOW_PRIO_LLR_MAP); |
---|
8954 | 11092 | #endif /* defined(PCIE_FULL_DONGLE) && defined(DHD_LOSSLESS_ROAMING) */ |
---|
| 11093 | + |
---|
| 11094 | +#if defined(BCMPCIE) && defined(EAPOL_PKT_PRIO) |
---|
| 11095 | + dhd_update_flow_prio_map(dhd, DHD_FLOW_PRIO_LLR_MAP); |
---|
| 11096 | +#endif /* defined(BCMPCIE) && defined(EAPOL_PKT_PRIO) */ |
---|
8955 | 11097 | |
---|
8956 | 11098 | /* Write updated Event mask */ |
---|
8957 | 11099 | ret = dhd_iovar(dhd, 0, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, NULL, 0, TRUE); |
---|
.. | .. |
---|
8962 | 11104 | |
---|
8963 | 11105 | /* make up event mask ext message iovar for event larger than 128 */ |
---|
8964 | 11106 | msglen = ROUNDUP(WLC_E_LAST, NBBY)/NBBY + EVENTMSGS_EXT_STRUCT_SIZE; |
---|
8965 | | - eventmask_msg = (eventmsgs_ext_t*)kmalloc(msglen, GFP_KERNEL); |
---|
| 11107 | + eventmask_msg = (eventmsgs_ext_t*)MALLOC(dhd->osh, msglen); |
---|
8966 | 11108 | if (eventmask_msg == NULL) { |
---|
8967 | 11109 | DHD_ERROR(("failed to allocate %d bytes for event_msg_ext\n", msglen)); |
---|
8968 | 11110 | ret = BCME_NOMEM; |
---|
.. | .. |
---|
8976 | 11118 | ret2 = dhd_iovar(dhd, 0, "event_msgs_ext", (char *)eventmask_msg, msglen, iov_buf, |
---|
8977 | 11119 | WLC_IOCTL_SMLEN, FALSE); |
---|
8978 | 11120 | |
---|
8979 | | - if (ret2 != BCME_UNSUPPORTED) |
---|
8980 | | - ret = ret2; |
---|
8981 | 11121 | if (ret2 == 0) { /* event_msgs_ext must be supported */ |
---|
8982 | | - memcpy(eventmask_msg, iov_buf, msglen); |
---|
| 11122 | + bcopy(iov_buf, eventmask_msg, msglen); |
---|
| 11123 | +#ifdef RSSI_MONITOR_SUPPORT |
---|
| 11124 | + setbit(eventmask_msg->mask, WLC_E_RSSI_LQM); |
---|
| 11125 | +#endif /* RSSI_MONITOR_SUPPORT */ |
---|
8983 | 11126 | #ifdef GSCAN_SUPPORT |
---|
8984 | 11127 | setbit(eventmask_msg->mask, WLC_E_PFN_GSCAN_FULL_RESULT); |
---|
8985 | 11128 | setbit(eventmask_msg->mask, WLC_E_PFN_SCAN_COMPLETE); |
---|
8986 | | - setbit(eventmask_msg->mask, WLC_E_PFN_SWC); |
---|
8987 | 11129 | setbit(eventmask_msg->mask, WLC_E_PFN_SSID_EXT); |
---|
8988 | 11130 | setbit(eventmask_msg->mask, WLC_E_ROAM_EXP_EVENT); |
---|
8989 | 11131 | #endif /* GSCAN_SUPPORT */ |
---|
.. | .. |
---|
8991 | 11133 | #ifdef BT_WIFI_HANDOVER |
---|
8992 | 11134 | setbit(eventmask_msg->mask, WLC_E_BT_WIFI_HANDOVER_REQ); |
---|
8993 | 11135 | #endif /* BT_WIFI_HANDOVER */ |
---|
| 11136 | +#ifdef DBG_PKT_MON |
---|
| 11137 | + setbit(eventmask_msg->mask, WLC_E_ROAM_PREP); |
---|
| 11138 | +#endif /* DBG_PKT_MON */ |
---|
8994 | 11139 | #ifdef DHD_ULP |
---|
8995 | 11140 | setbit(eventmask_msg->mask, WLC_E_ULP); |
---|
8996 | | -#endif |
---|
| 11141 | +#endif // endif |
---|
| 11142 | +#ifdef WL_NATOE |
---|
| 11143 | + setbit(eventmask_msg->mask, WLC_E_NATOE_NFCT); |
---|
| 11144 | +#endif /* WL_NATOE */ |
---|
| 11145 | +#ifdef WL_NAN |
---|
| 11146 | + setbit(eventmask_msg->mask, WLC_E_SLOTTED_BSS_PEER_OP); |
---|
| 11147 | +#endif /* WL_NAN */ |
---|
| 11148 | +#ifdef WL_MBO |
---|
| 11149 | + setbit(eventmask_msg->mask, WLC_E_MBO); |
---|
| 11150 | +#endif /* WL_MBO */ |
---|
| 11151 | +#ifdef WL_BCNRECV |
---|
| 11152 | + setbit(eventmask_msg->mask, WLC_E_BCNRECV_ABORTED); |
---|
| 11153 | +#endif /* WL_BCNRECV */ |
---|
| 11154 | +#ifdef WL_CAC_TS |
---|
| 11155 | + setbit(eventmask_msg->mask, WLC_E_ADDTS_IND); |
---|
| 11156 | + setbit(eventmask_msg->mask, WLC_E_DELTS_IND); |
---|
| 11157 | +#endif /* WL_CAC_TS */ |
---|
| 11158 | +#ifdef WL_CHAN_UTIL |
---|
| 11159 | + setbit(eventmask_msg->mask, WLC_E_BSS_LOAD); |
---|
| 11160 | +#endif /* WL_CHAN_UTIL */ |
---|
| 11161 | +#ifdef WL_SAE |
---|
| 11162 | + setbit(eventmask_msg->mask, WLC_E_EXT_AUTH_REQ); |
---|
| 11163 | + setbit(eventmask_msg->mask, WLC_E_EXT_AUTH_FRAME_RX); |
---|
| 11164 | + setbit(eventmask_msg->mask, WLC_E_MGMT_FRAME_TXSTATUS); |
---|
| 11165 | + setbit(eventmask_msg->mask, WLC_E_MGMT_FRAME_OFF_CHAN_COMPLETE); |
---|
| 11166 | +#endif /* WL_SAE */ |
---|
| 11167 | +#ifndef CONFIG_SOC_S5E5515 |
---|
| 11168 | + setbit(eventmask_msg->mask, WLC_E_IND_DOS_STATUS); |
---|
| 11169 | +#endif // endif |
---|
| 11170 | +#ifdef ENABLE_HOGSQS |
---|
| 11171 | + setbit(eventmask_msg->mask, WLC_E_LDF_HOGGER); |
---|
| 11172 | +#endif /* ENABLE_HOGSQS */ |
---|
| 11173 | + |
---|
| 11174 | + /* over temp event */ |
---|
| 11175 | + setbit(eventmask_msg->mask, WLC_E_OVERTEMP); |
---|
8997 | 11176 | |
---|
8998 | 11177 | /* Write updated Event mask */ |
---|
8999 | 11178 | eventmask_msg->ver = EVENTMSGS_VER; |
---|
.. | .. |
---|
9005 | 11184 | DHD_ERROR(("%s write event mask ext failed %d\n", __FUNCTION__, ret)); |
---|
9006 | 11185 | goto done; |
---|
9007 | 11186 | } |
---|
9008 | | - } else if (ret2 < 0 && ret2 == BCME_VERSION) { |
---|
9009 | | - DHD_ERROR(("%s Different Event version\n", __FUNCTION__)); |
---|
9010 | | - } else if (ret2 < 0 && ret2 != BCME_UNSUPPORTED) { |
---|
| 11187 | + } else if (ret2 == BCME_UNSUPPORTED || ret2 == BCME_VERSION) { |
---|
| 11188 | + /* Skip for BCME_UNSUPPORTED or BCME_VERSION */ |
---|
| 11189 | + DHD_ERROR(("%s event_msgs_ext not support or version mismatch %d\n", |
---|
| 11190 | + __FUNCTION__, ret2)); |
---|
| 11191 | + } else { |
---|
9011 | 11192 | DHD_ERROR(("%s read event mask ext failed %d\n", __FUNCTION__, ret2)); |
---|
| 11193 | + ret = ret2; |
---|
9012 | 11194 | goto done; |
---|
9013 | | - } /* unsupported is ok */ |
---|
| 11195 | + } |
---|
9014 | 11196 | |
---|
| 11197 | +#if defined(DHD_8021X_DUMP) && defined(SHOW_LOGTRACE) |
---|
| 11198 | + /* Enabling event log trace for EAP events */ |
---|
| 11199 | + el_tag = (wl_el_tag_params_t *)MALLOC(dhd->osh, sizeof(wl_el_tag_params_t)); |
---|
| 11200 | + if (el_tag == NULL) { |
---|
| 11201 | + DHD_ERROR(("failed to allocate %d bytes for event_msg_ext\n", |
---|
| 11202 | + (int)sizeof(wl_el_tag_params_t))); |
---|
| 11203 | + ret = BCME_NOMEM; |
---|
| 11204 | + goto done; |
---|
| 11205 | + } |
---|
| 11206 | + el_tag->tag = EVENT_LOG_TAG_4WAYHANDSHAKE; |
---|
| 11207 | + el_tag->set = 1; |
---|
| 11208 | + el_tag->flags = EVENT_LOG_TAG_FLAG_LOG; |
---|
| 11209 | + ret = dhd_iovar(dhd, 0, "event_log_tag_control", (char *)el_tag, sizeof(*el_tag), NULL, 0, |
---|
| 11210 | + TRUE); |
---|
| 11211 | +#endif /* DHD_8021X_DUMP */ |
---|
| 11212 | + |
---|
| 11213 | +#ifdef OEM_ANDROID |
---|
9015 | 11214 | dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time, |
---|
9016 | | - sizeof(scan_assoc_time), TRUE, 0); |
---|
| 11215 | + sizeof(scan_assoc_time), TRUE, 0); |
---|
9017 | 11216 | dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time, |
---|
9018 | | - sizeof(scan_unassoc_time), TRUE, 0); |
---|
| 11217 | + sizeof(scan_unassoc_time), TRUE, 0); |
---|
9019 | 11218 | dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_PASSIVE_TIME, (char *)&scan_passive_time, |
---|
9020 | | - sizeof(scan_passive_time), TRUE, 0); |
---|
| 11219 | + sizeof(scan_passive_time), TRUE, 0); |
---|
9021 | 11220 | |
---|
9022 | 11221 | #ifdef ARP_OFFLOAD_SUPPORT |
---|
9023 | 11222 | /* Set and enable ARP offload feature for STA only */ |
---|
9024 | | -#if defined(SOFTAP) |
---|
| 11223 | +#if defined(OEM_ANDROID) && defined(SOFTAP) |
---|
9025 | 11224 | if (arpoe && !ap_fw_loaded) { |
---|
9026 | 11225 | #else |
---|
9027 | 11226 | if (arpoe) { |
---|
9028 | | -#endif |
---|
| 11227 | +#endif /* defined(OEM_ANDROID) && defined(SOFTAP) */ |
---|
9029 | 11228 | dhd_arp_offload_enable(dhd, TRUE); |
---|
9030 | 11229 | dhd_arp_offload_set(dhd, dhd_arp_mode); |
---|
9031 | 11230 | } else { |
---|
.. | .. |
---|
9038 | 11237 | #ifdef PKT_FILTER_SUPPORT |
---|
9039 | 11238 | /* Setup default defintions for pktfilter , enable in suspend */ |
---|
9040 | 11239 | dhd->pktfilter_count = 6; |
---|
9041 | | - /* Setup filter to allow only unicast */ |
---|
9042 | | - dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0x01 0x00"; |
---|
9043 | 11240 | dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = NULL; |
---|
9044 | | - dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = NULL; |
---|
9045 | | - dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL; |
---|
9046 | | - /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */ |
---|
9047 | | - dhd->pktfilter[DHD_MDNS_FILTER_NUM] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB"; |
---|
| 11241 | + if (!FW_SUPPORTED(dhd, pf6)) { |
---|
| 11242 | + dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = NULL; |
---|
| 11243 | + dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL; |
---|
| 11244 | + } else { |
---|
| 11245 | + /* Immediately pkt filter TYPE 6 Discard IPv4/IPv6 Multicast Packet */ |
---|
| 11246 | + dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = DISCARD_IPV4_MCAST; |
---|
| 11247 | + dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = DISCARD_IPV6_MCAST; |
---|
| 11248 | + } |
---|
9048 | 11249 | /* apply APP pktfilter */ |
---|
9049 | 11250 | dhd->pktfilter[DHD_ARP_FILTER_NUM] = "105 0 0 12 0xFFFF 0x0806"; |
---|
9050 | 11251 | |
---|
| 11252 | +#ifdef BLOCK_IPV6_PACKET |
---|
| 11253 | + /* Setup filter to allow only IPv4 unicast frames */ |
---|
| 11254 | + dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 " |
---|
| 11255 | + HEX_PREF_STR UNI_FILTER_STR ZERO_ADDR_STR ETHER_TYPE_STR IPV6_FILTER_STR |
---|
| 11256 | + " " |
---|
| 11257 | + HEX_PREF_STR ZERO_ADDR_STR ZERO_ADDR_STR ETHER_TYPE_STR ZERO_TYPE_STR; |
---|
| 11258 | +#else |
---|
| 11259 | + /* Setup filter to allow only unicast */ |
---|
| 11260 | + dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0x01 0x00"; |
---|
| 11261 | +#endif /* BLOCK_IPV6_PACKET */ |
---|
| 11262 | + |
---|
| 11263 | +#ifdef PASS_IPV4_SUSPEND |
---|
| 11264 | + dhd->pktfilter[DHD_MDNS_FILTER_NUM] = "104 0 0 0 0xFFFFFF 0x01005E"; |
---|
| 11265 | +#else |
---|
| 11266 | + /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */ |
---|
| 11267 | + dhd->pktfilter[DHD_MDNS_FILTER_NUM] = NULL; |
---|
| 11268 | +#endif /* PASS_IPV4_SUSPEND */ |
---|
| 11269 | + if (FW_SUPPORTED(dhd, pf6)) { |
---|
| 11270 | + /* Immediately pkt filter TYPE 6 Dicard Broadcast IP packet */ |
---|
| 11271 | + dhd->pktfilter[DHD_IP4BCAST_DROP_FILTER_NUM] = DISCARD_IPV4_BCAST; |
---|
| 11272 | + /* Immediately pkt filter TYPE 6 Dicard Cisco STP packet */ |
---|
| 11273 | + dhd->pktfilter[DHD_LLC_STP_DROP_FILTER_NUM] = DISCARD_LLC_STP; |
---|
| 11274 | + /* Immediately pkt filter TYPE 6 Dicard Cisco XID protocol */ |
---|
| 11275 | + dhd->pktfilter[DHD_LLC_XID_DROP_FILTER_NUM] = DISCARD_LLC_XID; |
---|
| 11276 | + dhd->pktfilter_count = 10; |
---|
| 11277 | + } |
---|
| 11278 | + |
---|
| 11279 | +#ifdef GAN_LITE_NAT_KEEPALIVE_FILTER |
---|
| 11280 | + dhd->pktfilter_count = 4; |
---|
| 11281 | + /* Setup filter to block broadcast and NAT Keepalive packets */ |
---|
| 11282 | + /* discard all broadcast packets */ |
---|
| 11283 | + dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0xffffff 0xffffff"; |
---|
| 11284 | + /* discard NAT Keepalive packets */ |
---|
| 11285 | + dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = "102 0 0 36 0xffffffff 0x11940009"; |
---|
| 11286 | + /* discard NAT Keepalive packets */ |
---|
| 11287 | + dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = "104 0 0 38 0xffffffff 0x11940009"; |
---|
| 11288 | + dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL; |
---|
| 11289 | +#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */ |
---|
9051 | 11290 | |
---|
9052 | 11291 | #if defined(SOFTAP) |
---|
9053 | 11292 | if (ap_fw_loaded) { |
---|
.. | .. |
---|
9057 | 11296 | dhd_set_packet_filter(dhd); |
---|
9058 | 11297 | #endif /* PKT_FILTER_SUPPORT */ |
---|
9059 | 11298 | #ifdef DISABLE_11N |
---|
9060 | | - ret = dhd_iovar(dhd, 0, "nmode", (char *)&nmode, sizeof(nmode), |
---|
9061 | | - NULL, 0, TRUE); |
---|
| 11299 | + ret = dhd_iovar(dhd, 0, "nmode", (char *)&nmode, sizeof(nmode), NULL, 0, TRUE); |
---|
9062 | 11300 | if (ret < 0) |
---|
9063 | 11301 | DHD_ERROR(("%s wl nmode 0 failed %d\n", __FUNCTION__, ret)); |
---|
9064 | 11302 | #endif /* DISABLE_11N */ |
---|
9065 | 11303 | |
---|
9066 | | - /* query for 'ver' to get version info from firmware */ |
---|
| 11304 | +#ifdef ENABLE_BCN_LI_BCN_WAKEUP |
---|
| 11305 | + ret = dhd_iovar(dhd, 0, "bcn_li_bcn", (char *)&bcn_li_bcn, sizeof(bcn_li_bcn), NULL, 0, |
---|
| 11306 | + TRUE); |
---|
| 11307 | +#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ |
---|
| 11308 | +#ifdef AMPDU_VO_ENABLE |
---|
| 11309 | + tid.tid = PRIO_8021D_VO; /* Enable TID(6) for voice */ |
---|
| 11310 | + tid.enable = TRUE; |
---|
| 11311 | + ret = dhd_iovar(dhd, 0, "ampdu_tid", (char *)&tid, sizeof(tid), NULL, 0, TRUE); |
---|
| 11312 | + |
---|
| 11313 | + tid.tid = PRIO_8021D_NC; /* Enable TID(7) for voice */ |
---|
| 11314 | + tid.enable = TRUE; |
---|
| 11315 | + ret = dhd_iovar(dhd, 0, "ampdu_tid", (char *)&tid, sizeof(tid), NULL, 0, TRUE); |
---|
| 11316 | +#endif // endif |
---|
| 11317 | + /* query for 'clmver' to get clm version info from firmware */ |
---|
9067 | 11318 | memset(buf, 0, sizeof(buf)); |
---|
9068 | | - ptr = buf; |
---|
9069 | | - ret = dhd_iovar(dhd, 0, "ver", NULL, 0, (char *)&buf, sizeof(buf), FALSE); |
---|
| 11319 | + ret = dhd_iovar(dhd, 0, "clmver", NULL, 0, buf, sizeof(buf), FALSE); |
---|
9070 | 11320 | if (ret < 0) |
---|
9071 | 11321 | DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret)); |
---|
9072 | 11322 | else { |
---|
9073 | | - bcmstrtok(&ptr, "\n", 0); |
---|
9074 | | - /* Print fw version info */ |
---|
9075 | | - DHD_ERROR(("Firmware version = %s\n", buf)); |
---|
9076 | | -#if defined(BCMSDIO) || defined(BCMPCIE) |
---|
9077 | | - dhd_set_version_info(dhd, buf); |
---|
9078 | | -#endif /* BCMSDIO || BCMPCIE */ |
---|
| 11323 | + char *ver_temp_buf = NULL; |
---|
| 11324 | + |
---|
| 11325 | + if ((ver_temp_buf = bcmstrstr(buf, "Data:")) == NULL) { |
---|
| 11326 | + DHD_ERROR(("Couldn't find \"Data:\"\n")); |
---|
| 11327 | + } else { |
---|
| 11328 | + ptr = (ver_temp_buf + strlen("Data:")); |
---|
| 11329 | + if ((ver_temp_buf = bcmstrtok(&ptr, "\n", 0)) == NULL) { |
---|
| 11330 | + DHD_ERROR(("Couldn't find New line character\n")); |
---|
| 11331 | + } else { |
---|
| 11332 | + memset(clm_version, 0, CLM_VER_STR_LEN); |
---|
| 11333 | + strncpy(clm_version, ver_temp_buf, |
---|
| 11334 | + MIN(strlen(ver_temp_buf) + 1, CLM_VER_STR_LEN - 1)); |
---|
| 11335 | + DHD_INFO(("CLM version = %s\n", clm_version)); |
---|
| 11336 | + } |
---|
| 11337 | + } |
---|
| 11338 | + |
---|
| 11339 | +#if defined(CUSTOMER_HW4_DEBUG) |
---|
| 11340 | + if ((ver_temp_buf = bcmstrstr(ptr, "Customization:")) == NULL) { |
---|
| 11341 | + DHD_ERROR(("Couldn't find \"Customization:\"\n")); |
---|
| 11342 | + } else { |
---|
| 11343 | + char tokenlim; |
---|
| 11344 | + ptr = (ver_temp_buf + strlen("Customization:")); |
---|
| 11345 | + if ((ver_temp_buf = bcmstrtok(&ptr, "(\n", &tokenlim)) == NULL) { |
---|
| 11346 | + DHD_ERROR(("Couldn't find project blob version" |
---|
| 11347 | + "or New line character\n")); |
---|
| 11348 | + } else if (tokenlim == '(') { |
---|
| 11349 | + snprintf(clm_version, |
---|
| 11350 | + CLM_VER_STR_LEN - 1, "%s, Blob ver = Major : %s minor : ", |
---|
| 11351 | + clm_version, ver_temp_buf); |
---|
| 11352 | + DHD_INFO(("[INFO]CLM/Blob version = %s\n", clm_version)); |
---|
| 11353 | + if ((ver_temp_buf = bcmstrtok(&ptr, "\n", &tokenlim)) == NULL) { |
---|
| 11354 | + DHD_ERROR(("Couldn't find New line character\n")); |
---|
| 11355 | + } else { |
---|
| 11356 | + snprintf(clm_version, |
---|
| 11357 | + strlen(clm_version) + strlen(ver_temp_buf), |
---|
| 11358 | + "%s%s", clm_version, ver_temp_buf); |
---|
| 11359 | + DHD_INFO(("[INFO]CLM/Blob/project version = %s\n", |
---|
| 11360 | + clm_version)); |
---|
| 11361 | + |
---|
| 11362 | + } |
---|
| 11363 | + } else if (tokenlim == '\n') { |
---|
| 11364 | + snprintf(clm_version, |
---|
| 11365 | + strlen(clm_version) + strlen(", Blob ver = Major : ") + 1, |
---|
| 11366 | + "%s, Blob ver = Major : ", clm_version); |
---|
| 11367 | + snprintf(clm_version, |
---|
| 11368 | + strlen(clm_version) + strlen(ver_temp_buf) + 1, |
---|
| 11369 | + "%s%s", clm_version, ver_temp_buf); |
---|
| 11370 | + DHD_INFO(("[INFO]CLM/Blob/project version = %s\n", clm_version)); |
---|
| 11371 | + } |
---|
| 11372 | + } |
---|
| 11373 | +#endif /* CUSTOMER_HW4_DEBUG */ |
---|
| 11374 | + if (strlen(clm_version)) { |
---|
| 11375 | + DHD_ERROR(("CLM version = %s\n", clm_version)); |
---|
| 11376 | + } else { |
---|
| 11377 | + DHD_ERROR(("Couldn't find CLM version!\n")); |
---|
| 11378 | + } |
---|
9079 | 11379 | } |
---|
9080 | 11380 | |
---|
9081 | | -#if defined(BCMSDIO) |
---|
9082 | | - dhd_txglom_enable(dhd, TRUE); |
---|
9083 | | -#endif /* defined(BCMSDIO) */ |
---|
| 11381 | +#ifdef WRITE_WLANINFO |
---|
| 11382 | + sec_save_wlinfo(fw_version, EPI_VERSION_STR, dhd->info->nv_path, clm_version); |
---|
| 11383 | +#endif /* WRITE_WLANINFO */ |
---|
9084 | 11384 | |
---|
9085 | | -#if defined(BCMSDIO) || defined(BCMDBUS) |
---|
| 11385 | + /* query for 'wlc_ver' to get version info from firmware */ |
---|
| 11386 | + memset(&wlc_ver, 0, sizeof(wl_wlc_version_t)); |
---|
| 11387 | + ret = dhd_iovar(dhd, 0, "wlc_ver", NULL, 0, (char *)&wlc_ver, |
---|
| 11388 | + sizeof(wl_wlc_version_t), FALSE); |
---|
| 11389 | + if (ret < 0) |
---|
| 11390 | + DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret)); |
---|
| 11391 | + else { |
---|
| 11392 | + dhd->wlc_ver_major = wlc_ver.wlc_ver_major; |
---|
| 11393 | + dhd->wlc_ver_minor = wlc_ver.wlc_ver_minor; |
---|
| 11394 | + } |
---|
| 11395 | +#endif /* defined(OEM_ANDROID) */ |
---|
| 11396 | +#ifdef GEN_SOFTAP_INFO_FILE |
---|
| 11397 | + sec_save_softap_info(); |
---|
| 11398 | +#endif /* GEN_SOFTAP_INFO_FILE */ |
---|
| 11399 | + |
---|
| 11400 | +#if defined(BCMSDIO) && !defined(BCMSPI) |
---|
| 11401 | + dhd_txglom_enable(dhd, TRUE); |
---|
| 11402 | +#endif /* BCMSDIO && !BCMSPI */ |
---|
| 11403 | + |
---|
| 11404 | +#if defined(BCMSDIO) |
---|
9086 | 11405 | #ifdef PROP_TXSTATUS |
---|
9087 | 11406 | if (disable_proptx || |
---|
9088 | 11407 | #ifdef PROP_TXSTATUS_VSDB |
---|
9089 | 11408 | /* enable WLFC only if the firmware is VSDB when it is in STA mode */ |
---|
9090 | | - (dhd->op_mode != DHD_FLAG_HOSTAP_MODE && |
---|
9091 | | - dhd->op_mode != DHD_FLAG_IBSS_MODE) || |
---|
| 11409 | + (!FW_SUPPORTED(dhd, ap)) || |
---|
9092 | 11410 | #endif /* PROP_TXSTATUS_VSDB */ |
---|
9093 | 11411 | FALSE) { |
---|
9094 | 11412 | wlfc_enable = FALSE; |
---|
9095 | 11413 | } |
---|
9096 | 11414 | |
---|
9097 | 11415 | #if defined(PROP_TXSTATUS) |
---|
| 11416 | +#ifdef USE_WFA_CERT_CONF |
---|
| 11417 | + if (sec_get_param_wfa_cert(dhd, SET_PARAM_PROPTX, &proptx) == BCME_OK) { |
---|
| 11418 | + DHD_ERROR(("%s , read proptx param=%d\n", __FUNCTION__, proptx)); |
---|
| 11419 | + wlfc_enable = proptx; |
---|
| 11420 | + } |
---|
| 11421 | +#endif /* USE_WFA_CERT_CONF */ |
---|
9098 | 11422 | #endif /* PROP_TXSTATUS */ |
---|
9099 | 11423 | |
---|
9100 | 11424 | #ifndef DISABLE_11N |
---|
9101 | 11425 | ret2 = dhd_iovar(dhd, 0, "ampdu_hostreorder", (char *)&hostreorder, sizeof(hostreorder), |
---|
9102 | 11426 | NULL, 0, TRUE); |
---|
| 11427 | + chipid = dhd_bus_chip_id(dhd); |
---|
9103 | 11428 | if (ret2 < 0) { |
---|
9104 | 11429 | DHD_ERROR(("%s wl ampdu_hostreorder failed %d\n", __FUNCTION__, ret2)); |
---|
9105 | | - if (ret2 != BCME_UNSUPPORTED) |
---|
| 11430 | + if (ret2 != BCME_UNSUPPORTED && chipid != BCM4373_CHIP_ID) |
---|
9106 | 11431 | ret = ret2; |
---|
| 11432 | + |
---|
| 11433 | + if (ret == BCME_NOTDOWN) { |
---|
| 11434 | + uint wl_down = 1; |
---|
| 11435 | + ret2 = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, (char *)&wl_down, |
---|
| 11436 | + sizeof(wl_down), TRUE, 0); |
---|
| 11437 | + DHD_ERROR(("%s ampdu_hostreorder fail WL_DOWN : %d, hostreorder :%d\n", |
---|
| 11438 | + __FUNCTION__, ret2, hostreorder)); |
---|
| 11439 | + |
---|
| 11440 | + ret2 = dhd_iovar(dhd, 0, "ampdu_hostreorder", (char *)&hostreorder, |
---|
| 11441 | + sizeof(hostreorder), NULL, 0, TRUE); |
---|
| 11442 | + DHD_ERROR(("%s wl ampdu_hostreorder. ret --> %d\n", __FUNCTION__, ret2)); |
---|
| 11443 | + if (ret2 != BCME_UNSUPPORTED && chipid != BCM4373_CHIP_ID) |
---|
| 11444 | + ret = ret2; |
---|
| 11445 | + } |
---|
9107 | 11446 | if (ret2 != BCME_OK) |
---|
9108 | 11447 | hostreorder = 0; |
---|
9109 | 11448 | } |
---|
9110 | 11449 | #endif /* DISABLE_11N */ |
---|
9111 | | - |
---|
9112 | 11450 | |
---|
9113 | 11451 | if (wlfc_enable) |
---|
9114 | 11452 | dhd_wlfc_init(dhd); |
---|
.. | .. |
---|
9133 | 11471 | if (!dhd->pno_state) { |
---|
9134 | 11472 | dhd_pno_init(dhd); |
---|
9135 | 11473 | } |
---|
9136 | | -#endif |
---|
| 11474 | +#endif // endif |
---|
9137 | 11475 | #ifdef RTT_SUPPORT |
---|
9138 | 11476 | if (!dhd->rtt_state) { |
---|
9139 | 11477 | ret = dhd_rtt_init(dhd); |
---|
.. | .. |
---|
9141 | 11479 | DHD_ERROR(("%s failed to initialize RTT\n", __FUNCTION__)); |
---|
9142 | 11480 | } |
---|
9143 | 11481 | } |
---|
9144 | | -#endif |
---|
| 11482 | +#endif // endif |
---|
| 11483 | +#ifdef FILTER_IE |
---|
| 11484 | + /* Failure to configure filter IE is not a fatal error, ignore it. */ |
---|
| 11485 | + if (!(dhd->op_mode & (DHD_FLAG_HOSTAP_MODE | DHD_FLAG_MFG_MODE))) |
---|
| 11486 | + dhd_read_from_file(dhd); |
---|
| 11487 | +#endif /* FILTER_IE */ |
---|
9145 | 11488 | #ifdef WL11U |
---|
9146 | 11489 | dhd_interworking_enable(dhd); |
---|
9147 | 11490 | #endif /* WL11U */ |
---|
9148 | 11491 | |
---|
9149 | | -done: |
---|
| 11492 | +#ifdef NDO_CONFIG_SUPPORT |
---|
| 11493 | + dhd->ndo_enable = FALSE; |
---|
| 11494 | + dhd->ndo_host_ip_overflow = FALSE; |
---|
| 11495 | + dhd->ndo_max_host_ip = NDO_MAX_HOST_IP_ENTRIES; |
---|
| 11496 | +#endif /* NDO_CONFIG_SUPPORT */ |
---|
9150 | 11497 | |
---|
9151 | | - if (eventmask_msg) |
---|
9152 | | - kfree(eventmask_msg); |
---|
9153 | | - if (iov_buf) |
---|
9154 | | - kfree(iov_buf); |
---|
| 11498 | + /* ND offload version supported */ |
---|
| 11499 | + dhd->ndo_version = dhd_ndo_get_version(dhd); |
---|
| 11500 | + if (dhd->ndo_version > 0) { |
---|
| 11501 | + DHD_INFO(("%s: ndo version %d\n", __FUNCTION__, dhd->ndo_version)); |
---|
9155 | 11502 | |
---|
9156 | | - return ret; |
---|
9157 | | -} |
---|
9158 | | - |
---|
9159 | | -#ifdef LOAD_DHD_WITH_FW_ALIVE |
---|
9160 | | -int |
---|
9161 | | -dhd_preinit_ioctls_alive(dhd_pub_t *dhd) |
---|
9162 | | -{ |
---|
9163 | | - int ret = 0; |
---|
9164 | | - char buf[WLC_IOCTL_SMLEN]; |
---|
9165 | | - |
---|
9166 | | - DHD_TRACE(("Enter %s\n", __FUNCTION__)); |
---|
9167 | | - |
---|
9168 | | -#if (0) |
---|
9169 | | - char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ |
---|
9170 | | -#if defined(BCMSDIO) || defined(BCMDBUS) |
---|
9171 | | -#ifdef PROP_TXSTATUS |
---|
9172 | | - int wlfc_enable = TRUE; |
---|
9173 | | -#endif /* PROP_TXSTATUS */ |
---|
9174 | | -#endif /* defined(BCMSDIO) || defined(BCMDBUS) */ |
---|
9175 | | - |
---|
9176 | | -#if defined(ARP_OFFLOAD_SUPPORT) |
---|
9177 | | - int arpoe = 1; |
---|
9178 | | -#endif |
---|
9179 | | - |
---|
9180 | | -#if defined(SOFTAP) |
---|
9181 | | - uint dtim = 1; |
---|
9182 | | -#endif |
---|
9183 | | - |
---|
9184 | | -#ifdef WLTDLS |
---|
9185 | | - dhd->tdls_enable = FALSE; |
---|
9186 | | - dhd_tdls_set_mode(dhd, false); |
---|
9187 | | -#endif /* WLTDLS */ |
---|
9188 | | - dhd->suspend_bcn_li_dtim = CUSTOM_SUSPEND_BCN_LI_DTIM; |
---|
9189 | | - |
---|
9190 | | - DHD_TRACE(("Enter %s\n", __FUNCTION__)); |
---|
9191 | | - dhd->op_mode = 0; |
---|
9192 | | -#endif |
---|
9193 | | - |
---|
9194 | | - /* Get the default device MAC address directly from firmware */ |
---|
9195 | | - ret = dhd_iovar(dhd, 0, "cur_etheraddr", NULL, 0, (char *)&buf, sizeof(buf), FALSE); |
---|
9196 | | - if (ret < 0) { |
---|
9197 | | - DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret)); |
---|
9198 | | - ret = BCME_NOTUP; |
---|
9199 | | - goto done; |
---|
9200 | | - } |
---|
9201 | | - /* Update public MAC address after reading from Firmware */ |
---|
9202 | | - memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN); |
---|
9203 | | - |
---|
9204 | | - /* get a capabilities from firmware */ |
---|
9205 | | - { |
---|
9206 | | - uint32 cap_buf_size = sizeof(dhd->fw_capabilities); |
---|
9207 | | - memset(dhd->fw_capabilities, 0, cap_buf_size); |
---|
9208 | | - ret = dhd_iovar(dhd, 0, "cap", NULL, 0, dhd->fw_capabilities, (cap_buf_size - 1), |
---|
9209 | | - FALSE); |
---|
| 11503 | +#ifdef NDO_CONFIG_SUPPORT |
---|
| 11504 | + /* enable Unsolicited NA filter */ |
---|
| 11505 | + ret = dhd_ndo_unsolicited_na_filter_enable(dhd, 1); |
---|
9210 | 11506 | if (ret < 0) { |
---|
9211 | | - DHD_ERROR(("%s: Get Capability failed (error=%d)\n", |
---|
9212 | | - __FUNCTION__, ret)); |
---|
9213 | | - return 0; |
---|
| 11507 | + DHD_ERROR(("%s failed to enable Unsolicited NA filter\n", __FUNCTION__)); |
---|
9214 | 11508 | } |
---|
9215 | | - |
---|
9216 | | - memmove(&dhd->fw_capabilities[1], dhd->fw_capabilities, (cap_buf_size - 1)); |
---|
9217 | | - dhd->fw_capabilities[0] = ' '; |
---|
9218 | | - dhd->fw_capabilities[cap_buf_size - 2] = ' '; |
---|
9219 | | - dhd->fw_capabilities[cap_buf_size - 1] = '\0'; |
---|
| 11509 | +#endif /* NDO_CONFIG_SUPPORT */ |
---|
9220 | 11510 | } |
---|
9221 | 11511 | |
---|
9222 | | - dhd->op_mode = DHD_FLAG_STA_MODE; |
---|
| 11512 | + /* check dongle supports wbtext (product policy) or not */ |
---|
| 11513 | + dhd->wbtext_support = FALSE; |
---|
| 11514 | + if (dhd_wl_ioctl_get_intiovar(dhd, "wnm_bsstrans_resp", &wnm_bsstrans_resp, |
---|
| 11515 | + WLC_GET_VAR, FALSE, 0) != BCME_OK) { |
---|
| 11516 | + DHD_ERROR(("failed to get wnm_bsstrans_resp\n")); |
---|
| 11517 | + } |
---|
| 11518 | + dhd->wbtext_policy = wnm_bsstrans_resp; |
---|
| 11519 | + if (dhd->wbtext_policy == WL_BSSTRANS_POLICY_PRODUCT_WBTEXT) { |
---|
| 11520 | + dhd->wbtext_support = TRUE; |
---|
| 11521 | + } |
---|
| 11522 | +#ifndef WBTEXT |
---|
| 11523 | + /* driver can turn off wbtext feature through makefile */ |
---|
| 11524 | + if (dhd->wbtext_support) { |
---|
| 11525 | + if (dhd_wl_ioctl_set_intiovar(dhd, "wnm_bsstrans_resp", |
---|
| 11526 | + WL_BSSTRANS_POLICY_ROAM_ALWAYS, |
---|
| 11527 | + WLC_SET_VAR, FALSE, 0) != BCME_OK) { |
---|
| 11528 | + DHD_ERROR(("failed to disable WBTEXT\n")); |
---|
| 11529 | + } |
---|
| 11530 | + } |
---|
| 11531 | +#endif /* !WBTEXT */ |
---|
9223 | 11532 | |
---|
9224 | | - DHD_ERROR(("Firmware up: op_mode=0x%04x, MAC="MACDBG"\n", |
---|
9225 | | - dhd->op_mode, MAC2STRDBG(dhd->mac.octet))); |
---|
| 11533 | +#ifdef DHD_NON_DMA_M2M_CORRUPTION |
---|
| 11534 | + /* check pcie non dma loopback */ |
---|
| 11535 | + if (dhd->op_mode == DHD_FLAG_MFG_MODE && |
---|
| 11536 | + (dhd_bus_dmaxfer_lpbk(dhd, M2M_NON_DMA_LPBK) < 0)) { |
---|
| 11537 | + goto done; |
---|
| 11538 | + } |
---|
| 11539 | +#endif /* DHD_NON_DMA_M2M_CORRUPTION */ |
---|
9226 | 11540 | |
---|
9227 | | -#if (0) |
---|
9228 | | -#ifdef WLTDLS |
---|
9229 | | - /* by default TDLS on and auto mode off */ |
---|
9230 | | - _dhd_tdls_enable(dhd, true, false, NULL); |
---|
9231 | | -#endif /* WLTDLS */ |
---|
9232 | | - |
---|
9233 | | -#ifdef ARP_OFFLOAD_SUPPORT |
---|
9234 | | - /* Set and enable ARP offload feature for STA only */ |
---|
9235 | | - //get arp offload from firmware |
---|
9236 | | - dhd_arp_enable = arpoe; |
---|
9237 | | -#endif /* ARP_OFFLOAD_SUPPORT */ |
---|
9238 | | - |
---|
9239 | | -#ifdef PKT_FILTER_SUPPORT |
---|
9240 | | - /* Setup default defintions for pktfilter , enable in suspend */ |
---|
9241 | | - dhd->pktfilter_count = 6; |
---|
9242 | | - /* Setup filter to allow only unicast */ |
---|
9243 | | - dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0x01 0x00"; |
---|
9244 | | - dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = NULL; |
---|
9245 | | - dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = NULL; |
---|
9246 | | - dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL; |
---|
9247 | | - /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */ |
---|
9248 | | - dhd->pktfilter[DHD_MDNS_FILTER_NUM] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB"; |
---|
9249 | | - /* apply APP pktfilter */ |
---|
9250 | | - dhd->pktfilter[DHD_ARP_FILTER_NUM] = "105 0 0 12 0xFFFF 0x0806"; |
---|
9251 | | -#endif /* PKT_FILTER_SUPPORT */ |
---|
9252 | | - |
---|
9253 | | -#if defined(BCMSDIO) || defined(BCMDBUS) |
---|
9254 | | -#ifdef PROP_TXSTATUS |
---|
9255 | | - if (disable_proptx || |
---|
9256 | | -#ifdef PROP_TXSTATUS_VSDB |
---|
9257 | | - /* enable WLFC only if the firmware is VSDB when it is in STA mode */ |
---|
9258 | | - (dhd->op_mode != DHD_FLAG_HOSTAP_MODE && |
---|
9259 | | - dhd->op_mode != DHD_FLAG_IBSS_MODE) || |
---|
9260 | | -#endif /* PROP_TXSTATUS_VSDB */ |
---|
9261 | | - FALSE) { |
---|
9262 | | - wlfc_enable = FALSE; |
---|
| 11541 | + /* WNM capabilities */ |
---|
| 11542 | + wnm_cap = 0 |
---|
| 11543 | +#ifdef WL11U |
---|
| 11544 | + | WL_WNM_BSSTRANS | WL_WNM_NOTIF |
---|
| 11545 | +#endif // endif |
---|
| 11546 | +#ifdef WBTEXT |
---|
| 11547 | + | WL_WNM_BSSTRANS | WL_WNM_MAXIDLE |
---|
| 11548 | +#endif // endif |
---|
| 11549 | + ; |
---|
| 11550 | +#if defined(WL_MBO) && defined(WL_OCE) |
---|
| 11551 | + if (FW_SUPPORTED(dhd, estm)) { |
---|
| 11552 | + wnm_cap |= WL_WNM_ESTM; |
---|
| 11553 | + } |
---|
| 11554 | +#endif /* WL_MBO && WL_OCE */ |
---|
| 11555 | + if (dhd_iovar(dhd, 0, "wnm", (char *)&wnm_cap, sizeof(wnm_cap), NULL, 0, TRUE) < 0) { |
---|
| 11556 | + DHD_ERROR(("failed to set WNM capabilities\n")); |
---|
9263 | 11557 | } |
---|
9264 | 11558 | |
---|
9265 | | - if (wlfc_enable) |
---|
9266 | | - dhd_wlfc_init(dhd); |
---|
9267 | | -#ifndef DISABLE_11N |
---|
9268 | | - else if (hostreorder) |
---|
9269 | | - dhd_wlfc_hostreorder_init(dhd); |
---|
9270 | | -#endif /* DISABLE_11N */ |
---|
| 11559 | + if (FW_SUPPORTED(dhd, ecounters) && enable_ecounter) { |
---|
| 11560 | + dhd_ecounter_configure(dhd, TRUE); |
---|
| 11561 | + } |
---|
9271 | 11562 | |
---|
9272 | | -#endif /* PROP_TXSTATUS */ |
---|
9273 | | -#endif /* BCMSDIO || BCMBUS */ |
---|
9274 | | -#endif |
---|
| 11563 | + /* store the preserve log set numbers */ |
---|
| 11564 | + if (dhd_get_preserve_log_numbers(dhd, &dhd->logset_prsrv_mask) |
---|
| 11565 | + != BCME_OK) { |
---|
| 11566 | + DHD_ERROR(("%s: Failed to get preserve log # !\n", __FUNCTION__)); |
---|
| 11567 | + } |
---|
| 11568 | + |
---|
| 11569 | +#if defined(WBTEXT) && defined(WBTEXT_BTMDELTA) |
---|
| 11570 | + if (dhd_iovar(dhd, 0, "wnm_btmdelta", (char *)&btmdelta, sizeof(btmdelta), |
---|
| 11571 | + NULL, 0, TRUE) < 0) { |
---|
| 11572 | + DHD_ERROR(("failed to set BTM delta\n")); |
---|
| 11573 | + } |
---|
| 11574 | +#endif /* WBTEXT && WBTEXT_BTMDELTA */ |
---|
| 11575 | + |
---|
| 11576 | +#ifdef WL_MONITOR |
---|
| 11577 | + if (FW_SUPPORTED(dhd, monitor)) { |
---|
| 11578 | + dhd->monitor_enable = TRUE; |
---|
| 11579 | + DHD_ERROR(("%s: Monitor mode is enabled in FW cap\n", __FUNCTION__)); |
---|
| 11580 | + } else { |
---|
| 11581 | + dhd->monitor_enable = FALSE; |
---|
| 11582 | + DHD_ERROR(("%s: Monitor mode is not enabled in FW cap\n", __FUNCTION__)); |
---|
| 11583 | + } |
---|
| 11584 | +#endif /* WL_MONITOR */ |
---|
| 11585 | + |
---|
| 11586 | +#ifdef CONFIG_SILENT_ROAM |
---|
| 11587 | + dhd->sroam_turn_on = TRUE; |
---|
| 11588 | + dhd->sroamed = FALSE; |
---|
| 11589 | +#endif /* CONFIG_SILENT_ROAM */ |
---|
9275 | 11590 | |
---|
9276 | 11591 | done: |
---|
| 11592 | + |
---|
| 11593 | + if (eventmask_msg) { |
---|
| 11594 | + MFREE(dhd->osh, eventmask_msg, msglen); |
---|
| 11595 | + eventmask_msg = NULL; |
---|
| 11596 | + } |
---|
| 11597 | + if (iov_buf) { |
---|
| 11598 | + MFREE(dhd->osh, iov_buf, WLC_IOCTL_SMLEN); |
---|
| 11599 | + iov_buf = NULL; |
---|
| 11600 | + } |
---|
| 11601 | +#if defined(DHD_8021X_DUMP) && defined(SHOW_LOGTRACE) |
---|
| 11602 | + if (el_tag) { |
---|
| 11603 | + MFREE(dhd->osh, el_tag, sizeof(wl_el_tag_params_t)); |
---|
| 11604 | + el_tag = NULL; |
---|
| 11605 | + } |
---|
| 11606 | +#endif /* DHD_8021X_DUMP */ |
---|
9277 | 11607 | return ret; |
---|
9278 | 11608 | } |
---|
9279 | | -#endif /* LOAD_DHD_WITH_FW_ALIVE */ |
---|
9280 | 11609 | |
---|
9281 | 11610 | int |
---|
9282 | 11611 | dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *param_buf, uint param_len, char *res_buf, |
---|
.. | .. |
---|
9301 | 11630 | ret = BCME_BADARG; |
---|
9302 | 11631 | goto exit; |
---|
9303 | 11632 | } |
---|
9304 | | - buf = kzalloc(input_len, GFP_KERNEL); |
---|
| 11633 | + buf = MALLOCZ(pub->osh, input_len); |
---|
9305 | 11634 | if (!buf) { |
---|
9306 | 11635 | DHD_ERROR(("%s: mem alloc failed\n", __FUNCTION__)); |
---|
9307 | 11636 | ret = BCME_NOMEM; |
---|
.. | .. |
---|
9329 | 11658 | if (res_len < input_len) { |
---|
9330 | 11659 | DHD_INFO(("%s: res_len(%d) < input_len(%d)\n", __FUNCTION__, |
---|
9331 | 11660 | res_len, input_len)); |
---|
9332 | | - buf = kzalloc(input_len, GFP_KERNEL); |
---|
| 11661 | + buf = MALLOCZ(pub->osh, input_len); |
---|
9333 | 11662 | if (!buf) { |
---|
9334 | 11663 | DHD_ERROR(("%s: mem alloc failed\n", __FUNCTION__)); |
---|
9335 | 11664 | ret = BCME_NOMEM; |
---|
.. | .. |
---|
9368 | 11697 | } |
---|
9369 | 11698 | } |
---|
9370 | 11699 | exit: |
---|
9371 | | - kfree(buf); |
---|
| 11700 | + if (buf) { |
---|
| 11701 | + MFREE(pub->osh, buf, input_len); |
---|
| 11702 | + buf = NULL; |
---|
| 11703 | + } |
---|
9372 | 11704 | return ret; |
---|
9373 | 11705 | } |
---|
9374 | 11706 | |
---|
.. | .. |
---|
9385 | 11717 | |
---|
9386 | 11718 | memset(buf, 0, resp_len); |
---|
9387 | 11719 | |
---|
9388 | | - bcm_mkiovar(name, cmd_buf, cmd_len, buf, len); |
---|
| 11720 | + ret = bcm_mkiovar(name, cmd_buf, cmd_len, buf, len); |
---|
| 11721 | + if (ret == 0) { |
---|
| 11722 | + return BCME_BUFTOOSHORT; |
---|
| 11723 | + } |
---|
9389 | 11724 | |
---|
9390 | 11725 | memset(&ioc, 0, sizeof(ioc)); |
---|
9391 | 11726 | |
---|
.. | .. |
---|
9398 | 11733 | |
---|
9399 | 11734 | return ret; |
---|
9400 | 11735 | } |
---|
9401 | | - |
---|
9402 | 11736 | |
---|
9403 | 11737 | int dhd_change_mtu(dhd_pub_t *dhdp, int new_mtu, int ifidx) |
---|
9404 | 11738 | { |
---|
.. | .. |
---|
9440 | 11774 | /* display what we've got */ |
---|
9441 | 11775 | ret = dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx); |
---|
9442 | 11776 | DHD_ARPOE(("%s: hostip table read from Dongle:\n", __FUNCTION__)); |
---|
| 11777 | +#ifdef AOE_DBG |
---|
| 11778 | + dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */ |
---|
| 11779 | +#endif // endif |
---|
| 11780 | + /* now we saved hoste_ip table, clr it in the dongle AOE */ |
---|
| 11781 | + dhd_aoe_hostip_clr(dhd_pub, idx); |
---|
| 11782 | + |
---|
9443 | 11783 | if (ret) { |
---|
9444 | 11784 | DHD_ERROR(("%s failed\n", __FUNCTION__)); |
---|
9445 | 11785 | return; |
---|
9446 | 11786 | } |
---|
9447 | | -#ifdef AOE_DBG |
---|
9448 | | - dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */ |
---|
9449 | | -#endif |
---|
9450 | | - /* now we saved hoste_ip table, clr it in the dongle AOE */ |
---|
9451 | | - dhd_aoe_hostip_clr(dhd_pub, idx); |
---|
9452 | 11787 | |
---|
9453 | 11788 | for (i = 0; i < MAX_IPV4_ENTRIES; i++) { |
---|
9454 | 11789 | if (add && (ipv4_buf[i] == 0)) { |
---|
.. | .. |
---|
9474 | 11809 | dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx); |
---|
9475 | 11810 | DHD_ARPOE(("%s: read back arp_hostip table:\n", __FUNCTION__)); |
---|
9476 | 11811 | dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */ |
---|
9477 | | -#endif |
---|
| 11812 | +#endif // endif |
---|
9478 | 11813 | } |
---|
9479 | 11814 | |
---|
9480 | 11815 | /* |
---|
.. | .. |
---|
9497 | 11832 | if (!ifa || !(ifa->ifa_dev->dev)) |
---|
9498 | 11833 | return NOTIFY_DONE; |
---|
9499 | 11834 | |
---|
9500 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) |
---|
9501 | 11835 | /* Filter notifications meant for non Broadcom devices */ |
---|
9502 | 11836 | if ((ifa->ifa_dev->dev->netdev_ops != &dhd_ops_pri) && |
---|
9503 | 11837 | (ifa->ifa_dev->dev->netdev_ops != &dhd_ops_virt)) { |
---|
.. | .. |
---|
9506 | 11840 | #endif /* WL_ENABLE_P2P_IF */ |
---|
9507 | 11841 | return NOTIFY_DONE; |
---|
9508 | 11842 | } |
---|
9509 | | -#endif /* LINUX_VERSION_CODE */ |
---|
9510 | 11843 | |
---|
9511 | 11844 | dhd = DHD_DEV_INFO(ifa->ifa_dev->dev); |
---|
9512 | 11845 | if (!dhd) |
---|
.. | .. |
---|
9514 | 11847 | |
---|
9515 | 11848 | dhd_pub = &dhd->pub; |
---|
9516 | 11849 | |
---|
9517 | | -#ifndef STBLINUX |
---|
9518 | 11850 | if (dhd_pub->arp_version == 1) { |
---|
9519 | 11851 | idx = 0; |
---|
9520 | | - } else |
---|
9521 | | -#endif /* STBLINUX */ |
---|
9522 | | - { for (idx = 0; idx < DHD_MAX_IFS; idx++) { |
---|
| 11852 | + } else { |
---|
| 11853 | + for (idx = 0; idx < DHD_MAX_IFS; idx++) { |
---|
9523 | 11854 | if (dhd->iflist[idx] && dhd->iflist[idx]->net == ifa->ifa_dev->dev) |
---|
9524 | 11855 | break; |
---|
9525 | 11856 | } |
---|
9526 | | - if (idx < DHD_MAX_IFS) { |
---|
| 11857 | + if (idx < DHD_MAX_IFS) |
---|
9527 | 11858 | DHD_TRACE(("ifidx : %p %s %d\n", dhd->iflist[idx]->net, |
---|
9528 | 11859 | dhd->iflist[idx]->name, dhd->iflist[idx]->idx)); |
---|
9529 | | - } else { |
---|
| 11860 | + else { |
---|
9530 | 11861 | DHD_ERROR(("Cannot find ifidx for(%s) set to 0\n", ifa->ifa_label)); |
---|
9531 | 11862 | idx = 0; |
---|
9532 | 11863 | } |
---|
.. | .. |
---|
9537 | 11868 | DHD_ARPOE(("%s: [%s] Up IP: 0x%x\n", |
---|
9538 | 11869 | __FUNCTION__, ifa->ifa_label, ifa->ifa_address)); |
---|
9539 | 11870 | |
---|
9540 | | - if (dhd->pub.busstate != DHD_BUS_DATA) { |
---|
9541 | | - DHD_ERROR(("%s: bus not ready, exit\n", __FUNCTION__)); |
---|
| 11871 | + /* |
---|
| 11872 | + * Skip if Bus is not in a state to transport the IOVAR |
---|
| 11873 | + * (or) the Dongle is not ready. |
---|
| 11874 | + */ |
---|
| 11875 | + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(&dhd->pub) || |
---|
| 11876 | + dhd->pub.busstate == DHD_BUS_LOAD) { |
---|
| 11877 | + DHD_ERROR(("%s: bus not ready, exit NETDEV_UP : %d\n", |
---|
| 11878 | + __FUNCTION__, dhd->pub.busstate)); |
---|
9542 | 11879 | if (dhd->pend_ipaddr) { |
---|
9543 | 11880 | DHD_ERROR(("%s: overwrite pending ipaddr: 0x%x\n", |
---|
9544 | 11881 | __FUNCTION__, dhd->pend_ipaddr)); |
---|
.. | .. |
---|
9561 | 11898 | #ifdef AOE_IP_ALIAS_SUPPORT |
---|
9562 | 11899 | DHD_ARPOE(("%s:interface is down, AOE clr all for this if\n", |
---|
9563 | 11900 | __FUNCTION__)); |
---|
9564 | | - aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE, idx); |
---|
9565 | | -#else |
---|
9566 | | - dhd_aoe_hostip_clr(&dhd->pub, idx); |
---|
9567 | | - dhd_aoe_arp_clr(&dhd->pub, idx); |
---|
| 11901 | + if ((dhd_pub->op_mode & DHD_FLAG_HOSTAP_MODE) || |
---|
| 11902 | + (ifa->ifa_dev->dev != dhd_linux_get_primary_netdev(dhd_pub))) { |
---|
| 11903 | + aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE, idx); |
---|
| 11904 | + } else |
---|
9568 | 11905 | #endif /* AOE_IP_ALIAS_SUPPORT */ |
---|
| 11906 | + { |
---|
| 11907 | + dhd_aoe_hostip_clr(&dhd->pub, idx); |
---|
| 11908 | + dhd_aoe_arp_clr(&dhd->pub, idx); |
---|
| 11909 | + } |
---|
9569 | 11910 | break; |
---|
9570 | 11911 | |
---|
9571 | 11912 | default: |
---|
.. | .. |
---|
9577 | 11918 | } |
---|
9578 | 11919 | #endif /* ARP_OFFLOAD_SUPPORT */ |
---|
9579 | 11920 | |
---|
9580 | | -#if defined(CONFIG_IPV6) |
---|
| 11921 | +#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT) |
---|
9581 | 11922 | /* Neighbor Discovery Offload: defered handler */ |
---|
9582 | 11923 | static void |
---|
9583 | 11924 | dhd_inet6_work_handler(void *dhd_info, void *event_data, u8 event) |
---|
9584 | 11925 | { |
---|
9585 | 11926 | struct ipv6_work_info_t *ndo_work = (struct ipv6_work_info_t *)event_data; |
---|
9586 | | - dhd_pub_t *pub = &((dhd_info_t *)dhd_info)->pub; |
---|
9587 | | - int ret; |
---|
| 11927 | + dhd_info_t *dhd = (dhd_info_t *)dhd_info; |
---|
| 11928 | + dhd_pub_t *dhdp; |
---|
| 11929 | + int ret; |
---|
| 11930 | + |
---|
| 11931 | + if (!dhd) { |
---|
| 11932 | + DHD_ERROR(("%s: invalid dhd_info\n", __FUNCTION__)); |
---|
| 11933 | + goto done; |
---|
| 11934 | + } |
---|
| 11935 | + dhdp = &dhd->pub; |
---|
9588 | 11936 | |
---|
9589 | 11937 | if (event != DHD_WQ_WORK_IPV6_NDO) { |
---|
9590 | | - DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); |
---|
9591 | | - return; |
---|
| 11938 | + DHD_ERROR(("%s: unexpected event\n", __FUNCTION__)); |
---|
| 11939 | + goto done; |
---|
9592 | 11940 | } |
---|
9593 | 11941 | |
---|
9594 | 11942 | if (!ndo_work) { |
---|
9595 | | - DHD_ERROR(("%s: ipv6 work info is not initialized \n", __FUNCTION__)); |
---|
9596 | | - return; |
---|
9597 | | - } |
---|
9598 | | - |
---|
9599 | | - if (!pub) { |
---|
9600 | | - DHD_ERROR(("%s: dhd pub is not initialized \n", __FUNCTION__)); |
---|
9601 | | - return; |
---|
9602 | | - } |
---|
9603 | | - |
---|
9604 | | - if (ndo_work->if_idx) { |
---|
9605 | | - DHD_ERROR(("%s: idx %d \n", __FUNCTION__, ndo_work->if_idx)); |
---|
| 11943 | + DHD_ERROR(("%s: ipv6 work info is not initialized\n", __FUNCTION__)); |
---|
9606 | 11944 | return; |
---|
9607 | 11945 | } |
---|
9608 | 11946 | |
---|
9609 | 11947 | switch (ndo_work->event) { |
---|
9610 | 11948 | case NETDEV_UP: |
---|
9611 | | - DHD_TRACE(("%s: Enable NDO and add ipv6 into table \n ", __FUNCTION__)); |
---|
9612 | | - ret = dhd_ndo_enable(pub, TRUE); |
---|
| 11949 | +#ifndef NDO_CONFIG_SUPPORT |
---|
| 11950 | + DHD_TRACE(("%s: Enable NDO \n ", __FUNCTION__)); |
---|
| 11951 | + ret = dhd_ndo_enable(dhdp, TRUE); |
---|
9613 | 11952 | if (ret < 0) { |
---|
9614 | 11953 | DHD_ERROR(("%s: Enabling NDO Failed %d\n", __FUNCTION__, ret)); |
---|
9615 | 11954 | } |
---|
9616 | | - |
---|
9617 | | - ret = dhd_ndo_add_ip(pub, &ndo_work->ipv6_addr[0], ndo_work->if_idx); |
---|
| 11955 | +#endif /* !NDO_CONFIG_SUPPORT */ |
---|
| 11956 | + DHD_TRACE(("%s: Add a host ip for NDO\n", __FUNCTION__)); |
---|
| 11957 | + if (dhdp->ndo_version > 0) { |
---|
| 11958 | + /* inet6 addr notifier called only for unicast address */ |
---|
| 11959 | + ret = dhd_ndo_add_ip_with_type(dhdp, &ndo_work->ipv6_addr[0], |
---|
| 11960 | + WL_ND_IPV6_ADDR_TYPE_UNICAST, ndo_work->if_idx); |
---|
| 11961 | + } else { |
---|
| 11962 | + ret = dhd_ndo_add_ip(dhdp, &ndo_work->ipv6_addr[0], |
---|
| 11963 | + ndo_work->if_idx); |
---|
| 11964 | + } |
---|
9618 | 11965 | if (ret < 0) { |
---|
9619 | | - DHD_ERROR(("%s: Adding host ip for NDO failed %d\n", |
---|
| 11966 | + DHD_ERROR(("%s: Adding a host ip for NDO failed %d\n", |
---|
9620 | 11967 | __FUNCTION__, ret)); |
---|
9621 | 11968 | } |
---|
9622 | 11969 | break; |
---|
9623 | 11970 | case NETDEV_DOWN: |
---|
9624 | | - DHD_TRACE(("%s: clear ipv6 table \n", __FUNCTION__)); |
---|
9625 | | - ret = dhd_ndo_remove_ip(pub, ndo_work->if_idx); |
---|
| 11971 | + if (dhdp->ndo_version > 0) { |
---|
| 11972 | + DHD_TRACE(("%s: Remove a host ip for NDO\n", __FUNCTION__)); |
---|
| 11973 | + ret = dhd_ndo_remove_ip_by_addr(dhdp, |
---|
| 11974 | + &ndo_work->ipv6_addr[0], ndo_work->if_idx); |
---|
| 11975 | + } else { |
---|
| 11976 | + DHD_TRACE(("%s: Clear host ip table for NDO \n", __FUNCTION__)); |
---|
| 11977 | + ret = dhd_ndo_remove_ip(dhdp, ndo_work->if_idx); |
---|
| 11978 | + } |
---|
9626 | 11979 | if (ret < 0) { |
---|
9627 | 11980 | DHD_ERROR(("%s: Removing host ip for NDO failed %d\n", |
---|
9628 | 11981 | __FUNCTION__, ret)); |
---|
9629 | 11982 | goto done; |
---|
9630 | 11983 | } |
---|
9631 | | - |
---|
9632 | | - ret = dhd_ndo_enable(pub, FALSE); |
---|
| 11984 | +#ifdef NDO_CONFIG_SUPPORT |
---|
| 11985 | + if (dhdp->ndo_host_ip_overflow) { |
---|
| 11986 | + ret = dhd_dev_ndo_update_inet6addr( |
---|
| 11987 | + dhd_idx2net(dhdp, ndo_work->if_idx)); |
---|
| 11988 | + if ((ret < 0) && (ret != BCME_NORESOURCE)) { |
---|
| 11989 | + DHD_ERROR(("%s: Updating host ip for NDO failed %d\n", |
---|
| 11990 | + __FUNCTION__, ret)); |
---|
| 11991 | + goto done; |
---|
| 11992 | + } |
---|
| 11993 | + } |
---|
| 11994 | +#else /* !NDO_CONFIG_SUPPORT */ |
---|
| 11995 | + DHD_TRACE(("%s: Disable NDO\n ", __FUNCTION__)); |
---|
| 11996 | + ret = dhd_ndo_enable(dhdp, FALSE); |
---|
9633 | 11997 | if (ret < 0) { |
---|
9634 | 11998 | DHD_ERROR(("%s: disabling NDO Failed %d\n", __FUNCTION__, ret)); |
---|
9635 | 11999 | goto done; |
---|
9636 | 12000 | } |
---|
| 12001 | +#endif /* NDO_CONFIG_SUPPORT */ |
---|
9637 | 12002 | break; |
---|
| 12003 | + |
---|
9638 | 12004 | default: |
---|
9639 | 12005 | DHD_ERROR(("%s: unknown notifier event \n", __FUNCTION__)); |
---|
9640 | 12006 | break; |
---|
9641 | 12007 | } |
---|
9642 | 12008 | done: |
---|
| 12009 | + |
---|
9643 | 12010 | /* free ndo_work. alloced while scheduling the work */ |
---|
9644 | | - kfree(ndo_work); |
---|
| 12011 | + if (ndo_work) { |
---|
| 12012 | + kfree(ndo_work); |
---|
| 12013 | + } |
---|
9645 | 12014 | |
---|
9646 | 12015 | return; |
---|
9647 | | -} |
---|
| 12016 | +} /* dhd_init_logstrs_array */ |
---|
9648 | 12017 | |
---|
9649 | 12018 | /* |
---|
9650 | 12019 | * Neighbor Discovery Offload: Called when an interface |
---|
9651 | 12020 | * is assigned with ipv6 address. |
---|
9652 | 12021 | * Handles only primary interface |
---|
9653 | 12022 | */ |
---|
9654 | | -static int dhd_inet6addr_notifier_call(struct notifier_block *this, |
---|
9655 | | - unsigned long event, |
---|
9656 | | - void *ptr) |
---|
| 12023 | +int dhd_inet6addr_notifier_call(struct notifier_block *this, unsigned long event, void *ptr) |
---|
9657 | 12024 | { |
---|
9658 | 12025 | dhd_info_t *dhd; |
---|
9659 | | - dhd_pub_t *dhd_pub; |
---|
| 12026 | + dhd_pub_t *dhdp; |
---|
9660 | 12027 | struct inet6_ifaddr *inet6_ifa = ptr; |
---|
9661 | | - struct in6_addr *ipv6_addr = &inet6_ifa->addr; |
---|
9662 | 12028 | struct ipv6_work_info_t *ndo_info; |
---|
9663 | | - int idx = 0; /* REVISIT */ |
---|
| 12029 | + int idx; |
---|
9664 | 12030 | |
---|
9665 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) |
---|
9666 | 12031 | /* Filter notifications meant for non Broadcom devices */ |
---|
9667 | 12032 | if (inet6_ifa->idev->dev->netdev_ops != &dhd_ops_pri) { |
---|
9668 | 12033 | return NOTIFY_DONE; |
---|
9669 | 12034 | } |
---|
9670 | | -#endif /* LINUX_VERSION_CODE */ |
---|
9671 | 12035 | |
---|
9672 | 12036 | dhd = DHD_DEV_INFO(inet6_ifa->idev->dev); |
---|
9673 | | - if (!dhd) |
---|
| 12037 | + if (!dhd) { |
---|
9674 | 12038 | return NOTIFY_DONE; |
---|
| 12039 | + } |
---|
| 12040 | + dhdp = &dhd->pub; |
---|
9675 | 12041 | |
---|
9676 | | - if (dhd->iflist[idx] && dhd->iflist[idx]->net != inet6_ifa->idev->dev) |
---|
| 12042 | + /* Supports only primary interface */ |
---|
| 12043 | + idx = dhd_net2idx(dhd, inet6_ifa->idev->dev); |
---|
| 12044 | + if (idx != 0) { |
---|
9677 | 12045 | return NOTIFY_DONE; |
---|
9678 | | - dhd_pub = &dhd->pub; |
---|
| 12046 | + } |
---|
9679 | 12047 | |
---|
9680 | | - if (!FW_SUPPORTED(dhd_pub, ndoe)) |
---|
| 12048 | + /* FW capability */ |
---|
| 12049 | + if (!FW_SUPPORTED(dhdp, ndoe)) { |
---|
9681 | 12050 | return NOTIFY_DONE; |
---|
| 12051 | + } |
---|
9682 | 12052 | |
---|
9683 | 12053 | ndo_info = (struct ipv6_work_info_t *)kzalloc(sizeof(struct ipv6_work_info_t), GFP_ATOMIC); |
---|
9684 | 12054 | if (!ndo_info) { |
---|
.. | .. |
---|
9686 | 12056 | return NOTIFY_DONE; |
---|
9687 | 12057 | } |
---|
9688 | 12058 | |
---|
| 12059 | + /* fill up ndo_info */ |
---|
9689 | 12060 | ndo_info->event = event; |
---|
9690 | 12061 | ndo_info->if_idx = idx; |
---|
9691 | | - memcpy(&ndo_info->ipv6_addr[0], ipv6_addr, IPV6_ADDR_LEN); |
---|
| 12062 | + memcpy(ndo_info->ipv6_addr, &inet6_ifa->addr, IPV6_ADDR_LEN); |
---|
9692 | 12063 | |
---|
9693 | 12064 | /* defer the work to thread as it may block kernel */ |
---|
9694 | 12065 | dhd_deferred_schedule_work(dhd->dhd_deferred_wq, (void *)ndo_info, DHD_WQ_WORK_IPV6_NDO, |
---|
9695 | | - dhd_inet6_work_handler, DHD_WORK_PRIORITY_LOW); |
---|
| 12066 | + dhd_inet6_work_handler, DHD_WQ_WORK_PRIORITY_LOW); |
---|
9696 | 12067 | return NOTIFY_DONE; |
---|
9697 | 12068 | } |
---|
9698 | | -#endif /* OEM_ANDROID && CONFIG_IPV6 */ |
---|
| 12069 | +#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */ |
---|
| 12070 | + |
---|
| 12071 | +/* Network attach to be invoked from the bus probe handlers */ |
---|
| 12072 | +int |
---|
| 12073 | +dhd_attach_net(dhd_pub_t *dhdp, bool need_rtnl_lock) |
---|
| 12074 | +{ |
---|
| 12075 | + struct net_device *primary_ndev; |
---|
| 12076 | + BCM_REFERENCE(primary_ndev); |
---|
| 12077 | + |
---|
| 12078 | + /* Register primary net device */ |
---|
| 12079 | + if (dhd_register_if(dhdp, 0, need_rtnl_lock) != 0) { |
---|
| 12080 | + return BCME_ERROR; |
---|
| 12081 | + } |
---|
| 12082 | + |
---|
| 12083 | +#if defined(WL_CFG80211) |
---|
| 12084 | + primary_ndev = dhd_linux_get_primary_netdev(dhdp); |
---|
| 12085 | + if (wl_cfg80211_net_attach(primary_ndev) < 0) { |
---|
| 12086 | + /* fail the init */ |
---|
| 12087 | + dhd_remove_if(dhdp, 0, TRUE); |
---|
| 12088 | + return BCME_ERROR; |
---|
| 12089 | + } |
---|
| 12090 | +#endif /* WL_CFG80211 */ |
---|
| 12091 | + return BCME_OK; |
---|
| 12092 | +} |
---|
9699 | 12093 | |
---|
9700 | 12094 | int |
---|
9701 | 12095 | dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) |
---|
.. | .. |
---|
9708 | 12102 | |
---|
9709 | 12103 | DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); |
---|
9710 | 12104 | |
---|
| 12105 | + if (dhd == NULL || dhd->iflist[ifidx] == NULL) { |
---|
| 12106 | + DHD_ERROR(("%s: Invalid Interface\n", __FUNCTION__)); |
---|
| 12107 | + return BCME_ERROR; |
---|
| 12108 | + } |
---|
| 12109 | + |
---|
9711 | 12110 | ASSERT(dhd && dhd->iflist[ifidx]); |
---|
9712 | 12111 | ifp = dhd->iflist[ifidx]; |
---|
9713 | 12112 | net = ifp->net; |
---|
9714 | 12113 | ASSERT(net && (ifp->idx == ifidx)); |
---|
9715 | 12114 | |
---|
9716 | | -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) |
---|
9717 | | - ASSERT(!net->open); |
---|
9718 | | - net->get_stats = dhd_get_stats; |
---|
9719 | | - net->do_ioctl = dhd_ioctl_entry; |
---|
9720 | | - net->hard_start_xmit = dhd_start_xmit; |
---|
9721 | | - net->set_mac_address = dhd_set_mac_address; |
---|
9722 | | - net->set_multicast_list = dhd_set_multicast_list; |
---|
9723 | | - net->open = net->stop = NULL; |
---|
9724 | | -#else |
---|
9725 | 12115 | ASSERT(!net->netdev_ops); |
---|
9726 | 12116 | net->netdev_ops = &dhd_ops_virt; |
---|
9727 | | -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */ |
---|
9728 | 12117 | |
---|
9729 | 12118 | /* Ok, link into the network layer... */ |
---|
9730 | 12119 | if (ifidx == 0) { |
---|
9731 | 12120 | /* |
---|
9732 | 12121 | * device functions for the primary interface only |
---|
9733 | 12122 | */ |
---|
9734 | | -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) |
---|
9735 | | - net->open = dhd_open; |
---|
9736 | | - net->stop = dhd_stop; |
---|
9737 | | -#else |
---|
9738 | 12123 | net->netdev_ops = &dhd_ops_pri; |
---|
9739 | | -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */ |
---|
9740 | 12124 | if (!ETHER_ISNULLADDR(dhd->pub.mac.octet)) |
---|
9741 | 12125 | memcpy(temp_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN); |
---|
| 12126 | + memcpy(dhd->iflist[0]->mac_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN); |
---|
9742 | 12127 | } else { |
---|
9743 | 12128 | /* |
---|
9744 | 12129 | * We have to use the primary MAC for virtual interfaces |
---|
9745 | 12130 | */ |
---|
9746 | 12131 | memcpy(temp_addr, ifp->mac_addr, ETHER_ADDR_LEN); |
---|
| 12132 | +#if defined(OEM_ANDROID) |
---|
9747 | 12133 | /* |
---|
9748 | 12134 | * Android sets the locally administered bit to indicate that this is a |
---|
9749 | 12135 | * portable hotspot. This will not work in simultaneous AP/STA mode, |
---|
.. | .. |
---|
9754 | 12140 | DHD_ERROR(("%s interface [%s]: set locally administered bit in MAC\n", |
---|
9755 | 12141 | __func__, net->name)); |
---|
9756 | 12142 | temp_addr[0] |= 0x02; |
---|
| 12143 | + memcpy(dhd->iflist[ifidx]->mac_addr, temp_addr, ETHER_ADDR_LEN); |
---|
9757 | 12144 | } |
---|
| 12145 | +#endif /* defined(OEM_ANDROID) */ |
---|
9758 | 12146 | } |
---|
9759 | 12147 | |
---|
9760 | 12148 | net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen; |
---|
9761 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) |
---|
9762 | 12149 | net->ethtool_ops = &dhd_ethtool_ops; |
---|
9763 | | -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ |
---|
9764 | 12150 | |
---|
9765 | 12151 | #if defined(WL_WIRELESS_EXT) |
---|
9766 | 12152 | #if WIRELESS_EXT < 19 |
---|
9767 | 12153 | net->get_wireless_stats = dhd_get_wireless_stats; |
---|
9768 | 12154 | #endif /* WIRELESS_EXT < 19 */ |
---|
9769 | 12155 | #if WIRELESS_EXT > 12 |
---|
9770 | | - net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def; |
---|
| 12156 | + net->wireless_handlers = &wl_iw_handler_def; |
---|
9771 | 12157 | #endif /* WIRELESS_EXT > 12 */ |
---|
9772 | 12158 | #endif /* defined(WL_WIRELESS_EXT) */ |
---|
9773 | 12159 | |
---|
.. | .. |
---|
9788 | 12174 | goto fail; |
---|
9789 | 12175 | } |
---|
9790 | 12176 | |
---|
9791 | | - |
---|
9792 | | - |
---|
9793 | 12177 | printf("Register interface [%s] MAC: "MACDBG"\n\n", net->name, |
---|
| 12178 | +#if defined(CUSTOMER_HW4_DEBUG) |
---|
| 12179 | + MAC2STRDBG(dhd->pub.mac.octet)); |
---|
| 12180 | +#else |
---|
9794 | 12181 | MAC2STRDBG(net->dev_addr)); |
---|
| 12182 | +#endif /* CUSTOMER_HW4_DEBUG */ |
---|
9795 | 12183 | |
---|
9796 | | -#if defined(SOFTAP) && defined(WL_WIRELESS_EXT) && !defined(WL_CFG80211) |
---|
| 12184 | +#if defined(OEM_ANDROID) && defined(SOFTAP) && defined(WL_WIRELESS_EXT) && \ |
---|
| 12185 | + !defined(WL_CFG80211) |
---|
9797 | 12186 | wl_iw_iscan_set_scan_broadcast_prep(net, 1); |
---|
9798 | | -#endif |
---|
| 12187 | +#endif // endif |
---|
9799 | 12188 | |
---|
9800 | | -#if (defined(BCMPCIE) || (defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= \ |
---|
9801 | | - KERNEL_VERSION(2, 6, 27)))) |
---|
| 12189 | +#if defined(OEM_ANDROID) && (defined(BCMPCIE) || defined(BCMLXSDMMC)) |
---|
9802 | 12190 | if (ifidx == 0) { |
---|
9803 | 12191 | #ifdef BCMLXSDMMC |
---|
9804 | 12192 | up(&dhd_registration_sem); |
---|
9805 | 12193 | #endif /* BCMLXSDMMC */ |
---|
| 12194 | +#ifndef ENABLE_INSMOD_NO_FW_LOAD |
---|
9806 | 12195 | if (!dhd_download_fw_on_driverload) { |
---|
9807 | 12196 | #ifdef WL_CFG80211 |
---|
9808 | | - wl_terminate_event_handler(); |
---|
| 12197 | + wl_terminate_event_handler(net); |
---|
9809 | 12198 | #endif /* WL_CFG80211 */ |
---|
9810 | | -#if defined(DHD_LB) && defined(DHD_LB_RXP) |
---|
| 12199 | +#if defined(DHD_LB_RXP) |
---|
9811 | 12200 | __skb_queue_purge(&dhd->rx_pend_queue); |
---|
9812 | | -#endif /* DHD_LB && DHD_LB_RXP */ |
---|
| 12201 | +#endif /* DHD_LB_RXP */ |
---|
| 12202 | + |
---|
| 12203 | +#if defined(DHD_LB_TXP) |
---|
| 12204 | + skb_queue_purge(&dhd->tx_pend_queue); |
---|
| 12205 | +#endif /* DHD_LB_TXP */ |
---|
| 12206 | + |
---|
| 12207 | +#ifdef SHOW_LOGTRACE |
---|
| 12208 | + /* Release the skbs from queue for WLC_E_TRACE event */ |
---|
| 12209 | + dhd_event_logtrace_flush_queue(dhdp); |
---|
| 12210 | +#endif /* SHOW_LOGTRACE */ |
---|
| 12211 | + |
---|
9813 | 12212 | #if defined(BCMPCIE) && defined(DHDTCPACK_SUPPRESS) |
---|
9814 | 12213 | dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF); |
---|
9815 | 12214 | #endif /* BCMPCIE && DHDTCPACK_SUPPRESS */ |
---|
.. | .. |
---|
9818 | 12217 | dhd_net_bus_suspend(net); |
---|
9819 | 12218 | #endif /* BCMLXSDMMC */ |
---|
9820 | 12219 | wifi_platform_set_power(dhdp->info->adapter, FALSE, WIFI_TURNOFF_DELAY); |
---|
| 12220 | +#if defined(BT_OVER_SDIO) |
---|
| 12221 | + dhd->bus_user_count--; |
---|
| 12222 | +#endif /* BT_OVER_SDIO */ |
---|
9821 | 12223 | } |
---|
| 12224 | +#endif /* ENABLE_INSMOD_NO_FW_LOAD */ |
---|
9822 | 12225 | } |
---|
9823 | | -#endif /* OEM_ANDROID && (BCMPCIE || (BCMLXSDMMC && KERNEL_VERSION >= 2.6.27)) */ |
---|
| 12226 | +#endif /* OEM_ANDROID && (BCMPCIE || BCMLXSDMMC) */ |
---|
9824 | 12227 | return 0; |
---|
9825 | 12228 | |
---|
9826 | 12229 | fail: |
---|
9827 | | -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) |
---|
9828 | | - net->open = NULL; |
---|
9829 | | -#else |
---|
9830 | 12230 | net->netdev_ops = NULL; |
---|
9831 | | -#endif |
---|
9832 | 12231 | return err; |
---|
9833 | 12232 | } |
---|
9834 | 12233 | |
---|
| 12234 | +#ifdef WL_VIF_SUPPORT |
---|
| 12235 | +#define MAX_VIF_NUM 8 |
---|
| 12236 | +int |
---|
| 12237 | +dhd_register_vif(dhd_pub_t *dhdp) |
---|
| 12238 | +{ |
---|
| 12239 | + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
| 12240 | + dhd_if_t *ifp; |
---|
| 12241 | + struct net_device *net; |
---|
| 12242 | + int err = BCME_OK, i; |
---|
| 12243 | + char viface_name[IFNAMSIZ] = {'\0'}; |
---|
| 12244 | + ifp = dhd->iflist[0]; |
---|
| 12245 | + net = ifp->net; |
---|
| 12246 | + if (vif_num && vif_num > MAX_VIF_NUM) |
---|
| 12247 | + vif_num = MAX_VIF_NUM; |
---|
| 12248 | + /* Set virtual interface name if it was provided as module parameter */ |
---|
| 12249 | + if (vif_name[0]) { |
---|
| 12250 | + int len; |
---|
| 12251 | + char ch; |
---|
| 12252 | + strncpy(viface_name, vif_name, IFNAMSIZ); |
---|
| 12253 | + viface_name[IFNAMSIZ - 1] = 0; |
---|
| 12254 | + len = strlen(viface_name); |
---|
| 12255 | + ch = viface_name[len - 1]; |
---|
| 12256 | + if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2)) |
---|
| 12257 | + strcat(viface_name, "%d"); |
---|
| 12258 | + } else { |
---|
| 12259 | + DHD_ERROR(("%s check vif_name\n", __FUNCTION__)); |
---|
| 12260 | + return BCME_BADOPTION; |
---|
| 12261 | + } |
---|
| 12262 | + |
---|
| 12263 | + DHD_INFO(("%s Virtual interface [%s]:\n", __FUNCTION__, viface_name)); |
---|
| 12264 | + rtnl_lock(); |
---|
| 12265 | + for (i = 0; i < vif_num; i++) { |
---|
| 12266 | + if (wl_cfg80211_add_if(wl_get_cfg(net), net, WL_IF_TYPE_STA, viface_name, NULL) |
---|
| 12267 | + == NULL) { |
---|
| 12268 | + DHD_ERROR(("%s error Virtual interface [%s], i:%d\n", __FUNCTION__, |
---|
| 12269 | + viface_name, i)); |
---|
| 12270 | + break; |
---|
| 12271 | + } |
---|
| 12272 | + } |
---|
| 12273 | + rtnl_unlock(); |
---|
| 12274 | + return err; |
---|
| 12275 | +} |
---|
| 12276 | +#endif /* WL_VIF_SUPPORT */ |
---|
9835 | 12277 | void |
---|
9836 | 12278 | dhd_bus_detach(dhd_pub_t *dhdp) |
---|
9837 | 12279 | { |
---|
.. | .. |
---|
9852 | 12294 | dhd_prot_stop(&dhd->pub); |
---|
9853 | 12295 | |
---|
9854 | 12296 | /* Stop the bus module */ |
---|
9855 | | -#ifdef BCMDBUS |
---|
9856 | | - /* Force Dongle terminated */ |
---|
9857 | | - if (dhd_wl_ioctl_cmd(dhdp, WLC_TERMINATED, NULL, 0, TRUE, 0) < 0) |
---|
9858 | | - DHD_ERROR(("%s Setting WLC_TERMINATED failed\n", |
---|
9859 | | - __FUNCTION__)); |
---|
9860 | | - dbus_stop(dhd->pub.dbus); |
---|
9861 | | - dhd->pub.busstate = DHD_BUS_DOWN; |
---|
9862 | | -#else |
---|
9863 | 12297 | dhd_bus_stop(dhd->pub.bus, TRUE); |
---|
9864 | | -#endif /* BCMDBUS */ |
---|
9865 | 12298 | } |
---|
9866 | 12299 | |
---|
9867 | | -#if defined(OOB_INTR_ONLY) || defined(BCMPCIE_OOB_HOST_WAKE) |
---|
| 12300 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) || defined(BCMPCIE_OOB_HOST_WAKE) |
---|
9868 | 12301 | dhd_bus_oob_intr_unregister(dhdp); |
---|
9869 | | -#endif |
---|
| 12302 | +#endif /* OOB_INTR_ONLY || BCMSPI_ANDROID || BCMPCIE_OOB_HOST_WAKE */ |
---|
9870 | 12303 | } |
---|
9871 | 12304 | } |
---|
9872 | 12305 | } |
---|
9873 | | - |
---|
9874 | 12306 | |
---|
9875 | 12307 | void dhd_detach(dhd_pub_t *dhdp) |
---|
9876 | 12308 | { |
---|
9877 | 12309 | dhd_info_t *dhd; |
---|
9878 | 12310 | unsigned long flags; |
---|
9879 | 12311 | int timer_valid = FALSE; |
---|
9880 | | - struct net_device *dev; |
---|
9881 | | - |
---|
| 12312 | + struct net_device *dev = NULL; |
---|
| 12313 | +#ifdef WL_CFG80211 |
---|
| 12314 | + struct bcm_cfg80211 *cfg = NULL; |
---|
| 12315 | +#endif // endif |
---|
9882 | 12316 | if (!dhdp) |
---|
9883 | 12317 | return; |
---|
9884 | 12318 | |
---|
.. | .. |
---|
9886 | 12320 | if (!dhd) |
---|
9887 | 12321 | return; |
---|
9888 | 12322 | |
---|
9889 | | - dev = dhd->iflist[0]->net; |
---|
| 12323 | + if (dhd->iflist[0]) |
---|
| 12324 | + dev = dhd->iflist[0]->net; |
---|
9890 | 12325 | |
---|
9891 | 12326 | if (dev) { |
---|
9892 | 12327 | rtnl_lock(); |
---|
.. | .. |
---|
9904 | 12339 | |
---|
9905 | 12340 | DHD_TRACE(("%s: Enter state 0x%x\n", __FUNCTION__, dhd->dhd_state)); |
---|
9906 | 12341 | |
---|
| 12342 | + DHD_ERROR(("%s: making dhdpub up FALSE\n", __FUNCTION__)); |
---|
9907 | 12343 | dhd->pub.up = 0; |
---|
9908 | | - if (dhd->dhd_state & DHD_ATTACH_STATE_DONE) { |
---|
9909 | | - if (dhd_found > 0) |
---|
9910 | | - dhd_found--; |
---|
9911 | | - } |
---|
9912 | | - else { |
---|
| 12344 | + if (!(dhd->dhd_state & DHD_ATTACH_STATE_DONE)) { |
---|
9913 | 12345 | /* Give sufficient time for threads to start running in case |
---|
9914 | 12346 | * dhd_attach() has failed |
---|
9915 | 12347 | */ |
---|
.. | .. |
---|
9917 | 12349 | } |
---|
9918 | 12350 | #ifdef DHD_WET |
---|
9919 | 12351 | dhd_free_wet_info(&dhd->pub, dhd->pub.wet_info); |
---|
9920 | | -#endif |
---|
9921 | | - |
---|
| 12352 | +#endif /* DHD_WET */ |
---|
9922 | 12353 | #if defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) |
---|
9923 | | -#if defined(BCMDBUS) |
---|
9924 | | - if (dhd->fw_download_task) { |
---|
9925 | | - up(&dhd->fw_download_lock); |
---|
9926 | | - kthread_stop(dhd->fw_download_task); |
---|
9927 | | - dhd->fw_download_task = NULL; |
---|
9928 | | - } |
---|
9929 | | -#endif /* BCMDBUS */ |
---|
9930 | 12354 | #endif /* defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) */ |
---|
9931 | 12355 | |
---|
9932 | 12356 | #ifdef PROP_TXSTATUS |
---|
.. | .. |
---|
9941 | 12365 | #endif /* PROP_TXSTATUS */ |
---|
9942 | 12366 | |
---|
9943 | 12367 | #ifdef WL_CFG80211 |
---|
9944 | | - wl_cfg80211_down(NULL); |
---|
| 12368 | + if (dev) |
---|
| 12369 | + wl_cfg80211_down(dev); |
---|
9945 | 12370 | #endif /* WL_CFG80211 */ |
---|
9946 | 12371 | |
---|
9947 | 12372 | if (dhd->dhd_state & DHD_ATTACH_STATE_PROT_ATTACH) { |
---|
9948 | 12373 | |
---|
9949 | | -#ifndef BCMSDIO |
---|
| 12374 | +#if defined(OEM_ANDROID) || !defined(BCMSDIO) |
---|
9950 | 12375 | dhd_bus_detach(dhdp); |
---|
9951 | | -#endif |
---|
| 12376 | +#endif /* OEM_ANDROID || !BCMSDIO */ |
---|
| 12377 | +#ifdef OEM_ANDROID |
---|
9952 | 12378 | #ifdef BCMPCIE |
---|
9953 | 12379 | if (is_reboot == SYS_RESTART) { |
---|
9954 | 12380 | extern bcmdhd_wifi_platdata_t *dhd_wifi_platdata; |
---|
.. | .. |
---|
9959 | 12385 | } |
---|
9960 | 12386 | } |
---|
9961 | 12387 | #endif /* BCMPCIE */ |
---|
9962 | | -#if !defined(PCIE_FULL_DONGLE) && !defined(BCMSDIO) |
---|
| 12388 | +#endif /* OEM_ANDROID */ |
---|
| 12389 | +#ifndef PCIE_FULL_DONGLE |
---|
| 12390 | +#if defined(OEM_ANDROID) || !defined(BCMSDIO) |
---|
9963 | 12391 | if (dhdp->prot) |
---|
9964 | 12392 | dhd_prot_detach(dhdp); |
---|
9965 | | -#endif |
---|
| 12393 | +#endif /* OEM_ANDROID || !BCMSDIO */ |
---|
| 12394 | +#endif /* !PCIE_FULL_DONGLE */ |
---|
9966 | 12395 | } |
---|
9967 | 12396 | |
---|
9968 | 12397 | #ifdef ARP_OFFLOAD_SUPPORT |
---|
.. | .. |
---|
9971 | 12400 | unregister_inetaddr_notifier(&dhd_inetaddr_notifier); |
---|
9972 | 12401 | } |
---|
9973 | 12402 | #endif /* ARP_OFFLOAD_SUPPORT */ |
---|
9974 | | -#if defined(CONFIG_IPV6) |
---|
| 12403 | +#if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT) |
---|
9975 | 12404 | if (dhd_inet6addr_notifier_registered) { |
---|
9976 | 12405 | dhd_inet6addr_notifier_registered = FALSE; |
---|
9977 | 12406 | unregister_inet6addr_notifier(&dhd_inet6addr_notifier); |
---|
9978 | 12407 | } |
---|
9979 | | -#endif /* OEM_ANDROID && CONFIG_IPV6 */ |
---|
| 12408 | +#endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */ |
---|
9980 | 12409 | #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) |
---|
9981 | 12410 | if (dhd->dhd_state & DHD_ATTACH_STATE_EARLYSUSPEND_DONE) { |
---|
9982 | 12411 | if (dhd->early_suspend.suspend) |
---|
.. | .. |
---|
10011 | 12440 | |
---|
10012 | 12441 | /* delete primary interface 0 */ |
---|
10013 | 12442 | ifp = dhd->iflist[0]; |
---|
10014 | | - ASSERT(ifp); |
---|
10015 | | - ASSERT(ifp->net); |
---|
10016 | 12443 | if (ifp && ifp->net) { |
---|
10017 | | -#if (defined(STBLINUX) && defined(WL_CFG80211)) |
---|
10018 | 12444 | |
---|
10019 | | - /* keep wirless framework happy */ |
---|
10020 | | - wl_cfg80211_cleanup(); |
---|
10021 | | -#endif /* STBLINUX && WL_CFG80211 */ |
---|
10022 | | - |
---|
10023 | | - |
---|
10024 | | - |
---|
10025 | | - |
---|
| 12445 | +#ifdef WL_CFG80211 |
---|
| 12446 | + cfg = wl_get_cfg(ifp->net); |
---|
| 12447 | +#endif // endif |
---|
10026 | 12448 | /* in unregister_netdev case, the interface gets freed by net->destructor |
---|
10027 | 12449 | * (which is set to free_netdev) |
---|
10028 | 12450 | */ |
---|
10029 | 12451 | if (ifp->net->reg_state == NETREG_UNINITIALIZED) { |
---|
10030 | 12452 | free_netdev(ifp->net); |
---|
10031 | 12453 | } else { |
---|
| 12454 | +#if defined(ARGOS_NOTIFY_CB) |
---|
| 12455 | + argos_register_notifier_deinit(); |
---|
| 12456 | +#endif // endif |
---|
10032 | 12457 | #ifdef SET_RPS_CPUS |
---|
10033 | 12458 | custom_rps_map_clear(ifp->net->_rx); |
---|
10034 | 12459 | #endif /* SET_RPS_CPUS */ |
---|
10035 | 12460 | netif_tx_disable(ifp->net); |
---|
10036 | 12461 | unregister_netdev(ifp->net); |
---|
10037 | 12462 | } |
---|
| 12463 | +#ifdef PCIE_FULL_DONGLE |
---|
| 12464 | + ifp->net = DHD_NET_DEV_NULL; |
---|
| 12465 | +#else |
---|
10038 | 12466 | ifp->net = NULL; |
---|
10039 | | -#ifdef BCMSDIO |
---|
10040 | | - dhd_bus_detach(dhdp); |
---|
| 12467 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 12468 | +#if defined(BCMSDIO) && !defined(OEM_ANDROID) |
---|
| 12469 | + dhd_bus_detach(dhdp); |
---|
10041 | 12470 | |
---|
10042 | | - if (dhdp->prot) |
---|
10043 | | - dhd_prot_detach(dhdp); |
---|
10044 | | -#endif |
---|
10045 | | -#ifdef DHD_WMF |
---|
10046 | | - dhd_wmf_cleanup(dhdp, 0); |
---|
10047 | | -#endif /* DHD_WMF */ |
---|
| 12471 | + if (dhdp->prot) |
---|
| 12472 | + dhd_prot_detach(dhdp); |
---|
| 12473 | +#endif /* BCMSDIO && !OEM_ANDROID */ |
---|
| 12474 | + |
---|
10048 | 12475 | #ifdef DHD_L2_FILTER |
---|
10049 | 12476 | bcm_l2_filter_arp_table_update(dhdp->osh, ifp->phnd_arp_table, TRUE, |
---|
10050 | 12477 | NULL, FALSE, dhdp->tickcnt); |
---|
10051 | 12478 | deinit_l2_filter_arp_table(dhdp->osh, ifp->phnd_arp_table); |
---|
10052 | 12479 | ifp->phnd_arp_table = NULL; |
---|
10053 | 12480 | #endif /* DHD_L2_FILTER */ |
---|
10054 | | - |
---|
10055 | 12481 | |
---|
10056 | 12482 | dhd_if_del_sta_list(ifp); |
---|
10057 | 12483 | |
---|
.. | .. |
---|
10067 | 12493 | DHD_GENERAL_UNLOCK(&dhd->pub, flags); |
---|
10068 | 12494 | if (timer_valid) |
---|
10069 | 12495 | del_timer_sync(&dhd->timer); |
---|
| 12496 | + DHD_DISABLE_RUNTIME_PM(&dhd->pub); |
---|
10070 | 12497 | |
---|
10071 | | -#ifdef BCMDBUS |
---|
10072 | | - tasklet_kill(&dhd->tasklet); |
---|
10073 | | -#else |
---|
10074 | 12498 | if (dhd->dhd_state & DHD_ATTACH_STATE_THREADS_CREATED) { |
---|
| 12499 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 12500 | + if (dhd->thr_rpm_ctl.thr_pid >= 0) { |
---|
| 12501 | + PROC_STOP(&dhd->thr_rpm_ctl); |
---|
| 12502 | + } |
---|
| 12503 | +#endif /* DHD_PCIE_RUNTIMEPM */ |
---|
10075 | 12504 | if (dhd->thr_wdt_ctl.thr_pid >= 0) { |
---|
10076 | 12505 | PROC_STOP(&dhd->thr_wdt_ctl); |
---|
10077 | 12506 | } |
---|
.. | .. |
---|
10082 | 12511 | |
---|
10083 | 12512 | if (dhd->thr_dpc_ctl.thr_pid >= 0) { |
---|
10084 | 12513 | PROC_STOP(&dhd->thr_dpc_ctl); |
---|
10085 | | - } else { |
---|
| 12514 | + } else |
---|
| 12515 | + { |
---|
10086 | 12516 | tasklet_kill(&dhd->tasklet); |
---|
10087 | | -#ifdef DHD_LB_RXP |
---|
10088 | | - __skb_queue_purge(&dhd->rx_pend_queue); |
---|
10089 | | -#endif /* DHD_LB_RXP */ |
---|
10090 | 12517 | } |
---|
10091 | 12518 | } |
---|
10092 | | -#endif /* BCMDBUS */ |
---|
10093 | 12519 | |
---|
10094 | | -#if defined(DHD_LB) |
---|
10095 | | - /* Kill the Load Balancing Tasklets */ |
---|
10096 | | -#if defined(DHD_LB_TXC) |
---|
10097 | | - tasklet_disable(&dhd->tx_compl_tasklet); |
---|
10098 | | - tasklet_kill(&dhd->tx_compl_tasklet); |
---|
| 12520 | +#ifdef WL_NATOE |
---|
| 12521 | + if (dhd->pub.nfct) { |
---|
| 12522 | + dhd_ct_close(dhd->pub.nfct); |
---|
| 12523 | + } |
---|
| 12524 | +#endif /* WL_NATOE */ |
---|
| 12525 | + |
---|
| 12526 | +#ifdef DHD_LB |
---|
| 12527 | + if (dhd->dhd_state & DHD_ATTACH_STATE_LB_ATTACH_DONE) { |
---|
| 12528 | + /* Clear the flag first to avoid calling the cpu notifier */ |
---|
| 12529 | + dhd->dhd_state &= ~DHD_ATTACH_STATE_LB_ATTACH_DONE; |
---|
| 12530 | + |
---|
| 12531 | + /* Kill the Load Balancing Tasklets */ |
---|
| 12532 | +#ifdef DHD_LB_RXP |
---|
| 12533 | + cancel_work_sync(&dhd->rx_napi_dispatcher_work); |
---|
| 12534 | + __skb_queue_purge(&dhd->rx_pend_queue); |
---|
| 12535 | +#endif /* DHD_LB_RXP */ |
---|
| 12536 | +#ifdef DHD_LB_TXP |
---|
| 12537 | + cancel_work_sync(&dhd->tx_dispatcher_work); |
---|
| 12538 | + tasklet_kill(&dhd->tx_tasklet); |
---|
| 12539 | + __skb_queue_purge(&dhd->tx_pend_queue); |
---|
| 12540 | +#endif /* DHD_LB_TXP */ |
---|
| 12541 | +#ifdef DHD_LB_TXC |
---|
| 12542 | + cancel_work_sync(&dhd->tx_compl_dispatcher_work); |
---|
| 12543 | + tasklet_kill(&dhd->tx_compl_tasklet); |
---|
10099 | 12544 | #endif /* DHD_LB_TXC */ |
---|
10100 | | -#if defined(DHD_LB_RXC) |
---|
10101 | | - tasklet_disable(&dhd->rx_compl_tasklet); |
---|
10102 | | - tasklet_kill(&dhd->rx_compl_tasklet); |
---|
| 12545 | +#ifdef DHD_LB_RXC |
---|
| 12546 | + tasklet_kill(&dhd->rx_compl_tasklet); |
---|
10103 | 12547 | #endif /* DHD_LB_RXC */ |
---|
10104 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) |
---|
10105 | | - cpuhp_state_remove_instance(dhd_cpuhp_online_state, &dhd->node_online); |
---|
10106 | | - cpuhp_remove_multi_state(dhd_cpuhp_online_state); |
---|
10107 | | -#else |
---|
10108 | | - if (dhd->cpu_notifier.notifier_call != NULL) |
---|
10109 | | - unregister_cpu_notifier(&dhd->cpu_notifier); |
---|
10110 | | -#endif |
---|
10111 | | - dhd_cpumasks_deinit(dhd); |
---|
10112 | 12548 | |
---|
| 12549 | + /* Unregister from CPU Hotplug framework */ |
---|
| 12550 | + dhd_unregister_cpuhp_callback(dhd); |
---|
| 12551 | + |
---|
| 12552 | + dhd_cpumasks_deinit(dhd); |
---|
| 12553 | + DHD_LB_STATS_DEINIT(&dhd->pub); |
---|
| 12554 | + } |
---|
10113 | 12555 | #endif /* DHD_LB */ |
---|
| 12556 | + |
---|
| 12557 | +#if defined(DNGL_AXI_ERROR_LOGGING) && defined(DHD_USE_WQ_FOR_DNGL_AXI_ERROR) |
---|
| 12558 | + cancel_work_sync(&dhd->axi_error_dispatcher_work); |
---|
| 12559 | +#endif /* DNGL_AXI_ERROR_LOGGING && DHD_USE_WQ_FOR_DNGL_AXI_ERROR */ |
---|
| 12560 | + |
---|
| 12561 | + DHD_SSSR_MEMPOOL_DEINIT(&dhd->pub); |
---|
10114 | 12562 | |
---|
10115 | 12563 | #ifdef WL_CFG80211 |
---|
10116 | 12564 | if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { |
---|
10117 | | - wl_cfg80211_detach(NULL); |
---|
10118 | | - dhd_monitor_uninit(); |
---|
| 12565 | + if (!cfg) { |
---|
| 12566 | + DHD_ERROR(("cfg NULL!\n")); |
---|
| 12567 | + ASSERT(0); |
---|
| 12568 | + } else { |
---|
| 12569 | + wl_cfg80211_detach(cfg); |
---|
| 12570 | +#ifdef DHD_MONITOR_INTERFACE |
---|
| 12571 | + dhd_monitor_uninit(); |
---|
| 12572 | +#endif /* DHD_MONITOR_INTERFACE */ |
---|
| 12573 | + } |
---|
10119 | 12574 | } |
---|
10120 | | -#endif |
---|
10121 | | - /* free deferred work queue */ |
---|
10122 | | - dhd_deferred_work_deinit(dhd->dhd_deferred_wq); |
---|
10123 | | - dhd->dhd_deferred_wq = NULL; |
---|
| 12575 | +#endif /* WL_CFG80211 */ |
---|
10124 | 12576 | |
---|
10125 | | -#ifdef BCMDBUS |
---|
10126 | | - if (dhdp->dbus) { |
---|
10127 | | - dbus_detach(dhdp->dbus); |
---|
10128 | | - dhdp->dbus = NULL; |
---|
| 12577 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 12578 | + destroy_workqueue(dhd->tx_wq); |
---|
| 12579 | + dhd->tx_wq = NULL; |
---|
| 12580 | + destroy_workqueue(dhd->rx_wq); |
---|
| 12581 | + dhd->rx_wq = NULL; |
---|
| 12582 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
| 12583 | +#ifdef DEBUGABILITY |
---|
| 12584 | + if (dhdp->dbg) { |
---|
| 12585 | +#ifdef DBG_PKT_MON |
---|
| 12586 | + dhd_os_dbg_detach_pkt_monitor(dhdp); |
---|
| 12587 | + dhd_os_spin_lock_deinit(dhd->pub.osh, dhd->pub.dbg->pkt_mon_lock); |
---|
| 12588 | +#endif /* DBG_PKT_MON */ |
---|
10129 | 12589 | } |
---|
10130 | | -#endif /* BCMDBUS */ |
---|
10131 | | -#ifdef SHOW_LOGTRACE |
---|
10132 | | - if (dhdp->dbg) |
---|
| 12590 | +#endif /* DEBUGABILITY */ |
---|
| 12591 | + if (dhdp->dbg) { |
---|
10133 | 12592 | dhd_os_dbg_detach(dhdp); |
---|
10134 | | - if (dhd->event_data.fmts) |
---|
10135 | | - kfree(dhd->event_data.fmts); |
---|
10136 | | - if (dhd->event_data.raw_fmts) |
---|
10137 | | - kfree(dhd->event_data.raw_fmts); |
---|
10138 | | - if (dhd->event_data.raw_sstr) |
---|
10139 | | - kfree(dhd->event_data.raw_sstr); |
---|
10140 | | -#endif /* SHOW_LOGTRACE */ |
---|
| 12593 | + } |
---|
| 12594 | +#ifdef DHD_PKT_LOGGING |
---|
| 12595 | + dhd_os_detach_pktlog(dhdp); |
---|
| 12596 | +#endif /* DHD_PKT_LOGGING */ |
---|
| 12597 | +#ifdef DHD_STATUS_LOGGING |
---|
| 12598 | + dhd_detach_statlog(dhdp); |
---|
| 12599 | +#endif /* DHD_STATUS_LOGGING */ |
---|
| 12600 | +#ifdef DHD_PKTDUMP_ROAM |
---|
| 12601 | + dhd_dump_pkt_deinit(dhdp); |
---|
| 12602 | +#endif /* DHD_PKTDUMP_ROAM */ |
---|
| 12603 | +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT |
---|
| 12604 | + if (dhd->pub.hang_info) { |
---|
| 12605 | + MFREE(dhd->pub.osh, dhd->pub.hang_info, VENDOR_SEND_HANG_EXT_INFO_LEN); |
---|
| 12606 | + } |
---|
| 12607 | +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ |
---|
| 12608 | +#ifdef SHOW_LOGTRACE |
---|
| 12609 | + /* Release the skbs from queue for WLC_E_TRACE event */ |
---|
| 12610 | + dhd_event_logtrace_flush_queue(dhdp); |
---|
10141 | 12611 | |
---|
| 12612 | + /* Wait till event logtrace context finishes */ |
---|
| 12613 | + dhd_cancel_logtrace_process_sync(dhd); |
---|
| 12614 | + |
---|
| 12615 | + /* Remove ring proc entries */ |
---|
| 12616 | + dhd_dbg_ring_proc_destroy(&dhd->pub); |
---|
| 12617 | + |
---|
| 12618 | + if (dhd->dhd_state & DHD_ATTACH_LOGTRACE_INIT) { |
---|
| 12619 | + if (dhd->event_data.fmts) { |
---|
| 12620 | + MFREE(dhd->pub.osh, dhd->event_data.fmts, |
---|
| 12621 | + dhd->event_data.fmts_size); |
---|
| 12622 | + dhd->event_data.fmts = NULL; |
---|
| 12623 | + } |
---|
| 12624 | + if (dhd->event_data.raw_fmts) { |
---|
| 12625 | + MFREE(dhd->pub.osh, dhd->event_data.raw_fmts, |
---|
| 12626 | + dhd->event_data.raw_fmts_size); |
---|
| 12627 | + dhd->event_data.raw_fmts = NULL; |
---|
| 12628 | + } |
---|
| 12629 | + if (dhd->event_data.raw_sstr) { |
---|
| 12630 | + MFREE(dhd->pub.osh, dhd->event_data.raw_sstr, |
---|
| 12631 | + dhd->event_data.raw_sstr_size); |
---|
| 12632 | + dhd->event_data.raw_sstr = NULL; |
---|
| 12633 | + } |
---|
| 12634 | + if (dhd->event_data.rom_raw_sstr) { |
---|
| 12635 | + MFREE(dhd->pub.osh, dhd->event_data.rom_raw_sstr, |
---|
| 12636 | + dhd->event_data.rom_raw_sstr_size); |
---|
| 12637 | + dhd->event_data.rom_raw_sstr = NULL; |
---|
| 12638 | + } |
---|
| 12639 | + dhd->dhd_state &= ~DHD_ATTACH_LOGTRACE_INIT; |
---|
| 12640 | + } |
---|
| 12641 | +#endif /* SHOW_LOGTRACE */ |
---|
10142 | 12642 | #ifdef PNO_SUPPORT |
---|
10143 | 12643 | if (dhdp->pno_state) |
---|
10144 | 12644 | dhd_pno_deinit(dhdp); |
---|
10145 | | -#endif |
---|
| 12645 | +#endif // endif |
---|
10146 | 12646 | #ifdef RTT_SUPPORT |
---|
10147 | 12647 | if (dhdp->rtt_state) { |
---|
10148 | | - dhd_rtt_deinit(dhdp); |
---|
| 12648 | + dhd_rtt_deinit(dhdp); |
---|
10149 | 12649 | } |
---|
10150 | | -#endif |
---|
| 12650 | +#endif // endif |
---|
10151 | 12651 | #if defined(CONFIG_PM_SLEEP) |
---|
10152 | 12652 | if (dhd_pm_notifier_registered) { |
---|
10153 | 12653 | unregister_pm_notifier(&dhd->pm_notifier); |
---|
.. | .. |
---|
10160 | 12660 | free_percpu(dhd->new_freq); |
---|
10161 | 12661 | dhd->new_freq = NULL; |
---|
10162 | 12662 | cpufreq_unregister_notifier(&dhd->freq_trans, CPUFREQ_TRANSITION_NOTIFIER); |
---|
10163 | | -#endif |
---|
| 12663 | +#endif // endif |
---|
| 12664 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
| 12665 | + dhd->wakelock_wd_counter = 0; |
---|
| 12666 | + wake_lock_destroy(&dhd->wl_wdwake); |
---|
| 12667 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
10164 | 12668 | if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) { |
---|
10165 | 12669 | DHD_TRACE(("wd wakelock count:%d\n", dhd->wakelock_wd_counter)); |
---|
10166 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
10167 | | - dhd->wakelock_counter = 0; |
---|
10168 | | - dhd->wakelock_wd_counter = 0; |
---|
10169 | | - wake_lock_destroy(&dhd->wl_wifi); |
---|
10170 | | - wake_lock_destroy(&dhd->wl_wdwake); |
---|
10171 | 12670 | DHD_OS_WAKE_LOCK_DESTROY(dhd); |
---|
10172 | | -#endif /* CONFIG_HAS_WAKELOCK */ |
---|
10173 | 12671 | } |
---|
10174 | | - |
---|
10175 | | - |
---|
10176 | 12672 | |
---|
10177 | 12673 | #ifdef DHDTCPACK_SUPPRESS |
---|
10178 | 12674 | /* This will free all MEM allocated for TCPACK SUPPRESS */ |
---|
.. | .. |
---|
10180 | 12676 | #endif /* DHDTCPACK_SUPPRESS */ |
---|
10181 | 12677 | |
---|
10182 | 12678 | #ifdef PCIE_FULL_DONGLE |
---|
10183 | | - dhd_flow_rings_deinit(dhdp); |
---|
10184 | | - if (dhdp->prot) |
---|
10185 | | - dhd_prot_detach(dhdp); |
---|
10186 | | -#endif |
---|
| 12679 | + dhd_flow_rings_deinit(dhdp); |
---|
| 12680 | + if (dhdp->prot) |
---|
| 12681 | + dhd_prot_detach(dhdp); |
---|
| 12682 | +#endif // endif |
---|
10187 | 12683 | |
---|
10188 | | - dhd_fw_downloaded = FALSE; |
---|
10189 | | -} |
---|
| 12684 | +#if defined(WLTDLS) && defined(PCIE_FULL_DONGLE) |
---|
| 12685 | + dhd_free_tdls_peer_list(dhdp); |
---|
| 12686 | +#endif // endif |
---|
10190 | 12687 | |
---|
| 12688 | +#ifdef DUMP_IOCTL_IOV_LIST |
---|
| 12689 | + dhd_iov_li_delete(dhdp, &(dhdp->dump_iovlist_head)); |
---|
| 12690 | +#endif /* DUMP_IOCTL_IOV_LIST */ |
---|
| 12691 | +#ifdef DHD_DEBUG |
---|
| 12692 | + /* memory waste feature list initilization */ |
---|
| 12693 | + dhd_mw_list_delete(dhdp, &(dhdp->mw_list_head)); |
---|
| 12694 | +#endif /* DHD_DEBUG */ |
---|
| 12695 | +#ifdef WL_MONITOR |
---|
| 12696 | + dhd_del_monitor_if(dhd); |
---|
| 12697 | +#endif /* WL_MONITOR */ |
---|
| 12698 | + |
---|
| 12699 | +#ifdef DHD_ERPOM |
---|
| 12700 | + if (dhdp->enable_erpom) { |
---|
| 12701 | + dhdp->pom_func_deregister(&dhdp->pom_wlan_handler); |
---|
| 12702 | + } |
---|
| 12703 | +#endif /* DHD_ERPOM */ |
---|
| 12704 | + |
---|
| 12705 | + cancel_work_sync(&dhd->dhd_hang_process_work); |
---|
| 12706 | + |
---|
| 12707 | + /* Prefer adding de-init code above this comment unless necessary. |
---|
| 12708 | + * The idea is to cancel work queue, sysfs and flags at the end. |
---|
| 12709 | + */ |
---|
| 12710 | + dhd_deferred_work_deinit(dhd->dhd_deferred_wq); |
---|
| 12711 | + dhd->dhd_deferred_wq = NULL; |
---|
| 12712 | + |
---|
| 12713 | + /* log dump related buffers should be freed after wq is purged */ |
---|
| 12714 | +#ifdef DHD_LOG_DUMP |
---|
| 12715 | + dhd_log_dump_deinit(&dhd->pub); |
---|
| 12716 | +#endif /* DHD_LOG_DUMP */ |
---|
| 12717 | +#if defined(BCMPCIE) |
---|
| 12718 | + if (dhdp->extended_trap_data) |
---|
| 12719 | + { |
---|
| 12720 | + MFREE(dhdp->osh, dhdp->extended_trap_data, BCMPCIE_EXT_TRAP_DATA_MAXLEN); |
---|
| 12721 | + dhdp->extended_trap_data = NULL; |
---|
| 12722 | + } |
---|
| 12723 | +#ifdef DNGL_AXI_ERROR_LOGGING |
---|
| 12724 | + if (dhdp->axi_err_dump) |
---|
| 12725 | + { |
---|
| 12726 | + MFREE(dhdp->osh, dhdp->axi_err_dump, sizeof(dhd_axi_error_dump_t)); |
---|
| 12727 | + dhdp->axi_err_dump = NULL; |
---|
| 12728 | + } |
---|
| 12729 | +#endif /* DNGL_AXI_ERROR_LOGGING */ |
---|
| 12730 | +#endif /* BCMPCIE */ |
---|
| 12731 | + |
---|
| 12732 | +#ifdef DHD_DUMP_MNGR |
---|
| 12733 | + if (dhd->pub.dump_file_manage) { |
---|
| 12734 | + MFREE(dhd->pub.osh, dhd->pub.dump_file_manage, |
---|
| 12735 | + sizeof(dhd_dump_file_manage_t)); |
---|
| 12736 | + } |
---|
| 12737 | +#endif /* DHD_DUMP_MNGR */ |
---|
| 12738 | + dhd_sysfs_exit(dhd); |
---|
| 12739 | + dhd->pub.fw_download_status = FW_UNLOADED; |
---|
| 12740 | + |
---|
| 12741 | +#if defined(BT_OVER_SDIO) |
---|
| 12742 | + mutex_destroy(&dhd->bus_user_lock); |
---|
| 12743 | +#endif /* BT_OVER_SDIO */ |
---|
| 12744 | + |
---|
| 12745 | +} /* dhd_detach */ |
---|
10191 | 12746 | |
---|
10192 | 12747 | void |
---|
10193 | 12748 | dhd_free(dhd_pub_t *dhdp) |
---|
.. | .. |
---|
10224 | 12779 | #endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */ |
---|
10225 | 12780 | dhdp->soc_ram = NULL; |
---|
10226 | 12781 | } |
---|
10227 | | -#ifdef CACHE_FW_IMAGES |
---|
10228 | | - if (dhdp->cached_fw) { |
---|
10229 | | - MFREE(dhdp->osh, dhdp->cached_fw, dhdp->bus->ramsize); |
---|
10230 | | - dhdp->cached_fw = NULL; |
---|
10231 | | - } |
---|
| 12782 | + if (dhd != NULL) { |
---|
10232 | 12783 | |
---|
10233 | | - if (dhdp->cached_nvram) { |
---|
10234 | | - MFREE(dhdp->osh, dhdp->cached_nvram, MAX_NVRAMBUF_SIZE); |
---|
10235 | | - dhdp->cached_nvram = NULL; |
---|
| 12784 | + /* If pointer is allocated by dhd_os_prealloc then avoid MFREE */ |
---|
| 12785 | + if (dhd != (dhd_info_t *)dhd_os_prealloc(dhdp, |
---|
| 12786 | + DHD_PREALLOC_DHD_INFO, 0, FALSE)) |
---|
| 12787 | + MFREE(dhd->pub.osh, dhd, sizeof(*dhd)); |
---|
| 12788 | + dhd = NULL; |
---|
10236 | 12789 | } |
---|
10237 | | -#endif |
---|
10238 | | - /* If pointer is allocated by dhd_os_prealloc then avoid MFREE */ |
---|
10239 | | - if (dhd && |
---|
10240 | | - dhd != (dhd_info_t *)dhd_os_prealloc(dhdp, DHD_PREALLOC_DHD_INFO, 0, FALSE)) |
---|
10241 | | - MFREE(dhd->pub.osh, dhd, sizeof(*dhd)); |
---|
10242 | | - dhd = NULL; |
---|
10243 | 12790 | } |
---|
10244 | 12791 | } |
---|
10245 | 12792 | |
---|
.. | .. |
---|
10288 | 12835 | { |
---|
10289 | 12836 | DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
10290 | 12837 | |
---|
10291 | | -#ifdef BCMDBUS |
---|
10292 | | - dbus_deregister(); |
---|
10293 | | -#else |
---|
10294 | 12838 | dhd_bus_unregister(); |
---|
10295 | | -#endif /* BCMDBUS */ |
---|
10296 | 12839 | |
---|
| 12840 | +#if defined(OEM_ANDROID) |
---|
10297 | 12841 | wl_android_exit(); |
---|
| 12842 | +#endif /* OEM_ANDROID */ |
---|
10298 | 12843 | |
---|
10299 | 12844 | dhd_wifi_platform_unregister_drv(); |
---|
10300 | 12845 | } |
---|
.. | .. |
---|
10302 | 12847 | static void __exit |
---|
10303 | 12848 | dhd_module_exit(void) |
---|
10304 | 12849 | { |
---|
10305 | | - dhd_buzzz_detach(); |
---|
| 12850 | + atomic_set(&exit_in_progress, 1); |
---|
10306 | 12851 | dhd_module_cleanup(); |
---|
10307 | 12852 | unregister_reboot_notifier(&dhd_reboot_notifier); |
---|
| 12853 | + dhd_destroy_to_notifier_skt(); |
---|
10308 | 12854 | } |
---|
10309 | 12855 | |
---|
10310 | 12856 | static int __init |
---|
.. | .. |
---|
10315 | 12861 | |
---|
10316 | 12862 | DHD_ERROR(("%s in\n", __FUNCTION__)); |
---|
10317 | 12863 | |
---|
10318 | | - dhd_buzzz_attach(); |
---|
10319 | | - |
---|
10320 | 12864 | DHD_PERIM_RADIO_INIT(); |
---|
10321 | | - |
---|
10322 | 12865 | |
---|
10323 | 12866 | if (firmware_path[0] != '\0') { |
---|
10324 | 12867 | strncpy(fw_bak_path, firmware_path, MOD_PARAM_PATHLEN); |
---|
.. | .. |
---|
10335 | 12878 | if (!err) { |
---|
10336 | 12879 | register_reboot_notifier(&dhd_reboot_notifier); |
---|
10337 | 12880 | break; |
---|
10338 | | - } |
---|
10339 | | - else { |
---|
| 12881 | + } else { |
---|
10340 | 12882 | DHD_ERROR(("%s: Failed to load the driver, try cnt %d\n", |
---|
10341 | 12883 | __FUNCTION__, retry)); |
---|
10342 | 12884 | strncpy(firmware_path, fw_bak_path, MOD_PARAM_PATHLEN); |
---|
.. | .. |
---|
10345 | 12887 | nvram_path[MOD_PARAM_PATHLEN-1] = '\0'; |
---|
10346 | 12888 | } |
---|
10347 | 12889 | } while (retry--); |
---|
| 12890 | + |
---|
| 12891 | + dhd_create_to_notifier_skt(); |
---|
10348 | 12892 | |
---|
10349 | 12893 | if (err) { |
---|
10350 | 12894 | DHD_ERROR(("%s: Failed to load driver max retry reached**\n", __FUNCTION__)); |
---|
.. | .. |
---|
10363 | 12907 | dhd_reboot_callback(struct notifier_block *this, unsigned long code, void *unused) |
---|
10364 | 12908 | { |
---|
10365 | 12909 | DHD_TRACE(("%s: code = %ld\n", __FUNCTION__, code)); |
---|
10366 | | -#ifdef STBLINUX |
---|
10367 | | - dhd_module_cleanup(); |
---|
10368 | | -#else |
---|
10369 | 12910 | if (code == SYS_RESTART) { |
---|
| 12911 | +#ifdef OEM_ANDROID |
---|
10370 | 12912 | #ifdef BCMPCIE |
---|
10371 | 12913 | is_reboot = code; |
---|
10372 | 12914 | #endif /* BCMPCIE */ |
---|
| 12915 | +#else |
---|
| 12916 | + dhd_module_cleanup(); |
---|
| 12917 | +#endif /* OEM_ANDROID */ |
---|
10373 | 12918 | } |
---|
10374 | | -#endif /* STBLINUX */ |
---|
10375 | 12919 | return NOTIFY_DONE; |
---|
10376 | 12920 | } |
---|
10377 | 12921 | |
---|
10378 | | -#ifdef BCMDBUS |
---|
10379 | | - |
---|
10380 | | -/* |
---|
10381 | | - * hdrlen is space to reserve in pkt headroom for DBUS |
---|
10382 | | - */ |
---|
10383 | | -void * |
---|
10384 | | -dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype, uint32 hdrlen) |
---|
10385 | | -{ |
---|
10386 | | - osl_t *osh; |
---|
10387 | | - int ret = 0; |
---|
10388 | | - dbus_attrib_t attrib; |
---|
10389 | | - dhd_pub_t *pub = NULL; |
---|
10390 | | - |
---|
10391 | | - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
10392 | | - |
---|
10393 | | - /* Ask the OS interface part for an OSL handle */ |
---|
10394 | | - if (!(osh = osl_attach(NULL, bustype, TRUE))) { |
---|
10395 | | - DHD_ERROR(("%s: OSL attach failed\n", __FUNCTION__)); |
---|
10396 | | - ret = -ENOMEM; |
---|
10397 | | - goto fail; |
---|
10398 | | - } |
---|
10399 | | - |
---|
10400 | | - /* Attach to the dhd/OS interface */ |
---|
10401 | | - if (!(pub = dhd_attach(osh, NULL /* bus */, hdrlen))) { |
---|
10402 | | - DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__)); |
---|
10403 | | - ret = -ENXIO; |
---|
10404 | | - goto fail; |
---|
10405 | | - } |
---|
10406 | | - |
---|
10407 | | - /* Ok, finish the attach to the OS network interface */ |
---|
10408 | | - if (dhd_register_if(pub, 0, TRUE) != 0) { |
---|
10409 | | - DHD_ERROR(("%s: dhd_register_if failed\n", __FUNCTION__)); |
---|
10410 | | - ret = -ENXIO; |
---|
10411 | | - goto fail; |
---|
10412 | | - } |
---|
10413 | | - |
---|
10414 | | - pub->dbus = dbus_attach(osh, pub->rxsz, DBUS_NRXQ, DBUS_NTXQ, |
---|
10415 | | - pub->info, &dhd_dbus_cbs, NULL, NULL); |
---|
10416 | | - if (pub->dbus) { |
---|
10417 | | - dbus_get_attrib(pub->dbus, &attrib); |
---|
10418 | | - DHD_ERROR(("DBUS: vid=0x%x pid=0x%x devid=0x%x bustype=0x%x mtu=%d\n", |
---|
10419 | | - attrib.vid, attrib.pid, attrib.devid, attrib.bustype, attrib.mtu)); |
---|
10420 | | - } else { |
---|
10421 | | - ret = -ENXIO; |
---|
10422 | | - goto fail; |
---|
10423 | | - } |
---|
10424 | | -#ifdef BCM_FD_AGGR |
---|
10425 | | - pub->info->rpc_th = bcm_rpc_tp_attach(osh, (void *)pub->dbus); |
---|
10426 | | - if (!pub->info->rpc_th) { |
---|
10427 | | - DHD_ERROR(("%s: bcm_rpc_tp_attach failed\n", __FUNCTION__)); |
---|
10428 | | - ret = -ENXIO; |
---|
10429 | | - goto fail; |
---|
10430 | | - } |
---|
10431 | | - |
---|
10432 | | - pub->info->rpc_osh = rpc_osl_attach(osh); |
---|
10433 | | - if (!pub->info->rpc_osh) { |
---|
10434 | | - DHD_ERROR(("%s: rpc_osl_attach failed\n", __FUNCTION__)); |
---|
10435 | | - bcm_rpc_tp_detach(pub->info->rpc_th); |
---|
10436 | | - pub->info->rpc_th = NULL; |
---|
10437 | | - ret = -ENXIO; |
---|
10438 | | - goto fail; |
---|
10439 | | - } |
---|
10440 | | - /* Set up the aggregation release timer */ |
---|
10441 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) |
---|
10442 | | - timer_setup(&pub->info->rpcth_timer, dhd_rpcth_watchdog, 0) |
---|
10443 | | -#else |
---|
10444 | | - init_timer(&pub->info->rpcth_timer); |
---|
10445 | | - pub->info->rpcth_timer.data = (ulong)pub->info; |
---|
10446 | | - pub->info->rpcth_timer.function = dhd_rpcth_watchdog; |
---|
10447 | | -#endif |
---|
10448 | | - pub->info->rpcth_timer_active = FALSE; |
---|
10449 | | - |
---|
10450 | | - bcm_rpc_tp_register_cb(pub->info->rpc_th, NULL, pub->info, |
---|
10451 | | - dbus_rpcth_rx_pkt, pub->info, pub->info->rpc_osh); |
---|
10452 | | -#endif /* BCM_FD_AGGR */ |
---|
10453 | | - |
---|
10454 | | - /* This is passed to dhd_dbus_disconnect_cb */ |
---|
10455 | | - return pub->info; |
---|
10456 | | -fail: |
---|
10457 | | - /* Release resources in reverse order */ |
---|
10458 | | - if (osh) { |
---|
10459 | | - if (pub) { |
---|
10460 | | - dhd_detach(pub); |
---|
10461 | | - dhd_free(pub); |
---|
10462 | | - } |
---|
10463 | | - osl_detach(osh); |
---|
10464 | | - } |
---|
10465 | | - |
---|
10466 | | - BCM_REFERENCE(ret); |
---|
10467 | | - return NULL; |
---|
10468 | | -} |
---|
10469 | | - |
---|
10470 | | -void |
---|
10471 | | -dhd_dbus_disconnect_cb(void *arg) |
---|
10472 | | -{ |
---|
10473 | | - dhd_info_t *dhd = (dhd_info_t *)arg; |
---|
10474 | | - dhd_pub_t *pub; |
---|
10475 | | - osl_t *osh; |
---|
10476 | | - |
---|
10477 | | - if (dhd == NULL) |
---|
10478 | | - return; |
---|
10479 | | - |
---|
10480 | | - pub = &dhd->pub; |
---|
10481 | | - osh = pub->osh; |
---|
10482 | | -#ifdef BCM_FD_AGGR |
---|
10483 | | - del_timer_sync(&dhd->rpcth_timer); |
---|
10484 | | - bcm_rpc_tp_deregister_cb(dhd->rpc_th); |
---|
10485 | | - rpc_osl_detach(dhd->rpc_osh); |
---|
10486 | | - bcm_rpc_tp_detach(dhd->rpc_th); |
---|
10487 | | -#endif |
---|
10488 | | - dhd_detach(pub); |
---|
10489 | | - dhd_free(pub); |
---|
10490 | | - |
---|
10491 | | - if (MALLOCED(osh)) { |
---|
10492 | | - DHD_ERROR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh))); |
---|
10493 | | - } |
---|
10494 | | - osl_detach(osh); |
---|
10495 | | -} |
---|
10496 | | -#endif /* BCMDBUS */ |
---|
10497 | | - |
---|
10498 | | -#ifdef CONFIG_PLAT_ROCKCHIP |
---|
10499 | | -#include <linux/rfkill-wlan.h> |
---|
10500 | | - |
---|
10501 | | -//rk |
---|
10502 | | -/* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */ |
---|
10503 | | -//static char tcp_keepalive_param[200]; |
---|
10504 | | -static char sabuf[20]="", dabuf[20]=""; |
---|
10505 | | -static char seabuf[ETHER_ADDR_STR_LEN]=""; |
---|
10506 | | -static char deabuf[ETHER_ADDR_STR_LEN]=""; |
---|
10507 | | -static uint16 source, dest, window, ip_id; |
---|
10508 | | -static uint32 seq = 0, seq_ack = 0, tcp_option_len = 0, tcp_data_len = 0, tsval = 0, tsecr = 0; |
---|
10509 | | -#include <linux/hrtimer.h> |
---|
10510 | | -#include <linux/time.h> |
---|
10511 | | -#include <net/tcp.h> |
---|
10512 | | -#include <linux/proc_fs.h> |
---|
10513 | | - |
---|
10514 | | -static int tcp_param_show(struct seq_file *s, void *data) |
---|
10515 | | -{ |
---|
10516 | | - //seq_printf(s, "dhd_priv wl tcpka_conn_add 1 %s %s %s 1 %d %d 1 1 1 1 1 5 0x6865617274\n", |
---|
10517 | | - // deabuf, sabuf, dabuf, source, dest); |
---|
10518 | | - |
---|
10519 | | - //seq_printf(s, "dhd_priv wl tcpka_conn_add 1 %s %s %s %d %d %d %8u %8u %d %8u %8u 0 5 0x6865617274\n", deabuf, sabuf, dabuf, ip_id, source, dest, seq, seq_ack, window, tsval, tsecr); |
---|
10520 | | - seq_printf(s, "wl_cy tcpka_conn_add %s %s %s %d %d %d %8u %8u %d %8u %8u 0 7 Qghappy\n", deabuf, sabuf, dabuf, ip_id, source, dest, seq, seq_ack, window, tsval, tsecr); |
---|
10521 | | - |
---|
10522 | | - return 0; |
---|
10523 | | -} |
---|
10524 | | - |
---|
10525 | | -#ifndef CONFIG_PROC_FS |
---|
10526 | | -DEFINE_SHOW_ATTRIBUTE(tcp_param); |
---|
10527 | | -#endif |
---|
10528 | | - |
---|
10529 | | -static void rk_bcm_add_tcp_keepalive_debugfs(void) |
---|
10530 | | -{ |
---|
10531 | | -#ifdef CONFIG_PROC_FS |
---|
10532 | | - proc_create_single("tcp_params", 0, NULL, tcp_param_show); |
---|
10533 | | -#else |
---|
10534 | | - struct dentry *root; |
---|
10535 | | - |
---|
10536 | | - root = debugfs_create_dir("tcp_keepalive_param", NULL); |
---|
10537 | | - if (IS_ERR(root)) |
---|
10538 | | - /* Don't complain -- debugfs just isn't enabled */ |
---|
10539 | | - return; |
---|
10540 | | - if (!root) |
---|
10541 | | - /* Complain -- debugfs is enabled, but it failed to |
---|
10542 | | - * create the directory. */ |
---|
10543 | | - goto err_root; |
---|
10544 | | - |
---|
10545 | | - if (!debugfs_create_file("tcp_param", S_IRUSR, root, NULL, &tcp_param_fops)) |
---|
10546 | | - goto err_node; |
---|
10547 | | - |
---|
10548 | | - return; |
---|
10549 | | - |
---|
10550 | | -err_node: |
---|
10551 | | - debugfs_remove_recursive(root); |
---|
10552 | | -err_root: |
---|
10553 | | - pr_err("failed to initialize keepalive debugfs\n"); |
---|
10554 | | -#endif |
---|
10555 | | -} |
---|
10556 | | - |
---|
10557 | | -#define CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP 1 |
---|
10558 | | - |
---|
10559 | | -extern int get_wifi_chip_type(void); |
---|
10560 | | -extern char WIFI_MODULE_NAME[]; |
---|
10561 | | -extern char RKWIFI_DRV_VERSION[]; |
---|
10562 | | - |
---|
10563 | | -#ifdef CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP |
---|
10564 | | -static int wifi_init_thread(void *data) |
---|
10565 | | -{ |
---|
10566 | | - rk_bcm_add_tcp_keepalive_debugfs(); |
---|
10567 | | - dhd_module_init(); |
---|
10568 | | - return 0; |
---|
10569 | | -} |
---|
10570 | | -#endif /* CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP */ |
---|
10571 | | - |
---|
10572 | | -int rockchip_wifi_init_module_rkwifi(void) |
---|
10573 | | -{ |
---|
10574 | | -#ifdef CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP |
---|
10575 | | - struct task_struct *kthread = NULL; |
---|
10576 | | - |
---|
10577 | | - kthread = kthread_run(wifi_init_thread, NULL, "wifi_init_thread"); |
---|
10578 | | - |
---|
10579 | | - if (IS_ERR(kthread)) { |
---|
10580 | | - DHD_ERROR(("create wifi_init_thread failed.\n")); |
---|
10581 | | - } |
---|
10582 | | - |
---|
10583 | | - return 0; |
---|
10584 | | -#else /* CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP */ |
---|
10585 | | - return dhd_module_init(); |
---|
10586 | | -#endif /* CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP */ |
---|
10587 | | -} |
---|
10588 | | - |
---|
10589 | | -void rockchip_wifi_exit_module_rkwifi(void) |
---|
10590 | | -{ |
---|
10591 | | - dhd_module_exit(); |
---|
10592 | | -} |
---|
10593 | | - |
---|
10594 | | -#ifdef CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP |
---|
10595 | | -late_initcall(rockchip_wifi_init_module_rkwifi); |
---|
10596 | | -module_exit(rockchip_wifi_exit_module_rkwifi); |
---|
10597 | | -#else /* CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP */ |
---|
10598 | | -EXPORT_SYMBOL(rockchip_wifi_init_module_rkwifi); |
---|
10599 | | -EXPORT_SYMBOL(rockchip_wifi_exit_module_rkwifi); |
---|
10600 | | -#endif /* CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP */ |
---|
10601 | | - |
---|
10602 | | -#else /* CONFIG_PLAT_ROCKCHIP */ |
---|
10603 | | - |
---|
10604 | | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) |
---|
10605 | | -#if defined(CONFIG_DEFERRED_INITCALLS) |
---|
10606 | | -#if defined(CONFIG_MACH_UNIVERSAL7420) |
---|
| 12922 | +#if defined(CONFIG_DEFERRED_INITCALLS) && !defined(EXYNOS_PCIE_MODULE_PATCH) |
---|
| 12923 | +#if defined(CONFIG_MACH_UNIVERSAL7420) || defined(CONFIG_SOC_EXYNOS8890) || \ |
---|
| 12924 | + defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_ARCH_MSM8998) || \ |
---|
| 12925 | + defined(CONFIG_SOC_EXYNOS8895) || defined(CONFIG_SOC_EXYNOS9810) || \ |
---|
| 12926 | + defined(CONFIG_ARCH_SDM845) || defined(CONFIG_SOC_EXYNOS9820) || \ |
---|
| 12927 | + defined(CONFIG_ARCH_SM8150) |
---|
10607 | 12928 | deferred_module_init_sync(dhd_module_init); |
---|
10608 | 12929 | #else |
---|
10609 | 12930 | deferred_module_init(dhd_module_init); |
---|
10610 | | -#endif /* CONFIG_MACH_UNIVERSAL7420 */ |
---|
| 12931 | +#endif /* CONFIG_MACH_UNIVERSAL7420 || CONFIG_SOC_EXYNOS8890 || |
---|
| 12932 | + * CONFIG_ARCH_MSM8996 || CONFIG_ARCH_MSM8998 || CONFIG_SOC_EXYNOS8895 |
---|
| 12933 | + * CONFIG_SOC_EXYNOS9810 || CONFIG_ARCH_SDM845 || CONFIG_SOC_EXYNOS9820 |
---|
| 12934 | + * CONFIG_ARCH_SM8150 |
---|
| 12935 | + */ |
---|
10611 | 12936 | #elif defined(USE_LATE_INITCALL_SYNC) |
---|
10612 | 12937 | late_initcall_sync(dhd_module_init); |
---|
10613 | 12938 | #else |
---|
10614 | 12939 | late_initcall(dhd_module_init); |
---|
10615 | 12940 | #endif /* USE_LATE_INITCALL_SYNC */ |
---|
10616 | | -#else |
---|
10617 | | -module_init(dhd_module_init); |
---|
10618 | | -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ |
---|
10619 | 12941 | |
---|
10620 | 12942 | module_exit(dhd_module_exit); |
---|
10621 | | - |
---|
10622 | | -#endif/* CONFIG_PLAT_ROCKCHIP */ |
---|
10623 | 12943 | |
---|
10624 | 12944 | /* |
---|
10625 | 12945 | * OS specific functions required to implement DHD driver in OS independent way |
---|
.. | .. |
---|
10654 | 12974 | return 0; |
---|
10655 | 12975 | } |
---|
10656 | 12976 | |
---|
| 12977 | +void |
---|
| 12978 | +dhd_os_dhdiovar_lock(dhd_pub_t *pub) |
---|
| 12979 | +{ |
---|
| 12980 | + dhd_info_t * dhd = (dhd_info_t *)(pub->info); |
---|
| 12981 | + |
---|
| 12982 | + if (dhd) { |
---|
| 12983 | + mutex_lock(&dhd->dhd_iovar_mutex); |
---|
| 12984 | + } |
---|
| 12985 | +} |
---|
| 12986 | + |
---|
| 12987 | +void |
---|
| 12988 | +dhd_os_dhdiovar_unlock(dhd_pub_t *pub) |
---|
| 12989 | +{ |
---|
| 12990 | + dhd_info_t * dhd = (dhd_info_t *)(pub->info); |
---|
| 12991 | + |
---|
| 12992 | + if (dhd) { |
---|
| 12993 | + mutex_unlock(&dhd->dhd_iovar_mutex); |
---|
| 12994 | + } |
---|
| 12995 | +} |
---|
| 12996 | + |
---|
| 12997 | +void |
---|
| 12998 | +dhd_os_logdump_lock(dhd_pub_t *pub) |
---|
| 12999 | +{ |
---|
| 13000 | + dhd_info_t *dhd = NULL; |
---|
| 13001 | + |
---|
| 13002 | + if (!pub) |
---|
| 13003 | + return; |
---|
| 13004 | + |
---|
| 13005 | + dhd = (dhd_info_t *)(pub->info); |
---|
| 13006 | + |
---|
| 13007 | + if (dhd) { |
---|
| 13008 | + mutex_lock(&dhd->logdump_lock); |
---|
| 13009 | + } |
---|
| 13010 | +} |
---|
| 13011 | + |
---|
| 13012 | +void |
---|
| 13013 | +dhd_os_logdump_unlock(dhd_pub_t *pub) |
---|
| 13014 | +{ |
---|
| 13015 | + dhd_info_t *dhd = NULL; |
---|
| 13016 | + |
---|
| 13017 | + if (!pub) |
---|
| 13018 | + return; |
---|
| 13019 | + |
---|
| 13020 | + dhd = (dhd_info_t *)(pub->info); |
---|
| 13021 | + |
---|
| 13022 | + if (dhd) { |
---|
| 13023 | + mutex_unlock(&dhd->logdump_lock); |
---|
| 13024 | + } |
---|
| 13025 | +} |
---|
| 13026 | + |
---|
| 13027 | +unsigned long |
---|
| 13028 | +dhd_os_dbgring_lock(void *lock) |
---|
| 13029 | +{ |
---|
| 13030 | + if (!lock) |
---|
| 13031 | + return 0; |
---|
| 13032 | + |
---|
| 13033 | + mutex_lock((struct mutex *)lock); |
---|
| 13034 | + |
---|
| 13035 | + return 0; |
---|
| 13036 | +} |
---|
| 13037 | + |
---|
| 13038 | +void |
---|
| 13039 | +dhd_os_dbgring_unlock(void *lock, unsigned long flags) |
---|
| 13040 | +{ |
---|
| 13041 | + BCM_REFERENCE(flags); |
---|
| 13042 | + |
---|
| 13043 | + if (!lock) |
---|
| 13044 | + return; |
---|
| 13045 | + |
---|
| 13046 | + mutex_unlock((struct mutex *)lock); |
---|
| 13047 | +} |
---|
| 13048 | + |
---|
10657 | 13049 | unsigned int |
---|
10658 | 13050 | dhd_os_get_ioctl_resp_timeout(void) |
---|
10659 | 13051 | { |
---|
.. | .. |
---|
10673 | 13065 | int timeout; |
---|
10674 | 13066 | |
---|
10675 | 13067 | /* Convert timeout in millsecond to jiffies */ |
---|
10676 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) |
---|
10677 | 13068 | timeout = msecs_to_jiffies(dhd_ioctl_timeout_msec); |
---|
10678 | | -#else |
---|
10679 | | - timeout = dhd_ioctl_timeout_msec * HZ / 1000; |
---|
10680 | | -#endif |
---|
10681 | 13069 | |
---|
10682 | 13070 | DHD_PERIM_UNLOCK(pub); |
---|
10683 | 13071 | |
---|
.. | .. |
---|
10704 | 13092 | int timeout; |
---|
10705 | 13093 | |
---|
10706 | 13094 | /* Convert timeout in millsecond to jiffies */ |
---|
10707 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) |
---|
10708 | | - timeout = msecs_to_jiffies(dhd_ioctl_timeout_msec); |
---|
10709 | | -#else |
---|
10710 | | - timeout = dhd_ioctl_timeout_msec * HZ / 1000; |
---|
10711 | | -#endif |
---|
| 13095 | + timeout = msecs_to_jiffies(D3_ACK_RESP_TIMEOUT); |
---|
10712 | 13096 | |
---|
10713 | 13097 | DHD_PERIM_UNLOCK(pub); |
---|
10714 | 13098 | |
---|
.. | .. |
---|
10739 | 13123 | * so that IOCTL timeout should not get affected. |
---|
10740 | 13124 | */ |
---|
10741 | 13125 | /* Convert timeout in millsecond to jiffies */ |
---|
10742 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) |
---|
10743 | 13126 | timeout = msecs_to_jiffies(DHD_BUS_BUSY_TIMEOUT); |
---|
10744 | | -#else |
---|
10745 | | - timeout = DHD_BUS_BUSY_TIMEOUT * HZ / 1000; |
---|
10746 | | -#endif |
---|
10747 | 13127 | |
---|
10748 | 13128 | timeout = wait_event_timeout(dhd->dhd_bus_busy_state_wait, !(*condition), timeout); |
---|
10749 | 13129 | |
---|
10750 | 13130 | return timeout; |
---|
10751 | 13131 | } |
---|
10752 | 13132 | |
---|
| 13133 | +/* |
---|
| 13134 | + * Wait until the condition *var == condition is met. |
---|
| 13135 | + * Returns 0 if the @condition evaluated to false after the timeout elapsed |
---|
| 13136 | + * Returns 1 if the @condition evaluated to true |
---|
| 13137 | + */ |
---|
| 13138 | +int |
---|
| 13139 | +dhd_os_busbusy_wait_condition(dhd_pub_t *pub, uint *var, uint condition) |
---|
| 13140 | +{ |
---|
| 13141 | + dhd_info_t * dhd = (dhd_info_t *)(pub->info); |
---|
| 13142 | + int timeout; |
---|
| 13143 | + |
---|
| 13144 | + /* Convert timeout in millsecond to jiffies */ |
---|
| 13145 | + timeout = msecs_to_jiffies(DHD_BUS_BUSY_TIMEOUT); |
---|
| 13146 | + |
---|
| 13147 | + timeout = wait_event_timeout(dhd->dhd_bus_busy_state_wait, (*var == condition), timeout); |
---|
| 13148 | + |
---|
| 13149 | + return timeout; |
---|
| 13150 | +} |
---|
| 13151 | + |
---|
| 13152 | +/* |
---|
| 13153 | + * Wait until the '(*var & bitmask) == condition' is met. |
---|
| 13154 | + * Returns 0 if the @condition evaluated to false after the timeout elapsed |
---|
| 13155 | + * Returns 1 if the @condition evaluated to true |
---|
| 13156 | + */ |
---|
| 13157 | +int |
---|
| 13158 | +dhd_os_busbusy_wait_bitmask(dhd_pub_t *pub, uint *var, |
---|
| 13159 | + uint bitmask, uint condition) |
---|
| 13160 | +{ |
---|
| 13161 | + dhd_info_t * dhd = (dhd_info_t *)(pub->info); |
---|
| 13162 | + int timeout; |
---|
| 13163 | + |
---|
| 13164 | + /* Convert timeout in millsecond to jiffies */ |
---|
| 13165 | + timeout = msecs_to_jiffies(DHD_BUS_BUSY_TIMEOUT); |
---|
| 13166 | + |
---|
| 13167 | + timeout = wait_event_timeout(dhd->dhd_bus_busy_state_wait, |
---|
| 13168 | + ((*var & bitmask) == condition), timeout); |
---|
| 13169 | + |
---|
| 13170 | + return timeout; |
---|
| 13171 | +} |
---|
| 13172 | + |
---|
| 13173 | +int |
---|
| 13174 | +dhd_os_dmaxfer_wait(dhd_pub_t *pub, uint *condition) |
---|
| 13175 | +{ |
---|
| 13176 | + int ret = 0; |
---|
| 13177 | + dhd_info_t * dhd = (dhd_info_t *)(pub->info); |
---|
| 13178 | + int timeout; |
---|
| 13179 | + |
---|
| 13180 | + timeout = msecs_to_jiffies(IOCTL_DMAXFER_TIMEOUT); |
---|
| 13181 | + |
---|
| 13182 | + DHD_PERIM_UNLOCK(pub); |
---|
| 13183 | + ret = wait_event_timeout(dhd->dmaxfer_wait, (*condition), timeout); |
---|
| 13184 | + DHD_PERIM_LOCK(pub); |
---|
| 13185 | + |
---|
| 13186 | + return ret; |
---|
| 13187 | + |
---|
| 13188 | +} |
---|
| 13189 | + |
---|
| 13190 | +int |
---|
| 13191 | +dhd_os_dmaxfer_wake(dhd_pub_t *pub) |
---|
| 13192 | +{ |
---|
| 13193 | + dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
| 13194 | + |
---|
| 13195 | + wake_up(&dhd->dmaxfer_wait); |
---|
| 13196 | + return 0; |
---|
| 13197 | +} |
---|
| 13198 | + |
---|
| 13199 | +void |
---|
| 13200 | +dhd_os_tx_completion_wake(dhd_pub_t *dhd) |
---|
| 13201 | +{ |
---|
| 13202 | + /* Call wmb() to make sure before waking up the other event value gets updated */ |
---|
| 13203 | + OSL_SMP_WMB(); |
---|
| 13204 | + wake_up(&dhd->tx_completion_wait); |
---|
| 13205 | +} |
---|
| 13206 | + |
---|
| 13207 | +/* Fix compilation error for FC11 */ |
---|
10753 | 13208 | INLINE int |
---|
10754 | 13209 | dhd_os_busbusy_wake(dhd_pub_t *pub) |
---|
10755 | 13210 | { |
---|
.. | .. |
---|
10763 | 13218 | void |
---|
10764 | 13219 | dhd_os_wd_timer_extend(void *bus, bool extend) |
---|
10765 | 13220 | { |
---|
10766 | | -#ifndef BCMDBUS |
---|
10767 | 13221 | dhd_pub_t *pub = bus; |
---|
10768 | 13222 | dhd_info_t *dhd = (dhd_info_t *)pub->info; |
---|
10769 | 13223 | |
---|
.. | .. |
---|
10771 | 13225 | dhd_os_wd_timer(bus, WATCHDOG_EXTEND_INTERVAL); |
---|
10772 | 13226 | else |
---|
10773 | 13227 | dhd_os_wd_timer(bus, dhd->default_wd_interval); |
---|
10774 | | -#endif /* !BCMDBUS */ |
---|
10775 | 13228 | } |
---|
10776 | | - |
---|
10777 | 13229 | |
---|
10778 | 13230 | void |
---|
10779 | 13231 | dhd_os_wd_timer(void *bus, uint wdtick) |
---|
10780 | 13232 | { |
---|
10781 | | -#ifndef BCMDBUS |
---|
10782 | 13233 | dhd_pub_t *pub = bus; |
---|
10783 | 13234 | dhd_info_t *dhd = (dhd_info_t *)pub->info; |
---|
10784 | 13235 | unsigned long flags; |
---|
.. | .. |
---|
10795 | 13246 | /* don't start the wd until fw is loaded */ |
---|
10796 | 13247 | if (pub->busstate == DHD_BUS_DOWN) { |
---|
10797 | 13248 | DHD_GENERAL_UNLOCK(pub, flags); |
---|
| 13249 | +#ifdef BCMSDIO |
---|
| 13250 | + if (!wdtick) { |
---|
| 13251 | + DHD_OS_WD_WAKE_UNLOCK(pub); |
---|
| 13252 | + } |
---|
| 13253 | +#endif /* BCMSDIO */ |
---|
10798 | 13254 | return; |
---|
10799 | 13255 | } |
---|
10800 | 13256 | |
---|
.. | .. |
---|
10803 | 13259 | dhd->wd_timer_valid = FALSE; |
---|
10804 | 13260 | DHD_GENERAL_UNLOCK(pub, flags); |
---|
10805 | 13261 | del_timer_sync(&dhd->timer); |
---|
| 13262 | +#ifdef BCMSDIO |
---|
| 13263 | + DHD_OS_WD_WAKE_UNLOCK(pub); |
---|
| 13264 | +#endif /* BCMSDIO */ |
---|
10806 | 13265 | return; |
---|
10807 | 13266 | } |
---|
10808 | 13267 | |
---|
10809 | | - if (wdtick) { |
---|
| 13268 | + if (wdtick) { |
---|
| 13269 | +#ifdef BCMSDIO |
---|
| 13270 | + DHD_OS_WD_WAKE_LOCK(pub); |
---|
10810 | 13271 | dhd_watchdog_ms = (uint)wdtick; |
---|
| 13272 | +#endif /* BCMSDIO */ |
---|
10811 | 13273 | /* Re arm the timer, at last watchdog period */ |
---|
10812 | 13274 | mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms)); |
---|
10813 | 13275 | dhd->wd_timer_valid = TRUE; |
---|
10814 | 13276 | } |
---|
10815 | 13277 | DHD_GENERAL_UNLOCK(pub, flags); |
---|
10816 | | -#endif /* BCMDBUS */ |
---|
10817 | 13278 | } |
---|
10818 | 13279 | |
---|
| 13280 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 13281 | +void |
---|
| 13282 | +dhd_os_runtimepm_timer(void *bus, uint tick) |
---|
| 13283 | +{ |
---|
| 13284 | + dhd_pub_t *pub = bus; |
---|
| 13285 | + dhd_info_t *dhd = (dhd_info_t *)pub->info; |
---|
| 13286 | + unsigned long flags; |
---|
| 13287 | + |
---|
| 13288 | + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); |
---|
| 13289 | + |
---|
| 13290 | + if (!dhd) { |
---|
| 13291 | + DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); |
---|
| 13292 | + return; |
---|
| 13293 | + } |
---|
| 13294 | + |
---|
| 13295 | + DHD_GENERAL_LOCK(pub, flags); |
---|
| 13296 | + |
---|
| 13297 | + /* don't start the RPM until fw is loaded */ |
---|
| 13298 | + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(pub)) { |
---|
| 13299 | + DHD_GENERAL_UNLOCK(pub, flags); |
---|
| 13300 | + return; |
---|
| 13301 | + } |
---|
| 13302 | + |
---|
| 13303 | + /* If tick is non-zero, the request is to start the timer */ |
---|
| 13304 | + if (tick) { |
---|
| 13305 | + /* Start the timer only if its not already running */ |
---|
| 13306 | + if (dhd->rpm_timer_valid == FALSE) { |
---|
| 13307 | + mod_timer(&dhd->rpm_timer, jiffies + msecs_to_jiffies(dhd_runtimepm_ms)); |
---|
| 13308 | + dhd->rpm_timer_valid = TRUE; |
---|
| 13309 | + DHD_ERROR(("DHD Runtime PM Enabled \n")); |
---|
| 13310 | + } |
---|
| 13311 | + } else { |
---|
| 13312 | + /* tick is zero, we have to stop the timer */ |
---|
| 13313 | + /* Stop the timer only if its running, otherwise we don't have to do anything */ |
---|
| 13314 | + if (dhd->rpm_timer_valid == TRUE) { |
---|
| 13315 | + dhd->rpm_timer_valid = FALSE; |
---|
| 13316 | + DHD_GENERAL_UNLOCK(pub, flags); |
---|
| 13317 | + del_timer_sync(&dhd->rpm_timer); |
---|
| 13318 | + DHD_ERROR(("DHD Runtime PM Disabled \n")); |
---|
| 13319 | + /* we have already released the lock, so just go to exit */ |
---|
| 13320 | + goto exit; |
---|
| 13321 | + } |
---|
| 13322 | + } |
---|
| 13323 | + |
---|
| 13324 | + DHD_GENERAL_UNLOCK(pub, flags); |
---|
| 13325 | +exit: |
---|
| 13326 | + return; |
---|
| 13327 | + |
---|
| 13328 | +} |
---|
| 13329 | + |
---|
| 13330 | +#endif /* DHD_PCIE_RUNTIMEPM */ |
---|
| 13331 | + |
---|
10819 | 13332 | void * |
---|
10820 | | -dhd_os_open_image(char *filename) |
---|
| 13333 | +dhd_os_open_image1(dhd_pub_t *pub, char *filename) |
---|
10821 | 13334 | { |
---|
10822 | 13335 | struct file *fp; |
---|
| 13336 | + int size; |
---|
10823 | 13337 | |
---|
10824 | 13338 | fp = filp_open(filename, O_RDONLY, 0); |
---|
10825 | 13339 | /* |
---|
.. | .. |
---|
10828 | 13342 | * fp = open_namei(AT_FDCWD, filename, O_RD, 0); |
---|
10829 | 13343 | * ??? |
---|
10830 | 13344 | */ |
---|
10831 | | - if (IS_ERR(fp)) |
---|
| 13345 | + if (IS_ERR(fp)) { |
---|
10832 | 13346 | fp = NULL; |
---|
| 13347 | + goto err; |
---|
| 13348 | + } |
---|
10833 | 13349 | |
---|
| 13350 | + if (!S_ISREG(file_inode(fp)->i_mode)) { |
---|
| 13351 | + DHD_ERROR(("%s: %s is not regular file\n", __FUNCTION__, filename)); |
---|
| 13352 | + fp = NULL; |
---|
| 13353 | + goto err; |
---|
| 13354 | + } |
---|
| 13355 | + |
---|
| 13356 | + size = i_size_read(file_inode(fp)); |
---|
| 13357 | + if (size <= 0) { |
---|
| 13358 | + DHD_ERROR(("%s: %s file size invalid %d\n", __FUNCTION__, filename, size)); |
---|
| 13359 | + fp = NULL; |
---|
| 13360 | + goto err; |
---|
| 13361 | + } |
---|
| 13362 | + |
---|
| 13363 | + DHD_ERROR(("%s: %s (%d bytes) open success\n", __FUNCTION__, filename, size)); |
---|
| 13364 | + |
---|
| 13365 | +err: |
---|
10834 | 13366 | return fp; |
---|
10835 | 13367 | } |
---|
10836 | 13368 | |
---|
.. | .. |
---|
10839 | 13371 | { |
---|
10840 | 13372 | struct file *fp = (struct file *)image; |
---|
10841 | 13373 | int rdlen; |
---|
10842 | | - loff_t pos; |
---|
| 13374 | + int size; |
---|
10843 | 13375 | |
---|
10844 | | - if (!image) |
---|
| 13376 | + if (!image) { |
---|
10845 | 13377 | return 0; |
---|
| 13378 | + } |
---|
10846 | 13379 | |
---|
10847 | | - pos = fp->f_pos; |
---|
10848 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) |
---|
10849 | | - rdlen = kernel_read(fp, (void *) buf, (size_t) len, (loff_t *) &pos); |
---|
10850 | | -#else |
---|
10851 | | - rdlen = kernel_read(fp, pos, buf, len); |
---|
10852 | | -#endif |
---|
10853 | | - if (rdlen > 0) |
---|
| 13380 | + size = i_size_read(file_inode(fp)); |
---|
| 13381 | + rdlen = compat_kernel_read(fp, fp->f_pos, buf, MIN(len, size)); |
---|
| 13382 | + |
---|
| 13383 | + if (len >= size && size != rdlen) { |
---|
| 13384 | + return -EIO; |
---|
| 13385 | + } |
---|
| 13386 | + |
---|
| 13387 | + if (rdlen > 0) { |
---|
10854 | 13388 | fp->f_pos += rdlen; |
---|
| 13389 | + } |
---|
10855 | 13390 | |
---|
10856 | 13391 | return rdlen; |
---|
10857 | 13392 | } |
---|
10858 | 13393 | |
---|
10859 | | -void |
---|
10860 | | -dhd_os_close_image(void *image) |
---|
| 13394 | +#if defined(BT_OVER_SDIO) |
---|
| 13395 | +int |
---|
| 13396 | +dhd_os_gets_image(dhd_pub_t *pub, char *str, int len, void *image) |
---|
10861 | 13397 | { |
---|
10862 | | - if (image) |
---|
| 13398 | + struct file *fp = (struct file *)image; |
---|
| 13399 | + int rd_len; |
---|
| 13400 | + uint str_len = 0; |
---|
| 13401 | + char *str_end = NULL; |
---|
| 13402 | + |
---|
| 13403 | + if (!image) |
---|
| 13404 | + return 0; |
---|
| 13405 | + |
---|
| 13406 | + rd_len = compat_kernel_read(fp, fp->f_pos, str, len); |
---|
| 13407 | + str_end = strnchr(str, len, '\n'); |
---|
| 13408 | + if (str_end == NULL) { |
---|
| 13409 | + goto err; |
---|
| 13410 | + } |
---|
| 13411 | + str_len = (uint)(str_end - str); |
---|
| 13412 | + |
---|
| 13413 | + /* Advance file pointer past the string length */ |
---|
| 13414 | + fp->f_pos += str_len + 1; |
---|
| 13415 | + bzero(str_end, rd_len - str_len); |
---|
| 13416 | + |
---|
| 13417 | +err: |
---|
| 13418 | + return str_len; |
---|
| 13419 | +} |
---|
| 13420 | +#endif /* defined (BT_OVER_SDIO) */ |
---|
| 13421 | + |
---|
| 13422 | +int |
---|
| 13423 | +dhd_os_get_image_size(void *image) |
---|
| 13424 | +{ |
---|
| 13425 | + struct file *fp = (struct file *)image; |
---|
| 13426 | + int size; |
---|
| 13427 | + if (!image) { |
---|
| 13428 | + return 0; |
---|
| 13429 | + } |
---|
| 13430 | + |
---|
| 13431 | + size = i_size_read(file_inode(fp)); |
---|
| 13432 | + |
---|
| 13433 | + return size; |
---|
| 13434 | +} |
---|
| 13435 | + |
---|
| 13436 | +void |
---|
| 13437 | +dhd_os_close_image1(dhd_pub_t *pub, void *image) |
---|
| 13438 | +{ |
---|
| 13439 | + if (image) { |
---|
10863 | 13440 | filp_close((struct file *)image, NULL); |
---|
| 13441 | + } |
---|
10864 | 13442 | } |
---|
10865 | 13443 | |
---|
10866 | 13444 | void |
---|
.. | .. |
---|
10870 | 13448 | |
---|
10871 | 13449 | dhd = (dhd_info_t *)(pub->info); |
---|
10872 | 13450 | |
---|
10873 | | -#ifndef BCMDBUS |
---|
10874 | 13451 | if (dhd_dpc_prio >= 0) |
---|
10875 | 13452 | down(&dhd->sdsem); |
---|
10876 | 13453 | else |
---|
10877 | 13454 | spin_lock_bh(&dhd->sdlock); |
---|
10878 | | -#else |
---|
10879 | | - spin_lock_bh(&dhd->sdlock); |
---|
10880 | | -#endif /* BCMDBUS */ |
---|
10881 | 13455 | } |
---|
10882 | 13456 | |
---|
10883 | 13457 | void |
---|
.. | .. |
---|
10887 | 13461 | |
---|
10888 | 13462 | dhd = (dhd_info_t *)(pub->info); |
---|
10889 | 13463 | |
---|
10890 | | -#ifndef BCMDBUS |
---|
10891 | 13464 | if (dhd_dpc_prio >= 0) |
---|
10892 | 13465 | up(&dhd->sdsem); |
---|
10893 | 13466 | else |
---|
10894 | 13467 | spin_unlock_bh(&dhd->sdlock); |
---|
10895 | | -#else |
---|
10896 | | - spin_unlock_bh(&dhd->sdlock); |
---|
10897 | | -#endif /* BCMDBUS */ |
---|
10898 | 13468 | } |
---|
10899 | 13469 | |
---|
10900 | 13470 | void |
---|
.. | .. |
---|
10903 | 13473 | dhd_info_t *dhd; |
---|
10904 | 13474 | |
---|
10905 | 13475 | dhd = (dhd_info_t *)(pub->info); |
---|
10906 | | -#ifdef BCMDBUS |
---|
10907 | | - spin_lock_irqsave(&dhd->txqlock, dhd->txqlock_flags); |
---|
10908 | | -#else |
---|
10909 | 13476 | spin_lock_bh(&dhd->txqlock); |
---|
10910 | | -#endif |
---|
10911 | 13477 | } |
---|
10912 | 13478 | |
---|
10913 | 13479 | void |
---|
.. | .. |
---|
10916 | 13482 | dhd_info_t *dhd; |
---|
10917 | 13483 | |
---|
10918 | 13484 | dhd = (dhd_info_t *)(pub->info); |
---|
10919 | | -#ifdef BCMDBUS |
---|
10920 | | - spin_unlock_irqrestore(&dhd->txqlock, dhd->txqlock_flags); |
---|
10921 | | -#else |
---|
10922 | 13485 | spin_unlock_bh(&dhd->txqlock); |
---|
10923 | | -#endif |
---|
10924 | 13486 | } |
---|
10925 | 13487 | |
---|
10926 | 13488 | void |
---|
.. | .. |
---|
11030 | 13592 | #endif /* defined(WL_WIRELESS_EXT) */ |
---|
11031 | 13593 | |
---|
11032 | 13594 | static int |
---|
11033 | | -dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, uint16 pktlen, |
---|
| 13595 | +dhd_wl_host_event(dhd_info_t *dhd, int ifidx, void *pktdata, uint16 pktlen, |
---|
11034 | 13596 | wl_event_msg_t *event, void **data) |
---|
11035 | 13597 | { |
---|
11036 | 13598 | int bcmerror = 0; |
---|
.. | .. |
---|
11040 | 13602 | ASSERT(dhd != NULL); |
---|
11041 | 13603 | |
---|
11042 | 13604 | #ifdef SHOW_LOGTRACE |
---|
11043 | | - bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, pktlen, event, data, |
---|
11044 | | - &dhd->event_data); |
---|
| 13605 | + bcmerror = wl_process_host_event(&dhd->pub, &ifidx, pktdata, pktlen, event, data, |
---|
| 13606 | + &dhd->event_data); |
---|
11045 | 13607 | #else |
---|
11046 | | - bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, pktlen, event, data, |
---|
11047 | | - NULL); |
---|
| 13608 | + bcmerror = wl_process_host_event(&dhd->pub, &ifidx, pktdata, pktlen, event, data, |
---|
| 13609 | + NULL); |
---|
11048 | 13610 | #endif /* SHOW_LOGTRACE */ |
---|
| 13611 | + if (unlikely(bcmerror != BCME_OK)) { |
---|
| 13612 | + return bcmerror; |
---|
| 13613 | + } |
---|
11049 | 13614 | |
---|
11050 | | - if (bcmerror != BCME_OK) |
---|
11051 | | - return (bcmerror); |
---|
| 13615 | + if (ntoh32(event->event_type) == WLC_E_IF) { |
---|
| 13616 | + /* WLC_E_IF event types are consumed by wl_process_host_event. |
---|
| 13617 | + * For ifadd/del ops, the netdev ptr may not be valid at this |
---|
| 13618 | + * point. so return before invoking cfg80211/wext handlers. |
---|
| 13619 | + */ |
---|
| 13620 | + return BCME_OK; |
---|
| 13621 | + } |
---|
11052 | 13622 | |
---|
11053 | 13623 | #if defined(WL_WIRELESS_EXT) |
---|
11054 | 13624 | if (event->bsscfgidx == 0) { |
---|
11055 | 13625 | /* |
---|
11056 | 13626 | * Wireless ext is on primary interface only |
---|
11057 | 13627 | */ |
---|
| 13628 | + ASSERT(dhd->iflist[ifidx] != NULL); |
---|
| 13629 | + ASSERT(dhd->iflist[ifidx]->net != NULL); |
---|
11058 | 13630 | |
---|
11059 | | - ASSERT(dhd->iflist[*ifidx] != NULL); |
---|
11060 | | - ASSERT(dhd->iflist[*ifidx]->net != NULL); |
---|
11061 | | - |
---|
11062 | | - if (dhd->iflist[*ifidx]->net) { |
---|
11063 | | - wl_iw_event(dhd->iflist[*ifidx]->net, event, *data); |
---|
| 13631 | + if (dhd->iflist[ifidx]->net) { |
---|
| 13632 | + wl_iw_event(dhd->iflist[ifidx]->net, event, *data); |
---|
11064 | 13633 | } |
---|
11065 | 13634 | } |
---|
11066 | 13635 | #endif /* defined(WL_WIRELESS_EXT) */ |
---|
11067 | 13636 | |
---|
11068 | 13637 | #ifdef WL_CFG80211 |
---|
11069 | | - ASSERT(dhd->iflist[*ifidx] != NULL); |
---|
11070 | | - ASSERT(dhd->iflist[*ifidx]->net != NULL); |
---|
11071 | | - if (dhd->iflist[*ifidx]->net) { |
---|
| 13638 | + if (dhd->iflist[ifidx]->net) { |
---|
11072 | 13639 | spin_lock_irqsave(&dhd->pub.up_lock, flags); |
---|
11073 | 13640 | if (dhd->pub.up) { |
---|
11074 | | - wl_cfg80211_event(dhd->iflist[*ifidx]->net, event, *data); |
---|
| 13641 | + wl_cfg80211_event(dhd->iflist[ifidx]->net, event, *data); |
---|
11075 | 13642 | } |
---|
11076 | 13643 | spin_unlock_irqrestore(&dhd->pub.up_lock, flags); |
---|
11077 | 13644 | } |
---|
.. | .. |
---|
11085 | 13652 | dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data) |
---|
11086 | 13653 | { |
---|
11087 | 13654 | switch (ntoh32(event->event_type)) { |
---|
11088 | | - |
---|
| 13655 | + /* Handle error case or further events here */ |
---|
11089 | 13656 | default: |
---|
11090 | 13657 | break; |
---|
11091 | 13658 | } |
---|
.. | .. |
---|
11143 | 13710 | } else { |
---|
11144 | 13711 | netif_rx_ni(skb); |
---|
11145 | 13712 | } |
---|
11146 | | - } |
---|
11147 | | - else { |
---|
| 13713 | + } else { |
---|
11148 | 13714 | /* Could not allocate a sk_buf */ |
---|
11149 | 13715 | DHD_ERROR(("%s: unable to alloc sk_buf", __FUNCTION__)); |
---|
11150 | 13716 | } |
---|
.. | .. |
---|
11153 | 13719 | |
---|
11154 | 13720 | void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar) |
---|
11155 | 13721 | { |
---|
11156 | | -#if defined(BCMSDIO) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) |
---|
| 13722 | +#if defined(BCMSDIO) |
---|
11157 | 13723 | struct dhd_info *dhdinfo = dhd->info; |
---|
11158 | 13724 | |
---|
11159 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) |
---|
11160 | 13725 | int timeout = msecs_to_jiffies(IOCTL_RESP_TIMEOUT); |
---|
11161 | | -#else |
---|
11162 | | - int timeout = (IOCTL_RESP_TIMEOUT / 1000) * HZ; |
---|
11163 | | -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ |
---|
11164 | 13726 | |
---|
11165 | 13727 | dhd_os_sdunlock(dhd); |
---|
11166 | 13728 | wait_event_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), timeout); |
---|
11167 | 13729 | dhd_os_sdlock(dhd); |
---|
11168 | | -#endif /* defined(BCMSDIO) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */ |
---|
| 13730 | +#endif /* defined(BCMSDIO) */ |
---|
11169 | 13731 | return; |
---|
11170 | | -} |
---|
| 13732 | +} /* dhd_init_static_strs_array */ |
---|
11171 | 13733 | |
---|
11172 | 13734 | void dhd_wait_event_wakeup(dhd_pub_t *dhd) |
---|
11173 | 13735 | { |
---|
11174 | | -#if defined(BCMSDIO) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) |
---|
| 13736 | +#if defined(BCMSDIO) |
---|
11175 | 13737 | struct dhd_info *dhdinfo = dhd->info; |
---|
11176 | 13738 | if (waitqueue_active(&dhdinfo->ctrl_wait)) |
---|
11177 | 13739 | wake_up(&dhdinfo->ctrl_wait); |
---|
11178 | | -#endif |
---|
| 13740 | +#endif // endif |
---|
11179 | 13741 | return; |
---|
11180 | 13742 | } |
---|
11181 | 13743 | |
---|
.. | .. |
---|
11186 | 13748 | int ret; |
---|
11187 | 13749 | |
---|
11188 | 13750 | dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 13751 | + |
---|
| 13752 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 13753 | + if (pm_runtime_get_sync(dhd_bus_to_dev(dhd->pub.bus)) < 0) |
---|
| 13754 | + return BCME_ERROR; |
---|
| 13755 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
11189 | 13756 | |
---|
11190 | 13757 | if (flag == TRUE) { |
---|
11191 | 13758 | /* Issue wl down command before resetting the chip */ |
---|
.. | .. |
---|
11201 | 13768 | if (dhd->pub.pno_state) { |
---|
11202 | 13769 | dhd_pno_deinit(&dhd->pub); |
---|
11203 | 13770 | } |
---|
11204 | | -#endif |
---|
| 13771 | +#endif // endif |
---|
11205 | 13772 | #ifdef RTT_SUPPORT |
---|
11206 | 13773 | if (dhd->pub.rtt_state) { |
---|
11207 | 13774 | dhd_rtt_deinit(&dhd->pub); |
---|
11208 | 13775 | } |
---|
11209 | 13776 | #endif /* RTT_SUPPORT */ |
---|
| 13777 | + |
---|
| 13778 | +#if defined(DBG_PKT_MON) && !defined(DBG_PKT_MON_INIT_DEFAULT) |
---|
| 13779 | + dhd_os_dbg_detach_pkt_monitor(&dhd->pub); |
---|
| 13780 | +#endif /* DBG_PKT_MON */ |
---|
11210 | 13781 | } |
---|
11211 | 13782 | |
---|
11212 | 13783 | #ifdef BCMSDIO |
---|
.. | .. |
---|
11219 | 13790 | #endif /* BCMSDIO */ |
---|
11220 | 13791 | |
---|
11221 | 13792 | ret = dhd_bus_devreset(&dhd->pub, flag); |
---|
| 13793 | + |
---|
| 13794 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 13795 | + pm_runtime_mark_last_busy(dhd_bus_to_dev(dhd->pub.bus)); |
---|
| 13796 | + pm_runtime_put_autosuspend(dhd_bus_to_dev(dhd->pub.bus)); |
---|
| 13797 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
| 13798 | + |
---|
| 13799 | + if (flag) { |
---|
| 13800 | + /* Clear some flags for recovery logic */ |
---|
| 13801 | + dhd->pub.dongle_trap_occured = 0; |
---|
| 13802 | + dhd->pub.iovar_timeout_occured = 0; |
---|
| 13803 | +#ifdef PCIE_FULL_DONGLE |
---|
| 13804 | + dhd->pub.d3ack_timeout_occured = 0; |
---|
| 13805 | + dhd->pub.livelock_occured = 0; |
---|
| 13806 | + dhd->pub.pktid_audit_failed = 0; |
---|
| 13807 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 13808 | + dhd->pub.iface_op_failed = 0; |
---|
| 13809 | + dhd->pub.scan_timeout_occurred = 0; |
---|
| 13810 | + dhd->pub.scan_busy_occurred = 0; |
---|
| 13811 | + dhd->pub.smmu_fault_occurred = 0; |
---|
| 13812 | + } |
---|
| 13813 | + |
---|
11222 | 13814 | if (ret) { |
---|
11223 | 13815 | DHD_ERROR(("%s: dhd_bus_devreset: %d\n", __FUNCTION__, ret)); |
---|
11224 | | - return ret; |
---|
11225 | 13816 | } |
---|
11226 | 13817 | |
---|
11227 | 13818 | return ret; |
---|
.. | .. |
---|
11269 | 13860 | ret = dhd_set_suspend(val, &dhd->pub); |
---|
11270 | 13861 | #else |
---|
11271 | 13862 | ret = dhd_suspend_resume_helper(dhd, val, force); |
---|
11272 | | -#endif |
---|
| 13863 | +#endif // endif |
---|
11273 | 13864 | #ifdef WL_CFG80211 |
---|
11274 | 13865 | wl_cfg80211_update_power_mode(dev); |
---|
11275 | | -#endif |
---|
| 13866 | +#endif // endif |
---|
11276 | 13867 | } |
---|
11277 | 13868 | return ret; |
---|
11278 | 13869 | } |
---|
.. | .. |
---|
11281 | 13872 | { |
---|
11282 | 13873 | dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
11283 | 13874 | |
---|
11284 | | - if (dhd) |
---|
| 13875 | + if (dhd) { |
---|
| 13876 | + DHD_ERROR(("%s: Set bcn_li_dtim in suspend %d\n", |
---|
| 13877 | + __FUNCTION__, val)); |
---|
11285 | 13878 | dhd->pub.suspend_bcn_li_dtim = val; |
---|
| 13879 | + } |
---|
11286 | 13880 | |
---|
11287 | 13881 | return 0; |
---|
11288 | 13882 | } |
---|
11289 | 13883 | |
---|
| 13884 | +int net_os_set_max_dtim_enable(struct net_device *dev, int val) |
---|
| 13885 | +{ |
---|
| 13886 | + dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 13887 | + |
---|
| 13888 | + if (dhd) { |
---|
| 13889 | + DHD_ERROR(("%s: use MAX bcn_li_dtim in suspend %s\n", |
---|
| 13890 | + __FUNCTION__, (val ? "Enable" : "Disable"))); |
---|
| 13891 | + if (val) { |
---|
| 13892 | + dhd->pub.max_dtim_enable = TRUE; |
---|
| 13893 | + } else { |
---|
| 13894 | + dhd->pub.max_dtim_enable = FALSE; |
---|
| 13895 | + } |
---|
| 13896 | + } else { |
---|
| 13897 | + return -1; |
---|
| 13898 | + } |
---|
| 13899 | + |
---|
| 13900 | + return 0; |
---|
| 13901 | +} |
---|
| 13902 | + |
---|
| 13903 | +#ifdef DISABLE_DTIM_IN_SUSPEND |
---|
| 13904 | +int net_os_set_disable_dtim_in_suspend(struct net_device *dev, int val) |
---|
| 13905 | +{ |
---|
| 13906 | + dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 13907 | + |
---|
| 13908 | + if (dhd) { |
---|
| 13909 | + DHD_ERROR(("%s: Disable bcn_li_dtim in suspend %s\n", |
---|
| 13910 | + __FUNCTION__, (val ? "Enable" : "Disable"))); |
---|
| 13911 | + if (val) { |
---|
| 13912 | + dhd->pub.disable_dtim_in_suspend = TRUE; |
---|
| 13913 | + } else { |
---|
| 13914 | + dhd->pub.disable_dtim_in_suspend = FALSE; |
---|
| 13915 | + } |
---|
| 13916 | + } else { |
---|
| 13917 | + return -1; |
---|
| 13918 | + } |
---|
| 13919 | + |
---|
| 13920 | + return 0; |
---|
| 13921 | +} |
---|
| 13922 | +#endif /* DISABLE_DTIM_IN_SUSPEND */ |
---|
| 13923 | + |
---|
11290 | 13924 | #ifdef PKT_FILTER_SUPPORT |
---|
11291 | 13925 | int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) |
---|
11292 | 13926 | { |
---|
11293 | | - dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
11294 | | - char *filterp = NULL; |
---|
11295 | | - int filter_id = 0; |
---|
11296 | 13927 | int ret = 0; |
---|
11297 | 13928 | |
---|
11298 | | - if (!dhd || (num == DHD_UNICAST_FILTER_NUM) || |
---|
11299 | | - (num == DHD_MDNS_FILTER_NUM)) |
---|
11300 | | - return ret; |
---|
11301 | | - if (num >= dhd->pub.pktfilter_count) |
---|
11302 | | - return -EINVAL; |
---|
11303 | | - switch (num) { |
---|
11304 | | - case DHD_BROADCAST_FILTER_NUM: |
---|
11305 | | - filterp = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF"; |
---|
11306 | | - filter_id = 101; |
---|
11307 | | - break; |
---|
11308 | | - case DHD_MULTICAST4_FILTER_NUM: |
---|
11309 | | - filterp = "102 0 0 0 0xFFFFFF 0x01005E"; |
---|
11310 | | - filter_id = 102; |
---|
11311 | | - break; |
---|
11312 | | - case DHD_MULTICAST6_FILTER_NUM: |
---|
11313 | | - filterp = "103 0 0 0 0xFFFF 0x3333"; |
---|
11314 | | - filter_id = 103; |
---|
11315 | | - break; |
---|
11316 | | - default: |
---|
11317 | | - return -EINVAL; |
---|
| 13929 | +#ifndef GAN_LITE_NAT_KEEPALIVE_FILTER |
---|
| 13930 | + dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 13931 | + |
---|
| 13932 | + DHD_ERROR(("%s: add_remove = %d, num = %d\n", __FUNCTION__, add_remove, num)); |
---|
| 13933 | + if (!dhd || (num == DHD_UNICAST_FILTER_NUM)) { |
---|
| 13934 | + return 0; |
---|
11318 | 13935 | } |
---|
11319 | 13936 | |
---|
11320 | | - /* Add filter */ |
---|
11321 | | - if (add_remove) { |
---|
11322 | | - dhd->pub.pktfilter[num] = filterp; |
---|
11323 | | - dhd_pktfilter_offload_set(&dhd->pub, dhd->pub.pktfilter[num]); |
---|
11324 | | - } else { /* Delete filter */ |
---|
11325 | | - if (dhd->pub.pktfilter[num] != NULL) { |
---|
11326 | | - dhd_pktfilter_offload_delete(&dhd->pub, filter_id); |
---|
11327 | | - dhd->pub.pktfilter[num] = NULL; |
---|
11328 | | - } |
---|
| 13937 | +#ifdef BLOCK_IPV6_PACKET |
---|
| 13938 | + /* customer want to use NO IPV6 packets only */ |
---|
| 13939 | + if (num == DHD_MULTICAST6_FILTER_NUM) { |
---|
| 13940 | + return 0; |
---|
11329 | 13941 | } |
---|
| 13942 | +#endif /* BLOCK_IPV6_PACKET */ |
---|
| 13943 | + |
---|
| 13944 | + if (num >= dhd->pub.pktfilter_count) { |
---|
| 13945 | + return -EINVAL; |
---|
| 13946 | + } |
---|
| 13947 | + |
---|
| 13948 | + ret = dhd_packet_filter_add_remove(&dhd->pub, add_remove, num); |
---|
| 13949 | +#endif /* !GAN_LITE_NAT_KEEPALIVE_FILTER */ |
---|
| 13950 | + |
---|
11330 | 13951 | return ret; |
---|
11331 | 13952 | } |
---|
11332 | 13953 | |
---|
.. | .. |
---|
11354 | 13975 | { |
---|
11355 | 13976 | dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
11356 | 13977 | |
---|
| 13978 | + DHD_ERROR(("%s: val = %d\n", __FUNCTION__, val)); |
---|
11357 | 13979 | return dhd_os_enable_packet_filter(&dhd->pub, val); |
---|
11358 | 13980 | } |
---|
11359 | 13981 | #endif /* PKT_FILTER_SUPPORT */ |
---|
.. | .. |
---|
11378 | 14000 | dhd_pub_t *dhd = (&ptr->pub); |
---|
11379 | 14001 | int feature_set = 0; |
---|
11380 | 14002 | |
---|
11381 | | -#ifdef DYNAMIC_SWOOB_DURATION |
---|
11382 | | -#ifndef CUSTOM_INTR_WIDTH |
---|
11383 | | -#define CUSTOM_INTR_WIDTH 100 |
---|
11384 | | - int intr_width = 0; |
---|
11385 | | -#endif /* CUSTOM_INTR_WIDTH */ |
---|
11386 | | -#endif /* DYNAMIC_SWOOB_DURATION */ |
---|
11387 | | - if (!dhd) |
---|
11388 | | - return feature_set; |
---|
11389 | | - |
---|
11390 | | - if (FW_SUPPORTED(dhd, sta)) |
---|
| 14003 | + if (FW_SUPPORTED(dhd, sta)) { |
---|
| 14004 | +#if defined(OEM_ANDROID) |
---|
| 14005 | + feature_set |= WIFI_FEATURE_SET_LATENCY_MODE; |
---|
| 14006 | + feature_set |= WIFI_FEATURE_SET_TX_POWER_LIMIT; |
---|
| 14007 | +#endif /* OEM_ANDROID */ |
---|
11391 | 14008 | feature_set |= WIFI_FEATURE_INFRA; |
---|
| 14009 | + } |
---|
11392 | 14010 | if (FW_SUPPORTED(dhd, dualband)) |
---|
11393 | 14011 | feature_set |= WIFI_FEATURE_INFRA_5G; |
---|
11394 | | - if (FW_SUPPORTED(dhd, p2p)) |
---|
| 14012 | + if (FW_SUPPORTED(dhd, p2p)) { |
---|
11395 | 14013 | feature_set |= WIFI_FEATURE_P2P; |
---|
| 14014 | +#if defined(OEM_ANDROID) |
---|
| 14015 | + feature_set |= WIFI_FEATURE_P2P_RAND_MAC; |
---|
| 14016 | +#endif /* OEM_ANDROID */ |
---|
| 14017 | + } |
---|
11396 | 14018 | if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) |
---|
11397 | 14019 | feature_set |= WIFI_FEATURE_SOFT_AP; |
---|
11398 | 14020 | if (FW_SUPPORTED(dhd, tdls)) |
---|
.. | .. |
---|
11406 | 14028 | feature_set |= WIFI_FEATURE_D2D_RTT; |
---|
11407 | 14029 | } |
---|
11408 | 14030 | #ifdef RTT_SUPPORT |
---|
| 14031 | + feature_set |= WIFI_FEATURE_D2D_RTT; |
---|
11409 | 14032 | feature_set |= WIFI_FEATURE_D2AP_RTT; |
---|
11410 | 14033 | #endif /* RTT_SUPPORT */ |
---|
11411 | 14034 | #ifdef LINKSTAT_SUPPORT |
---|
11412 | 14035 | feature_set |= WIFI_FEATURE_LINKSTAT; |
---|
11413 | 14036 | #endif /* LINKSTAT_SUPPORT */ |
---|
11414 | | - /* Supports STA + STA always */ |
---|
11415 | | - feature_set |= WIFI_FEATURE_ADDITIONAL_STA; |
---|
11416 | | -#ifdef PNO_SUPPORT |
---|
| 14037 | + |
---|
| 14038 | +#if defined(PNO_SUPPORT) && !defined(DISABLE_ANDROID_PNO) |
---|
11417 | 14039 | if (dhd_is_pno_supported(dhd)) { |
---|
11418 | 14040 | feature_set |= WIFI_FEATURE_PNO; |
---|
11419 | | - feature_set |= WIFI_FEATURE_BATCH_SCAN; |
---|
11420 | 14041 | #ifdef GSCAN_SUPPORT |
---|
11421 | 14042 | feature_set |= WIFI_FEATURE_GSCAN; |
---|
| 14043 | + feature_set |= WIFI_FEATURE_HAL_EPNO; |
---|
11422 | 14044 | #endif /* GSCAN_SUPPORT */ |
---|
11423 | 14045 | } |
---|
| 14046 | +#endif /* PNO_SUPPORT && !DISABLE_ANDROID_PNO */ |
---|
| 14047 | +#ifdef RSSI_MONITOR_SUPPORT |
---|
11424 | 14048 | if (FW_SUPPORTED(dhd, rssi_mon)) { |
---|
11425 | 14049 | feature_set |= WIFI_FEATURE_RSSI_MONITOR; |
---|
11426 | 14050 | } |
---|
11427 | | -#endif /* PNO_SUPPORT */ |
---|
| 14051 | +#endif /* RSSI_MONITOR_SUPPORT */ |
---|
11428 | 14052 | #ifdef WL11U |
---|
11429 | 14053 | feature_set |= WIFI_FEATURE_HOTSPOT; |
---|
11430 | 14054 | #endif /* WL11U */ |
---|
| 14055 | +#ifdef NDO_CONFIG_SUPPORT |
---|
| 14056 | + if (FW_SUPPORTED(dhd, ndoe)) |
---|
| 14057 | + feature_set |= WIFI_FEATURE_CONFIG_NDO; |
---|
| 14058 | +#endif /* NDO_CONFIG_SUPPORT */ |
---|
| 14059 | +#ifdef KEEP_ALIVE |
---|
| 14060 | + feature_set |= WIFI_FEATURE_MKEEP_ALIVE; |
---|
| 14061 | +#endif /* KEEP_ALIVE */ |
---|
| 14062 | +#ifdef SUPPORT_RANDOM_MAC_SCAN |
---|
| 14063 | + feature_set |= WIFI_FEATURE_SCAN_RAND; |
---|
| 14064 | +#endif /* SUPPORT_RANDOM_MAC_SCAN */ |
---|
| 14065 | +#ifdef FILTER_IE |
---|
| 14066 | + if (FW_SUPPORTED(dhd, fie)) { |
---|
| 14067 | + feature_set |= WIFI_FEATURE_FILTER_IE; |
---|
| 14068 | + } |
---|
| 14069 | +#endif /* FILTER_IE */ |
---|
| 14070 | +#ifdef ROAMEXP_SUPPORT |
---|
| 14071 | + /* Check if the Android O roam feature is supported by FW */ |
---|
| 14072 | + if (!(BCME_UNSUPPORTED == dhd_dev_set_whitelist_ssid(dev, NULL, 0, true))) { |
---|
| 14073 | + feature_set |= WIFI_FEATURE_CONTROL_ROAMING; |
---|
| 14074 | + } |
---|
| 14075 | +#endif /* ROAMEXP_SUPPORT */ |
---|
11431 | 14076 | return feature_set; |
---|
11432 | 14077 | } |
---|
11433 | 14078 | |
---|
11434 | | -int *dhd_dev_get_feature_set_matrix(struct net_device *dev, int *num) |
---|
| 14079 | +int |
---|
| 14080 | +dhd_dev_get_feature_set_matrix(struct net_device *dev, int num) |
---|
11435 | 14081 | { |
---|
11436 | | - int feature_set_full, mem_needed; |
---|
11437 | | - int *ret; |
---|
11438 | | - |
---|
11439 | | - *num = 0; |
---|
11440 | | - mem_needed = sizeof(int) * MAX_FEATURE_SET_CONCURRRENT_GROUPS; |
---|
11441 | | - ret = (int *) kmalloc(mem_needed, GFP_KERNEL); |
---|
11442 | | - if (!ret) { |
---|
11443 | | - DHD_ERROR(("%s: failed to allocate %d bytes\n", __FUNCTION__, |
---|
11444 | | - mem_needed)); |
---|
11445 | | - return ret; |
---|
11446 | | - } |
---|
| 14082 | + int feature_set_full; |
---|
| 14083 | + int ret = 0; |
---|
11447 | 14084 | |
---|
11448 | 14085 | feature_set_full = dhd_dev_get_feature_set(dev); |
---|
11449 | 14086 | |
---|
11450 | | - ret[0] = (feature_set_full & WIFI_FEATURE_INFRA) | |
---|
11451 | | - (feature_set_full & WIFI_FEATURE_INFRA_5G) | |
---|
11452 | | - (feature_set_full & WIFI_FEATURE_NAN) | |
---|
11453 | | - (feature_set_full & WIFI_FEATURE_D2D_RTT) | |
---|
11454 | | - (feature_set_full & WIFI_FEATURE_D2AP_RTT) | |
---|
11455 | | - (feature_set_full & WIFI_FEATURE_PNO) | |
---|
11456 | | - (feature_set_full & WIFI_FEATURE_HAL_EPNO) | |
---|
11457 | | - (feature_set_full & WIFI_FEATURE_RSSI_MONITOR) | |
---|
11458 | | - (feature_set_full & WIFI_FEATURE_BATCH_SCAN) | |
---|
11459 | | - (feature_set_full & WIFI_FEATURE_GSCAN) | |
---|
11460 | | - (feature_set_full & WIFI_FEATURE_HOTSPOT) | |
---|
11461 | | - (feature_set_full & WIFI_FEATURE_ADDITIONAL_STA) | |
---|
11462 | | - (feature_set_full & WIFI_FEATURE_EPR); |
---|
| 14087 | + /* Common feature set for all interface */ |
---|
| 14088 | + ret = (feature_set_full & WIFI_FEATURE_INFRA) | |
---|
| 14089 | + (feature_set_full & WIFI_FEATURE_INFRA_5G) | |
---|
| 14090 | + (feature_set_full & WIFI_FEATURE_D2D_RTT) | |
---|
| 14091 | + (feature_set_full & WIFI_FEATURE_D2AP_RTT) | |
---|
| 14092 | + (feature_set_full & WIFI_FEATURE_RSSI_MONITOR) | |
---|
| 14093 | + (feature_set_full & WIFI_FEATURE_EPR); |
---|
11463 | 14094 | |
---|
11464 | | - ret[1] = (feature_set_full & WIFI_FEATURE_INFRA) | |
---|
11465 | | - (feature_set_full & WIFI_FEATURE_INFRA_5G) | |
---|
11466 | | - (feature_set_full & WIFI_FEATURE_RSSI_MONITOR) | |
---|
11467 | | - /* Not yet verified NAN with P2P */ |
---|
11468 | | - /* (feature_set_full & WIFI_FEATURE_NAN) | */ |
---|
11469 | | - (feature_set_full & WIFI_FEATURE_P2P) | |
---|
11470 | | - (feature_set_full & WIFI_FEATURE_D2AP_RTT) | |
---|
11471 | | - (feature_set_full & WIFI_FEATURE_D2D_RTT) | |
---|
11472 | | - (feature_set_full & WIFI_FEATURE_EPR); |
---|
| 14095 | + /* Specific feature group for each interface */ |
---|
| 14096 | + switch (num) { |
---|
| 14097 | + case 0: |
---|
| 14098 | + ret |= (feature_set_full & WIFI_FEATURE_P2P) | |
---|
| 14099 | + /* Not supported yet */ |
---|
| 14100 | + /* (feature_set_full & WIFI_FEATURE_NAN) | */ |
---|
| 14101 | + (feature_set_full & WIFI_FEATURE_TDLS) | |
---|
| 14102 | + (feature_set_full & WIFI_FEATURE_PNO) | |
---|
| 14103 | + (feature_set_full & WIFI_FEATURE_HAL_EPNO) | |
---|
| 14104 | + (feature_set_full & WIFI_FEATURE_BATCH_SCAN) | |
---|
| 14105 | + (feature_set_full & WIFI_FEATURE_GSCAN) | |
---|
| 14106 | + (feature_set_full & WIFI_FEATURE_HOTSPOT) | |
---|
| 14107 | + (feature_set_full & WIFI_FEATURE_ADDITIONAL_STA); |
---|
| 14108 | + break; |
---|
11473 | 14109 | |
---|
11474 | | - ret[2] = (feature_set_full & WIFI_FEATURE_INFRA) | |
---|
11475 | | - (feature_set_full & WIFI_FEATURE_INFRA_5G) | |
---|
11476 | | - (feature_set_full & WIFI_FEATURE_RSSI_MONITOR) | |
---|
11477 | | - (feature_set_full & WIFI_FEATURE_NAN) | |
---|
11478 | | - (feature_set_full & WIFI_FEATURE_D2D_RTT) | |
---|
11479 | | - (feature_set_full & WIFI_FEATURE_D2AP_RTT) | |
---|
11480 | | - (feature_set_full & WIFI_FEATURE_TDLS) | |
---|
11481 | | - (feature_set_full & WIFI_FEATURE_TDLS_OFFCHANNEL) | |
---|
11482 | | - (feature_set_full & WIFI_FEATURE_EPR); |
---|
11483 | | - *num = MAX_FEATURE_SET_CONCURRRENT_GROUPS; |
---|
| 14110 | + case 1: |
---|
| 14111 | + ret |= (feature_set_full & WIFI_FEATURE_P2P); |
---|
| 14112 | + /* Not yet verified NAN with P2P */ |
---|
| 14113 | + /* (feature_set_full & WIFI_FEATURE_NAN) | */ |
---|
| 14114 | + break; |
---|
| 14115 | + |
---|
| 14116 | + case 2: |
---|
| 14117 | + ret |= (feature_set_full & WIFI_FEATURE_NAN) | |
---|
| 14118 | + (feature_set_full & WIFI_FEATURE_TDLS) | |
---|
| 14119 | + (feature_set_full & WIFI_FEATURE_TDLS_OFFCHANNEL); |
---|
| 14120 | + break; |
---|
| 14121 | + |
---|
| 14122 | + default: |
---|
| 14123 | + ret = WIFI_FEATURE_INVALID; |
---|
| 14124 | + DHD_ERROR(("%s: Out of index(%d) for get feature set\n", __FUNCTION__, num)); |
---|
| 14125 | + break; |
---|
| 14126 | + } |
---|
11484 | 14127 | |
---|
11485 | 14128 | return ret; |
---|
11486 | 14129 | } |
---|
.. | .. |
---|
11490 | 14133 | { |
---|
11491 | 14134 | dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
11492 | 14135 | |
---|
11493 | | - if (nodfs) |
---|
| 14136 | + if (nodfs) { |
---|
| 14137 | + if (dhd->pub.dhd_cflags & WLAN_PLAT_NODFS_FLAG) { |
---|
| 14138 | + return 0; |
---|
| 14139 | + } |
---|
11494 | 14140 | dhd->pub.dhd_cflags |= WLAN_PLAT_NODFS_FLAG; |
---|
11495 | | - else |
---|
| 14141 | + } else { |
---|
| 14142 | + if (!(dhd->pub.dhd_cflags & WLAN_PLAT_NODFS_FLAG)) { |
---|
| 14143 | + return 0; |
---|
| 14144 | + } |
---|
11496 | 14145 | dhd->pub.dhd_cflags &= ~WLAN_PLAT_NODFS_FLAG; |
---|
| 14146 | + } |
---|
11497 | 14147 | dhd->pub.force_country_change = TRUE; |
---|
11498 | 14148 | return 0; |
---|
11499 | 14149 | } |
---|
11500 | 14150 | #endif /* CUSTOM_FORCE_NODFS_FLAG */ |
---|
| 14151 | +#ifdef NDO_CONFIG_SUPPORT |
---|
| 14152 | +int |
---|
| 14153 | +dhd_dev_ndo_cfg(struct net_device *dev, u8 enable) |
---|
| 14154 | +{ |
---|
| 14155 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
| 14156 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 14157 | + int ret = 0; |
---|
| 14158 | + |
---|
| 14159 | + if (enable) { |
---|
| 14160 | + /* enable ND offload feature (will be enabled in FW on suspend) */ |
---|
| 14161 | + dhdp->ndo_enable = TRUE; |
---|
| 14162 | + |
---|
| 14163 | + /* Update changes of anycast address & DAD failed address */ |
---|
| 14164 | + ret = dhd_dev_ndo_update_inet6addr(dev); |
---|
| 14165 | + if ((ret < 0) && (ret != BCME_NORESOURCE)) { |
---|
| 14166 | + DHD_ERROR(("%s: failed to update host ip addr: %d\n", __FUNCTION__, ret)); |
---|
| 14167 | + return ret; |
---|
| 14168 | + } |
---|
| 14169 | + } else { |
---|
| 14170 | + /* disable ND offload feature */ |
---|
| 14171 | + dhdp->ndo_enable = FALSE; |
---|
| 14172 | + |
---|
| 14173 | + /* disable ND offload in FW */ |
---|
| 14174 | + ret = dhd_ndo_enable(dhdp, FALSE); |
---|
| 14175 | + if (ret < 0) { |
---|
| 14176 | + DHD_ERROR(("%s: failed to disable NDO: %d\n", __FUNCTION__, ret)); |
---|
| 14177 | + } |
---|
| 14178 | + } |
---|
| 14179 | + return ret; |
---|
| 14180 | +} |
---|
| 14181 | + |
---|
| 14182 | +/* #pragma used as a WAR to fix build failure, |
---|
| 14183 | +* ignore dropping of 'const' qualifier in 'list_entry' macro |
---|
| 14184 | +* this pragma disables the warning only for the following function |
---|
| 14185 | +*/ |
---|
| 14186 | +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) |
---|
| 14187 | +#pragma GCC diagnostic push |
---|
| 14188 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 14189 | +#endif /* __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 */ |
---|
| 14190 | +static int |
---|
| 14191 | +dhd_dev_ndo_get_valid_inet6addr_count(struct inet6_dev *inet6) |
---|
| 14192 | +{ |
---|
| 14193 | + struct inet6_ifaddr *ifa; |
---|
| 14194 | + struct ifacaddr6 *acaddr = NULL; |
---|
| 14195 | + int addr_count = 0; |
---|
| 14196 | + |
---|
| 14197 | + /* lock */ |
---|
| 14198 | + read_lock_bh(&inet6->lock); |
---|
| 14199 | + |
---|
| 14200 | + /* Count valid unicast address */ |
---|
| 14201 | + list_for_each_entry(ifa, &inet6->addr_list, if_list) { |
---|
| 14202 | + if ((ifa->flags & IFA_F_DADFAILED) == 0) { |
---|
| 14203 | + addr_count++; |
---|
| 14204 | + } |
---|
| 14205 | + } |
---|
| 14206 | + |
---|
| 14207 | + /* Count anycast address */ |
---|
| 14208 | + acaddr = inet6->ac_list; |
---|
| 14209 | + while (acaddr) { |
---|
| 14210 | + addr_count++; |
---|
| 14211 | + acaddr = acaddr->aca_next; |
---|
| 14212 | + } |
---|
| 14213 | + |
---|
| 14214 | + /* unlock */ |
---|
| 14215 | + read_unlock_bh(&inet6->lock); |
---|
| 14216 | + |
---|
| 14217 | + return addr_count; |
---|
| 14218 | +} |
---|
| 14219 | + |
---|
| 14220 | +int |
---|
| 14221 | +dhd_dev_ndo_update_inet6addr(struct net_device *dev) |
---|
| 14222 | +{ |
---|
| 14223 | + dhd_info_t *dhd; |
---|
| 14224 | + dhd_pub_t *dhdp; |
---|
| 14225 | + struct inet6_dev *inet6; |
---|
| 14226 | + struct inet6_ifaddr *ifa; |
---|
| 14227 | + struct ifacaddr6 *acaddr = NULL; |
---|
| 14228 | + struct in6_addr *ipv6_addr = NULL; |
---|
| 14229 | + int cnt, i; |
---|
| 14230 | + int ret = BCME_OK; |
---|
| 14231 | + |
---|
| 14232 | + /* |
---|
| 14233 | + * this function evaulates host ip address in struct inet6_dev |
---|
| 14234 | + * unicast addr in inet6_dev->addr_list |
---|
| 14235 | + * anycast addr in inet6_dev->ac_list |
---|
| 14236 | + * while evaluating inet6_dev, read_lock_bh() is required to prevent |
---|
| 14237 | + * access on null(freed) pointer. |
---|
| 14238 | + */ |
---|
| 14239 | + |
---|
| 14240 | + if (dev) { |
---|
| 14241 | + inet6 = dev->ip6_ptr; |
---|
| 14242 | + if (!inet6) { |
---|
| 14243 | + DHD_ERROR(("%s: Invalid inet6_dev\n", __FUNCTION__)); |
---|
| 14244 | + return BCME_ERROR; |
---|
| 14245 | + } |
---|
| 14246 | + |
---|
| 14247 | + dhd = DHD_DEV_INFO(dev); |
---|
| 14248 | + if (!dhd) { |
---|
| 14249 | + DHD_ERROR(("%s: Invalid dhd_info\n", __FUNCTION__)); |
---|
| 14250 | + return BCME_ERROR; |
---|
| 14251 | + } |
---|
| 14252 | + dhdp = &dhd->pub; |
---|
| 14253 | + |
---|
| 14254 | + if (dhd_net2idx(dhd, dev) != 0) { |
---|
| 14255 | + DHD_ERROR(("%s: Not primary interface\n", __FUNCTION__)); |
---|
| 14256 | + return BCME_ERROR; |
---|
| 14257 | + } |
---|
| 14258 | + } else { |
---|
| 14259 | + DHD_ERROR(("%s: Invalid net_device\n", __FUNCTION__)); |
---|
| 14260 | + return BCME_ERROR; |
---|
| 14261 | + } |
---|
| 14262 | + |
---|
| 14263 | + /* Check host IP overflow */ |
---|
| 14264 | + cnt = dhd_dev_ndo_get_valid_inet6addr_count(inet6); |
---|
| 14265 | + if (cnt > dhdp->ndo_max_host_ip) { |
---|
| 14266 | + if (!dhdp->ndo_host_ip_overflow) { |
---|
| 14267 | + dhdp->ndo_host_ip_overflow = TRUE; |
---|
| 14268 | + /* Disable ND offload in FW */ |
---|
| 14269 | + DHD_INFO(("%s: Host IP overflow, disable NDO\n", __FUNCTION__)); |
---|
| 14270 | + ret = dhd_ndo_enable(dhdp, FALSE); |
---|
| 14271 | + } |
---|
| 14272 | + |
---|
| 14273 | + return ret; |
---|
| 14274 | + } |
---|
| 14275 | + |
---|
| 14276 | + /* |
---|
| 14277 | + * Allocate ipv6 addr buffer to store addresses to be added/removed. |
---|
| 14278 | + * driver need to lock inet6_dev while accessing structure. but, driver |
---|
| 14279 | + * cannot use ioctl while inet6_dev locked since it requires scheduling |
---|
| 14280 | + * hence, copy addresses to the buffer and do ioctl after unlock. |
---|
| 14281 | + */ |
---|
| 14282 | + ipv6_addr = (struct in6_addr *)MALLOC(dhdp->osh, |
---|
| 14283 | + sizeof(struct in6_addr) * dhdp->ndo_max_host_ip); |
---|
| 14284 | + if (!ipv6_addr) { |
---|
| 14285 | + DHD_ERROR(("%s: failed to alloc ipv6 addr buffer\n", __FUNCTION__)); |
---|
| 14286 | + return BCME_NOMEM; |
---|
| 14287 | + } |
---|
| 14288 | + |
---|
| 14289 | + /* Find DAD failed unicast address to be removed */ |
---|
| 14290 | + cnt = 0; |
---|
| 14291 | + read_lock_bh(&inet6->lock); |
---|
| 14292 | + list_for_each_entry(ifa, &inet6->addr_list, if_list) { |
---|
| 14293 | + /* DAD failed unicast address */ |
---|
| 14294 | + if ((ifa->flags & IFA_F_DADFAILED) && |
---|
| 14295 | + (cnt < dhdp->ndo_max_host_ip)) { |
---|
| 14296 | + memcpy(&ipv6_addr[cnt], &ifa->addr, sizeof(struct in6_addr)); |
---|
| 14297 | + cnt++; |
---|
| 14298 | + } |
---|
| 14299 | + } |
---|
| 14300 | + read_unlock_bh(&inet6->lock); |
---|
| 14301 | + |
---|
| 14302 | + /* Remove DAD failed unicast address */ |
---|
| 14303 | + for (i = 0; i < cnt; i++) { |
---|
| 14304 | + DHD_INFO(("%s: Remove DAD failed addr\n", __FUNCTION__)); |
---|
| 14305 | + ret = dhd_ndo_remove_ip_by_addr(dhdp, (char *)&ipv6_addr[i], 0); |
---|
| 14306 | + if (ret < 0) { |
---|
| 14307 | + goto done; |
---|
| 14308 | + } |
---|
| 14309 | + } |
---|
| 14310 | + |
---|
| 14311 | + /* Remove all anycast address */ |
---|
| 14312 | + ret = dhd_ndo_remove_ip_by_type(dhdp, WL_ND_IPV6_ADDR_TYPE_ANYCAST, 0); |
---|
| 14313 | + if (ret < 0) { |
---|
| 14314 | + goto done; |
---|
| 14315 | + } |
---|
| 14316 | + |
---|
| 14317 | + /* |
---|
| 14318 | + * if ND offload was disabled due to host ip overflow, |
---|
| 14319 | + * attempt to add valid unicast address. |
---|
| 14320 | + */ |
---|
| 14321 | + if (dhdp->ndo_host_ip_overflow) { |
---|
| 14322 | + /* Find valid unicast address */ |
---|
| 14323 | + cnt = 0; |
---|
| 14324 | + read_lock_bh(&inet6->lock); |
---|
| 14325 | + list_for_each_entry(ifa, &inet6->addr_list, if_list) { |
---|
| 14326 | + /* valid unicast address */ |
---|
| 14327 | + if (!(ifa->flags & IFA_F_DADFAILED) && |
---|
| 14328 | + (cnt < dhdp->ndo_max_host_ip)) { |
---|
| 14329 | + memcpy(&ipv6_addr[cnt], &ifa->addr, |
---|
| 14330 | + sizeof(struct in6_addr)); |
---|
| 14331 | + cnt++; |
---|
| 14332 | + } |
---|
| 14333 | + } |
---|
| 14334 | + read_unlock_bh(&inet6->lock); |
---|
| 14335 | + |
---|
| 14336 | + /* Add valid unicast address */ |
---|
| 14337 | + for (i = 0; i < cnt; i++) { |
---|
| 14338 | + ret = dhd_ndo_add_ip_with_type(dhdp, |
---|
| 14339 | + (char *)&ipv6_addr[i], WL_ND_IPV6_ADDR_TYPE_UNICAST, 0); |
---|
| 14340 | + if (ret < 0) { |
---|
| 14341 | + goto done; |
---|
| 14342 | + } |
---|
| 14343 | + } |
---|
| 14344 | + } |
---|
| 14345 | + |
---|
| 14346 | + /* Find anycast address */ |
---|
| 14347 | + cnt = 0; |
---|
| 14348 | + read_lock_bh(&inet6->lock); |
---|
| 14349 | + acaddr = inet6->ac_list; |
---|
| 14350 | + while (acaddr) { |
---|
| 14351 | + if (cnt < dhdp->ndo_max_host_ip) { |
---|
| 14352 | + memcpy(&ipv6_addr[cnt], &acaddr->aca_addr, sizeof(struct in6_addr)); |
---|
| 14353 | + cnt++; |
---|
| 14354 | + } |
---|
| 14355 | + acaddr = acaddr->aca_next; |
---|
| 14356 | + } |
---|
| 14357 | + read_unlock_bh(&inet6->lock); |
---|
| 14358 | + |
---|
| 14359 | + /* Add anycast address */ |
---|
| 14360 | + for (i = 0; i < cnt; i++) { |
---|
| 14361 | + ret = dhd_ndo_add_ip_with_type(dhdp, |
---|
| 14362 | + (char *)&ipv6_addr[i], WL_ND_IPV6_ADDR_TYPE_ANYCAST, 0); |
---|
| 14363 | + if (ret < 0) { |
---|
| 14364 | + goto done; |
---|
| 14365 | + } |
---|
| 14366 | + } |
---|
| 14367 | + |
---|
| 14368 | + /* Now All host IP addr were added successfully */ |
---|
| 14369 | + if (dhdp->ndo_host_ip_overflow) { |
---|
| 14370 | + dhdp->ndo_host_ip_overflow = FALSE; |
---|
| 14371 | + if (dhdp->in_suspend) { |
---|
| 14372 | + /* drvier is in (early) suspend state, need to enable ND offload in FW */ |
---|
| 14373 | + DHD_INFO(("%s: enable NDO\n", __FUNCTION__)); |
---|
| 14374 | + ret = dhd_ndo_enable(dhdp, TRUE); |
---|
| 14375 | + } |
---|
| 14376 | + } |
---|
| 14377 | + |
---|
| 14378 | +done: |
---|
| 14379 | + if (ipv6_addr) { |
---|
| 14380 | + MFREE(dhdp->osh, ipv6_addr, sizeof(struct in6_addr) * dhdp->ndo_max_host_ip); |
---|
| 14381 | + } |
---|
| 14382 | + |
---|
| 14383 | + return ret; |
---|
| 14384 | +} |
---|
| 14385 | +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) |
---|
| 14386 | +#pragma GCC diagnostic pop |
---|
| 14387 | +#endif /* __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) */ |
---|
| 14388 | +#endif /* NDO_CONFIG_SUPPORT */ |
---|
| 14389 | + |
---|
11501 | 14390 | #ifdef PNO_SUPPORT |
---|
11502 | 14391 | /* Linux wrapper to call common dhd_pno_stop_for_ssid */ |
---|
11503 | 14392 | int |
---|
.. | .. |
---|
11556 | 14445 | dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
11557 | 14446 | return (dhd_pno_get_for_batch(&dhd->pub, buf, bufsize, PNO_STATUS_NORMAL)); |
---|
11558 | 14447 | } |
---|
| 14448 | +#endif /* PNO_SUPPORT */ |
---|
11559 | 14449 | |
---|
| 14450 | +#if defined(OEM_ANDROID) && defined(PNO_SUPPORT) |
---|
| 14451 | +#ifdef GSCAN_SUPPORT |
---|
11560 | 14452 | bool |
---|
11561 | 14453 | dhd_dev_is_legacy_pno_enabled(struct net_device *dev) |
---|
11562 | 14454 | { |
---|
.. | .. |
---|
11564 | 14456 | |
---|
11565 | 14457 | return (dhd_is_legacy_pno_enabled(&dhd->pub)); |
---|
11566 | 14458 | } |
---|
11567 | | -#endif /* PNO_SUPPORT */ |
---|
11568 | 14459 | |
---|
11569 | | -#if defined(PNO_SUPPORT) |
---|
11570 | | -#ifdef GSCAN_SUPPORT |
---|
| 14460 | +int |
---|
| 14461 | +dhd_dev_set_epno(struct net_device *dev) |
---|
| 14462 | +{ |
---|
| 14463 | + dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 14464 | + if (!dhd) { |
---|
| 14465 | + return BCME_ERROR; |
---|
| 14466 | + } |
---|
| 14467 | + return dhd_pno_set_epno(&dhd->pub); |
---|
| 14468 | +} |
---|
| 14469 | +int |
---|
| 14470 | +dhd_dev_flush_fw_epno(struct net_device *dev) |
---|
| 14471 | +{ |
---|
| 14472 | + dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 14473 | + if (!dhd) { |
---|
| 14474 | + return BCME_ERROR; |
---|
| 14475 | + } |
---|
| 14476 | + return dhd_pno_flush_fw_epno(&dhd->pub); |
---|
| 14477 | +} |
---|
| 14478 | + |
---|
11571 | 14479 | /* Linux wrapper to call common dhd_pno_set_cfg_gscan */ |
---|
11572 | 14480 | int |
---|
11573 | 14481 | dhd_dev_pno_set_cfg_gscan(struct net_device *dev, dhd_pno_gscan_cmd_cfg_t type, |
---|
11574 | | - void *buf, uint8 flush) |
---|
| 14482 | + void *buf, bool flush) |
---|
11575 | 14483 | { |
---|
11576 | 14484 | dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
11577 | 14485 | |
---|
11578 | 14486 | return (dhd_pno_set_cfg_gscan(&dhd->pub, type, buf, flush)); |
---|
11579 | | -} |
---|
11580 | | - |
---|
11581 | | -/* Linux wrapper to call common dhd_pno_get_gscan */ |
---|
11582 | | -void * |
---|
11583 | | -dhd_dev_pno_get_gscan(struct net_device *dev, dhd_pno_gscan_cmd_cfg_t type, |
---|
11584 | | - void *info, uint32 *len) |
---|
11585 | | -{ |
---|
11586 | | - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
11587 | | - |
---|
11588 | | - return (dhd_pno_get_gscan(&dhd->pub, type, info, len)); |
---|
11589 | 14487 | } |
---|
11590 | 14488 | |
---|
11591 | 14489 | /* Linux wrapper to call common dhd_wait_batch_results_complete */ |
---|
.. | .. |
---|
11632 | 14530 | return (dhd_pno_enable_full_scan_result(&dhd->pub, real_time_flag)); |
---|
11633 | 14531 | } |
---|
11634 | 14532 | |
---|
11635 | | -/* Linux wrapper to call common dhd_handle_swc_evt */ |
---|
11636 | | -void * |
---|
11637 | | -dhd_dev_swc_scan_event(struct net_device *dev, const void *data, int *send_evt_bytes) |
---|
11638 | | -{ |
---|
11639 | | - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
11640 | | - |
---|
11641 | | - return (dhd_handle_swc_evt(&dhd->pub, data, send_evt_bytes)); |
---|
11642 | | -} |
---|
11643 | | - |
---|
11644 | 14533 | /* Linux wrapper to call common dhd_handle_hotlist_scan_evt */ |
---|
11645 | 14534 | void * |
---|
11646 | 14535 | dhd_dev_hotlist_scan_event(struct net_device *dev, |
---|
11647 | | - const void *data, int *send_evt_bytes, hotlist_type_t type) |
---|
| 14536 | + const void *data, int *send_evt_bytes, hotlist_type_t type, u32 *buf_len) |
---|
11648 | 14537 | { |
---|
11649 | 14538 | dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
11650 | 14539 | |
---|
11651 | | - return (dhd_handle_hotlist_scan_evt(&dhd->pub, data, send_evt_bytes, type)); |
---|
| 14540 | + return (dhd_handle_hotlist_scan_evt(&dhd->pub, data, send_evt_bytes, type, buf_len)); |
---|
11652 | 14541 | } |
---|
11653 | 14542 | |
---|
11654 | 14543 | /* Linux wrapper to call common dhd_process_full_gscan_result */ |
---|
.. | .. |
---|
11688 | 14577 | return (dhd_retreive_batch_scan_results(&dhd->pub)); |
---|
11689 | 14578 | } |
---|
11690 | 14579 | /* Linux wrapper to call common dhd_pno_process_epno_result */ |
---|
11691 | | -void * |
---|
11692 | | -dhd_dev_process_epno_result(struct net_device *dev, |
---|
11693 | | - const void *data, uint32 event, int *send_evt_bytes) |
---|
| 14580 | +void * dhd_dev_process_epno_result(struct net_device *dev, |
---|
| 14581 | + const void *data, uint32 event, int *send_evt_bytes) |
---|
11694 | 14582 | { |
---|
11695 | 14583 | dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
11696 | 14584 | |
---|
.. | .. |
---|
11709 | 14597 | return BCME_BADARG; |
---|
11710 | 14598 | } |
---|
11711 | 14599 | |
---|
11712 | | - DHD_ERROR(("a_band_boost_thr %d a_band_penalty_thr %d\n", |
---|
| 14600 | + DHD_INFO(("a_band_boost_thr %d a_band_penalty_thr %d\n", |
---|
11713 | 14601 | roam_param->a_band_boost_threshold, roam_param->a_band_penalty_threshold)); |
---|
11714 | | - DHD_ERROR(("a_band_boost_factor %d a_band_penalty_factor %d cur_bssid_boost %d\n", |
---|
| 14602 | + DHD_INFO(("a_band_boost_factor %d a_band_penalty_factor %d cur_bssid_boost %d\n", |
---|
11715 | 14603 | roam_param->a_band_boost_factor, roam_param->a_band_penalty_factor, |
---|
11716 | 14604 | roam_param->cur_bssid_boost)); |
---|
11717 | | - DHD_ERROR(("alert_roam_trigger_thr %d a_band_max_boost %d\n", |
---|
| 14605 | + DHD_INFO(("alert_roam_trigger_thr %d a_band_max_boost %d\n", |
---|
11718 | 14606 | roam_param->alert_roam_trigger_threshold, roam_param->a_band_max_boost)); |
---|
11719 | 14607 | |
---|
11720 | 14608 | memcpy(&roam_exp_cfg.params, roam_param, sizeof(*roam_param)); |
---|
.. | .. |
---|
11760 | 14648 | wl_bssid_pref_cfg_t *bssid_pref, uint32 flush) |
---|
11761 | 14649 | { |
---|
11762 | 14650 | int err; |
---|
11763 | | - int len; |
---|
| 14651 | + uint len; |
---|
11764 | 14652 | dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
11765 | 14653 | |
---|
11766 | 14654 | bssid_pref->version = BSSID_PREF_LIST_VERSION; |
---|
11767 | 14655 | /* By default programming bssid pref flushes out old values */ |
---|
11768 | 14656 | bssid_pref->flags = (flush && !bssid_pref->count) ? ROAM_EXP_CLEAR_BSSID_PREF: 0; |
---|
11769 | 14657 | len = sizeof(wl_bssid_pref_cfg_t); |
---|
11770 | | - len += (bssid_pref->count - 1) * sizeof(wl_bssid_pref_list_t); |
---|
| 14658 | + if (bssid_pref->count) { |
---|
| 14659 | + len += (bssid_pref->count - 1) * sizeof(wl_bssid_pref_list_t); |
---|
| 14660 | + } |
---|
11771 | 14661 | err = dhd_iovar(&dhd->pub, 0, "roam_exp_bssid_pref", |
---|
11772 | 14662 | (char *)bssid_pref, len, NULL, 0, TRUE); |
---|
11773 | 14663 | if (err != BCME_OK) { |
---|
.. | .. |
---|
11775 | 14665 | } |
---|
11776 | 14666 | return err; |
---|
11777 | 14667 | } |
---|
| 14668 | +#endif /* GSCAN_SUPPORT */ |
---|
| 14669 | +#if defined(GSCAN_SUPPORT) || defined(ROAMEXP_SUPPORT) |
---|
11778 | 14670 | int |
---|
11779 | 14671 | dhd_dev_set_blacklist_bssid(struct net_device *dev, maclist_t *blacklist, |
---|
11780 | 14672 | uint32 len, uint32 flush) |
---|
.. | .. |
---|
11826 | 14718 | } |
---|
11827 | 14719 | return err; |
---|
11828 | 14720 | } |
---|
| 14721 | +#endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */ |
---|
11829 | 14722 | |
---|
11830 | | -#endif /* GSCAN_SUPPORT */ |
---|
11831 | | -#endif |
---|
| 14723 | +#if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS) |
---|
| 14724 | +/* Linux wrapper to call common dhd_pno_get_gscan */ |
---|
| 14725 | +void * |
---|
| 14726 | +dhd_dev_pno_get_gscan(struct net_device *dev, dhd_pno_gscan_cmd_cfg_t type, |
---|
| 14727 | + void *info, uint32 *len) |
---|
| 14728 | +{ |
---|
| 14729 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
| 14730 | + |
---|
| 14731 | + return (dhd_pno_get_gscan(&dhd->pub, type, info, len)); |
---|
| 14732 | +} |
---|
| 14733 | +#endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */ |
---|
| 14734 | +#endif /* defined(OEM_ANDROID) && defined(PNO_SUPPORT) */ |
---|
| 14735 | + |
---|
| 14736 | +#ifdef RSSI_MONITOR_SUPPORT |
---|
11832 | 14737 | int |
---|
11833 | 14738 | dhd_dev_set_rssi_monitor_cfg(struct net_device *dev, int start, |
---|
11834 | 14739 | int8 max_rssi, int8 min_rssi) |
---|
.. | .. |
---|
11848 | 14753 | } |
---|
11849 | 14754 | return err; |
---|
11850 | 14755 | } |
---|
| 14756 | +#endif /* RSSI_MONITOR_SUPPORT */ |
---|
| 14757 | + |
---|
| 14758 | +#ifdef DHDTCPACK_SUPPRESS |
---|
| 14759 | +int |
---|
| 14760 | +dhd_dev_set_tcpack_sup_mode_cfg(struct net_device *dev, uint8 enable) |
---|
| 14761 | +{ |
---|
| 14762 | + int err; |
---|
| 14763 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
| 14764 | + |
---|
| 14765 | + err = dhd_tcpack_suppress_set(&dhd->pub, enable); |
---|
| 14766 | + if (err != BCME_OK) { |
---|
| 14767 | + DHD_ERROR(("%s : Failed to set tcpack_suppress mode: %d\n", __FUNCTION__, err)); |
---|
| 14768 | + } |
---|
| 14769 | + return err; |
---|
| 14770 | +} |
---|
| 14771 | +#endif /* DHDTCPACK_SUPPRESS */ |
---|
11851 | 14772 | |
---|
11852 | 14773 | int |
---|
11853 | 14774 | dhd_dev_cfg_rand_mac_oui(struct net_device *dev, uint8 *oui) |
---|
.. | .. |
---|
11866 | 14787 | } else { |
---|
11867 | 14788 | uint8 *rand_mac_oui = dhdp->rand_mac_oui; |
---|
11868 | 14789 | memcpy(rand_mac_oui, oui, DOT11_OUI_LEN); |
---|
11869 | | - DHD_ERROR(("Random MAC OUI to be used - %02x:%02x:%02x\n", rand_mac_oui[0], |
---|
11870 | | - rand_mac_oui[1], rand_mac_oui[2])); |
---|
| 14790 | + DHD_ERROR(("Random MAC OUI to be used - "MACOUIDBG"\n", |
---|
| 14791 | + MACOUI2STRDBG(rand_mac_oui))); |
---|
11871 | 14792 | } |
---|
11872 | 14793 | return BCME_OK; |
---|
11873 | 14794 | } |
---|
.. | .. |
---|
11876 | 14797 | dhd_set_rand_mac_oui(dhd_pub_t *dhd) |
---|
11877 | 14798 | { |
---|
11878 | 14799 | int err; |
---|
11879 | | - wl_pfn_macaddr_cfg_t cfg; |
---|
| 14800 | + wl_pfn_macaddr_cfg_t wl_cfg; |
---|
11880 | 14801 | uint8 *rand_mac_oui = dhd->rand_mac_oui; |
---|
11881 | 14802 | |
---|
11882 | | - memset(&cfg.macaddr, 0, ETHER_ADDR_LEN); |
---|
11883 | | - memcpy(&cfg.macaddr, rand_mac_oui, DOT11_OUI_LEN); |
---|
11884 | | - cfg.version = WL_PFN_MACADDR_CFG_VER; |
---|
11885 | | - if (ETHER_ISNULLADDR(&cfg.macaddr)) |
---|
11886 | | - cfg.flags = 0; |
---|
11887 | | - else |
---|
11888 | | - cfg.flags = (WL_PFN_MAC_OUI_ONLY_MASK | WL_PFN_SET_MAC_UNASSOC_MASK); |
---|
| 14803 | + memset(&wl_cfg.macaddr, 0, ETHER_ADDR_LEN); |
---|
| 14804 | + memcpy(&wl_cfg.macaddr, rand_mac_oui, DOT11_OUI_LEN); |
---|
| 14805 | + wl_cfg.version = WL_PFN_MACADDR_CFG_VER; |
---|
| 14806 | + if (ETHER_ISNULLADDR(&wl_cfg.macaddr)) { |
---|
| 14807 | + wl_cfg.flags = 0; |
---|
| 14808 | + } else { |
---|
| 14809 | + wl_cfg.flags = (WL_PFN_MAC_OUI_ONLY_MASK | WL_PFN_SET_MAC_UNASSOC_MASK); |
---|
| 14810 | + } |
---|
11889 | 14811 | |
---|
11890 | | - DHD_ERROR(("Setting rand mac oui to FW - %02x:%02x:%02x\n", rand_mac_oui[0], |
---|
11891 | | - rand_mac_oui[1], rand_mac_oui[2])); |
---|
| 14812 | + DHD_ERROR(("Setting rand mac oui to FW - "MACOUIDBG"\n", |
---|
| 14813 | + MACOUI2STRDBG(rand_mac_oui))); |
---|
11892 | 14814 | |
---|
11893 | | - err = dhd_iovar(dhd, 0, "pfn_macaddr", (char *)&cfg, sizeof(cfg), NULL, 0, TRUE); |
---|
| 14815 | + err = dhd_iovar(dhd, 0, "pfn_macaddr", (char *)&wl_cfg, sizeof(wl_cfg), NULL, 0, TRUE); |
---|
11894 | 14816 | if (err < 0) { |
---|
11895 | 14817 | DHD_ERROR(("%s : failed to execute pfn_macaddr %d\n", __FUNCTION__, err)); |
---|
11896 | 14818 | } |
---|
11897 | 14819 | return err; |
---|
11898 | 14820 | } |
---|
11899 | | -#ifdef RTT_SUPPORT |
---|
| 14821 | + |
---|
| 14822 | +#if defined(RTT_SUPPORT) && defined(WL_CFG80211) |
---|
11900 | 14823 | /* Linux wrapper to call common dhd_pno_set_cfg_gscan */ |
---|
11901 | 14824 | int |
---|
11902 | 14825 | dhd_dev_rtt_set_cfg(struct net_device *dev, void *buf) |
---|
.. | .. |
---|
11905 | 14828 | |
---|
11906 | 14829 | return (dhd_rtt_set_cfg(&dhd->pub, buf)); |
---|
11907 | 14830 | } |
---|
| 14831 | + |
---|
11908 | 14832 | int |
---|
11909 | 14833 | dhd_dev_rtt_cancel_cfg(struct net_device *dev, struct ether_addr *mac_list, int mac_cnt) |
---|
11910 | 14834 | { |
---|
.. | .. |
---|
11912 | 14836 | |
---|
11913 | 14837 | return (dhd_rtt_stop(&dhd->pub, mac_list, mac_cnt)); |
---|
11914 | 14838 | } |
---|
| 14839 | + |
---|
11915 | 14840 | int |
---|
11916 | 14841 | dhd_dev_rtt_register_noti_callback(struct net_device *dev, void *ctx, dhd_rtt_compl_noti_fn noti_fn) |
---|
11917 | 14842 | { |
---|
.. | .. |
---|
11919 | 14844 | |
---|
11920 | 14845 | return (dhd_rtt_register_noti_callback(&dhd->pub, ctx, noti_fn)); |
---|
11921 | 14846 | } |
---|
| 14847 | + |
---|
11922 | 14848 | int |
---|
11923 | 14849 | dhd_dev_rtt_unregister_noti_callback(struct net_device *dev, dhd_rtt_compl_noti_fn noti_fn) |
---|
11924 | 14850 | { |
---|
.. | .. |
---|
11935 | 14861 | return (dhd_rtt_capability(&dhd->pub, capa)); |
---|
11936 | 14862 | } |
---|
11937 | 14863 | |
---|
| 14864 | +int |
---|
| 14865 | +dhd_dev_rtt_avail_channel(struct net_device *dev, wifi_channel_info *channel_info) |
---|
| 14866 | +{ |
---|
| 14867 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
| 14868 | + return (dhd_rtt_avail_channel(&dhd->pub, channel_info)); |
---|
| 14869 | +} |
---|
| 14870 | + |
---|
| 14871 | +int |
---|
| 14872 | +dhd_dev_rtt_enable_responder(struct net_device *dev, wifi_channel_info *channel_info) |
---|
| 14873 | +{ |
---|
| 14874 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
| 14875 | + return (dhd_rtt_enable_responder(&dhd->pub, channel_info)); |
---|
| 14876 | +} |
---|
| 14877 | + |
---|
| 14878 | +int dhd_dev_rtt_cancel_responder(struct net_device *dev) |
---|
| 14879 | +{ |
---|
| 14880 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
| 14881 | + return (dhd_rtt_cancel_responder(&dhd->pub)); |
---|
| 14882 | +} |
---|
| 14883 | + |
---|
11938 | 14884 | #endif /* RTT_SUPPORT */ |
---|
11939 | 14885 | |
---|
11940 | | -#if defined(KEEP_ALIVE) |
---|
11941 | | -#define TEMP_BUF_SIZE 512 |
---|
11942 | | -#define TEMP_FRAME_SIZE 300 |
---|
| 14886 | +#ifdef KEEP_ALIVE |
---|
| 14887 | +#define KA_TEMP_BUF_SIZE 512 |
---|
| 14888 | +#define KA_FRAME_SIZE 300 |
---|
| 14889 | + |
---|
11943 | 14890 | int |
---|
11944 | | -dhd_dev_start_mkeep_alive(dhd_pub_t *dhd_pub, u8 mkeep_alive_id, u8 *ip_pkt, u16 ip_pkt_len, |
---|
11945 | | - u8* src_mac, u8* dst_mac, u32 period_msec) |
---|
| 14891 | +dhd_dev_start_mkeep_alive(dhd_pub_t *dhd_pub, uint8 mkeep_alive_id, uint8 *ip_pkt, |
---|
| 14892 | + uint16 ip_pkt_len, uint8* src_mac, uint8* dst_mac, uint32 period_msec) |
---|
11946 | 14893 | { |
---|
11947 | | - char *pbuf; |
---|
| 14894 | + const int ETHERTYPE_LEN = 2; |
---|
| 14895 | + char *pbuf = NULL; |
---|
11948 | 14896 | const char *str; |
---|
11949 | | - wl_mkeep_alive_pkt_t mkeep_alive_pkt = {0}; |
---|
11950 | | - wl_mkeep_alive_pkt_t *mkeep_alive_pktp; |
---|
11951 | | - int buf_len; |
---|
11952 | | - int str_len; |
---|
| 14897 | + wl_mkeep_alive_pkt_t mkeep_alive_pkt; |
---|
| 14898 | + wl_mkeep_alive_pkt_t *mkeep_alive_pktp = NULL; |
---|
| 14899 | + int buf_len = 0; |
---|
| 14900 | + int str_len = 0; |
---|
11953 | 14901 | int res = BCME_ERROR; |
---|
11954 | 14902 | int len_bytes = 0; |
---|
11955 | | - int i; |
---|
| 14903 | + int i = 0; |
---|
11956 | 14904 | |
---|
11957 | 14905 | /* ether frame to have both max IP pkt (256 bytes) and ether header */ |
---|
11958 | | - char *pmac_frame; |
---|
| 14906 | + char *pmac_frame = NULL; |
---|
| 14907 | + char *pmac_frame_begin = NULL; |
---|
11959 | 14908 | |
---|
11960 | 14909 | /* |
---|
11961 | 14910 | * The mkeep_alive packet is for STA interface only; if the bss is configured as AP, |
---|
.. | .. |
---|
11966 | 14915 | |
---|
11967 | 14916 | DHD_TRACE(("%s execution\n", __FUNCTION__)); |
---|
11968 | 14917 | |
---|
11969 | | - if ((pbuf = kzalloc(TEMP_BUF_SIZE, GFP_KERNEL)) == NULL) { |
---|
11970 | | - DHD_ERROR(("failed to allocate buf with size %d\n", TEMP_BUF_SIZE)); |
---|
| 14918 | + if ((pbuf = MALLOCZ(dhd_pub->osh, KA_TEMP_BUF_SIZE)) == NULL) { |
---|
| 14919 | + DHD_ERROR(("failed to allocate buf with size %d\n", KA_TEMP_BUF_SIZE)); |
---|
11971 | 14920 | res = BCME_NOMEM; |
---|
11972 | 14921 | return res; |
---|
11973 | 14922 | } |
---|
11974 | 14923 | |
---|
11975 | | - if ((pmac_frame = kzalloc(TEMP_FRAME_SIZE, GFP_KERNEL)) == NULL) { |
---|
11976 | | - DHD_ERROR(("failed to allocate mac_frame with size %d\n", TEMP_FRAME_SIZE)); |
---|
| 14924 | + if ((pmac_frame = MALLOCZ(dhd_pub->osh, KA_FRAME_SIZE)) == NULL) { |
---|
| 14925 | + DHD_ERROR(("failed to allocate mac_frame with size %d\n", KA_FRAME_SIZE)); |
---|
11977 | 14926 | res = BCME_NOMEM; |
---|
11978 | 14927 | goto exit; |
---|
11979 | 14928 | } |
---|
| 14929 | + pmac_frame_begin = pmac_frame; |
---|
11980 | 14930 | |
---|
11981 | 14931 | /* |
---|
11982 | 14932 | * Get current mkeep-alive status. |
---|
11983 | 14933 | */ |
---|
11984 | | - bcm_mkiovar("mkeep_alive", &mkeep_alive_id, sizeof(mkeep_alive_id), |
---|
11985 | | - pbuf, TEMP_BUF_SIZE); |
---|
11986 | | - |
---|
11987 | | - if ((res = dhd_wl_ioctl_cmd(dhd_pub, WLC_GET_VAR, pbuf, TEMP_BUF_SIZE, |
---|
11988 | | - FALSE, 0)) < 0) { |
---|
| 14934 | + res = dhd_iovar(dhd_pub, 0, "mkeep_alive", &mkeep_alive_id, sizeof(mkeep_alive_id), pbuf, |
---|
| 14935 | + KA_TEMP_BUF_SIZE, FALSE); |
---|
| 14936 | + if (res < 0) { |
---|
11989 | 14937 | DHD_ERROR(("%s: Get mkeep_alive failed (error=%d)\n", __FUNCTION__, res)); |
---|
11990 | 14938 | goto exit; |
---|
11991 | 14939 | } else { |
---|
.. | .. |
---|
12017 | 14965 | |
---|
12018 | 14966 | /* Request the specified ID */ |
---|
12019 | 14967 | memset(&mkeep_alive_pkt, 0, sizeof(wl_mkeep_alive_pkt_t)); |
---|
12020 | | - memset(pbuf, 0, TEMP_BUF_SIZE); |
---|
| 14968 | + memset(pbuf, 0, KA_TEMP_BUF_SIZE); |
---|
12021 | 14969 | str = "mkeep_alive"; |
---|
12022 | 14970 | str_len = strlen(str); |
---|
12023 | 14971 | strncpy(pbuf, str, str_len); |
---|
.. | .. |
---|
12058 | 15006 | * Length of ether frame (assume to be all hexa bytes) |
---|
12059 | 15007 | * = src mac + dst mac + ether type + ip pkt len |
---|
12060 | 15008 | */ |
---|
12061 | | - len_bytes = ETHER_ADDR_LEN*2 + ETHER_TYPE_LEN + ip_pkt_len; |
---|
12062 | | - /* Get back to the beginning. */ |
---|
12063 | | - pmac_frame -= len_bytes; |
---|
12064 | | - memcpy(mkeep_alive_pktp->data, pmac_frame, len_bytes); |
---|
| 15009 | + len_bytes = ETHER_ADDR_LEN*2 + ETHERTYPE_LEN + ip_pkt_len; |
---|
| 15010 | + memcpy(mkeep_alive_pktp->data, pmac_frame_begin, len_bytes); |
---|
12065 | 15011 | buf_len += len_bytes; |
---|
12066 | 15012 | mkeep_alive_pkt.len_bytes = htod16(len_bytes); |
---|
12067 | 15013 | |
---|
.. | .. |
---|
12074 | 15020 | |
---|
12075 | 15021 | res = dhd_wl_ioctl_cmd(dhd_pub, WLC_SET_VAR, pbuf, buf_len, TRUE, 0); |
---|
12076 | 15022 | exit: |
---|
12077 | | - kfree(pmac_frame); |
---|
12078 | | - kfree(pbuf); |
---|
| 15023 | + if (pmac_frame_begin) { |
---|
| 15024 | + MFREE(dhd_pub->osh, pmac_frame_begin, KA_FRAME_SIZE); |
---|
| 15025 | + pmac_frame_begin = NULL; |
---|
| 15026 | + } |
---|
| 15027 | + if (pbuf) { |
---|
| 15028 | + MFREE(dhd_pub->osh, pbuf, KA_TEMP_BUF_SIZE); |
---|
| 15029 | + pbuf = NULL; |
---|
| 15030 | + } |
---|
12079 | 15031 | return res; |
---|
12080 | 15032 | } |
---|
12081 | 15033 | |
---|
12082 | 15034 | int |
---|
12083 | | -dhd_dev_stop_mkeep_alive(dhd_pub_t *dhd_pub, u8 mkeep_alive_id) |
---|
| 15035 | +dhd_dev_stop_mkeep_alive(dhd_pub_t *dhd_pub, uint8 mkeep_alive_id) |
---|
12084 | 15036 | { |
---|
12085 | | - char *pbuf; |
---|
12086 | | - const char *str; |
---|
| 15037 | + char *pbuf = NULL; |
---|
12087 | 15038 | wl_mkeep_alive_pkt_t mkeep_alive_pkt; |
---|
12088 | | - wl_mkeep_alive_pkt_t *mkeep_alive_pktp; |
---|
12089 | | - int buf_len; |
---|
12090 | | - int str_len; |
---|
| 15039 | + wl_mkeep_alive_pkt_t *mkeep_alive_pktp = NULL; |
---|
12091 | 15040 | int res = BCME_ERROR; |
---|
12092 | | - int i; |
---|
| 15041 | + int i = 0; |
---|
12093 | 15042 | |
---|
12094 | 15043 | /* |
---|
12095 | 15044 | * The mkeep_alive packet is for STA interface only; if the bss is configured as AP, |
---|
.. | .. |
---|
12103 | 15052 | /* |
---|
12104 | 15053 | * Get current mkeep-alive status. Skip ID 0 which is being used for NULL pkt. |
---|
12105 | 15054 | */ |
---|
12106 | | - if ((pbuf = kzalloc(TEMP_BUF_SIZE, GFP_KERNEL)) == NULL) { |
---|
12107 | | - DHD_ERROR(("failed to allocate buf with size %d\n", TEMP_BUF_SIZE)); |
---|
| 15055 | + if ((pbuf = MALLOC(dhd_pub->osh, KA_TEMP_BUF_SIZE)) == NULL) { |
---|
| 15056 | + DHD_ERROR(("failed to allocate buf with size %d\n", KA_TEMP_BUF_SIZE)); |
---|
12108 | 15057 | return res; |
---|
12109 | 15058 | } |
---|
12110 | 15059 | |
---|
12111 | | - bcm_mkiovar("mkeep_alive", &mkeep_alive_id, sizeof(mkeep_alive_id), pbuf, TEMP_BUF_SIZE); |
---|
12112 | | - |
---|
12113 | | - if ((res = dhd_wl_ioctl_cmd(dhd_pub, WLC_GET_VAR, pbuf, TEMP_BUF_SIZE, FALSE, 0)) < 0) { |
---|
| 15060 | + res = dhd_iovar(dhd_pub, 0, "mkeep_alive", &mkeep_alive_id, |
---|
| 15061 | + sizeof(mkeep_alive_id), pbuf, KA_TEMP_BUF_SIZE, FALSE); |
---|
| 15062 | + if (res < 0) { |
---|
12114 | 15063 | DHD_ERROR(("%s: Get mkeep_alive failed (error=%d)\n", __FUNCTION__, res)); |
---|
12115 | 15064 | goto exit; |
---|
12116 | 15065 | } else { |
---|
.. | .. |
---|
12135 | 15084 | if (dtoh32(mkeep_alive_pktp->period_msec != 0)) { |
---|
12136 | 15085 | DHD_INFO(("stop mkeep_alive on ID %d\n", mkeep_alive_id)); |
---|
12137 | 15086 | memset(&mkeep_alive_pkt, 0, sizeof(wl_mkeep_alive_pkt_t)); |
---|
12138 | | - memset(pbuf, 0, TEMP_BUF_SIZE); |
---|
12139 | | - str = "mkeep_alive"; |
---|
12140 | | - str_len = strlen(str); |
---|
12141 | | - strncpy(pbuf, str, str_len); |
---|
12142 | | - pbuf[str_len] = '\0'; |
---|
12143 | | - |
---|
12144 | | - mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) (pbuf + str_len + 1); |
---|
12145 | 15087 | |
---|
12146 | 15088 | mkeep_alive_pkt.period_msec = 0; |
---|
12147 | | - buf_len = str_len + 1; |
---|
12148 | 15089 | mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION); |
---|
12149 | 15090 | mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN); |
---|
12150 | 15091 | mkeep_alive_pkt.keep_alive_id = mkeep_alive_id; |
---|
12151 | | - buf_len += WL_MKEEP_ALIVE_FIXED_LEN; |
---|
12152 | 15092 | |
---|
12153 | | - /* |
---|
12154 | | - * Keep-alive attributes are set in local variable (mkeep_alive_pkt), and |
---|
12155 | | - * then memcpy'ed into buffer (mkeep_alive_pktp) since there is no |
---|
12156 | | - * guarantee that the buffer is properly aligned. |
---|
12157 | | - */ |
---|
12158 | | - memcpy((char *)mkeep_alive_pktp, &mkeep_alive_pkt, WL_MKEEP_ALIVE_FIXED_LEN); |
---|
12159 | | - |
---|
12160 | | - res = dhd_wl_ioctl_cmd(dhd_pub, WLC_SET_VAR, pbuf, buf_len, TRUE, 0); |
---|
| 15093 | + res = dhd_iovar(dhd_pub, 0, "mkeep_alive", |
---|
| 15094 | + (char *)&mkeep_alive_pkt, |
---|
| 15095 | + WL_MKEEP_ALIVE_FIXED_LEN, NULL, 0, TRUE); |
---|
12161 | 15096 | } else { |
---|
12162 | 15097 | DHD_ERROR(("%s: ID %u does not exist.\n", __FUNCTION__, mkeep_alive_id)); |
---|
12163 | 15098 | res = BCME_NOTFOUND; |
---|
12164 | 15099 | } |
---|
12165 | 15100 | exit: |
---|
12166 | | - kfree(pbuf); |
---|
| 15101 | + if (pbuf) { |
---|
| 15102 | + MFREE(dhd_pub->osh, pbuf, KA_TEMP_BUF_SIZE); |
---|
| 15103 | + pbuf = NULL; |
---|
| 15104 | + } |
---|
12167 | 15105 | return res; |
---|
12168 | 15106 | } |
---|
12169 | | -#endif /* defined(KEEP_ALIVE) */ |
---|
| 15107 | +#endif /* KEEP_ALIVE */ |
---|
12170 | 15108 | |
---|
12171 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) |
---|
12172 | | -static void dhd_hang_process(void *dhd_info, void *event_info, u8 event) |
---|
| 15109 | +#if defined(PKT_FILTER_SUPPORT) && defined(APF) |
---|
| 15110 | +static void _dhd_apf_lock_local(dhd_info_t *dhd) |
---|
12173 | 15111 | { |
---|
12174 | | - dhd_info_t *dhd; |
---|
12175 | | - struct net_device *dev; |
---|
12176 | | - |
---|
12177 | | - dhd = (dhd_info_t *)dhd_info; |
---|
12178 | | - dev = dhd->iflist[0]->net; |
---|
12179 | | - |
---|
12180 | | - if (dev) { |
---|
12181 | | - rtnl_lock(); |
---|
12182 | | - dev_close(dev); |
---|
12183 | | - rtnl_unlock(); |
---|
12184 | | -#if defined(WL_WIRELESS_EXT) |
---|
12185 | | - wl_iw_send_priv_event(dev, "HANG"); |
---|
12186 | | -#endif |
---|
12187 | | -#if defined(WL_CFG80211) |
---|
12188 | | - wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); |
---|
12189 | | -#endif |
---|
| 15112 | + if (dhd) { |
---|
| 15113 | + mutex_lock(&dhd->dhd_apf_mutex); |
---|
12190 | 15114 | } |
---|
12191 | 15115 | } |
---|
12192 | 15116 | |
---|
| 15117 | +static void _dhd_apf_unlock_local(dhd_info_t *dhd) |
---|
| 15118 | +{ |
---|
| 15119 | + if (dhd) { |
---|
| 15120 | + mutex_unlock(&dhd->dhd_apf_mutex); |
---|
| 15121 | + } |
---|
| 15122 | +} |
---|
| 15123 | + |
---|
| 15124 | +static int |
---|
| 15125 | +__dhd_apf_add_filter(struct net_device *ndev, uint32 filter_id, |
---|
| 15126 | + u8* program, uint32 program_len) |
---|
| 15127 | +{ |
---|
| 15128 | + dhd_info_t *dhd = DHD_DEV_INFO(ndev); |
---|
| 15129 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 15130 | + wl_pkt_filter_t * pkt_filterp; |
---|
| 15131 | + wl_apf_program_t *apf_program; |
---|
| 15132 | + char *buf; |
---|
| 15133 | + u32 cmd_len, buf_len; |
---|
| 15134 | + int ifidx, ret; |
---|
| 15135 | + char cmd[] = "pkt_filter_add"; |
---|
| 15136 | + |
---|
| 15137 | + ifidx = dhd_net2idx(dhd, ndev); |
---|
| 15138 | + if (ifidx == DHD_BAD_IF) { |
---|
| 15139 | + DHD_ERROR(("%s: bad ifidx\n", __FUNCTION__)); |
---|
| 15140 | + return -ENODEV; |
---|
| 15141 | + } |
---|
| 15142 | + |
---|
| 15143 | + cmd_len = sizeof(cmd); |
---|
| 15144 | + |
---|
| 15145 | + /* Check if the program_len is more than the expected len |
---|
| 15146 | + * and if the program is NULL return from here. |
---|
| 15147 | + */ |
---|
| 15148 | + if ((program_len > WL_APF_PROGRAM_MAX_SIZE) || (program == NULL)) { |
---|
| 15149 | + DHD_ERROR(("%s Invalid program_len: %d, program: %pK\n", |
---|
| 15150 | + __FUNCTION__, program_len, program)); |
---|
| 15151 | + return -EINVAL; |
---|
| 15152 | + } |
---|
| 15153 | + buf_len = cmd_len + WL_PKT_FILTER_FIXED_LEN + |
---|
| 15154 | + WL_APF_PROGRAM_FIXED_LEN + program_len; |
---|
| 15155 | + |
---|
| 15156 | + buf = MALLOCZ(dhdp->osh, buf_len); |
---|
| 15157 | + if (unlikely(!buf)) { |
---|
| 15158 | + DHD_ERROR(("%s: MALLOC failure, %d bytes\n", __FUNCTION__, buf_len)); |
---|
| 15159 | + return -ENOMEM; |
---|
| 15160 | + } |
---|
| 15161 | + |
---|
| 15162 | + memcpy(buf, cmd, cmd_len); |
---|
| 15163 | + |
---|
| 15164 | + pkt_filterp = (wl_pkt_filter_t *) (buf + cmd_len); |
---|
| 15165 | + pkt_filterp->id = htod32(filter_id); |
---|
| 15166 | + pkt_filterp->negate_match = htod32(FALSE); |
---|
| 15167 | + pkt_filterp->type = htod32(WL_PKT_FILTER_TYPE_APF_MATCH); |
---|
| 15168 | + |
---|
| 15169 | + apf_program = &pkt_filterp->u.apf_program; |
---|
| 15170 | + apf_program->version = htod16(WL_APF_INTERNAL_VERSION); |
---|
| 15171 | + apf_program->instr_len = htod16(program_len); |
---|
| 15172 | + memcpy(apf_program->instrs, program, program_len); |
---|
| 15173 | + |
---|
| 15174 | + ret = dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, buf, buf_len, TRUE, ifidx); |
---|
| 15175 | + if (unlikely(ret)) { |
---|
| 15176 | + DHD_ERROR(("%s: failed to add APF filter, id=%d, ret=%d\n", |
---|
| 15177 | + __FUNCTION__, filter_id, ret)); |
---|
| 15178 | + } |
---|
| 15179 | + |
---|
| 15180 | + if (buf) { |
---|
| 15181 | + MFREE(dhdp->osh, buf, buf_len); |
---|
| 15182 | + } |
---|
| 15183 | + return ret; |
---|
| 15184 | +} |
---|
| 15185 | + |
---|
| 15186 | +static int |
---|
| 15187 | +__dhd_apf_config_filter(struct net_device *ndev, uint32 filter_id, |
---|
| 15188 | + uint32 mode, uint32 enable) |
---|
| 15189 | +{ |
---|
| 15190 | + dhd_info_t *dhd = DHD_DEV_INFO(ndev); |
---|
| 15191 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 15192 | + wl_pkt_filter_enable_t * pkt_filterp; |
---|
| 15193 | + char *buf; |
---|
| 15194 | + u32 cmd_len, buf_len; |
---|
| 15195 | + int ifidx, ret; |
---|
| 15196 | + char cmd[] = "pkt_filter_enable"; |
---|
| 15197 | + |
---|
| 15198 | + ifidx = dhd_net2idx(dhd, ndev); |
---|
| 15199 | + if (ifidx == DHD_BAD_IF) { |
---|
| 15200 | + DHD_ERROR(("%s: bad ifidx\n", __FUNCTION__)); |
---|
| 15201 | + return -ENODEV; |
---|
| 15202 | + } |
---|
| 15203 | + |
---|
| 15204 | + cmd_len = sizeof(cmd); |
---|
| 15205 | + buf_len = cmd_len + sizeof(*pkt_filterp); |
---|
| 15206 | + |
---|
| 15207 | + buf = MALLOCZ(dhdp->osh, buf_len); |
---|
| 15208 | + if (unlikely(!buf)) { |
---|
| 15209 | + DHD_ERROR(("%s: MALLOC failure, %d bytes\n", __FUNCTION__, buf_len)); |
---|
| 15210 | + return -ENOMEM; |
---|
| 15211 | + } |
---|
| 15212 | + |
---|
| 15213 | + memcpy(buf, cmd, cmd_len); |
---|
| 15214 | + |
---|
| 15215 | + pkt_filterp = (wl_pkt_filter_enable_t *) (buf + cmd_len); |
---|
| 15216 | + pkt_filterp->id = htod32(filter_id); |
---|
| 15217 | + pkt_filterp->enable = htod32(enable); |
---|
| 15218 | + |
---|
| 15219 | + ret = dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, buf, buf_len, TRUE, ifidx); |
---|
| 15220 | + if (unlikely(ret)) { |
---|
| 15221 | + DHD_ERROR(("%s: failed to enable APF filter, id=%d, ret=%d\n", |
---|
| 15222 | + __FUNCTION__, filter_id, ret)); |
---|
| 15223 | + goto exit; |
---|
| 15224 | + } |
---|
| 15225 | + |
---|
| 15226 | + ret = dhd_wl_ioctl_set_intiovar(dhdp, "pkt_filter_mode", dhd_master_mode, |
---|
| 15227 | + WLC_SET_VAR, TRUE, ifidx); |
---|
| 15228 | + if (unlikely(ret)) { |
---|
| 15229 | + DHD_ERROR(("%s: failed to set APF filter mode, id=%d, ret=%d\n", |
---|
| 15230 | + __FUNCTION__, filter_id, ret)); |
---|
| 15231 | + } |
---|
| 15232 | + |
---|
| 15233 | +exit: |
---|
| 15234 | + if (buf) { |
---|
| 15235 | + MFREE(dhdp->osh, buf, buf_len); |
---|
| 15236 | + } |
---|
| 15237 | + return ret; |
---|
| 15238 | +} |
---|
| 15239 | + |
---|
| 15240 | +static int |
---|
| 15241 | +__dhd_apf_delete_filter(struct net_device *ndev, uint32 filter_id) |
---|
| 15242 | +{ |
---|
| 15243 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(ndev); |
---|
| 15244 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 15245 | + int ifidx, ret; |
---|
| 15246 | + |
---|
| 15247 | + ifidx = dhd_net2idx(dhd, ndev); |
---|
| 15248 | + if (ifidx == DHD_BAD_IF) { |
---|
| 15249 | + DHD_ERROR(("%s: bad ifidx\n", __FUNCTION__)); |
---|
| 15250 | + return -ENODEV; |
---|
| 15251 | + } |
---|
| 15252 | + |
---|
| 15253 | + ret = dhd_wl_ioctl_set_intiovar(dhdp, "pkt_filter_delete", |
---|
| 15254 | + htod32(filter_id), WLC_SET_VAR, TRUE, ifidx); |
---|
| 15255 | + if (unlikely(ret)) { |
---|
| 15256 | + DHD_ERROR(("%s: failed to delete APF filter, id=%d, ret=%d\n", |
---|
| 15257 | + __FUNCTION__, filter_id, ret)); |
---|
| 15258 | + } |
---|
| 15259 | + |
---|
| 15260 | + return ret; |
---|
| 15261 | +} |
---|
| 15262 | + |
---|
| 15263 | +void dhd_apf_lock(struct net_device *dev) |
---|
| 15264 | +{ |
---|
| 15265 | + dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 15266 | + _dhd_apf_lock_local(dhd); |
---|
| 15267 | +} |
---|
| 15268 | + |
---|
| 15269 | +void dhd_apf_unlock(struct net_device *dev) |
---|
| 15270 | +{ |
---|
| 15271 | + dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 15272 | + _dhd_apf_unlock_local(dhd); |
---|
| 15273 | +} |
---|
| 15274 | + |
---|
| 15275 | +int |
---|
| 15276 | +dhd_dev_apf_get_version(struct net_device *ndev, uint32 *version) |
---|
| 15277 | +{ |
---|
| 15278 | + dhd_info_t *dhd = DHD_DEV_INFO(ndev); |
---|
| 15279 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 15280 | + int ifidx, ret; |
---|
| 15281 | + |
---|
| 15282 | + if (!FW_SUPPORTED(dhdp, apf)) { |
---|
| 15283 | + DHD_ERROR(("%s: firmware doesn't support APF\n", __FUNCTION__)); |
---|
| 15284 | + |
---|
| 15285 | + /* |
---|
| 15286 | + * Notify Android framework that APF is not supported by setting |
---|
| 15287 | + * version as zero. |
---|
| 15288 | + */ |
---|
| 15289 | + *version = 0; |
---|
| 15290 | + return BCME_OK; |
---|
| 15291 | + } |
---|
| 15292 | + |
---|
| 15293 | + ifidx = dhd_net2idx(dhd, ndev); |
---|
| 15294 | + if (ifidx == DHD_BAD_IF) { |
---|
| 15295 | + DHD_ERROR(("%s: bad ifidx\n", __FUNCTION__)); |
---|
| 15296 | + return -ENODEV; |
---|
| 15297 | + } |
---|
| 15298 | + |
---|
| 15299 | + ret = dhd_wl_ioctl_get_intiovar(dhdp, "apf_ver", version, |
---|
| 15300 | + WLC_GET_VAR, FALSE, ifidx); |
---|
| 15301 | + if (unlikely(ret)) { |
---|
| 15302 | + DHD_ERROR(("%s: failed to get APF version, ret=%d\n", |
---|
| 15303 | + __FUNCTION__, ret)); |
---|
| 15304 | + } |
---|
| 15305 | + |
---|
| 15306 | + return ret; |
---|
| 15307 | +} |
---|
| 15308 | + |
---|
| 15309 | +int |
---|
| 15310 | +dhd_dev_apf_get_max_len(struct net_device *ndev, uint32 *max_len) |
---|
| 15311 | +{ |
---|
| 15312 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(ndev); |
---|
| 15313 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 15314 | + int ifidx, ret; |
---|
| 15315 | + |
---|
| 15316 | + if (!FW_SUPPORTED(dhdp, apf)) { |
---|
| 15317 | + DHD_ERROR(("%s: firmware doesn't support APF\n", __FUNCTION__)); |
---|
| 15318 | + *max_len = 0; |
---|
| 15319 | + return BCME_OK; |
---|
| 15320 | + } |
---|
| 15321 | + |
---|
| 15322 | + ifidx = dhd_net2idx(dhd, ndev); |
---|
| 15323 | + if (ifidx == DHD_BAD_IF) { |
---|
| 15324 | + DHD_ERROR(("%s bad ifidx\n", __FUNCTION__)); |
---|
| 15325 | + return -ENODEV; |
---|
| 15326 | + } |
---|
| 15327 | + |
---|
| 15328 | + ret = dhd_wl_ioctl_get_intiovar(dhdp, "apf_size_limit", max_len, |
---|
| 15329 | + WLC_GET_VAR, FALSE, ifidx); |
---|
| 15330 | + if (unlikely(ret)) { |
---|
| 15331 | + DHD_ERROR(("%s: failed to get APF size limit, ret=%d\n", |
---|
| 15332 | + __FUNCTION__, ret)); |
---|
| 15333 | + } |
---|
| 15334 | + |
---|
| 15335 | + return ret; |
---|
| 15336 | +} |
---|
| 15337 | + |
---|
| 15338 | +int |
---|
| 15339 | +dhd_dev_apf_add_filter(struct net_device *ndev, u8* program, |
---|
| 15340 | + uint32 program_len) |
---|
| 15341 | +{ |
---|
| 15342 | + dhd_info_t *dhd = DHD_DEV_INFO(ndev); |
---|
| 15343 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 15344 | + int ret; |
---|
| 15345 | + |
---|
| 15346 | + DHD_APF_LOCK(ndev); |
---|
| 15347 | + |
---|
| 15348 | + /* delete, if filter already exists */ |
---|
| 15349 | + if (dhdp->apf_set) { |
---|
| 15350 | + ret = __dhd_apf_delete_filter(ndev, PKT_FILTER_APF_ID); |
---|
| 15351 | + if (unlikely(ret)) { |
---|
| 15352 | + goto exit; |
---|
| 15353 | + } |
---|
| 15354 | + dhdp->apf_set = FALSE; |
---|
| 15355 | + } |
---|
| 15356 | + |
---|
| 15357 | + ret = __dhd_apf_add_filter(ndev, PKT_FILTER_APF_ID, program, program_len); |
---|
| 15358 | + if (ret) { |
---|
| 15359 | + goto exit; |
---|
| 15360 | + } |
---|
| 15361 | + dhdp->apf_set = TRUE; |
---|
| 15362 | + |
---|
| 15363 | + if (dhdp->in_suspend && dhdp->apf_set && !(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) { |
---|
| 15364 | + /* Driver is still in (early) suspend state, enable APF filter back */ |
---|
| 15365 | + ret = __dhd_apf_config_filter(ndev, PKT_FILTER_APF_ID, |
---|
| 15366 | + PKT_FILTER_MODE_FORWARD_ON_MATCH, TRUE); |
---|
| 15367 | + } |
---|
| 15368 | +exit: |
---|
| 15369 | + DHD_APF_UNLOCK(ndev); |
---|
| 15370 | + |
---|
| 15371 | + return ret; |
---|
| 15372 | +} |
---|
| 15373 | + |
---|
| 15374 | +int |
---|
| 15375 | +dhd_dev_apf_enable_filter(struct net_device *ndev) |
---|
| 15376 | +{ |
---|
| 15377 | + dhd_info_t *dhd = DHD_DEV_INFO(ndev); |
---|
| 15378 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 15379 | + int ret = 0; |
---|
| 15380 | + bool nan_dp_active = false; |
---|
| 15381 | + |
---|
| 15382 | + DHD_APF_LOCK(ndev); |
---|
| 15383 | +#ifdef WL_NAN |
---|
| 15384 | + nan_dp_active = wl_cfgnan_is_dp_active(ndev); |
---|
| 15385 | +#endif /* WL_NAN */ |
---|
| 15386 | + if (dhdp->apf_set && (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE) && |
---|
| 15387 | + !nan_dp_active)) { |
---|
| 15388 | + ret = __dhd_apf_config_filter(ndev, PKT_FILTER_APF_ID, |
---|
| 15389 | + PKT_FILTER_MODE_FORWARD_ON_MATCH, TRUE); |
---|
| 15390 | + } |
---|
| 15391 | + |
---|
| 15392 | + DHD_APF_UNLOCK(ndev); |
---|
| 15393 | + |
---|
| 15394 | + return ret; |
---|
| 15395 | +} |
---|
| 15396 | + |
---|
| 15397 | +int |
---|
| 15398 | +dhd_dev_apf_disable_filter(struct net_device *ndev) |
---|
| 15399 | +{ |
---|
| 15400 | + dhd_info_t *dhd = DHD_DEV_INFO(ndev); |
---|
| 15401 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 15402 | + int ret = 0; |
---|
| 15403 | + |
---|
| 15404 | + DHD_APF_LOCK(ndev); |
---|
| 15405 | + |
---|
| 15406 | + if (dhdp->apf_set) { |
---|
| 15407 | + ret = __dhd_apf_config_filter(ndev, PKT_FILTER_APF_ID, |
---|
| 15408 | + PKT_FILTER_MODE_FORWARD_ON_MATCH, FALSE); |
---|
| 15409 | + } |
---|
| 15410 | + |
---|
| 15411 | + DHD_APF_UNLOCK(ndev); |
---|
| 15412 | + |
---|
| 15413 | + return ret; |
---|
| 15414 | +} |
---|
| 15415 | + |
---|
| 15416 | +int |
---|
| 15417 | +dhd_dev_apf_delete_filter(struct net_device *ndev) |
---|
| 15418 | +{ |
---|
| 15419 | + dhd_info_t *dhd = DHD_DEV_INFO(ndev); |
---|
| 15420 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 15421 | + int ret = 0; |
---|
| 15422 | + |
---|
| 15423 | + DHD_APF_LOCK(ndev); |
---|
| 15424 | + |
---|
| 15425 | + if (dhdp->apf_set) { |
---|
| 15426 | + ret = __dhd_apf_delete_filter(ndev, PKT_FILTER_APF_ID); |
---|
| 15427 | + if (!ret) { |
---|
| 15428 | + dhdp->apf_set = FALSE; |
---|
| 15429 | + } |
---|
| 15430 | + } |
---|
| 15431 | + |
---|
| 15432 | + DHD_APF_UNLOCK(ndev); |
---|
| 15433 | + |
---|
| 15434 | + return ret; |
---|
| 15435 | +} |
---|
| 15436 | +#endif /* PKT_FILTER_SUPPORT && APF */ |
---|
| 15437 | + |
---|
| 15438 | +#if defined(OEM_ANDROID) |
---|
| 15439 | +static void dhd_hang_process(struct work_struct *work_data) |
---|
| 15440 | +{ |
---|
| 15441 | + struct net_device *dev; |
---|
| 15442 | +#ifdef IFACE_HANG_FORCE_DEV_CLOSE |
---|
| 15443 | + struct net_device *ndev; |
---|
| 15444 | + uint8 i = 0; |
---|
| 15445 | +#endif /* IFACE_HANG_FORCE_DEV_CLOSE */ |
---|
| 15446 | +/* Ignore compiler warnings due to -Werror=cast-qual */ |
---|
| 15447 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 15448 | +#pragma GCC diagnostic push |
---|
| 15449 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 15450 | +#endif // endif |
---|
| 15451 | + struct dhd_info *dhd = |
---|
| 15452 | + container_of(work_data, dhd_info_t, dhd_hang_process_work); |
---|
| 15453 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 15454 | +#pragma GCC diagnostic pop |
---|
| 15455 | +#endif // endif |
---|
| 15456 | + |
---|
| 15457 | + dev = dhd->iflist[0]->net; |
---|
| 15458 | + |
---|
| 15459 | + if (dev) { |
---|
| 15460 | +#if defined(WL_WIRELESS_EXT) |
---|
| 15461 | + wl_iw_send_priv_event(dev, "HANG"); |
---|
| 15462 | +#endif // endif |
---|
| 15463 | +#if defined(WL_CFG80211) |
---|
| 15464 | + wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); |
---|
| 15465 | +#endif // endif |
---|
| 15466 | + } |
---|
| 15467 | +#ifdef IFACE_HANG_FORCE_DEV_CLOSE |
---|
| 15468 | + /* |
---|
| 15469 | + * For HW2, dev_close need to be done to recover |
---|
| 15470 | + * from upper layer after hang. For Interposer skip |
---|
| 15471 | + * dev_close so that dhd iovars can be used to take |
---|
| 15472 | + * socramdump after crash, also skip for HW4 as |
---|
| 15473 | + * handling of hang event is different |
---|
| 15474 | + */ |
---|
| 15475 | + |
---|
| 15476 | + rtnl_lock(); |
---|
| 15477 | + for (i = 0; i < DHD_MAX_IFS; i++) { |
---|
| 15478 | + ndev = dhd->iflist[i] ? dhd->iflist[i]->net : NULL; |
---|
| 15479 | + if (ndev && (ndev->flags & IFF_UP)) { |
---|
| 15480 | + DHD_ERROR(("ndev->name : %s dev close\n", |
---|
| 15481 | + ndev->name)); |
---|
| 15482 | + dev_close(ndev); |
---|
| 15483 | + } |
---|
| 15484 | + } |
---|
| 15485 | + rtnl_unlock(); |
---|
| 15486 | +#endif /* IFACE_HANG_FORCE_DEV_CLOSE */ |
---|
| 15487 | +} |
---|
| 15488 | + |
---|
| 15489 | +#ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY |
---|
| 15490 | +extern dhd_pub_t *link_recovery; |
---|
| 15491 | +void dhd_host_recover_link(void) |
---|
| 15492 | +{ |
---|
| 15493 | + DHD_ERROR(("****** %s ******\n", __FUNCTION__)); |
---|
| 15494 | + link_recovery->hang_reason = HANG_REASON_PCIE_LINK_DOWN_RC_DETECT; |
---|
| 15495 | + dhd_bus_set_linkdown(link_recovery, TRUE); |
---|
| 15496 | + dhd_os_send_hang_message(link_recovery); |
---|
| 15497 | +} |
---|
| 15498 | +EXPORT_SYMBOL(dhd_host_recover_link); |
---|
| 15499 | +#endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */ |
---|
12193 | 15500 | |
---|
12194 | 15501 | int dhd_os_send_hang_message(dhd_pub_t *dhdp) |
---|
12195 | 15502 | { |
---|
12196 | 15503 | int ret = 0; |
---|
12197 | | - if (dhdp) { |
---|
12198 | | - if (!dhdp->hang_was_sent) { |
---|
12199 | | - dhdp->hang_was_sent = 1; |
---|
12200 | | - dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, (void *)dhdp, |
---|
12201 | | - DHD_WQ_WORK_HANG_MSG, dhd_hang_process, DHD_WORK_PRIORITY_HIGH); |
---|
| 15504 | +#ifdef WL_CFG80211 |
---|
| 15505 | + struct net_device *primary_ndev; |
---|
| 15506 | + struct bcm_cfg80211 *cfg; |
---|
| 15507 | +#ifdef DHD_FILE_DUMP_EVENT |
---|
| 15508 | + dhd_info_t *dhd_info = NULL; |
---|
| 15509 | +#endif /* DHD_FILE_DUMP_EVENT */ |
---|
| 15510 | +#endif /* WL_CFG80211 */ |
---|
| 15511 | + |
---|
| 15512 | + if (!dhdp) { |
---|
| 15513 | + DHD_ERROR(("%s: dhdp is null\n", __FUNCTION__)); |
---|
| 15514 | + return -EINVAL; |
---|
| 15515 | + } |
---|
| 15516 | + |
---|
| 15517 | +#if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT) |
---|
| 15518 | + dhd_info = (dhd_info_t *)dhdp->info; |
---|
| 15519 | + |
---|
| 15520 | + if (dhd_info->scheduled_memdump) { |
---|
| 15521 | + DHD_ERROR_RLMT(("[DUMP]:%s, memdump in progress. return\n", __FUNCTION__)); |
---|
| 15522 | + dhdp->hang_was_pending = 1; |
---|
| 15523 | + return BCME_OK; |
---|
| 15524 | + } |
---|
| 15525 | +#endif /* WL_CFG80211 && DHD_FILE_DUMP_EVENT */ |
---|
| 15526 | + |
---|
| 15527 | +#ifdef WL_CFG80211 |
---|
| 15528 | + primary_ndev = dhd_linux_get_primary_netdev(dhdp); |
---|
| 15529 | + if (!primary_ndev) { |
---|
| 15530 | + DHD_ERROR(("%s: Cannot find primary netdev\n", __FUNCTION__)); |
---|
| 15531 | + return -ENODEV; |
---|
| 15532 | + } |
---|
| 15533 | + cfg = wl_get_cfg(primary_ndev); |
---|
| 15534 | + if (!cfg) { |
---|
| 15535 | + DHD_ERROR(("%s: Cannot find cfg\n", __FUNCTION__)); |
---|
| 15536 | + return -EINVAL; |
---|
| 15537 | + } |
---|
| 15538 | + |
---|
| 15539 | + /* Skip sending HANG event to framework if driver is not ready */ |
---|
| 15540 | + if (!wl_get_drv_status(cfg, READY, primary_ndev)) { |
---|
| 15541 | + DHD_ERROR(("%s: device is not ready\n", __FUNCTION__)); |
---|
| 15542 | + return -ENODEV; |
---|
| 15543 | + } |
---|
| 15544 | +#endif /* WL_CFG80211 */ |
---|
| 15545 | + |
---|
| 15546 | +#if defined(DHD_HANG_SEND_UP_TEST) |
---|
| 15547 | + if (dhdp->req_hang_type) { |
---|
| 15548 | + DHD_ERROR(("%s, Clear HANG test request 0x%x\n", |
---|
| 15549 | + __FUNCTION__, dhdp->req_hang_type)); |
---|
| 15550 | + dhdp->req_hang_type = 0; |
---|
| 15551 | + } |
---|
| 15552 | +#endif /* DHD_HANG_SEND_UP_TEST */ |
---|
| 15553 | + |
---|
| 15554 | + if (!dhdp->hang_was_sent) { |
---|
| 15555 | +#if defined(CONFIG_BCM_DETECT_CONSECUTIVE_HANG) |
---|
| 15556 | + dhdp->hang_counts++; |
---|
| 15557 | + if (dhdp->hang_counts >= MAX_CONSECUTIVE_HANG_COUNTS) { |
---|
| 15558 | + DHD_ERROR(("%s, Consecutive hang from Dongle :%u\n", |
---|
| 15559 | + __func__, dhdp->hang_counts)); |
---|
| 15560 | + BUG_ON(1); |
---|
12202 | 15561 | } |
---|
| 15562 | +#endif /* CONFIG_BCM_DETECT_CONSECUTIVE_HANG */ |
---|
| 15563 | +#ifdef DHD_DEBUG_UART |
---|
| 15564 | + /* If PCIe lane has broken, execute the debug uart application |
---|
| 15565 | + * to gether a ramdump data from dongle via uart |
---|
| 15566 | + */ |
---|
| 15567 | + if (!dhdp->info->duart_execute) { |
---|
| 15568 | + dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, |
---|
| 15569 | + (void *)dhdp, DHD_WQ_WORK_DEBUG_UART_DUMP, |
---|
| 15570 | + dhd_debug_uart_exec_rd, DHD_WQ_WORK_PRIORITY_HIGH); |
---|
| 15571 | + } |
---|
| 15572 | +#endif /* DHD_DEBUG_UART */ |
---|
| 15573 | + dhdp->hang_was_sent = 1; |
---|
| 15574 | +#ifdef BT_OVER_SDIO |
---|
| 15575 | + dhdp->is_bt_recovery_required = TRUE; |
---|
| 15576 | +#endif // endif |
---|
| 15577 | + schedule_work(&dhdp->info->dhd_hang_process_work); |
---|
| 15578 | + |
---|
12203 | 15579 | } |
---|
12204 | 15580 | return ret; |
---|
12205 | 15581 | } |
---|
.. | .. |
---|
12212 | 15588 | if (dhd) { |
---|
12213 | 15589 | /* Report FW problem when enabled */ |
---|
12214 | 15590 | if (dhd->pub.hang_report) { |
---|
12215 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) |
---|
12216 | | - ret = dhd_os_send_hang_message(&dhd->pub); |
---|
12217 | | -#else |
---|
12218 | | - ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); |
---|
12219 | | -#endif |
---|
| 15591 | +#ifdef BT_OVER_SDIO |
---|
| 15592 | + if (netif_running(dev)) { |
---|
| 15593 | +#endif /* BT_OVER_SDIO */ |
---|
| 15594 | + ret = dhd_os_send_hang_message(&dhd->pub); |
---|
| 15595 | +#ifdef BT_OVER_SDIO |
---|
| 15596 | + } |
---|
| 15597 | + DHD_ERROR(("%s: HANG -> Reset BT\n", __FUNCTION__)); |
---|
| 15598 | + bcmsdh_btsdio_process_dhd_hang_notification(!netif_running(dev)); |
---|
| 15599 | +#endif /* BT_OVER_SDIO */ |
---|
12220 | 15600 | } else { |
---|
12221 | 15601 | DHD_ERROR(("%s: FW HANG ignored (for testing purpose) and not sent up\n", |
---|
12222 | 15602 | __FUNCTION__)); |
---|
12223 | | - /* Enforce bus down to stop any future traffic */ |
---|
12224 | | - dhd->pub.busstate = DHD_BUS_DOWN; |
---|
12225 | 15603 | } |
---|
12226 | 15604 | } |
---|
12227 | 15605 | return ret; |
---|
12228 | 15606 | } |
---|
12229 | | -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && OEM_ANDROID */ |
---|
12230 | 15607 | |
---|
| 15608 | +int net_os_send_hang_message_reason(struct net_device *dev, const char *string_num) |
---|
| 15609 | +{ |
---|
| 15610 | + dhd_info_t *dhd = NULL; |
---|
| 15611 | + dhd_pub_t *dhdp = NULL; |
---|
| 15612 | + int reason; |
---|
| 15613 | + |
---|
| 15614 | + dhd = DHD_DEV_INFO(dev); |
---|
| 15615 | + if (dhd) { |
---|
| 15616 | + dhdp = &dhd->pub; |
---|
| 15617 | + } |
---|
| 15618 | + |
---|
| 15619 | + if (!dhd || !dhdp) { |
---|
| 15620 | + return 0; |
---|
| 15621 | + } |
---|
| 15622 | + |
---|
| 15623 | + reason = bcm_strtoul(string_num, NULL, 0); |
---|
| 15624 | + DHD_INFO(("%s: Enter, reason=0x%x\n", __FUNCTION__, reason)); |
---|
| 15625 | + |
---|
| 15626 | + if ((reason <= HANG_REASON_MASK) || (reason >= HANG_REASON_MAX)) { |
---|
| 15627 | + reason = 0; |
---|
| 15628 | + } |
---|
| 15629 | + |
---|
| 15630 | + dhdp->hang_reason = reason; |
---|
| 15631 | + |
---|
| 15632 | + return net_os_send_hang_message(dev); |
---|
| 15633 | +} |
---|
| 15634 | +#endif /* OEM_ANDROID */ |
---|
12231 | 15635 | |
---|
12232 | 15636 | int dhd_net_wifi_platform_set_power(struct net_device *dev, bool on, unsigned long delay_msec) |
---|
12233 | 15637 | { |
---|
.. | .. |
---|
12243 | 15647 | return dhd->pub.force_country_change; |
---|
12244 | 15648 | return FALSE; |
---|
12245 | 15649 | } |
---|
| 15650 | + |
---|
12246 | 15651 | void dhd_get_customized_country_code(struct net_device *dev, char *country_iso_code, |
---|
12247 | 15652 | wl_country_t *cspec) |
---|
12248 | 15653 | { |
---|
12249 | 15654 | dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
12250 | | -#ifdef CUSTOM_COUNTRY_CODE |
---|
12251 | | - get_customized_country_code(dhd->adapter, country_iso_code, cspec, |
---|
| 15655 | +#if defined(DHD_BLOB_EXISTENCE_CHECK) |
---|
| 15656 | + if (!dhd->pub.is_blob) |
---|
| 15657 | +#endif /* DHD_BLOB_EXISTENCE_CHECK */ |
---|
| 15658 | + { |
---|
| 15659 | +#if defined(CUSTOM_COUNTRY_CODE) |
---|
| 15660 | + get_customized_country_code(dhd->adapter, country_iso_code, cspec, |
---|
12252 | 15661 | dhd->pub.dhd_cflags); |
---|
12253 | 15662 | #else |
---|
12254 | | - get_customized_country_code(dhd->adapter, country_iso_code, cspec); |
---|
| 15663 | + get_customized_country_code(dhd->adapter, country_iso_code, cspec); |
---|
12255 | 15664 | #endif /* CUSTOM_COUNTRY_CODE */ |
---|
| 15665 | + } |
---|
| 15666 | +#if defined(DHD_BLOB_EXISTENCE_CHECK) && !defined(CUSTOM_COUNTRY_CODE) |
---|
| 15667 | + else { |
---|
| 15668 | + /* Replace the ccode to XZ if ccode is undefined country */ |
---|
| 15669 | + if (strncmp(country_iso_code, "", WLC_CNTRY_BUF_SZ) == 0) { |
---|
| 15670 | + strlcpy(country_iso_code, "XZ", WLC_CNTRY_BUF_SZ); |
---|
| 15671 | + strlcpy(cspec->country_abbrev, country_iso_code, WLC_CNTRY_BUF_SZ); |
---|
| 15672 | + strlcpy(cspec->ccode, country_iso_code, WLC_CNTRY_BUF_SZ); |
---|
| 15673 | + DHD_ERROR(("%s: ccode change to %s\n", __FUNCTION__, country_iso_code)); |
---|
| 15674 | + } |
---|
| 15675 | + } |
---|
| 15676 | +#endif /* DHD_BLOB_EXISTENCE_CHECK && !CUSTOM_COUNTRY_CODE */ |
---|
| 15677 | + |
---|
| 15678 | + BCM_REFERENCE(dhd); |
---|
12256 | 15679 | } |
---|
12257 | 15680 | void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, bool notify) |
---|
12258 | 15681 | { |
---|
12259 | 15682 | dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 15683 | +#ifdef WL_CFG80211 |
---|
| 15684 | + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); |
---|
| 15685 | +#endif // endif |
---|
| 15686 | + |
---|
12260 | 15687 | if (dhd && dhd->pub.up) { |
---|
| 15688 | + dhd->pub.force_country_change = FALSE; |
---|
12261 | 15689 | memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t)); |
---|
12262 | 15690 | #ifdef WL_CFG80211 |
---|
12263 | | - wl_update_wiphybands(NULL, notify); |
---|
12264 | | -#endif |
---|
| 15691 | + wl_update_wiphybands(cfg, notify); |
---|
| 15692 | +#endif // endif |
---|
12265 | 15693 | } |
---|
12266 | 15694 | } |
---|
12267 | 15695 | |
---|
12268 | 15696 | void dhd_bus_band_set(struct net_device *dev, uint band) |
---|
12269 | 15697 | { |
---|
12270 | 15698 | dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 15699 | +#ifdef WL_CFG80211 |
---|
| 15700 | + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); |
---|
| 15701 | +#endif // endif |
---|
12271 | 15702 | if (dhd && dhd->pub.up) { |
---|
12272 | 15703 | #ifdef WL_CFG80211 |
---|
12273 | | - wl_update_wiphybands(NULL, true); |
---|
12274 | | -#endif |
---|
| 15704 | + wl_update_wiphybands(cfg, true); |
---|
| 15705 | +#endif // endif |
---|
12275 | 15706 | } |
---|
12276 | 15707 | } |
---|
12277 | 15708 | |
---|
.. | .. |
---|
12285 | 15716 | strncpy(dhd->fw_path, fw, sizeof(dhd->fw_path) - 1); |
---|
12286 | 15717 | dhd->fw_path[sizeof(dhd->fw_path)-1] = '\0'; |
---|
12287 | 15718 | |
---|
12288 | | -#if defined(SOFTAP) |
---|
| 15719 | +#if defined(OEM_ANDROID) && defined(SOFTAP) |
---|
12289 | 15720 | if (strstr(fw, "apsta") != NULL) { |
---|
12290 | 15721 | DHD_INFO(("GOT APSTA FIRMWARE\n")); |
---|
12291 | 15722 | ap_fw_loaded = TRUE; |
---|
.. | .. |
---|
12293 | 15724 | DHD_INFO(("GOT STA FIRMWARE\n")); |
---|
12294 | 15725 | ap_fw_loaded = FALSE; |
---|
12295 | 15726 | } |
---|
12296 | | -#endif |
---|
| 15727 | +#endif /* defined(OEM_ANDROID) && defined(SOFTAP) */ |
---|
12297 | 15728 | return 0; |
---|
12298 | 15729 | } |
---|
12299 | 15730 | |
---|
.. | .. |
---|
12311 | 15742 | |
---|
12312 | 15743 | static void dhd_net_if_lock_local(dhd_info_t *dhd) |
---|
12313 | 15744 | { |
---|
12314 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) |
---|
| 15745 | +#if defined(OEM_ANDROID) |
---|
12315 | 15746 | if (dhd) |
---|
12316 | 15747 | mutex_lock(&dhd->dhd_net_if_mutex); |
---|
12317 | | -#endif |
---|
| 15748 | +#endif // endif |
---|
12318 | 15749 | } |
---|
12319 | 15750 | |
---|
12320 | 15751 | static void dhd_net_if_unlock_local(dhd_info_t *dhd) |
---|
12321 | 15752 | { |
---|
12322 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) |
---|
| 15753 | +#if defined(OEM_ANDROID) |
---|
12323 | 15754 | if (dhd) |
---|
12324 | 15755 | mutex_unlock(&dhd->dhd_net_if_mutex); |
---|
12325 | | -#endif |
---|
| 15756 | +#endif // endif |
---|
12326 | 15757 | } |
---|
12327 | 15758 | |
---|
12328 | 15759 | static void dhd_suspend_lock(dhd_pub_t *pub) |
---|
12329 | 15760 | { |
---|
12330 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) |
---|
| 15761 | +#if defined(OEM_ANDROID) |
---|
12331 | 15762 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12332 | 15763 | if (dhd) |
---|
12333 | 15764 | mutex_lock(&dhd->dhd_suspend_mutex); |
---|
12334 | | -#endif |
---|
| 15765 | +#endif // endif |
---|
12335 | 15766 | } |
---|
12336 | 15767 | |
---|
12337 | 15768 | static void dhd_suspend_unlock(dhd_pub_t *pub) |
---|
12338 | 15769 | { |
---|
12339 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) |
---|
| 15770 | +#if defined(OEM_ANDROID) |
---|
12340 | 15771 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12341 | 15772 | if (dhd) |
---|
12342 | 15773 | mutex_unlock(&dhd->dhd_suspend_mutex); |
---|
12343 | | -#endif |
---|
| 15774 | +#endif // endif |
---|
12344 | 15775 | } |
---|
12345 | 15776 | |
---|
12346 | 15777 | unsigned long dhd_os_general_spin_lock(dhd_pub_t *pub) |
---|
.. | .. |
---|
12397 | 15828 | spin_unlock_irqrestore((spinlock_t *)lock, flags); |
---|
12398 | 15829 | } |
---|
12399 | 15830 | |
---|
| 15831 | +void * |
---|
| 15832 | +dhd_os_dbgring_lock_init(osl_t *osh) |
---|
| 15833 | +{ |
---|
| 15834 | + struct mutex *mtx = NULL; |
---|
| 15835 | + |
---|
| 15836 | + mtx = MALLOCZ(osh, sizeof(*mtx)); |
---|
| 15837 | + if (mtx) |
---|
| 15838 | + mutex_init(mtx); |
---|
| 15839 | + |
---|
| 15840 | + return mtx; |
---|
| 15841 | +} |
---|
| 15842 | + |
---|
| 15843 | +void |
---|
| 15844 | +dhd_os_dbgring_lock_deinit(osl_t *osh, void *mtx) |
---|
| 15845 | +{ |
---|
| 15846 | + if (mtx) { |
---|
| 15847 | + mutex_destroy(mtx); |
---|
| 15848 | + MFREE(osh, mtx, sizeof(struct mutex)); |
---|
| 15849 | + } |
---|
| 15850 | +} |
---|
| 15851 | + |
---|
12400 | 15852 | static int |
---|
12401 | 15853 | dhd_get_pend_8021x_cnt(dhd_info_t *dhd) |
---|
12402 | 15854 | { |
---|
.. | .. |
---|
12433 | 15885 | } |
---|
12434 | 15886 | |
---|
12435 | 15887 | #if defined(DHD_DEBUG) |
---|
12436 | | -int |
---|
12437 | | -write_file(char * file_name, uint32 flags, uint8 *buf, int size) |
---|
| 15888 | +int write_file(const char * file_name, uint32 flags, uint8 *buf, int size) |
---|
12438 | 15889 | { |
---|
12439 | 15890 | int ret = 0; |
---|
12440 | 15891 | struct file *fp = NULL; |
---|
12441 | | - mm_segment_t old_fs; |
---|
12442 | 15892 | loff_t pos = 0; |
---|
12443 | 15893 | /* change to KERNEL_DS address limit */ |
---|
| 15894 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 15895 | + mm_segment_t old_fs; |
---|
12444 | 15896 | old_fs = get_fs(); |
---|
12445 | 15897 | set_fs(KERNEL_DS); |
---|
12446 | | - |
---|
| 15898 | +#endif /* KERNEL_DS && USER_DS */ |
---|
12447 | 15899 | /* open file to write */ |
---|
12448 | | - fp = filp_open(file_name, flags, 0644); |
---|
| 15900 | + fp = filp_open(file_name, flags, 0664); |
---|
12449 | 15901 | if (IS_ERR(fp)) { |
---|
12450 | | - printf("%s: open file error, err = %ld\n", __FUNCTION__, PTR_ERR(fp)); |
---|
12451 | | - ret = -1; |
---|
| 15902 | + DHD_ERROR(("open file error, err = %ld\n", PTR_ERR(fp))); |
---|
12452 | 15903 | goto exit; |
---|
12453 | 15904 | } |
---|
12454 | 15905 | |
---|
12455 | 15906 | /* Write buf to file */ |
---|
12456 | | - fp->f_op->write(fp, buf, size, &pos); |
---|
| 15907 | + ret = vfs_write(fp, buf, size, &pos); |
---|
| 15908 | + if (ret < 0) { |
---|
| 15909 | + DHD_ERROR(("write file error, err = %d\n", ret)); |
---|
| 15910 | + goto exit; |
---|
| 15911 | + } |
---|
| 15912 | + |
---|
| 15913 | + /* Sync file from filesystem to physical media */ |
---|
| 15914 | + ret = vfs_fsync(fp, 0); |
---|
| 15915 | + if (ret < 0) { |
---|
| 15916 | + DHD_ERROR(("sync file error, error = %d\n", ret)); |
---|
| 15917 | + goto exit; |
---|
| 15918 | + } |
---|
| 15919 | + ret = BCME_OK; |
---|
12457 | 15920 | |
---|
12458 | 15921 | exit: |
---|
12459 | 15922 | /* close file before return */ |
---|
.. | .. |
---|
12461 | 15924 | filp_close(fp, current->files); |
---|
12462 | 15925 | |
---|
12463 | 15926 | /* restore previous address limit */ |
---|
| 15927 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
12464 | 15928 | set_fs(old_fs); |
---|
12465 | | - |
---|
12466 | | - /* buf is actually dhd_pub->soc_ram and freed in in dhd_{free,clear} */ |
---|
12467 | | - |
---|
| 15929 | +#endif /* KERNEL_DS && USER_DS */ |
---|
12468 | 15930 | return ret; |
---|
12469 | 15931 | } |
---|
12470 | | -#endif |
---|
| 15932 | +#endif // endif |
---|
12471 | 15933 | |
---|
12472 | 15934 | #ifdef DHD_DEBUG |
---|
12473 | 15935 | static void |
---|
12474 | | -dhd_convert_memdump_type_to_str(uint32 type, char *buf) |
---|
| 15936 | +dhd_convert_memdump_type_to_str(uint32 type, char *buf, int substr_type) |
---|
12475 | 15937 | { |
---|
12476 | 15938 | char *type_str = NULL; |
---|
12477 | 15939 | |
---|
.. | .. |
---|
12491 | 15953 | case DUMP_TYPE_PKTID_AUDIT_FAILURE: |
---|
12492 | 15954 | type_str = "PKTID_AUDIT_Fail"; |
---|
12493 | 15955 | break; |
---|
| 15956 | + case DUMP_TYPE_PKTID_INVALID: |
---|
| 15957 | + type_str = "PKTID_INVALID"; |
---|
| 15958 | + break; |
---|
12494 | 15959 | case DUMP_TYPE_SCAN_TIMEOUT: |
---|
12495 | 15960 | type_str = "SCAN_timeout"; |
---|
| 15961 | + break; |
---|
| 15962 | + case DUMP_TYPE_SCAN_BUSY: |
---|
| 15963 | + type_str = "SCAN_Busy"; |
---|
| 15964 | + break; |
---|
| 15965 | + case DUMP_TYPE_BY_SYSDUMP: |
---|
| 15966 | + if (substr_type == CMD_UNWANTED) { |
---|
| 15967 | + type_str = "BY_SYSDUMP_FORUSER_unwanted"; |
---|
| 15968 | + } else if (substr_type == CMD_DISCONNECTED) { |
---|
| 15969 | + type_str = "BY_SYSDUMP_FORUSER_disconnected"; |
---|
| 15970 | + } else { |
---|
| 15971 | + type_str = "BY_SYSDUMP_FORUSER"; |
---|
| 15972 | + } |
---|
| 15973 | + break; |
---|
| 15974 | + case DUMP_TYPE_BY_LIVELOCK: |
---|
| 15975 | + type_str = "BY_LIVELOCK"; |
---|
| 15976 | + break; |
---|
| 15977 | + case DUMP_TYPE_AP_LINKUP_FAILURE: |
---|
| 15978 | + type_str = "BY_AP_LINK_FAILURE"; |
---|
| 15979 | + break; |
---|
| 15980 | + case DUMP_TYPE_AP_ABNORMAL_ACCESS: |
---|
| 15981 | + type_str = "INVALID_ACCESS"; |
---|
| 15982 | + break; |
---|
| 15983 | + case DUMP_TYPE_RESUMED_ON_TIMEOUT_RX: |
---|
| 15984 | + type_str = "ERROR_RX_TIMED_OUT"; |
---|
| 15985 | + break; |
---|
| 15986 | + case DUMP_TYPE_RESUMED_ON_TIMEOUT_TX: |
---|
| 15987 | + type_str = "ERROR_TX_TIMED_OUT"; |
---|
| 15988 | + break; |
---|
| 15989 | + case DUMP_TYPE_CFG_VENDOR_TRIGGERED: |
---|
| 15990 | + type_str = "CFG_VENDOR_TRIGGERED"; |
---|
| 15991 | + break; |
---|
| 15992 | + case DUMP_TYPE_RESUMED_ON_INVALID_RING_RDWR: |
---|
| 15993 | + type_str = "BY_INVALID_RING_RDWR"; |
---|
| 15994 | + break; |
---|
| 15995 | + case DUMP_TYPE_IFACE_OP_FAILURE: |
---|
| 15996 | + type_str = "BY_IFACE_OP_FAILURE"; |
---|
| 15997 | + break; |
---|
| 15998 | + case DUMP_TYPE_TRANS_ID_MISMATCH: |
---|
| 15999 | + type_str = "BY_TRANS_ID_MISMATCH"; |
---|
| 16000 | + break; |
---|
| 16001 | +#ifdef DEBUG_DNGL_INIT_FAIL |
---|
| 16002 | + case DUMP_TYPE_DONGLE_INIT_FAILURE: |
---|
| 16003 | + type_str = "DONGLE_INIT_FAIL"; |
---|
| 16004 | + break; |
---|
| 16005 | +#endif /* DEBUG_DNGL_INIT_FAIL */ |
---|
| 16006 | +#ifdef SUPPORT_LINKDOWN_RECOVERY |
---|
| 16007 | + case DUMP_TYPE_READ_SHM_FAIL: |
---|
| 16008 | + type_str = "READ_SHM_FAIL"; |
---|
| 16009 | + break; |
---|
| 16010 | +#endif /* SUPPORT_LINKDOWN_RECOVERY */ |
---|
| 16011 | + case DUMP_TYPE_DONGLE_HOST_EVENT: |
---|
| 16012 | + type_str = "BY_DONGLE_HOST_EVENT"; |
---|
| 16013 | + break; |
---|
| 16014 | + case DUMP_TYPE_SMMU_FAULT: |
---|
| 16015 | + type_str = "SMMU_FAULT"; |
---|
| 16016 | + break; |
---|
| 16017 | + case DUMP_TYPE_BY_USER: |
---|
| 16018 | + type_str = "BY_USER"; |
---|
| 16019 | + break; |
---|
| 16020 | +#ifdef DHD_ERPOM |
---|
| 16021 | + case DUMP_TYPE_DUE_TO_BT: |
---|
| 16022 | + type_str = "DUE_TO_BT"; |
---|
| 16023 | + break; |
---|
| 16024 | +#endif /* DHD_ERPOM */ |
---|
| 16025 | + case DUMP_TYPE_LOGSET_BEYOND_RANGE: |
---|
| 16026 | + type_str = "LOGSET_BEYOND_RANGE"; |
---|
| 16027 | + break; |
---|
| 16028 | + case DUMP_TYPE_CTO_RECOVERY: |
---|
| 16029 | + type_str = "CTO_RECOVERY"; |
---|
| 16030 | + break; |
---|
| 16031 | + case DUMP_TYPE_SEQUENTIAL_PRIVCMD_ERROR: |
---|
| 16032 | + type_str = "SEQUENTIAL_PRIVCMD_ERROR"; |
---|
| 16033 | + break; |
---|
| 16034 | + case DUMP_TYPE_PROXD_TIMEOUT: |
---|
| 16035 | + type_str = "PROXD_TIMEOUT"; |
---|
| 16036 | + break; |
---|
| 16037 | + case DUMP_TYPE_PKTID_POOL_DEPLETED: |
---|
| 16038 | + type_str = "PKTID_POOL_DEPLETED"; |
---|
12496 | 16039 | break; |
---|
12497 | 16040 | default: |
---|
12498 | 16041 | type_str = "Unknown_type"; |
---|
.. | .. |
---|
12503 | 16046 | buf[strlen(type_str)] = 0; |
---|
12504 | 16047 | } |
---|
12505 | 16048 | |
---|
| 16049 | +void |
---|
| 16050 | +dhd_get_memdump_filename(struct net_device *ndev, char *memdump_path, int len, char *fname) |
---|
| 16051 | +{ |
---|
| 16052 | + char memdump_type[32]; |
---|
| 16053 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(ndev); |
---|
| 16054 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 16055 | + |
---|
| 16056 | + /* Init file name */ |
---|
| 16057 | + memset(memdump_path, 0, len); |
---|
| 16058 | + memset(memdump_type, 0, sizeof(memdump_type)); |
---|
| 16059 | + dhd_convert_memdump_type_to_str(dhdp->memdump_type, memdump_type, dhdp->debug_dump_subcmd); |
---|
| 16060 | + clear_debug_dump_time(dhdp->debug_dump_time_str); |
---|
| 16061 | + get_debug_dump_time(dhdp->debug_dump_time_str); |
---|
| 16062 | +#ifdef CUSTOMER_HW4_DEBUG |
---|
| 16063 | + snprintf(memdump_path, len, "%s%s_%s_" "%s", |
---|
| 16064 | + DHD_COMMON_DUMP_PATH, fname, memdump_type, dhdp->debug_dump_time_str); |
---|
| 16065 | +#elif defined(CUSTOMER_HW2) || defined(BOARD_HIKEY) |
---|
| 16066 | + snprintf(memdump_path, len, "%s%s_%s_" "%s", |
---|
| 16067 | + DHD_COMMON_DUMP_PATH, fname, memdump_type, dhdp->debug_dump_time_str); |
---|
| 16068 | +#elif defined(OEM_ANDROID) && (defined(BOARD_PANDA) || defined(__ARM_ARCH_7A__)) |
---|
| 16069 | + snprintf(memdump_path, len, "%s%s_%s_" "%s", |
---|
| 16070 | + DHD_COMMON_DUMP_PATH, fname, memdump_type, dhdp->debug_dump_time_str); |
---|
| 16071 | +#elif defined(OEM_ANDROID) |
---|
| 16072 | + snprintf(memdump_path, len, "%s%s_%s_" "%s", |
---|
| 16073 | + DHD_COMMON_DUMP_PATH, fname, memdump_type, dhdp->debug_dump_time_str); |
---|
| 16074 | +#else |
---|
| 16075 | + snprintf(memdump_path, len, "%s%s_%s_" "%s", |
---|
| 16076 | + DHD_COMMON_DUMP_PATH, fname, memdump_type, dhdp->debug_dump_time_str); |
---|
| 16077 | +#endif /* CUSTOMER_HW4_DEBUG */ |
---|
| 16078 | + if (strstr(fname, "sssr_dump")) { |
---|
| 16079 | + DHD_SSSR_PRINT_FILEPATH(dhdp, memdump_path); |
---|
| 16080 | + } else { |
---|
| 16081 | + DHD_ERROR(("%s: file_path = %s%s\n", __FUNCTION__, |
---|
| 16082 | + memdump_path, FILE_NAME_HAL_TAG)); |
---|
| 16083 | + } |
---|
| 16084 | +} |
---|
| 16085 | + |
---|
12506 | 16086 | int |
---|
12507 | | -write_to_file(dhd_pub_t *dhd, uint8 *buf, int size) |
---|
| 16087 | +write_dump_to_file(dhd_pub_t *dhd, uint8 *buf, int size, char *fname) |
---|
12508 | 16088 | { |
---|
12509 | 16089 | int ret = 0; |
---|
12510 | | - char memdump_path[64]; |
---|
| 16090 | + char memdump_path[128]; |
---|
12511 | 16091 | char memdump_type[32]; |
---|
12512 | | -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) |
---|
12513 | | - struct timeval curtime; |
---|
12514 | | -#else |
---|
12515 | | - struct timespec64 curtime; |
---|
12516 | | -#endif |
---|
12517 | 16092 | uint32 file_mode; |
---|
12518 | 16093 | |
---|
12519 | 16094 | /* Init file name */ |
---|
12520 | 16095 | memset(memdump_path, 0, sizeof(memdump_path)); |
---|
12521 | 16096 | memset(memdump_type, 0, sizeof(memdump_type)); |
---|
12522 | | -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) |
---|
12523 | | - do_gettimeofday(&curtime); |
---|
12524 | | -#else |
---|
12525 | | - ktime_get_real_ts64(&curtime); |
---|
12526 | | -#endif |
---|
12527 | | - dhd_convert_memdump_type_to_str(dhd->memdump_type, memdump_type); |
---|
12528 | | - sprintf(memdump_path, "%s_%s_%ld.%ld", "/installmedia/mem_dump", |
---|
12529 | | - memdump_type, (unsigned long)curtime.tv_sec, |
---|
12530 | | -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) |
---|
12531 | | - (unsigned long)curtime.tv_usec); |
---|
12532 | | -#else |
---|
12533 | | - (unsigned long)curtime.tv_nsec); |
---|
12534 | | -#endif |
---|
12535 | | - |
---|
| 16097 | + dhd_convert_memdump_type_to_str(dhd->memdump_type, memdump_type, dhd->debug_dump_subcmd); |
---|
| 16098 | + clear_debug_dump_time(dhd->debug_dump_time_str); |
---|
| 16099 | + get_debug_dump_time(dhd->debug_dump_time_str); |
---|
| 16100 | +#ifdef CUSTOMER_HW4_DEBUG |
---|
| 16101 | + snprintf(memdump_path, sizeof(memdump_path), "%s%s_%s_" "%s", |
---|
| 16102 | + DHD_COMMON_DUMP_PATH, fname, memdump_type, dhd->debug_dump_time_str); |
---|
| 16103 | + file_mode = O_CREAT | O_WRONLY | O_SYNC; |
---|
| 16104 | +#elif defined(CUSTOMER_HW2) || defined(BOARD_HIKEY) |
---|
| 16105 | + snprintf(memdump_path, sizeof(memdump_path), "%s%s_%s_" "%s", |
---|
| 16106 | + DHD_COMMON_DUMP_PATH, fname, memdump_type, dhd->debug_dump_time_str); |
---|
| 16107 | + file_mode = O_CREAT | O_WRONLY | O_SYNC; |
---|
| 16108 | +#elif defined(OEM_ANDROID) && (defined(BOARD_PANDA) || defined(__ARM_ARCH_7A__)) |
---|
| 16109 | + snprintf(memdump_path, sizeof(memdump_path), "%s%s_%s_" "%s", |
---|
| 16110 | + DHD_COMMON_DUMP_PATH, fname, memdump_type, dhd->debug_dump_time_str); |
---|
| 16111 | + file_mode = O_CREAT | O_WRONLY; |
---|
| 16112 | +#elif defined(OEM_ANDROID) |
---|
| 16113 | + snprintf(memdump_path, sizeof(memdump_path), "%s%s_%s_" "%s", |
---|
| 16114 | + "/root/", fname, memdump_type, dhd->debug_dump_time_str); |
---|
12536 | 16115 | /* Extra flags O_DIRECT and O_SYNC are required for Brix Android, as we are |
---|
12537 | 16116 | * calling BUG_ON immediately after collecting the socram dump. |
---|
12538 | 16117 | * So the file write operation should directly write the contents into the |
---|
12539 | 16118 | * file instead of caching it. O_TRUNC flag ensures that file will be re-written |
---|
12540 | 16119 | * instead of appending. |
---|
12541 | 16120 | */ |
---|
12542 | | - file_mode = O_CREAT | O_WRONLY | O_DIRECT | O_SYNC | O_TRUNC; |
---|
| 16121 | + file_mode = O_CREAT | O_WRONLY | O_SYNC; |
---|
| 16122 | + { |
---|
| 16123 | + struct file *fp = filp_open(memdump_path, file_mode, 0664); |
---|
| 16124 | + /* Check if it is live Brix image having /installmedia, else use /data */ |
---|
| 16125 | + if (IS_ERR(fp)) { |
---|
| 16126 | + DHD_ERROR(("open file %s, try /tmp/\n", memdump_path)); |
---|
| 16127 | + snprintf(memdump_path, sizeof(memdump_path), "%s%s_%s_" "%s", |
---|
| 16128 | + "/tmp/", fname, memdump_type, dhd->debug_dump_time_str); |
---|
| 16129 | + } else { |
---|
| 16130 | + filp_close(fp, NULL); |
---|
| 16131 | + } |
---|
| 16132 | + } |
---|
| 16133 | +#else |
---|
| 16134 | + snprintf(memdump_path, sizeof(memdump_path), "%s%s_%s_" "%s", |
---|
| 16135 | + DHD_COMMON_DUMP_PATH, fname, memdump_type, dhd->debug_dump_time_str); |
---|
| 16136 | + file_mode = O_CREAT | O_WRONLY; |
---|
| 16137 | +#endif /* CUSTOMER_HW4_DEBUG */ |
---|
12543 | 16138 | |
---|
12544 | 16139 | /* print SOCRAM dump file path */ |
---|
12545 | | - DHD_ERROR(("%s: memdump_path = %s\n", __FUNCTION__, memdump_path)); |
---|
| 16140 | + DHD_ERROR(("%s: file_path = %s\n", __FUNCTION__, memdump_path)); |
---|
| 16141 | + |
---|
| 16142 | +#ifdef DHD_LOG_DUMP |
---|
| 16143 | + dhd_print_buf_addr(dhd, "write_dump_to_file", buf, size); |
---|
| 16144 | +#endif /* DHD_LOG_DUMP */ |
---|
12546 | 16145 | |
---|
12547 | 16146 | /* Write file */ |
---|
12548 | 16147 | ret = write_file(memdump_path, file_mode, buf, size); |
---|
| 16148 | + |
---|
| 16149 | +#ifdef DHD_DUMP_MNGR |
---|
| 16150 | + if (ret == BCME_OK) { |
---|
| 16151 | + dhd_dump_file_manage_enqueue(dhd, memdump_path, fname); |
---|
| 16152 | + } |
---|
| 16153 | +#endif /* DHD_DUMP_MNGR */ |
---|
12549 | 16154 | |
---|
12550 | 16155 | return ret; |
---|
12551 | 16156 | } |
---|
.. | .. |
---|
12557 | 16162 | unsigned long flags; |
---|
12558 | 16163 | int ret = 0; |
---|
12559 | 16164 | |
---|
12560 | | - if (dhd) { |
---|
| 16165 | + if (dhd && (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) { |
---|
12561 | 16166 | spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
12562 | 16167 | ret = dhd->wakelock_rx_timeout_enable > dhd->wakelock_ctrl_timeout_enable ? |
---|
12563 | 16168 | dhd->wakelock_rx_timeout_enable : dhd->wakelock_ctrl_timeout_enable; |
---|
12564 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16169 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12565 | 16170 | if (dhd->wakelock_rx_timeout_enable) |
---|
12566 | 16171 | wake_lock_timeout(&dhd->wl_rxwake, |
---|
12567 | 16172 | msecs_to_jiffies(dhd->wakelock_rx_timeout_enable)); |
---|
12568 | 16173 | if (dhd->wakelock_ctrl_timeout_enable) |
---|
12569 | 16174 | wake_lock_timeout(&dhd->wl_ctrlwake, |
---|
12570 | 16175 | msecs_to_jiffies(dhd->wakelock_ctrl_timeout_enable)); |
---|
12571 | | -#endif |
---|
| 16176 | +#endif // endif |
---|
12572 | 16177 | dhd->wakelock_rx_timeout_enable = 0; |
---|
12573 | 16178 | dhd->wakelock_ctrl_timeout_enable = 0; |
---|
12574 | 16179 | spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); |
---|
.. | .. |
---|
12591 | 16196 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12592 | 16197 | unsigned long flags; |
---|
12593 | 16198 | |
---|
12594 | | - if (dhd) { |
---|
| 16199 | + if (dhd && (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) { |
---|
12595 | 16200 | spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
12596 | 16201 | if (val > dhd->wakelock_rx_timeout_enable) |
---|
12597 | 16202 | dhd->wakelock_rx_timeout_enable = val; |
---|
.. | .. |
---|
12605 | 16210 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12606 | 16211 | unsigned long flags; |
---|
12607 | 16212 | |
---|
12608 | | - if (dhd) { |
---|
| 16213 | + if (dhd && (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) { |
---|
12609 | 16214 | spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
12610 | 16215 | if (val > dhd->wakelock_ctrl_timeout_enable) |
---|
12611 | 16216 | dhd->wakelock_ctrl_timeout_enable = val; |
---|
.. | .. |
---|
12619 | 16224 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12620 | 16225 | unsigned long flags; |
---|
12621 | 16226 | |
---|
12622 | | - if (dhd) { |
---|
| 16227 | + if (dhd && (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) { |
---|
12623 | 16228 | spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
12624 | 16229 | dhd->wakelock_ctrl_timeout_enable = 0; |
---|
12625 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16230 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12626 | 16231 | if (wake_lock_active(&dhd->wl_ctrlwake)) |
---|
12627 | 16232 | wake_unlock(&dhd->wl_ctrlwake); |
---|
12628 | | -#endif |
---|
| 16233 | +#endif // endif |
---|
12629 | 16234 | spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); |
---|
12630 | 16235 | } |
---|
12631 | 16236 | return 0; |
---|
.. | .. |
---|
12651 | 16256 | return ret; |
---|
12652 | 16257 | } |
---|
12653 | 16258 | |
---|
| 16259 | +#if defined(DHD_TRACE_WAKE_LOCK) |
---|
| 16260 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) |
---|
| 16261 | +#include <linux/hashtable.h> |
---|
| 16262 | +#else |
---|
| 16263 | +#include <linux/hash.h> |
---|
| 16264 | +#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */ |
---|
| 16265 | + |
---|
| 16266 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) |
---|
| 16267 | +/* Define 2^5 = 32 bucket size hash table */ |
---|
| 16268 | +DEFINE_HASHTABLE(wklock_history, 5); |
---|
| 16269 | +#else |
---|
| 16270 | +/* Define 2^5 = 32 bucket size hash table */ |
---|
| 16271 | +struct hlist_head wklock_history[32] = { [0 ... 31] = HLIST_HEAD_INIT }; |
---|
| 16272 | +#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */ |
---|
| 16273 | + |
---|
| 16274 | +atomic_t trace_wklock_onoff; |
---|
| 16275 | +typedef enum dhd_wklock_type { |
---|
| 16276 | + DHD_WAKE_LOCK, |
---|
| 16277 | + DHD_WAKE_UNLOCK, |
---|
| 16278 | + DHD_WAIVE_LOCK, |
---|
| 16279 | + DHD_RESTORE_LOCK |
---|
| 16280 | +} dhd_wklock_t; |
---|
| 16281 | + |
---|
| 16282 | +struct wk_trace_record { |
---|
| 16283 | + unsigned long addr; /* Address of the instruction */ |
---|
| 16284 | + dhd_wklock_t lock_type; /* lock_type */ |
---|
| 16285 | + unsigned long long counter; /* counter information */ |
---|
| 16286 | + struct hlist_node wklock_node; /* hash node */ |
---|
| 16287 | +}; |
---|
| 16288 | + |
---|
| 16289 | +static struct wk_trace_record *find_wklock_entry(unsigned long addr) |
---|
| 16290 | +{ |
---|
| 16291 | + struct wk_trace_record *wklock_info; |
---|
| 16292 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) |
---|
| 16293 | + hash_for_each_possible(wklock_history, wklock_info, wklock_node, addr) |
---|
| 16294 | +#else |
---|
| 16295 | + struct hlist_node *entry; |
---|
| 16296 | + int index = hash_long(addr, ilog2(ARRAY_SIZE(wklock_history))); |
---|
| 16297 | + hlist_for_each_entry(wklock_info, entry, &wklock_history[index], wklock_node) |
---|
| 16298 | +#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */ |
---|
| 16299 | + { |
---|
| 16300 | + if (wklock_info->addr == addr) { |
---|
| 16301 | + return wklock_info; |
---|
| 16302 | + } |
---|
| 16303 | + } |
---|
| 16304 | + return NULL; |
---|
| 16305 | +} |
---|
| 16306 | + |
---|
| 16307 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) |
---|
| 16308 | +#define HASH_ADD(hashtable, node, key) \ |
---|
| 16309 | + do { \ |
---|
| 16310 | + hash_add(hashtable, node, key); \ |
---|
| 16311 | + } while (0); |
---|
| 16312 | +#else |
---|
| 16313 | +#define HASH_ADD(hashtable, node, key) \ |
---|
| 16314 | + do { \ |
---|
| 16315 | + int index = hash_long(key, ilog2(ARRAY_SIZE(hashtable))); \ |
---|
| 16316 | + hlist_add_head(node, &hashtable[index]); \ |
---|
| 16317 | + } while (0); |
---|
| 16318 | +#endif /* KERNEL_VER < KERNEL_VERSION(3, 7, 0) */ |
---|
| 16319 | + |
---|
| 16320 | +#define STORE_WKLOCK_RECORD(wklock_type) \ |
---|
| 16321 | + do { \ |
---|
| 16322 | + struct wk_trace_record *wklock_info = NULL; \ |
---|
| 16323 | + unsigned long func_addr = (unsigned long)__builtin_return_address(0); \ |
---|
| 16324 | + wklock_info = find_wklock_entry(func_addr); \ |
---|
| 16325 | + if (wklock_info) { \ |
---|
| 16326 | + if (wklock_type == DHD_WAIVE_LOCK || wklock_type == DHD_RESTORE_LOCK) { \ |
---|
| 16327 | + wklock_info->counter = dhd->wakelock_counter; \ |
---|
| 16328 | + } else { \ |
---|
| 16329 | + wklock_info->counter++; \ |
---|
| 16330 | + } \ |
---|
| 16331 | + } else { \ |
---|
| 16332 | + wklock_info = kzalloc(sizeof(*wklock_info), GFP_ATOMIC); \ |
---|
| 16333 | + if (!wklock_info) {\ |
---|
| 16334 | + printk("Can't allocate wk_trace_record \n"); \ |
---|
| 16335 | + } else { \ |
---|
| 16336 | + wklock_info->addr = func_addr; \ |
---|
| 16337 | + wklock_info->lock_type = wklock_type; \ |
---|
| 16338 | + if (wklock_type == DHD_WAIVE_LOCK || \ |
---|
| 16339 | + wklock_type == DHD_RESTORE_LOCK) { \ |
---|
| 16340 | + wklock_info->counter = dhd->wakelock_counter; \ |
---|
| 16341 | + } else { \ |
---|
| 16342 | + wklock_info->counter++; \ |
---|
| 16343 | + } \ |
---|
| 16344 | + HASH_ADD(wklock_history, &wklock_info->wklock_node, func_addr); \ |
---|
| 16345 | + } \ |
---|
| 16346 | + } \ |
---|
| 16347 | + } while (0); |
---|
| 16348 | + |
---|
| 16349 | +static inline void dhd_wk_lock_rec_dump(void) |
---|
| 16350 | +{ |
---|
| 16351 | + int bkt; |
---|
| 16352 | + struct wk_trace_record *wklock_info; |
---|
| 16353 | + |
---|
| 16354 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) |
---|
| 16355 | + hash_for_each(wklock_history, bkt, wklock_info, wklock_node) |
---|
| 16356 | +#else |
---|
| 16357 | + struct hlist_node *entry = NULL; |
---|
| 16358 | + int max_index = ARRAY_SIZE(wklock_history); |
---|
| 16359 | + for (bkt = 0; bkt < max_index; bkt++) |
---|
| 16360 | + hlist_for_each_entry(wklock_info, entry, &wklock_history[bkt], wklock_node) |
---|
| 16361 | +#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */ |
---|
| 16362 | + { |
---|
| 16363 | + switch (wklock_info->lock_type) { |
---|
| 16364 | + case DHD_WAKE_LOCK: |
---|
| 16365 | + printk("wakelock lock : %pS lock_counter : %llu \n", |
---|
| 16366 | + (void *)wklock_info->addr, wklock_info->counter); |
---|
| 16367 | + break; |
---|
| 16368 | + case DHD_WAKE_UNLOCK: |
---|
| 16369 | + printk("wakelock unlock : %pS, unlock_counter : %llu \n", |
---|
| 16370 | + (void *)wklock_info->addr, wklock_info->counter); |
---|
| 16371 | + break; |
---|
| 16372 | + case DHD_WAIVE_LOCK: |
---|
| 16373 | + printk("wakelock waive : %pS before_waive : %llu \n", |
---|
| 16374 | + (void *)wklock_info->addr, wklock_info->counter); |
---|
| 16375 | + break; |
---|
| 16376 | + case DHD_RESTORE_LOCK: |
---|
| 16377 | + printk("wakelock restore : %pS, after_waive : %llu \n", |
---|
| 16378 | + (void *)wklock_info->addr, wklock_info->counter); |
---|
| 16379 | + break; |
---|
| 16380 | + } |
---|
| 16381 | + } |
---|
| 16382 | +} |
---|
| 16383 | + |
---|
| 16384 | +static void dhd_wk_lock_trace_init(struct dhd_info *dhd) |
---|
| 16385 | +{ |
---|
| 16386 | + unsigned long flags; |
---|
| 16387 | +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)) |
---|
| 16388 | + int i; |
---|
| 16389 | +#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */ |
---|
| 16390 | + |
---|
| 16391 | + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
| 16392 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) |
---|
| 16393 | + hash_init(wklock_history); |
---|
| 16394 | +#else |
---|
| 16395 | + for (i = 0; i < ARRAY_SIZE(wklock_history); i++) |
---|
| 16396 | + INIT_HLIST_HEAD(&wklock_history[i]); |
---|
| 16397 | +#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */ |
---|
| 16398 | + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); |
---|
| 16399 | + atomic_set(&trace_wklock_onoff, 1); |
---|
| 16400 | +} |
---|
| 16401 | + |
---|
| 16402 | +static void dhd_wk_lock_trace_deinit(struct dhd_info *dhd) |
---|
| 16403 | +{ |
---|
| 16404 | + int bkt; |
---|
| 16405 | + struct wk_trace_record *wklock_info; |
---|
| 16406 | + struct hlist_node *tmp; |
---|
| 16407 | + unsigned long flags; |
---|
| 16408 | +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)) |
---|
| 16409 | + struct hlist_node *entry = NULL; |
---|
| 16410 | + int max_index = ARRAY_SIZE(wklock_history); |
---|
| 16411 | +#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */ |
---|
| 16412 | + |
---|
| 16413 | + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
| 16414 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) |
---|
| 16415 | + hash_for_each_safe(wklock_history, bkt, tmp, wklock_info, wklock_node) |
---|
| 16416 | +#else |
---|
| 16417 | + for (bkt = 0; bkt < max_index; bkt++) |
---|
| 16418 | + hlist_for_each_entry_safe(wklock_info, entry, tmp, |
---|
| 16419 | + &wklock_history[bkt], wklock_node) |
---|
| 16420 | +#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0)) */ |
---|
| 16421 | + { |
---|
| 16422 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) |
---|
| 16423 | + hash_del(&wklock_info->wklock_node); |
---|
| 16424 | +#else |
---|
| 16425 | + hlist_del_init(&wklock_info->wklock_node); |
---|
| 16426 | +#endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0)) */ |
---|
| 16427 | + kfree(wklock_info); |
---|
| 16428 | + } |
---|
| 16429 | + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); |
---|
| 16430 | +} |
---|
| 16431 | + |
---|
| 16432 | +void dhd_wk_lock_stats_dump(dhd_pub_t *dhdp) |
---|
| 16433 | +{ |
---|
| 16434 | + dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); |
---|
| 16435 | + unsigned long flags; |
---|
| 16436 | + |
---|
| 16437 | + printk(KERN_ERR"DHD Printing wl_wake Lock/Unlock Record \r\n"); |
---|
| 16438 | + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
| 16439 | + dhd_wk_lock_rec_dump(); |
---|
| 16440 | + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); |
---|
| 16441 | + |
---|
| 16442 | +} |
---|
| 16443 | +#else |
---|
| 16444 | +#define STORE_WKLOCK_RECORD(wklock_type) |
---|
| 16445 | +#endif /* ! DHD_TRACE_WAKE_LOCK */ |
---|
| 16446 | + |
---|
12654 | 16447 | int dhd_os_wake_lock(dhd_pub_t *pub) |
---|
12655 | 16448 | { |
---|
12656 | 16449 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12657 | 16450 | unsigned long flags; |
---|
12658 | 16451 | int ret = 0; |
---|
12659 | 16452 | |
---|
12660 | | - if (dhd) { |
---|
| 16453 | + if (dhd && (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) { |
---|
12661 | 16454 | spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
12662 | | - |
---|
12663 | 16455 | if (dhd->wakelock_counter == 0 && !dhd->waive_wakelock) { |
---|
12664 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16456 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12665 | 16457 | wake_lock(&dhd->wl_wifi); |
---|
12666 | | -#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
---|
| 16458 | +#elif defined(BCMSDIO) |
---|
12667 | 16459 | dhd_bus_dev_pm_stay_awake(pub); |
---|
12668 | | -#endif |
---|
| 16460 | +#endif // endif |
---|
12669 | 16461 | } |
---|
| 16462 | +#ifdef DHD_TRACE_WAKE_LOCK |
---|
| 16463 | + if (atomic_read(&trace_wklock_onoff)) { |
---|
| 16464 | + STORE_WKLOCK_RECORD(DHD_WAKE_LOCK); |
---|
| 16465 | + } |
---|
| 16466 | +#endif /* DHD_TRACE_WAKE_LOCK */ |
---|
12670 | 16467 | dhd->wakelock_counter++; |
---|
12671 | 16468 | ret = dhd->wakelock_counter; |
---|
12672 | 16469 | spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); |
---|
12673 | 16470 | } |
---|
| 16471 | + |
---|
12674 | 16472 | return ret; |
---|
| 16473 | +} |
---|
| 16474 | + |
---|
| 16475 | +void dhd_event_wake_lock(dhd_pub_t *pub) |
---|
| 16476 | +{ |
---|
| 16477 | + dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
| 16478 | + |
---|
| 16479 | + if (dhd) { |
---|
| 16480 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
| 16481 | + wake_lock(&dhd->wl_evtwake); |
---|
| 16482 | +#elif defined(BCMSDIO) |
---|
| 16483 | + dhd_bus_dev_pm_stay_awake(pub); |
---|
| 16484 | +#endif // endif |
---|
| 16485 | + } |
---|
| 16486 | +} |
---|
| 16487 | + |
---|
| 16488 | +void |
---|
| 16489 | +dhd_pm_wake_lock_timeout(dhd_pub_t *pub, int val) |
---|
| 16490 | +{ |
---|
| 16491 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
| 16492 | + dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
| 16493 | + |
---|
| 16494 | + if (dhd) { |
---|
| 16495 | + wake_lock_timeout(&dhd->wl_pmwake, msecs_to_jiffies(val)); |
---|
| 16496 | + } |
---|
| 16497 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
| 16498 | +} |
---|
| 16499 | + |
---|
| 16500 | +void |
---|
| 16501 | +dhd_txfl_wake_lock_timeout(dhd_pub_t *pub, int val) |
---|
| 16502 | +{ |
---|
| 16503 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
| 16504 | + dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
| 16505 | + |
---|
| 16506 | + if (dhd) { |
---|
| 16507 | + wake_lock_timeout(&dhd->wl_txflwake, msecs_to_jiffies(val)); |
---|
| 16508 | + } |
---|
| 16509 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
12675 | 16510 | } |
---|
12676 | 16511 | |
---|
12677 | 16512 | int net_os_wake_lock(struct net_device *dev) |
---|
.. | .. |
---|
12691 | 16526 | int ret = 0; |
---|
12692 | 16527 | |
---|
12693 | 16528 | dhd_os_wake_lock_timeout(pub); |
---|
12694 | | - if (dhd) { |
---|
| 16529 | + if (dhd && (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) { |
---|
12695 | 16530 | spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
| 16531 | + |
---|
12696 | 16532 | if (dhd->wakelock_counter > 0) { |
---|
12697 | 16533 | dhd->wakelock_counter--; |
---|
| 16534 | +#ifdef DHD_TRACE_WAKE_LOCK |
---|
| 16535 | + if (atomic_read(&trace_wklock_onoff)) { |
---|
| 16536 | + STORE_WKLOCK_RECORD(DHD_WAKE_UNLOCK); |
---|
| 16537 | + } |
---|
| 16538 | +#endif /* DHD_TRACE_WAKE_LOCK */ |
---|
12698 | 16539 | if (dhd->wakelock_counter == 0 && !dhd->waive_wakelock) { |
---|
12699 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16540 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12700 | 16541 | wake_unlock(&dhd->wl_wifi); |
---|
12701 | | -#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
---|
| 16542 | +#elif defined(BCMSDIO) |
---|
12702 | 16543 | dhd_bus_dev_pm_relax(pub); |
---|
12703 | | -#endif |
---|
| 16544 | +#endif // endif |
---|
12704 | 16545 | } |
---|
12705 | 16546 | ret = dhd->wakelock_counter; |
---|
12706 | 16547 | } |
---|
.. | .. |
---|
12709 | 16550 | return ret; |
---|
12710 | 16551 | } |
---|
12711 | 16552 | |
---|
12712 | | -void dhd_event_wake_lock(dhd_pub_t *pub) |
---|
12713 | | -{ |
---|
12714 | | - dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12715 | | - |
---|
12716 | | - if (dhd) { |
---|
12717 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
12718 | | - wake_lock(&dhd->wl_evtwake); |
---|
12719 | | -#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
---|
12720 | | - dhd_bus_dev_pm_stay_awake(pub); |
---|
12721 | | -#endif |
---|
12722 | | - } |
---|
12723 | | -} |
---|
12724 | | - |
---|
12725 | 16553 | void dhd_event_wake_unlock(dhd_pub_t *pub) |
---|
12726 | 16554 | { |
---|
12727 | 16555 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12728 | 16556 | |
---|
12729 | 16557 | if (dhd) { |
---|
12730 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16558 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12731 | 16559 | wake_unlock(&dhd->wl_evtwake); |
---|
12732 | | -#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
---|
| 16560 | +#elif defined(BCMSDIO) |
---|
12733 | 16561 | dhd_bus_dev_pm_relax(pub); |
---|
12734 | | -#endif |
---|
| 16562 | +#endif // endif |
---|
12735 | 16563 | } |
---|
12736 | 16564 | } |
---|
12737 | 16565 | |
---|
12738 | | -void dhd_txfl_wake_lock_timeout(dhd_pub_t *pub, int val) |
---|
| 16566 | +void dhd_pm_wake_unlock(dhd_pub_t *pub) |
---|
12739 | 16567 | { |
---|
12740 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16568 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12741 | 16569 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12742 | 16570 | |
---|
12743 | 16571 | if (dhd) { |
---|
12744 | | - wake_lock_timeout(&dhd->wl_txflwake, msecs_to_jiffies(val)); |
---|
| 16572 | + /* if wl_pmwake is active, unlock it */ |
---|
| 16573 | + if (wake_lock_active(&dhd->wl_pmwake)) { |
---|
| 16574 | + wake_unlock(&dhd->wl_pmwake); |
---|
| 16575 | + } |
---|
12745 | 16576 | } |
---|
12746 | | -#endif /* CONFIG_HAS_WAKE_LOCK */ |
---|
| 16577 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
12747 | 16578 | } |
---|
12748 | 16579 | |
---|
12749 | 16580 | void dhd_txfl_wake_unlock(dhd_pub_t *pub) |
---|
12750 | 16581 | { |
---|
12751 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16582 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12752 | 16583 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12753 | 16584 | |
---|
12754 | 16585 | if (dhd) { |
---|
.. | .. |
---|
12757 | 16588 | wake_unlock(&dhd->wl_txflwake); |
---|
12758 | 16589 | } |
---|
12759 | 16590 | } |
---|
12760 | | -#endif /* CONFIG_HAS_WAKELOCK */ |
---|
| 16591 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
12761 | 16592 | } |
---|
12762 | 16593 | |
---|
12763 | 16594 | int dhd_os_check_wakelock(dhd_pub_t *pub) |
---|
12764 | 16595 | { |
---|
12765 | | -#if defined(CONFIG_HAS_WAKELOCK) || (defined(BCMSDIO) && (LINUX_VERSION_CODE > \ |
---|
12766 | | - KERNEL_VERSION(2, 6, 36))) |
---|
| 16596 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) || defined(BCMSDIO) |
---|
12767 | 16597 | dhd_info_t *dhd; |
---|
12768 | 16598 | |
---|
12769 | 16599 | if (!pub) |
---|
12770 | 16600 | return 0; |
---|
12771 | 16601 | dhd = (dhd_info_t *)(pub->info); |
---|
12772 | | -#endif /* CONFIG_HAS_WAKELOCK || BCMSDIO */ |
---|
| 16602 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK || BCMSDIO */ |
---|
12773 | 16603 | |
---|
12774 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16604 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12775 | 16605 | /* Indicate to the SD Host to avoid going to suspend if internal locks are up */ |
---|
12776 | 16606 | if (dhd && (wake_lock_active(&dhd->wl_wifi) || |
---|
12777 | 16607 | (wake_lock_active(&dhd->wl_wdwake)))) |
---|
12778 | 16608 | return 1; |
---|
12779 | | -#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
---|
| 16609 | +#elif defined(BCMSDIO) |
---|
12780 | 16610 | if (dhd && (dhd->wakelock_counter > 0) && dhd_bus_dev_pm_enabled(pub)) |
---|
12781 | 16611 | return 1; |
---|
12782 | | -#endif |
---|
| 16612 | +#endif // endif |
---|
12783 | 16613 | return 0; |
---|
12784 | 16614 | } |
---|
12785 | 16615 | |
---|
12786 | 16616 | int |
---|
12787 | 16617 | dhd_os_check_wakelock_all(dhd_pub_t *pub) |
---|
12788 | 16618 | { |
---|
12789 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
12790 | | - int l1, l2, l3, l4; |
---|
| 16619 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) || defined(BCMSDIO) |
---|
| 16620 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
| 16621 | + int l1, l2, l3, l4, l7, l8, l9; |
---|
12791 | 16622 | int l5 = 0, l6 = 0; |
---|
12792 | | - int l7, l8; |
---|
12793 | 16623 | int c, lock_active; |
---|
12794 | | -#endif /* CONFIG_HAS_WAKELOCK */ |
---|
12795 | | -#if defined(CONFIG_HAS_WAKELOCK) || (defined(BCMSDIO) && (LINUX_VERSION_CODE > \ |
---|
12796 | | - KERNEL_VERSION(2, 6, 36))) |
---|
| 16624 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
12797 | 16625 | dhd_info_t *dhd; |
---|
12798 | 16626 | |
---|
12799 | 16627 | if (!pub) { |
---|
.. | .. |
---|
12803 | 16631 | if (!dhd) { |
---|
12804 | 16632 | return 0; |
---|
12805 | 16633 | } |
---|
12806 | | -#endif /* CONFIG_HAS_WAKELOCK || BCMSDIO */ |
---|
| 16634 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK || BCMSDIO */ |
---|
12807 | 16635 | |
---|
12808 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16636 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12809 | 16637 | c = dhd->wakelock_counter; |
---|
12810 | 16638 | l1 = wake_lock_active(&dhd->wl_wifi); |
---|
12811 | 16639 | l2 = wake_lock_active(&dhd->wl_wdwake); |
---|
12812 | 16640 | l3 = wake_lock_active(&dhd->wl_rxwake); |
---|
12813 | 16641 | l4 = wake_lock_active(&dhd->wl_ctrlwake); |
---|
| 16642 | + l7 = wake_lock_active(&dhd->wl_evtwake); |
---|
12814 | 16643 | #ifdef BCMPCIE_OOB_HOST_WAKE |
---|
12815 | 16644 | l5 = wake_lock_active(&dhd->wl_intrwake); |
---|
12816 | 16645 | #endif /* BCMPCIE_OOB_HOST_WAKE */ |
---|
12817 | 16646 | #ifdef DHD_USE_SCAN_WAKELOCK |
---|
12818 | 16647 | l6 = wake_lock_active(&dhd->wl_scanwake); |
---|
12819 | 16648 | #endif /* DHD_USE_SCAN_WAKELOCK */ |
---|
12820 | | - l7 = wake_lock_active(&dhd->wl_evtwake); |
---|
12821 | | - l8 = wake_lock_active(&dhd->wl_txflwake); |
---|
12822 | | - lock_active = (l1 || l2 || l3 || l4 || l5 || l6 || l7 || l8); |
---|
| 16649 | + l8 = wake_lock_active(&dhd->wl_pmwake); |
---|
| 16650 | + l9 = wake_lock_active(&dhd->wl_txflwake); |
---|
| 16651 | + lock_active = (l1 || l2 || l3 || l4 || l5 || l6 || l7 || l8 || l9); |
---|
12823 | 16652 | |
---|
12824 | 16653 | /* Indicate to the Host to avoid going to suspend if internal locks are up */ |
---|
12825 | | - if (dhd && lock_active) { |
---|
| 16654 | + if (lock_active) { |
---|
12826 | 16655 | DHD_ERROR(("%s wakelock c-%d wl-%d wd-%d rx-%d " |
---|
12827 | | - "ctl-%d intr-%d scan-%d\n", |
---|
12828 | | - __FUNCTION__, c, l1, l2, l3, l4, l5, l6)); |
---|
| 16656 | + "ctl-%d intr-%d scan-%d evt-%d, pm-%d, txfl-%d\n", |
---|
| 16657 | + __FUNCTION__, c, l1, l2, l3, l4, l5, l6, l7, l8, l9)); |
---|
12829 | 16658 | return 1; |
---|
12830 | 16659 | } |
---|
12831 | | -#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
---|
| 16660 | +#elif defined(BCMSDIO) |
---|
12832 | 16661 | if (dhd && (dhd->wakelock_counter > 0) && dhd_bus_dev_pm_enabled(pub)) { |
---|
12833 | 16662 | return 1; |
---|
12834 | 16663 | } |
---|
12835 | | -#endif /* CONFIG_HAS_WAKELOCK */ |
---|
| 16664 | +#endif /* defined(BCMSDIO) */ |
---|
12836 | 16665 | return 0; |
---|
12837 | 16666 | } |
---|
12838 | 16667 | |
---|
.. | .. |
---|
12854 | 16683 | |
---|
12855 | 16684 | if (dhd) { |
---|
12856 | 16685 | spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
12857 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
12858 | | - /* if wakelock_wd_counter was never used : lock it at once */ |
---|
12859 | | - if (!dhd->wakelock_wd_counter) |
---|
| 16686 | + if (dhd->wakelock_wd_counter == 0 && !dhd->waive_wakelock) { |
---|
| 16687 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
| 16688 | + /* if wakelock_wd_counter was never used : lock it at once */ |
---|
12860 | 16689 | wake_lock(&dhd->wl_wdwake); |
---|
12861 | | -#endif |
---|
| 16690 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
| 16691 | + } |
---|
12862 | 16692 | dhd->wakelock_wd_counter++; |
---|
12863 | 16693 | ret = dhd->wakelock_wd_counter; |
---|
12864 | 16694 | spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); |
---|
.. | .. |
---|
12874 | 16704 | |
---|
12875 | 16705 | if (dhd) { |
---|
12876 | 16706 | spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
12877 | | - if (dhd->wakelock_wd_counter) { |
---|
| 16707 | + if (dhd->wakelock_wd_counter > 0) { |
---|
12878 | 16708 | dhd->wakelock_wd_counter = 0; |
---|
12879 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
12880 | | - wake_unlock(&dhd->wl_wdwake); |
---|
12881 | | -#endif |
---|
| 16709 | + if (!dhd->waive_wakelock) { |
---|
| 16710 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
| 16711 | + wake_unlock(&dhd->wl_wdwake); |
---|
| 16712 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
| 16713 | + } |
---|
12882 | 16714 | } |
---|
12883 | 16715 | spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); |
---|
12884 | 16716 | } |
---|
.. | .. |
---|
12889 | 16721 | void |
---|
12890 | 16722 | dhd_os_oob_irq_wake_lock_timeout(dhd_pub_t *pub, int val) |
---|
12891 | 16723 | { |
---|
12892 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16724 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12893 | 16725 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12894 | 16726 | |
---|
12895 | 16727 | if (dhd) { |
---|
12896 | 16728 | wake_lock_timeout(&dhd->wl_intrwake, msecs_to_jiffies(val)); |
---|
12897 | 16729 | } |
---|
12898 | | -#endif /* CONFIG_HAS_WAKELOCK */ |
---|
| 16730 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
12899 | 16731 | } |
---|
12900 | 16732 | |
---|
12901 | 16733 | void |
---|
12902 | 16734 | dhd_os_oob_irq_wake_unlock(dhd_pub_t *pub) |
---|
12903 | 16735 | { |
---|
12904 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16736 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12905 | 16737 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12906 | 16738 | |
---|
12907 | 16739 | if (dhd) { |
---|
.. | .. |
---|
12910 | 16742 | wake_unlock(&dhd->wl_intrwake); |
---|
12911 | 16743 | } |
---|
12912 | 16744 | } |
---|
12913 | | -#endif /* CONFIG_HAS_WAKELOCK */ |
---|
| 16745 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
12914 | 16746 | } |
---|
12915 | 16747 | #endif /* BCMPCIE_OOB_HOST_WAKE */ |
---|
12916 | 16748 | |
---|
.. | .. |
---|
12918 | 16750 | void |
---|
12919 | 16751 | dhd_os_scan_wake_lock_timeout(dhd_pub_t *pub, int val) |
---|
12920 | 16752 | { |
---|
12921 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16753 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12922 | 16754 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12923 | 16755 | |
---|
12924 | 16756 | if (dhd) { |
---|
12925 | 16757 | wake_lock_timeout(&dhd->wl_scanwake, msecs_to_jiffies(val)); |
---|
12926 | 16758 | } |
---|
12927 | | -#endif /* CONFIG_HAS_WAKELOCK */ |
---|
| 16759 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
12928 | 16760 | } |
---|
12929 | 16761 | |
---|
12930 | 16762 | void |
---|
12931 | 16763 | dhd_os_scan_wake_unlock(dhd_pub_t *pub) |
---|
12932 | 16764 | { |
---|
12933 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16765 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12934 | 16766 | dhd_info_t *dhd = (dhd_info_t *)(pub->info); |
---|
12935 | 16767 | |
---|
12936 | 16768 | if (dhd) { |
---|
.. | .. |
---|
12939 | 16771 | wake_unlock(&dhd->wl_scanwake); |
---|
12940 | 16772 | } |
---|
12941 | 16773 | } |
---|
12942 | | -#endif /* CONFIG_HAS_WAKELOCK */ |
---|
| 16774 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
12943 | 16775 | } |
---|
12944 | 16776 | #endif /* DHD_USE_SCAN_WAKELOCK */ |
---|
12945 | 16777 | |
---|
.. | .. |
---|
12952 | 16784 | unsigned long flags; |
---|
12953 | 16785 | int ret = 0; |
---|
12954 | 16786 | |
---|
12955 | | - if (dhd) { |
---|
| 16787 | + if (dhd && (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) { |
---|
12956 | 16788 | spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
| 16789 | + |
---|
12957 | 16790 | /* dhd_wakelock_waive/dhd_wakelock_restore must be paired */ |
---|
12958 | 16791 | if (dhd->waive_wakelock == FALSE) { |
---|
| 16792 | +#ifdef DHD_TRACE_WAKE_LOCK |
---|
| 16793 | + if (atomic_read(&trace_wklock_onoff)) { |
---|
| 16794 | + STORE_WKLOCK_RECORD(DHD_WAIVE_LOCK); |
---|
| 16795 | + } |
---|
| 16796 | +#endif /* DHD_TRACE_WAKE_LOCK */ |
---|
12959 | 16797 | /* record current lock status */ |
---|
12960 | 16798 | dhd->wakelock_before_waive = dhd->wakelock_counter; |
---|
12961 | 16799 | dhd->waive_wakelock = TRUE; |
---|
.. | .. |
---|
12974 | 16812 | |
---|
12975 | 16813 | if (!dhd) |
---|
12976 | 16814 | return 0; |
---|
| 16815 | + if ((dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) == 0) |
---|
| 16816 | + return 0; |
---|
12977 | 16817 | |
---|
12978 | 16818 | spin_lock_irqsave(&dhd->wakelock_spinlock, flags); |
---|
| 16819 | + |
---|
12979 | 16820 | /* dhd_wakelock_waive/dhd_wakelock_restore must be paired */ |
---|
12980 | 16821 | if (!dhd->waive_wakelock) |
---|
12981 | 16822 | goto exit; |
---|
.. | .. |
---|
12985 | 16826 | * we need to make it up by calling wake_lock or pm_stay_awake. or if somebody releases |
---|
12986 | 16827 | * the lock in between, do the same by calling wake_unlock or pm_relax |
---|
12987 | 16828 | */ |
---|
| 16829 | +#ifdef DHD_TRACE_WAKE_LOCK |
---|
| 16830 | + if (atomic_read(&trace_wklock_onoff)) { |
---|
| 16831 | + STORE_WKLOCK_RECORD(DHD_RESTORE_LOCK); |
---|
| 16832 | + } |
---|
| 16833 | +#endif /* DHD_TRACE_WAKE_LOCK */ |
---|
| 16834 | + |
---|
12988 | 16835 | if (dhd->wakelock_before_waive == 0 && dhd->wakelock_counter > 0) { |
---|
12989 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16836 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12990 | 16837 | wake_lock(&dhd->wl_wifi); |
---|
12991 | | -#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
---|
| 16838 | +#elif defined(BCMSDIO) |
---|
12992 | 16839 | dhd_bus_dev_pm_stay_awake(&dhd->pub); |
---|
12993 | | -#endif |
---|
| 16840 | +#endif // endif |
---|
12994 | 16841 | } else if (dhd->wakelock_before_waive > 0 && dhd->wakelock_counter == 0) { |
---|
12995 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16842 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
12996 | 16843 | wake_unlock(&dhd->wl_wifi); |
---|
12997 | | -#elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
---|
| 16844 | +#elif defined(BCMSDIO) |
---|
12998 | 16845 | dhd_bus_dev_pm_relax(&dhd->pub); |
---|
12999 | | -#endif |
---|
| 16846 | +#endif // endif |
---|
13000 | 16847 | } |
---|
13001 | 16848 | dhd->wakelock_before_waive = 0; |
---|
13002 | 16849 | exit: |
---|
.. | .. |
---|
13011 | 16858 | dhd->wakelock_counter = 0; |
---|
13012 | 16859 | dhd->wakelock_rx_timeout_enable = 0; |
---|
13013 | 16860 | dhd->wakelock_ctrl_timeout_enable = 0; |
---|
13014 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16861 | + /* wakelocks prevent a system from going into a low power state */ |
---|
| 16862 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
| 16863 | + wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); |
---|
13015 | 16864 | wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); |
---|
13016 | 16865 | wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake"); |
---|
13017 | 16866 | wake_lock_init(&dhd->wl_evtwake, WAKE_LOCK_SUSPEND, "wlan_evt_wake"); |
---|
| 16867 | + wake_lock_init(&dhd->wl_pmwake, WAKE_LOCK_SUSPEND, "wlan_pm_wake"); |
---|
13018 | 16868 | wake_lock_init(&dhd->wl_txflwake, WAKE_LOCK_SUSPEND, "wlan_txfl_wake"); |
---|
13019 | 16869 | #ifdef BCMPCIE_OOB_HOST_WAKE |
---|
13020 | 16870 | wake_lock_init(&dhd->wl_intrwake, WAKE_LOCK_SUSPEND, "wlan_oob_irq_wake"); |
---|
.. | .. |
---|
13022 | 16872 | #ifdef DHD_USE_SCAN_WAKELOCK |
---|
13023 | 16873 | wake_lock_init(&dhd->wl_scanwake, WAKE_LOCK_SUSPEND, "wlan_scan_wake"); |
---|
13024 | 16874 | #endif /* DHD_USE_SCAN_WAKELOCK */ |
---|
13025 | | -#endif /* CONFIG_HAS_WAKELOCK */ |
---|
| 16875 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
| 16876 | +#ifdef DHD_TRACE_WAKE_LOCK |
---|
| 16877 | + dhd_wk_lock_trace_init(dhd); |
---|
| 16878 | +#endif /* DHD_TRACE_WAKE_LOCK */ |
---|
13026 | 16879 | } |
---|
13027 | 16880 | |
---|
13028 | 16881 | void dhd_os_wake_lock_destroy(struct dhd_info *dhd) |
---|
13029 | 16882 | { |
---|
13030 | 16883 | DHD_TRACE(("%s: deinit wake_lock_counters\n", __FUNCTION__)); |
---|
13031 | | -#ifdef CONFIG_HAS_WAKELOCK |
---|
| 16884 | +#if defined(CONFIG_PM_WAKELOCKS) || defined(CONFIG_HAS_WAKELOCK) |
---|
13032 | 16885 | dhd->wakelock_counter = 0; |
---|
13033 | 16886 | dhd->wakelock_rx_timeout_enable = 0; |
---|
13034 | 16887 | dhd->wakelock_ctrl_timeout_enable = 0; |
---|
| 16888 | + wake_lock_destroy(&dhd->wl_wifi); |
---|
13035 | 16889 | wake_lock_destroy(&dhd->wl_rxwake); |
---|
13036 | 16890 | wake_lock_destroy(&dhd->wl_ctrlwake); |
---|
13037 | 16891 | wake_lock_destroy(&dhd->wl_evtwake); |
---|
| 16892 | + wake_lock_destroy(&dhd->wl_pmwake); |
---|
13038 | 16893 | wake_lock_destroy(&dhd->wl_txflwake); |
---|
13039 | 16894 | #ifdef BCMPCIE_OOB_HOST_WAKE |
---|
13040 | 16895 | wake_lock_destroy(&dhd->wl_intrwake); |
---|
.. | .. |
---|
13042 | 16897 | #ifdef DHD_USE_SCAN_WAKELOCK |
---|
13043 | 16898 | wake_lock_destroy(&dhd->wl_scanwake); |
---|
13044 | 16899 | #endif /* DHD_USE_SCAN_WAKELOCK */ |
---|
13045 | | -#endif /* CONFIG_HAS_WAKELOCK */ |
---|
| 16900 | +#ifdef DHD_TRACE_WAKE_LOCK |
---|
| 16901 | + dhd_wk_lock_trace_deinit(dhd); |
---|
| 16902 | +#endif /* DHD_TRACE_WAKE_LOCK */ |
---|
| 16903 | +#endif /* CONFIG_PM_WAKELOCKS || CONFIG_HAS_WAKELOCK */ |
---|
13046 | 16904 | } |
---|
13047 | 16905 | |
---|
13048 | 16906 | bool dhd_os_check_if_up(dhd_pub_t *pub) |
---|
.. | .. |
---|
13069 | 16927 | dhd_bus_chiprev_id(dhdp), dhd_bus_chippkg_id(dhdp)); |
---|
13070 | 16928 | } |
---|
13071 | 16929 | #endif /* BCMSDIO || BCMPCIE */ |
---|
13072 | | - |
---|
13073 | 16930 | int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd) |
---|
13074 | 16931 | { |
---|
13075 | 16932 | int ifidx; |
---|
.. | .. |
---|
13077 | 16934 | dhd_info_t *dhd = NULL; |
---|
13078 | 16935 | |
---|
13079 | 16936 | if (!net || !DEV_PRIV(net)) { |
---|
13080 | | - DHD_ERROR(("%s invalid parameter\n", __FUNCTION__)); |
---|
| 16937 | + DHD_ERROR(("%s invalid parameter net %p dev_priv %p\n", |
---|
| 16938 | + __FUNCTION__, net, DEV_PRIV(net))); |
---|
13081 | 16939 | return -EINVAL; |
---|
13082 | 16940 | } |
---|
13083 | 16941 | |
---|
.. | .. |
---|
13122 | 16980 | return dhdp->info->unit; |
---|
13123 | 16981 | } |
---|
13124 | 16982 | |
---|
| 16983 | +#if defined(WL_CFG80211) && defined(SUPPORT_DEEP_SLEEP) |
---|
| 16984 | +#define MAX_TRY_CNT 5 /* Number of tries to disable deepsleep */ |
---|
| 16985 | +int dhd_deepsleep(struct net_device *dev, int flag) |
---|
| 16986 | +{ |
---|
| 16987 | + char iovbuf[20]; |
---|
| 16988 | + uint powervar = 0; |
---|
| 16989 | + dhd_info_t *dhd; |
---|
| 16990 | + dhd_pub_t *dhdp; |
---|
| 16991 | + int cnt = 0; |
---|
| 16992 | + int ret = 0; |
---|
| 16993 | + |
---|
| 16994 | + dhd = DHD_DEV_INFO(dev); |
---|
| 16995 | + dhdp = &dhd->pub; |
---|
| 16996 | + |
---|
| 16997 | + switch (flag) { |
---|
| 16998 | + case 1 : /* Deepsleep on */ |
---|
| 16999 | + DHD_ERROR(("[WiFi] Deepsleep On\n")); |
---|
| 17000 | + /* give some time to sysioc_work before deepsleep */ |
---|
| 17001 | + OSL_SLEEP(200); |
---|
| 17002 | +#ifdef PKT_FILTER_SUPPORT |
---|
| 17003 | + /* disable pkt filter */ |
---|
| 17004 | + dhd_enable_packet_filter(0, dhdp); |
---|
| 17005 | +#endif /* PKT_FILTER_SUPPORT */ |
---|
| 17006 | + /* Disable MPC */ |
---|
| 17007 | + powervar = 0; |
---|
| 17008 | + ret = dhd_iovar(dhdp, 0, "mpc", (char *)&powervar, sizeof(powervar), NULL, |
---|
| 17009 | + 0, TRUE); |
---|
| 17010 | + |
---|
| 17011 | + /* Enable Deepsleep */ |
---|
| 17012 | + powervar = 1; |
---|
| 17013 | + ret = dhd_iovar(dhdp, 0, "deepsleep", (char *)&powervar, sizeof(powervar), |
---|
| 17014 | + NULL, 0, TRUE); |
---|
| 17015 | + break; |
---|
| 17016 | + |
---|
| 17017 | + case 0: /* Deepsleep Off */ |
---|
| 17018 | + DHD_ERROR(("[WiFi] Deepsleep Off\n")); |
---|
| 17019 | + |
---|
| 17020 | + /* Disable Deepsleep */ |
---|
| 17021 | + for (cnt = 0; cnt < MAX_TRY_CNT; cnt++) { |
---|
| 17022 | + powervar = 0; |
---|
| 17023 | + ret = dhd_iovar(dhdp, 0, "deepsleep", (char *)&powervar, |
---|
| 17024 | + sizeof(powervar), NULL, 0, TRUE); |
---|
| 17025 | + |
---|
| 17026 | + ret = dhd_iovar(dhdp, 0, "deepsleep", (char *)&powervar, |
---|
| 17027 | + sizeof(powervar), iovbuf, sizeof(iovbuf), FALSE); |
---|
| 17028 | + if (ret < 0) { |
---|
| 17029 | + DHD_ERROR(("the error of dhd deepsleep status" |
---|
| 17030 | + " ret value :%d\n", ret)); |
---|
| 17031 | + } else { |
---|
| 17032 | + if (!(*(int *)iovbuf)) { |
---|
| 17033 | + DHD_ERROR(("deepsleep mode is 0," |
---|
| 17034 | + " count: %d\n", cnt)); |
---|
| 17035 | + break; |
---|
| 17036 | + } |
---|
| 17037 | + } |
---|
| 17038 | + } |
---|
| 17039 | + |
---|
| 17040 | + /* Enable MPC */ |
---|
| 17041 | + powervar = 1; |
---|
| 17042 | + ret = dhd_iovar(dhdp, 0, "mpc", (char *)&powervar, sizeof(powervar), NULL, |
---|
| 17043 | + 0, TRUE); |
---|
| 17044 | + break; |
---|
| 17045 | + } |
---|
| 17046 | + |
---|
| 17047 | + return 0; |
---|
| 17048 | +} |
---|
| 17049 | +#endif /* WL_CFG80211 && SUPPORT_DEEP_SLEEP */ |
---|
13125 | 17050 | |
---|
13126 | 17051 | #ifdef PROP_TXSTATUS |
---|
13127 | 17052 | |
---|
13128 | 17053 | void dhd_wlfc_plat_init(void *dhd) |
---|
13129 | 17054 | { |
---|
| 17055 | +#ifdef USE_DYNAMIC_F2_BLKSIZE |
---|
| 17056 | + dhdsdio_func_blocksize((dhd_pub_t *)dhd, 2, sd_f2_blocksize); |
---|
| 17057 | +#endif /* USE_DYNAMIC_F2_BLKSIZE */ |
---|
13130 | 17058 | return; |
---|
13131 | 17059 | } |
---|
13132 | 17060 | |
---|
13133 | 17061 | void dhd_wlfc_plat_deinit(void *dhd) |
---|
13134 | 17062 | { |
---|
| 17063 | +#ifdef USE_DYNAMIC_F2_BLKSIZE |
---|
| 17064 | + dhdsdio_func_blocksize((dhd_pub_t *)dhd, 2, sd_f2_blocksize); |
---|
| 17065 | +#endif /* USE_DYNAMIC_F2_BLKSIZE */ |
---|
13135 | 17066 | return; |
---|
13136 | 17067 | } |
---|
13137 | 17068 | |
---|
13138 | | -bool dhd_wlfc_skip_fc(void) |
---|
| 17069 | +bool dhd_wlfc_skip_fc(void * dhdp, uint8 idx) |
---|
13139 | 17070 | { |
---|
| 17071 | +#ifdef SKIP_WLFC_ON_CONCURRENT |
---|
| 17072 | + |
---|
| 17073 | +#ifdef WL_CFG80211 |
---|
| 17074 | + struct net_device * net = dhd_idx2net((dhd_pub_t *)dhdp, idx); |
---|
| 17075 | + if (net) |
---|
| 17076 | + /* enable flow control in vsdb mode */ |
---|
| 17077 | + return !(wl_cfg80211_is_concurrent_mode(net)); |
---|
| 17078 | +#else |
---|
| 17079 | + return TRUE; /* skip flow control */ |
---|
| 17080 | +#endif /* WL_CFG80211 */ |
---|
| 17081 | + |
---|
| 17082 | +#else |
---|
| 17083 | + return FALSE; |
---|
| 17084 | +#endif /* SKIP_WLFC_ON_CONCURRENT */ |
---|
13140 | 17085 | return FALSE; |
---|
13141 | 17086 | } |
---|
13142 | 17087 | #endif /* PROP_TXSTATUS */ |
---|
.. | .. |
---|
13193 | 17138 | return rval; |
---|
13194 | 17139 | } |
---|
13195 | 17140 | |
---|
13196 | | - |
---|
13197 | 17141 | static ssize_t |
---|
13198 | 17142 | dhd_debugfs_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) |
---|
13199 | 17143 | { |
---|
.. | .. |
---|
13217 | 17161 | |
---|
13218 | 17162 | return count; |
---|
13219 | 17163 | } |
---|
13220 | | - |
---|
13221 | 17164 | |
---|
13222 | 17165 | loff_t |
---|
13223 | 17166 | dhd_debugfs_lseek(struct file *file, loff_t off, int whence) |
---|
.. | .. |
---|
13244 | 17187 | .llseek = dhd_debugfs_lseek |
---|
13245 | 17188 | }; |
---|
13246 | 17189 | |
---|
13247 | | -static void dhd_dbg_create(void) |
---|
| 17190 | +static void dhd_dbgfs_create(void) |
---|
13248 | 17191 | { |
---|
13249 | 17192 | if (g_dbgfs.debugfs_dir) { |
---|
13250 | 17193 | g_dbgfs.debugfs_mem = debugfs_create_file("mem", 0644, g_dbgfs.debugfs_dir, |
---|
.. | .. |
---|
13252 | 17195 | } |
---|
13253 | 17196 | } |
---|
13254 | 17197 | |
---|
13255 | | -void dhd_dbg_init(dhd_pub_t *dhdp) |
---|
| 17198 | +void dhd_dbgfs_init(dhd_pub_t *dhdp) |
---|
13256 | 17199 | { |
---|
13257 | 17200 | g_dbgfs.dhdp = dhdp; |
---|
13258 | 17201 | g_dbgfs.size = 0x20000000; /* Allow access to various cores regs */ |
---|
.. | .. |
---|
13263 | 17206 | return; |
---|
13264 | 17207 | } |
---|
13265 | 17208 | |
---|
13266 | | - dhd_dbg_create(); |
---|
| 17209 | + dhd_dbgfs_create(); |
---|
13267 | 17210 | |
---|
13268 | 17211 | return; |
---|
13269 | 17212 | } |
---|
13270 | 17213 | |
---|
13271 | | -void dhd_dbg_remove(void) |
---|
| 17214 | +void dhd_dbgfs_remove(void) |
---|
13272 | 17215 | { |
---|
13273 | 17216 | debugfs_remove(g_dbgfs.debugfs_mem); |
---|
13274 | 17217 | debugfs_remove(g_dbgfs.debugfs_dir); |
---|
.. | .. |
---|
13276 | 17219 | bzero((unsigned char *) &g_dbgfs, sizeof(g_dbgfs)); |
---|
13277 | 17220 | } |
---|
13278 | 17221 | #endif /* BCMDBGFS */ |
---|
13279 | | - |
---|
13280 | | -#ifdef WLMEDIA_HTSF |
---|
13281 | | - |
---|
13282 | | -static |
---|
13283 | | -void dhd_htsf_addtxts(dhd_pub_t *dhdp, void *pktbuf) |
---|
13284 | | -{ |
---|
13285 | | - dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); |
---|
13286 | | - struct sk_buff *skb; |
---|
13287 | | - uint32 htsf = 0; |
---|
13288 | | - uint16 dport = 0, oldmagic = 0xACAC; |
---|
13289 | | - char *p1; |
---|
13290 | | - htsfts_t ts; |
---|
13291 | | - |
---|
13292 | | - /* timestamp packet */ |
---|
13293 | | - |
---|
13294 | | - p1 = (char*) PKTDATA(dhdp->osh, pktbuf); |
---|
13295 | | - |
---|
13296 | | - if (PKTLEN(dhdp->osh, pktbuf) > HTSF_MINLEN) { |
---|
13297 | | -/* memcpy(&proto, p1+26, 4); */ |
---|
13298 | | - memcpy(&dport, p1+40, 2); |
---|
13299 | | -/* proto = ((ntoh32(proto))>> 16) & 0xFF; */ |
---|
13300 | | - dport = ntoh16(dport); |
---|
13301 | | - } |
---|
13302 | | - |
---|
13303 | | - /* timestamp only if icmp or udb iperf with port 5555 */ |
---|
13304 | | -/* if (proto == 17 && dport == tsport) { */ |
---|
13305 | | - if (dport >= tsport && dport <= tsport + 20) { |
---|
13306 | | - |
---|
13307 | | - skb = (struct sk_buff *) pktbuf; |
---|
13308 | | - |
---|
13309 | | - htsf = dhd_get_htsf(dhd, 0); |
---|
13310 | | - memset(skb->data + 44, 0, 2); /* clear checksum */ |
---|
13311 | | - memcpy(skb->data+82, &oldmagic, 2); |
---|
13312 | | - memcpy(skb->data+84, &htsf, 4); |
---|
13313 | | - |
---|
13314 | | - memset(&ts, 0, sizeof(htsfts_t)); |
---|
13315 | | - ts.magic = HTSFMAGIC; |
---|
13316 | | - ts.prio = PKTPRIO(pktbuf); |
---|
13317 | | - ts.seqnum = htsf_seqnum++; |
---|
13318 | | - ts.c10 = get_cycles(); |
---|
13319 | | - ts.t10 = htsf; |
---|
13320 | | - ts.endmagic = HTSFENDMAGIC; |
---|
13321 | | - |
---|
13322 | | - memcpy(skb->data + HTSF_HOSTOFFSET, &ts, sizeof(ts)); |
---|
13323 | | - } |
---|
13324 | | -} |
---|
13325 | | - |
---|
13326 | | -static void dhd_dump_htsfhisto(histo_t *his, char *s) |
---|
13327 | | -{ |
---|
13328 | | - int pktcnt = 0, curval = 0, i; |
---|
13329 | | - for (i = 0; i < (NUMBIN-2); i++) { |
---|
13330 | | - curval += 500; |
---|
13331 | | - printf("%d ", his->bin[i]); |
---|
13332 | | - pktcnt += his->bin[i]; |
---|
13333 | | - } |
---|
13334 | | - printf(" max: %d TotPkt: %d neg: %d [%s]\n", his->bin[NUMBIN-2], pktcnt, |
---|
13335 | | - his->bin[NUMBIN-1], s); |
---|
13336 | | -} |
---|
13337 | | - |
---|
13338 | | -static |
---|
13339 | | -void sorttobin(int value, histo_t *histo) |
---|
13340 | | -{ |
---|
13341 | | - int i, binval = 0; |
---|
13342 | | - |
---|
13343 | | - if (value < 0) { |
---|
13344 | | - histo->bin[NUMBIN-1]++; |
---|
13345 | | - return; |
---|
13346 | | - } |
---|
13347 | | - if (value > histo->bin[NUMBIN-2]) /* store the max value */ |
---|
13348 | | - histo->bin[NUMBIN-2] = value; |
---|
13349 | | - |
---|
13350 | | - for (i = 0; i < (NUMBIN-2); i++) { |
---|
13351 | | - binval += 500; /* 500m s bins */ |
---|
13352 | | - if (value <= binval) { |
---|
13353 | | - histo->bin[i]++; |
---|
13354 | | - return; |
---|
13355 | | - } |
---|
13356 | | - } |
---|
13357 | | - histo->bin[NUMBIN-3]++; |
---|
13358 | | -} |
---|
13359 | | - |
---|
13360 | | -static |
---|
13361 | | -void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf) |
---|
13362 | | -{ |
---|
13363 | | - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; |
---|
13364 | | - struct sk_buff *skb; |
---|
13365 | | - char *p1; |
---|
13366 | | - uint16 old_magic; |
---|
13367 | | - int d1, d2, d3, end2end; |
---|
13368 | | - htsfts_t *htsf_ts; |
---|
13369 | | - uint32 htsf; |
---|
13370 | | - |
---|
13371 | | - skb = PKTTONATIVE(dhdp->osh, pktbuf); |
---|
13372 | | - p1 = (char*)PKTDATA(dhdp->osh, pktbuf); |
---|
13373 | | - |
---|
13374 | | - if (PKTLEN(osh, pktbuf) > HTSF_MINLEN) { |
---|
13375 | | - memcpy(&old_magic, p1+78, 2); |
---|
13376 | | - htsf_ts = (htsfts_t*) (p1 + HTSF_HOSTOFFSET - 4); |
---|
13377 | | - } else { |
---|
13378 | | - return; |
---|
13379 | | - } |
---|
13380 | | - if (htsf_ts->magic == HTSFMAGIC) { |
---|
13381 | | - htsf_ts->tE0 = dhd_get_htsf(dhd, 0); |
---|
13382 | | - htsf_ts->cE0 = get_cycles(); |
---|
13383 | | - } |
---|
13384 | | - |
---|
13385 | | - if (old_magic == 0xACAC) { |
---|
13386 | | - |
---|
13387 | | - tspktcnt++; |
---|
13388 | | - htsf = dhd_get_htsf(dhd, 0); |
---|
13389 | | - memcpy(skb->data+92, &htsf, sizeof(uint32)); |
---|
13390 | | - |
---|
13391 | | - memcpy(&ts[tsidx].t1, skb->data+80, 16); |
---|
13392 | | - |
---|
13393 | | - d1 = ts[tsidx].t2 - ts[tsidx].t1; |
---|
13394 | | - d2 = ts[tsidx].t3 - ts[tsidx].t2; |
---|
13395 | | - d3 = ts[tsidx].t4 - ts[tsidx].t3; |
---|
13396 | | - end2end = ts[tsidx].t4 - ts[tsidx].t1; |
---|
13397 | | - |
---|
13398 | | - sorttobin(d1, &vi_d1); |
---|
13399 | | - sorttobin(d2, &vi_d2); |
---|
13400 | | - sorttobin(d3, &vi_d3); |
---|
13401 | | - sorttobin(end2end, &vi_d4); |
---|
13402 | | - |
---|
13403 | | - if (end2end > 0 && end2end > maxdelay) { |
---|
13404 | | - maxdelay = end2end; |
---|
13405 | | - maxdelaypktno = tspktcnt; |
---|
13406 | | - memcpy(&maxdelayts, &ts[tsidx], 16); |
---|
13407 | | - } |
---|
13408 | | - if (++tsidx >= TSMAX) |
---|
13409 | | - tsidx = 0; |
---|
13410 | | - } |
---|
13411 | | -} |
---|
13412 | | - |
---|
13413 | | -uint32 dhd_get_htsf(dhd_info_t *dhd, int ifidx) |
---|
13414 | | -{ |
---|
13415 | | - uint32 htsf = 0, cur_cycle, delta, delta_us; |
---|
13416 | | - uint32 factor, baseval, baseval2; |
---|
13417 | | - cycles_t t; |
---|
13418 | | - |
---|
13419 | | - t = get_cycles(); |
---|
13420 | | - cur_cycle = t; |
---|
13421 | | - |
---|
13422 | | - if (cur_cycle > dhd->htsf.last_cycle) { |
---|
13423 | | - delta = cur_cycle - dhd->htsf.last_cycle; |
---|
13424 | | - } else { |
---|
13425 | | - delta = cur_cycle + (0xFFFFFFFF - dhd->htsf.last_cycle); |
---|
13426 | | - } |
---|
13427 | | - |
---|
13428 | | - delta = delta >> 4; |
---|
13429 | | - |
---|
13430 | | - if (dhd->htsf.coef) { |
---|
13431 | | - /* times ten to get the first digit */ |
---|
13432 | | - factor = (dhd->htsf.coef*10 + dhd->htsf.coefdec1); |
---|
13433 | | - baseval = (delta*10)/factor; |
---|
13434 | | - baseval2 = (delta*10)/(factor+1); |
---|
13435 | | - delta_us = (baseval - (((baseval - baseval2) * dhd->htsf.coefdec2)) / 10); |
---|
13436 | | - htsf = (delta_us << 4) + dhd->htsf.last_tsf + HTSF_BUS_DELAY; |
---|
13437 | | - } else { |
---|
13438 | | - DHD_ERROR(("-------dhd->htsf.coef = 0 -------\n")); |
---|
13439 | | - } |
---|
13440 | | - |
---|
13441 | | - return htsf; |
---|
13442 | | -} |
---|
13443 | | - |
---|
13444 | | -static void dhd_dump_latency(void) |
---|
13445 | | -{ |
---|
13446 | | - int i, max = 0; |
---|
13447 | | - int d1, d2, d3, d4, d5; |
---|
13448 | | - |
---|
13449 | | - printf("T1 T2 T3 T4 d1 d2 t4-t1 i \n"); |
---|
13450 | | - for (i = 0; i < TSMAX; i++) { |
---|
13451 | | - d1 = ts[i].t2 - ts[i].t1; |
---|
13452 | | - d2 = ts[i].t3 - ts[i].t2; |
---|
13453 | | - d3 = ts[i].t4 - ts[i].t3; |
---|
13454 | | - d4 = ts[i].t4 - ts[i].t1; |
---|
13455 | | - d5 = ts[max].t4-ts[max].t1; |
---|
13456 | | - if (d4 > d5 && d4 > 0) { |
---|
13457 | | - max = i; |
---|
13458 | | - } |
---|
13459 | | - printf("%08X %08X %08X %08X \t%d %d %d %d i=%d\n", |
---|
13460 | | - ts[i].t1, ts[i].t2, ts[i].t3, ts[i].t4, |
---|
13461 | | - d1, d2, d3, d4, i); |
---|
13462 | | - } |
---|
13463 | | - |
---|
13464 | | - printf("current idx = %d \n", tsidx); |
---|
13465 | | - |
---|
13466 | | - printf("Highest latency %d pkt no.%d total=%d\n", maxdelay, maxdelaypktno, tspktcnt); |
---|
13467 | | - printf("%08X %08X %08X %08X \t%d %d %d %d\n", |
---|
13468 | | - maxdelayts.t1, maxdelayts.t2, maxdelayts.t3, maxdelayts.t4, |
---|
13469 | | - maxdelayts.t2 - maxdelayts.t1, |
---|
13470 | | - maxdelayts.t3 - maxdelayts.t2, |
---|
13471 | | - maxdelayts.t4 - maxdelayts.t3, |
---|
13472 | | - maxdelayts.t4 - maxdelayts.t1); |
---|
13473 | | -} |
---|
13474 | | - |
---|
13475 | | - |
---|
13476 | | -static int |
---|
13477 | | -dhd_ioctl_htsf_get(dhd_info_t *dhd, int ifidx) |
---|
13478 | | -{ |
---|
13479 | | - char buf[32]; |
---|
13480 | | - int ret; |
---|
13481 | | - uint32 s1, s2; |
---|
13482 | | - |
---|
13483 | | - struct tsf { |
---|
13484 | | - uint32 low; |
---|
13485 | | - uint32 high; |
---|
13486 | | - } tsf_buf; |
---|
13487 | | - |
---|
13488 | | - memset(&tsf_buf, 0, sizeof(tsf_buf)); |
---|
13489 | | - |
---|
13490 | | - s1 = dhd_get_htsf(dhd, 0); |
---|
13491 | | - ret = dhd_iovar(&dhd->pub, ifidx, "tsf", NULL, 0, buf, sizeof(buf), FALSE); |
---|
13492 | | - if (ret < 0) { |
---|
13493 | | - if (ret == -EIO) { |
---|
13494 | | - DHD_ERROR(("%s: tsf is not supported by device\n", |
---|
13495 | | - dhd_ifname(&dhd->pub, ifidx))); |
---|
13496 | | - return -EOPNOTSUPP; |
---|
13497 | | - } |
---|
13498 | | - return ret; |
---|
13499 | | - } |
---|
13500 | | - s2 = dhd_get_htsf(dhd, 0); |
---|
13501 | | - |
---|
13502 | | - memcpy(&tsf_buf, buf, sizeof(tsf_buf)); |
---|
13503 | | - printf(" TSF_h=%04X lo=%08X Calc:htsf=%08X, coef=%d.%d%d delta=%d ", |
---|
13504 | | - tsf_buf.high, tsf_buf.low, s2, dhd->htsf.coef, dhd->htsf.coefdec1, |
---|
13505 | | - dhd->htsf.coefdec2, s2-tsf_buf.low); |
---|
13506 | | - printf("lasttsf=%08X lastcycle=%08X\n", dhd->htsf.last_tsf, dhd->htsf.last_cycle); |
---|
13507 | | - return 0; |
---|
13508 | | -} |
---|
13509 | | - |
---|
13510 | | -void htsf_update(dhd_info_t *dhd, void *data) |
---|
13511 | | -{ |
---|
13512 | | - static ulong cur_cycle = 0, prev_cycle = 0; |
---|
13513 | | - uint32 htsf, tsf_delta = 0; |
---|
13514 | | - uint32 hfactor = 0, cyc_delta, dec1 = 0, dec2, dec3, tmp; |
---|
13515 | | - ulong b, a; |
---|
13516 | | - cycles_t t; |
---|
13517 | | - |
---|
13518 | | - /* cycles_t in inlcude/mips/timex.h */ |
---|
13519 | | - |
---|
13520 | | - t = get_cycles(); |
---|
13521 | | - |
---|
13522 | | - prev_cycle = cur_cycle; |
---|
13523 | | - cur_cycle = t; |
---|
13524 | | - |
---|
13525 | | - if (cur_cycle > prev_cycle) |
---|
13526 | | - cyc_delta = cur_cycle - prev_cycle; |
---|
13527 | | - else { |
---|
13528 | | - b = cur_cycle; |
---|
13529 | | - a = prev_cycle; |
---|
13530 | | - cyc_delta = cur_cycle + (0xFFFFFFFF - prev_cycle); |
---|
13531 | | - } |
---|
13532 | | - |
---|
13533 | | - if (data == NULL) |
---|
13534 | | - printf(" tsf update ata point er is null \n"); |
---|
13535 | | - |
---|
13536 | | - memcpy(&prev_tsf, &cur_tsf, sizeof(tsf_t)); |
---|
13537 | | - memcpy(&cur_tsf, data, sizeof(tsf_t)); |
---|
13538 | | - |
---|
13539 | | - if (cur_tsf.low == 0) { |
---|
13540 | | - DHD_INFO((" ---- 0 TSF, do not update, return\n")); |
---|
13541 | | - return; |
---|
13542 | | - } |
---|
13543 | | - |
---|
13544 | | - if (cur_tsf.low > prev_tsf.low) |
---|
13545 | | - tsf_delta = (cur_tsf.low - prev_tsf.low); |
---|
13546 | | - else { |
---|
13547 | | - DHD_INFO((" ---- tsf low is smaller cur_tsf= %08X, prev_tsf=%08X, \n", |
---|
13548 | | - cur_tsf.low, prev_tsf.low)); |
---|
13549 | | - if (cur_tsf.high > prev_tsf.high) { |
---|
13550 | | - tsf_delta = cur_tsf.low + (0xFFFFFFFF - prev_tsf.low); |
---|
13551 | | - DHD_INFO((" ---- Wrap around tsf coutner adjusted TSF=%08X\n", tsf_delta)); |
---|
13552 | | - } else { |
---|
13553 | | - return; /* do not update */ |
---|
13554 | | - } |
---|
13555 | | - } |
---|
13556 | | - |
---|
13557 | | - if (tsf_delta) { |
---|
13558 | | - hfactor = cyc_delta / tsf_delta; |
---|
13559 | | - tmp = (cyc_delta - (hfactor * tsf_delta))*10; |
---|
13560 | | - dec1 = tmp/tsf_delta; |
---|
13561 | | - dec2 = ((tmp - dec1*tsf_delta)*10) / tsf_delta; |
---|
13562 | | - tmp = (tmp - (dec1*tsf_delta))*10; |
---|
13563 | | - dec3 = ((tmp - dec2*tsf_delta)*10) / tsf_delta; |
---|
13564 | | - |
---|
13565 | | - if (dec3 > 4) { |
---|
13566 | | - if (dec2 == 9) { |
---|
13567 | | - dec2 = 0; |
---|
13568 | | - if (dec1 == 9) { |
---|
13569 | | - dec1 = 0; |
---|
13570 | | - hfactor++; |
---|
13571 | | - } else { |
---|
13572 | | - dec1++; |
---|
13573 | | - } |
---|
13574 | | - } else { |
---|
13575 | | - dec2++; |
---|
13576 | | - } |
---|
13577 | | - } |
---|
13578 | | - } |
---|
13579 | | - |
---|
13580 | | - if (hfactor) { |
---|
13581 | | - htsf = ((cyc_delta * 10) / (hfactor*10+dec1)) + prev_tsf.low; |
---|
13582 | | - dhd->htsf.coef = hfactor; |
---|
13583 | | - dhd->htsf.last_cycle = cur_cycle; |
---|
13584 | | - dhd->htsf.last_tsf = cur_tsf.low; |
---|
13585 | | - dhd->htsf.coefdec1 = dec1; |
---|
13586 | | - dhd->htsf.coefdec2 = dec2; |
---|
13587 | | - } else { |
---|
13588 | | - htsf = prev_tsf.low; |
---|
13589 | | - } |
---|
13590 | | -} |
---|
13591 | | - |
---|
13592 | | -#endif /* WLMEDIA_HTSF */ |
---|
13593 | 17222 | |
---|
13594 | 17223 | #ifdef CUSTOM_SET_CPUCORE |
---|
13595 | 17224 | void dhd_set_cpucore(dhd_pub_t *dhd, int set) |
---|
.. | .. |
---|
13636 | 17265 | } while (e_rxf < 0); |
---|
13637 | 17266 | } |
---|
13638 | 17267 | #ifdef DHD_OF_SUPPORT |
---|
13639 | | - interrupt_set_cpucore(set); |
---|
| 17268 | + interrupt_set_cpucore(set, DPC_CPUCORE, PRIMARY_CPUCORE); |
---|
13640 | 17269 | #endif /* DHD_OF_SUPPORT */ |
---|
13641 | 17270 | DHD_TRACE(("%s: set(%d) cpucore success!\n", __FUNCTION__, set)); |
---|
13642 | 17271 | |
---|
.. | .. |
---|
13707 | 17336 | return 0; |
---|
13708 | 17337 | } |
---|
13709 | 17338 | |
---|
13710 | | -#ifdef DHD_FW_COREDUMP |
---|
| 17339 | +#ifdef DHD_RND_DEBUG |
---|
13711 | 17340 | |
---|
| 17341 | +#ifdef CUSTOMER_HW4_DEBUG |
---|
| 17342 | +#define RNDINFO PLATFORM_PATH".rnd" |
---|
| 17343 | +#elif defined(CUSTOMER_HW2) || defined(BOARD_HIKEY) |
---|
| 17344 | +#define RNDINFO "/data/misc/wifi/.rnd" |
---|
| 17345 | +#elif defined(OEM_ANDROID) && (defined(BOARD_PANDA) || defined(__ARM_ARCH_7A__)) |
---|
| 17346 | +#define RNDINFO "/data/misc/wifi/.rnd" |
---|
| 17347 | +#elif defined(OEM_ANDROID) |
---|
| 17348 | +#define RNDINFO_LIVE "/installmedia/.rnd" |
---|
| 17349 | +#define RNDINFO_INST "/data/.rnd" |
---|
| 17350 | +#define RNDINFO RNDINFO_LIVE |
---|
| 17351 | +#else /* FC19 and Others */ |
---|
| 17352 | +#define RNDINFO "/root/.rnd" |
---|
| 17353 | +#endif /* CUSTOMER_HW4_DEBUG */ |
---|
13712 | 17354 | |
---|
13713 | | -/* |
---|
13714 | | - * dhd_get_memdump_info is defined only for Android builds. |
---|
13715 | | - * The filename to store memdump is defined for CUSTOMER_HW4, |
---|
13716 | | - * for other platforms it will take default path "/installmedia/.memdump.info" |
---|
13717 | | - * New platforms can add their ifdefs accordingly below. |
---|
13718 | | - */ |
---|
13719 | | -#define MEMDUMPINFO "/installmedia/.memdump.info" |
---|
| 17355 | +#define RND_IN RNDINFO".in" |
---|
| 17356 | +#define RND_OUT RNDINFO".out" |
---|
13720 | 17357 | |
---|
13721 | | -void dhd_get_memdump_info(dhd_pub_t *dhd) |
---|
| 17358 | +int |
---|
| 17359 | +dhd_get_rnd_info(dhd_pub_t *dhd) |
---|
13722 | 17360 | { |
---|
13723 | 17361 | struct file *fp = NULL; |
---|
13724 | | - uint32 mem_val = DUMP_MEMFILE_MAX; |
---|
13725 | | - int ret = 0; |
---|
13726 | | - char *filepath = MEMDUMPINFO; |
---|
| 17362 | + int ret = BCME_ERROR; |
---|
| 17363 | + char *filepath = RND_IN; |
---|
| 17364 | + uint32 file_mode = O_RDONLY; |
---|
| 17365 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 17366 | + mm_segment_t old_fs; |
---|
| 17367 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 17368 | + loff_t pos = 0; |
---|
13727 | 17369 | |
---|
13728 | 17370 | /* Read memdump info from the file */ |
---|
13729 | | - fp = filp_open(filepath, O_RDONLY, 0); |
---|
| 17371 | + fp = filp_open(filepath, file_mode, 0); |
---|
13730 | 17372 | if (IS_ERR(fp)) { |
---|
13731 | | - DHD_ERROR(("[WIFI_SEC] %s: File [%s] doesn't exist\n", __FUNCTION__, filepath)); |
---|
13732 | | - goto done; |
---|
13733 | | - } else { |
---|
13734 | | -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) |
---|
13735 | | - loff_t zero = 0; |
---|
13736 | | - ret = kernel_read(fp, (void *) &mem_val, (size_t) 4, (loff_t *) &zero); |
---|
13737 | | -#else |
---|
13738 | | - ret = kernel_read(fp, 0, (char *)&mem_val, 4); |
---|
13739 | | -#endif |
---|
13740 | | - if (ret < 0) { |
---|
13741 | | - DHD_ERROR(("[WIFI_SEC] %s: File read error, ret=%d\n", __FUNCTION__, ret)); |
---|
13742 | | - filp_close(fp, NULL); |
---|
13743 | | - goto done; |
---|
| 17373 | + DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath)); |
---|
| 17374 | +#if defined(CONFIG_X86) && defined(OEM_ANDROID) |
---|
| 17375 | + /* Check if it is Live Brix Image */ |
---|
| 17376 | + if (bcmstrstr(filepath, RNDINFO_LIVE)) { |
---|
| 17377 | + goto err1; |
---|
13744 | 17378 | } |
---|
13745 | | - |
---|
13746 | | - mem_val = bcm_atoi((char *)&mem_val); |
---|
13747 | | - |
---|
13748 | | - DHD_ERROR(("[WIFI_SEC]%s: MEMDUMP ENABLED = %d\n", __FUNCTION__, mem_val)); |
---|
13749 | | - filp_close(fp, NULL); |
---|
| 17379 | + /* Try if it is Installed Brix Image */ |
---|
| 17380 | + filepath = RNDINFO_INST".in"; |
---|
| 17381 | + DHD_ERROR(("%s: Try File [%s]\n", __FUNCTION__, filepath)); |
---|
| 17382 | + fp = filp_open(filepath, file_mode, 0); |
---|
| 17383 | + if (IS_ERR(fp)) { |
---|
| 17384 | + DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath)); |
---|
| 17385 | + goto err1; |
---|
| 17386 | + } |
---|
| 17387 | +#else /* Non Brix Android platform */ |
---|
| 17388 | + goto err1; |
---|
| 17389 | +#endif /* CONFIG_X86 && OEM_ANDROID */ |
---|
13750 | 17390 | } |
---|
13751 | 17391 | |
---|
13752 | | -done: |
---|
13753 | | - /* |
---|
13754 | | - * The default behavior for Customer_hw4 is to disable the memdump |
---|
13755 | | - * But for Brix Android, default behavior is to collect memdump and crash the host. |
---|
13756 | | - * Other platforms can change the behavior accordingly by adding appropriate ifdefs |
---|
13757 | | - */ |
---|
13758 | | - dhd->memdump_enabled = (mem_val < DUMP_MEMFILE_MAX) ? mem_val : DUMP_MEMFILE_BUGON; |
---|
| 17392 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 17393 | + old_fs = get_fs(); |
---|
| 17394 | + set_fs(KERNEL_DS); |
---|
| 17395 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 17396 | + |
---|
| 17397 | + /* Handle success case */ |
---|
| 17398 | + ret = vfs_read(fp, (char *)&dhd->rnd_len, sizeof(dhd->rnd_len), &pos); |
---|
| 17399 | + if (ret < 0) { |
---|
| 17400 | + DHD_ERROR(("%s: rnd_len read error, ret=%d\n", __FUNCTION__, ret)); |
---|
| 17401 | + goto err2; |
---|
| 17402 | + } |
---|
| 17403 | + |
---|
| 17404 | + dhd->rnd_buf = MALLOCZ(dhd->osh, dhd->rnd_len); |
---|
| 17405 | + if (!dhd->rnd_buf) { |
---|
| 17406 | + DHD_ERROR(("%s: MALLOC failed\n", __FUNCTION__)); |
---|
| 17407 | + goto err2; |
---|
| 17408 | + } |
---|
| 17409 | + |
---|
| 17410 | + ret = vfs_read(fp, (char *)dhd->rnd_buf, dhd->rnd_len, &pos); |
---|
| 17411 | + if (ret < 0) { |
---|
| 17412 | + DHD_ERROR(("%s: rnd_buf read error, ret=%d\n", __FUNCTION__, ret)); |
---|
| 17413 | + goto err3; |
---|
| 17414 | + } |
---|
| 17415 | + |
---|
| 17416 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 17417 | + set_fs(old_fs); |
---|
| 17418 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 17419 | + filp_close(fp, NULL); |
---|
| 17420 | + |
---|
| 17421 | + DHD_ERROR(("%s: RND read from %s\n", __FUNCTION__, filepath)); |
---|
| 17422 | + return BCME_OK; |
---|
| 17423 | + |
---|
| 17424 | +err3: |
---|
| 17425 | + MFREE(dhd->osh, dhd->rnd_buf, dhd->rnd_len); |
---|
| 17426 | + dhd->rnd_buf = NULL; |
---|
| 17427 | +err2: |
---|
| 17428 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 17429 | + set_fs(old_fs); |
---|
| 17430 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 17431 | + filp_close(fp, NULL); |
---|
| 17432 | +err1: |
---|
| 17433 | + return BCME_ERROR; |
---|
13759 | 17434 | } |
---|
13760 | 17435 | |
---|
| 17436 | +int |
---|
| 17437 | +dhd_dump_rnd_info(dhd_pub_t *dhd, uint8 *rnd_buf, uint32 rnd_len) |
---|
| 17438 | +{ |
---|
| 17439 | + struct file *fp = NULL; |
---|
| 17440 | + int ret = BCME_OK; |
---|
| 17441 | + char *filepath = RND_OUT; |
---|
| 17442 | + uint32 file_mode = O_CREAT | O_WRONLY | O_SYNC; |
---|
| 17443 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 17444 | + mm_segment_t old_fs; |
---|
| 17445 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 17446 | + loff_t pos = 0; |
---|
| 17447 | + |
---|
| 17448 | + /* Read memdump info from the file */ |
---|
| 17449 | + fp = filp_open(filepath, file_mode, 0664); |
---|
| 17450 | + if (IS_ERR(fp)) { |
---|
| 17451 | + DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath)); |
---|
| 17452 | +#if defined(CONFIG_X86) && defined(OEM_ANDROID) |
---|
| 17453 | + /* Check if it is Live Brix Image */ |
---|
| 17454 | + if (bcmstrstr(filepath, RNDINFO_LIVE)) { |
---|
| 17455 | + goto err1; |
---|
| 17456 | + } |
---|
| 17457 | + /* Try if it is Installed Brix Image */ |
---|
| 17458 | + filepath = RNDINFO_INST".out"; |
---|
| 17459 | + DHD_ERROR(("%s: Try File [%s]\n", __FUNCTION__, filepath)); |
---|
| 17460 | + fp = filp_open(filepath, file_mode, 0664); |
---|
| 17461 | + if (IS_ERR(fp)) { |
---|
| 17462 | + DHD_ERROR(("%s: File [%s] doesn't exist\n", __FUNCTION__, filepath)); |
---|
| 17463 | + goto err1; |
---|
| 17464 | + } |
---|
| 17465 | +#else /* Non Brix Android platform */ |
---|
| 17466 | + goto err1; |
---|
| 17467 | +#endif /* CONFIG_X86 && OEM_ANDROID */ |
---|
| 17468 | + } |
---|
| 17469 | + |
---|
| 17470 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 17471 | + old_fs = get_fs(); |
---|
| 17472 | + set_fs(KERNEL_DS); |
---|
| 17473 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 17474 | + |
---|
| 17475 | + /* Handle success case */ |
---|
| 17476 | + ret = vfs_write(fp, (char *)&rnd_len, sizeof(rnd_len), &pos); |
---|
| 17477 | + if (ret < 0) { |
---|
| 17478 | + DHD_ERROR(("%s: rnd_len write error, ret=%d\n", __FUNCTION__, ret)); |
---|
| 17479 | + goto err2; |
---|
| 17480 | + } |
---|
| 17481 | + |
---|
| 17482 | + ret = vfs_write(fp, (char *)rnd_buf, rnd_len, &pos); |
---|
| 17483 | + if (ret < 0) { |
---|
| 17484 | + DHD_ERROR(("%s: rnd_buf write error, ret=%d\n", __FUNCTION__, ret)); |
---|
| 17485 | + goto err2; |
---|
| 17486 | + } |
---|
| 17487 | + |
---|
| 17488 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 17489 | + set_fs(old_fs); |
---|
| 17490 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 17491 | + filp_close(fp, NULL); |
---|
| 17492 | + DHD_ERROR(("%s: RND written to %s\n", __FUNCTION__, filepath)); |
---|
| 17493 | + return BCME_OK; |
---|
| 17494 | + |
---|
| 17495 | +err2: |
---|
| 17496 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 17497 | + set_fs(old_fs); |
---|
| 17498 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 17499 | + filp_close(fp, NULL); |
---|
| 17500 | +err1: |
---|
| 17501 | + return BCME_ERROR; |
---|
| 17502 | + |
---|
| 17503 | +} |
---|
| 17504 | +#endif /* DHD_RND_DEBUG */ |
---|
| 17505 | + |
---|
| 17506 | +#ifdef DHD_FW_COREDUMP |
---|
13761 | 17507 | void dhd_schedule_memdump(dhd_pub_t *dhdp, uint8 *buf, uint32 size) |
---|
13762 | 17508 | { |
---|
| 17509 | + unsigned long flags = 0; |
---|
13763 | 17510 | dhd_dump_t *dump = NULL; |
---|
| 17511 | + dhd_info_t *dhd_info = NULL; |
---|
| 17512 | +#if !defined(DHD_DUMP_FILE_WRITE_FROM_KERNEL) |
---|
| 17513 | + log_dump_type_t type = DLD_BUF_TYPE_ALL; |
---|
| 17514 | +#endif /* !DHD_DUMP_FILE_WRITE_FROM_KERNEL */ |
---|
| 17515 | + |
---|
| 17516 | + dhd_info = (dhd_info_t *)dhdp->info; |
---|
13764 | 17517 | dump = (dhd_dump_t *)MALLOC(dhdp->osh, sizeof(dhd_dump_t)); |
---|
13765 | 17518 | if (dump == NULL) { |
---|
13766 | 17519 | DHD_ERROR(("%s: dhd dump memory allocation failed\n", __FUNCTION__)); |
---|
.. | .. |
---|
13768 | 17521 | } |
---|
13769 | 17522 | dump->buf = buf; |
---|
13770 | 17523 | dump->bufsize = size; |
---|
| 17524 | +#ifdef BCMPCIE |
---|
| 17525 | + dhd_get_hscb_info(dhdp, (void*)(&dump->hscb_buf), |
---|
| 17526 | + (uint32 *)(&dump->hscb_bufsize)); |
---|
| 17527 | +#else /* BCMPCIE */ |
---|
| 17528 | + dump->hscb_bufsize = 0; |
---|
| 17529 | +#endif /* BCMPCIE */ |
---|
13771 | 17530 | |
---|
13772 | | -#if defined(CONFIG_ARM64) |
---|
13773 | | - DHD_ERROR(("%s: buf(va)=%llx, buf(pa)=%llx, bufsize=%d\n", __FUNCTION__, |
---|
13774 | | - (uint64)buf, (uint64)__virt_to_phys((ulong)buf), size)); |
---|
13775 | | -#elif defined(__ARM_ARCH_7A__) |
---|
13776 | | - DHD_ERROR(("%s: buf(va)=%x, buf(pa)=%x, bufsize=%d\n", __FUNCTION__, |
---|
13777 | | - (uint32)buf, (uint32)__virt_to_phys((ulong)buf), size)); |
---|
13778 | | -#endif /* __ARM_ARCH_7A__ */ |
---|
13779 | | - if (dhdp->memdump_enabled == DUMP_MEMONLY) { |
---|
| 17531 | +#ifdef DHD_LOG_DUMP |
---|
| 17532 | + dhd_print_buf_addr(dhdp, "memdump", buf, size); |
---|
| 17533 | +#if !defined(DHD_DUMP_FILE_WRITE_FROM_KERNEL) |
---|
| 17534 | + /* Print out buffer infomation */ |
---|
| 17535 | + dhd_log_dump_buf_addr(dhdp, &type); |
---|
| 17536 | +#endif /* !DHD_DUMP_FILE_WRITE_FROM_KERNEL */ |
---|
| 17537 | +#endif /* DHD_LOG_DUMP */ |
---|
| 17538 | + |
---|
| 17539 | + if (dhdp->memdump_enabled == DUMP_MEMONLY && (!disable_bug_on)) { |
---|
13780 | 17540 | BUG_ON(1); |
---|
13781 | 17541 | } |
---|
13782 | 17542 | |
---|
| 17543 | +#if defined(DEBUG_DNGL_INIT_FAIL) || defined(DHD_ERPOM) || \ |
---|
| 17544 | + defined(DNGL_AXI_ERROR_LOGGING) |
---|
| 17545 | + if ( |
---|
| 17546 | +#if defined(DEBUG_DNGL_INIT_FAIL) |
---|
| 17547 | + (dhdp->memdump_type == DUMP_TYPE_DONGLE_INIT_FAILURE) || |
---|
| 17548 | +#endif /* DEBUG_DNGL_INIT_FAIL */ |
---|
| 17549 | +#ifdef DHD_ERPOM |
---|
| 17550 | + (dhdp->memdump_type == DUMP_TYPE_DUE_TO_BT) || |
---|
| 17551 | +#endif /* DHD_ERPOM */ |
---|
| 17552 | +#ifdef DNGL_AXI_ERROR_LOGGING |
---|
| 17553 | + (dhdp->memdump_type == DUMP_TYPE_SMMU_FAULT) || |
---|
| 17554 | +#endif /* DNGL_AXI_ERROR_LOGGING */ |
---|
| 17555 | + FALSE) |
---|
| 17556 | + { |
---|
| 17557 | +#if defined(DHD_DUMP_FILE_WRITE_FROM_KERNEL) && defined(DHD_LOG_DUMP) |
---|
| 17558 | + log_dump_type_t *flush_type = NULL; |
---|
| 17559 | +#endif /* DHD_DUMP_FILE_WRITE_FROM_KERNEL && DHD_LOG_DUMP */ |
---|
| 17560 | + dhd_info->scheduled_memdump = FALSE; |
---|
| 17561 | + dhd_mem_dump((void *)dhdp->info, (void *)dump, 0); |
---|
| 17562 | +#if defined(DHD_DUMP_FILE_WRITE_FROM_KERNEL) && defined(DHD_LOG_DUMP) |
---|
| 17563 | + /* for dongle init fail cases, 'dhd_mem_dump' does |
---|
| 17564 | + * not call 'dhd_log_dump', so call it here. |
---|
| 17565 | + */ |
---|
| 17566 | + flush_type = MALLOCZ(dhdp->osh, |
---|
| 17567 | + sizeof(log_dump_type_t)); |
---|
| 17568 | + if (flush_type) { |
---|
| 17569 | + *flush_type = DLD_BUF_TYPE_ALL; |
---|
| 17570 | + DHD_ERROR(("%s: calling log dump.. \n", __FUNCTION__)); |
---|
| 17571 | + dhd_log_dump(dhdp->info, flush_type, 0); |
---|
| 17572 | + } |
---|
| 17573 | +#endif /* DHD_DUMP_FILE_WRITE_FROM_KERNEL && DHD_LOG_DUMP */ |
---|
| 17574 | + return; |
---|
| 17575 | + } |
---|
| 17576 | +#endif /* DEBUG_DNGL_INIT_FAIL || DHD_ERPOM || DNGL_AXI_ERROR_LOGGING */ |
---|
| 17577 | + |
---|
| 17578 | + dhd_info->scheduled_memdump = TRUE; |
---|
| 17579 | + /* bus busy bit for mem dump will be cleared in mem dump |
---|
| 17580 | + * work item context, after mem dump file is written |
---|
| 17581 | + */ |
---|
| 17582 | + DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 17583 | + DHD_BUS_BUSY_SET_IN_MEMDUMP(dhdp); |
---|
| 17584 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 17585 | + DHD_ERROR(("%s: scheduling mem dump.. \n", __FUNCTION__)); |
---|
13783 | 17586 | dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, (void *)dump, |
---|
13784 | | - DHD_WQ_WORK_SOC_RAM_DUMP, dhd_mem_dump, DHD_WORK_PRIORITY_HIGH); |
---|
| 17587 | + DHD_WQ_WORK_SOC_RAM_DUMP, dhd_mem_dump, DHD_WQ_WORK_PRIORITY_HIGH); |
---|
| 17588 | +} |
---|
| 17589 | +static void |
---|
| 17590 | +dhd_mem_dump(void *handle, void *event_info, u8 event) |
---|
| 17591 | +{ |
---|
| 17592 | + dhd_info_t *dhd = handle; |
---|
| 17593 | + dhd_pub_t *dhdp = NULL; |
---|
| 17594 | + unsigned long flags = 0; |
---|
| 17595 | + int ret = 0; |
---|
| 17596 | + dhd_dump_t *dump = NULL; |
---|
| 17597 | + |
---|
| 17598 | + DHD_ERROR(("%s: ENTER, memdump type %u\n", __FUNCTION__, dhd->pub.memdump_type)); |
---|
| 17599 | + |
---|
| 17600 | + if (!dhd) { |
---|
| 17601 | + DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); |
---|
| 17602 | + return; |
---|
| 17603 | + } |
---|
| 17604 | + |
---|
| 17605 | + dhdp = &dhd->pub; |
---|
| 17606 | + if (!dhdp) { |
---|
| 17607 | + DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__)); |
---|
| 17608 | + return; |
---|
| 17609 | + } |
---|
| 17610 | + |
---|
| 17611 | + DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 17612 | + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp)) { |
---|
| 17613 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 17614 | + DHD_ERROR(("%s: bus is down! can't collect mem dump. \n", __FUNCTION__)); |
---|
| 17615 | + ret = -ENODEV; |
---|
| 17616 | + goto exit; |
---|
| 17617 | + } |
---|
| 17618 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 17619 | + |
---|
| 17620 | +#ifdef DHD_SSSR_DUMP |
---|
| 17621 | + if (dhdp->sssr_inited && dhdp->collect_sssr) { |
---|
| 17622 | + dhdpcie_sssr_dump(dhdp); |
---|
| 17623 | + } |
---|
| 17624 | + dhdp->collect_sssr = FALSE; |
---|
| 17625 | +#endif /* DHD_SSSR_DUMP */ |
---|
| 17626 | +#if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT) |
---|
| 17627 | + dhd_wait_for_file_dump(dhdp); |
---|
| 17628 | +#endif /* WL_CFG80211 && DHD_FILE_DUMP_EVENT */ |
---|
| 17629 | + |
---|
| 17630 | + dump = (dhd_dump_t *)event_info; |
---|
| 17631 | + if (!dump) { |
---|
| 17632 | + DHD_ERROR(("%s: dump is NULL\n", __FUNCTION__)); |
---|
| 17633 | + ret = -EINVAL; |
---|
| 17634 | + goto exit; |
---|
| 17635 | + } |
---|
| 17636 | + |
---|
| 17637 | + /* |
---|
| 17638 | + * If kernel does not have file write access enabled |
---|
| 17639 | + * then skip writing dumps to files. |
---|
| 17640 | + * The dumps will be pushed to HAL layer which will |
---|
| 17641 | + * write into files |
---|
| 17642 | + */ |
---|
| 17643 | +#ifdef DHD_DUMP_FILE_WRITE_FROM_KERNEL |
---|
| 17644 | + |
---|
| 17645 | + if (write_dump_to_file(&dhd->pub, dump->buf, dump->bufsize, "mem_dump")) { |
---|
| 17646 | + DHD_ERROR(("%s: writing SoC_RAM dump to the file failed\n", __FUNCTION__)); |
---|
| 17647 | +#ifdef DHD_DEBUG_UART |
---|
| 17648 | + dhd->pub.memdump_success = FALSE; |
---|
| 17649 | +#endif /* DHD_DEBUG_UART */ |
---|
| 17650 | + } |
---|
| 17651 | + |
---|
| 17652 | + /* directly call dhd_log_dump for debug_dump collection from the mem_dump work queue |
---|
| 17653 | + * context, no need to schedule another work queue for log dump. In case of |
---|
| 17654 | + * user initiated DEBUG_DUMP wpa_cli command (DUMP_TYPE_BY_SYSDUMP), |
---|
| 17655 | + * cfg layer is itself scheduling the log_dump work queue. |
---|
| 17656 | + * that path is not disturbed. If 'dhd_mem_dump' is called directly then we will not |
---|
| 17657 | + * collect debug_dump as it may be called from non-sleepable context. |
---|
| 17658 | + */ |
---|
| 17659 | +#ifdef DHD_LOG_DUMP |
---|
| 17660 | + if (dhd->scheduled_memdump && |
---|
| 17661 | + dhdp->memdump_type != DUMP_TYPE_BY_SYSDUMP) { |
---|
| 17662 | + log_dump_type_t *flush_type = MALLOCZ(dhdp->osh, |
---|
| 17663 | + sizeof(log_dump_type_t)); |
---|
| 17664 | + if (flush_type) { |
---|
| 17665 | + *flush_type = DLD_BUF_TYPE_ALL; |
---|
| 17666 | + DHD_ERROR(("%s: calling log dump.. \n", __FUNCTION__)); |
---|
| 17667 | + dhd_log_dump(dhd, flush_type, 0); |
---|
| 17668 | + } |
---|
| 17669 | + } |
---|
| 17670 | +#endif /* DHD_LOG_DUMP */ |
---|
| 17671 | + |
---|
| 17672 | +#ifdef DHD_PKT_LOGGING |
---|
| 17673 | + copy_debug_dump_time(dhdp->debug_dump_time_pktlog_str, dhdp->debug_dump_time_str); |
---|
| 17674 | +#endif /* DHD_PKT_LOGGING */ |
---|
| 17675 | + clear_debug_dump_time(dhdp->debug_dump_time_str); |
---|
| 17676 | + |
---|
| 17677 | + /* before calling bug on, wait for other logs to be dumped. |
---|
| 17678 | + * we cannot wait in case dhd_mem_dump is called directly |
---|
| 17679 | + * as it may not be in a sleepable context |
---|
| 17680 | + */ |
---|
| 17681 | + if (dhd->scheduled_memdump) { |
---|
| 17682 | + uint bitmask = 0; |
---|
| 17683 | + int timeleft = 0; |
---|
| 17684 | +#ifdef DHD_SSSR_DUMP |
---|
| 17685 | + bitmask |= DHD_BUS_BUSY_IN_SSSRDUMP; |
---|
| 17686 | +#endif // endif |
---|
| 17687 | + if (bitmask != 0) { |
---|
| 17688 | + DHD_ERROR(("%s: wait to clear dhd_bus_busy_state: 0x%x\n", |
---|
| 17689 | + __FUNCTION__, dhdp->dhd_bus_busy_state)); |
---|
| 17690 | + timeleft = dhd_os_busbusy_wait_bitmask(dhdp, |
---|
| 17691 | + &dhdp->dhd_bus_busy_state, bitmask, 0); |
---|
| 17692 | + if ((timeleft == 0) || (timeleft == 1)) { |
---|
| 17693 | + DHD_ERROR(("%s: Timed out dhd_bus_busy_state=0x%x\n", |
---|
| 17694 | + __FUNCTION__, dhdp->dhd_bus_busy_state)); |
---|
| 17695 | + } |
---|
| 17696 | + } |
---|
| 17697 | + } |
---|
| 17698 | + |
---|
| 17699 | + if (dump->hscb_buf && dump->hscb_bufsize) { |
---|
| 17700 | + DHD_ERROR(("%s: write HSCB dump... \n", __FUNCTION__)); |
---|
| 17701 | + if (write_dump_to_file(&dhd->pub, dump->hscb_buf, |
---|
| 17702 | + dump->hscb_bufsize, "mem_dump_hscb")) { |
---|
| 17703 | + DHD_ERROR(("%s: writing HSCB dump to the file failed\n", __FUNCTION__)); |
---|
| 17704 | +#ifdef DHD_DEBUG_UART |
---|
| 17705 | + dhd->pub.memdump_success = FALSE; |
---|
| 17706 | +#endif /* DHD_DEBUG_UART */ |
---|
| 17707 | + } |
---|
| 17708 | + } |
---|
| 17709 | +#endif /* DHD_DUMP_FILE_WRITE_FROM_KERNEL */ |
---|
| 17710 | + |
---|
| 17711 | + DHD_ERROR(("%s: memdump type %u\n", __FUNCTION__, dhd->pub.memdump_type)); |
---|
| 17712 | + if (dhd->pub.memdump_enabled == DUMP_MEMFILE_BUGON && |
---|
| 17713 | +#ifdef DHD_LOG_DUMP |
---|
| 17714 | + dhd->pub.memdump_type != DUMP_TYPE_BY_SYSDUMP && |
---|
| 17715 | +#endif /* DHD_LOG_DUMP */ |
---|
| 17716 | + dhd->pub.memdump_type != DUMP_TYPE_BY_USER && |
---|
| 17717 | +#ifdef DHD_DEBUG_UART |
---|
| 17718 | + dhd->pub.memdump_success == TRUE && |
---|
| 17719 | +#endif /* DHD_DEBUG_UART */ |
---|
| 17720 | +#ifdef DNGL_EVENT_SUPPORT |
---|
| 17721 | + dhd->pub.memdump_type != DUMP_TYPE_DONGLE_HOST_EVENT && |
---|
| 17722 | +#endif /* DNGL_EVENT_SUPPORT */ |
---|
| 17723 | + dhd->pub.memdump_type != DUMP_TYPE_CFG_VENDOR_TRIGGERED) { |
---|
| 17724 | + |
---|
| 17725 | +#ifdef SHOW_LOGTRACE |
---|
| 17726 | + /* Wait till logtrace context is flushed */ |
---|
| 17727 | + dhd_flush_logtrace_process(dhd); |
---|
| 17728 | +#endif /* SHOW_LOGTRACE */ |
---|
| 17729 | + |
---|
| 17730 | + DHD_ERROR(("%s: call BUG_ON \n", __FUNCTION__)); |
---|
| 17731 | + if (!disable_bug_on) { |
---|
| 17732 | + BUG_ON(1); |
---|
| 17733 | + } |
---|
| 17734 | + } |
---|
| 17735 | + DHD_ERROR(("%s: No BUG ON, memdump type %u \n", __FUNCTION__, dhd->pub.memdump_type)); |
---|
| 17736 | + |
---|
| 17737 | +exit: |
---|
| 17738 | + if (dump) { |
---|
| 17739 | + MFREE(dhd->pub.osh, dump, sizeof(dhd_dump_t)); |
---|
| 17740 | + } |
---|
| 17741 | + DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 17742 | + DHD_BUS_BUSY_CLEAR_IN_MEMDUMP(&dhd->pub); |
---|
| 17743 | + dhd_os_busbusy_wake(dhdp); |
---|
| 17744 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 17745 | + dhd->scheduled_memdump = FALSE; |
---|
| 17746 | +#ifdef OEM_ANDROID |
---|
| 17747 | + if (dhdp->hang_was_pending) { |
---|
| 17748 | + DHD_ERROR(("%s: Send pending HANG event...\n", __FUNCTION__)); |
---|
| 17749 | + dhd_os_send_hang_message(dhdp); |
---|
| 17750 | + dhdp->hang_was_pending = 0; |
---|
| 17751 | + } |
---|
| 17752 | +#endif /* OEM_ANDROID */ |
---|
| 17753 | + DHD_ERROR(("%s: EXIT %d\n", __FUNCTION__, ret)); |
---|
| 17754 | + return; |
---|
| 17755 | +} |
---|
| 17756 | +#endif /* DHD_FW_COREDUMP */ |
---|
| 17757 | + |
---|
| 17758 | +#ifdef DHD_SSSR_DUMP |
---|
| 17759 | +int |
---|
| 17760 | +dhd_sssr_dump_dig_buf_before(void *dev, const void *user_buf, uint32 len) |
---|
| 17761 | +{ |
---|
| 17762 | + dhd_info_t *dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 17763 | + dhd_pub_t *dhdp = &dhd_info->pub; |
---|
| 17764 | + int pos = 0, ret = BCME_ERROR; |
---|
| 17765 | + uint dig_buf_size = 0; |
---|
| 17766 | + |
---|
| 17767 | + if (dhdp->sssr_reg_info.vasip_regs.vasip_sr_size) { |
---|
| 17768 | + dig_buf_size = dhdp->sssr_reg_info.vasip_regs.vasip_sr_size; |
---|
| 17769 | + } else if ((dhdp->sssr_reg_info.length > OFFSETOF(sssr_reg_info_v1_t, dig_mem_info)) && |
---|
| 17770 | + dhdp->sssr_reg_info.dig_mem_info.dig_sr_size) { |
---|
| 17771 | + dig_buf_size = dhdp->sssr_reg_info.dig_mem_info.dig_sr_size; |
---|
| 17772 | + } |
---|
| 17773 | + |
---|
| 17774 | + if (dhdp->sssr_dig_buf_before && (dhdp->sssr_dump_mode == SSSR_DUMP_MODE_SSSR)) { |
---|
| 17775 | + ret = dhd_export_debug_data((char *)dhdp->sssr_dig_buf_before, |
---|
| 17776 | + NULL, user_buf, dig_buf_size, &pos); |
---|
| 17777 | + } |
---|
| 17778 | + return ret; |
---|
13785 | 17779 | } |
---|
13786 | 17780 | |
---|
13787 | | -int dhd_os_socram_dump(struct net_device *dev, uint32 *dump_size) |
---|
| 17781 | +int |
---|
| 17782 | +dhd_sssr_dump_dig_buf_after(void *dev, const void *user_buf, uint32 len) |
---|
| 17783 | +{ |
---|
| 17784 | + dhd_info_t *dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 17785 | + dhd_pub_t *dhdp = &dhd_info->pub; |
---|
| 17786 | + int pos = 0, ret = BCME_ERROR; |
---|
| 17787 | + uint dig_buf_size = 0; |
---|
| 17788 | + |
---|
| 17789 | + if (dhdp->sssr_reg_info.vasip_regs.vasip_sr_size) { |
---|
| 17790 | + dig_buf_size = dhdp->sssr_reg_info.vasip_regs.vasip_sr_size; |
---|
| 17791 | + } else if ((dhdp->sssr_reg_info.length > OFFSETOF(sssr_reg_info_v1_t, dig_mem_info)) && |
---|
| 17792 | + dhdp->sssr_reg_info.dig_mem_info.dig_sr_size) { |
---|
| 17793 | + dig_buf_size = dhdp->sssr_reg_info.dig_mem_info.dig_sr_size; |
---|
| 17794 | + } |
---|
| 17795 | + |
---|
| 17796 | + if (dhdp->sssr_dig_buf_after) { |
---|
| 17797 | + ret = dhd_export_debug_data((char *)dhdp->sssr_dig_buf_after, |
---|
| 17798 | + NULL, user_buf, dig_buf_size, &pos); |
---|
| 17799 | + } |
---|
| 17800 | + return ret; |
---|
| 17801 | +} |
---|
| 17802 | + |
---|
| 17803 | +int |
---|
| 17804 | +dhd_sssr_dump_d11_buf_before(void *dev, const void *user_buf, uint32 len, int core) |
---|
| 17805 | +{ |
---|
| 17806 | + dhd_info_t *dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 17807 | + dhd_pub_t *dhdp = &dhd_info->pub; |
---|
| 17808 | + int pos = 0, ret = BCME_ERROR; |
---|
| 17809 | + |
---|
| 17810 | + if (dhdp->sssr_d11_before[core] && |
---|
| 17811 | + dhdp->sssr_d11_outofreset[core] && |
---|
| 17812 | + (dhdp->sssr_dump_mode == SSSR_DUMP_MODE_SSSR)) { |
---|
| 17813 | + ret = dhd_export_debug_data((char *)dhdp->sssr_d11_before[core], |
---|
| 17814 | + NULL, user_buf, len, &pos); |
---|
| 17815 | + } |
---|
| 17816 | + return ret; |
---|
| 17817 | +} |
---|
| 17818 | + |
---|
| 17819 | +int |
---|
| 17820 | +dhd_sssr_dump_d11_buf_after(void *dev, const void *user_buf, uint32 len, int core) |
---|
| 17821 | +{ |
---|
| 17822 | + dhd_info_t *dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 17823 | + dhd_pub_t *dhdp = &dhd_info->pub; |
---|
| 17824 | + int pos = 0, ret = BCME_ERROR; |
---|
| 17825 | + |
---|
| 17826 | + if (dhdp->sssr_d11_after[core] && |
---|
| 17827 | + dhdp->sssr_d11_outofreset[core]) { |
---|
| 17828 | + ret = dhd_export_debug_data((char *)dhdp->sssr_d11_after[core], |
---|
| 17829 | + NULL, user_buf, len, &pos); |
---|
| 17830 | + } |
---|
| 17831 | + return ret; |
---|
| 17832 | +} |
---|
| 17833 | + |
---|
| 17834 | +static void |
---|
| 17835 | +dhd_sssr_dump_to_file(dhd_info_t* dhdinfo) |
---|
| 17836 | +{ |
---|
| 17837 | + dhd_info_t *dhd = dhdinfo; |
---|
| 17838 | + dhd_pub_t *dhdp; |
---|
| 17839 | + int i; |
---|
| 17840 | + char before_sr_dump[128]; |
---|
| 17841 | + char after_sr_dump[128]; |
---|
| 17842 | + unsigned long flags = 0; |
---|
| 17843 | + uint dig_buf_size = 0; |
---|
| 17844 | + |
---|
| 17845 | + DHD_ERROR(("%s: ENTER \n", __FUNCTION__)); |
---|
| 17846 | + |
---|
| 17847 | + if (!dhd) { |
---|
| 17848 | + DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); |
---|
| 17849 | + return; |
---|
| 17850 | + } |
---|
| 17851 | + |
---|
| 17852 | + dhdp = &dhd->pub; |
---|
| 17853 | + |
---|
| 17854 | + DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 17855 | + DHD_BUS_BUSY_SET_IN_SSSRDUMP(dhdp); |
---|
| 17856 | + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp)) { |
---|
| 17857 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 17858 | + DHD_ERROR(("%s: bus is down! can't collect sssr dump. \n", __FUNCTION__)); |
---|
| 17859 | + goto exit; |
---|
| 17860 | + } |
---|
| 17861 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 17862 | + |
---|
| 17863 | + for (i = 0; i < MAX_NUM_D11CORES; i++) { |
---|
| 17864 | + /* Init file name */ |
---|
| 17865 | + memset(before_sr_dump, 0, sizeof(before_sr_dump)); |
---|
| 17866 | + memset(after_sr_dump, 0, sizeof(after_sr_dump)); |
---|
| 17867 | + |
---|
| 17868 | + snprintf(before_sr_dump, sizeof(before_sr_dump), "%s_%d_%s", |
---|
| 17869 | + "sssr_dump_core", i, "before_SR"); |
---|
| 17870 | + snprintf(after_sr_dump, sizeof(after_sr_dump), "%s_%d_%s", |
---|
| 17871 | + "sssr_dump_core", i, "after_SR"); |
---|
| 17872 | + |
---|
| 17873 | + if (dhdp->sssr_d11_before[i] && dhdp->sssr_d11_outofreset[i] && |
---|
| 17874 | + (dhdp->sssr_dump_mode == SSSR_DUMP_MODE_SSSR)) { |
---|
| 17875 | + if (write_dump_to_file(dhdp, (uint8 *)dhdp->sssr_d11_before[i], |
---|
| 17876 | + dhdp->sssr_reg_info.mac_regs[i].sr_size, before_sr_dump)) { |
---|
| 17877 | + DHD_ERROR(("%s: writing SSSR MAIN dump before to the file failed\n", |
---|
| 17878 | + __FUNCTION__)); |
---|
| 17879 | + } |
---|
| 17880 | + } |
---|
| 17881 | + if (dhdp->sssr_d11_after[i] && dhdp->sssr_d11_outofreset[i]) { |
---|
| 17882 | + if (write_dump_to_file(dhdp, (uint8 *)dhdp->sssr_d11_after[i], |
---|
| 17883 | + dhdp->sssr_reg_info.mac_regs[i].sr_size, after_sr_dump)) { |
---|
| 17884 | + DHD_ERROR(("%s: writing SSSR AUX dump after to the file failed\n", |
---|
| 17885 | + __FUNCTION__)); |
---|
| 17886 | + } |
---|
| 17887 | + } |
---|
| 17888 | + } |
---|
| 17889 | + |
---|
| 17890 | + if (dhdp->sssr_reg_info.vasip_regs.vasip_sr_size) { |
---|
| 17891 | + dig_buf_size = dhdp->sssr_reg_info.vasip_regs.vasip_sr_size; |
---|
| 17892 | + } else if ((dhdp->sssr_reg_info.length > OFFSETOF(sssr_reg_info_v1_t, dig_mem_info)) && |
---|
| 17893 | + dhdp->sssr_reg_info.dig_mem_info.dig_sr_size) { |
---|
| 17894 | + dig_buf_size = dhdp->sssr_reg_info.dig_mem_info.dig_sr_size; |
---|
| 17895 | + } |
---|
| 17896 | + |
---|
| 17897 | + if (dhdp->sssr_dig_buf_before && (dhdp->sssr_dump_mode == SSSR_DUMP_MODE_SSSR)) { |
---|
| 17898 | + if (write_dump_to_file(dhdp, (uint8 *)dhdp->sssr_dig_buf_before, |
---|
| 17899 | + dig_buf_size, "sssr_dump_dig_before_SR")) { |
---|
| 17900 | + DHD_ERROR(("%s: writing SSSR Dig dump before to the file failed\n", |
---|
| 17901 | + __FUNCTION__)); |
---|
| 17902 | + } |
---|
| 17903 | + } |
---|
| 17904 | + |
---|
| 17905 | + if (dhdp->sssr_dig_buf_after) { |
---|
| 17906 | + if (write_dump_to_file(dhdp, (uint8 *)dhdp->sssr_dig_buf_after, |
---|
| 17907 | + dig_buf_size, "sssr_dump_dig_after_SR")) { |
---|
| 17908 | + DHD_ERROR(("%s: writing SSSR Dig VASIP dump after to the file failed\n", |
---|
| 17909 | + __FUNCTION__)); |
---|
| 17910 | + } |
---|
| 17911 | + } |
---|
| 17912 | + |
---|
| 17913 | +exit: |
---|
| 17914 | + DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 17915 | + DHD_BUS_BUSY_CLEAR_IN_SSSRDUMP(dhdp); |
---|
| 17916 | + dhd_os_busbusy_wake(dhdp); |
---|
| 17917 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 17918 | +} |
---|
| 17919 | + |
---|
| 17920 | +void |
---|
| 17921 | +dhd_write_sssr_dump(dhd_pub_t *dhdp, uint32 dump_mode) |
---|
| 17922 | +{ |
---|
| 17923 | + dhdp->sssr_dump_mode = dump_mode; |
---|
| 17924 | + |
---|
| 17925 | + /* |
---|
| 17926 | + * If kernel does not have file write access enabled |
---|
| 17927 | + * then skip writing dumps to files. |
---|
| 17928 | + * The dumps will be pushed to HAL layer which will |
---|
| 17929 | + * write into files |
---|
| 17930 | + */ |
---|
| 17931 | +#if !defined(DHD_DUMP_FILE_WRITE_FROM_KERNEL) |
---|
| 17932 | + return; |
---|
| 17933 | +#endif /* !DHD_DUMP_FILE_WRITE_FROM_KERNEL */ |
---|
| 17934 | + |
---|
| 17935 | + /* |
---|
| 17936 | + * dhd_mem_dump -> dhd_sssr_dump -> dhd_write_sssr_dump |
---|
| 17937 | + * Without workqueue - |
---|
| 17938 | + * DUMP_TYPE_DONGLE_INIT_FAILURE/DUMP_TYPE_DUE_TO_BT/DUMP_TYPE_SMMU_FAULT |
---|
| 17939 | + * : These are called in own handler, not in the interrupt context |
---|
| 17940 | + * With workqueue - all other DUMP_TYPEs : dhd_mem_dump is called in workqueue |
---|
| 17941 | + * Thus, it doesn't neeed to dump SSSR in workqueue |
---|
| 17942 | + */ |
---|
| 17943 | + DHD_ERROR(("%s: writing sssr dump to file... \n", __FUNCTION__)); |
---|
| 17944 | + dhd_sssr_dump_to_file(dhdp->info); |
---|
| 17945 | + |
---|
| 17946 | +} |
---|
| 17947 | +#endif /* DHD_SSSR_DUMP */ |
---|
| 17948 | + |
---|
| 17949 | +#ifdef DHD_LOG_DUMP |
---|
| 17950 | +static void |
---|
| 17951 | +dhd_log_dump(void *handle, void *event_info, u8 event) |
---|
| 17952 | +{ |
---|
| 17953 | + dhd_info_t *dhd = handle; |
---|
| 17954 | + log_dump_type_t *type = (log_dump_type_t *)event_info; |
---|
| 17955 | + |
---|
| 17956 | + if (!dhd || !type) { |
---|
| 17957 | + DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); |
---|
| 17958 | + return; |
---|
| 17959 | + } |
---|
| 17960 | + |
---|
| 17961 | +#ifdef WL_CFG80211 |
---|
| 17962 | + /* flush the fw side logs */ |
---|
| 17963 | + wl_flush_fw_log_buffer(dhd_linux_get_primary_netdev(&dhd->pub), |
---|
| 17964 | + FW_LOGSET_MASK_ALL); |
---|
| 17965 | +#endif // endif |
---|
| 17966 | + /* there are currently 3 possible contexts from which |
---|
| 17967 | + * log dump can be scheduled - |
---|
| 17968 | + * 1.TRAP 2.supplicant DEBUG_DUMP pvt driver command |
---|
| 17969 | + * 3.HEALTH CHECK event |
---|
| 17970 | + * The concise debug info buffer is a shared resource |
---|
| 17971 | + * and in case a trap is one of the contexts then both the |
---|
| 17972 | + * scheduled work queues need to run because trap data is |
---|
| 17973 | + * essential for debugging. Hence a mutex lock is acquired |
---|
| 17974 | + * before calling do_dhd_log_dump(). |
---|
| 17975 | + */ |
---|
| 17976 | + DHD_ERROR(("%s: calling log dump.. \n", __FUNCTION__)); |
---|
| 17977 | + dhd_os_logdump_lock(&dhd->pub); |
---|
| 17978 | + DHD_OS_WAKE_LOCK(&dhd->pub); |
---|
| 17979 | + if (do_dhd_log_dump(&dhd->pub, type) != BCME_OK) { |
---|
| 17980 | + DHD_ERROR(("%s: writing debug dump to the file failed\n", __FUNCTION__)); |
---|
| 17981 | + } |
---|
| 17982 | + DHD_OS_WAKE_UNLOCK(&dhd->pub); |
---|
| 17983 | + dhd_os_logdump_unlock(&dhd->pub); |
---|
| 17984 | +} |
---|
| 17985 | + |
---|
| 17986 | +void dhd_schedule_log_dump(dhd_pub_t *dhdp, void *type) |
---|
| 17987 | +{ |
---|
| 17988 | + DHD_ERROR(("%s: scheduling log dump.. \n", __FUNCTION__)); |
---|
| 17989 | + dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, |
---|
| 17990 | + type, DHD_WQ_WORK_DHD_LOG_DUMP, |
---|
| 17991 | + dhd_log_dump, DHD_WQ_WORK_PRIORITY_HIGH); |
---|
| 17992 | +} |
---|
| 17993 | + |
---|
| 17994 | +static void |
---|
| 17995 | +dhd_print_buf_addr(dhd_pub_t *dhdp, char *name, void *buf, unsigned int size) |
---|
| 17996 | +{ |
---|
| 17997 | + if ((dhdp->memdump_enabled == DUMP_MEMONLY) || |
---|
| 17998 | + (dhdp->memdump_enabled == DUMP_MEMFILE_BUGON) || |
---|
| 17999 | + (dhdp->memdump_type == DUMP_TYPE_SMMU_FAULT)) { |
---|
| 18000 | +#if defined(CONFIG_ARM64) |
---|
| 18001 | + DHD_ERROR(("-------- %s: buf(va)=%llx, buf(pa)=%llx, bufsize=%d\n", |
---|
| 18002 | + name, (uint64)buf, (uint64)__virt_to_phys((ulong)buf), size)); |
---|
| 18003 | +#elif defined(__ARM_ARCH_7A__) |
---|
| 18004 | + DHD_ERROR(("-------- %s: buf(va)=%x, buf(pa)=%x, bufsize=%d\n", |
---|
| 18005 | + name, (uint32)buf, (uint32)__virt_to_phys((ulong)buf), size)); |
---|
| 18006 | +#endif /* __ARM_ARCH_7A__ */ |
---|
| 18007 | + } |
---|
| 18008 | +} |
---|
| 18009 | + |
---|
| 18010 | +static void |
---|
| 18011 | +dhd_log_dump_buf_addr(dhd_pub_t *dhdp, log_dump_type_t *type) |
---|
| 18012 | +{ |
---|
| 18013 | + int i; |
---|
| 18014 | + unsigned long wr_size = 0; |
---|
| 18015 | + struct dhd_log_dump_buf *dld_buf = &g_dld_buf[0]; |
---|
| 18016 | + size_t log_size = 0; |
---|
| 18017 | + char buf_name[DHD_PRINT_BUF_NAME_LEN]; |
---|
| 18018 | + dhd_dbg_ring_t *ring = NULL; |
---|
| 18019 | + |
---|
| 18020 | + BCM_REFERENCE(ring); |
---|
| 18021 | + |
---|
| 18022 | + for (i = 0; i < DLD_BUFFER_NUM; i++) { |
---|
| 18023 | + dld_buf = &g_dld_buf[i]; |
---|
| 18024 | + log_size = (unsigned long)dld_buf->max - |
---|
| 18025 | + (unsigned long)dld_buf->buffer; |
---|
| 18026 | + if (dld_buf->wraparound) { |
---|
| 18027 | + wr_size = log_size; |
---|
| 18028 | + } else { |
---|
| 18029 | + wr_size = (unsigned long)dld_buf->present - |
---|
| 18030 | + (unsigned long)dld_buf->front; |
---|
| 18031 | + } |
---|
| 18032 | + scnprintf(buf_name, sizeof(buf_name), "dlb_buf[%d]", i); |
---|
| 18033 | + dhd_print_buf_addr(dhdp, buf_name, dld_buf, dld_buf_size[i]); |
---|
| 18034 | + scnprintf(buf_name, sizeof(buf_name), "dlb_buf[%d] buffer", i); |
---|
| 18035 | + dhd_print_buf_addr(dhdp, buf_name, dld_buf->buffer, wr_size); |
---|
| 18036 | + scnprintf(buf_name, sizeof(buf_name), "dlb_buf[%d] present", i); |
---|
| 18037 | + dhd_print_buf_addr(dhdp, buf_name, dld_buf->present, wr_size); |
---|
| 18038 | + scnprintf(buf_name, sizeof(buf_name), "dlb_buf[%d] front", i); |
---|
| 18039 | + dhd_print_buf_addr(dhdp, buf_name, dld_buf->front, wr_size); |
---|
| 18040 | + } |
---|
| 18041 | + |
---|
| 18042 | +#ifdef EWP_ECNTRS_LOGGING |
---|
| 18043 | + /* periodic flushing of ecounters is NOT supported */ |
---|
| 18044 | + if (*type == DLD_BUF_TYPE_ALL && |
---|
| 18045 | + logdump_ecntr_enable && |
---|
| 18046 | + dhdp->ecntr_dbg_ring) { |
---|
| 18047 | + |
---|
| 18048 | + ring = (dhd_dbg_ring_t *)dhdp->ecntr_dbg_ring; |
---|
| 18049 | + dhd_print_buf_addr(dhdp, "ecntr_dbg_ring", ring, LOG_DUMP_ECNTRS_MAX_BUFSIZE); |
---|
| 18050 | + dhd_print_buf_addr(dhdp, "ecntr_dbg_ring ring_buf", ring->ring_buf, |
---|
| 18051 | + LOG_DUMP_ECNTRS_MAX_BUFSIZE); |
---|
| 18052 | + } |
---|
| 18053 | +#endif /* EWP_ECNTRS_LOGGING */ |
---|
| 18054 | + |
---|
| 18055 | +#ifdef DHD_STATUS_LOGGING |
---|
| 18056 | + if (dhdp->statlog) { |
---|
| 18057 | + dhd_print_buf_addr(dhdp, "statlog_logbuf", dhd_statlog_get_logbuf(dhdp), |
---|
| 18058 | + dhd_statlog_get_logbuf_len(dhdp)); |
---|
| 18059 | + } |
---|
| 18060 | +#endif /* DHD_STATUS_LOGGING */ |
---|
| 18061 | + |
---|
| 18062 | +#ifdef EWP_RTT_LOGGING |
---|
| 18063 | + /* periodic flushing of ecounters is NOT supported */ |
---|
| 18064 | + if (*type == DLD_BUF_TYPE_ALL && |
---|
| 18065 | + logdump_rtt_enable && |
---|
| 18066 | + dhdp->rtt_dbg_ring) { |
---|
| 18067 | + |
---|
| 18068 | + ring = (dhd_dbg_ring_t *)dhdp->rtt_dbg_ring; |
---|
| 18069 | + dhd_print_buf_addr(dhdp, "rtt_dbg_ring", ring, LOG_DUMP_RTT_MAX_BUFSIZE); |
---|
| 18070 | + dhd_print_buf_addr(dhdp, "rtt_dbg_ring ring_buf", ring->ring_buf, |
---|
| 18071 | + LOG_DUMP_RTT_MAX_BUFSIZE); |
---|
| 18072 | + } |
---|
| 18073 | +#endif /* EWP_RTT_LOGGING */ |
---|
| 18074 | + |
---|
| 18075 | +#ifdef BCMPCIE |
---|
| 18076 | + if (dhdp->dongle_trap_occured && dhdp->extended_trap_data) { |
---|
| 18077 | + dhd_print_buf_addr(dhdp, "extended_trap_data", dhdp->extended_trap_data, |
---|
| 18078 | + BCMPCIE_EXT_TRAP_DATA_MAXLEN); |
---|
| 18079 | + } |
---|
| 18080 | +#endif /* BCMPCIE */ |
---|
| 18081 | + |
---|
| 18082 | +#if defined(DHD_FW_COREDUMP) && defined(DNGL_EVENT_SUPPORT) |
---|
| 18083 | + /* if health check event was received */ |
---|
| 18084 | + if (dhdp->memdump_type == DUMP_TYPE_DONGLE_HOST_EVENT) { |
---|
| 18085 | + dhd_print_buf_addr(dhdp, "health_chk_event_data", dhdp->health_chk_event_data, |
---|
| 18086 | + HEALTH_CHK_BUF_SIZE); |
---|
| 18087 | + } |
---|
| 18088 | +#endif /* DHD_FW_COREDUMP && DNGL_EVENT_SUPPORT */ |
---|
| 18089 | + |
---|
| 18090 | + /* append the concise debug information */ |
---|
| 18091 | + if (dhdp->concise_dbg_buf) { |
---|
| 18092 | + dhd_print_buf_addr(dhdp, "concise_dbg_buf", dhdp->concise_dbg_buf, |
---|
| 18093 | + CONCISE_DUMP_BUFLEN); |
---|
| 18094 | + } |
---|
| 18095 | +} |
---|
| 18096 | + |
---|
| 18097 | +#ifdef CUSTOMER_HW4_DEBUG |
---|
| 18098 | +static void |
---|
| 18099 | +dhd_log_dump_print_to_kmsg(char *bufptr, unsigned long len) |
---|
| 18100 | +{ |
---|
| 18101 | + char tmp_buf[DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE + 1]; |
---|
| 18102 | + char *end = NULL; |
---|
| 18103 | + unsigned long plen = 0; |
---|
| 18104 | + |
---|
| 18105 | + if (!bufptr || !len) |
---|
| 18106 | + return; |
---|
| 18107 | + |
---|
| 18108 | + memset(tmp_buf, 0, DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE); |
---|
| 18109 | + end = bufptr + len; |
---|
| 18110 | + while (bufptr < end) { |
---|
| 18111 | + if ((bufptr + DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE) < end) { |
---|
| 18112 | + memcpy(tmp_buf, bufptr, DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE); |
---|
| 18113 | + tmp_buf[DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE] = '\0'; |
---|
| 18114 | + printf("%s", tmp_buf); |
---|
| 18115 | + bufptr += DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE; |
---|
| 18116 | + } else { |
---|
| 18117 | + plen = (unsigned long)end - (unsigned long)bufptr; |
---|
| 18118 | + memcpy(tmp_buf, bufptr, plen); |
---|
| 18119 | + tmp_buf[plen] = '\0'; |
---|
| 18120 | + printf("%s", tmp_buf); |
---|
| 18121 | + bufptr += plen; |
---|
| 18122 | + } |
---|
| 18123 | + } |
---|
| 18124 | +} |
---|
| 18125 | + |
---|
| 18126 | +static void |
---|
| 18127 | +dhd_log_dump_print_tail(dhd_pub_t *dhdp, |
---|
| 18128 | + struct dhd_log_dump_buf *dld_buf, |
---|
| 18129 | + uint tail_len) |
---|
| 18130 | +{ |
---|
| 18131 | + char *flush_ptr1 = NULL, *flush_ptr2 = NULL; |
---|
| 18132 | + unsigned long len_flush1 = 0, len_flush2 = 0; |
---|
| 18133 | + unsigned long flags = 0; |
---|
| 18134 | + |
---|
| 18135 | + /* need to hold the lock before accessing 'present' and 'remain' ptrs */ |
---|
| 18136 | + spin_lock_irqsave(&dld_buf->lock, flags); |
---|
| 18137 | + flush_ptr1 = dld_buf->present - tail_len; |
---|
| 18138 | + if (flush_ptr1 >= dld_buf->front) { |
---|
| 18139 | + /* tail content is within the buffer */ |
---|
| 18140 | + flush_ptr2 = NULL; |
---|
| 18141 | + len_flush1 = tail_len; |
---|
| 18142 | + } else if (dld_buf->wraparound) { |
---|
| 18143 | + /* tail content spans the buffer length i.e, wrap around */ |
---|
| 18144 | + flush_ptr1 = dld_buf->front; |
---|
| 18145 | + len_flush1 = (unsigned long)dld_buf->present - (unsigned long)flush_ptr1; |
---|
| 18146 | + len_flush2 = (unsigned long)tail_len - len_flush1; |
---|
| 18147 | + flush_ptr2 = (char *)((unsigned long)dld_buf->max - |
---|
| 18148 | + (unsigned long)len_flush2); |
---|
| 18149 | + } else { |
---|
| 18150 | + /* amt of logs in buffer is less than tail size */ |
---|
| 18151 | + flush_ptr1 = dld_buf->front; |
---|
| 18152 | + flush_ptr2 = NULL; |
---|
| 18153 | + len_flush1 = (unsigned long)dld_buf->present - (unsigned long)dld_buf->front; |
---|
| 18154 | + } |
---|
| 18155 | + spin_unlock_irqrestore(&dld_buf->lock, flags); |
---|
| 18156 | + |
---|
| 18157 | + printf("\n================= LOG_DUMP tail =================\n"); |
---|
| 18158 | + if (flush_ptr2) { |
---|
| 18159 | + dhd_log_dump_print_to_kmsg(flush_ptr2, len_flush2); |
---|
| 18160 | + } |
---|
| 18161 | + dhd_log_dump_print_to_kmsg(flush_ptr1, len_flush1); |
---|
| 18162 | + printf("\n===================================================\n"); |
---|
| 18163 | +} |
---|
| 18164 | +#endif /* CUSTOMER_HW4_DEBUG */ |
---|
| 18165 | + |
---|
| 18166 | +#ifdef DHD_SSSR_DUMP |
---|
| 18167 | +int |
---|
| 18168 | +dhdpcie_sssr_dump_get_before_after_len(dhd_pub_t *dhd, uint32 *arr_len) |
---|
| 18169 | +{ |
---|
| 18170 | + int i = 0; |
---|
| 18171 | + |
---|
| 18172 | + DHD_ERROR(("%s\n", __FUNCTION__)); |
---|
| 18173 | + |
---|
| 18174 | + /* core 0 */ |
---|
| 18175 | + i = 0; |
---|
| 18176 | + if (dhd->sssr_d11_before[i] && dhd->sssr_d11_outofreset[i] && |
---|
| 18177 | + (dhd->sssr_dump_mode == SSSR_DUMP_MODE_SSSR)) { |
---|
| 18178 | + arr_len[SSSR_C0_D11_BEFORE] = (dhd->sssr_reg_info.mac_regs[i].sr_size); |
---|
| 18179 | + DHD_ERROR(("%s: arr_len[SSSR_C0_D11_BEFORE] : %d\n", __FUNCTION__, |
---|
| 18180 | + arr_len[SSSR_C0_D11_BEFORE])); |
---|
| 18181 | +#ifdef DHD_LOG_DUMP |
---|
| 18182 | + dhd_print_buf_addr(dhd, "SSSR_C0_D11_BEFORE", |
---|
| 18183 | + dhd->sssr_d11_before[i], arr_len[SSSR_C0_D11_BEFORE]); |
---|
| 18184 | +#endif /* DHD_LOG_DUMP */ |
---|
| 18185 | + } |
---|
| 18186 | + if (dhd->sssr_d11_after[i] && dhd->sssr_d11_outofreset[i]) { |
---|
| 18187 | + arr_len[SSSR_C0_D11_AFTER] = (dhd->sssr_reg_info.mac_regs[i].sr_size); |
---|
| 18188 | + DHD_ERROR(("%s: arr_len[SSSR_C0_D11_AFTER] : %d\n", __FUNCTION__, |
---|
| 18189 | + arr_len[SSSR_C0_D11_AFTER])); |
---|
| 18190 | +#ifdef DHD_LOG_DUMP |
---|
| 18191 | + dhd_print_buf_addr(dhd, "SSSR_C0_D11_AFTER", |
---|
| 18192 | + dhd->sssr_d11_after[i], arr_len[SSSR_C0_D11_AFTER]); |
---|
| 18193 | +#endif /* DHD_LOG_DUMP */ |
---|
| 18194 | + } |
---|
| 18195 | + |
---|
| 18196 | + /* core 1 */ |
---|
| 18197 | + i = 1; |
---|
| 18198 | + if (dhd->sssr_d11_before[i] && dhd->sssr_d11_outofreset[i] && |
---|
| 18199 | + (dhd->sssr_dump_mode == SSSR_DUMP_MODE_SSSR)) { |
---|
| 18200 | + arr_len[SSSR_C1_D11_BEFORE] = (dhd->sssr_reg_info.mac_regs[i].sr_size); |
---|
| 18201 | + DHD_ERROR(("%s: arr_len[SSSR_C1_D11_BEFORE] : %d\n", __FUNCTION__, |
---|
| 18202 | + arr_len[SSSR_C1_D11_BEFORE])); |
---|
| 18203 | +#ifdef DHD_LOG_DUMP |
---|
| 18204 | + dhd_print_buf_addr(dhd, "SSSR_C1_D11_BEFORE", |
---|
| 18205 | + dhd->sssr_d11_before[i], arr_len[SSSR_C1_D11_BEFORE]); |
---|
| 18206 | +#endif /* DHD_LOG_DUMP */ |
---|
| 18207 | + } |
---|
| 18208 | + if (dhd->sssr_d11_after[i] && dhd->sssr_d11_outofreset[i]) { |
---|
| 18209 | + arr_len[SSSR_C1_D11_AFTER] = (dhd->sssr_reg_info.mac_regs[i].sr_size); |
---|
| 18210 | + DHD_ERROR(("%s: arr_len[SSSR_C1_D11_AFTER] : %d\n", __FUNCTION__, |
---|
| 18211 | + arr_len[SSSR_C1_D11_AFTER])); |
---|
| 18212 | +#ifdef DHD_LOG_DUMP |
---|
| 18213 | + dhd_print_buf_addr(dhd, "SSSR_C1_D11_AFTER", |
---|
| 18214 | + dhd->sssr_d11_after[i], arr_len[SSSR_C1_D11_AFTER]); |
---|
| 18215 | +#endif /* DHD_LOG_DUMP */ |
---|
| 18216 | + } |
---|
| 18217 | + |
---|
| 18218 | + if (dhd->sssr_reg_info.vasip_regs.vasip_sr_size) { |
---|
| 18219 | + arr_len[SSSR_DIG_BEFORE] = (dhd->sssr_reg_info.vasip_regs.vasip_sr_size); |
---|
| 18220 | + arr_len[SSSR_DIG_AFTER] = (dhd->sssr_reg_info.vasip_regs.vasip_sr_size); |
---|
| 18221 | + DHD_ERROR(("%s: arr_len[SSSR_DIG_BEFORE] : %d\n", __FUNCTION__, |
---|
| 18222 | + arr_len[SSSR_DIG_BEFORE])); |
---|
| 18223 | + DHD_ERROR(("%s: arr_len[SSSR_DIG_AFTER] : %d\n", __FUNCTION__, |
---|
| 18224 | + arr_len[SSSR_DIG_AFTER])); |
---|
| 18225 | +#ifdef DHD_LOG_DUMP |
---|
| 18226 | + if (dhd->sssr_dig_buf_before) { |
---|
| 18227 | + dhd_print_buf_addr(dhd, "SSSR_DIG_BEFORE", |
---|
| 18228 | + dhd->sssr_dig_buf_before, arr_len[SSSR_DIG_BEFORE]); |
---|
| 18229 | + } |
---|
| 18230 | + if (dhd->sssr_dig_buf_after) { |
---|
| 18231 | + dhd_print_buf_addr(dhd, "SSSR_DIG_AFTER", |
---|
| 18232 | + dhd->sssr_dig_buf_after, arr_len[SSSR_DIG_AFTER]); |
---|
| 18233 | + } |
---|
| 18234 | +#endif /* DHD_LOG_DUMP */ |
---|
| 18235 | + } else if ((dhd->sssr_reg_info.length > OFFSETOF(sssr_reg_info_v1_t, dig_mem_info)) && |
---|
| 18236 | + dhd->sssr_reg_info.dig_mem_info.dig_sr_addr) { |
---|
| 18237 | + arr_len[SSSR_DIG_BEFORE] = (dhd->sssr_reg_info.dig_mem_info.dig_sr_size); |
---|
| 18238 | + arr_len[SSSR_DIG_AFTER] = (dhd->sssr_reg_info.dig_mem_info.dig_sr_size); |
---|
| 18239 | + DHD_ERROR(("%s: arr_len[SSSR_DIG_BEFORE] : %d\n", __FUNCTION__, |
---|
| 18240 | + arr_len[SSSR_DIG_BEFORE])); |
---|
| 18241 | + DHD_ERROR(("%s: arr_len[SSSR_DIG_AFTER] : %d\n", __FUNCTION__, |
---|
| 18242 | + arr_len[SSSR_DIG_AFTER])); |
---|
| 18243 | +#ifdef DHD_LOG_DUMP |
---|
| 18244 | + if (dhd->sssr_dig_buf_before) { |
---|
| 18245 | + dhd_print_buf_addr(dhd, "SSSR_DIG_BEFORE", |
---|
| 18246 | + dhd->sssr_dig_buf_before, arr_len[SSSR_DIG_BEFORE]); |
---|
| 18247 | + } |
---|
| 18248 | + if (dhd->sssr_dig_buf_after) { |
---|
| 18249 | + dhd_print_buf_addr(dhd, "SSSR_DIG_AFTER", |
---|
| 18250 | + dhd->sssr_dig_buf_after, arr_len[SSSR_DIG_AFTER]); |
---|
| 18251 | + } |
---|
| 18252 | +#endif /* DHD_LOG_DUMP */ |
---|
| 18253 | + } |
---|
| 18254 | + return BCME_OK; |
---|
| 18255 | +} |
---|
| 18256 | + |
---|
| 18257 | +void |
---|
| 18258 | +dhd_nla_put_sssr_dump_len(void *ndev, uint32 *arr_len) |
---|
| 18259 | +{ |
---|
| 18260 | + dhd_info_t *dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)ndev); |
---|
| 18261 | + dhd_pub_t *dhdp = &dhd_info->pub; |
---|
| 18262 | + |
---|
| 18263 | + if (dhdp->sssr_dump_collected) { |
---|
| 18264 | + dhdpcie_sssr_dump_get_before_after_len(dhdp, arr_len); |
---|
| 18265 | + } |
---|
| 18266 | +} |
---|
| 18267 | +#endif /* DHD_SSSR_DUMP */ |
---|
| 18268 | + |
---|
| 18269 | +uint32 |
---|
| 18270 | +dhd_get_time_str_len() |
---|
| 18271 | +{ |
---|
| 18272 | + char *ts = NULL, time_str[128]; |
---|
| 18273 | + |
---|
| 18274 | + ts = dhd_log_dump_get_timestamp(); |
---|
| 18275 | + snprintf(time_str, sizeof(time_str), |
---|
| 18276 | + "\n\n ========== LOG DUMP TAKEN AT : %s =========\n", ts); |
---|
| 18277 | + return strlen(time_str); |
---|
| 18278 | +} |
---|
| 18279 | + |
---|
| 18280 | +#ifdef BCMPCIE |
---|
| 18281 | +uint32 |
---|
| 18282 | +dhd_get_ext_trap_len(void *ndev, dhd_pub_t *dhdp) |
---|
| 18283 | +{ |
---|
| 18284 | + int length = 0; |
---|
| 18285 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18286 | + dhd_info_t *dhd_info; |
---|
| 18287 | + |
---|
| 18288 | + if (ndev) { |
---|
| 18289 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)ndev); |
---|
| 18290 | + dhdp = &dhd_info->pub; |
---|
| 18291 | + } |
---|
| 18292 | + |
---|
| 18293 | + if (!dhdp) |
---|
| 18294 | + return length; |
---|
| 18295 | + |
---|
| 18296 | + if (dhdp->extended_trap_data) { |
---|
| 18297 | + length = (strlen(EXT_TRAP_LOG_HDR) |
---|
| 18298 | + + sizeof(sec_hdr) + BCMPCIE_EXT_TRAP_DATA_MAXLEN); |
---|
| 18299 | + } |
---|
| 18300 | + return length; |
---|
| 18301 | +} |
---|
| 18302 | +#endif /* BCMPCIE */ |
---|
| 18303 | + |
---|
| 18304 | +#if defined(DHD_FW_COREDUMP) && defined(DNGL_EVENT_SUPPORT) |
---|
| 18305 | +uint32 |
---|
| 18306 | +dhd_get_health_chk_len(void *ndev, dhd_pub_t *dhdp) |
---|
| 18307 | +{ |
---|
| 18308 | + int length = 0; |
---|
| 18309 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18310 | + dhd_info_t *dhd_info; |
---|
| 18311 | + |
---|
| 18312 | + if (ndev) { |
---|
| 18313 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)ndev); |
---|
| 18314 | + dhdp = &dhd_info->pub; |
---|
| 18315 | + } |
---|
| 18316 | + |
---|
| 18317 | + if (!dhdp) |
---|
| 18318 | + return length; |
---|
| 18319 | + |
---|
| 18320 | + if (dhdp->memdump_type == DUMP_TYPE_DONGLE_HOST_EVENT) { |
---|
| 18321 | + length = (strlen(HEALTH_CHK_LOG_HDR) |
---|
| 18322 | + + sizeof(sec_hdr) + HEALTH_CHK_BUF_SIZE); |
---|
| 18323 | + } |
---|
| 18324 | + return length; |
---|
| 18325 | +} |
---|
| 18326 | +#endif /* DHD_FW_COREDUMP && DNGL_EVENT_SUPPORT */ |
---|
| 18327 | + |
---|
| 18328 | +uint32 |
---|
| 18329 | +dhd_get_dhd_dump_len(void *ndev, dhd_pub_t *dhdp) |
---|
| 18330 | +{ |
---|
| 18331 | + int length = 0; |
---|
| 18332 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18333 | + dhd_info_t *dhd_info; |
---|
| 18334 | + uint32 remain_len = 0; |
---|
| 18335 | + |
---|
| 18336 | + if (ndev) { |
---|
| 18337 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)ndev); |
---|
| 18338 | + dhdp = &dhd_info->pub; |
---|
| 18339 | + } |
---|
| 18340 | + |
---|
| 18341 | + if (!dhdp) |
---|
| 18342 | + return length; |
---|
| 18343 | + |
---|
| 18344 | + if (dhdp->concise_dbg_buf) { |
---|
| 18345 | + remain_len = dhd_dump(dhdp, (char *)dhdp->concise_dbg_buf, CONCISE_DUMP_BUFLEN); |
---|
| 18346 | + if (remain_len <= 0) { |
---|
| 18347 | + DHD_ERROR(("%s: error getting concise debug info !\n", |
---|
| 18348 | + __FUNCTION__)); |
---|
| 18349 | + return length; |
---|
| 18350 | + } |
---|
| 18351 | + length = (strlen(DHD_DUMP_LOG_HDR) + sizeof(sec_hdr) + |
---|
| 18352 | + (CONCISE_DUMP_BUFLEN - remain_len)); |
---|
| 18353 | + } |
---|
| 18354 | + return length; |
---|
| 18355 | +} |
---|
| 18356 | + |
---|
| 18357 | +uint32 |
---|
| 18358 | +dhd_get_cookie_log_len(void *ndev, dhd_pub_t *dhdp) |
---|
| 18359 | +{ |
---|
| 18360 | + int length = 0; |
---|
| 18361 | + dhd_info_t *dhd_info; |
---|
| 18362 | + |
---|
| 18363 | + if (ndev) { |
---|
| 18364 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)ndev); |
---|
| 18365 | + dhdp = &dhd_info->pub; |
---|
| 18366 | + } |
---|
| 18367 | + |
---|
| 18368 | + if (!dhdp) |
---|
| 18369 | + return length; |
---|
| 18370 | + |
---|
| 18371 | + if (dhdp->logdump_cookie && dhd_logdump_cookie_count(dhdp) > 0) { |
---|
| 18372 | + length = dhd_log_dump_cookie_len(dhdp); |
---|
| 18373 | + } |
---|
| 18374 | + return length; |
---|
| 18375 | + |
---|
| 18376 | +} |
---|
| 18377 | + |
---|
| 18378 | +#ifdef DHD_DUMP_PCIE_RINGS |
---|
| 18379 | +uint32 |
---|
| 18380 | +dhd_get_flowring_len(void *ndev, dhd_pub_t *dhdp) |
---|
| 18381 | +{ |
---|
| 18382 | + int length = 0; |
---|
| 18383 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18384 | + dhd_info_t *dhd_info; |
---|
| 18385 | + uint16 h2d_flowrings_total; |
---|
| 18386 | + uint32 remain_len = 0; |
---|
| 18387 | + |
---|
| 18388 | + if (ndev) { |
---|
| 18389 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)ndev); |
---|
| 18390 | + dhdp = &dhd_info->pub; |
---|
| 18391 | + } |
---|
| 18392 | + |
---|
| 18393 | + if (!dhdp) |
---|
| 18394 | + return length; |
---|
| 18395 | + |
---|
| 18396 | + if (dhdp->concise_dbg_buf) { |
---|
| 18397 | + remain_len = dhd_dump(dhdp, (char *)dhdp->concise_dbg_buf, CONCISE_DUMP_BUFLEN); |
---|
| 18398 | + if (remain_len <= 0) { |
---|
| 18399 | + DHD_ERROR(("%s: error getting concise debug info !\n", |
---|
| 18400 | + __FUNCTION__)); |
---|
| 18401 | + return length; |
---|
| 18402 | + } |
---|
| 18403 | + } |
---|
| 18404 | + |
---|
| 18405 | + length += strlen(FLOWRING_DUMP_HDR); |
---|
| 18406 | + length += CONCISE_DUMP_BUFLEN - remain_len; |
---|
| 18407 | + length += sizeof(sec_hdr); |
---|
| 18408 | + h2d_flowrings_total = dhd_get_max_flow_rings(dhdp); |
---|
| 18409 | + length += ((H2DRING_TXPOST_ITEMSIZE |
---|
| 18410 | + * H2DRING_TXPOST_MAX_ITEM * h2d_flowrings_total) |
---|
| 18411 | + + (D2HRING_TXCMPLT_ITEMSIZE * D2HRING_TXCMPLT_MAX_ITEM) |
---|
| 18412 | + + (H2DRING_RXPOST_ITEMSIZE * H2DRING_RXPOST_MAX_ITEM) |
---|
| 18413 | + + (D2HRING_RXCMPLT_ITEMSIZE * D2HRING_RXCMPLT_MAX_ITEM) |
---|
| 18414 | + + (H2DRING_CTRL_SUB_ITEMSIZE * H2DRING_CTRL_SUB_MAX_ITEM) |
---|
| 18415 | + + (D2HRING_CTRL_CMPLT_ITEMSIZE * D2HRING_CTRL_CMPLT_MAX_ITEM) |
---|
| 18416 | +#ifdef EWP_EDL |
---|
| 18417 | + + (D2HRING_EDL_HDR_SIZE * D2HRING_EDL_MAX_ITEM)); |
---|
| 18418 | +#else |
---|
| 18419 | + + (H2DRING_INFO_BUFPOST_ITEMSIZE * H2DRING_DYNAMIC_INFO_MAX_ITEM) |
---|
| 18420 | + + (D2HRING_INFO_BUFCMPLT_ITEMSIZE * D2HRING_DYNAMIC_INFO_MAX_ITEM)); |
---|
| 18421 | +#endif /* EWP_EDL */ |
---|
| 18422 | + return length; |
---|
| 18423 | +} |
---|
| 18424 | +#endif /* DHD_DUMP_PCIE_RINGS */ |
---|
| 18425 | + |
---|
| 18426 | +#ifdef EWP_ECNTRS_LOGGING |
---|
| 18427 | +uint32 |
---|
| 18428 | +dhd_get_ecntrs_len(void *ndev, dhd_pub_t *dhdp) |
---|
| 18429 | +{ |
---|
| 18430 | + dhd_info_t *dhd_info; |
---|
| 18431 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18432 | + int length = 0; |
---|
| 18433 | + dhd_dbg_ring_t *ring; |
---|
| 18434 | + |
---|
| 18435 | + if (ndev) { |
---|
| 18436 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)ndev); |
---|
| 18437 | + dhdp = &dhd_info->pub; |
---|
| 18438 | + } |
---|
| 18439 | + |
---|
| 18440 | + if (!dhdp) |
---|
| 18441 | + return length; |
---|
| 18442 | + |
---|
| 18443 | + if (logdump_ecntr_enable && dhdp->ecntr_dbg_ring) { |
---|
| 18444 | + ring = (dhd_dbg_ring_t *)dhdp->ecntr_dbg_ring; |
---|
| 18445 | + length = ring->ring_size + strlen(ECNTRS_LOG_HDR) + sizeof(sec_hdr); |
---|
| 18446 | + } |
---|
| 18447 | + return length; |
---|
| 18448 | +} |
---|
| 18449 | +#endif /* EWP_ECNTRS_LOGGING */ |
---|
| 18450 | + |
---|
| 18451 | +#ifdef EWP_RTT_LOGGING |
---|
| 18452 | +uint32 |
---|
| 18453 | +dhd_get_rtt_len(void *ndev, dhd_pub_t *dhdp) |
---|
| 18454 | +{ |
---|
| 18455 | + dhd_info_t *dhd_info; |
---|
| 18456 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18457 | + int length = 0; |
---|
| 18458 | + dhd_dbg_ring_t *ring; |
---|
| 18459 | + |
---|
| 18460 | + if (ndev) { |
---|
| 18461 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)ndev); |
---|
| 18462 | + dhdp = &dhd_info->pub; |
---|
| 18463 | + } |
---|
| 18464 | + |
---|
| 18465 | + if (!dhdp) |
---|
| 18466 | + return length; |
---|
| 18467 | + |
---|
| 18468 | + if (logdump_rtt_enable && dhdp->rtt_dbg_ring) { |
---|
| 18469 | + ring = (dhd_dbg_ring_t *)dhdp->rtt_dbg_ring; |
---|
| 18470 | + length = ring->ring_size + strlen(RTT_LOG_HDR) + sizeof(sec_hdr); |
---|
| 18471 | + } |
---|
| 18472 | + return length; |
---|
| 18473 | +} |
---|
| 18474 | +#endif /* EWP_RTT_LOGGING */ |
---|
| 18475 | + |
---|
| 18476 | +int |
---|
| 18477 | +dhd_get_dld_log_dump(void *dev, dhd_pub_t *dhdp, const void *user_buf, |
---|
| 18478 | + void *fp, uint32 len, int type, void *pos) |
---|
| 18479 | +{ |
---|
| 18480 | + int ret = BCME_OK; |
---|
| 18481 | + struct dhd_log_dump_buf *dld_buf; |
---|
| 18482 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18483 | + dhd_info_t *dhd_info; |
---|
| 18484 | + |
---|
| 18485 | + dld_buf = &g_dld_buf[type]; |
---|
| 18486 | + |
---|
| 18487 | + if (dev) { |
---|
| 18488 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 18489 | + dhdp = &dhd_info->pub; |
---|
| 18490 | + } else if (!dhdp) { |
---|
| 18491 | + return BCME_ERROR; |
---|
| 18492 | + } |
---|
| 18493 | + |
---|
| 18494 | + DHD_ERROR(("%s: ENTER \n", __FUNCTION__)); |
---|
| 18495 | + |
---|
| 18496 | + dhd_init_sec_hdr(&sec_hdr); |
---|
| 18497 | + |
---|
| 18498 | + /* write the section header first */ |
---|
| 18499 | + ret = dhd_export_debug_data(dld_hdrs[type].hdr_str, fp, user_buf, |
---|
| 18500 | + strlen(dld_hdrs[type].hdr_str), pos); |
---|
| 18501 | + if (ret < 0) |
---|
| 18502 | + goto exit; |
---|
| 18503 | + len -= (uint32)strlen(dld_hdrs[type].hdr_str); |
---|
| 18504 | + len -= (uint32)sizeof(sec_hdr); |
---|
| 18505 | + sec_hdr.type = dld_hdrs[type].sec_type; |
---|
| 18506 | + sec_hdr.length = len; |
---|
| 18507 | + ret = dhd_export_debug_data((char *)&sec_hdr, fp, user_buf, sizeof(sec_hdr), pos); |
---|
| 18508 | + if (ret < 0) |
---|
| 18509 | + goto exit; |
---|
| 18510 | + ret = dhd_export_debug_data(dld_buf->buffer, fp, user_buf, len, pos); |
---|
| 18511 | + if (ret < 0) |
---|
| 18512 | + goto exit; |
---|
| 18513 | + |
---|
| 18514 | +exit: |
---|
| 18515 | + return ret; |
---|
| 18516 | +} |
---|
| 18517 | + |
---|
| 18518 | +static int |
---|
| 18519 | +dhd_log_flush(dhd_pub_t *dhdp, log_dump_type_t *type) |
---|
| 18520 | +{ |
---|
| 18521 | + unsigned long flags = 0; |
---|
| 18522 | +#ifdef EWP_EDL |
---|
| 18523 | + int i = 0; |
---|
| 18524 | +#endif /* EWP_EDL */ |
---|
| 18525 | + dhd_info_t *dhd_info = NULL; |
---|
| 18526 | + |
---|
| 18527 | + /* if dhdp is null, its extremely unlikely that log dump will be scheduled |
---|
| 18528 | + * so not freeing 'type' here is ok, even if we want to free 'type' |
---|
| 18529 | + * we cannot do so, since 'dhdp->osh' is unavailable |
---|
| 18530 | + * as dhdp is null |
---|
| 18531 | + */ |
---|
| 18532 | + if (!dhdp || !type) { |
---|
| 18533 | + if (dhdp) { |
---|
| 18534 | + DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 18535 | + DHD_BUS_BUSY_CLEAR_IN_LOGDUMP(dhdp); |
---|
| 18536 | + dhd_os_busbusy_wake(dhdp); |
---|
| 18537 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 18538 | + } |
---|
| 18539 | + return BCME_ERROR; |
---|
| 18540 | + } |
---|
| 18541 | + |
---|
| 18542 | + dhd_info = (dhd_info_t *)dhdp->info; |
---|
| 18543 | + /* in case of trap get preserve logs from ETD */ |
---|
| 18544 | +#if defined(BCMPCIE) && defined(EWP_ETD_PRSRV_LOGS) |
---|
| 18545 | + if (dhdp->dongle_trap_occured && |
---|
| 18546 | + dhdp->extended_trap_data) { |
---|
| 18547 | + dhdpcie_get_etd_preserve_logs(dhdp, (uint8 *)dhdp->extended_trap_data, |
---|
| 18548 | + &dhd_info->event_data); |
---|
| 18549 | + } |
---|
| 18550 | +#endif /* BCMPCIE */ |
---|
| 18551 | + |
---|
| 18552 | + /* flush the event work items to get any fw events/logs |
---|
| 18553 | + * flush_work is a blocking call |
---|
| 18554 | + */ |
---|
| 18555 | +#ifdef EWP_EDL |
---|
| 18556 | + if (dhd_info->pub.dongle_edl_support) { |
---|
| 18557 | + /* wait till existing edl items are processed */ |
---|
| 18558 | + dhd_flush_logtrace_process(dhd_info); |
---|
| 18559 | + /* dhd_flush_logtrace_process will ensure the work items in the ring |
---|
| 18560 | + * (EDL ring) from rd to wr are processed. But if wr had |
---|
| 18561 | + * wrapped around, only the work items from rd to ring-end are processed. |
---|
| 18562 | + * So to ensure that the work items at the |
---|
| 18563 | + * beginning of ring are also processed in the wrap around case, call |
---|
| 18564 | + * it twice |
---|
| 18565 | + */ |
---|
| 18566 | + for (i = 0; i < 2; i++) { |
---|
| 18567 | + /* blocks till the edl items are processed */ |
---|
| 18568 | + dhd_flush_logtrace_process(dhd_info); |
---|
| 18569 | + } |
---|
| 18570 | + } else { |
---|
| 18571 | + dhd_flush_logtrace_process(dhd_info); |
---|
| 18572 | + } |
---|
| 18573 | +#else |
---|
| 18574 | + dhd_flush_logtrace_process(dhd_info); |
---|
| 18575 | +#endif /* EWP_EDL */ |
---|
| 18576 | + |
---|
| 18577 | +#ifdef CUSTOMER_HW4_DEBUG |
---|
| 18578 | + /* print last 'x' KB of preserve buffer data to kmsg console |
---|
| 18579 | + * this is to address cases where debug_dump is not |
---|
| 18580 | + * available for debugging |
---|
| 18581 | + */ |
---|
| 18582 | + dhd_log_dump_print_tail(dhdp, |
---|
| 18583 | + &g_dld_buf[DLD_BUF_TYPE_PRESERVE], logdump_prsrv_tailsize); |
---|
| 18584 | +#endif /* CUSTOMER_HW4_DEBUG */ |
---|
| 18585 | + return BCME_OK; |
---|
| 18586 | +} |
---|
| 18587 | + |
---|
| 18588 | +int |
---|
| 18589 | +dhd_get_debug_dump_file_name(void *dev, dhd_pub_t *dhdp, char *dump_path, int size) |
---|
| 18590 | +{ |
---|
| 18591 | + dhd_info_t *dhd_info; |
---|
| 18592 | + |
---|
| 18593 | + if (dev) { |
---|
| 18594 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 18595 | + dhdp = &dhd_info->pub; |
---|
| 18596 | + } |
---|
| 18597 | + |
---|
| 18598 | + if (!dhdp) |
---|
| 18599 | + return BCME_ERROR; |
---|
| 18600 | + |
---|
| 18601 | + memset(dump_path, 0, size); |
---|
| 18602 | + |
---|
| 18603 | + switch (dhdp->debug_dump_subcmd) { |
---|
| 18604 | + case CMD_UNWANTED: |
---|
| 18605 | + snprintf(dump_path, size, "%s", |
---|
| 18606 | + DHD_COMMON_DUMP_PATH DHD_DEBUG_DUMP_TYPE |
---|
| 18607 | + DHD_DUMP_SUBSTR_UNWANTED); |
---|
| 18608 | + break; |
---|
| 18609 | + case CMD_DISCONNECTED: |
---|
| 18610 | + snprintf(dump_path, size, "%s", |
---|
| 18611 | + DHD_COMMON_DUMP_PATH DHD_DEBUG_DUMP_TYPE |
---|
| 18612 | + DHD_DUMP_SUBSTR_DISCONNECTED); |
---|
| 18613 | + break; |
---|
| 18614 | + default: |
---|
| 18615 | + snprintf(dump_path, size, "%s", |
---|
| 18616 | + DHD_COMMON_DUMP_PATH DHD_DEBUG_DUMP_TYPE); |
---|
| 18617 | + } |
---|
| 18618 | + |
---|
| 18619 | + if (!dhdp->logdump_periodic_flush) { |
---|
| 18620 | + get_debug_dump_time(dhdp->debug_dump_time_str); |
---|
| 18621 | + snprintf(dump_path + strlen(dump_path), |
---|
| 18622 | + size - strlen(dump_path), |
---|
| 18623 | + "_%s", dhdp->debug_dump_time_str); |
---|
| 18624 | + } |
---|
| 18625 | + return BCME_OK; |
---|
| 18626 | +} |
---|
| 18627 | + |
---|
| 18628 | +uint32 |
---|
| 18629 | +dhd_get_dld_len(int log_type) |
---|
| 18630 | +{ |
---|
| 18631 | + unsigned long wr_size = 0; |
---|
| 18632 | + unsigned long buf_size = 0; |
---|
| 18633 | + unsigned long flags = 0; |
---|
| 18634 | + struct dhd_log_dump_buf *dld_buf; |
---|
| 18635 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18636 | + |
---|
| 18637 | + /* calculate the length of the log */ |
---|
| 18638 | + dld_buf = &g_dld_buf[log_type]; |
---|
| 18639 | + buf_size = (unsigned long)dld_buf->max - |
---|
| 18640 | + (unsigned long)dld_buf->buffer; |
---|
| 18641 | + |
---|
| 18642 | + if (dld_buf->wraparound) { |
---|
| 18643 | + wr_size = buf_size; |
---|
| 18644 | + } else { |
---|
| 18645 | + /* need to hold the lock before accessing 'present' and 'remain' ptrs */ |
---|
| 18646 | + spin_lock_irqsave(&dld_buf->lock, flags); |
---|
| 18647 | + wr_size = (unsigned long)dld_buf->present - |
---|
| 18648 | + (unsigned long)dld_buf->front; |
---|
| 18649 | + spin_unlock_irqrestore(&dld_buf->lock, flags); |
---|
| 18650 | + } |
---|
| 18651 | + return (wr_size + sizeof(sec_hdr) + strlen(dld_hdrs[log_type].hdr_str)); |
---|
| 18652 | +} |
---|
| 18653 | + |
---|
| 18654 | +static void |
---|
| 18655 | +dhd_get_time_str(dhd_pub_t *dhdp, char *time_str, int size) |
---|
| 18656 | +{ |
---|
| 18657 | + char *ts = NULL; |
---|
| 18658 | + memset(time_str, 0, size); |
---|
| 18659 | + ts = dhd_log_dump_get_timestamp(); |
---|
| 18660 | + snprintf(time_str, size, |
---|
| 18661 | + "\n\n ========== LOG DUMP TAKEN AT : %s =========\n", ts); |
---|
| 18662 | +} |
---|
| 18663 | + |
---|
| 18664 | +int |
---|
| 18665 | +dhd_print_time_str(const void *user_buf, void *fp, uint32 len, void *pos) |
---|
| 18666 | +{ |
---|
| 18667 | + char *ts = NULL; |
---|
| 18668 | + int ret = 0; |
---|
| 18669 | + char time_str[128]; |
---|
| 18670 | + |
---|
| 18671 | + memset_s(time_str, sizeof(time_str), 0, sizeof(time_str)); |
---|
| 18672 | + ts = dhd_log_dump_get_timestamp(); |
---|
| 18673 | + snprintf(time_str, sizeof(time_str), |
---|
| 18674 | + "\n\n ========== LOG DUMP TAKEN AT : %s =========\n", ts); |
---|
| 18675 | + |
---|
| 18676 | + /* write the timestamp hdr to the file first */ |
---|
| 18677 | + ret = dhd_export_debug_data(time_str, fp, user_buf, strlen(time_str), pos); |
---|
| 18678 | + if (ret < 0) { |
---|
| 18679 | + DHD_ERROR(("write file error, err = %d\n", ret)); |
---|
| 18680 | + } |
---|
| 18681 | + return ret; |
---|
| 18682 | +} |
---|
| 18683 | + |
---|
| 18684 | +#if defined(DHD_FW_COREDUMP) && defined(DNGL_EVENT_SUPPORT) |
---|
| 18685 | +int |
---|
| 18686 | +dhd_print_health_chk_data(void *dev, dhd_pub_t *dhdp, const void *user_buf, |
---|
| 18687 | + void *fp, uint32 len, void *pos) |
---|
| 18688 | +{ |
---|
| 18689 | + int ret = BCME_OK; |
---|
| 18690 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18691 | + dhd_info_t *dhd_info; |
---|
| 18692 | + |
---|
| 18693 | + if (dev) { |
---|
| 18694 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 18695 | + dhdp = &dhd_info->pub; |
---|
| 18696 | + } |
---|
| 18697 | + |
---|
| 18698 | + if (!dhdp) |
---|
| 18699 | + return BCME_ERROR; |
---|
| 18700 | + |
---|
| 18701 | + dhd_init_sec_hdr(&sec_hdr); |
---|
| 18702 | + |
---|
| 18703 | + if (dhdp->memdump_type == DUMP_TYPE_DONGLE_HOST_EVENT) { |
---|
| 18704 | + /* write the section header first */ |
---|
| 18705 | + ret = dhd_export_debug_data(HEALTH_CHK_LOG_HDR, fp, user_buf, |
---|
| 18706 | + strlen(HEALTH_CHK_LOG_HDR), pos); |
---|
| 18707 | + if (ret < 0) |
---|
| 18708 | + goto exit; |
---|
| 18709 | + |
---|
| 18710 | + len -= (uint32)strlen(HEALTH_CHK_LOG_HDR); |
---|
| 18711 | + sec_hdr.type = LOG_DUMP_SECTION_HEALTH_CHK; |
---|
| 18712 | + sec_hdr.length = HEALTH_CHK_BUF_SIZE; |
---|
| 18713 | + ret = dhd_export_debug_data((char *)&sec_hdr, fp, user_buf, sizeof(sec_hdr), pos); |
---|
| 18714 | + if (ret < 0) |
---|
| 18715 | + goto exit; |
---|
| 18716 | + |
---|
| 18717 | + len -= (uint32)sizeof(sec_hdr); |
---|
| 18718 | + /* write the log */ |
---|
| 18719 | + ret = dhd_export_debug_data((char *)dhdp->health_chk_event_data, fp, |
---|
| 18720 | + user_buf, len, pos); |
---|
| 18721 | + if (ret < 0) |
---|
| 18722 | + goto exit; |
---|
| 18723 | + } |
---|
| 18724 | +exit: |
---|
| 18725 | + return ret; |
---|
| 18726 | +} |
---|
| 18727 | +#endif /* DHD_FW_COREDUMP && DNGL_EVENT_SUPPORT */ |
---|
| 18728 | + |
---|
| 18729 | +#ifdef BCMPCIE |
---|
| 18730 | +int |
---|
| 18731 | +dhd_print_ext_trap_data(void *dev, dhd_pub_t *dhdp, const void *user_buf, |
---|
| 18732 | + void *fp, uint32 len, void *pos) |
---|
| 18733 | +{ |
---|
| 18734 | + int ret = BCME_OK; |
---|
| 18735 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18736 | + dhd_info_t *dhd_info; |
---|
| 18737 | + |
---|
| 18738 | + if (dev) { |
---|
| 18739 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 18740 | + dhdp = &dhd_info->pub; |
---|
| 18741 | + } |
---|
| 18742 | + |
---|
| 18743 | + if (!dhdp) |
---|
| 18744 | + return BCME_ERROR; |
---|
| 18745 | + |
---|
| 18746 | + dhd_init_sec_hdr(&sec_hdr); |
---|
| 18747 | + |
---|
| 18748 | + /* append extended trap data to the file in case of traps */ |
---|
| 18749 | + if (dhdp->dongle_trap_occured && |
---|
| 18750 | + dhdp->extended_trap_data) { |
---|
| 18751 | + /* write the section header first */ |
---|
| 18752 | + ret = dhd_export_debug_data(EXT_TRAP_LOG_HDR, fp, user_buf, |
---|
| 18753 | + strlen(EXT_TRAP_LOG_HDR), pos); |
---|
| 18754 | + if (ret < 0) |
---|
| 18755 | + goto exit; |
---|
| 18756 | + |
---|
| 18757 | + len -= (uint32)strlen(EXT_TRAP_LOG_HDR); |
---|
| 18758 | + sec_hdr.type = LOG_DUMP_SECTION_EXT_TRAP; |
---|
| 18759 | + sec_hdr.length = BCMPCIE_EXT_TRAP_DATA_MAXLEN; |
---|
| 18760 | + ret = dhd_export_debug_data((uint8 *)&sec_hdr, fp, user_buf, sizeof(sec_hdr), pos); |
---|
| 18761 | + if (ret < 0) |
---|
| 18762 | + goto exit; |
---|
| 18763 | + |
---|
| 18764 | + len -= (uint32)sizeof(sec_hdr); |
---|
| 18765 | + /* write the log */ |
---|
| 18766 | + ret = dhd_export_debug_data((uint8 *)dhdp->extended_trap_data, fp, |
---|
| 18767 | + user_buf, len, pos); |
---|
| 18768 | + if (ret < 0) |
---|
| 18769 | + goto exit; |
---|
| 18770 | + } |
---|
| 18771 | +exit: |
---|
| 18772 | + return ret; |
---|
| 18773 | +} |
---|
| 18774 | +#endif /* BCMPCIE */ |
---|
| 18775 | + |
---|
| 18776 | +int |
---|
| 18777 | +dhd_print_dump_data(void *dev, dhd_pub_t *dhdp, const void *user_buf, |
---|
| 18778 | + void *fp, uint32 len, void *pos) |
---|
| 18779 | +{ |
---|
| 18780 | + int ret = BCME_OK; |
---|
| 18781 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18782 | + dhd_info_t *dhd_info; |
---|
| 18783 | + |
---|
| 18784 | + if (dev) { |
---|
| 18785 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 18786 | + dhdp = &dhd_info->pub; |
---|
| 18787 | + } |
---|
| 18788 | + |
---|
| 18789 | + if (!dhdp) |
---|
| 18790 | + return BCME_ERROR; |
---|
| 18791 | + |
---|
| 18792 | + dhd_init_sec_hdr(&sec_hdr); |
---|
| 18793 | + |
---|
| 18794 | + ret = dhd_export_debug_data(DHD_DUMP_LOG_HDR, fp, user_buf, strlen(DHD_DUMP_LOG_HDR), pos); |
---|
| 18795 | + if (ret < 0) |
---|
| 18796 | + goto exit; |
---|
| 18797 | + |
---|
| 18798 | + len -= (uint32)strlen(DHD_DUMP_LOG_HDR); |
---|
| 18799 | + sec_hdr.type = LOG_DUMP_SECTION_DHD_DUMP; |
---|
| 18800 | + sec_hdr.length = len; |
---|
| 18801 | + ret = dhd_export_debug_data((char *)&sec_hdr, fp, user_buf, sizeof(sec_hdr), pos); |
---|
| 18802 | + if (ret < 0) |
---|
| 18803 | + goto exit; |
---|
| 18804 | + |
---|
| 18805 | + len -= (uint32)sizeof(sec_hdr); |
---|
| 18806 | + |
---|
| 18807 | + if (dhdp->concise_dbg_buf) { |
---|
| 18808 | + dhd_dump(dhdp, (char *)dhdp->concise_dbg_buf, CONCISE_DUMP_BUFLEN); |
---|
| 18809 | + ret = dhd_export_debug_data(dhdp->concise_dbg_buf, fp, user_buf, len, pos); |
---|
| 18810 | + if (ret < 0) |
---|
| 18811 | + goto exit; |
---|
| 18812 | + } |
---|
| 18813 | + |
---|
| 18814 | +exit: |
---|
| 18815 | + return ret; |
---|
| 18816 | +} |
---|
| 18817 | + |
---|
| 18818 | +int |
---|
| 18819 | +dhd_print_cookie_data(void *dev, dhd_pub_t *dhdp, const void *user_buf, |
---|
| 18820 | + void *fp, uint32 len, void *pos) |
---|
| 18821 | +{ |
---|
| 18822 | + int ret = BCME_OK; |
---|
| 18823 | + dhd_info_t *dhd_info; |
---|
| 18824 | + |
---|
| 18825 | + if (dev) { |
---|
| 18826 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 18827 | + dhdp = &dhd_info->pub; |
---|
| 18828 | + } |
---|
| 18829 | + |
---|
| 18830 | + if (!dhdp) |
---|
| 18831 | + return BCME_ERROR; |
---|
| 18832 | + |
---|
| 18833 | + if (dhdp->logdump_cookie && dhd_logdump_cookie_count(dhdp) > 0) { |
---|
| 18834 | + ret = dhd_log_dump_cookie_to_file(dhdp, fp, user_buf, (unsigned long *)pos); |
---|
| 18835 | + } |
---|
| 18836 | + return ret; |
---|
| 18837 | +} |
---|
| 18838 | + |
---|
| 18839 | +#ifdef DHD_DUMP_PCIE_RINGS |
---|
| 18840 | +int |
---|
| 18841 | +dhd_print_flowring_data(void *dev, dhd_pub_t *dhdp, const void *user_buf, |
---|
| 18842 | + void *fp, uint32 len, void *pos) |
---|
| 18843 | +{ |
---|
| 18844 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18845 | + int ret = BCME_OK; |
---|
| 18846 | + uint32 remain_len = 0; |
---|
| 18847 | + dhd_info_t *dhd_info; |
---|
| 18848 | + |
---|
| 18849 | + if (dev) { |
---|
| 18850 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 18851 | + dhdp = &dhd_info->pub; |
---|
| 18852 | + } |
---|
| 18853 | + |
---|
| 18854 | + if (!dhdp) |
---|
| 18855 | + return BCME_ERROR; |
---|
| 18856 | + |
---|
| 18857 | + dhd_init_sec_hdr(&sec_hdr); |
---|
| 18858 | + |
---|
| 18859 | + remain_len = dhd_dump(dhdp, (char *)dhdp->concise_dbg_buf, CONCISE_DUMP_BUFLEN); |
---|
| 18860 | + memset(dhdp->concise_dbg_buf, 0, CONCISE_DUMP_BUFLEN); |
---|
| 18861 | + |
---|
| 18862 | + /* write the section header first */ |
---|
| 18863 | + ret = dhd_export_debug_data(FLOWRING_DUMP_HDR, fp, user_buf, |
---|
| 18864 | + strlen(FLOWRING_DUMP_HDR), pos); |
---|
| 18865 | + if (ret < 0) |
---|
| 18866 | + goto exit; |
---|
| 18867 | + |
---|
| 18868 | + /* Write the ring summary */ |
---|
| 18869 | + ret = dhd_export_debug_data(dhdp->concise_dbg_buf, fp, user_buf, |
---|
| 18870 | + (CONCISE_DUMP_BUFLEN - remain_len), pos); |
---|
| 18871 | + if (ret < 0) |
---|
| 18872 | + goto exit; |
---|
| 18873 | + |
---|
| 18874 | + sec_hdr.type = LOG_DUMP_SECTION_FLOWRING; |
---|
| 18875 | + sec_hdr.length = len; |
---|
| 18876 | + ret = dhd_export_debug_data((char *)&sec_hdr, fp, user_buf, sizeof(sec_hdr), pos); |
---|
| 18877 | + if (ret < 0) |
---|
| 18878 | + goto exit; |
---|
| 18879 | + |
---|
| 18880 | + /* write the log */ |
---|
| 18881 | + ret = dhd_d2h_h2d_ring_dump(dhdp, fp, user_buf, (unsigned long *)pos, TRUE); |
---|
| 18882 | + if (ret < 0) |
---|
| 18883 | + goto exit; |
---|
| 18884 | + |
---|
| 18885 | +exit: |
---|
| 18886 | + return ret; |
---|
| 18887 | +} |
---|
| 18888 | +#endif /* DHD_DUMP_PCIE_RINGS */ |
---|
| 18889 | + |
---|
| 18890 | +#ifdef EWP_ECNTRS_LOGGING |
---|
| 18891 | +int |
---|
| 18892 | +dhd_print_ecntrs_data(void *dev, dhd_pub_t *dhdp, const void *user_buf, |
---|
| 18893 | + void *fp, uint32 len, void *pos) |
---|
| 18894 | +{ |
---|
| 18895 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18896 | + int ret = BCME_OK; |
---|
| 18897 | + dhd_info_t *dhd_info; |
---|
| 18898 | + |
---|
| 18899 | + if (dev) { |
---|
| 18900 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 18901 | + dhdp = &dhd_info->pub; |
---|
| 18902 | + } |
---|
| 18903 | + |
---|
| 18904 | + if (!dhdp) |
---|
| 18905 | + return BCME_ERROR; |
---|
| 18906 | + |
---|
| 18907 | + dhd_init_sec_hdr(&sec_hdr); |
---|
| 18908 | + |
---|
| 18909 | + if (logdump_ecntr_enable && |
---|
| 18910 | + dhdp->ecntr_dbg_ring) { |
---|
| 18911 | + sec_hdr.type = LOG_DUMP_SECTION_ECNTRS; |
---|
| 18912 | + ret = dhd_dump_debug_ring(dhdp, dhdp->ecntr_dbg_ring, |
---|
| 18913 | + user_buf, &sec_hdr, ECNTRS_LOG_HDR, len, LOG_DUMP_SECTION_ECNTRS); |
---|
| 18914 | + } |
---|
| 18915 | + return ret; |
---|
| 18916 | + |
---|
| 18917 | +} |
---|
| 18918 | +#endif /* EWP_ECNTRS_LOGGING */ |
---|
| 18919 | + |
---|
| 18920 | +#ifdef EWP_RTT_LOGGING |
---|
| 18921 | +int |
---|
| 18922 | +dhd_print_rtt_data(void *dev, dhd_pub_t *dhdp, const void *user_buf, |
---|
| 18923 | + void *fp, uint32 len, void *pos) |
---|
| 18924 | +{ |
---|
| 18925 | + log_dump_section_hdr_t sec_hdr; |
---|
| 18926 | + int ret = BCME_OK; |
---|
| 18927 | + dhd_info_t *dhd_info; |
---|
| 18928 | + |
---|
| 18929 | + if (dev) { |
---|
| 18930 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 18931 | + dhdp = &dhd_info->pub; |
---|
| 18932 | + } |
---|
| 18933 | + |
---|
| 18934 | + if (!dhdp) |
---|
| 18935 | + return BCME_ERROR; |
---|
| 18936 | + |
---|
| 18937 | + dhd_init_sec_hdr(&sec_hdr); |
---|
| 18938 | + |
---|
| 18939 | + if (logdump_rtt_enable && dhdp->rtt_dbg_ring) { |
---|
| 18940 | + ret = dhd_dump_debug_ring(dhdp, dhdp->rtt_dbg_ring, |
---|
| 18941 | + user_buf, &sec_hdr, RTT_LOG_HDR, len, LOG_DUMP_SECTION_RTT); |
---|
| 18942 | + } |
---|
| 18943 | + return ret; |
---|
| 18944 | + |
---|
| 18945 | +} |
---|
| 18946 | +#endif /* EWP_RTT_LOGGING */ |
---|
| 18947 | + |
---|
| 18948 | +#ifdef DHD_STATUS_LOGGING |
---|
| 18949 | +int |
---|
| 18950 | +dhd_print_status_log_data(void *dev, dhd_pub_t *dhdp, const void *user_buf, |
---|
| 18951 | + void *fp, uint32 len, void *pos) |
---|
| 18952 | +{ |
---|
| 18953 | + dhd_info_t *dhd_info; |
---|
| 18954 | + |
---|
| 18955 | + if (dev) { |
---|
| 18956 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)dev); |
---|
| 18957 | + dhdp = &dhd_info->pub; |
---|
| 18958 | + } |
---|
| 18959 | + |
---|
| 18960 | + if (!dhdp) { |
---|
| 18961 | + return BCME_ERROR; |
---|
| 18962 | + } |
---|
| 18963 | + |
---|
| 18964 | + return dhd_statlog_write_logdump(dhdp, user_buf, fp, len, pos); |
---|
| 18965 | +} |
---|
| 18966 | + |
---|
| 18967 | +uint32 |
---|
| 18968 | +dhd_get_status_log_len(void *ndev, dhd_pub_t *dhdp) |
---|
| 18969 | +{ |
---|
| 18970 | + dhd_info_t *dhd_info; |
---|
| 18971 | + uint32 length = 0; |
---|
| 18972 | + |
---|
| 18973 | + if (ndev) { |
---|
| 18974 | + dhd_info = *(dhd_info_t **)netdev_priv((struct net_device *)ndev); |
---|
| 18975 | + dhdp = &dhd_info->pub; |
---|
| 18976 | + } |
---|
| 18977 | + |
---|
| 18978 | + if (dhdp) { |
---|
| 18979 | + length = dhd_statlog_get_logbuf_len(dhdp); |
---|
| 18980 | + } |
---|
| 18981 | + |
---|
| 18982 | + return length; |
---|
| 18983 | +} |
---|
| 18984 | +#endif /* DHD_STATUS_LOGGING */ |
---|
| 18985 | + |
---|
| 18986 | +void |
---|
| 18987 | +dhd_init_sec_hdr(log_dump_section_hdr_t *sec_hdr) |
---|
| 18988 | +{ |
---|
| 18989 | + /* prep the section header */ |
---|
| 18990 | + memset(sec_hdr, 0, sizeof(*sec_hdr)); |
---|
| 18991 | + sec_hdr->magic = LOG_DUMP_MAGIC; |
---|
| 18992 | + sec_hdr->timestamp = local_clock(); |
---|
| 18993 | +} |
---|
| 18994 | + |
---|
| 18995 | +/* Must hold 'dhd_os_logdump_lock' before calling this function ! */ |
---|
| 18996 | +static int |
---|
| 18997 | +do_dhd_log_dump(dhd_pub_t *dhdp, log_dump_type_t *type) |
---|
| 18998 | +{ |
---|
| 18999 | + int ret = 0, i = 0; |
---|
| 19000 | + struct file *fp = NULL; |
---|
| 19001 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 19002 | + mm_segment_t old_fs; |
---|
| 19003 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 19004 | + loff_t pos = 0; |
---|
| 19005 | + char dump_path[128]; |
---|
| 19006 | + uint32 file_mode; |
---|
| 19007 | + unsigned long flags = 0; |
---|
| 19008 | + size_t log_size = 0; |
---|
| 19009 | + size_t fspace_remain = 0; |
---|
| 19010 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) |
---|
| 19011 | + int isize = 0; |
---|
| 19012 | +#else |
---|
| 19013 | + struct kstat stat; |
---|
| 19014 | +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) */ |
---|
| 19015 | + char time_str[128]; |
---|
| 19016 | + unsigned int len = 0; |
---|
| 19017 | + log_dump_section_hdr_t sec_hdr; |
---|
| 19018 | + |
---|
| 19019 | + DHD_ERROR(("%s: ENTER \n", __FUNCTION__)); |
---|
| 19020 | + |
---|
| 19021 | + DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 19022 | + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp)) { |
---|
| 19023 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 19024 | + DHD_ERROR(("%s: bus is down! can't collect log dump. \n", __FUNCTION__)); |
---|
| 19025 | + goto exit1; |
---|
| 19026 | + } |
---|
| 19027 | + DHD_BUS_BUSY_SET_IN_LOGDUMP(dhdp); |
---|
| 19028 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 19029 | + |
---|
| 19030 | + if ((ret = dhd_log_flush(dhdp, type)) < 0) { |
---|
| 19031 | + goto exit1; |
---|
| 19032 | + } |
---|
| 19033 | + /* change to KERNEL_DS address limit */ |
---|
| 19034 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 19035 | + old_fs = get_fs(); |
---|
| 19036 | + set_fs(KERNEL_DS); |
---|
| 19037 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 19038 | + dhd_get_debug_dump_file_name(NULL, dhdp, dump_path, sizeof(dump_path)); |
---|
| 19039 | + |
---|
| 19040 | + DHD_ERROR(("debug_dump_path = %s\n", dump_path)); |
---|
| 19041 | + DHD_ERROR(("DHD version: %s\n", dhd_version)); |
---|
| 19042 | + DHD_ERROR(("F/W version: %s\n", fw_version)); |
---|
| 19043 | + |
---|
| 19044 | + dhd_log_dump_buf_addr(dhdp, type); |
---|
| 19045 | + |
---|
| 19046 | + dhd_get_time_str(dhdp, time_str, 128); |
---|
| 19047 | + |
---|
| 19048 | + /* if this is the first time after dhd is loaded, |
---|
| 19049 | + * or, if periodic flush is disabled, clear the log file |
---|
| 19050 | + */ |
---|
| 19051 | + if (!dhdp->logdump_periodic_flush || dhdp->last_file_posn == 0) |
---|
| 19052 | + file_mode = O_CREAT | O_WRONLY | O_SYNC | O_TRUNC; |
---|
| 19053 | + else |
---|
| 19054 | + file_mode = O_CREAT | O_RDWR | O_SYNC; |
---|
| 19055 | + |
---|
| 19056 | + fp = filp_open(dump_path, file_mode, 0664); |
---|
| 19057 | + if (IS_ERR(fp)) { |
---|
| 19058 | + /* If android installed image, try '/data' directory */ |
---|
| 19059 | +#if defined(CONFIG_X86) && defined(OEM_ANDROID) |
---|
| 19060 | + DHD_ERROR(("%s: File open error on Installed android image, trying /data...\n", |
---|
| 19061 | + __FUNCTION__)); |
---|
| 19062 | + snprintf(dump_path, sizeof(dump_path), "/root/" DHD_DEBUG_DUMP_TYPE); |
---|
| 19063 | + if (!dhdp->logdump_periodic_flush) { |
---|
| 19064 | + snprintf(dump_path + strlen(dump_path), |
---|
| 19065 | + sizeof(dump_path) - strlen(dump_path), |
---|
| 19066 | + "_%s", dhdp->debug_dump_time_str); |
---|
| 19067 | + } |
---|
| 19068 | + fp = filp_open(dump_path, file_mode, 0664); |
---|
| 19069 | + if (IS_ERR(fp)) { |
---|
| 19070 | + ret = PTR_ERR(fp); |
---|
| 19071 | + DHD_ERROR(("open file error, err = %d\n", ret)); |
---|
| 19072 | + goto exit2; |
---|
| 19073 | + } |
---|
| 19074 | + DHD_ERROR(("debug_dump_path = %s\n", dump_path)); |
---|
| 19075 | +#else |
---|
| 19076 | + ret = PTR_ERR(fp); |
---|
| 19077 | + DHD_ERROR(("open file error, err = %d\n", ret)); |
---|
| 19078 | + goto exit2; |
---|
| 19079 | +#endif /* CONFIG_X86 && OEM_ANDROID */ |
---|
| 19080 | + } |
---|
| 19081 | + |
---|
| 19082 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) |
---|
| 19083 | + isize = i_size_read(file_inode(fp)); |
---|
| 19084 | + |
---|
| 19085 | + /* if some one else has changed the file */ |
---|
| 19086 | + if (dhdp->last_file_posn != 0 && |
---|
| 19087 | + isize < dhdp->last_file_posn) { |
---|
| 19088 | + dhdp->last_file_posn = 0; |
---|
| 19089 | + } |
---|
| 19090 | +#else |
---|
| 19091 | + ret = vfs_stat(dump_path, &stat); |
---|
| 19092 | + if (ret < 0) { |
---|
| 19093 | + DHD_ERROR(("file stat error, err = %d\n", ret)); |
---|
| 19094 | + goto exit2; |
---|
| 19095 | + } |
---|
| 19096 | + |
---|
| 19097 | + /* if some one else has changed the file */ |
---|
| 19098 | + if (dhdp->last_file_posn != 0 && |
---|
| 19099 | + stat.size < dhdp->last_file_posn) { |
---|
| 19100 | + dhdp->last_file_posn = 0; |
---|
| 19101 | + } |
---|
| 19102 | +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) */ |
---|
| 19103 | + if (dhdp->logdump_periodic_flush) { |
---|
| 19104 | + log_size = strlen(time_str) + strlen(DHD_DUMP_LOG_HDR) + sizeof(sec_hdr); |
---|
| 19105 | + /* calculate the amount of space required to dump all logs */ |
---|
| 19106 | + for (i = 0; i < DLD_BUFFER_NUM; ++i) { |
---|
| 19107 | + if (*type != DLD_BUF_TYPE_ALL && i != *type) |
---|
| 19108 | + continue; |
---|
| 19109 | + |
---|
| 19110 | + if (g_dld_buf[i].wraparound) { |
---|
| 19111 | + log_size += (unsigned long)g_dld_buf[i].max |
---|
| 19112 | + - (unsigned long)g_dld_buf[i].buffer; |
---|
| 19113 | + } else { |
---|
| 19114 | + spin_lock_irqsave(&g_dld_buf[i].lock, flags); |
---|
| 19115 | + log_size += (unsigned long)g_dld_buf[i].present - |
---|
| 19116 | + (unsigned long)g_dld_buf[i].front; |
---|
| 19117 | + spin_unlock_irqrestore(&g_dld_buf[i].lock, flags); |
---|
| 19118 | + } |
---|
| 19119 | + log_size += strlen(dld_hdrs[i].hdr_str) + sizeof(sec_hdr); |
---|
| 19120 | + |
---|
| 19121 | + if (*type != DLD_BUF_TYPE_ALL && i == *type) |
---|
| 19122 | + break; |
---|
| 19123 | + } |
---|
| 19124 | + |
---|
| 19125 | + ret = generic_file_llseek(fp, dhdp->last_file_posn, SEEK_CUR); |
---|
| 19126 | + if (ret < 0) { |
---|
| 19127 | + DHD_ERROR(("file seek last posn error ! err = %d \n", ret)); |
---|
| 19128 | + goto exit2; |
---|
| 19129 | + } |
---|
| 19130 | + pos = fp->f_pos; |
---|
| 19131 | + |
---|
| 19132 | + /* if the max file size is reached, wrap around to beginning of the file |
---|
| 19133 | + * we're treating the file as a large ring buffer |
---|
| 19134 | + */ |
---|
| 19135 | + fspace_remain = logdump_max_filesize - pos; |
---|
| 19136 | + if (log_size > fspace_remain) { |
---|
| 19137 | + fp->f_pos -= pos; |
---|
| 19138 | + pos = fp->f_pos; |
---|
| 19139 | + } |
---|
| 19140 | + } |
---|
| 19141 | + |
---|
| 19142 | + dhd_print_time_str(0, fp, len, &pos); |
---|
| 19143 | + |
---|
| 19144 | + for (i = 0; i < DLD_BUFFER_NUM; ++i) { |
---|
| 19145 | + |
---|
| 19146 | + if (*type != DLD_BUF_TYPE_ALL && i != *type) |
---|
| 19147 | + continue; |
---|
| 19148 | + |
---|
| 19149 | + len = dhd_get_dld_len(i); |
---|
| 19150 | + dhd_get_dld_log_dump(NULL, dhdp, 0, fp, len, i, &pos); |
---|
| 19151 | + if (*type != DLD_BUF_TYPE_ALL) |
---|
| 19152 | + break; |
---|
| 19153 | + } |
---|
| 19154 | + |
---|
| 19155 | +#ifdef EWP_ECNTRS_LOGGING |
---|
| 19156 | + /* periodic flushing of ecounters is NOT supported */ |
---|
| 19157 | + if (*type == DLD_BUF_TYPE_ALL && |
---|
| 19158 | + logdump_ecntr_enable && |
---|
| 19159 | + dhdp->ecntr_dbg_ring) { |
---|
| 19160 | + dhd_log_dump_ring_to_file(dhdp, dhdp->ecntr_dbg_ring, |
---|
| 19161 | + fp, (unsigned long *)&pos, |
---|
| 19162 | + &sec_hdr, ECNTRS_LOG_HDR, LOG_DUMP_SECTION_ECNTRS); |
---|
| 19163 | + } |
---|
| 19164 | +#endif /* EWP_ECNTRS_LOGGING */ |
---|
| 19165 | + |
---|
| 19166 | +#ifdef DHD_STATUS_LOGGING |
---|
| 19167 | + if (dhdp->statlog) { |
---|
| 19168 | + /* write the statlog */ |
---|
| 19169 | + len = dhd_get_status_log_len(NULL, dhdp); |
---|
| 19170 | + if (len) { |
---|
| 19171 | + if (dhd_print_status_log_data(NULL, dhdp, 0, fp, |
---|
| 19172 | + len, &pos) < 0) { |
---|
| 19173 | + goto exit2; |
---|
| 19174 | + } |
---|
| 19175 | + } |
---|
| 19176 | + } |
---|
| 19177 | +#endif /* DHD_STATUS_LOGGING */ |
---|
| 19178 | + |
---|
| 19179 | +#ifdef EWP_RTT_LOGGING |
---|
| 19180 | + /* periodic flushing of ecounters is NOT supported */ |
---|
| 19181 | + if (*type == DLD_BUF_TYPE_ALL && |
---|
| 19182 | + logdump_rtt_enable && |
---|
| 19183 | + dhdp->rtt_dbg_ring) { |
---|
| 19184 | + dhd_log_dump_ring_to_file(dhdp, dhdp->rtt_dbg_ring, |
---|
| 19185 | + fp, (unsigned long *)&pos, |
---|
| 19186 | + &sec_hdr, RTT_LOG_HDR, LOG_DUMP_SECTION_RTT); |
---|
| 19187 | + } |
---|
| 19188 | +#endif /* EWP_RTT_LOGGING */ |
---|
| 19189 | + |
---|
| 19190 | +#ifdef BCMPCIE |
---|
| 19191 | + len = dhd_get_ext_trap_len(NULL, dhdp); |
---|
| 19192 | + if (len) { |
---|
| 19193 | + if (dhd_print_ext_trap_data(NULL, dhdp, 0, fp, len, &pos) < 0) |
---|
| 19194 | + goto exit2; |
---|
| 19195 | + } |
---|
| 19196 | +#endif /* BCMPCIE */ |
---|
| 19197 | + |
---|
| 19198 | +#if defined(DHD_FW_COREDUMP) && defined(DNGL_EVENT_SUPPORT) && defined(BCMPCIE) |
---|
| 19199 | + len = dhd_get_health_chk_len(NULL, dhdp); |
---|
| 19200 | + if (len) { |
---|
| 19201 | + if (dhd_print_ext_trap_data(NULL, dhdp, 0, fp, len, &pos) < 0) |
---|
| 19202 | + goto exit2; |
---|
| 19203 | + } |
---|
| 19204 | +#endif /* DHD_FW_COREDUMP && DNGL_EVENT_SUPPORT && BCMPCIE */ |
---|
| 19205 | + |
---|
| 19206 | + len = dhd_get_dhd_dump_len(NULL, dhdp); |
---|
| 19207 | + if (len) { |
---|
| 19208 | + if (dhd_print_dump_data(NULL, dhdp, 0, fp, len, &pos) < 0) |
---|
| 19209 | + goto exit2; |
---|
| 19210 | + } |
---|
| 19211 | + |
---|
| 19212 | + len = dhd_get_cookie_log_len(NULL, dhdp); |
---|
| 19213 | + if (len) { |
---|
| 19214 | + if (dhd_print_cookie_data(NULL, dhdp, 0, fp, len, &pos) < 0) |
---|
| 19215 | + goto exit2; |
---|
| 19216 | + } |
---|
| 19217 | + |
---|
| 19218 | +#ifdef DHD_DUMP_PCIE_RINGS |
---|
| 19219 | + len = dhd_get_flowring_len(NULL, dhdp); |
---|
| 19220 | + if (len) { |
---|
| 19221 | + if (dhd_print_flowring_data(NULL, dhdp, 0, fp, len, &pos) < 0) |
---|
| 19222 | + goto exit2; |
---|
| 19223 | + } |
---|
| 19224 | +#endif // endif |
---|
| 19225 | + |
---|
| 19226 | + if (dhdp->logdump_periodic_flush) { |
---|
| 19227 | + /* store the last position written to in the file for future use */ |
---|
| 19228 | + dhdp->last_file_posn = pos; |
---|
| 19229 | + } |
---|
| 19230 | + |
---|
| 19231 | +exit2: |
---|
| 19232 | + if (!IS_ERR(fp) && fp != NULL) { |
---|
| 19233 | + filp_close(fp, NULL); |
---|
| 19234 | + DHD_ERROR(("%s: Finished writing log dump to file - '%s' \n", |
---|
| 19235 | + __FUNCTION__, dump_path)); |
---|
| 19236 | + } |
---|
| 19237 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 19238 | + set_fs(old_fs); |
---|
| 19239 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 19240 | +exit1: |
---|
| 19241 | + if (type) { |
---|
| 19242 | + MFREE(dhdp->osh, type, sizeof(*type)); |
---|
| 19243 | + } |
---|
| 19244 | + DHD_GENERAL_LOCK(dhdp, flags); |
---|
| 19245 | + DHD_BUS_BUSY_CLEAR_IN_LOGDUMP(dhdp); |
---|
| 19246 | + dhd_os_busbusy_wake(dhdp); |
---|
| 19247 | + DHD_GENERAL_UNLOCK(dhdp, flags); |
---|
| 19248 | + |
---|
| 19249 | +#ifdef DHD_DUMP_MNGR |
---|
| 19250 | + if (ret >= 0) { |
---|
| 19251 | + dhd_dump_file_manage_enqueue(dhdp, dump_path, DHD_DEBUG_DUMP_TYPE); |
---|
| 19252 | + } |
---|
| 19253 | +#endif /* DHD_DUMP_MNGR */ |
---|
| 19254 | + |
---|
| 19255 | + return (ret < 0) ? BCME_ERROR : BCME_OK; |
---|
| 19256 | +} |
---|
| 19257 | +#endif /* DHD_LOG_DUMP */ |
---|
| 19258 | + |
---|
| 19259 | +/* This function writes data to the file pointed by fp, OR |
---|
| 19260 | + * copies data to the user buffer sent by upper layer(HAL). |
---|
| 19261 | + */ |
---|
| 19262 | +int |
---|
| 19263 | +dhd_export_debug_data(void *mem_buf, void *fp, const void *user_buf, int buf_len, void *pos) |
---|
| 19264 | +{ |
---|
| 19265 | + int ret = BCME_OK; |
---|
| 19266 | + |
---|
| 19267 | + if (fp) { |
---|
| 19268 | + ret = vfs_write(fp, mem_buf, buf_len, (loff_t *)pos); |
---|
| 19269 | + if (ret < 0) { |
---|
| 19270 | + DHD_ERROR(("write file error, err = %d\n", ret)); |
---|
| 19271 | + goto exit; |
---|
| 19272 | + } |
---|
| 19273 | + } else { |
---|
| 19274 | + { |
---|
| 19275 | + ret = copy_to_user((void *)((uintptr_t)user_buf + (*(int *)pos)), |
---|
| 19276 | + mem_buf, buf_len); |
---|
| 19277 | + if (ret) { |
---|
| 19278 | + DHD_ERROR(("failed to copy into user buffer : %d\n", ret)); |
---|
| 19279 | + goto exit; |
---|
| 19280 | + } |
---|
| 19281 | + } |
---|
| 19282 | + (*(int *)pos) += buf_len; |
---|
| 19283 | + } |
---|
| 19284 | +exit: |
---|
| 19285 | + return ret; |
---|
| 19286 | +} |
---|
| 19287 | + |
---|
| 19288 | +/* |
---|
| 19289 | + * This call is to get the memdump size so that, |
---|
| 19290 | + * halutil can alloc that much buffer in user space. |
---|
| 19291 | + */ |
---|
| 19292 | +int |
---|
| 19293 | +dhd_os_socram_dump(struct net_device *dev, uint32 *dump_size) |
---|
13788 | 19294 | { |
---|
13789 | 19295 | int ret = BCME_OK; |
---|
13790 | 19296 | dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
13791 | 19297 | dhd_pub_t *dhdp = &dhd->pub; |
---|
| 19298 | + |
---|
| 19299 | + if (dhdp->busstate == DHD_BUS_DOWN) { |
---|
| 19300 | + DHD_ERROR(("%s: bus is down\n", __FUNCTION__)); |
---|
| 19301 | + return BCME_ERROR; |
---|
| 19302 | + } |
---|
| 19303 | + |
---|
| 19304 | + if (DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(dhdp)) { |
---|
| 19305 | + DHD_ERROR(("%s: bus is in suspend(%d) or suspending(0x%x) state, so skip\n", |
---|
| 19306 | + __FUNCTION__, dhdp->busstate, dhdp->dhd_bus_busy_state)); |
---|
| 19307 | + return BCME_ERROR; |
---|
| 19308 | + } |
---|
| 19309 | +#ifdef DHD_PCIE_RUNTIMEPM |
---|
| 19310 | + dhdpcie_runtime_bus_wake(dhdp, TRUE, __builtin_return_address(0)); |
---|
| 19311 | +#endif /* DHD_PCIE_RUNTIMEPM */ |
---|
13792 | 19312 | ret = dhd_common_socram_dump(dhdp); |
---|
13793 | 19313 | if (ret == BCME_OK) { |
---|
13794 | 19314 | *dump_size = dhdp->soc_ram_length; |
---|
.. | .. |
---|
13796 | 19316 | return ret; |
---|
13797 | 19317 | } |
---|
13798 | 19318 | |
---|
13799 | | -int dhd_os_get_socram_dump(struct net_device *dev, char **buf, uint32 *size) |
---|
| 19319 | +/* |
---|
| 19320 | + * This is to get the actual memdup after getting the memdump size |
---|
| 19321 | + */ |
---|
| 19322 | +int |
---|
| 19323 | +dhd_os_get_socram_dump(struct net_device *dev, char **buf, uint32 *size) |
---|
13800 | 19324 | { |
---|
13801 | 19325 | int ret = BCME_OK; |
---|
13802 | 19326 | int orig_len = 0; |
---|
.. | .. |
---|
13807 | 19331 | orig_len = *size; |
---|
13808 | 19332 | if (dhdp->soc_ram) { |
---|
13809 | 19333 | if (orig_len >= dhdp->soc_ram_length) { |
---|
13810 | | - memcpy(*buf, dhdp->soc_ram, dhdp->soc_ram_length); |
---|
13811 | | - /* reset the storage of dump */ |
---|
13812 | | - memset(dhdp->soc_ram, 0, dhdp->soc_ram_length); |
---|
| 19334 | + *buf = dhdp->soc_ram; |
---|
13813 | 19335 | *size = dhdp->soc_ram_length; |
---|
13814 | | - dhdp->soc_ram_length = 0; |
---|
13815 | 19336 | } else { |
---|
13816 | 19337 | ret = BCME_BUFTOOSHORT; |
---|
13817 | 19338 | DHD_ERROR(("The length of the buffer is too short" |
---|
.. | .. |
---|
13824 | 19345 | return ret; |
---|
13825 | 19346 | } |
---|
13826 | 19347 | |
---|
13827 | | -int dhd_os_get_version(struct net_device *dev, bool dhd_ver, char **buf, uint32 size) |
---|
| 19348 | +int |
---|
| 19349 | +dhd_os_get_version(struct net_device *dev, bool dhd_ver, char **buf, uint32 size) |
---|
13828 | 19350 | { |
---|
13829 | | - int ret = BCME_OK; |
---|
| 19351 | + char *fw_str; |
---|
| 19352 | + |
---|
| 19353 | + if (size == 0) |
---|
| 19354 | + return BCME_BADARG; |
---|
| 19355 | + |
---|
| 19356 | + fw_str = strstr(info_string, "Firmware: "); |
---|
| 19357 | + if (fw_str == NULL) { |
---|
| 19358 | + return BCME_ERROR; |
---|
| 19359 | + } |
---|
| 19360 | + |
---|
13830 | 19361 | memset(*buf, 0, size); |
---|
13831 | 19362 | if (dhd_ver) { |
---|
13832 | 19363 | strncpy(*buf, dhd_version, size - 1); |
---|
13833 | 19364 | } else { |
---|
13834 | | - strncpy(*buf, strstr(info_string, "Firmware: "), size - 1); |
---|
| 19365 | + strncpy(*buf, fw_str, size - 1); |
---|
| 19366 | + } |
---|
| 19367 | + return BCME_OK; |
---|
| 19368 | +} |
---|
| 19369 | + |
---|
| 19370 | +#ifdef DHD_PKT_LOGGING |
---|
| 19371 | +int |
---|
| 19372 | +dhd_os_get_pktlog_dump(void *dev, const void *user_buf, uint32 len) |
---|
| 19373 | +{ |
---|
| 19374 | + int ret = BCME_OK; |
---|
| 19375 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
| 19376 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 19377 | + if (user_buf == NULL) { |
---|
| 19378 | + DHD_ERROR(("%s(): user buffer is NULL\n", __FUNCTION__)); |
---|
| 19379 | + return BCME_ERROR; |
---|
| 19380 | + } |
---|
| 19381 | + |
---|
| 19382 | + ret = dhd_pktlog_dump_write_memory(dhdp, user_buf, len); |
---|
| 19383 | + if (ret < 0) { |
---|
| 19384 | + DHD_ERROR(("%s(): fail to dump pktlog, err = %d\n", __FUNCTION__, ret)); |
---|
| 19385 | + return ret; |
---|
13835 | 19386 | } |
---|
13836 | 19387 | return ret; |
---|
13837 | 19388 | } |
---|
13838 | 19389 | |
---|
13839 | | -static void |
---|
13840 | | -dhd_mem_dump(void *handle, void *event_info, u8 event) |
---|
| 19390 | +uint32 |
---|
| 19391 | +dhd_os_get_pktlog_dump_size(struct net_device *dev) |
---|
13841 | 19392 | { |
---|
13842 | | - dhd_info_t *dhd = handle; |
---|
13843 | | - dhd_dump_t *dump = event_info; |
---|
| 19393 | + uint32 size = 0; |
---|
| 19394 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
| 19395 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
13844 | 19396 | |
---|
13845 | | - if (!dhd) { |
---|
13846 | | - DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); |
---|
13847 | | - return; |
---|
| 19397 | + size = dhd_pktlog_get_dump_length(dhdp); |
---|
| 19398 | + if (size == 0) { |
---|
| 19399 | + DHD_ERROR(("%s(): fail to get pktlog size, err = %d\n", __FUNCTION__, size)); |
---|
13848 | 19400 | } |
---|
13849 | | - |
---|
13850 | | - if (!dump) { |
---|
13851 | | - DHD_ERROR(("%s: dump is NULL\n", __FUNCTION__)); |
---|
13852 | | - return; |
---|
13853 | | - } |
---|
13854 | | - |
---|
13855 | | - if (write_to_file(&dhd->pub, dump->buf, dump->bufsize)) { |
---|
13856 | | - DHD_ERROR(("%s: writing SoC_RAM dump to the file failed\n", __FUNCTION__)); |
---|
13857 | | - } |
---|
13858 | | - |
---|
13859 | | - if (dhd->pub.memdump_enabled == DUMP_MEMFILE_BUGON) { |
---|
13860 | | - BUG_ON(1); |
---|
13861 | | - } |
---|
13862 | | - MFREE(dhd->pub.osh, dump, sizeof(dhd_dump_t)); |
---|
| 19401 | + return size; |
---|
13863 | 19402 | } |
---|
13864 | | -#endif /* DHD_FW_COREDUMP */ |
---|
13865 | 19403 | |
---|
13866 | | - |
---|
13867 | | -#ifdef DHD_WMF |
---|
13868 | | -/* Returns interface specific WMF configuration */ |
---|
13869 | | -dhd_wmf_t* dhd_wmf_conf(dhd_pub_t *dhdp, uint32 idx) |
---|
| 19404 | +void |
---|
| 19405 | +dhd_os_get_pktlogdump_filename(struct net_device *dev, char *dump_path, int len) |
---|
13870 | 19406 | { |
---|
13871 | | - dhd_info_t *dhd = dhdp->info; |
---|
13872 | | - dhd_if_t *ifp; |
---|
| 19407 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
| 19408 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
13873 | 19409 | |
---|
13874 | | - ASSERT(idx < DHD_MAX_IFS); |
---|
13875 | | - |
---|
13876 | | - ifp = dhd->iflist[idx]; |
---|
13877 | | - return &ifp->wmf; |
---|
| 19410 | + dhd_pktlog_get_filename(dhdp, dump_path, len); |
---|
13878 | 19411 | } |
---|
13879 | | -#endif /* DHD_WMF */ |
---|
13880 | | - |
---|
13881 | | -#if defined(TRAFFIC_MGMT_DWM) |
---|
13882 | | -void traffic_mgmt_pkt_set_prio(dhd_pub_t *dhdp, void * pktbuf) |
---|
| 19412 | +#endif /* DHD_PKT_LOGGING */ |
---|
| 19413 | +#ifdef DNGL_AXI_ERROR_LOGGING |
---|
| 19414 | +int |
---|
| 19415 | +dhd_os_get_axi_error_dump(void *dev, const void *user_buf, uint32 len) |
---|
13883 | 19416 | { |
---|
13884 | | - struct ether_header *eh; |
---|
13885 | | - struct ethervlan_header *evh; |
---|
13886 | | - uint8 *pktdata, *ip_body; |
---|
13887 | | - uint8 dwm_filter; |
---|
13888 | | - uint8 tos_tc = 0; |
---|
13889 | | - uint8 dscp = 0; |
---|
13890 | | - pktdata = (uint8 *)PKTDATA(dhdp->osh, pktbuf); |
---|
13891 | | - eh = (struct ether_header *) pktdata; |
---|
13892 | | - ip_body = NULL; |
---|
13893 | | - |
---|
13894 | | - if (dhdp->dhd_tm_dwm_tbl.dhd_dwm_enabled) { |
---|
13895 | | - if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) { |
---|
13896 | | - evh = (struct ethervlan_header *)eh; |
---|
13897 | | - if ((evh->ether_type == hton16(ETHER_TYPE_IP)) || |
---|
13898 | | - (evh->ether_type == hton16(ETHER_TYPE_IPV6))) { |
---|
13899 | | - ip_body = pktdata + sizeof(struct ethervlan_header); |
---|
13900 | | - } |
---|
13901 | | - } else if ((eh->ether_type == hton16(ETHER_TYPE_IP)) || |
---|
13902 | | - (eh->ether_type == hton16(ETHER_TYPE_IPV6))) { |
---|
13903 | | - ip_body = pktdata + sizeof(struct ether_header); |
---|
13904 | | - } |
---|
13905 | | - if (ip_body) { |
---|
13906 | | - tos_tc = IP_TOS46(ip_body); |
---|
13907 | | - dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT; |
---|
13908 | | - } |
---|
13909 | | - |
---|
13910 | | - if (dscp < DHD_DWM_TBL_SIZE) { |
---|
13911 | | - dwm_filter = dhdp->dhd_tm_dwm_tbl.dhd_dwm_tbl[dscp]; |
---|
13912 | | - if (DHD_TRF_MGMT_DWM_IS_FILTER_SET(dwm_filter)) { |
---|
13913 | | - PKTSETPRIO(pktbuf, DHD_TRF_MGMT_DWM_PRIO(dwm_filter)); |
---|
13914 | | - } |
---|
13915 | | - } |
---|
| 19417 | + int ret = BCME_OK; |
---|
| 19418 | + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); |
---|
| 19419 | + dhd_pub_t *dhdp = &dhd->pub; |
---|
| 19420 | + loff_t pos = 0; |
---|
| 19421 | + if (user_buf == NULL) { |
---|
| 19422 | + DHD_ERROR(("%s(): user buffer is NULL\n", __FUNCTION__)); |
---|
| 19423 | + return BCME_ERROR; |
---|
13916 | 19424 | } |
---|
13917 | | -} |
---|
13918 | | -#endif |
---|
13919 | 19425 | |
---|
13920 | | -#if defined(DHD_L2_FILTER) |
---|
| 19426 | + ret = dhd_export_debug_data((char *)dhdp->axi_err_dump, |
---|
| 19427 | + NULL, user_buf, sizeof(dhd_axi_error_dump_t), &pos); |
---|
| 19428 | + |
---|
| 19429 | + if (ret < 0) { |
---|
| 19430 | + DHD_ERROR(("%s(): fail to dump pktlog, err = %d\n", __FUNCTION__, ret)); |
---|
| 19431 | + return ret; |
---|
| 19432 | + } |
---|
| 19433 | + return ret; |
---|
| 19434 | +} |
---|
| 19435 | + |
---|
| 19436 | +int |
---|
| 19437 | +dhd_os_get_axi_error_dump_size(struct net_device *dev) |
---|
| 19438 | +{ |
---|
| 19439 | + int size = -1; |
---|
| 19440 | + |
---|
| 19441 | + size = sizeof(dhd_axi_error_dump_t); |
---|
| 19442 | + if (size < 0) { |
---|
| 19443 | + DHD_ERROR(("%s(): fail to get axi error size, err = %d\n", __FUNCTION__, size)); |
---|
| 19444 | + } |
---|
| 19445 | + return size; |
---|
| 19446 | +} |
---|
| 19447 | + |
---|
| 19448 | +void |
---|
| 19449 | +dhd_os_get_axi_error_filename(struct net_device *dev, char *dump_path, int len) |
---|
| 19450 | +{ |
---|
| 19451 | + snprintf(dump_path, len, "%s", |
---|
| 19452 | + DHD_COMMON_DUMP_PATH DHD_DUMP_AXI_ERROR_FILENAME); |
---|
| 19453 | +} |
---|
| 19454 | +#endif /* DNGL_AXI_ERROR_LOGGING */ |
---|
| 19455 | + |
---|
13921 | 19456 | bool dhd_sta_associated(dhd_pub_t *dhdp, uint32 bssidx, uint8 *mac) |
---|
13922 | 19457 | { |
---|
13923 | 19458 | return dhd_find_sta(dhdp, bssidx, mac) ? TRUE : FALSE; |
---|
13924 | 19459 | } |
---|
13925 | | -#endif |
---|
13926 | 19460 | |
---|
13927 | 19461 | #ifdef DHD_L2_FILTER |
---|
13928 | 19462 | arp_table_t* |
---|
.. | .. |
---|
14091 | 19625 | |
---|
14092 | 19626 | return BCME_OK; |
---|
14093 | 19627 | } |
---|
14094 | | -#endif /* DHD_L2_FILTER */ |
---|
14095 | 19628 | |
---|
| 19629 | +int dhd_get_block_tdls_status(dhd_pub_t *dhdp, uint32 idx) |
---|
| 19630 | +{ |
---|
| 19631 | + dhd_info_t *dhd = dhdp->info; |
---|
| 19632 | + dhd_if_t *ifp; |
---|
| 19633 | + |
---|
| 19634 | + ASSERT(idx < DHD_MAX_IFS); |
---|
| 19635 | + |
---|
| 19636 | + ifp = dhd->iflist[idx]; |
---|
| 19637 | + |
---|
| 19638 | + ASSERT(ifp); |
---|
| 19639 | + |
---|
| 19640 | + return ifp->block_tdls; |
---|
| 19641 | +} |
---|
| 19642 | + |
---|
| 19643 | +int dhd_set_block_tdls_status(dhd_pub_t *dhdp, uint32 idx, int val) |
---|
| 19644 | +{ |
---|
| 19645 | + dhd_info_t *dhd = dhdp->info; |
---|
| 19646 | + dhd_if_t *ifp; |
---|
| 19647 | + ASSERT(idx < DHD_MAX_IFS); |
---|
| 19648 | + ifp = dhd->iflist[idx]; |
---|
| 19649 | + |
---|
| 19650 | + ASSERT(ifp); |
---|
| 19651 | + |
---|
| 19652 | + ifp->block_tdls = val; |
---|
| 19653 | + |
---|
| 19654 | + return BCME_OK; |
---|
| 19655 | +} |
---|
| 19656 | +#endif /* DHD_L2_FILTER */ |
---|
14096 | 19657 | |
---|
14097 | 19658 | #if defined(SET_RPS_CPUS) |
---|
14098 | 19659 | int dhd_rps_cpus_enable(struct net_device *net, int enable) |
---|
.. | .. |
---|
14216 | 19777 | DHD_INFO(("%s : rps_cpus map clear.\n", __FUNCTION__)); |
---|
14217 | 19778 | } |
---|
14218 | 19779 | } |
---|
14219 | | -#endif |
---|
| 19780 | +#endif // endif |
---|
14220 | 19781 | |
---|
| 19782 | +#if defined(ARGOS_NOTIFY_CB) |
---|
14221 | 19783 | |
---|
| 19784 | +static int argos_status_notifier_wifi_cb(struct notifier_block *notifier, |
---|
| 19785 | + unsigned long speed, void *v); |
---|
| 19786 | +static int argos_status_notifier_p2p_cb(struct notifier_block *notifier, |
---|
| 19787 | + unsigned long speed, void *v); |
---|
| 19788 | + |
---|
| 19789 | +int |
---|
| 19790 | +argos_register_notifier_init(struct net_device *net) |
---|
| 19791 | +{ |
---|
| 19792 | + int ret = 0; |
---|
| 19793 | + |
---|
| 19794 | + DHD_INFO(("DHD: %s: \n", __FUNCTION__)); |
---|
| 19795 | + argos_rps_ctrl_data.wlan_primary_netdev = net; |
---|
| 19796 | + argos_rps_ctrl_data.argos_rps_cpus_enabled = 0; |
---|
| 19797 | + |
---|
| 19798 | + if (argos_wifi.notifier_call == NULL) { |
---|
| 19799 | + argos_wifi.notifier_call = argos_status_notifier_wifi_cb; |
---|
| 19800 | + ret = sec_argos_register_notifier(&argos_wifi, ARGOS_WIFI_TABLE_LABEL); |
---|
| 19801 | + if (ret < 0) { |
---|
| 19802 | + DHD_ERROR(("DHD:Failed to register WIFI notifier, ret=%d\n", ret)); |
---|
| 19803 | + goto exit; |
---|
| 19804 | + } |
---|
| 19805 | + } |
---|
| 19806 | + |
---|
| 19807 | + if (argos_p2p.notifier_call == NULL) { |
---|
| 19808 | + argos_p2p.notifier_call = argos_status_notifier_p2p_cb; |
---|
| 19809 | + ret = sec_argos_register_notifier(&argos_p2p, ARGOS_P2P_TABLE_LABEL); |
---|
| 19810 | + if (ret < 0) { |
---|
| 19811 | + DHD_ERROR(("DHD:Failed to register P2P notifier, ret=%d\n", ret)); |
---|
| 19812 | + sec_argos_unregister_notifier(&argos_wifi, ARGOS_WIFI_TABLE_LABEL); |
---|
| 19813 | + goto exit; |
---|
| 19814 | + } |
---|
| 19815 | + } |
---|
| 19816 | + |
---|
| 19817 | + return 0; |
---|
| 19818 | + |
---|
| 19819 | +exit: |
---|
| 19820 | + if (argos_wifi.notifier_call) { |
---|
| 19821 | + argos_wifi.notifier_call = NULL; |
---|
| 19822 | + } |
---|
| 19823 | + |
---|
| 19824 | + if (argos_p2p.notifier_call) { |
---|
| 19825 | + argos_p2p.notifier_call = NULL; |
---|
| 19826 | + } |
---|
| 19827 | + |
---|
| 19828 | + return ret; |
---|
| 19829 | +} |
---|
| 19830 | + |
---|
| 19831 | +int |
---|
| 19832 | +argos_register_notifier_deinit(void) |
---|
| 19833 | +{ |
---|
| 19834 | + DHD_INFO(("DHD: %s: \n", __FUNCTION__)); |
---|
| 19835 | + |
---|
| 19836 | + if (argos_rps_ctrl_data.wlan_primary_netdev == NULL) { |
---|
| 19837 | + DHD_ERROR(("DHD: primary_net_dev is null %s: \n", __FUNCTION__)); |
---|
| 19838 | + return -1; |
---|
| 19839 | + } |
---|
| 19840 | +#ifndef DHD_LB |
---|
| 19841 | + custom_rps_map_clear(argos_rps_ctrl_data.wlan_primary_netdev->_rx); |
---|
| 19842 | +#endif /* !DHD_LB */ |
---|
| 19843 | + |
---|
| 19844 | + if (argos_p2p.notifier_call) { |
---|
| 19845 | + sec_argos_unregister_notifier(&argos_p2p, ARGOS_P2P_TABLE_LABEL); |
---|
| 19846 | + argos_p2p.notifier_call = NULL; |
---|
| 19847 | + } |
---|
| 19848 | + |
---|
| 19849 | + if (argos_wifi.notifier_call) { |
---|
| 19850 | + sec_argos_unregister_notifier(&argos_wifi, ARGOS_WIFI_TABLE_LABEL); |
---|
| 19851 | + argos_wifi.notifier_call = NULL; |
---|
| 19852 | + } |
---|
| 19853 | + |
---|
| 19854 | + argos_rps_ctrl_data.wlan_primary_netdev = NULL; |
---|
| 19855 | + argos_rps_ctrl_data.argos_rps_cpus_enabled = 0; |
---|
| 19856 | + |
---|
| 19857 | + return 0; |
---|
| 19858 | +} |
---|
| 19859 | + |
---|
| 19860 | +int |
---|
| 19861 | +argos_status_notifier_wifi_cb(struct notifier_block *notifier, |
---|
| 19862 | + unsigned long speed, void *v) |
---|
| 19863 | +{ |
---|
| 19864 | + dhd_info_t *dhd; |
---|
| 19865 | + dhd_pub_t *dhdp; |
---|
| 19866 | +#if defined(ARGOS_NOTIFY_CB) |
---|
| 19867 | + unsigned int pcie_irq = 0; |
---|
| 19868 | +#endif /* ARGOS_NOTIFY_CB */ |
---|
| 19869 | + DHD_INFO(("DHD: %s: speed=%ld\n", __FUNCTION__, speed)); |
---|
| 19870 | + |
---|
| 19871 | + if (argos_rps_ctrl_data.wlan_primary_netdev == NULL) { |
---|
| 19872 | + goto exit; |
---|
| 19873 | + } |
---|
| 19874 | + |
---|
| 19875 | + dhd = DHD_DEV_INFO(argos_rps_ctrl_data.wlan_primary_netdev); |
---|
| 19876 | + if (dhd == NULL) { |
---|
| 19877 | + goto exit; |
---|
| 19878 | + } |
---|
| 19879 | + |
---|
| 19880 | + dhdp = &dhd->pub; |
---|
| 19881 | + if (dhdp == NULL || !dhdp->up) { |
---|
| 19882 | + goto exit; |
---|
| 19883 | + } |
---|
| 19884 | + /* Check if reported TPut value is more than threshold value */ |
---|
| 19885 | + if (speed > RPS_TPUT_THRESHOLD) { |
---|
| 19886 | + if (argos_rps_ctrl_data.argos_rps_cpus_enabled == 0) { |
---|
| 19887 | + /* It does not need to configre rps_cpus |
---|
| 19888 | + * if Load Balance is enabled |
---|
| 19889 | + */ |
---|
| 19890 | +#ifndef DHD_LB |
---|
| 19891 | + int err = 0; |
---|
| 19892 | + |
---|
| 19893 | + if (cpu_online(RPS_CPUS_WLAN_CORE_ID)) { |
---|
| 19894 | + err = custom_rps_map_set( |
---|
| 19895 | + argos_rps_ctrl_data.wlan_primary_netdev->_rx, |
---|
| 19896 | + RPS_CPUS_MASK, strlen(RPS_CPUS_MASK)); |
---|
| 19897 | + } else { |
---|
| 19898 | + DHD_ERROR(("DHD: %s: RPS_Set fail," |
---|
| 19899 | + " Core=%d Offline\n", __FUNCTION__, |
---|
| 19900 | + RPS_CPUS_WLAN_CORE_ID)); |
---|
| 19901 | + err = -1; |
---|
| 19902 | + } |
---|
| 19903 | + |
---|
| 19904 | + if (err < 0) { |
---|
| 19905 | + DHD_ERROR(("DHD: %s: Failed to RPS_CPUs. " |
---|
| 19906 | + "speed=%ld, error=%d\n", |
---|
| 19907 | + __FUNCTION__, speed, err)); |
---|
| 19908 | + } else { |
---|
| 19909 | +#endif /* !DHD_LB */ |
---|
| 19910 | +#if (defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE)) |
---|
| 19911 | + if (dhdp->tcpack_sup_mode != TCPACK_SUP_HOLD) { |
---|
| 19912 | + DHD_ERROR(("%s : set ack suppress. TCPACK_SUP_ON(%d)\n", |
---|
| 19913 | + __FUNCTION__, TCPACK_SUP_HOLD)); |
---|
| 19914 | + dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_HOLD); |
---|
| 19915 | + } |
---|
| 19916 | +#endif /* DHDTCPACK_SUPPRESS && BCMPCIE */ |
---|
| 19917 | + argos_rps_ctrl_data.argos_rps_cpus_enabled = 1; |
---|
| 19918 | +#ifndef DHD_LB |
---|
| 19919 | + DHD_ERROR(("DHD: %s: Set RPS_CPUs, speed=%ld\n", |
---|
| 19920 | + __FUNCTION__, speed)); |
---|
| 19921 | + } |
---|
| 19922 | +#endif /* !DHD_LB */ |
---|
| 19923 | + } |
---|
| 19924 | + } else { |
---|
| 19925 | + if (argos_rps_ctrl_data.argos_rps_cpus_enabled == 1) { |
---|
| 19926 | +#if (defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE)) |
---|
| 19927 | + if (dhdp->tcpack_sup_mode != TCPACK_SUP_OFF) { |
---|
| 19928 | + DHD_ERROR(("%s : set ack suppress. TCPACK_SUP_OFF\n", |
---|
| 19929 | + __FUNCTION__)); |
---|
| 19930 | + dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF); |
---|
| 19931 | + } |
---|
| 19932 | +#endif /* DHDTCPACK_SUPPRESS && BCMPCIE */ |
---|
| 19933 | +#ifndef DHD_LB |
---|
| 19934 | + /* It does not need to configre rps_cpus |
---|
| 19935 | + * if Load Balance is enabled |
---|
| 19936 | + */ |
---|
| 19937 | + custom_rps_map_clear(argos_rps_ctrl_data.wlan_primary_netdev->_rx); |
---|
| 19938 | + DHD_ERROR(("DHD: %s: Clear RPS_CPUs, speed=%ld\n", __FUNCTION__, speed)); |
---|
| 19939 | + OSL_SLEEP(DELAY_TO_CLEAR_RPS_CPUS); |
---|
| 19940 | +#endif /* !DHD_LB */ |
---|
| 19941 | + argos_rps_ctrl_data.argos_rps_cpus_enabled = 0; |
---|
| 19942 | + } |
---|
| 19943 | + } |
---|
| 19944 | + |
---|
| 19945 | +exit: |
---|
| 19946 | + return NOTIFY_OK; |
---|
| 19947 | +} |
---|
| 19948 | + |
---|
| 19949 | +int |
---|
| 19950 | +argos_status_notifier_p2p_cb(struct notifier_block *notifier, |
---|
| 19951 | + unsigned long speed, void *v) |
---|
| 19952 | +{ |
---|
| 19953 | + DHD_INFO(("DHD: %s: speed=%ld\n", __FUNCTION__, speed)); |
---|
| 19954 | + return argos_status_notifier_wifi_cb(notifier, speed, v); |
---|
| 19955 | +} |
---|
| 19956 | +#endif // endif |
---|
14222 | 19957 | |
---|
14223 | 19958 | #ifdef DHD_DEBUG_PAGEALLOC |
---|
14224 | 19959 | |
---|
.. | .. |
---|
14242 | 19977 | DHD_OS_WAKE_UNLOCK(dhdp); |
---|
14243 | 19978 | } |
---|
14244 | 19979 | EXPORT_SYMBOL(dhd_page_corrupt_cb); |
---|
| 19980 | +#endif /* DHD_DEBUG_PAGEALLOC */ |
---|
14245 | 19981 | |
---|
14246 | | -#ifdef DHD_PKTID_AUDIT_ENABLED |
---|
| 19982 | +#if defined(BCMPCIE) && defined(DHD_PKTID_AUDIT_ENABLED) |
---|
14247 | 19983 | void |
---|
14248 | | -dhd_pktid_audit_fail_cb(dhd_pub_t *dhdp) |
---|
| 19984 | +dhd_pktid_error_handler(dhd_pub_t *dhdp) |
---|
14249 | 19985 | { |
---|
14250 | 19986 | DHD_ERROR(("%s: Got Pkt Id Audit failure \n", __FUNCTION__)); |
---|
14251 | 19987 | DHD_OS_WAKE_LOCK(dhdp); |
---|
14252 | | -#if defined(BCMPCIE) && defined(DHD_FW_COREDUMP) |
---|
14253 | | - /* Load the dongle side dump to host memory and then BUG_ON() */ |
---|
14254 | | - dhdp->memdump_enabled = DUMP_MEMONLY; |
---|
| 19988 | + dhd_dump_to_kernelog(dhdp); |
---|
| 19989 | +#ifdef DHD_FW_COREDUMP |
---|
| 19990 | + /* Load the dongle side dump to host memory */ |
---|
| 19991 | + if (dhdp->memdump_enabled == DUMP_DISABLED) { |
---|
| 19992 | + dhdp->memdump_enabled = DUMP_MEMFILE; |
---|
| 19993 | + } |
---|
14255 | 19994 | dhdp->memdump_type = DUMP_TYPE_PKTID_AUDIT_FAILURE; |
---|
14256 | 19995 | dhd_bus_mem_dump(dhdp); |
---|
14257 | | -#endif /* BCMPCIE && DHD_FW_COREDUMP */ |
---|
| 19996 | +#endif /* DHD_FW_COREDUMP */ |
---|
| 19997 | +#ifdef OEM_ANDROID |
---|
| 19998 | + dhdp->hang_reason = HANG_REASON_PCIE_PKTID_ERROR; |
---|
| 19999 | + dhd_os_check_hang(dhdp, 0, -EREMOTEIO); |
---|
| 20000 | +#endif /* OEM_ANDROID */ |
---|
14258 | 20001 | DHD_OS_WAKE_UNLOCK(dhdp); |
---|
14259 | 20002 | } |
---|
14260 | | -#endif /* DHD_PKTID_AUDIT_ENABLED */ |
---|
14261 | | -#endif /* DHD_DEBUG_PAGEALLOC */ |
---|
14262 | | - |
---|
14263 | | -struct tcp_fmt { |
---|
14264 | | - struct iphdr ip_header; |
---|
14265 | | - struct tcphdr tcp_header; |
---|
14266 | | -}; |
---|
14267 | | - |
---|
14268 | | -#define KP_PORT 5150 |
---|
14269 | | - |
---|
14270 | | -static void |
---|
14271 | | -dhd_tcp_dump(char *ifname, uint8 *pktdata, bool tx) |
---|
14272 | | -{ |
---|
14273 | | - struct tcp_fmt *b = (struct tcp_fmt *) &pktdata[ETHER_HDR_LEN]; |
---|
14274 | | - struct iphdr *h = &b->ip_header; |
---|
14275 | | - uint32 ip_saddr, ip_daddr, c, max_c, opt, tsval_t, tsecr_t; |
---|
14276 | | - unsigned char *opts; |
---|
14277 | | - |
---|
14278 | | - /* check IP header */ |
---|
14279 | | - if (h->ihl != 5 || h->version != 4 || h->protocol != IPPROTO_TCP) { |
---|
14280 | | - return; |
---|
14281 | | - } |
---|
14282 | | - |
---|
14283 | | - if ((ntohs(b->tcp_header.source) != KP_PORT) && (ntohs(b->tcp_header.dest) != KP_PORT)) |
---|
14284 | | - return; |
---|
14285 | | - |
---|
14286 | | - if (tx) { |
---|
14287 | | - ip_saddr = h->saddr; |
---|
14288 | | - ip_daddr = h->daddr; |
---|
14289 | | - ip_id = ntohs(h->id); |
---|
14290 | | - bcm_ip_ntoa((struct ipv4_addr *)&ip_saddr, sabuf); |
---|
14291 | | - bcm_ip_ntoa((struct ipv4_addr *)&ip_daddr, dabuf); |
---|
14292 | | - bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf); |
---|
14293 | | - bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf); |
---|
14294 | | - source = ntohs(b->tcp_header.source); |
---|
14295 | | - dest = ntohs(b->tcp_header.dest); |
---|
14296 | | - seq = ntohl(b->tcp_header.seq); |
---|
14297 | | - seq_ack = ntohl(b->tcp_header.ack_seq); |
---|
14298 | | - window = ntohs(b->tcp_header.window); |
---|
14299 | | - tcp_data_len = ntohs(h->tot_len) - 20 - (b->tcp_header.doff * 4); |
---|
14300 | | - } |
---|
14301 | | - |
---|
14302 | | - tcp_option_len = (b->tcp_header.doff * 4) - 20; |
---|
14303 | | - if (tcp_option_len) { |
---|
14304 | | - max_c = tcp_option_len; |
---|
14305 | | - opts = &pktdata[ETHER_HDR_LEN + 40]; |
---|
14306 | | - for (c = 0; c < max_c; ) { |
---|
14307 | | - opt = opts[c]; |
---|
14308 | | - switch (opt) { |
---|
14309 | | - case 0x00: |
---|
14310 | | - /* End of options. */ |
---|
14311 | | - pr_debug("rk tcp_parseopt: EOL\n"); |
---|
14312 | | - return; |
---|
14313 | | - case 0x01: |
---|
14314 | | - /* NOP option. */ |
---|
14315 | | - ++c; |
---|
14316 | | - pr_debug("rk tcp_parseopt: NOP\n"); |
---|
14317 | | - break; |
---|
14318 | | - case 0x02: |
---|
14319 | | - pr_debug("rk tcp_parseopt: MSS\n"); |
---|
14320 | | - if (opts[c + 1] != 0x04 || c + 0x04 > max_c) { |
---|
14321 | | - /* Bad length */ |
---|
14322 | | - pr_err("rk tcp_parseopt: bad length\n"); |
---|
14323 | | - return; |
---|
14324 | | - } |
---|
14325 | | - /* Advance to next option */ |
---|
14326 | | - c += 0x04; |
---|
14327 | | - break; |
---|
14328 | | - case 0x08: |
---|
14329 | | - pr_debug("rk tcp_parseopt: TS\n"); |
---|
14330 | | - if (opts[c + 1] != 0x0A || c + 0x0A > max_c) { |
---|
14331 | | - /* Bad length */ |
---|
14332 | | - pr_err("rk tcp_parseopt: bad length\n"); |
---|
14333 | | - return; |
---|
14334 | | - } |
---|
14335 | | - /* TCP timestamp option with valid length */ |
---|
14336 | | - tsval_t = (opts[c+2]) | (opts[c+3] << 8) | |
---|
14337 | | - (opts[c+4] << 16) | (opts[c+5] << 24); |
---|
14338 | | - tsecr_t = (opts[c+6]) | (opts[c+7] << 8) | |
---|
14339 | | - (opts[c+8] << 16) | (opts[c+9] << 24); |
---|
14340 | | - |
---|
14341 | | - if (tx) { |
---|
14342 | | - tsval = ntohl(tsval_t); |
---|
14343 | | - tsecr = ntohl(tsecr_t); |
---|
14344 | | - } else { |
---|
14345 | | - tsecr = ntohl(tsval_t); |
---|
14346 | | - tsval = ntohl(tsecr_t); |
---|
14347 | | - } |
---|
14348 | | - /* Advance to next option */ |
---|
14349 | | - c += 0x0A; |
---|
14350 | | - break; |
---|
14351 | | - default: |
---|
14352 | | - pr_debug("rk tcp_parseopt: other\n"); |
---|
14353 | | - if (opts[c + 1] == 0) { |
---|
14354 | | - pr_err("rk tcp_parseopt: bad length\n"); |
---|
14355 | | - /* If the length field is zero, the options are malformed |
---|
14356 | | - and we don't process them further. */ |
---|
14357 | | - return; |
---|
14358 | | - } |
---|
14359 | | - /* All other options have a length field, so that we easily |
---|
14360 | | - can skip past them. */ |
---|
14361 | | - c += opts[c + 1]; |
---|
14362 | | - } |
---|
14363 | | - } |
---|
14364 | | - } |
---|
14365 | | - |
---|
14366 | | - if (tx) |
---|
14367 | | - pr_debug("[%s-%s] %s %s %s %s %d, %d, %d, %8u, %8u, %d, %d, %d, %8u, %8u\n", ifname, tx ? "tx" : "rx", |
---|
14368 | | - sabuf, dabuf, seabuf, deabuf, ip_id, source, dest, seq, seq_ack, window, |
---|
14369 | | - tcp_option_len, tcp_data_len, tsval, tsecr); |
---|
14370 | | -} |
---|
14371 | | - |
---|
14372 | | -#ifdef DHD_DHCP_DUMP |
---|
14373 | | -static void |
---|
14374 | | -dhd_dhcp_dump(uint8 *pktdata, bool tx) |
---|
14375 | | -{ |
---|
14376 | | - struct bootp_fmt *b = (struct bootp_fmt *) &pktdata[ETHER_HDR_LEN]; |
---|
14377 | | - struct iphdr *h = &b->ip_header; |
---|
14378 | | - uint8 *ptr, *opt, *end = (uint8 *) b + ntohs(b->ip_header.tot_len); |
---|
14379 | | - int dhcp_type = 0, len, opt_len; |
---|
14380 | | - |
---|
14381 | | - /* check IP header */ |
---|
14382 | | - if (h->ihl != 5 || h->version != 4 || h->protocol != IPPROTO_UDP) { |
---|
14383 | | - return; |
---|
14384 | | - } |
---|
14385 | | - |
---|
14386 | | - /* check UDP port for bootp (67, 68) */ |
---|
14387 | | - if (b->udp_header.source != htons(67) && b->udp_header.source != htons(68) && |
---|
14388 | | - b->udp_header.dest != htons(67) && b->udp_header.dest != htons(68)) { |
---|
14389 | | - return; |
---|
14390 | | - } |
---|
14391 | | - |
---|
14392 | | - /* check header length */ |
---|
14393 | | - if (ntohs(h->tot_len) < ntohs(b->udp_header.len) + sizeof(struct iphdr)) { |
---|
14394 | | - return; |
---|
14395 | | - } |
---|
14396 | | - |
---|
14397 | | - len = ntohs(b->udp_header.len) - sizeof(struct udphdr); |
---|
14398 | | - opt_len = len |
---|
14399 | | - - (sizeof(*b) - sizeof(struct iphdr) - sizeof(struct udphdr) - sizeof(b->options)); |
---|
14400 | | - |
---|
14401 | | - /* parse bootp options */ |
---|
14402 | | - if (opt_len >= 4 && !memcmp(b->options, bootp_magic_cookie, 4)) { |
---|
14403 | | - ptr = &b->options[4]; |
---|
14404 | | - while (ptr < end && *ptr != 0xff) { |
---|
14405 | | - opt = ptr++; |
---|
14406 | | - if (*opt == 0) { |
---|
14407 | | - continue; |
---|
14408 | | - } |
---|
14409 | | - ptr += *ptr + 1; |
---|
14410 | | - if (ptr >= end) { |
---|
14411 | | - break; |
---|
14412 | | - } |
---|
14413 | | - /* 53 is dhcp type */ |
---|
14414 | | - if (*opt == 53) { |
---|
14415 | | - if (opt[1]) { |
---|
14416 | | - dhcp_type = opt[2]; |
---|
14417 | | - DHD_ERROR(("DHCP - %s [%s] [%s]\n", |
---|
14418 | | - dhcp_types[dhcp_type], tx?"TX":"RX", |
---|
14419 | | - dhcp_ops[b->op])); |
---|
14420 | | - break; |
---|
14421 | | - } |
---|
14422 | | - } |
---|
14423 | | - } |
---|
14424 | | - } |
---|
14425 | | -} |
---|
14426 | | -#endif /* DHD_DHCP_DUMP */ |
---|
14427 | | - |
---|
14428 | | - |
---|
14429 | | -typedef struct dhd_mon_dev_priv { |
---|
14430 | | - struct net_device_stats stats; |
---|
14431 | | -} dhd_mon_dev_priv_t; |
---|
14432 | | - |
---|
14433 | | -#define DHD_MON_DEV_PRIV_SIZE (sizeof(dhd_mon_dev_priv_t)) |
---|
14434 | | -#define DHD_MON_DEV_PRIV(dev) ((dhd_mon_dev_priv_t *)DEV_PRIV(dev)) |
---|
14435 | | -#define DHD_MON_DEV_STATS(dev) (((dhd_mon_dev_priv_t *)DEV_PRIV(dev))->stats) |
---|
14436 | | - |
---|
14437 | | -static int |
---|
14438 | | -dhd_monitor_start(struct sk_buff *skb, struct net_device *dev) |
---|
14439 | | -{ |
---|
14440 | | - PKTFREE(NULL, skb, FALSE); |
---|
14441 | | - return 0; |
---|
14442 | | -} |
---|
14443 | | - |
---|
14444 | | -static int |
---|
14445 | | -dhd_monitor_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
---|
14446 | | -{ |
---|
14447 | | - return 0; |
---|
14448 | | -} |
---|
14449 | | - |
---|
14450 | | -static struct net_device_stats* |
---|
14451 | | -dhd_monitor_get_stats(struct net_device *dev) |
---|
14452 | | -{ |
---|
14453 | | - return &DHD_MON_DEV_STATS(dev); |
---|
14454 | | -} |
---|
14455 | | - |
---|
14456 | | -static const struct net_device_ops netdev_monitor_ops = |
---|
14457 | | -{ |
---|
14458 | | - .ndo_start_xmit = dhd_monitor_start, |
---|
14459 | | - .ndo_get_stats = dhd_monitor_get_stats, |
---|
14460 | | - .ndo_do_ioctl = dhd_monitor_ioctl |
---|
14461 | | -}; |
---|
14462 | | - |
---|
14463 | | -static void |
---|
14464 | | -dhd_add_monitor_if(void *handle, void *event_info, u8 event) |
---|
14465 | | -{ |
---|
14466 | | - dhd_info_t *dhd = handle; |
---|
14467 | | - struct net_device *dev; |
---|
14468 | | - char *devname; |
---|
14469 | | - |
---|
14470 | | - if (event != DHD_WQ_WORK_IF_ADD) { |
---|
14471 | | - DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); |
---|
14472 | | - return; |
---|
14473 | | - } |
---|
14474 | | - |
---|
14475 | | - if (!dhd) { |
---|
14476 | | - DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); |
---|
14477 | | - return; |
---|
14478 | | - } |
---|
14479 | | - |
---|
14480 | | - dev = alloc_etherdev(DHD_MON_DEV_PRIV_SIZE); |
---|
14481 | | - if (!dev) { |
---|
14482 | | - DHD_ERROR(("%s: alloc wlif failed\n", __FUNCTION__)); |
---|
14483 | | - return; |
---|
14484 | | - } |
---|
14485 | | - |
---|
14486 | | - if (dhd->monitor_type == 1) |
---|
14487 | | - devname = "prism"; |
---|
14488 | | - else |
---|
14489 | | - devname = "radiotap"; |
---|
14490 | | - |
---|
14491 | | - snprintf(dev->name, sizeof(dev->name), "%s%u", devname, dhd->unit); |
---|
14492 | | - |
---|
14493 | | -#ifndef ARPHRD_IEEE80211_PRISM /* From Linux 2.4.18 */ |
---|
14494 | | -#define ARPHRD_IEEE80211_PRISM 802 |
---|
14495 | | -#endif |
---|
14496 | | - |
---|
14497 | | -#ifndef ARPHRD_IEEE80211_RADIOTAP |
---|
14498 | | -#define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */ |
---|
14499 | | -#endif /* ARPHRD_IEEE80211_RADIOTAP */ |
---|
14500 | | - |
---|
14501 | | - if (dhd->monitor_type == 1) |
---|
14502 | | - dev->type = ARPHRD_IEEE80211_PRISM; |
---|
14503 | | - else |
---|
14504 | | - dev->type = ARPHRD_IEEE80211_RADIOTAP; |
---|
14505 | | - |
---|
14506 | | -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) |
---|
14507 | | - dev->hard_start_xmit = dhd_monitor_start; |
---|
14508 | | - dev->do_ioctl = dhd_monitor_ioctl; |
---|
14509 | | - dev->get_stats = dhd_monitor_get_stats; |
---|
14510 | | -#else |
---|
14511 | | - dev->netdev_ops = &netdev_monitor_ops; |
---|
14512 | | -#endif |
---|
14513 | | - |
---|
14514 | | - if (register_netdev(dev)) { |
---|
14515 | | - DHD_ERROR(("%s, register_netdev failed for %s\n", |
---|
14516 | | - __FUNCTION__, dev->name)); |
---|
14517 | | - free_netdev(dev); |
---|
14518 | | - } |
---|
14519 | | - |
---|
14520 | | - dhd->monitor_dev = dev; |
---|
14521 | | -} |
---|
14522 | | - |
---|
14523 | | -static void |
---|
14524 | | -dhd_del_monitor_if(void *handle, void *event_info, u8 event) |
---|
14525 | | -{ |
---|
14526 | | - dhd_info_t *dhd = handle; |
---|
14527 | | - |
---|
14528 | | - if (event != DHD_WQ_WORK_IF_DEL) { |
---|
14529 | | - DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); |
---|
14530 | | - return; |
---|
14531 | | - } |
---|
14532 | | - |
---|
14533 | | - if (!dhd) { |
---|
14534 | | - DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); |
---|
14535 | | - return; |
---|
14536 | | - } |
---|
14537 | | - |
---|
14538 | | - if (dhd->monitor_dev) { |
---|
14539 | | - unregister_netdev(dhd->monitor_dev); |
---|
14540 | | - |
---|
14541 | | -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) |
---|
14542 | | - MFREE(dhd->osh, dhd->monitor_dev->priv, DHD_MON_DEV_PRIV_SIZE); |
---|
14543 | | - MFREE(dhd->osh, dhd->monitor_dev, sizeof(struct net_device)); |
---|
14544 | | -#else |
---|
14545 | | - free_netdev(dhd->monitor_dev); |
---|
14546 | | -#endif /* 2.6.24 */ |
---|
14547 | | - |
---|
14548 | | - dhd->monitor_dev = NULL; |
---|
14549 | | - } |
---|
14550 | | -} |
---|
14551 | | - |
---|
14552 | | -void |
---|
14553 | | -dhd_set_monitor(dhd_pub_t *dhd, int ifidx, int val) |
---|
14554 | | -{ |
---|
14555 | | - dhd_info_t *info = dhd->info; |
---|
14556 | | - |
---|
14557 | | - DHD_TRACE(("%s: val %d\n", __FUNCTION__, val)); |
---|
14558 | | - if ((val && info->monitor_dev) || (!val && !info->monitor_dev)) { |
---|
14559 | | - DHD_ERROR(("%s: Mismatched params, return\n", __FUNCTION__)); |
---|
14560 | | - return; |
---|
14561 | | - } |
---|
14562 | | - |
---|
14563 | | - /* Delete monitor */ |
---|
14564 | | - if (!val) { |
---|
14565 | | - info->monitor_type = val; |
---|
14566 | | - dhd_deferred_schedule_work(info->dhd_deferred_wq, NULL, DHD_WQ_WORK_IF_DEL, |
---|
14567 | | - dhd_del_monitor_if, DHD_WORK_PRIORITY_LOW); |
---|
14568 | | - return; |
---|
14569 | | - } |
---|
14570 | | - |
---|
14571 | | - /* Add monitor */ |
---|
14572 | | - if (val >= 1 && val <= 3) { |
---|
14573 | | - info->monitor_type = val; |
---|
14574 | | - dhd_deferred_schedule_work(info->dhd_deferred_wq, NULL, DHD_WQ_WORK_IF_ADD, |
---|
14575 | | - dhd_add_monitor_if, DHD_WORK_PRIORITY_LOW); |
---|
14576 | | - } else { |
---|
14577 | | - DHD_ERROR(("monitor type %d not supported\n", val)); |
---|
14578 | | - ASSERT(0); |
---|
14579 | | - } |
---|
14580 | | -} |
---|
14581 | | - |
---|
14582 | | -bool |
---|
14583 | | -dhd_monitor_enabled(dhd_pub_t *dhd, int ifidx) |
---|
14584 | | -{ |
---|
14585 | | - return (dhd->info->monitor_type != 0); |
---|
14586 | | -} |
---|
| 20003 | +#endif /* BCMPCIE && DHD_PKTID_AUDIT_ENABLED */ |
---|
14587 | 20004 | |
---|
14588 | 20005 | struct net_device * |
---|
14589 | 20006 | dhd_linux_get_primary_netdev(dhd_pub_t *dhdp) |
---|
.. | .. |
---|
14595 | 20012 | else |
---|
14596 | 20013 | return NULL; |
---|
14597 | 20014 | } |
---|
| 20015 | + |
---|
| 20016 | +fw_download_status_t |
---|
| 20017 | +dhd_fw_download_status(dhd_pub_t * dhd_pub) |
---|
| 20018 | +{ |
---|
| 20019 | + return dhd_pub->fw_download_status; |
---|
| 20020 | +} |
---|
| 20021 | + |
---|
| 20022 | +static int |
---|
| 20023 | +dhd_create_to_notifier_skt(void) |
---|
| 20024 | +{ |
---|
| 20025 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) |
---|
| 20026 | + /* Kernel 3.7 onwards this API accepts only 3 arguments. */ |
---|
| 20027 | + /* Kernel version 3.6 is a special case which accepts 4 arguments */ |
---|
| 20028 | + nl_to_event_sk = netlink_kernel_create(&init_net, BCM_NL_USER, &dhd_netlink_cfg); |
---|
| 20029 | +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) |
---|
| 20030 | + /* Kernel version 3.5 and below use this old API format */ |
---|
| 20031 | + nl_to_event_sk = netlink_kernel_create(&init_net, BCM_NL_USER, 0, |
---|
| 20032 | + dhd_process_daemon_msg, NULL, THIS_MODULE); |
---|
| 20033 | +#else |
---|
| 20034 | + nl_to_event_sk = netlink_kernel_create(&init_net, BCM_NL_USER, THIS_MODULE, |
---|
| 20035 | + &dhd_netlink_cfg); |
---|
| 20036 | +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) */ |
---|
| 20037 | + if (!nl_to_event_sk) |
---|
| 20038 | + { |
---|
| 20039 | + printf("Error creating socket.\n"); |
---|
| 20040 | + return -1; |
---|
| 20041 | + } |
---|
| 20042 | + DHD_INFO(("nl_to socket created successfully...\n")); |
---|
| 20043 | + return 0; |
---|
| 20044 | +} |
---|
| 20045 | + |
---|
| 20046 | +void |
---|
| 20047 | +dhd_destroy_to_notifier_skt(void) |
---|
| 20048 | +{ |
---|
| 20049 | + DHD_INFO(("Destroying nl_to socket\n")); |
---|
| 20050 | + netlink_kernel_release(nl_to_event_sk); |
---|
| 20051 | +} |
---|
| 20052 | + |
---|
| 20053 | +static void |
---|
| 20054 | +dhd_recv_msg_from_daemon(struct sk_buff *skb) |
---|
| 20055 | +{ |
---|
| 20056 | + struct nlmsghdr *nlh; |
---|
| 20057 | + bcm_to_info_t *cmd; |
---|
| 20058 | + |
---|
| 20059 | + nlh = (struct nlmsghdr *)skb->data; |
---|
| 20060 | + cmd = (bcm_to_info_t *)nlmsg_data(nlh); |
---|
| 20061 | + if ((cmd->magic == BCM_TO_MAGIC) && (cmd->reason == REASON_DAEMON_STARTED)) { |
---|
| 20062 | + sender_pid = ((struct nlmsghdr *)(skb->data))->nlmsg_pid; |
---|
| 20063 | + DHD_INFO(("DHD Daemon Started\n")); |
---|
| 20064 | + } |
---|
| 20065 | +} |
---|
| 20066 | + |
---|
| 20067 | +int |
---|
| 20068 | +dhd_send_msg_to_daemon(struct sk_buff *skb, void *data, int size) |
---|
| 20069 | +{ |
---|
| 20070 | + struct nlmsghdr *nlh; |
---|
| 20071 | + struct sk_buff *skb_out; |
---|
| 20072 | + int ret = BCME_ERROR; |
---|
| 20073 | + |
---|
| 20074 | + BCM_REFERENCE(skb); |
---|
| 20075 | + if (sender_pid == 0) { |
---|
| 20076 | + DHD_INFO(("Invalid PID 0\n")); |
---|
| 20077 | + skb_out = NULL; |
---|
| 20078 | + goto err; |
---|
| 20079 | + } |
---|
| 20080 | + |
---|
| 20081 | + if ((skb_out = nlmsg_new(size, 0)) == NULL) { |
---|
| 20082 | + DHD_ERROR(("%s: skb alloc failed\n", __FUNCTION__)); |
---|
| 20083 | + ret = BCME_NOMEM; |
---|
| 20084 | + goto err; |
---|
| 20085 | + } |
---|
| 20086 | + nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, size, 0); |
---|
| 20087 | + if (nlh == NULL) { |
---|
| 20088 | + DHD_ERROR(("%s: nlmsg_put failed\n", __FUNCTION__)); |
---|
| 20089 | + goto err; |
---|
| 20090 | + } |
---|
| 20091 | + NETLINK_CB(skb_out).dst_group = 0; /* Unicast */ |
---|
| 20092 | + (void)memcpy_s(nlmsg_data(nlh), size, (char *)data, size); |
---|
| 20093 | + |
---|
| 20094 | + if ((ret = nlmsg_unicast(nl_to_event_sk, skb_out, sender_pid)) < 0) { |
---|
| 20095 | + DHD_ERROR(("Error sending message, ret:%d\n", ret)); |
---|
| 20096 | + /* skb is already freed inside nlmsg_unicast() on error case */ |
---|
| 20097 | + /* explicitly making skb_out to NULL to avoid double free */ |
---|
| 20098 | + skb_out = NULL; |
---|
| 20099 | + goto err; |
---|
| 20100 | + } |
---|
| 20101 | + return BCME_OK; |
---|
| 20102 | +err: |
---|
| 20103 | + if (skb_out) { |
---|
| 20104 | + nlmsg_free(skb_out); |
---|
| 20105 | + } |
---|
| 20106 | + return ret; |
---|
| 20107 | +} |
---|
| 20108 | + |
---|
| 20109 | +static void |
---|
| 20110 | +dhd_process_daemon_msg(struct sk_buff *skb) |
---|
| 20111 | +{ |
---|
| 20112 | + bcm_to_info_t to_info; |
---|
| 20113 | + |
---|
| 20114 | + to_info.magic = BCM_TO_MAGIC; |
---|
| 20115 | + to_info.reason = REASON_DAEMON_STARTED; |
---|
| 20116 | + to_info.trap = NO_TRAP; |
---|
| 20117 | + |
---|
| 20118 | + dhd_recv_msg_from_daemon(skb); |
---|
| 20119 | + dhd_send_msg_to_daemon(skb, &to_info, sizeof(to_info)); |
---|
| 20120 | +} |
---|
| 20121 | + |
---|
| 20122 | +#ifdef DHD_LOG_DUMP |
---|
| 20123 | +bool |
---|
| 20124 | +dhd_log_dump_ecntr_enabled(void) |
---|
| 20125 | +{ |
---|
| 20126 | + return (bool)logdump_ecntr_enable; |
---|
| 20127 | +} |
---|
| 20128 | + |
---|
| 20129 | +bool |
---|
| 20130 | +dhd_log_dump_rtt_enabled(void) |
---|
| 20131 | +{ |
---|
| 20132 | + return (bool)logdump_rtt_enable; |
---|
| 20133 | +} |
---|
| 20134 | + |
---|
| 20135 | +void |
---|
| 20136 | +dhd_log_dump_init(dhd_pub_t *dhd) |
---|
| 20137 | +{ |
---|
| 20138 | + struct dhd_log_dump_buf *dld_buf, *dld_buf_special; |
---|
| 20139 | + int i = 0; |
---|
| 20140 | + uint8 *prealloc_buf = NULL, *bufptr = NULL; |
---|
| 20141 | +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP) |
---|
| 20142 | + int prealloc_idx = DHD_PREALLOC_DHD_LOG_DUMP_BUF; |
---|
| 20143 | +#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */ |
---|
| 20144 | + int ret; |
---|
| 20145 | + dhd_dbg_ring_t *ring = NULL; |
---|
| 20146 | + unsigned long flags = 0; |
---|
| 20147 | + dhd_info_t *dhd_info = dhd->info; |
---|
| 20148 | + void *cookie_buf = NULL; |
---|
| 20149 | + |
---|
| 20150 | + BCM_REFERENCE(ret); |
---|
| 20151 | + BCM_REFERENCE(ring); |
---|
| 20152 | + BCM_REFERENCE(flags); |
---|
| 20153 | + |
---|
| 20154 | + /* sanity check */ |
---|
| 20155 | + if (logdump_prsrv_tailsize <= 0 || |
---|
| 20156 | + logdump_prsrv_tailsize > DHD_LOG_DUMP_MAX_TAIL_FLUSH_SIZE) { |
---|
| 20157 | + logdump_prsrv_tailsize = DHD_LOG_DUMP_MAX_TAIL_FLUSH_SIZE; |
---|
| 20158 | + } |
---|
| 20159 | + /* now adjust the preserve log flush size based on the |
---|
| 20160 | + * kernel printk log buffer size |
---|
| 20161 | + */ |
---|
| 20162 | +#ifdef CONFIG_LOG_BUF_SHIFT |
---|
| 20163 | + DHD_ERROR(("%s: kernel log buf size = %uKB; logdump_prsrv_tailsize = %uKB;" |
---|
| 20164 | + " limit prsrv tail size to = %uKB\n", |
---|
| 20165 | + __FUNCTION__, (1 << CONFIG_LOG_BUF_SHIFT)/1024, |
---|
| 20166 | + logdump_prsrv_tailsize/1024, LOG_DUMP_KERNEL_TAIL_FLUSH_SIZE/1024)); |
---|
| 20167 | + |
---|
| 20168 | + if (logdump_prsrv_tailsize > LOG_DUMP_KERNEL_TAIL_FLUSH_SIZE) { |
---|
| 20169 | + logdump_prsrv_tailsize = LOG_DUMP_KERNEL_TAIL_FLUSH_SIZE; |
---|
| 20170 | + } |
---|
| 20171 | +#else |
---|
| 20172 | + DHD_ERROR(("%s: logdump_prsrv_tailsize = %uKB \n", |
---|
| 20173 | + __FUNCTION__, logdump_prsrv_tailsize/1024); |
---|
| 20174 | +#endif /* CONFIG_LOG_BUF_SHIFT */ |
---|
| 20175 | + |
---|
| 20176 | + mutex_init(&dhd_info->logdump_lock); |
---|
| 20177 | + |
---|
| 20178 | + /* initialize log dump buf structures */ |
---|
| 20179 | + memset(g_dld_buf, 0, sizeof(struct dhd_log_dump_buf) * DLD_BUFFER_NUM); |
---|
| 20180 | + |
---|
| 20181 | + /* set the log dump buffer size based on the module_param */ |
---|
| 20182 | + if (logdump_max_bufsize > LOG_DUMP_GENERAL_MAX_BUFSIZE || |
---|
| 20183 | + logdump_max_bufsize <= 0) |
---|
| 20184 | + dld_buf_size[DLD_BUF_TYPE_GENERAL] = LOG_DUMP_GENERAL_MAX_BUFSIZE; |
---|
| 20185 | + else |
---|
| 20186 | + dld_buf_size[DLD_BUF_TYPE_GENERAL] = logdump_max_bufsize; |
---|
| 20187 | + |
---|
| 20188 | + /* pre-alloc the memory for the log buffers & 'special' buffer */ |
---|
| 20189 | + dld_buf_special = &g_dld_buf[DLD_BUF_TYPE_SPECIAL]; |
---|
| 20190 | +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP) |
---|
| 20191 | + DHD_ERROR(("%s : Try to allocate memory total(%d) special(%d)\n", |
---|
| 20192 | + __FUNCTION__, LOG_DUMP_TOTAL_BUFSIZE, LOG_DUMP_SPECIAL_MAX_BUFSIZE)); |
---|
| 20193 | + prealloc_buf = DHD_OS_PREALLOC(dhd, prealloc_idx++, LOG_DUMP_TOTAL_BUFSIZE); |
---|
| 20194 | + dld_buf_special->buffer = DHD_OS_PREALLOC(dhd, prealloc_idx++, |
---|
| 20195 | + dld_buf_size[DLD_BUF_TYPE_SPECIAL]); |
---|
| 20196 | +#else |
---|
| 20197 | + prealloc_buf = VMALLOCZ(dhd->osh, LOG_DUMP_TOTAL_BUFSIZE); |
---|
| 20198 | + dld_buf_special->buffer = VMALLOCZ(dhd->osh, dld_buf_size[DLD_BUF_TYPE_SPECIAL]); |
---|
| 20199 | +#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */ |
---|
| 20200 | + if (!prealloc_buf) { |
---|
| 20201 | + DHD_ERROR(("Failed to pre-allocate memory for log buffers !\n")); |
---|
| 20202 | + goto fail; |
---|
| 20203 | + } |
---|
| 20204 | + if (!dld_buf_special->buffer) { |
---|
| 20205 | + DHD_ERROR(("Failed to pre-allocate memory for special buffer !\n")); |
---|
| 20206 | + goto fail; |
---|
| 20207 | + } |
---|
| 20208 | + |
---|
| 20209 | + bufptr = prealloc_buf; |
---|
| 20210 | + for (i = 0; i < DLD_BUFFER_NUM; i++) { |
---|
| 20211 | + dld_buf = &g_dld_buf[i]; |
---|
| 20212 | + dld_buf->dhd_pub = dhd; |
---|
| 20213 | + spin_lock_init(&dld_buf->lock); |
---|
| 20214 | + dld_buf->wraparound = 0; |
---|
| 20215 | + if (i != DLD_BUF_TYPE_SPECIAL) { |
---|
| 20216 | + dld_buf->buffer = bufptr; |
---|
| 20217 | + dld_buf->max = (unsigned long)dld_buf->buffer + dld_buf_size[i]; |
---|
| 20218 | + bufptr = (uint8 *)dld_buf->max; |
---|
| 20219 | + } else { |
---|
| 20220 | + dld_buf->max = (unsigned long)dld_buf->buffer + dld_buf_size[i]; |
---|
| 20221 | + } |
---|
| 20222 | + dld_buf->present = dld_buf->front = dld_buf->buffer; |
---|
| 20223 | + dld_buf->remain = dld_buf_size[i]; |
---|
| 20224 | + dld_buf->enable = 1; |
---|
| 20225 | + } |
---|
| 20226 | + |
---|
| 20227 | +#ifdef EWP_ECNTRS_LOGGING |
---|
| 20228 | + /* now use the rest of the pre-alloc'd memory for filter and ecounter log */ |
---|
| 20229 | + dhd->ecntr_dbg_ring = MALLOCZ(dhd->osh, sizeof(dhd_dbg_ring_t)); |
---|
| 20230 | + if (!dhd->ecntr_dbg_ring) |
---|
| 20231 | + goto fail; |
---|
| 20232 | + |
---|
| 20233 | + ring = (dhd_dbg_ring_t *)dhd->ecntr_dbg_ring; |
---|
| 20234 | + ret = dhd_dbg_ring_init(dhd, ring, ECNTR_RING_ID, |
---|
| 20235 | + ECNTR_RING_NAME, LOG_DUMP_ECNTRS_MAX_BUFSIZE, |
---|
| 20236 | + bufptr, TRUE); |
---|
| 20237 | + if (ret != BCME_OK) { |
---|
| 20238 | + DHD_ERROR(("%s: unable to init ecntr ring !\n", |
---|
| 20239 | + __FUNCTION__)); |
---|
| 20240 | + goto fail; |
---|
| 20241 | + } |
---|
| 20242 | + DHD_DBG_RING_LOCK(ring->lock, flags); |
---|
| 20243 | + ring->state = RING_ACTIVE; |
---|
| 20244 | + ring->threshold = 0; |
---|
| 20245 | + DHD_DBG_RING_UNLOCK(ring->lock, flags); |
---|
| 20246 | + |
---|
| 20247 | + bufptr += LOG_DUMP_ECNTRS_MAX_BUFSIZE; |
---|
| 20248 | +#endif /* EWP_ECNTRS_LOGGING */ |
---|
| 20249 | + |
---|
| 20250 | +#ifdef EWP_RTT_LOGGING |
---|
| 20251 | + /* now use the rest of the pre-alloc'd memory for filter and ecounter log */ |
---|
| 20252 | + dhd->rtt_dbg_ring = MALLOCZ(dhd->osh, sizeof(dhd_dbg_ring_t)); |
---|
| 20253 | + if (!dhd->rtt_dbg_ring) |
---|
| 20254 | + goto fail; |
---|
| 20255 | + |
---|
| 20256 | + ring = (dhd_dbg_ring_t *)dhd->rtt_dbg_ring; |
---|
| 20257 | + ret = dhd_dbg_ring_init(dhd, ring, RTT_RING_ID, |
---|
| 20258 | + RTT_RING_NAME, LOG_DUMP_RTT_MAX_BUFSIZE, |
---|
| 20259 | + bufptr, TRUE); |
---|
| 20260 | + if (ret != BCME_OK) { |
---|
| 20261 | + DHD_ERROR(("%s: unable to init ecntr ring !\n", |
---|
| 20262 | + __FUNCTION__)); |
---|
| 20263 | + goto fail; |
---|
| 20264 | + } |
---|
| 20265 | + DHD_DBG_RING_LOCK(ring->lock, flags); |
---|
| 20266 | + ring->state = RING_ACTIVE; |
---|
| 20267 | + ring->threshold = 0; |
---|
| 20268 | + DHD_DBG_RING_UNLOCK(ring->lock, flags); |
---|
| 20269 | + |
---|
| 20270 | + bufptr += LOG_DUMP_RTT_MAX_BUFSIZE; |
---|
| 20271 | +#endif /* EWP_RTT_LOGGING */ |
---|
| 20272 | + |
---|
| 20273 | + /* Concise buffer is used as intermediate buffer for following purposes |
---|
| 20274 | + * a) pull ecounters records temporarily before |
---|
| 20275 | + * writing it to file |
---|
| 20276 | + * b) to store dhd dump data before putting it to file |
---|
| 20277 | + * It should have a size equal to |
---|
| 20278 | + * MAX(largest possible ecntr record, 'dhd dump' data size) |
---|
| 20279 | + */ |
---|
| 20280 | + dhd->concise_dbg_buf = MALLOC(dhd->osh, CONCISE_DUMP_BUFLEN); |
---|
| 20281 | + if (!dhd->concise_dbg_buf) { |
---|
| 20282 | + DHD_ERROR(("%s: unable to alloc mem for concise debug info !\n", |
---|
| 20283 | + __FUNCTION__)); |
---|
| 20284 | + goto fail; |
---|
| 20285 | + } |
---|
| 20286 | + |
---|
| 20287 | +#if defined(DHD_EVENT_LOG_FILTER) |
---|
| 20288 | + ret = dhd_event_log_filter_init(dhd, |
---|
| 20289 | + bufptr, |
---|
| 20290 | + LOG_DUMP_FILTER_MAX_BUFSIZE); |
---|
| 20291 | + if (ret != BCME_OK) { |
---|
| 20292 | + goto fail; |
---|
| 20293 | + } |
---|
| 20294 | +#endif /* DHD_EVENT_LOG_FILTER */ |
---|
| 20295 | + |
---|
| 20296 | + cookie_buf = MALLOC(dhd->osh, LOG_DUMP_COOKIE_BUFSIZE); |
---|
| 20297 | + if (!cookie_buf) { |
---|
| 20298 | + DHD_ERROR(("%s: unable to alloc mem for logdump cookie buffer\n", |
---|
| 20299 | + __FUNCTION__)); |
---|
| 20300 | + goto fail; |
---|
| 20301 | + } |
---|
| 20302 | + ret = dhd_logdump_cookie_init(dhd, cookie_buf, LOG_DUMP_COOKIE_BUFSIZE); |
---|
| 20303 | + if (ret != BCME_OK) { |
---|
| 20304 | + MFREE(dhd->osh, cookie_buf, LOG_DUMP_COOKIE_BUFSIZE); |
---|
| 20305 | + goto fail; |
---|
| 20306 | + } |
---|
| 20307 | + return; |
---|
| 20308 | + |
---|
| 20309 | +fail: |
---|
| 20310 | + |
---|
| 20311 | + if (dhd->logdump_cookie) { |
---|
| 20312 | + dhd_logdump_cookie_deinit(dhd); |
---|
| 20313 | + MFREE(dhd->osh, dhd->logdump_cookie, LOG_DUMP_COOKIE_BUFSIZE); |
---|
| 20314 | + dhd->logdump_cookie = NULL; |
---|
| 20315 | + } |
---|
| 20316 | +#if defined(DHD_EVENT_LOG_FILTER) |
---|
| 20317 | + if (dhd->event_log_filter) { |
---|
| 20318 | + dhd_event_log_filter_deinit(dhd); |
---|
| 20319 | + } |
---|
| 20320 | +#endif /* DHD_EVENT_LOG_FILTER */ |
---|
| 20321 | + |
---|
| 20322 | + if (dhd->concise_dbg_buf) { |
---|
| 20323 | + MFREE(dhd->osh, dhd->concise_dbg_buf, CONCISE_DUMP_BUFLEN); |
---|
| 20324 | + } |
---|
| 20325 | + |
---|
| 20326 | +#ifdef EWP_ECNTRS_LOGGING |
---|
| 20327 | + if (dhd->ecntr_dbg_ring) { |
---|
| 20328 | + ring = (dhd_dbg_ring_t *)dhd->ecntr_dbg_ring; |
---|
| 20329 | + dhd_dbg_ring_deinit(dhd, ring); |
---|
| 20330 | + ring->ring_buf = NULL; |
---|
| 20331 | + ring->ring_size = 0; |
---|
| 20332 | + MFREE(dhd->osh, ring, sizeof(dhd_dbg_ring_t)); |
---|
| 20333 | + dhd->ecntr_dbg_ring = NULL; |
---|
| 20334 | + } |
---|
| 20335 | +#endif /* EWP_ECNTRS_LOGGING */ |
---|
| 20336 | + |
---|
| 20337 | +#ifdef EWP_RTT_LOGGING |
---|
| 20338 | + if (dhd->rtt_dbg_ring) { |
---|
| 20339 | + ring = (dhd_dbg_ring_t *)dhd->rtt_dbg_ring; |
---|
| 20340 | + dhd_dbg_ring_deinit(dhd, ring); |
---|
| 20341 | + ring->ring_buf = NULL; |
---|
| 20342 | + ring->ring_size = 0; |
---|
| 20343 | + MFREE(dhd->osh, ring, sizeof(dhd_dbg_ring_t)); |
---|
| 20344 | + dhd->rtt_dbg_ring = NULL; |
---|
| 20345 | + } |
---|
| 20346 | +#endif /* EWP_RTT_LOGGING */ |
---|
| 20347 | + |
---|
| 20348 | +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP) |
---|
| 20349 | + if (prealloc_buf) { |
---|
| 20350 | + DHD_OS_PREFREE(dhd, prealloc_buf, LOG_DUMP_TOTAL_BUFSIZE); |
---|
| 20351 | + } |
---|
| 20352 | + if (dld_buf_special->buffer) { |
---|
| 20353 | + DHD_OS_PREFREE(dhd, dld_buf_special->buffer, |
---|
| 20354 | + dld_buf_size[DLD_BUF_TYPE_SPECIAL]); |
---|
| 20355 | + } |
---|
| 20356 | +#else |
---|
| 20357 | + if (prealloc_buf) { |
---|
| 20358 | + VMFREE(dhd->osh, prealloc_buf, LOG_DUMP_TOTAL_BUFSIZE); |
---|
| 20359 | + } |
---|
| 20360 | + if (dld_buf_special->buffer) { |
---|
| 20361 | + VMFREE(dhd->osh, dld_buf_special->buffer, |
---|
| 20362 | + dld_buf_size[DLD_BUF_TYPE_SPECIAL]); |
---|
| 20363 | + } |
---|
| 20364 | +#endif /* CONFIG_DHD_USE_STATIC_BUF */ |
---|
| 20365 | + for (i = 0; i < DLD_BUFFER_NUM; i++) { |
---|
| 20366 | + dld_buf = &g_dld_buf[i]; |
---|
| 20367 | + dld_buf->enable = 0; |
---|
| 20368 | + dld_buf->buffer = NULL; |
---|
| 20369 | + } |
---|
| 20370 | + |
---|
| 20371 | + mutex_destroy(&dhd_info->logdump_lock); |
---|
| 20372 | +} |
---|
| 20373 | + |
---|
| 20374 | +void |
---|
| 20375 | +dhd_log_dump_deinit(dhd_pub_t *dhd) |
---|
| 20376 | +{ |
---|
| 20377 | + struct dhd_log_dump_buf *dld_buf = NULL, *dld_buf_special = NULL; |
---|
| 20378 | + int i = 0; |
---|
| 20379 | + dhd_info_t *dhd_info = dhd->info; |
---|
| 20380 | + dhd_dbg_ring_t *ring = NULL; |
---|
| 20381 | + |
---|
| 20382 | + BCM_REFERENCE(ring); |
---|
| 20383 | + |
---|
| 20384 | + if (dhd->concise_dbg_buf) { |
---|
| 20385 | + MFREE(dhd->osh, dhd->concise_dbg_buf, CONCISE_DUMP_BUFLEN); |
---|
| 20386 | + dhd->concise_dbg_buf = NULL; |
---|
| 20387 | + } |
---|
| 20388 | + |
---|
| 20389 | + if (dhd->logdump_cookie) { |
---|
| 20390 | + dhd_logdump_cookie_deinit(dhd); |
---|
| 20391 | + MFREE(dhd->osh, dhd->logdump_cookie, LOG_DUMP_COOKIE_BUFSIZE); |
---|
| 20392 | + dhd->logdump_cookie = NULL; |
---|
| 20393 | + } |
---|
| 20394 | + |
---|
| 20395 | +#if defined(DHD_EVENT_LOG_FILTER) |
---|
| 20396 | + if (dhd->event_log_filter) { |
---|
| 20397 | + dhd_event_log_filter_deinit(dhd); |
---|
| 20398 | + } |
---|
| 20399 | +#endif /* DHD_EVENT_LOG_FILTER */ |
---|
| 20400 | + |
---|
| 20401 | +#ifdef EWP_ECNTRS_LOGGING |
---|
| 20402 | + if (dhd->ecntr_dbg_ring) { |
---|
| 20403 | + ring = (dhd_dbg_ring_t *)dhd->ecntr_dbg_ring; |
---|
| 20404 | + dhd_dbg_ring_deinit(dhd, ring); |
---|
| 20405 | + ring->ring_buf = NULL; |
---|
| 20406 | + ring->ring_size = 0; |
---|
| 20407 | + MFREE(dhd->osh, ring, sizeof(dhd_dbg_ring_t)); |
---|
| 20408 | + dhd->ecntr_dbg_ring = NULL; |
---|
| 20409 | + } |
---|
| 20410 | +#endif /* EWP_ECNTRS_LOGGING */ |
---|
| 20411 | + |
---|
| 20412 | +#ifdef EWP_RTT_LOGGING |
---|
| 20413 | + if (dhd->rtt_dbg_ring) { |
---|
| 20414 | + ring = (dhd_dbg_ring_t *)dhd->rtt_dbg_ring; |
---|
| 20415 | + dhd_dbg_ring_deinit(dhd, ring); |
---|
| 20416 | + ring->ring_buf = NULL; |
---|
| 20417 | + ring->ring_size = 0; |
---|
| 20418 | + MFREE(dhd->osh, ring, sizeof(dhd_dbg_ring_t)); |
---|
| 20419 | + dhd->rtt_dbg_ring = NULL; |
---|
| 20420 | + } |
---|
| 20421 | +#endif /* EWP_RTT_LOGGING */ |
---|
| 20422 | + |
---|
| 20423 | + /* 'general' buffer points to start of the pre-alloc'd memory */ |
---|
| 20424 | + dld_buf = &g_dld_buf[DLD_BUF_TYPE_GENERAL]; |
---|
| 20425 | + dld_buf_special = &g_dld_buf[DLD_BUF_TYPE_SPECIAL]; |
---|
| 20426 | +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP) |
---|
| 20427 | + if (dld_buf->buffer) { |
---|
| 20428 | + DHD_OS_PREFREE(dhd, dld_buf->buffer, LOG_DUMP_TOTAL_BUFSIZE); |
---|
| 20429 | + } |
---|
| 20430 | + if (dld_buf_special->buffer) { |
---|
| 20431 | + DHD_OS_PREFREE(dhd, dld_buf_special->buffer, |
---|
| 20432 | + dld_buf_size[DLD_BUF_TYPE_SPECIAL]); |
---|
| 20433 | + } |
---|
| 20434 | +#else |
---|
| 20435 | + if (dld_buf->buffer) { |
---|
| 20436 | + VMFREE(dhd->osh, dld_buf->buffer, LOG_DUMP_TOTAL_BUFSIZE); |
---|
| 20437 | + } |
---|
| 20438 | + if (dld_buf_special->buffer) { |
---|
| 20439 | + VMFREE(dhd->osh, dld_buf_special->buffer, |
---|
| 20440 | + dld_buf_size[DLD_BUF_TYPE_SPECIAL]); |
---|
| 20441 | + } |
---|
| 20442 | +#endif /* CONFIG_DHD_USE_STATIC_BUF */ |
---|
| 20443 | + for (i = 0; i < DLD_BUFFER_NUM; i++) { |
---|
| 20444 | + dld_buf = &g_dld_buf[i]; |
---|
| 20445 | + dld_buf->enable = 0; |
---|
| 20446 | + dld_buf->buffer = NULL; |
---|
| 20447 | + } |
---|
| 20448 | + |
---|
| 20449 | + mutex_destroy(&dhd_info->logdump_lock); |
---|
| 20450 | +} |
---|
| 20451 | + |
---|
| 20452 | +void |
---|
| 20453 | +dhd_log_dump_write(int type, char *binary_data, |
---|
| 20454 | + int binary_len, const char *fmt, ...) |
---|
| 20455 | +{ |
---|
| 20456 | + int len = 0; |
---|
| 20457 | + char tmp_buf[DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE] = {0, }; |
---|
| 20458 | + va_list args; |
---|
| 20459 | + unsigned long flags = 0; |
---|
| 20460 | + struct dhd_log_dump_buf *dld_buf = NULL; |
---|
| 20461 | + bool flush_log = FALSE; |
---|
| 20462 | + |
---|
| 20463 | + if (type < 0 || type >= DLD_BUFFER_NUM) { |
---|
| 20464 | + DHD_INFO(("%s: Unknown DHD_LOG_DUMP_BUF_TYPE(%d).\n", |
---|
| 20465 | + __FUNCTION__, type)); |
---|
| 20466 | + return; |
---|
| 20467 | + } |
---|
| 20468 | + |
---|
| 20469 | + dld_buf = &g_dld_buf[type]; |
---|
| 20470 | + |
---|
| 20471 | + if (dld_buf->enable != 1) { |
---|
| 20472 | + return; |
---|
| 20473 | + } |
---|
| 20474 | + |
---|
| 20475 | + va_start(args, fmt); |
---|
| 20476 | + len = vsnprintf(tmp_buf, DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE, fmt, args); |
---|
| 20477 | + /* Non ANSI C99 compliant returns -1, |
---|
| 20478 | + * ANSI compliant return len >= DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE |
---|
| 20479 | + */ |
---|
| 20480 | + va_end(args); |
---|
| 20481 | + if (len < 0) { |
---|
| 20482 | + return; |
---|
| 20483 | + } |
---|
| 20484 | + |
---|
| 20485 | + if (len >= DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE) { |
---|
| 20486 | + len = DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE - 1; |
---|
| 20487 | + tmp_buf[len] = '\0'; |
---|
| 20488 | + } |
---|
| 20489 | + |
---|
| 20490 | + /* make a critical section to eliminate race conditions */ |
---|
| 20491 | + spin_lock_irqsave(&dld_buf->lock, flags); |
---|
| 20492 | + if (dld_buf->remain < len) { |
---|
| 20493 | + dld_buf->wraparound = 1; |
---|
| 20494 | + dld_buf->present = dld_buf->front; |
---|
| 20495 | + dld_buf->remain = dld_buf_size[type]; |
---|
| 20496 | + /* if wrap around happens, flush the ring buffer to the file */ |
---|
| 20497 | + flush_log = TRUE; |
---|
| 20498 | + } |
---|
| 20499 | + |
---|
| 20500 | + memcpy(dld_buf->present, tmp_buf, len); |
---|
| 20501 | + dld_buf->remain -= len; |
---|
| 20502 | + dld_buf->present += len; |
---|
| 20503 | + spin_unlock_irqrestore(&dld_buf->lock, flags); |
---|
| 20504 | + |
---|
| 20505 | + /* double check invalid memory operation */ |
---|
| 20506 | + ASSERT((unsigned long)dld_buf->present <= dld_buf->max); |
---|
| 20507 | + |
---|
| 20508 | + if (dld_buf->dhd_pub) { |
---|
| 20509 | + dhd_pub_t *dhdp = (dhd_pub_t *)dld_buf->dhd_pub; |
---|
| 20510 | + dhdp->logdump_periodic_flush = |
---|
| 20511 | + logdump_periodic_flush; |
---|
| 20512 | + if (logdump_periodic_flush && flush_log) { |
---|
| 20513 | + log_dump_type_t *flush_type = MALLOCZ(dhdp->osh, |
---|
| 20514 | + sizeof(log_dump_type_t)); |
---|
| 20515 | + if (flush_type) { |
---|
| 20516 | + *flush_type = type; |
---|
| 20517 | + dhd_schedule_log_dump(dld_buf->dhd_pub, flush_type); |
---|
| 20518 | + } |
---|
| 20519 | + } |
---|
| 20520 | + } |
---|
| 20521 | +} |
---|
| 20522 | + |
---|
| 20523 | +char* |
---|
| 20524 | +dhd_log_dump_get_timestamp(void) |
---|
| 20525 | +{ |
---|
| 20526 | + static char buf[16]; |
---|
| 20527 | + u64 ts_nsec; |
---|
| 20528 | + unsigned long rem_nsec; |
---|
| 20529 | + |
---|
| 20530 | + ts_nsec = local_clock(); |
---|
| 20531 | + rem_nsec = DIV_AND_MOD_U64_BY_U32(ts_nsec, NSEC_PER_SEC); |
---|
| 20532 | + snprintf(buf, sizeof(buf), "%5lu.%06lu", |
---|
| 20533 | + (unsigned long)ts_nsec, rem_nsec / NSEC_PER_USEC); |
---|
| 20534 | + |
---|
| 20535 | + return buf; |
---|
| 20536 | +} |
---|
| 20537 | +#endif /* DHD_LOG_DUMP */ |
---|
| 20538 | + |
---|
| 20539 | +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM |
---|
| 20540 | +void |
---|
| 20541 | +dhd_flush_rx_tx_wq(dhd_pub_t *dhdp) |
---|
| 20542 | +{ |
---|
| 20543 | + dhd_info_t * dhd; |
---|
| 20544 | + |
---|
| 20545 | + if (dhdp) { |
---|
| 20546 | + dhd = dhdp->info; |
---|
| 20547 | + if (dhd) { |
---|
| 20548 | + flush_workqueue(dhd->tx_wq); |
---|
| 20549 | + flush_workqueue(dhd->rx_wq); |
---|
| 20550 | + } |
---|
| 20551 | + } |
---|
| 20552 | + |
---|
| 20553 | + return; |
---|
| 20554 | +} |
---|
| 20555 | +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ |
---|
| 20556 | + |
---|
| 20557 | +#ifdef DHD_DEBUG_UART |
---|
| 20558 | +bool |
---|
| 20559 | +dhd_debug_uart_is_running(struct net_device *dev) |
---|
| 20560 | +{ |
---|
| 20561 | + dhd_info_t *dhd = DHD_DEV_INFO(dev); |
---|
| 20562 | + |
---|
| 20563 | + if (dhd->duart_execute) { |
---|
| 20564 | + return TRUE; |
---|
| 20565 | + } |
---|
| 20566 | + |
---|
| 20567 | + return FALSE; |
---|
| 20568 | +} |
---|
| 20569 | + |
---|
| 20570 | +static void |
---|
| 20571 | +dhd_debug_uart_exec_rd(void *handle, void *event_info, u8 event) |
---|
| 20572 | +{ |
---|
| 20573 | + dhd_pub_t *dhdp = handle; |
---|
| 20574 | + dhd_debug_uart_exec(dhdp, "rd"); |
---|
| 20575 | +} |
---|
| 20576 | + |
---|
| 20577 | +static void |
---|
| 20578 | +dhd_debug_uart_exec(dhd_pub_t *dhdp, char *cmd) |
---|
| 20579 | +{ |
---|
| 20580 | + int ret; |
---|
| 20581 | + |
---|
| 20582 | + char *argv[] = {DHD_DEBUG_UART_EXEC_PATH, cmd, NULL}; |
---|
| 20583 | + char *envp[] = {"HOME=/", "TERM=linux", "PATH=/sbin:/system/bin", NULL}; |
---|
| 20584 | + |
---|
| 20585 | +#ifdef DHD_FW_COREDUMP |
---|
| 20586 | + if (dhdp->memdump_enabled == DUMP_MEMFILE_BUGON) |
---|
| 20587 | +#endif // endif |
---|
| 20588 | + { |
---|
| 20589 | + if (dhdp->hang_reason == HANG_REASON_PCIE_LINK_DOWN_RC_DETECT || |
---|
| 20590 | + dhdp->hang_reason == HANG_REASON_PCIE_LINK_DOWN_EP_DETECT || |
---|
| 20591 | +#ifdef DHD_FW_COREDUMP |
---|
| 20592 | + dhdp->memdump_success == FALSE || |
---|
| 20593 | +#endif // endif |
---|
| 20594 | + FALSE) { |
---|
| 20595 | + dhdp->info->duart_execute = TRUE; |
---|
| 20596 | + DHD_ERROR(("DHD: %s - execute %s %s\n", |
---|
| 20597 | + __FUNCTION__, DHD_DEBUG_UART_EXEC_PATH, cmd)); |
---|
| 20598 | + ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); |
---|
| 20599 | + DHD_ERROR(("DHD: %s - %s %s ret = %d\n", |
---|
| 20600 | + __FUNCTION__, DHD_DEBUG_UART_EXEC_PATH, cmd, ret)); |
---|
| 20601 | + dhdp->info->duart_execute = FALSE; |
---|
| 20602 | + |
---|
| 20603 | +#ifdef DHD_LOG_DUMP |
---|
| 20604 | + if (dhdp->memdump_type != DUMP_TYPE_BY_SYSDUMP) |
---|
| 20605 | +#endif // endif |
---|
| 20606 | + { |
---|
| 20607 | + BUG_ON(1); |
---|
| 20608 | + } |
---|
| 20609 | + } |
---|
| 20610 | + } |
---|
| 20611 | +} |
---|
| 20612 | +#endif /* DHD_DEBUG_UART */ |
---|
| 20613 | + |
---|
| 20614 | +#if defined(DHD_BLOB_EXISTENCE_CHECK) |
---|
| 20615 | +void |
---|
| 20616 | +dhd_set_blob_support(dhd_pub_t *dhdp, char *fw_path) |
---|
| 20617 | +{ |
---|
| 20618 | + struct file *fp; |
---|
| 20619 | + char *filepath = VENDOR_PATH CONFIG_BCMDHD_CLM_PATH; |
---|
| 20620 | + fp = filp_open(filepath, O_RDONLY, 0); |
---|
| 20621 | + if (IS_ERR(fp)) { |
---|
| 20622 | + DHD_ERROR(("%s: ----- blob file doesn't exist (%s) -----\n", __FUNCTION__, |
---|
| 20623 | + filepath)); |
---|
| 20624 | + dhdp->is_blob = FALSE; |
---|
| 20625 | + } else { |
---|
| 20626 | + DHD_ERROR(("%s: ----- blob file exists (%s)-----\n", __FUNCTION__, filepath)); |
---|
| 20627 | + dhdp->is_blob = TRUE; |
---|
| 20628 | +#if defined(CONCATE_BLOB) |
---|
| 20629 | + strncat(fw_path, "_blob", strlen("_blob")); |
---|
| 20630 | +#else |
---|
| 20631 | + BCM_REFERENCE(fw_path); |
---|
| 20632 | +#endif /* SKIP_CONCATE_BLOB */ |
---|
| 20633 | + filp_close(fp, NULL); |
---|
| 20634 | + } |
---|
| 20635 | +} |
---|
| 20636 | +#endif /* DHD_BLOB_EXISTENCE_CHECK */ |
---|
| 20637 | + |
---|
| 20638 | +#if defined(PCIE_FULL_DONGLE) |
---|
| 20639 | +/** test / loopback */ |
---|
| 20640 | +void |
---|
| 20641 | +dmaxfer_free_dmaaddr_handler(void *handle, void *event_info, u8 event) |
---|
| 20642 | +{ |
---|
| 20643 | + dmaxref_mem_map_t *dmmap = (dmaxref_mem_map_t *)event_info; |
---|
| 20644 | + dhd_info_t *dhd_info = (dhd_info_t *)handle; |
---|
| 20645 | + |
---|
| 20646 | + if (event != DHD_WQ_WORK_DMA_LB_MEM_REL) { |
---|
| 20647 | + DHD_ERROR(("%s: Unexpected event \n", __FUNCTION__)); |
---|
| 20648 | + return; |
---|
| 20649 | + } |
---|
| 20650 | + if (dhd_info == NULL) { |
---|
| 20651 | + DHD_ERROR(("%s: Invalid dhd_info\n", __FUNCTION__)); |
---|
| 20652 | + return; |
---|
| 20653 | + } |
---|
| 20654 | + if (dmmap == NULL) { |
---|
| 20655 | + DHD_ERROR(("%s: dmmap is null\n", __FUNCTION__)); |
---|
| 20656 | + return; |
---|
| 20657 | + } |
---|
| 20658 | + dmaxfer_free_prev_dmaaddr(&dhd_info->pub, dmmap); |
---|
| 20659 | +} |
---|
| 20660 | + |
---|
| 20661 | +void |
---|
| 20662 | +dhd_schedule_dmaxfer_free(dhd_pub_t *dhdp, dmaxref_mem_map_t *dmmap) |
---|
| 20663 | +{ |
---|
| 20664 | + dhd_info_t *dhd_info = dhdp->info; |
---|
| 20665 | + |
---|
| 20666 | + dhd_deferred_schedule_work(dhd_info->dhd_deferred_wq, (void *)dmmap, |
---|
| 20667 | + DHD_WQ_WORK_DMA_LB_MEM_REL, dmaxfer_free_dmaaddr_handler, DHD_WQ_WORK_PRIORITY_LOW); |
---|
| 20668 | +} |
---|
| 20669 | +#endif /* PCIE_FULL_DONGLE */ |
---|
| 20670 | +/* ---------------------------- End of sysfs implementation ------------------------------------- */ |
---|
| 20671 | + |
---|
| 20672 | +#ifdef SET_PCIE_IRQ_CPU_CORE |
---|
| 20673 | +void |
---|
| 20674 | +dhd_set_irq_cpucore(dhd_pub_t *dhdp, int affinity_cmd) |
---|
| 20675 | +{ |
---|
| 20676 | + unsigned int pcie_irq = 0; |
---|
| 20677 | + |
---|
| 20678 | + if (!dhdp) { |
---|
| 20679 | + DHD_ERROR(("%s : dhd is NULL\n", __FUNCTION__)); |
---|
| 20680 | + return; |
---|
| 20681 | + } |
---|
| 20682 | + |
---|
| 20683 | + if (!dhdp->bus) { |
---|
| 20684 | + DHD_ERROR(("%s : dhd->bus is NULL\n", __FUNCTION__)); |
---|
| 20685 | + return; |
---|
| 20686 | + } |
---|
| 20687 | + |
---|
| 20688 | + DHD_ERROR(("Enter %s, PCIe affinity cmd=0x%x\n", __FUNCTION__, affinity_cmd)); |
---|
| 20689 | + |
---|
| 20690 | + if (dhdpcie_get_pcieirq(dhdp->bus, &pcie_irq)) { |
---|
| 20691 | + DHD_ERROR(("%s : Can't get interrupt number\n", __FUNCTION__)); |
---|
| 20692 | + return; |
---|
| 20693 | + } |
---|
| 20694 | + |
---|
| 20695 | + /* |
---|
| 20696 | + irq_set_affinity() assign dedicated CPU core PCIe interrupt |
---|
| 20697 | + If dedicated CPU core is not on-line, |
---|
| 20698 | + PCIe interrupt scheduled on CPU core 0 |
---|
| 20699 | + */ |
---|
| 20700 | + switch (affinity_cmd) { |
---|
| 20701 | + case PCIE_IRQ_AFFINITY_OFF: |
---|
| 20702 | + break; |
---|
| 20703 | + case PCIE_IRQ_AFFINITY_BIG_CORE_ANY: |
---|
| 20704 | +#if defined(CONFIG_ARCH_SM8150) |
---|
| 20705 | + irq_set_affinity_hint(pcie_irq, dhdp->info->cpumask_primary); |
---|
| 20706 | + irq_set_affinity(pcie_irq, dhdp->info->cpumask_primary); |
---|
| 20707 | +#else /* Exynos and Others */ |
---|
| 20708 | + irq_set_affinity(pcie_irq, dhdp->info->cpumask_primary); |
---|
| 20709 | +#endif /* CONFIG_ARCH_SM8150 */ |
---|
| 20710 | + break; |
---|
| 20711 | +#if defined(CONFIG_SOC_EXYNOS9810) || defined(CONFIG_SOC_EXYNOS9820) |
---|
| 20712 | + case PCIE_IRQ_AFFINITY_BIG_CORE_EXYNOS: |
---|
| 20713 | + DHD_ERROR(("%s, PCIe IRQ:%u set Core %d\n", |
---|
| 20714 | + __FUNCTION__, pcie_irq, PCIE_IRQ_CPU_CORE)); |
---|
| 20715 | + irq_set_affinity(pcie_irq, cpumask_of(PCIE_IRQ_CPU_CORE)); |
---|
| 20716 | + break; |
---|
| 20717 | +#endif /* CONFIG_SOC_EXYNOS9810 || CONFIG_SOC_EXYNOS9820 */ |
---|
| 20718 | + default: |
---|
| 20719 | + DHD_ERROR(("%s, Unknown PCIe affinity cmd=0x%x\n", |
---|
| 20720 | + __FUNCTION__, affinity_cmd)); |
---|
| 20721 | + } |
---|
| 20722 | +} |
---|
| 20723 | +#endif /* SET_PCIE_IRQ_CPU_CORE */ |
---|
| 20724 | + |
---|
| 20725 | +int |
---|
| 20726 | +dhd_write_file(const char *filepath, char *buf, int buf_len) |
---|
| 20727 | +{ |
---|
| 20728 | + struct file *fp = NULL; |
---|
| 20729 | + int ret = 0; |
---|
| 20730 | + /* change to KERNEL_DS address limit */ |
---|
| 20731 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 20732 | + mm_segment_t old_fs; |
---|
| 20733 | + old_fs = get_fs(); |
---|
| 20734 | + set_fs(KERNEL_DS); |
---|
| 20735 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 20736 | + |
---|
| 20737 | + /* File is always created. */ |
---|
| 20738 | + fp = filp_open(filepath, O_RDWR | O_CREAT, 0664); |
---|
| 20739 | + if (IS_ERR(fp)) { |
---|
| 20740 | + DHD_ERROR(("%s: Couldn't open file '%s' err %ld\n", |
---|
| 20741 | + __FUNCTION__, filepath, PTR_ERR(fp))); |
---|
| 20742 | + ret = BCME_ERROR; |
---|
| 20743 | + } else { |
---|
| 20744 | + if (fp->f_mode & FMODE_WRITE) { |
---|
| 20745 | + ret = vfs_write(fp, buf, buf_len, &fp->f_pos); |
---|
| 20746 | + if (ret < 0) { |
---|
| 20747 | + DHD_ERROR(("%s: Couldn't write file '%s'\n", |
---|
| 20748 | + __FUNCTION__, filepath)); |
---|
| 20749 | + ret = BCME_ERROR; |
---|
| 20750 | + } else { |
---|
| 20751 | + ret = BCME_OK; |
---|
| 20752 | + } |
---|
| 20753 | + } |
---|
| 20754 | + filp_close(fp, NULL); |
---|
| 20755 | + } |
---|
| 20756 | + |
---|
| 20757 | + /* restore previous address limit */ |
---|
| 20758 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 20759 | + set_fs(old_fs); |
---|
| 20760 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 20761 | + |
---|
| 20762 | + return ret; |
---|
| 20763 | +} |
---|
| 20764 | + |
---|
| 20765 | +int |
---|
| 20766 | +dhd_read_file(const char *filepath, char *buf, int buf_len) |
---|
| 20767 | +{ |
---|
| 20768 | + struct file *fp = NULL; |
---|
| 20769 | + int ret; |
---|
| 20770 | + /* change to KERNEL_DS address limit */ |
---|
| 20771 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 20772 | + mm_segment_t old_fs; |
---|
| 20773 | + old_fs = get_fs(); |
---|
| 20774 | + set_fs(KERNEL_DS); |
---|
| 20775 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 20776 | + fp = filp_open(filepath, O_RDONLY, 0); |
---|
| 20777 | + if (IS_ERR(fp)) { |
---|
| 20778 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 20779 | + set_fs(old_fs); |
---|
| 20780 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 20781 | + DHD_ERROR(("%s: File %s doesn't exist\n", __FUNCTION__, filepath)); |
---|
| 20782 | + return BCME_ERROR; |
---|
| 20783 | + } |
---|
| 20784 | + |
---|
| 20785 | + ret = compat_kernel_read(fp, 0, buf, buf_len); |
---|
| 20786 | + filp_close(fp, NULL); |
---|
| 20787 | + |
---|
| 20788 | + /* restore previous address limit */ |
---|
| 20789 | +#if defined(KERNEL_DS) && defined(USER_DS) |
---|
| 20790 | + set_fs(old_fs); |
---|
| 20791 | +#endif /* KERNEL_DS && USER_DS */ |
---|
| 20792 | + |
---|
| 20793 | + /* Return the number of bytes read */ |
---|
| 20794 | + if (ret > 0) { |
---|
| 20795 | + /* Success to read */ |
---|
| 20796 | + ret = 0; |
---|
| 20797 | + } else { |
---|
| 20798 | + DHD_ERROR(("%s: Couldn't read the file %s, ret=%d\n", |
---|
| 20799 | + __FUNCTION__, filepath, ret)); |
---|
| 20800 | + ret = BCME_ERROR; |
---|
| 20801 | + } |
---|
| 20802 | + |
---|
| 20803 | + return ret; |
---|
| 20804 | +} |
---|
| 20805 | + |
---|
| 20806 | +int |
---|
| 20807 | +dhd_write_file_and_check(const char *filepath, char *buf, int buf_len) |
---|
| 20808 | +{ |
---|
| 20809 | + int ret; |
---|
| 20810 | + |
---|
| 20811 | + ret = dhd_write_file(filepath, buf, buf_len); |
---|
| 20812 | + if (ret < 0) { |
---|
| 20813 | + return ret; |
---|
| 20814 | + } |
---|
| 20815 | + |
---|
| 20816 | + /* Read the file again and check if the file size is not zero */ |
---|
| 20817 | + memset(buf, 0, buf_len); |
---|
| 20818 | + ret = dhd_read_file(filepath, buf, buf_len); |
---|
| 20819 | + |
---|
| 20820 | + return ret; |
---|
| 20821 | +} |
---|
| 20822 | + |
---|
| 20823 | +#ifdef DHD_BANDSTEER |
---|
| 20824 | +/* |
---|
| 20825 | + * Function return true only if there exactly two GO interfaces |
---|
| 20826 | + * TODO: Make it flexible to have AP + AP |
---|
| 20827 | + */ |
---|
| 20828 | +s32 |
---|
| 20829 | +dhd_bandsteer_get_ifaces(void *pub, void *ifaces) |
---|
| 20830 | +{ |
---|
| 20831 | + dhd_if_t *iflist; /* For supporting multiple interfaces */ |
---|
| 20832 | + uint8 idx; |
---|
| 20833 | + uint8 ap_idx_count = 0; |
---|
| 20834 | + dhd_pub_t *dhd = (dhd_pub_t *) pub; |
---|
| 20835 | + dhd_bandsteer_iface_info_t *bsd_ifp = (dhd_bandsteer_iface_info_t *)ifaces; |
---|
| 20836 | + |
---|
| 20837 | + DHD_INFO(("%s: entered\n", __FUNCTION__)); |
---|
| 20838 | + for (idx = 0; idx < DHD_MAX_IFS; idx++) { |
---|
| 20839 | + iflist = dhd->info->iflist[idx]; |
---|
| 20840 | + if (iflist == NULL) { |
---|
| 20841 | + continue; |
---|
| 20842 | + } |
---|
| 20843 | + |
---|
| 20844 | + if (iflist->net != NULL) { |
---|
| 20845 | + if (iflist->net->ieee80211_ptr != NULL) { |
---|
| 20846 | + if ( |
---|
| 20847 | + (iflist->net->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) || |
---|
| 20848 | + (iflist->net->ieee80211_ptr->iftype == NL80211_IFTYPE_AP)) { |
---|
| 20849 | + ap_idx_count++; |
---|
| 20850 | + if (ap_idx_count > 2) { |
---|
| 20851 | + continue; |
---|
| 20852 | + } |
---|
| 20853 | + bsd_ifp->ndev = iflist->net; |
---|
| 20854 | + bsd_ifp->bssidx = iflist->bssidx; |
---|
| 20855 | + bsd_ifp++; |
---|
| 20856 | + } |
---|
| 20857 | + } |
---|
| 20858 | + } |
---|
| 20859 | + } |
---|
| 20860 | + if (ap_idx_count == 2) { |
---|
| 20861 | + return BCME_OK; |
---|
| 20862 | + } else { |
---|
| 20863 | + return BCME_ERROR; |
---|
| 20864 | + } |
---|
| 20865 | +} |
---|
| 20866 | + |
---|
| 20867 | +void |
---|
| 20868 | +dhd_bandsteer_schedule_work_on_timeout(dhd_bandsteer_mac_entry_t *dhd_bandsteer_mac) |
---|
| 20869 | +{ |
---|
| 20870 | + dhd_bandsteer_context_t *dhd_bandsteer_cntx = dhd_bandsteer_mac->dhd_bandsteer_cntx; |
---|
| 20871 | + dhd_pub_t *dhd = (dhd_pub_t *) dhd_bandsteer_cntx->dhd_pub; |
---|
| 20872 | + |
---|
| 20873 | + dhd_deferred_schedule_work(dhd->info->dhd_deferred_wq, |
---|
| 20874 | + (void *)dhd_bandsteer_mac, DHD_WQ_WORK_BANDSTEER_STEP_MOVE, |
---|
| 20875 | + dhd_bandsteer_workqueue_wrapper, DHD_WQ_WORK_PRIORITY_LOW); |
---|
| 20876 | +} |
---|
| 20877 | +#endif /* DHD_BANDSTEER */ |
---|
| 20878 | + |
---|
| 20879 | +#ifdef FILTER_IE |
---|
| 20880 | +int dhd_read_from_file(dhd_pub_t *dhd) |
---|
| 20881 | +{ |
---|
| 20882 | + int ret = 0, nread = 0; |
---|
| 20883 | + void *fd; |
---|
| 20884 | + uint8 *buf; |
---|
| 20885 | + NULL_CHECK(dhd, "dhd is NULL", ret); |
---|
| 20886 | + |
---|
| 20887 | + buf = MALLOCZ(dhd->osh, FILE_BLOCK_READ_SIZE); |
---|
| 20888 | + if (!buf) { |
---|
| 20889 | + DHD_ERROR(("error: failed to alllocate buf.\n")); |
---|
| 20890 | + return BCME_NOMEM; |
---|
| 20891 | + } |
---|
| 20892 | + |
---|
| 20893 | + /* open file to read */ |
---|
| 20894 | + fd = dhd_os_open_image1(dhd, FILTER_IE_PATH); |
---|
| 20895 | + if (!fd) { |
---|
| 20896 | + DHD_ERROR(("error: failed to open %s\n", FILTER_IE_PATH)); |
---|
| 20897 | + ret = BCME_EPERM; |
---|
| 20898 | + goto exit; |
---|
| 20899 | + } |
---|
| 20900 | + nread = dhd_os_get_image_block(buf, (FILE_BLOCK_READ_SIZE - 1), fd); |
---|
| 20901 | + if (nread > 0) { |
---|
| 20902 | + buf[nread] = '\0'; |
---|
| 20903 | + if ((ret = dhd_parse_filter_ie(dhd, buf)) < 0) { |
---|
| 20904 | + DHD_ERROR(("error: failed to parse filter ie\n")); |
---|
| 20905 | + } |
---|
| 20906 | + } else { |
---|
| 20907 | + DHD_ERROR(("error: zero length file.failed to read\n")); |
---|
| 20908 | + ret = BCME_ERROR; |
---|
| 20909 | + } |
---|
| 20910 | + dhd_os_close_image1(dhd, fd); |
---|
| 20911 | +exit: |
---|
| 20912 | + if (buf) { |
---|
| 20913 | + MFREE(dhd->osh, buf, FILE_BLOCK_READ_SIZE); |
---|
| 20914 | + buf = NULL; |
---|
| 20915 | + } |
---|
| 20916 | + return ret; |
---|
| 20917 | +} |
---|
| 20918 | + |
---|
| 20919 | +int dhd_get_filter_ie_count(dhd_pub_t *dhdp, uint8* buf) |
---|
| 20920 | +{ |
---|
| 20921 | + uint8* pstr = buf; |
---|
| 20922 | + int element_count = 0; |
---|
| 20923 | + |
---|
| 20924 | + if (buf == NULL) { |
---|
| 20925 | + return BCME_ERROR; |
---|
| 20926 | + } |
---|
| 20927 | + |
---|
| 20928 | + while (*pstr != '\0') { |
---|
| 20929 | + if (*pstr == '\n') { |
---|
| 20930 | + element_count++; |
---|
| 20931 | + } |
---|
| 20932 | + pstr++; |
---|
| 20933 | + } |
---|
| 20934 | + /* |
---|
| 20935 | + * New line character must not be present after last line. |
---|
| 20936 | + * To count last line |
---|
| 20937 | + */ |
---|
| 20938 | + element_count++; |
---|
| 20939 | + |
---|
| 20940 | + return element_count; |
---|
| 20941 | +} |
---|
| 20942 | + |
---|
| 20943 | +int dhd_parse_oui(dhd_pub_t *dhd, uint8 *inbuf, uint8 *oui, int len) |
---|
| 20944 | +{ |
---|
| 20945 | + uint8 i, j, msb, lsb, oui_len = 0; |
---|
| 20946 | + /* |
---|
| 20947 | + * OUI can vary from 3 bytes to 5 bytes. |
---|
| 20948 | + * While reading from file as ascii input it can |
---|
| 20949 | + * take maximum size of 14 bytes and minumum size of |
---|
| 20950 | + * 8 bytes including ":" |
---|
| 20951 | + * Example 5byte OUI <AB:DE:BE:CD:FA> |
---|
| 20952 | + * Example 3byte OUI <AB:DC:EF> |
---|
| 20953 | + */ |
---|
| 20954 | + |
---|
| 20955 | + if ((inbuf == NULL) || (len < 8) || (len > 14)) { |
---|
| 20956 | + DHD_ERROR(("error: failed to parse OUI \n")); |
---|
| 20957 | + return BCME_ERROR; |
---|
| 20958 | + } |
---|
| 20959 | + |
---|
| 20960 | + for (j = 0, i = 0; i < len; i += 3, ++j) { |
---|
| 20961 | + if (!bcm_isxdigit(inbuf[i]) || !bcm_isxdigit(inbuf[i + 1])) { |
---|
| 20962 | + DHD_ERROR(("error: invalid OUI format \n")); |
---|
| 20963 | + return BCME_ERROR; |
---|
| 20964 | + } |
---|
| 20965 | + msb = inbuf[i] > '9' ? bcm_toupper(inbuf[i]) - 'A' + 10 : inbuf[i] - '0'; |
---|
| 20966 | + lsb = inbuf[i + 1] > '9' ? bcm_toupper(inbuf[i + 1]) - |
---|
| 20967 | + 'A' + 10 : inbuf[i + 1] - '0'; |
---|
| 20968 | + oui[j] = (msb << 4) | lsb; |
---|
| 20969 | + } |
---|
| 20970 | + /* Size of oui.It can vary from 3/4/5 */ |
---|
| 20971 | + oui_len = j; |
---|
| 20972 | + |
---|
| 20973 | + return oui_len; |
---|
| 20974 | +} |
---|
| 20975 | + |
---|
| 20976 | +int dhd_check_valid_ie(dhd_pub_t *dhdp, uint8* buf, int len) |
---|
| 20977 | +{ |
---|
| 20978 | + int i = 0; |
---|
| 20979 | + |
---|
| 20980 | + while (i < len) { |
---|
| 20981 | + if (!bcm_isdigit(buf[i])) { |
---|
| 20982 | + DHD_ERROR(("error: non digit value found in filter_ie \n")); |
---|
| 20983 | + return BCME_ERROR; |
---|
| 20984 | + } |
---|
| 20985 | + i++; |
---|
| 20986 | + } |
---|
| 20987 | + if (bcm_atoi((char*)buf) > 255) { |
---|
| 20988 | + DHD_ERROR(("error: element id cannot be greater than 255 \n")); |
---|
| 20989 | + return BCME_ERROR; |
---|
| 20990 | + } |
---|
| 20991 | + |
---|
| 20992 | + return BCME_OK; |
---|
| 20993 | +} |
---|
| 20994 | + |
---|
| 20995 | +int dhd_parse_filter_ie(dhd_pub_t *dhd, uint8 *buf) |
---|
| 20996 | +{ |
---|
| 20997 | + int element_count = 0, i = 0, oui_size = 0, ret = 0; |
---|
| 20998 | + uint16 bufsize, buf_space_left, id = 0, len = 0; |
---|
| 20999 | + uint16 filter_iovsize, all_tlvsize; |
---|
| 21000 | + wl_filter_ie_tlv_t *p_ie_tlv = NULL; |
---|
| 21001 | + wl_filter_ie_iov_v1_t *p_filter_iov = (wl_filter_ie_iov_v1_t *) NULL; |
---|
| 21002 | + char *token = NULL, *ele_token = NULL, *oui_token = NULL, *type = NULL; |
---|
| 21003 | + uint8 data[20]; |
---|
| 21004 | + |
---|
| 21005 | + element_count = dhd_get_filter_ie_count(dhd, buf); |
---|
| 21006 | + DHD_INFO(("total element count %d \n", element_count)); |
---|
| 21007 | + /* Calculate the whole buffer size */ |
---|
| 21008 | + filter_iovsize = sizeof(wl_filter_ie_iov_v1_t) + FILTER_IE_BUFSZ; |
---|
| 21009 | + p_filter_iov = MALLOCZ(dhd->osh, filter_iovsize); |
---|
| 21010 | + |
---|
| 21011 | + if (p_filter_iov == NULL) { |
---|
| 21012 | + DHD_ERROR(("error: failed to allocate %d bytes of memory\n", filter_iovsize)); |
---|
| 21013 | + return BCME_ERROR; |
---|
| 21014 | + } |
---|
| 21015 | + |
---|
| 21016 | + /* setup filter iovar header */ |
---|
| 21017 | + p_filter_iov->version = WL_FILTER_IE_VERSION; |
---|
| 21018 | + p_filter_iov->len = filter_iovsize; |
---|
| 21019 | + p_filter_iov->fixed_length = p_filter_iov->len - FILTER_IE_BUFSZ; |
---|
| 21020 | + p_filter_iov->pktflag = FC_PROBE_REQ; |
---|
| 21021 | + p_filter_iov->option = WL_FILTER_IE_CHECK_SUB_OPTION; |
---|
| 21022 | + /* setup TLVs */ |
---|
| 21023 | + bufsize = filter_iovsize - WL_FILTER_IE_IOV_HDR_SIZE; /* adjust available size for TLVs */ |
---|
| 21024 | + p_ie_tlv = (wl_filter_ie_tlv_t *)&p_filter_iov->tlvs[0]; |
---|
| 21025 | + buf_space_left = bufsize; |
---|
| 21026 | + |
---|
| 21027 | + while ((i < element_count) && (buf != NULL)) { |
---|
| 21028 | + len = 0; |
---|
| 21029 | + /* token contains one line of input data */ |
---|
| 21030 | + token = bcmstrtok((char**)&buf, "\n", NULL); |
---|
| 21031 | + if (token == NULL) { |
---|
| 21032 | + break; |
---|
| 21033 | + } |
---|
| 21034 | + if ((ele_token = bcmstrstr(token, ",")) == NULL) { |
---|
| 21035 | + /* only element id is present */ |
---|
| 21036 | + if (dhd_check_valid_ie(dhd, token, strlen(token)) == BCME_ERROR) { |
---|
| 21037 | + DHD_ERROR(("error: Invalid element id \n")); |
---|
| 21038 | + ret = BCME_ERROR; |
---|
| 21039 | + goto exit; |
---|
| 21040 | + } |
---|
| 21041 | + id = bcm_atoi((char*)token); |
---|
| 21042 | + data[len++] = WL_FILTER_IE_SET; |
---|
| 21043 | + } else { |
---|
| 21044 | + /* oui is present */ |
---|
| 21045 | + ele_token = bcmstrtok(&token, ",", NULL); |
---|
| 21046 | + if ((ele_token == NULL) || (dhd_check_valid_ie(dhd, ele_token, |
---|
| 21047 | + strlen(ele_token)) == BCME_ERROR)) { |
---|
| 21048 | + DHD_ERROR(("error: Invalid element id \n")); |
---|
| 21049 | + ret = BCME_ERROR; |
---|
| 21050 | + goto exit; |
---|
| 21051 | + } |
---|
| 21052 | + id = bcm_atoi((char*)ele_token); |
---|
| 21053 | + data[len++] = WL_FILTER_IE_SET; |
---|
| 21054 | + if ((oui_token = bcmstrstr(token, ",")) == NULL) { |
---|
| 21055 | + oui_size = dhd_parse_oui(dhd, token, &(data[len]), strlen(token)); |
---|
| 21056 | + if (oui_size == BCME_ERROR) { |
---|
| 21057 | + DHD_ERROR(("error: Invalid OUI \n")); |
---|
| 21058 | + ret = BCME_ERROR; |
---|
| 21059 | + goto exit; |
---|
| 21060 | + } |
---|
| 21061 | + len += oui_size; |
---|
| 21062 | + } else { |
---|
| 21063 | + /* type is present */ |
---|
| 21064 | + oui_token = bcmstrtok(&token, ",", NULL); |
---|
| 21065 | + if ((oui_token == NULL) || ((oui_size = |
---|
| 21066 | + dhd_parse_oui(dhd, oui_token, |
---|
| 21067 | + &(data[len]), strlen(oui_token))) == BCME_ERROR)) { |
---|
| 21068 | + DHD_ERROR(("error: Invalid OUI \n")); |
---|
| 21069 | + ret = BCME_ERROR; |
---|
| 21070 | + goto exit; |
---|
| 21071 | + } |
---|
| 21072 | + len += oui_size; |
---|
| 21073 | + if ((type = bcmstrstr(token, ",")) == NULL) { |
---|
| 21074 | + if (dhd_check_valid_ie(dhd, token, |
---|
| 21075 | + strlen(token)) == BCME_ERROR) { |
---|
| 21076 | + DHD_ERROR(("error: Invalid type \n")); |
---|
| 21077 | + ret = BCME_ERROR; |
---|
| 21078 | + goto exit; |
---|
| 21079 | + } |
---|
| 21080 | + data[len++] = bcm_atoi((char*)token); |
---|
| 21081 | + } else { |
---|
| 21082 | + /* subtype is present */ |
---|
| 21083 | + type = bcmstrtok(&token, ",", NULL); |
---|
| 21084 | + if ((type == NULL) || (dhd_check_valid_ie(dhd, type, |
---|
| 21085 | + strlen(type)) == BCME_ERROR)) { |
---|
| 21086 | + DHD_ERROR(("error: Invalid type \n")); |
---|
| 21087 | + ret = BCME_ERROR; |
---|
| 21088 | + goto exit; |
---|
| 21089 | + } |
---|
| 21090 | + data[len++] = bcm_atoi((char*)type); |
---|
| 21091 | + /* subtype is last element */ |
---|
| 21092 | + if ((token == NULL) || (*token == '\0') || |
---|
| 21093 | + (dhd_check_valid_ie(dhd, token, |
---|
| 21094 | + strlen(token)) == BCME_ERROR)) { |
---|
| 21095 | + DHD_ERROR(("error: Invalid subtype \n")); |
---|
| 21096 | + ret = BCME_ERROR; |
---|
| 21097 | + goto exit; |
---|
| 21098 | + } |
---|
| 21099 | + data[len++] = bcm_atoi((char*)token); |
---|
| 21100 | + } |
---|
| 21101 | + } |
---|
| 21102 | + } |
---|
| 21103 | + ret = bcm_pack_xtlv_entry((uint8 **)&p_ie_tlv, |
---|
| 21104 | + &buf_space_left, id, len, data, BCM_XTLV_OPTION_ALIGN32); |
---|
| 21105 | + if (ret != BCME_OK) { |
---|
| 21106 | + DHD_ERROR(("%s : bcm_pack_xtlv_entry() failed ," |
---|
| 21107 | + "status=%d\n", __FUNCTION__, ret)); |
---|
| 21108 | + goto exit; |
---|
| 21109 | + } |
---|
| 21110 | + i++; |
---|
| 21111 | + } |
---|
| 21112 | + if (i == 0) { |
---|
| 21113 | + /* file is empty or first line is blank */ |
---|
| 21114 | + DHD_ERROR(("error: filter_ie file is empty or first line is blank \n")); |
---|
| 21115 | + ret = BCME_ERROR; |
---|
| 21116 | + goto exit; |
---|
| 21117 | + } |
---|
| 21118 | + /* update the iov header, set len to include all TLVs + header */ |
---|
| 21119 | + all_tlvsize = (bufsize - buf_space_left); |
---|
| 21120 | + p_filter_iov->len = htol16(all_tlvsize + WL_FILTER_IE_IOV_HDR_SIZE); |
---|
| 21121 | + ret = dhd_iovar(dhd, 0, "filter_ie", (void *)p_filter_iov, |
---|
| 21122 | + p_filter_iov->len, NULL, 0, TRUE); |
---|
| 21123 | + if (ret != BCME_OK) { |
---|
| 21124 | + DHD_ERROR(("error: IOVAR failed, status=%d\n", ret)); |
---|
| 21125 | + } |
---|
| 21126 | +exit: |
---|
| 21127 | + /* clean up */ |
---|
| 21128 | + if (p_filter_iov) { |
---|
| 21129 | + MFREE(dhd->osh, p_filter_iov, filter_iovsize); |
---|
| 21130 | + p_filter_iov = NULL; |
---|
| 21131 | + } |
---|
| 21132 | + return ret; |
---|
| 21133 | +} |
---|
| 21134 | +#endif /* FILTER_IE */ |
---|
| 21135 | +#ifdef DHD_WAKE_STATUS |
---|
| 21136 | +wake_counts_t* |
---|
| 21137 | +dhd_get_wakecount(dhd_pub_t *dhdp) |
---|
| 21138 | +{ |
---|
| 21139 | + return dhd_bus_get_wakecount(dhdp); |
---|
| 21140 | +} |
---|
| 21141 | +#endif /* DHD_WAKE_STATUS */ |
---|
| 21142 | + |
---|
| 21143 | +int |
---|
| 21144 | +dhd_get_random_bytes(uint8 *buf, uint len) |
---|
| 21145 | +{ |
---|
| 21146 | +#ifdef BCMPCIE |
---|
| 21147 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) |
---|
| 21148 | + int rndlen = get_random_bytes_arch(buf, len); |
---|
| 21149 | + if (rndlen != len) { |
---|
| 21150 | + bzero(buf, len); |
---|
| 21151 | + get_random_bytes(buf, len); |
---|
| 21152 | + } |
---|
| 21153 | +#else |
---|
| 21154 | + get_random_bytes_arch(buf, len); |
---|
| 21155 | +#endif // endif |
---|
| 21156 | +#endif /* BCMPCIE */ |
---|
| 21157 | + return BCME_OK; |
---|
| 21158 | +} |
---|
| 21159 | + |
---|
| 21160 | +#if defined(DHD_HANG_SEND_UP_TEST) |
---|
| 21161 | +void |
---|
| 21162 | +dhd_make_hang_with_reason(struct net_device *dev, const char *string_num) |
---|
| 21163 | +{ |
---|
| 21164 | + dhd_info_t *dhd = NULL; |
---|
| 21165 | + dhd_pub_t *dhdp = NULL; |
---|
| 21166 | + uint reason = HANG_REASON_MAX; |
---|
| 21167 | + uint32 fw_test_code = 0; |
---|
| 21168 | + dhd = DHD_DEV_INFO(dev); |
---|
| 21169 | + |
---|
| 21170 | + if (dhd) { |
---|
| 21171 | + dhdp = &dhd->pub; |
---|
| 21172 | + } |
---|
| 21173 | + |
---|
| 21174 | + if (!dhd || !dhdp) { |
---|
| 21175 | + return; |
---|
| 21176 | + } |
---|
| 21177 | + |
---|
| 21178 | + reason = (uint) bcm_strtoul(string_num, NULL, 0); |
---|
| 21179 | + DHD_ERROR(("Enter %s, reason=0x%x\n", __FUNCTION__, reason)); |
---|
| 21180 | + |
---|
| 21181 | + if (reason == 0) { |
---|
| 21182 | + if (dhdp->req_hang_type) { |
---|
| 21183 | + DHD_ERROR(("%s, Clear HANG test request 0x%x\n", |
---|
| 21184 | + __FUNCTION__, dhdp->req_hang_type)); |
---|
| 21185 | + dhdp->req_hang_type = 0; |
---|
| 21186 | + return; |
---|
| 21187 | + } else { |
---|
| 21188 | + DHD_ERROR(("%s, No requested HANG test\n", __FUNCTION__)); |
---|
| 21189 | + return; |
---|
| 21190 | + } |
---|
| 21191 | + } else if ((reason <= HANG_REASON_MASK) || (reason >= HANG_REASON_MAX)) { |
---|
| 21192 | + DHD_ERROR(("Invalid HANG request, reason 0x%x\n", reason)); |
---|
| 21193 | + return; |
---|
| 21194 | + } |
---|
| 21195 | + |
---|
| 21196 | + if (dhdp->req_hang_type != 0) { |
---|
| 21197 | + DHD_ERROR(("Already HANG requested for test\n")); |
---|
| 21198 | + return; |
---|
| 21199 | + } |
---|
| 21200 | + |
---|
| 21201 | + switch (reason) { |
---|
| 21202 | + case HANG_REASON_IOCTL_RESP_TIMEOUT: |
---|
| 21203 | + DHD_ERROR(("Make HANG!!!: IOCTL response timeout(0x%x)\n", reason)); |
---|
| 21204 | + dhdp->req_hang_type = reason; |
---|
| 21205 | + fw_test_code = 102; /* resumed on timeour */ |
---|
| 21206 | + (void) dhd_wl_ioctl_set_intiovar(dhdp, "bus:disconnect", fw_test_code, |
---|
| 21207 | + WLC_SET_VAR, TRUE, 0); |
---|
| 21208 | + break; |
---|
| 21209 | + case HANG_REASON_DONGLE_TRAP: |
---|
| 21210 | + DHD_ERROR(("Make HANG!!!: Dongle trap (0x%x)\n", reason)); |
---|
| 21211 | + dhdp->req_hang_type = reason; |
---|
| 21212 | + fw_test_code = 99; /* dongle trap */ |
---|
| 21213 | + (void) dhd_wl_ioctl_set_intiovar(dhdp, "bus:disconnect", fw_test_code, |
---|
| 21214 | + WLC_SET_VAR, TRUE, 0); |
---|
| 21215 | + break; |
---|
| 21216 | + case HANG_REASON_D3_ACK_TIMEOUT: |
---|
| 21217 | + DHD_ERROR(("Make HANG!!!: D3 ACK timeout (0x%x)\n", reason)); |
---|
| 21218 | + dhdp->req_hang_type = reason; |
---|
| 21219 | + break; |
---|
| 21220 | + case HANG_REASON_BUS_DOWN: |
---|
| 21221 | + DHD_ERROR(("Make HANG!!!: BUS down(0x%x)\n", reason)); |
---|
| 21222 | + dhdp->req_hang_type = reason; |
---|
| 21223 | + break; |
---|
| 21224 | + case HANG_REASON_PCIE_LINK_DOWN_RC_DETECT: |
---|
| 21225 | + case HANG_REASON_PCIE_LINK_DOWN_EP_DETECT: |
---|
| 21226 | + case HANG_REASON_MSGBUF_LIVELOCK: |
---|
| 21227 | + dhdp->req_hang_type = 0; |
---|
| 21228 | + DHD_ERROR(("Does not support requested HANG(0x%x)\n", reason)); |
---|
| 21229 | + break; |
---|
| 21230 | + case HANG_REASON_IFACE_DEL_FAILURE: |
---|
| 21231 | + dhdp->req_hang_type = 0; |
---|
| 21232 | + DHD_ERROR(("Does not support requested HANG(0x%x)\n", reason)); |
---|
| 21233 | + break; |
---|
| 21234 | + case HANG_REASON_HT_AVAIL_ERROR: |
---|
| 21235 | + dhdp->req_hang_type = 0; |
---|
| 21236 | + DHD_ERROR(("PCIe does not support requested HANG(0x%x)\n", reason)); |
---|
| 21237 | + break; |
---|
| 21238 | + case HANG_REASON_PCIE_RC_LINK_UP_FAIL: |
---|
| 21239 | + DHD_ERROR(("Make HANG!!!:Link Up(0x%x)\n", reason)); |
---|
| 21240 | + dhdp->req_hang_type = reason; |
---|
| 21241 | + break; |
---|
| 21242 | + default: |
---|
| 21243 | + dhdp->req_hang_type = 0; |
---|
| 21244 | + DHD_ERROR(("Unknown HANG request (0x%x)\n", reason)); |
---|
| 21245 | + break; |
---|
| 21246 | + } |
---|
| 21247 | +} |
---|
| 21248 | +#endif /* DHD_HANG_SEND_UP_TEST */ |
---|
| 21249 | + |
---|
| 21250 | +#ifdef DHD_ERPOM |
---|
| 21251 | +static void |
---|
| 21252 | +dhd_error_recovery(void *handle, void *event_info, u8 event) |
---|
| 21253 | +{ |
---|
| 21254 | + dhd_info_t *dhd = handle; |
---|
| 21255 | + dhd_pub_t *dhdp; |
---|
| 21256 | + int ret = 0; |
---|
| 21257 | + |
---|
| 21258 | + if (!dhd) { |
---|
| 21259 | + DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); |
---|
| 21260 | + return; |
---|
| 21261 | + } |
---|
| 21262 | + |
---|
| 21263 | + dhdp = &dhd->pub; |
---|
| 21264 | + |
---|
| 21265 | + if (!(dhd->dhd_state & DHD_ATTACH_STATE_DONE)) { |
---|
| 21266 | + DHD_ERROR(("%s: init not completed, cannot initiate recovery\n", |
---|
| 21267 | + __FUNCTION__)); |
---|
| 21268 | + return; |
---|
| 21269 | + } |
---|
| 21270 | + |
---|
| 21271 | + ret = dhd_bus_perform_flr_with_quiesce(dhdp, dhdp->bus, FALSE); |
---|
| 21272 | + if (ret != BCME_DNGL_DEVRESET) { |
---|
| 21273 | + DHD_ERROR(("%s: dhd_bus_perform_flr_with_quiesce failed with ret: %d," |
---|
| 21274 | + "toggle REG_ON\n", __FUNCTION__, ret)); |
---|
| 21275 | + /* toggle REG_ON */ |
---|
| 21276 | + dhdp->pom_toggle_reg_on(WLAN_FUNC_ID, BY_WLAN_DUE_TO_WLAN); |
---|
| 21277 | + return; |
---|
| 21278 | + } |
---|
| 21279 | +} |
---|
| 21280 | + |
---|
| 21281 | +void |
---|
| 21282 | +dhd_schedule_reset(dhd_pub_t *dhdp) |
---|
| 21283 | +{ |
---|
| 21284 | + if (dhdp->enable_erpom) { |
---|
| 21285 | + dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, NULL, |
---|
| 21286 | + DHD_WQ_WORK_ERROR_RECOVERY, dhd_error_recovery, DHD_WQ_WORK_PRIORITY_HIGH); |
---|
| 21287 | + } |
---|
| 21288 | +} |
---|
| 21289 | +#endif /* DHD_ERPOM */ |
---|
| 21290 | + |
---|
| 21291 | +#ifdef DHD_PKT_LOGGING |
---|
| 21292 | +void |
---|
| 21293 | +dhd_pktlog_dump(void *handle, void *event_info, u8 event) |
---|
| 21294 | +{ |
---|
| 21295 | + dhd_info_t *dhd = handle; |
---|
| 21296 | + |
---|
| 21297 | + if (!dhd) { |
---|
| 21298 | + DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); |
---|
| 21299 | + return; |
---|
| 21300 | + } |
---|
| 21301 | + |
---|
| 21302 | + if (dhd_pktlog_dump_write_file(&dhd->pub)) { |
---|
| 21303 | + DHD_ERROR(("%s: writing pktlog dump file failed\n", __FUNCTION__)); |
---|
| 21304 | + return; |
---|
| 21305 | + } |
---|
| 21306 | +} |
---|
| 21307 | + |
---|
| 21308 | +void |
---|
| 21309 | +dhd_schedule_pktlog_dump(dhd_pub_t *dhdp) |
---|
| 21310 | +{ |
---|
| 21311 | + dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, |
---|
| 21312 | + (void*)NULL, DHD_WQ_WORK_PKTLOG_DUMP, |
---|
| 21313 | + dhd_pktlog_dump, DHD_WQ_WORK_PRIORITY_HIGH); |
---|
| 21314 | +} |
---|
| 21315 | +#endif /* DHD_PKT_LOGGING */ |
---|
| 21316 | + |
---|
| 21317 | +#ifdef BIGDATA_SOFTAP |
---|
| 21318 | +void dhd_schedule_gather_ap_stadata(void *bcm_cfg, void *ndev, const wl_event_msg_t *e) |
---|
| 21319 | +{ |
---|
| 21320 | + struct bcm_cfg80211 *cfg; |
---|
| 21321 | + dhd_pub_t *dhdp; |
---|
| 21322 | + ap_sta_wq_data_t *p_wq_data; |
---|
| 21323 | + |
---|
| 21324 | + if (!bcm_cfg || !ndev || !e) { |
---|
| 21325 | + WL_ERR(("bcm_cfg=%p ndev=%p e=%p\n", bcm_cfg, ndev, e)); |
---|
| 21326 | + return; |
---|
| 21327 | + } |
---|
| 21328 | + |
---|
| 21329 | + cfg = (struct bcm_cfg80211 *)bcm_cfg; |
---|
| 21330 | + dhdp = (dhd_pub_t *)cfg->pub; |
---|
| 21331 | + |
---|
| 21332 | + if (!dhdp || !cfg->ap_sta_info) { |
---|
| 21333 | + WL_ERR(("dhdp=%p ap_sta_info=%p\n", dhdp, cfg->ap_sta_info)); |
---|
| 21334 | + return; |
---|
| 21335 | + } |
---|
| 21336 | + |
---|
| 21337 | + p_wq_data = (ap_sta_wq_data_t *)MALLOCZ(dhdp->osh, sizeof(ap_sta_wq_data_t)); |
---|
| 21338 | + if (unlikely(!p_wq_data)) { |
---|
| 21339 | + DHD_ERROR(("%s(): could not allocate memory for - " |
---|
| 21340 | + "ap_sta_wq_data_t\n", __FUNCTION__)); |
---|
| 21341 | + return; |
---|
| 21342 | + } |
---|
| 21343 | + |
---|
| 21344 | + mutex_lock(&cfg->ap_sta_info->wq_data_sync); |
---|
| 21345 | + |
---|
| 21346 | + memcpy(&p_wq_data->e, e, sizeof(wl_event_msg_t)); |
---|
| 21347 | + p_wq_data->dhdp = dhdp; |
---|
| 21348 | + p_wq_data->bcm_cfg = cfg; |
---|
| 21349 | + p_wq_data->ndev = (struct net_device *)ndev; |
---|
| 21350 | + |
---|
| 21351 | + mutex_unlock(&cfg->ap_sta_info->wq_data_sync); |
---|
| 21352 | + |
---|
| 21353 | + dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, |
---|
| 21354 | + p_wq_data, DHD_WQ_WORK_GET_BIGDATA_AP, |
---|
| 21355 | + wl_gather_ap_stadata, DHD_WQ_WORK_PRIORITY_HIGH); |
---|
| 21356 | + |
---|
| 21357 | +} |
---|
| 21358 | +#endif /* BIGDATA_SOFTAP */ |
---|
| 21359 | + |
---|
| 21360 | +void |
---|
| 21361 | +get_debug_dump_time(char *str) |
---|
| 21362 | +{ |
---|
| 21363 | + struct timespec64 curtime; |
---|
| 21364 | + unsigned long long local_time; |
---|
| 21365 | + |
---|
| 21366 | + struct rtc_time tm; |
---|
| 21367 | + |
---|
| 21368 | + if (!strlen(str)) { |
---|
| 21369 | + ktime_get_real_ts64(&curtime); |
---|
| 21370 | + local_time = (u64)(curtime.tv_sec - |
---|
| 21371 | + (sys_tz.tz_minuteswest * DHD_LOG_DUMP_TS_MULTIPLIER_VALUE)); |
---|
| 21372 | + rtc_time_to_tm(local_time, &tm); |
---|
| 21373 | + |
---|
| 21374 | + snprintf(str, DEBUG_DUMP_TIME_BUF_LEN, DHD_LOG_DUMP_TS_FMT_YYMMDDHHMMSSMSMS, |
---|
| 21375 | + tm.tm_year - 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, |
---|
| 21376 | + tm.tm_sec, (int)(curtime.tv_nsec/NSEC_PER_MSEC)); |
---|
| 21377 | + } |
---|
| 21378 | +} |
---|
| 21379 | + |
---|
| 21380 | +void |
---|
| 21381 | +clear_debug_dump_time(char *str) |
---|
| 21382 | +{ |
---|
| 21383 | + memset(str, 0, DEBUG_DUMP_TIME_BUF_LEN); |
---|
| 21384 | +} |
---|
| 21385 | +#if defined(WL_CFGVENDOR_SEND_HANG_EVENT) || defined(DHD_PKT_LOGGING) |
---|
| 21386 | +void |
---|
| 21387 | +copy_debug_dump_time(char *dest, char *src) |
---|
| 21388 | +{ |
---|
| 21389 | + memcpy(dest, src, DEBUG_DUMP_TIME_BUF_LEN); |
---|
| 21390 | +} |
---|
| 21391 | +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT || DHD_PKT_LOGGING */ |
---|
| 21392 | + |
---|
| 21393 | +void |
---|
| 21394 | +dhd_print_tasklet_status(dhd_pub_t *dhd) |
---|
| 21395 | +{ |
---|
| 21396 | + dhd_info_t *dhdinfo; |
---|
| 21397 | + |
---|
| 21398 | + if (!dhd) { |
---|
| 21399 | + DHD_ERROR(("%s : DHD is null\n", __FUNCTION__)); |
---|
| 21400 | + return; |
---|
| 21401 | + } |
---|
| 21402 | + |
---|
| 21403 | + dhdinfo = dhd->info; |
---|
| 21404 | + |
---|
| 21405 | + if (!dhdinfo) { |
---|
| 21406 | + DHD_ERROR(("%s : DHD INFO is null \n", __FUNCTION__)); |
---|
| 21407 | + return; |
---|
| 21408 | + } |
---|
| 21409 | + |
---|
| 21410 | + DHD_ERROR(("DHD Tasklet status : 0x%lx\n", dhdinfo->tasklet.state)); |
---|
| 21411 | +} |
---|
| 21412 | + |
---|
| 21413 | +/* |
---|
| 21414 | + * DHD RING |
---|
| 21415 | + */ |
---|
| 21416 | +#define DHD_RING_ERR_INTERNAL(fmt, ...) DHD_ERROR(("EWPF-" fmt, ##__VA_ARGS__)) |
---|
| 21417 | +#define DHD_RING_TRACE_INTERNAL(fmt, ...) DHD_INFO(("EWPF-" fmt, ##__VA_ARGS__)) |
---|
| 21418 | + |
---|
| 21419 | +#define DHD_RING_ERR(x) DHD_RING_ERR_INTERNAL x |
---|
| 21420 | +#define DHD_RING_TRACE(x) DHD_RING_TRACE_INTERNAL x |
---|
| 21421 | + |
---|
| 21422 | +#define DHD_RING_MAGIC 0x20170910 |
---|
| 21423 | +#define DHD_RING_IDX_INVALID 0xffffffff |
---|
| 21424 | + |
---|
| 21425 | +#define DHD_RING_SYNC_LOCK_INIT(osh) dhd_os_spin_lock_init(osh) |
---|
| 21426 | +#define DHD_RING_SYNC_LOCK_DEINIT(osh, lock) dhd_os_spin_lock_deinit(osh, lock) |
---|
| 21427 | +#define DHD_RING_SYNC_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) |
---|
| 21428 | +#define DHD_RING_SYNC_UNLOCK(lock, flags) dhd_os_spin_unlock(lock, flags) |
---|
| 21429 | + |
---|
| 21430 | +typedef struct { |
---|
| 21431 | + uint32 elem_size; |
---|
| 21432 | + uint32 elem_cnt; |
---|
| 21433 | + uint32 write_idx; /* next write index, -1 : not started */ |
---|
| 21434 | + uint32 read_idx; /* next read index, -1 : not start */ |
---|
| 21435 | + |
---|
| 21436 | + /* protected elements during serialization */ |
---|
| 21437 | + int lock_idx; /* start index of locked, element will not be overried */ |
---|
| 21438 | + int lock_count; /* number of locked, from lock idx */ |
---|
| 21439 | + |
---|
| 21440 | + /* saved data elements */ |
---|
| 21441 | + void *elem; |
---|
| 21442 | +} dhd_fixed_ring_info_t; |
---|
| 21443 | + |
---|
| 21444 | +typedef struct { |
---|
| 21445 | + uint32 elem_size; |
---|
| 21446 | + uint32 elem_cnt; |
---|
| 21447 | + uint32 idx; /* -1 : not started */ |
---|
| 21448 | + uint32 rsvd; /* reserved for future use */ |
---|
| 21449 | + |
---|
| 21450 | + /* protected elements during serialization */ |
---|
| 21451 | + atomic_t ring_locked; |
---|
| 21452 | + /* check the overwriting */ |
---|
| 21453 | + uint32 ring_overwrited; |
---|
| 21454 | + |
---|
| 21455 | + /* saved data elements */ |
---|
| 21456 | + void *elem; |
---|
| 21457 | +} dhd_singleidx_ring_info_t; |
---|
| 21458 | + |
---|
| 21459 | +typedef struct { |
---|
| 21460 | + uint32 magic; |
---|
| 21461 | + uint32 type; |
---|
| 21462 | + void *ring_sync; /* spinlock for sync */ |
---|
| 21463 | + union { |
---|
| 21464 | + dhd_fixed_ring_info_t fixed; |
---|
| 21465 | + dhd_singleidx_ring_info_t single; |
---|
| 21466 | + }; |
---|
| 21467 | +} dhd_ring_info_t; |
---|
| 21468 | + |
---|
| 21469 | +uint32 |
---|
| 21470 | +dhd_ring_get_hdr_size(void) |
---|
| 21471 | +{ |
---|
| 21472 | + return sizeof(dhd_ring_info_t); |
---|
| 21473 | +} |
---|
| 21474 | + |
---|
| 21475 | +void * |
---|
| 21476 | +dhd_ring_init(dhd_pub_t *dhdp, uint8 *buf, uint32 buf_size, uint32 elem_size, |
---|
| 21477 | + uint32 elem_cnt, uint32 type) |
---|
| 21478 | +{ |
---|
| 21479 | + dhd_ring_info_t *ret_ring; |
---|
| 21480 | + |
---|
| 21481 | + if (!buf) { |
---|
| 21482 | + DHD_RING_ERR(("NO RING BUFFER\n")); |
---|
| 21483 | + return NULL; |
---|
| 21484 | + } |
---|
| 21485 | + |
---|
| 21486 | + if (buf_size < dhd_ring_get_hdr_size() + elem_size * elem_cnt) { |
---|
| 21487 | + DHD_RING_ERR(("RING SIZE IS TOO SMALL\n")); |
---|
| 21488 | + return NULL; |
---|
| 21489 | + } |
---|
| 21490 | + |
---|
| 21491 | + if (type != DHD_RING_TYPE_FIXED && type != DHD_RING_TYPE_SINGLE_IDX) { |
---|
| 21492 | + DHD_RING_ERR(("UNSUPPORTED RING TYPE\n")); |
---|
| 21493 | + return NULL; |
---|
| 21494 | + } |
---|
| 21495 | + |
---|
| 21496 | + ret_ring = (dhd_ring_info_t *)buf; |
---|
| 21497 | + ret_ring->type = type; |
---|
| 21498 | + ret_ring->ring_sync = DHD_RING_SYNC_LOCK_INIT(dhdp->osh); |
---|
| 21499 | + ret_ring->magic = DHD_RING_MAGIC; |
---|
| 21500 | + |
---|
| 21501 | + if (type == DHD_RING_TYPE_FIXED) { |
---|
| 21502 | + ret_ring->fixed.read_idx = DHD_RING_IDX_INVALID; |
---|
| 21503 | + ret_ring->fixed.write_idx = DHD_RING_IDX_INVALID; |
---|
| 21504 | + ret_ring->fixed.lock_idx = DHD_RING_IDX_INVALID; |
---|
| 21505 | + ret_ring->fixed.elem = buf + sizeof(dhd_ring_info_t); |
---|
| 21506 | + ret_ring->fixed.elem_size = elem_size; |
---|
| 21507 | + ret_ring->fixed.elem_cnt = elem_cnt; |
---|
| 21508 | + } else { |
---|
| 21509 | + ret_ring->single.idx = DHD_RING_IDX_INVALID; |
---|
| 21510 | + atomic_set(&ret_ring->single.ring_locked, 0); |
---|
| 21511 | + ret_ring->single.ring_overwrited = 0; |
---|
| 21512 | + ret_ring->single.rsvd = 0; |
---|
| 21513 | + ret_ring->single.elem = buf + sizeof(dhd_ring_info_t); |
---|
| 21514 | + ret_ring->single.elem_size = elem_size; |
---|
| 21515 | + ret_ring->single.elem_cnt = elem_cnt; |
---|
| 21516 | + } |
---|
| 21517 | + |
---|
| 21518 | + return ret_ring; |
---|
| 21519 | +} |
---|
| 21520 | + |
---|
| 21521 | +void |
---|
| 21522 | +dhd_ring_deinit(dhd_pub_t *dhdp, void *_ring) |
---|
| 21523 | +{ |
---|
| 21524 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 21525 | + if (!ring) { |
---|
| 21526 | + return; |
---|
| 21527 | + } |
---|
| 21528 | + |
---|
| 21529 | + if (ring->magic != DHD_RING_MAGIC) { |
---|
| 21530 | + return; |
---|
| 21531 | + } |
---|
| 21532 | + |
---|
| 21533 | + if (ring->type != DHD_RING_TYPE_FIXED && |
---|
| 21534 | + ring->type != DHD_RING_TYPE_SINGLE_IDX) { |
---|
| 21535 | + return; |
---|
| 21536 | + } |
---|
| 21537 | + |
---|
| 21538 | + DHD_RING_SYNC_LOCK_DEINIT(dhdp->osh, ring->ring_sync); |
---|
| 21539 | + ring->ring_sync = NULL; |
---|
| 21540 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 21541 | + dhd_fixed_ring_info_t *fixed = &ring->fixed; |
---|
| 21542 | + memset(fixed->elem, 0, fixed->elem_size * fixed->elem_cnt); |
---|
| 21543 | + fixed->elem_size = fixed->elem_cnt = 0; |
---|
| 21544 | + } else { |
---|
| 21545 | + dhd_singleidx_ring_info_t *single = &ring->single; |
---|
| 21546 | + memset(single->elem, 0, single->elem_size * single->elem_cnt); |
---|
| 21547 | + single->elem_size = single->elem_cnt = 0; |
---|
| 21548 | + } |
---|
| 21549 | + ring->type = 0; |
---|
| 21550 | + ring->magic = 0; |
---|
| 21551 | +} |
---|
| 21552 | + |
---|
| 21553 | +static inline uint32 |
---|
| 21554 | +__dhd_ring_ptr2idx(void *ring, void *ptr, char *sig, uint32 type) |
---|
| 21555 | +{ |
---|
| 21556 | + uint32 diff; |
---|
| 21557 | + uint32 ret_idx = (uint32)DHD_RING_IDX_INVALID; |
---|
| 21558 | + uint32 elem_size, elem_cnt; |
---|
| 21559 | + void *elem; |
---|
| 21560 | + |
---|
| 21561 | + if (type == DHD_RING_TYPE_FIXED) { |
---|
| 21562 | + dhd_fixed_ring_info_t *fixed = (dhd_fixed_ring_info_t *)ring; |
---|
| 21563 | + elem_size = fixed->elem_size; |
---|
| 21564 | + elem_cnt = fixed->elem_cnt; |
---|
| 21565 | + elem = fixed->elem; |
---|
| 21566 | + } else if (type == DHD_RING_TYPE_SINGLE_IDX) { |
---|
| 21567 | + dhd_singleidx_ring_info_t *single = (dhd_singleidx_ring_info_t *)ring; |
---|
| 21568 | + elem_size = single->elem_size; |
---|
| 21569 | + elem_cnt = single->elem_cnt; |
---|
| 21570 | + elem = single->elem; |
---|
| 21571 | + } else { |
---|
| 21572 | + DHD_RING_ERR(("UNSUPPORTED RING TYPE %d\n", type)); |
---|
| 21573 | + return ret_idx; |
---|
| 21574 | + } |
---|
| 21575 | + |
---|
| 21576 | + if (ptr < elem) { |
---|
| 21577 | + DHD_RING_ERR(("INVALID POINTER %s:%p, ring->elem:%p\n", sig, ptr, elem)); |
---|
| 21578 | + return ret_idx; |
---|
| 21579 | + } |
---|
| 21580 | + diff = (uint32)((uint8 *)ptr - (uint8 *)elem); |
---|
| 21581 | + if (diff % elem_size != 0) { |
---|
| 21582 | + DHD_RING_ERR(("INVALID POINTER %s:%p, ring->elem:%p\n", sig, ptr, elem)); |
---|
| 21583 | + return ret_idx; |
---|
| 21584 | + } |
---|
| 21585 | + ret_idx = diff / elem_size; |
---|
| 21586 | + if (ret_idx >= elem_cnt) { |
---|
| 21587 | + DHD_RING_ERR(("INVALID POINTER max:%d cur:%d\n", elem_cnt, ret_idx)); |
---|
| 21588 | + } |
---|
| 21589 | + return ret_idx; |
---|
| 21590 | +} |
---|
| 21591 | + |
---|
| 21592 | +/* Sub functions for fixed ring */ |
---|
| 21593 | +/* get counts between two indexes of ring buffer (internal only) */ |
---|
| 21594 | +static inline int |
---|
| 21595 | +__dhd_fixed_ring_get_count(dhd_fixed_ring_info_t *ring, int start, int end) |
---|
| 21596 | +{ |
---|
| 21597 | + if (start == DHD_RING_IDX_INVALID || end == DHD_RING_IDX_INVALID) { |
---|
| 21598 | + return 0; |
---|
| 21599 | + } |
---|
| 21600 | + |
---|
| 21601 | + return (ring->elem_cnt + end - start) % ring->elem_cnt + 1; |
---|
| 21602 | +} |
---|
| 21603 | + |
---|
| 21604 | +static inline int |
---|
| 21605 | +__dhd_fixed_ring_get_cur_size(dhd_fixed_ring_info_t *ring) |
---|
| 21606 | +{ |
---|
| 21607 | + return __dhd_fixed_ring_get_count(ring, ring->read_idx, ring->write_idx); |
---|
| 21608 | +} |
---|
| 21609 | + |
---|
| 21610 | +static inline void * |
---|
| 21611 | +__dhd_fixed_ring_get_first(dhd_fixed_ring_info_t *ring) |
---|
| 21612 | +{ |
---|
| 21613 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21614 | + return NULL; |
---|
| 21615 | + } |
---|
| 21616 | + return (uint8 *)ring->elem + (ring->elem_size * ring->read_idx); |
---|
| 21617 | +} |
---|
| 21618 | + |
---|
| 21619 | +static inline void |
---|
| 21620 | +__dhd_fixed_ring_free_first(dhd_fixed_ring_info_t *ring) |
---|
| 21621 | +{ |
---|
| 21622 | + uint32 next_idx; |
---|
| 21623 | + |
---|
| 21624 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21625 | + DHD_RING_ERR(("EMPTY RING\n")); |
---|
| 21626 | + return; |
---|
| 21627 | + } |
---|
| 21628 | + |
---|
| 21629 | + next_idx = (ring->read_idx + 1) % ring->elem_cnt; |
---|
| 21630 | + if (ring->read_idx == ring->write_idx) { |
---|
| 21631 | + /* Become empty */ |
---|
| 21632 | + ring->read_idx = ring->write_idx = DHD_RING_IDX_INVALID; |
---|
| 21633 | + return; |
---|
| 21634 | + } |
---|
| 21635 | + |
---|
| 21636 | + ring->read_idx = next_idx; |
---|
| 21637 | + return; |
---|
| 21638 | +} |
---|
| 21639 | + |
---|
| 21640 | +static inline void * |
---|
| 21641 | +__dhd_fixed_ring_get_last(dhd_fixed_ring_info_t *ring) |
---|
| 21642 | +{ |
---|
| 21643 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21644 | + return NULL; |
---|
| 21645 | + } |
---|
| 21646 | + return (uint8 *)ring->elem + (ring->elem_size * ring->write_idx); |
---|
| 21647 | +} |
---|
| 21648 | + |
---|
| 21649 | +static inline void * |
---|
| 21650 | +__dhd_fixed_ring_get_empty(dhd_fixed_ring_info_t *ring) |
---|
| 21651 | +{ |
---|
| 21652 | + uint32 tmp_idx; |
---|
| 21653 | + |
---|
| 21654 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21655 | + ring->read_idx = ring->write_idx = 0; |
---|
| 21656 | + return (uint8 *)ring->elem; |
---|
| 21657 | + } |
---|
| 21658 | + |
---|
| 21659 | + /* check next index is not locked */ |
---|
| 21660 | + tmp_idx = (ring->write_idx + 1) % ring->elem_cnt; |
---|
| 21661 | + if (ring->lock_idx == tmp_idx) { |
---|
| 21662 | + return NULL; |
---|
| 21663 | + } |
---|
| 21664 | + |
---|
| 21665 | + ring->write_idx = tmp_idx; |
---|
| 21666 | + if (ring->write_idx == ring->read_idx) { |
---|
| 21667 | + /* record is full, drop oldest one */ |
---|
| 21668 | + ring->read_idx = (ring->read_idx + 1) % ring->elem_cnt; |
---|
| 21669 | + |
---|
| 21670 | + } |
---|
| 21671 | + return (uint8 *)ring->elem + (ring->elem_size * ring->write_idx); |
---|
| 21672 | +} |
---|
| 21673 | + |
---|
| 21674 | +static inline void * |
---|
| 21675 | +__dhd_fixed_ring_get_next(dhd_fixed_ring_info_t *ring, void *prev, uint32 type) |
---|
| 21676 | +{ |
---|
| 21677 | + uint32 cur_idx; |
---|
| 21678 | + |
---|
| 21679 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21680 | + DHD_RING_ERR(("EMPTY RING\n")); |
---|
| 21681 | + return NULL; |
---|
| 21682 | + } |
---|
| 21683 | + |
---|
| 21684 | + cur_idx = __dhd_ring_ptr2idx(ring, prev, "NEXT", type); |
---|
| 21685 | + if (cur_idx >= ring->elem_cnt) { |
---|
| 21686 | + return NULL; |
---|
| 21687 | + } |
---|
| 21688 | + |
---|
| 21689 | + if (cur_idx == ring->write_idx) { |
---|
| 21690 | + /* no more new record */ |
---|
| 21691 | + return NULL; |
---|
| 21692 | + } |
---|
| 21693 | + |
---|
| 21694 | + cur_idx = (cur_idx + 1) % ring->elem_cnt; |
---|
| 21695 | + return (uint8 *)ring->elem + ring->elem_size * cur_idx; |
---|
| 21696 | +} |
---|
| 21697 | + |
---|
| 21698 | +static inline void * |
---|
| 21699 | +__dhd_fixed_ring_get_prev(dhd_fixed_ring_info_t *ring, void *prev, uint32 type) |
---|
| 21700 | +{ |
---|
| 21701 | + uint32 cur_idx; |
---|
| 21702 | + |
---|
| 21703 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21704 | + DHD_RING_ERR(("EMPTY RING\n")); |
---|
| 21705 | + return NULL; |
---|
| 21706 | + } |
---|
| 21707 | + cur_idx = __dhd_ring_ptr2idx(ring, prev, "PREV", type); |
---|
| 21708 | + if (cur_idx >= ring->elem_cnt) { |
---|
| 21709 | + return NULL; |
---|
| 21710 | + } |
---|
| 21711 | + if (cur_idx == ring->read_idx) { |
---|
| 21712 | + /* no more new record */ |
---|
| 21713 | + return NULL; |
---|
| 21714 | + } |
---|
| 21715 | + |
---|
| 21716 | + cur_idx = (cur_idx + ring->elem_cnt - 1) % ring->elem_cnt; |
---|
| 21717 | + return (uint8 *)ring->elem + ring->elem_size * cur_idx; |
---|
| 21718 | +} |
---|
| 21719 | + |
---|
| 21720 | +static inline void |
---|
| 21721 | +__dhd_fixed_ring_lock(dhd_fixed_ring_info_t *ring, void *first_ptr, void *last_ptr, uint32 type) |
---|
| 21722 | +{ |
---|
| 21723 | + uint32 first_idx; |
---|
| 21724 | + uint32 last_idx; |
---|
| 21725 | + uint32 ring_filled_cnt; |
---|
| 21726 | + uint32 tmp_cnt; |
---|
| 21727 | + |
---|
| 21728 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21729 | + DHD_RING_ERR(("EMPTY RING\n")); |
---|
| 21730 | + return; |
---|
| 21731 | + } |
---|
| 21732 | + |
---|
| 21733 | + if (first_ptr) { |
---|
| 21734 | + first_idx = __dhd_ring_ptr2idx(ring, first_ptr, "LCK FIRST", type); |
---|
| 21735 | + if (first_idx >= ring->elem_cnt) { |
---|
| 21736 | + return; |
---|
| 21737 | + } |
---|
| 21738 | + } else { |
---|
| 21739 | + first_idx = ring->read_idx; |
---|
| 21740 | + } |
---|
| 21741 | + |
---|
| 21742 | + if (last_ptr) { |
---|
| 21743 | + last_idx = __dhd_ring_ptr2idx(ring, last_ptr, "LCK LAST", type); |
---|
| 21744 | + if (last_idx >= ring->elem_cnt) { |
---|
| 21745 | + return; |
---|
| 21746 | + } |
---|
| 21747 | + } else { |
---|
| 21748 | + last_idx = ring->write_idx; |
---|
| 21749 | + } |
---|
| 21750 | + |
---|
| 21751 | + ring_filled_cnt = __dhd_fixed_ring_get_count(ring, ring->read_idx, ring->write_idx); |
---|
| 21752 | + tmp_cnt = __dhd_fixed_ring_get_count(ring, ring->read_idx, first_idx); |
---|
| 21753 | + if (tmp_cnt > ring_filled_cnt) { |
---|
| 21754 | + DHD_RING_ERR(("LOCK FIRST IS TO EMPTY ELEM: write: %d read: %d cur:%d\n", |
---|
| 21755 | + ring->write_idx, ring->read_idx, first_idx)); |
---|
| 21756 | + return; |
---|
| 21757 | + } |
---|
| 21758 | + |
---|
| 21759 | + tmp_cnt = __dhd_fixed_ring_get_count(ring, ring->read_idx, last_idx); |
---|
| 21760 | + if (tmp_cnt > ring_filled_cnt) { |
---|
| 21761 | + DHD_RING_ERR(("LOCK LAST IS TO EMPTY ELEM: write: %d read: %d cur:%d\n", |
---|
| 21762 | + ring->write_idx, ring->read_idx, last_idx)); |
---|
| 21763 | + return; |
---|
| 21764 | + } |
---|
| 21765 | + |
---|
| 21766 | + ring->lock_idx = first_idx; |
---|
| 21767 | + ring->lock_count = __dhd_fixed_ring_get_count(ring, first_idx, last_idx); |
---|
| 21768 | + return; |
---|
| 21769 | +} |
---|
| 21770 | + |
---|
| 21771 | +static inline void |
---|
| 21772 | +__dhd_fixed_ring_lock_free(dhd_fixed_ring_info_t *ring) |
---|
| 21773 | +{ |
---|
| 21774 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21775 | + DHD_RING_ERR(("EMPTY RING\n")); |
---|
| 21776 | + return; |
---|
| 21777 | + } |
---|
| 21778 | + |
---|
| 21779 | + ring->lock_idx = DHD_RING_IDX_INVALID; |
---|
| 21780 | + ring->lock_count = 0; |
---|
| 21781 | + return; |
---|
| 21782 | +} |
---|
| 21783 | +static inline void * |
---|
| 21784 | +__dhd_fixed_ring_lock_get_first(dhd_fixed_ring_info_t *ring) |
---|
| 21785 | +{ |
---|
| 21786 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21787 | + DHD_RING_ERR(("EMPTY RING\n")); |
---|
| 21788 | + return NULL; |
---|
| 21789 | + } |
---|
| 21790 | + if (ring->lock_idx == DHD_RING_IDX_INVALID) { |
---|
| 21791 | + DHD_RING_ERR(("NO LOCK POINT\n")); |
---|
| 21792 | + return NULL; |
---|
| 21793 | + } |
---|
| 21794 | + return (uint8 *)ring->elem + ring->elem_size * ring->lock_idx; |
---|
| 21795 | +} |
---|
| 21796 | + |
---|
| 21797 | +static inline void * |
---|
| 21798 | +__dhd_fixed_ring_lock_get_last(dhd_fixed_ring_info_t *ring) |
---|
| 21799 | +{ |
---|
| 21800 | + int lock_last_idx; |
---|
| 21801 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21802 | + DHD_RING_ERR(("EMPTY RING\n")); |
---|
| 21803 | + return NULL; |
---|
| 21804 | + } |
---|
| 21805 | + if (ring->lock_idx == DHD_RING_IDX_INVALID) { |
---|
| 21806 | + DHD_RING_ERR(("NO LOCK POINT\n")); |
---|
| 21807 | + return NULL; |
---|
| 21808 | + } |
---|
| 21809 | + |
---|
| 21810 | + lock_last_idx = (ring->lock_idx + ring->lock_count - 1) % ring->elem_cnt; |
---|
| 21811 | + return (uint8 *)ring->elem + ring->elem_size * lock_last_idx; |
---|
| 21812 | +} |
---|
| 21813 | + |
---|
| 21814 | +static inline int |
---|
| 21815 | +__dhd_fixed_ring_lock_get_count(dhd_fixed_ring_info_t *ring) |
---|
| 21816 | +{ |
---|
| 21817 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21818 | + DHD_RING_ERR(("EMPTY RING\n")); |
---|
| 21819 | + return BCME_ERROR; |
---|
| 21820 | + } |
---|
| 21821 | + if (ring->lock_idx == DHD_RING_IDX_INVALID) { |
---|
| 21822 | + DHD_RING_ERR(("NO LOCK POINT\n")); |
---|
| 21823 | + return BCME_ERROR; |
---|
| 21824 | + } |
---|
| 21825 | + return ring->lock_count; |
---|
| 21826 | +} |
---|
| 21827 | + |
---|
| 21828 | +static inline void |
---|
| 21829 | +__dhd_fixed_ring_lock_free_first(dhd_fixed_ring_info_t *ring) |
---|
| 21830 | +{ |
---|
| 21831 | + if (ring->read_idx == DHD_RING_IDX_INVALID) { |
---|
| 21832 | + DHD_RING_ERR(("EMPTY RING\n")); |
---|
| 21833 | + return; |
---|
| 21834 | + } |
---|
| 21835 | + if (ring->lock_idx == DHD_RING_IDX_INVALID) { |
---|
| 21836 | + DHD_RING_ERR(("NO LOCK POINT\n")); |
---|
| 21837 | + return; |
---|
| 21838 | + } |
---|
| 21839 | + |
---|
| 21840 | + ring->lock_count--; |
---|
| 21841 | + if (ring->lock_count <= 0) { |
---|
| 21842 | + ring->lock_idx = DHD_RING_IDX_INVALID; |
---|
| 21843 | + } else { |
---|
| 21844 | + ring->lock_idx = (ring->lock_idx + 1) % ring->elem_cnt; |
---|
| 21845 | + } |
---|
| 21846 | + return; |
---|
| 21847 | +} |
---|
| 21848 | + |
---|
| 21849 | +static inline void |
---|
| 21850 | +__dhd_fixed_ring_set_read_idx(dhd_fixed_ring_info_t *ring, uint32 idx) |
---|
| 21851 | +{ |
---|
| 21852 | + ring->read_idx = idx; |
---|
| 21853 | +} |
---|
| 21854 | + |
---|
| 21855 | +static inline void |
---|
| 21856 | +__dhd_fixed_ring_set_write_idx(dhd_fixed_ring_info_t *ring, uint32 idx) |
---|
| 21857 | +{ |
---|
| 21858 | + ring->write_idx = idx; |
---|
| 21859 | +} |
---|
| 21860 | + |
---|
| 21861 | +static inline uint32 |
---|
| 21862 | +__dhd_fixed_ring_get_read_idx(dhd_fixed_ring_info_t *ring) |
---|
| 21863 | +{ |
---|
| 21864 | + return ring->read_idx; |
---|
| 21865 | +} |
---|
| 21866 | + |
---|
| 21867 | +static inline uint32 |
---|
| 21868 | +__dhd_fixed_ring_get_write_idx(dhd_fixed_ring_info_t *ring) |
---|
| 21869 | +{ |
---|
| 21870 | + return ring->write_idx; |
---|
| 21871 | +} |
---|
| 21872 | + |
---|
| 21873 | +/* Sub functions for single index ring */ |
---|
| 21874 | +static inline void * |
---|
| 21875 | +__dhd_singleidx_ring_get_first(dhd_singleidx_ring_info_t *ring) |
---|
| 21876 | +{ |
---|
| 21877 | + uint32 tmp_idx = 0; |
---|
| 21878 | + |
---|
| 21879 | + if (ring->idx == DHD_RING_IDX_INVALID) { |
---|
| 21880 | + return NULL; |
---|
| 21881 | + } |
---|
| 21882 | + |
---|
| 21883 | + if (ring->ring_overwrited) { |
---|
| 21884 | + tmp_idx = (ring->idx + 1) % ring->elem_cnt; |
---|
| 21885 | + } |
---|
| 21886 | + |
---|
| 21887 | + return (uint8 *)ring->elem + (ring->elem_size * tmp_idx); |
---|
| 21888 | +} |
---|
| 21889 | + |
---|
| 21890 | +static inline void * |
---|
| 21891 | +__dhd_singleidx_ring_get_last(dhd_singleidx_ring_info_t *ring) |
---|
| 21892 | +{ |
---|
| 21893 | + if (ring->idx == DHD_RING_IDX_INVALID) { |
---|
| 21894 | + return NULL; |
---|
| 21895 | + } |
---|
| 21896 | + |
---|
| 21897 | + return (uint8 *)ring->elem + (ring->elem_size * ring->idx); |
---|
| 21898 | +} |
---|
| 21899 | + |
---|
| 21900 | +static inline void * |
---|
| 21901 | +__dhd_singleidx_ring_get_empty(dhd_singleidx_ring_info_t *ring) |
---|
| 21902 | +{ |
---|
| 21903 | + if (ring->idx == DHD_RING_IDX_INVALID) { |
---|
| 21904 | + ring->idx = 0; |
---|
| 21905 | + return (uint8 *)ring->elem; |
---|
| 21906 | + } |
---|
| 21907 | + |
---|
| 21908 | + /* check the lock is held */ |
---|
| 21909 | + if (atomic_read(&ring->ring_locked)) { |
---|
| 21910 | + return NULL; |
---|
| 21911 | + } |
---|
| 21912 | + |
---|
| 21913 | + /* check the index rollover */ |
---|
| 21914 | + if (!ring->ring_overwrited && ring->idx == (ring->elem_cnt - 1)) { |
---|
| 21915 | + ring->ring_overwrited = 1; |
---|
| 21916 | + } |
---|
| 21917 | + |
---|
| 21918 | + ring->idx = (ring->idx + 1) % ring->elem_cnt; |
---|
| 21919 | + |
---|
| 21920 | + return (uint8 *)ring->elem + (ring->elem_size * ring->idx); |
---|
| 21921 | +} |
---|
| 21922 | + |
---|
| 21923 | +static inline void * |
---|
| 21924 | +__dhd_singleidx_ring_get_next(dhd_singleidx_ring_info_t *ring, void *prev, uint32 type) |
---|
| 21925 | +{ |
---|
| 21926 | + uint32 cur_idx; |
---|
| 21927 | + |
---|
| 21928 | + if (ring->idx == DHD_RING_IDX_INVALID) { |
---|
| 21929 | + DHD_RING_ERR(("EMPTY RING\n")); |
---|
| 21930 | + return NULL; |
---|
| 21931 | + } |
---|
| 21932 | + |
---|
| 21933 | + cur_idx = __dhd_ring_ptr2idx(ring, prev, "NEXT", type); |
---|
| 21934 | + if (cur_idx >= ring->elem_cnt) { |
---|
| 21935 | + return NULL; |
---|
| 21936 | + } |
---|
| 21937 | + |
---|
| 21938 | + if (cur_idx == ring->idx) { |
---|
| 21939 | + /* no more new record */ |
---|
| 21940 | + return NULL; |
---|
| 21941 | + } |
---|
| 21942 | + |
---|
| 21943 | + cur_idx = (cur_idx + 1) % ring->elem_cnt; |
---|
| 21944 | + |
---|
| 21945 | + return (uint8 *)ring->elem + ring->elem_size * cur_idx; |
---|
| 21946 | +} |
---|
| 21947 | + |
---|
| 21948 | +static inline void * |
---|
| 21949 | +__dhd_singleidx_ring_get_prev(dhd_singleidx_ring_info_t *ring, void *prev, uint32 type) |
---|
| 21950 | +{ |
---|
| 21951 | + uint32 cur_idx; |
---|
| 21952 | + |
---|
| 21953 | + if (ring->idx == DHD_RING_IDX_INVALID) { |
---|
| 21954 | + DHD_RING_ERR(("EMPTY RING\n")); |
---|
| 21955 | + return NULL; |
---|
| 21956 | + } |
---|
| 21957 | + cur_idx = __dhd_ring_ptr2idx(ring, prev, "PREV", type); |
---|
| 21958 | + if (cur_idx >= ring->elem_cnt) { |
---|
| 21959 | + return NULL; |
---|
| 21960 | + } |
---|
| 21961 | + |
---|
| 21962 | + if (!ring->ring_overwrited && cur_idx == 0) { |
---|
| 21963 | + /* no more new record */ |
---|
| 21964 | + return NULL; |
---|
| 21965 | + } |
---|
| 21966 | + |
---|
| 21967 | + cur_idx = (cur_idx + ring->elem_cnt - 1) % ring->elem_cnt; |
---|
| 21968 | + if (ring->ring_overwrited && cur_idx == ring->idx) { |
---|
| 21969 | + /* no more new record */ |
---|
| 21970 | + return NULL; |
---|
| 21971 | + } |
---|
| 21972 | + |
---|
| 21973 | + return (uint8 *)ring->elem + ring->elem_size * cur_idx; |
---|
| 21974 | +} |
---|
| 21975 | + |
---|
| 21976 | +static inline void |
---|
| 21977 | +__dhd_singleidx_ring_whole_lock(dhd_singleidx_ring_info_t *ring) |
---|
| 21978 | +{ |
---|
| 21979 | + if (!atomic_read(&ring->ring_locked)) { |
---|
| 21980 | + atomic_set(&ring->ring_locked, 1); |
---|
| 21981 | + } |
---|
| 21982 | +} |
---|
| 21983 | + |
---|
| 21984 | +static inline void |
---|
| 21985 | +__dhd_singleidx_ring_whole_unlock(dhd_singleidx_ring_info_t *ring) |
---|
| 21986 | +{ |
---|
| 21987 | + if (atomic_read(&ring->ring_locked)) { |
---|
| 21988 | + atomic_set(&ring->ring_locked, 0); |
---|
| 21989 | + } |
---|
| 21990 | +} |
---|
| 21991 | + |
---|
| 21992 | +/* Get first element : oldest element */ |
---|
| 21993 | +void * |
---|
| 21994 | +dhd_ring_get_first(void *_ring) |
---|
| 21995 | +{ |
---|
| 21996 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 21997 | + void *ret = NULL; |
---|
| 21998 | + unsigned long flags; |
---|
| 21999 | + |
---|
| 22000 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22001 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22002 | + return NULL; |
---|
| 22003 | + } |
---|
| 22004 | + |
---|
| 22005 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22006 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22007 | + ret = __dhd_fixed_ring_get_first(&ring->fixed); |
---|
| 22008 | + } |
---|
| 22009 | + if (ring->type == DHD_RING_TYPE_SINGLE_IDX) { |
---|
| 22010 | + ret = __dhd_singleidx_ring_get_first(&ring->single); |
---|
| 22011 | + } |
---|
| 22012 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22013 | + return ret; |
---|
| 22014 | +} |
---|
| 22015 | + |
---|
| 22016 | +/* Free first element : oldest element */ |
---|
| 22017 | +void |
---|
| 22018 | +dhd_ring_free_first(void *_ring) |
---|
| 22019 | +{ |
---|
| 22020 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22021 | + unsigned long flags; |
---|
| 22022 | + |
---|
| 22023 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22024 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22025 | + return; |
---|
| 22026 | + } |
---|
| 22027 | + |
---|
| 22028 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22029 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22030 | + __dhd_fixed_ring_free_first(&ring->fixed); |
---|
| 22031 | + } |
---|
| 22032 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22033 | +} |
---|
| 22034 | + |
---|
| 22035 | +void |
---|
| 22036 | +dhd_ring_set_read_idx(void *_ring, uint32 read_idx) |
---|
| 22037 | +{ |
---|
| 22038 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22039 | + unsigned long flags; |
---|
| 22040 | + |
---|
| 22041 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22042 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22043 | + return; |
---|
| 22044 | + } |
---|
| 22045 | + |
---|
| 22046 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22047 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22048 | + __dhd_fixed_ring_set_read_idx(&ring->fixed, read_idx); |
---|
| 22049 | + } |
---|
| 22050 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22051 | +} |
---|
| 22052 | + |
---|
| 22053 | +void |
---|
| 22054 | +dhd_ring_set_write_idx(void *_ring, uint32 write_idx) |
---|
| 22055 | +{ |
---|
| 22056 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22057 | + unsigned long flags; |
---|
| 22058 | + |
---|
| 22059 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22060 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22061 | + return; |
---|
| 22062 | + } |
---|
| 22063 | + |
---|
| 22064 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22065 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22066 | + __dhd_fixed_ring_set_write_idx(&ring->fixed, write_idx); |
---|
| 22067 | + } |
---|
| 22068 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22069 | +} |
---|
| 22070 | + |
---|
| 22071 | +uint32 |
---|
| 22072 | +dhd_ring_get_read_idx(void *_ring) |
---|
| 22073 | +{ |
---|
| 22074 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22075 | + uint32 read_idx = DHD_RING_IDX_INVALID; |
---|
| 22076 | + unsigned long flags; |
---|
| 22077 | + |
---|
| 22078 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22079 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22080 | + return read_idx; |
---|
| 22081 | + } |
---|
| 22082 | + |
---|
| 22083 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22084 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22085 | + read_idx = __dhd_fixed_ring_get_read_idx(&ring->fixed); |
---|
| 22086 | + } |
---|
| 22087 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22088 | + |
---|
| 22089 | + return read_idx; |
---|
| 22090 | +} |
---|
| 22091 | + |
---|
| 22092 | +uint32 |
---|
| 22093 | +dhd_ring_get_write_idx(void *_ring) |
---|
| 22094 | +{ |
---|
| 22095 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22096 | + uint32 write_idx = DHD_RING_IDX_INVALID; |
---|
| 22097 | + unsigned long flags; |
---|
| 22098 | + |
---|
| 22099 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22100 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22101 | + return write_idx; |
---|
| 22102 | + } |
---|
| 22103 | + |
---|
| 22104 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22105 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22106 | + write_idx = __dhd_fixed_ring_get_write_idx(&ring->fixed); |
---|
| 22107 | + } |
---|
| 22108 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22109 | + |
---|
| 22110 | + return write_idx; |
---|
| 22111 | +} |
---|
| 22112 | + |
---|
| 22113 | +/* Get latest element */ |
---|
| 22114 | +void * |
---|
| 22115 | +dhd_ring_get_last(void *_ring) |
---|
| 22116 | +{ |
---|
| 22117 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22118 | + void *ret = NULL; |
---|
| 22119 | + unsigned long flags; |
---|
| 22120 | + |
---|
| 22121 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22122 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22123 | + return NULL; |
---|
| 22124 | + } |
---|
| 22125 | + |
---|
| 22126 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22127 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22128 | + ret = __dhd_fixed_ring_get_last(&ring->fixed); |
---|
| 22129 | + } |
---|
| 22130 | + if (ring->type == DHD_RING_TYPE_SINGLE_IDX) { |
---|
| 22131 | + ret = __dhd_singleidx_ring_get_last(&ring->single); |
---|
| 22132 | + } |
---|
| 22133 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22134 | + return ret; |
---|
| 22135 | +} |
---|
| 22136 | + |
---|
| 22137 | +/* Get next point can be written |
---|
| 22138 | + * will overwrite which doesn't read |
---|
| 22139 | + * will return NULL if next pointer is locked |
---|
| 22140 | + */ |
---|
| 22141 | +void * |
---|
| 22142 | +dhd_ring_get_empty(void *_ring) |
---|
| 22143 | +{ |
---|
| 22144 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22145 | + void *ret = NULL; |
---|
| 22146 | + unsigned long flags; |
---|
| 22147 | + |
---|
| 22148 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22149 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22150 | + return NULL; |
---|
| 22151 | + } |
---|
| 22152 | + |
---|
| 22153 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22154 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22155 | + ret = __dhd_fixed_ring_get_empty(&ring->fixed); |
---|
| 22156 | + } |
---|
| 22157 | + if (ring->type == DHD_RING_TYPE_SINGLE_IDX) { |
---|
| 22158 | + ret = __dhd_singleidx_ring_get_empty(&ring->single); |
---|
| 22159 | + } |
---|
| 22160 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22161 | + return ret; |
---|
| 22162 | +} |
---|
| 22163 | + |
---|
| 22164 | +void * |
---|
| 22165 | +dhd_ring_get_next(void *_ring, void *cur) |
---|
| 22166 | +{ |
---|
| 22167 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22168 | + void *ret = NULL; |
---|
| 22169 | + unsigned long flags; |
---|
| 22170 | + |
---|
| 22171 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22172 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22173 | + return NULL; |
---|
| 22174 | + } |
---|
| 22175 | + |
---|
| 22176 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22177 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22178 | + ret = __dhd_fixed_ring_get_next(&ring->fixed, cur, ring->type); |
---|
| 22179 | + } |
---|
| 22180 | + if (ring->type == DHD_RING_TYPE_SINGLE_IDX) { |
---|
| 22181 | + ret = __dhd_singleidx_ring_get_next(&ring->single, cur, ring->type); |
---|
| 22182 | + } |
---|
| 22183 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22184 | + return ret; |
---|
| 22185 | +} |
---|
| 22186 | + |
---|
| 22187 | +void * |
---|
| 22188 | +dhd_ring_get_prev(void *_ring, void *cur) |
---|
| 22189 | +{ |
---|
| 22190 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22191 | + void *ret = NULL; |
---|
| 22192 | + unsigned long flags; |
---|
| 22193 | + |
---|
| 22194 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22195 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22196 | + return NULL; |
---|
| 22197 | + } |
---|
| 22198 | + |
---|
| 22199 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22200 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22201 | + ret = __dhd_fixed_ring_get_prev(&ring->fixed, cur, ring->type); |
---|
| 22202 | + } |
---|
| 22203 | + if (ring->type == DHD_RING_TYPE_SINGLE_IDX) { |
---|
| 22204 | + ret = __dhd_singleidx_ring_get_prev(&ring->single, cur, ring->type); |
---|
| 22205 | + } |
---|
| 22206 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22207 | + return ret; |
---|
| 22208 | +} |
---|
| 22209 | + |
---|
| 22210 | +int |
---|
| 22211 | +dhd_ring_get_cur_size(void *_ring) |
---|
| 22212 | +{ |
---|
| 22213 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22214 | + int cnt = 0; |
---|
| 22215 | + unsigned long flags; |
---|
| 22216 | + |
---|
| 22217 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22218 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22219 | + return cnt; |
---|
| 22220 | + } |
---|
| 22221 | + |
---|
| 22222 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22223 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22224 | + cnt = __dhd_fixed_ring_get_cur_size(&ring->fixed); |
---|
| 22225 | + } |
---|
| 22226 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22227 | + return cnt; |
---|
| 22228 | +} |
---|
| 22229 | + |
---|
| 22230 | +/* protect element between lock_ptr and write_idx */ |
---|
| 22231 | +void |
---|
| 22232 | +dhd_ring_lock(void *_ring, void *first_ptr, void *last_ptr) |
---|
| 22233 | +{ |
---|
| 22234 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22235 | + unsigned long flags; |
---|
| 22236 | + |
---|
| 22237 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22238 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22239 | + return; |
---|
| 22240 | + } |
---|
| 22241 | + |
---|
| 22242 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22243 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22244 | + __dhd_fixed_ring_lock(&ring->fixed, first_ptr, last_ptr, ring->type); |
---|
| 22245 | + } |
---|
| 22246 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22247 | +} |
---|
| 22248 | + |
---|
| 22249 | +/* free all lock */ |
---|
| 22250 | +void |
---|
| 22251 | +dhd_ring_lock_free(void *_ring) |
---|
| 22252 | +{ |
---|
| 22253 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22254 | + unsigned long flags; |
---|
| 22255 | + |
---|
| 22256 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22257 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22258 | + return; |
---|
| 22259 | + } |
---|
| 22260 | + |
---|
| 22261 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22262 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22263 | + __dhd_fixed_ring_lock_free(&ring->fixed); |
---|
| 22264 | + } |
---|
| 22265 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22266 | +} |
---|
| 22267 | + |
---|
| 22268 | +void * |
---|
| 22269 | +dhd_ring_lock_get_first(void *_ring) |
---|
| 22270 | +{ |
---|
| 22271 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22272 | + void *ret = NULL; |
---|
| 22273 | + unsigned long flags; |
---|
| 22274 | + |
---|
| 22275 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22276 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22277 | + return NULL; |
---|
| 22278 | + } |
---|
| 22279 | + |
---|
| 22280 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22281 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22282 | + ret = __dhd_fixed_ring_lock_get_first(&ring->fixed); |
---|
| 22283 | + } |
---|
| 22284 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22285 | + return ret; |
---|
| 22286 | +} |
---|
| 22287 | + |
---|
| 22288 | +void * |
---|
| 22289 | +dhd_ring_lock_get_last(void *_ring) |
---|
| 22290 | +{ |
---|
| 22291 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22292 | + void *ret = NULL; |
---|
| 22293 | + unsigned long flags; |
---|
| 22294 | + |
---|
| 22295 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22296 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22297 | + return NULL; |
---|
| 22298 | + } |
---|
| 22299 | + |
---|
| 22300 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22301 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22302 | + ret = __dhd_fixed_ring_lock_get_last(&ring->fixed); |
---|
| 22303 | + } |
---|
| 22304 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22305 | + return ret; |
---|
| 22306 | +} |
---|
| 22307 | + |
---|
| 22308 | +int |
---|
| 22309 | +dhd_ring_lock_get_count(void *_ring) |
---|
| 22310 | +{ |
---|
| 22311 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22312 | + int ret = BCME_ERROR; |
---|
| 22313 | + unsigned long flags; |
---|
| 22314 | + |
---|
| 22315 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22316 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22317 | + return ret; |
---|
| 22318 | + } |
---|
| 22319 | + |
---|
| 22320 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22321 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22322 | + ret = __dhd_fixed_ring_lock_get_count(&ring->fixed); |
---|
| 22323 | + } |
---|
| 22324 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22325 | + return ret; |
---|
| 22326 | +} |
---|
| 22327 | + |
---|
| 22328 | +/* free first locked element */ |
---|
| 22329 | +void |
---|
| 22330 | +dhd_ring_lock_free_first(void *_ring) |
---|
| 22331 | +{ |
---|
| 22332 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22333 | + unsigned long flags; |
---|
| 22334 | + |
---|
| 22335 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22336 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22337 | + return; |
---|
| 22338 | + } |
---|
| 22339 | + |
---|
| 22340 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22341 | + if (ring->type == DHD_RING_TYPE_FIXED) { |
---|
| 22342 | + __dhd_fixed_ring_lock_free_first(&ring->fixed); |
---|
| 22343 | + } |
---|
| 22344 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22345 | +} |
---|
| 22346 | + |
---|
| 22347 | +void |
---|
| 22348 | +dhd_ring_whole_lock(void *_ring) |
---|
| 22349 | +{ |
---|
| 22350 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22351 | + unsigned long flags; |
---|
| 22352 | + |
---|
| 22353 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22354 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22355 | + return; |
---|
| 22356 | + } |
---|
| 22357 | + |
---|
| 22358 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22359 | + if (ring->type == DHD_RING_TYPE_SINGLE_IDX) { |
---|
| 22360 | + __dhd_singleidx_ring_whole_lock(&ring->single); |
---|
| 22361 | + } |
---|
| 22362 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22363 | +} |
---|
| 22364 | + |
---|
| 22365 | +void |
---|
| 22366 | +dhd_ring_whole_unlock(void *_ring) |
---|
| 22367 | +{ |
---|
| 22368 | + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; |
---|
| 22369 | + unsigned long flags; |
---|
| 22370 | + |
---|
| 22371 | + if (!ring || ring->magic != DHD_RING_MAGIC) { |
---|
| 22372 | + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); |
---|
| 22373 | + return; |
---|
| 22374 | + } |
---|
| 22375 | + |
---|
| 22376 | + DHD_RING_SYNC_LOCK(ring->ring_sync, flags); |
---|
| 22377 | + if (ring->type == DHD_RING_TYPE_SINGLE_IDX) { |
---|
| 22378 | + __dhd_singleidx_ring_whole_unlock(&ring->single); |
---|
| 22379 | + } |
---|
| 22380 | + DHD_RING_SYNC_UNLOCK(ring->ring_sync, flags); |
---|
| 22381 | +} |
---|
| 22382 | + |
---|
| 22383 | +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)) |
---|
| 22384 | +#define DHD_VFS_INODE(dir) (dir->d_inode) |
---|
| 22385 | +#else |
---|
| 22386 | +#define DHD_VFS_INODE(dir) d_inode(dir) |
---|
| 22387 | +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) */ |
---|
| 22388 | + |
---|
| 22389 | +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) |
---|
| 22390 | +#define DHD_VFS_UNLINK(dir, b, c) vfs_unlink(DHD_VFS_INODE(dir), b) |
---|
| 22391 | +#else |
---|
| 22392 | +#define DHD_VFS_UNLINK(dir, b, c) vfs_unlink(DHD_VFS_INODE(dir), b, c) |
---|
| 22393 | +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */ |
---|
| 22394 | +int |
---|
| 22395 | +dhd_file_delete(char *path) |
---|
| 22396 | +{ |
---|
| 22397 | + struct path file_path; |
---|
| 22398 | + int err; |
---|
| 22399 | + struct dentry *dir; |
---|
| 22400 | + |
---|
| 22401 | + err = kern_path(path, 0, &file_path); |
---|
| 22402 | + |
---|
| 22403 | + if (err < 0) { |
---|
| 22404 | + DHD_ERROR(("Failed to get kern-path delete file: %s error: %d\n", path, err)); |
---|
| 22405 | + return err; |
---|
| 22406 | + } |
---|
| 22407 | + if ( |
---|
| 22408 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) |
---|
| 22409 | + !d_is_file(file_path.dentry) || |
---|
| 22410 | +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 1, 0)) |
---|
| 22411 | + d_really_is_negative(file_path.dentry) || |
---|
| 22412 | +#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(4, 1, 0) */ |
---|
| 22413 | +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) */ |
---|
| 22414 | + FALSE) |
---|
| 22415 | + { |
---|
| 22416 | + err = -EINVAL; |
---|
| 22417 | + } else { |
---|
| 22418 | + dir = dget_parent(file_path.dentry); |
---|
| 22419 | + |
---|
| 22420 | + if (!IS_ERR(dir)) { |
---|
| 22421 | + err = DHD_VFS_UNLINK(dir, file_path.dentry, NULL); |
---|
| 22422 | + dput(dir); |
---|
| 22423 | + } else { |
---|
| 22424 | + err = PTR_ERR(dir); |
---|
| 22425 | + } |
---|
| 22426 | + } |
---|
| 22427 | + |
---|
| 22428 | + path_put(&file_path); |
---|
| 22429 | + |
---|
| 22430 | + if (err < 0) { |
---|
| 22431 | + DHD_ERROR(("Failed to delete file: %s error: %d\n", path, err)); |
---|
| 22432 | + } |
---|
| 22433 | + |
---|
| 22434 | + return err; |
---|
| 22435 | +} |
---|
| 22436 | +#ifdef DHD_DUMP_MNGR |
---|
| 22437 | +static int |
---|
| 22438 | +dhd_dump_file_manage_idx(dhd_dump_file_manage_t *fm_ptr, char *fname) |
---|
| 22439 | +{ |
---|
| 22440 | + int i; |
---|
| 22441 | + int fm_idx = -1; |
---|
| 22442 | + |
---|
| 22443 | + for (i = 0; i < DHD_DUMP_TYPE_COUNT_MAX; i++) { |
---|
| 22444 | + if (strlen(fm_ptr->elems[i].type_name) == 0) { |
---|
| 22445 | + fm_idx = i; |
---|
| 22446 | + break; |
---|
| 22447 | + } |
---|
| 22448 | + if (!(strncmp(fname, fm_ptr->elems[i].type_name, strlen(fname)))) { |
---|
| 22449 | + fm_idx = i; |
---|
| 22450 | + break; |
---|
| 22451 | + } |
---|
| 22452 | + } |
---|
| 22453 | + |
---|
| 22454 | + if (fm_idx == -1) { |
---|
| 22455 | + return fm_idx; |
---|
| 22456 | + } |
---|
| 22457 | + |
---|
| 22458 | + if (strlen(fm_ptr->elems[fm_idx].type_name) == 0) { |
---|
| 22459 | + strncpy(fm_ptr->elems[fm_idx].type_name, fname, DHD_DUMP_TYPE_NAME_SIZE); |
---|
| 22460 | + fm_ptr->elems[fm_idx].type_name[DHD_DUMP_TYPE_NAME_SIZE - 1] = '\0'; |
---|
| 22461 | + fm_ptr->elems[fm_idx].file_idx = 0; |
---|
| 22462 | + } |
---|
| 22463 | + |
---|
| 22464 | + return fm_idx; |
---|
| 22465 | +} |
---|
| 22466 | + |
---|
| 22467 | +/* |
---|
| 22468 | + * dhd_dump_file_manage_enqueue - enqueue dump file path |
---|
| 22469 | + * and delete odest file if file count is max. |
---|
| 22470 | +*/ |
---|
| 22471 | +void |
---|
| 22472 | +dhd_dump_file_manage_enqueue(dhd_pub_t *dhd, char *dump_path, char *fname) |
---|
| 22473 | +{ |
---|
| 22474 | + int fm_idx; |
---|
| 22475 | + int fp_idx; |
---|
| 22476 | + dhd_dump_file_manage_t *fm_ptr; |
---|
| 22477 | + DFM_elem_t *elem; |
---|
| 22478 | + |
---|
| 22479 | + if (!dhd || !dhd->dump_file_manage) { |
---|
| 22480 | + DHD_ERROR(("%s(): dhdp=%p dump_file_manage=%p\n", |
---|
| 22481 | + __FUNCTION__, dhd, (dhd ? dhd->dump_file_manage : NULL))); |
---|
| 22482 | + return; |
---|
| 22483 | + } |
---|
| 22484 | + |
---|
| 22485 | + fm_ptr = dhd->dump_file_manage; |
---|
| 22486 | + |
---|
| 22487 | + /* find file_manage idx */ |
---|
| 22488 | + DHD_INFO(("%s(): fname: %s dump_path: %s\n", __FUNCTION__, fname, dump_path)); |
---|
| 22489 | + if ((fm_idx = dhd_dump_file_manage_idx(fm_ptr, fname)) < 0) { |
---|
| 22490 | + DHD_ERROR(("%s(): Out of file manager entries, fname: %s\n", |
---|
| 22491 | + __FUNCTION__, fname)); |
---|
| 22492 | + return; |
---|
| 22493 | + } |
---|
| 22494 | + |
---|
| 22495 | + elem = &fm_ptr->elems[fm_idx]; |
---|
| 22496 | + fp_idx = elem->file_idx; |
---|
| 22497 | + DHD_INFO(("%s(): fm_idx: %d fp_idx: %d path: %s\n", |
---|
| 22498 | + __FUNCTION__, fm_idx, fp_idx, elem->file_path[fp_idx])); |
---|
| 22499 | + |
---|
| 22500 | + /* delete oldest file */ |
---|
| 22501 | + if (strlen(elem->file_path[fp_idx]) != 0) { |
---|
| 22502 | + if (dhd_file_delete(elem->file_path[fp_idx]) < 0) { |
---|
| 22503 | + DHD_ERROR(("%s(): Failed to delete file: %s\n", |
---|
| 22504 | + __FUNCTION__, elem->file_path[fp_idx])); |
---|
| 22505 | + } else { |
---|
| 22506 | + DHD_ERROR(("%s(): Successed to delete file: %s\n", |
---|
| 22507 | + __FUNCTION__, elem->file_path[fp_idx])); |
---|
| 22508 | + } |
---|
| 22509 | + } |
---|
| 22510 | + |
---|
| 22511 | + /* save dump file path */ |
---|
| 22512 | + strncpy(elem->file_path[fp_idx], dump_path, DHD_DUMP_FILE_PATH_SIZE); |
---|
| 22513 | + elem->file_path[fp_idx][DHD_DUMP_FILE_PATH_SIZE - 1] = '\0'; |
---|
| 22514 | + |
---|
| 22515 | + /* change file index to next file index */ |
---|
| 22516 | + elem->file_idx = (elem->file_idx + 1) % DHD_DUMP_FILE_COUNT_MAX; |
---|
| 22517 | +} |
---|
| 22518 | +#endif /* DHD_DUMP_MNGR */ |
---|
| 22519 | + |
---|
| 22520 | +#ifdef DHD_MAP_LOGGING |
---|
| 22521 | +/* Will be called from SMMU fault handler */ |
---|
| 22522 | +void |
---|
| 22523 | +dhd_smmu_fault_handler(uint32 axid, ulong fault_addr) |
---|
| 22524 | +{ |
---|
| 22525 | + dhd_pub_t *dhdp = (dhd_pub_t *)g_dhd_pub; |
---|
| 22526 | + uint32 irq = (uint32)-1; |
---|
| 22527 | + |
---|
| 22528 | + DHD_ERROR(("%s: Trigger SMMU Fault\n", __FUNCTION__)); |
---|
| 22529 | + DHD_ERROR(("%s: axid:0x%x, fault_addr:0x%lx", __FUNCTION__, axid, fault_addr)); |
---|
| 22530 | + dhdp->smmu_fault_occurred = TRUE; |
---|
| 22531 | +#ifdef DNGL_AXI_ERROR_LOGGING |
---|
| 22532 | + dhdp->axi_error = TRUE; |
---|
| 22533 | + dhdp->axi_err_dump->axid = axid; |
---|
| 22534 | + dhdp->axi_err_dump->fault_address = fault_addr; |
---|
| 22535 | +#endif /* DNGL_AXI_ERROR_LOGGING */ |
---|
| 22536 | + |
---|
| 22537 | + /* Disable PCIe IRQ */ |
---|
| 22538 | + dhdpcie_get_pcieirq(dhdp->bus, &irq); |
---|
| 22539 | + if (irq != (uint32)-1) { |
---|
| 22540 | + disable_irq_nosync(irq); |
---|
| 22541 | + } |
---|
| 22542 | + |
---|
| 22543 | + /* Take debug information first */ |
---|
| 22544 | + DHD_OS_WAKE_LOCK(dhdp); |
---|
| 22545 | + dhd_prot_smmu_fault_dump(dhdp); |
---|
| 22546 | + DHD_OS_WAKE_UNLOCK(dhdp); |
---|
| 22547 | + |
---|
| 22548 | + /* Take AXI information if possible */ |
---|
| 22549 | +#ifdef DNGL_AXI_ERROR_LOGGING |
---|
| 22550 | +#ifdef DHD_USE_WQ_FOR_DNGL_AXI_ERROR |
---|
| 22551 | + dhd_axi_error_dispatch(dhdp); |
---|
| 22552 | +#else |
---|
| 22553 | + dhd_axi_error(dhdp); |
---|
| 22554 | +#endif /* DHD_USE_WQ_FOR_DNGL_AXI_ERROR */ |
---|
| 22555 | +#endif /* DNGL_AXI_ERROR_LOGGING */ |
---|
| 22556 | +} |
---|
| 22557 | +EXPORT_SYMBOL(dhd_smmu_fault_handler); |
---|
| 22558 | +#endif /* DHD_MAP_LOGGING */ |
---|
| 22559 | + |
---|
| 22560 | +#ifdef DHD_WIFI_SHUTDOWN |
---|
| 22561 | +void wifi_plat_dev_drv_shutdown(struct platform_device *pdev) |
---|
| 22562 | +{ |
---|
| 22563 | + dhd_pub_t *dhd_pub = NULL; |
---|
| 22564 | + dhd_info_t *dhd_info = NULL; |
---|
| 22565 | + dhd_if_t *dhd_if = NULL; |
---|
| 22566 | + |
---|
| 22567 | + DHD_ERROR(("%s enter\n", __FUNCTION__)); |
---|
| 22568 | + dhd_pub = g_dhd_pub; |
---|
| 22569 | + |
---|
| 22570 | + if (dhd_os_check_if_up(dhd_pub)) { |
---|
| 22571 | + dhd_info = (dhd_info_t *)dhd_pub->info; |
---|
| 22572 | + dhd_if = dhd_info->iflist[0]; |
---|
| 22573 | + ASSERT(dhd_if); |
---|
| 22574 | + ASSERT(dhd_if->net); |
---|
| 22575 | + if (dhd_if && dhd_if->net) { |
---|
| 22576 | + dhd_stop(dhd_if->net); |
---|
| 22577 | + } |
---|
| 22578 | + } |
---|
| 22579 | +} |
---|
| 22580 | +#endif /* DHD_WIFI_SHUTDOWN */ |
---|
| 22581 | + |
---|
| 22582 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) |
---|
| 22583 | +int |
---|
| 22584 | +compat_kernel_read(struct file *file, loff_t offset, char *addr, unsigned long count) |
---|
| 22585 | +{ |
---|
| 22586 | + return (int)kernel_read(file, addr, (size_t)count, &offset); |
---|
| 22587 | +} |
---|
| 22588 | +#else |
---|
| 22589 | +int |
---|
| 22590 | +compat_kernel_read(struct file *file, loff_t offset, char *addr, unsigned long count) |
---|
| 22591 | +{ |
---|
| 22592 | + return kernel_read(file, offset, addr, count); |
---|
| 22593 | +} |
---|
| 22594 | +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) */ |
---|
| 22595 | + |
---|
| 22596 | +#ifdef DHDTCPSYNC_FLOOD_BLK |
---|
| 22597 | +static void dhd_blk_tsfl_handler(struct work_struct * work) |
---|
| 22598 | +{ |
---|
| 22599 | + dhd_if_t *ifp = NULL; |
---|
| 22600 | + dhd_pub_t *dhdp = NULL; |
---|
| 22601 | + /* Ignore compiler warnings due to -Werror=cast-qual */ |
---|
| 22602 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 22603 | +#pragma GCC diagnostic push |
---|
| 22604 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 22605 | +#endif /* STRICT_GCC_WARNINGS && __GNUC__ */ |
---|
| 22606 | + ifp = container_of(work, dhd_if_t, blk_tsfl_work); |
---|
| 22607 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 22608 | +#pragma GCC diagnostic pop |
---|
| 22609 | +#endif /* STRICT_GCC_WARNINGS && __GNUC__ */ |
---|
| 22610 | + if (ifp) { |
---|
| 22611 | + dhdp = &ifp->info->pub; |
---|
| 22612 | + if (dhdp) { |
---|
| 22613 | + if ((dhdp->op_mode & DHD_FLAG_P2P_GO_MODE)|| |
---|
| 22614 | + (dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) { |
---|
| 22615 | + DHD_ERROR(("Disassoc due to TCP SYNC FLOOD ATTACK\n")); |
---|
| 22616 | + wl_cfg80211_del_all_sta(ifp->net, WLAN_REASON_UNSPECIFIED); |
---|
| 22617 | + } else if ((dhdp->op_mode & DHD_FLAG_P2P_GC_MODE)|| |
---|
| 22618 | + (dhdp->op_mode & DHD_FLAG_STA_MODE)) { |
---|
| 22619 | + DHD_ERROR(("Diconnect due to TCP SYNC FLOOD ATTACK\n")); |
---|
| 22620 | + wl_cfg80211_disassoc(ifp->net, WLAN_REASON_UNSPECIFIED); |
---|
| 22621 | + } |
---|
| 22622 | + } |
---|
| 22623 | + } |
---|
| 22624 | +} |
---|
| 22625 | +void dhd_reset_tcpsync_info_by_ifp(dhd_if_t *ifp) |
---|
| 22626 | +{ |
---|
| 22627 | + ifp->tsync_rcvd = 0; |
---|
| 22628 | + ifp->tsyncack_txed = 0; |
---|
| 22629 | + ifp->last_sync = DIV_U64_BY_U32(OSL_LOCALTIME_NS(), NSEC_PER_SEC); |
---|
| 22630 | +} |
---|
| 22631 | +void dhd_reset_tcpsync_info_by_dev(struct net_device *dev) |
---|
| 22632 | +{ |
---|
| 22633 | + dhd_if_t *ifp = NULL; |
---|
| 22634 | + if (dev) { |
---|
| 22635 | + ifp = DHD_DEV_IFP(dev); |
---|
| 22636 | + } |
---|
| 22637 | + if (ifp) { |
---|
| 22638 | + ifp->tsync_rcvd = 0; |
---|
| 22639 | + ifp->tsyncack_txed = 0; |
---|
| 22640 | + ifp->last_sync = DIV_U64_BY_U32(OSL_LOCALTIME_NS(), NSEC_PER_SEC); |
---|
| 22641 | + } |
---|
| 22642 | +} |
---|
| 22643 | +#endif /* DHDTCPSYNC_FLOOD_BLK */ |
---|
| 22644 | + |
---|
| 22645 | +#ifdef DHD_4WAYM4_FAIL_DISCONNECT |
---|
| 22646 | +static void dhd_m4_state_handler(struct work_struct *work) |
---|
| 22647 | +{ |
---|
| 22648 | + dhd_if_t *ifp = NULL; |
---|
| 22649 | + /* Ignore compiler warnings due to -Werror=cast-qual */ |
---|
| 22650 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 22651 | +#pragma GCC diagnostic push |
---|
| 22652 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
---|
| 22653 | +#endif // endif |
---|
| 22654 | + struct delayed_work *dw = to_delayed_work(work); |
---|
| 22655 | + ifp = container_of(dw, dhd_if_t, m4state_work); |
---|
| 22656 | +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) |
---|
| 22657 | +#pragma GCC diagnostic pop |
---|
| 22658 | +#endif // endif |
---|
| 22659 | + |
---|
| 22660 | + if (ifp && ifp->net && |
---|
| 22661 | + (OSL_ATOMIC_READ(ifp->info->pub->osh, &ifp->m4state) == M4_TXFAILED)) { |
---|
| 22662 | + DHD_ERROR(("Disassoc for 4WAY_HANDSHAKE_TIMEOUT at %s\n", |
---|
| 22663 | + ifp->net->name)); |
---|
| 22664 | + wl_cfg80211_disassoc(ifp->net, WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT); |
---|
| 22665 | + } |
---|
| 22666 | +} |
---|
| 22667 | + |
---|
| 22668 | +void |
---|
| 22669 | +dhd_eap_txcomplete(dhd_pub_t *dhdp, void *txp, bool success, int ifidx) |
---|
| 22670 | +{ |
---|
| 22671 | + dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); |
---|
| 22672 | + struct ether_header *eh; |
---|
| 22673 | + uint16 type; |
---|
| 22674 | + |
---|
| 22675 | + if (!success) { |
---|
| 22676 | + dhd_prot_hdrpull(dhdp, NULL, txp, NULL, NULL); |
---|
| 22677 | + |
---|
| 22678 | + eh = (struct ether_header *)PKTDATA(dhdp->osh, txp); |
---|
| 22679 | + type = ntoh16(eh->ether_type); |
---|
| 22680 | + if (type == ETHER_TYPE_802_1X) { |
---|
| 22681 | + if (dhd_is_4way_msg((uint8 *)eh) == EAPOL_4WAY_M4) { |
---|
| 22682 | + dhd_if_t *ifp = NULL; |
---|
| 22683 | + ifp = dhd->iflist[ifidx]; |
---|
| 22684 | + if (!ifp || !ifp->net) { |
---|
| 22685 | + return; |
---|
| 22686 | + } |
---|
| 22687 | + |
---|
| 22688 | + DHD_INFO(("%s: M4 TX failed on %d.\n", |
---|
| 22689 | + __FUNCTION__, ifidx)); |
---|
| 22690 | + |
---|
| 22691 | + OSL_ATOMIC_SET(dhdp->osh, &ifp->m4state, M4_TXFAILED); |
---|
| 22692 | + schedule_delayed_work(&ifp->m4state_work, |
---|
| 22693 | + msecs_to_jiffies(MAX_4WAY_TIMEOUT_MS)); |
---|
| 22694 | + } |
---|
| 22695 | + } |
---|
| 22696 | + } |
---|
| 22697 | +} |
---|
| 22698 | + |
---|
| 22699 | +void |
---|
| 22700 | +dhd_cleanup_m4_state_work(dhd_pub_t *dhdp, int ifidx) |
---|
| 22701 | +{ |
---|
| 22702 | + dhd_info_t *dhdinfo; |
---|
| 22703 | + dhd_if_t *ifp; |
---|
| 22704 | + |
---|
| 22705 | + if ((ifidx < 0) || (ifidx >= DHD_MAX_IFS)) { |
---|
| 22706 | + DHD_ERROR(("%s: invalid ifidx %d\n", __FUNCTION__, ifidx)); |
---|
| 22707 | + return; |
---|
| 22708 | + } |
---|
| 22709 | + |
---|
| 22710 | + dhdinfo = (dhd_info_t *)(dhdp->info); |
---|
| 22711 | + if (!dhdinfo) { |
---|
| 22712 | + DHD_ERROR(("%s: dhdinfo is NULL\n", __FUNCTION__)); |
---|
| 22713 | + return; |
---|
| 22714 | + } |
---|
| 22715 | + |
---|
| 22716 | + ifp = dhdinfo->iflist[ifidx]; |
---|
| 22717 | + if (ifp) { |
---|
| 22718 | + cancel_delayed_work_sync(&ifp->m4state_work); |
---|
| 22719 | + } |
---|
| 22720 | +} |
---|
| 22721 | +#endif /* DHD_4WAYM4_FAIL_DISCONNECT */ |
---|
| 22722 | + |
---|
| 22723 | +#ifdef DHD_HP2P |
---|
| 22724 | +unsigned long |
---|
| 22725 | +dhd_os_hp2plock(dhd_pub_t *pub) |
---|
| 22726 | +{ |
---|
| 22727 | + dhd_info_t *dhd; |
---|
| 22728 | + unsigned long flags = 0; |
---|
| 22729 | + |
---|
| 22730 | + dhd = (dhd_info_t *)(pub->info); |
---|
| 22731 | + |
---|
| 22732 | + if (dhd) { |
---|
| 22733 | + spin_lock_irqsave(&dhd->hp2p_lock, flags); |
---|
| 22734 | + } |
---|
| 22735 | + |
---|
| 22736 | + return flags; |
---|
| 22737 | +} |
---|
| 22738 | + |
---|
| 22739 | +void |
---|
| 22740 | +dhd_os_hp2punlock(dhd_pub_t *pub, unsigned long flags) |
---|
| 22741 | +{ |
---|
| 22742 | + dhd_info_t *dhd; |
---|
| 22743 | + |
---|
| 22744 | + dhd = (dhd_info_t *)(pub->info); |
---|
| 22745 | + |
---|
| 22746 | + if (dhd) { |
---|
| 22747 | + spin_unlock_irqrestore(&dhd->hp2p_lock, flags); |
---|
| 22748 | + } |
---|
| 22749 | +} |
---|
| 22750 | +#endif /* DHD_HP2P */ |
---|
| 22751 | +#ifdef DNGL_AXI_ERROR_LOGGING |
---|
| 22752 | +static void |
---|
| 22753 | +dhd_axi_error_dump(void *handle, void *event_info, u8 event) |
---|
| 22754 | +{ |
---|
| 22755 | + dhd_info_t *dhd = (dhd_info_t *)handle; |
---|
| 22756 | + dhd_pub_t *dhdp = NULL; |
---|
| 22757 | + |
---|
| 22758 | + if (!dhd) { |
---|
| 22759 | + DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); |
---|
| 22760 | + goto exit; |
---|
| 22761 | + } |
---|
| 22762 | + |
---|
| 22763 | + dhdp = &dhd->pub; |
---|
| 22764 | + if (!dhdp) { |
---|
| 22765 | + DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__)); |
---|
| 22766 | + goto exit; |
---|
| 22767 | + } |
---|
| 22768 | + |
---|
| 22769 | + /** |
---|
| 22770 | + * First save axi error information to a file |
---|
| 22771 | + * because panic should happen right after this. |
---|
| 22772 | + * After dhd reset, dhd reads the file, and do hang event process |
---|
| 22773 | + * to send axi error stored on the file to Bigdata server |
---|
| 22774 | + */ |
---|
| 22775 | + if (dhdp->axi_err_dump->etd_axi_error_v1.version != HND_EXT_TRAP_AXIERROR_VERSION_1) { |
---|
| 22776 | + DHD_ERROR(("%s: Invalid AXI version: 0x%x\n", |
---|
| 22777 | + __FUNCTION__, dhdp->axi_err_dump->etd_axi_error_v1.version)); |
---|
| 22778 | + } |
---|
| 22779 | + |
---|
| 22780 | + DHD_OS_WAKE_LOCK(dhdp); |
---|
| 22781 | +#ifdef DHD_FW_COREDUMP |
---|
| 22782 | +#ifdef DHD_SSSR_DUMP |
---|
| 22783 | + dhdp->collect_sssr = TRUE; |
---|
| 22784 | +#endif /* DHD_SSSR_DUMP */ |
---|
| 22785 | + DHD_ERROR(("%s: scheduling mem dump.. \n", __FUNCTION__)); |
---|
| 22786 | + dhd_schedule_memdump(dhdp, dhdp->soc_ram, dhdp->soc_ram_length); |
---|
| 22787 | +#endif /* DHD_FW_COREDUMP */ |
---|
| 22788 | + DHD_OS_WAKE_UNLOCK(dhdp); |
---|
| 22789 | + |
---|
| 22790 | +exit: |
---|
| 22791 | + /* Trigger kernel panic after taking necessary dumps */ |
---|
| 22792 | + BUG_ON(1); |
---|
| 22793 | +} |
---|
| 22794 | + |
---|
| 22795 | +void dhd_schedule_axi_error_dump(dhd_pub_t *dhdp, void *type) |
---|
| 22796 | +{ |
---|
| 22797 | + DHD_ERROR(("%s: scheduling axi_error_dump.. \n", __FUNCTION__)); |
---|
| 22798 | + dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, |
---|
| 22799 | + type, DHD_WQ_WORK_AXI_ERROR_DUMP, |
---|
| 22800 | + dhd_axi_error_dump, DHD_WQ_WORK_PRIORITY_HIGH); |
---|
| 22801 | +} |
---|
| 22802 | +#endif /* DNGL_AXI_ERROR_LOGGING */ |
---|
| 22803 | + |
---|
| 22804 | +#ifdef BCMPCIE |
---|
| 22805 | +static void |
---|
| 22806 | +dhd_cto_recovery_handler(void *handle, void *event_info, u8 event) |
---|
| 22807 | +{ |
---|
| 22808 | + dhd_info_t *dhd = handle; |
---|
| 22809 | + dhd_pub_t *dhdp = NULL; |
---|
| 22810 | + |
---|
| 22811 | + if (!dhd) { |
---|
| 22812 | + DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); |
---|
| 22813 | + BUG_ON(1); |
---|
| 22814 | + return; |
---|
| 22815 | + } |
---|
| 22816 | + |
---|
| 22817 | + dhdp = &dhd->pub; |
---|
| 22818 | + dhdpcie_cto_recovery_handler(dhdp); |
---|
| 22819 | +} |
---|
| 22820 | + |
---|
| 22821 | +void |
---|
| 22822 | +dhd_schedule_cto_recovery(dhd_pub_t *dhdp) |
---|
| 22823 | +{ |
---|
| 22824 | + DHD_ERROR(("%s: scheduling cto recovery.. \n", __FUNCTION__)); |
---|
| 22825 | + dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, |
---|
| 22826 | + NULL, DHD_WQ_WORK_CTO_RECOVERY, |
---|
| 22827 | + dhd_cto_recovery_handler, DHD_WQ_WORK_PRIORITY_HIGH); |
---|
| 22828 | +} |
---|
| 22829 | +#endif /* BCMPCIE */ |
---|
| 22830 | + |
---|
| 22831 | +#ifdef SUPPORT_SET_TID |
---|
| 22832 | +/* |
---|
| 22833 | + * Set custom TID value for UDP frame based on UID value. |
---|
| 22834 | + * This will be triggered by android private command below. |
---|
| 22835 | + * DRIVER SET_TID <Mode:uint8> <Target UID:uint32> <Custom TID:uint8> |
---|
| 22836 | + * Mode 0(SET_TID_OFF) : Disable changing TID |
---|
| 22837 | + * Mode 1(SET_TID_ALL_UDP) : Change TID for all UDP frames |
---|
| 22838 | + * Mode 2(SET_TID_BASED_ON_UID) : Change TID for UDP frames based on target UID |
---|
| 22839 | +*/ |
---|
| 22840 | +void |
---|
| 22841 | +dhd_set_tid_based_on_uid(dhd_pub_t *dhdp, void *pkt) |
---|
| 22842 | +{ |
---|
| 22843 | + struct ether_header *eh = NULL; |
---|
| 22844 | + struct sock *sk = NULL; |
---|
| 22845 | + uint8 *pktdata = NULL; |
---|
| 22846 | + uint8 *ip_hdr = NULL; |
---|
| 22847 | + uint8 cur_prio; |
---|
| 22848 | + uint8 prio; |
---|
| 22849 | + uint32 uid; |
---|
| 22850 | + |
---|
| 22851 | + if (dhdp->tid_mode == SET_TID_OFF) { |
---|
| 22852 | + return; |
---|
| 22853 | + } |
---|
| 22854 | + |
---|
| 22855 | + pktdata = (uint8 *)PKTDATA(dhdp->osh, pkt); |
---|
| 22856 | + eh = (struct ether_header *) pktdata; |
---|
| 22857 | + ip_hdr = (uint8 *)eh + ETHER_HDR_LEN; |
---|
| 22858 | + |
---|
| 22859 | + if (IPV4_PROT(ip_hdr) != IP_PROT_UDP) { |
---|
| 22860 | + return; |
---|
| 22861 | + } |
---|
| 22862 | + |
---|
| 22863 | + cur_prio = PKTPRIO(pkt); |
---|
| 22864 | + prio = dhdp->target_tid; |
---|
| 22865 | + uid = dhdp->target_uid; |
---|
| 22866 | + |
---|
| 22867 | + if ((cur_prio == prio) || |
---|
| 22868 | + (cur_prio != PRIO_8021D_BE)) { |
---|
| 22869 | + return; |
---|
| 22870 | + } |
---|
| 22871 | + |
---|
| 22872 | + sk = ((struct sk_buff*)(pkt))->sk; |
---|
| 22873 | + |
---|
| 22874 | + if ((dhdp->tid_mode == SET_TID_ALL_UDP) || |
---|
| 22875 | + (sk && (uid == __kuid_val(sock_i_uid(sk))))) { |
---|
| 22876 | + PKTSETPRIO(pkt, prio); |
---|
| 22877 | + } |
---|
| 22878 | +} |
---|
| 22879 | +#endif /* SUPPORT_SET_TID */ |
---|