1 /*
2 * vendor/amlogic/wifi/dhd_static_buf.c
3 *
4 * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 */
17
18 #define pr_fmt(fmt) "Wifi: %s: " fmt, __func__
19
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/init.h>
23 #include <linux/platform_device.h>
24 #include <linux/delay.h>
25 #include <linux/err.h>
26 #include <linux/skbuff.h>
27 #include "dhd_static_buf.h"
28
29 #define DHD_STATIC_VERSION_STR "100.10.545.3"
30
31 #define BCMDHD_SDIO
32 #define BCMDHD_PCIE
33
34 enum dhd_prealloc_index {
35 DHD_PREALLOC_PROT = 0,
36 #if defined(BCMDHD_SDIO)
37 DHD_PREALLOC_RXBUF = 1,
38 DHD_PREALLOC_DATABUF = 2,
39 #endif
40 DHD_PREALLOC_OSL_BUF = 3,
41 DHD_PREALLOC_SKB_BUF = 4,
42 DHD_PREALLOC_WIPHY_ESCAN0 = 5,
43 DHD_PREALLOC_WIPHY_ESCAN1 = 6,
44 DHD_PREALLOC_DHD_INFO = 7,
45 DHD_PREALLOC_DHD_WLFC_INFO = 8,
46 #ifdef BCMDHD_PCIE
47 DHD_PREALLOC_IF_FLOW_LKUP = 9,
48 #endif
49 DHD_PREALLOC_MEMDUMP_BUF = 10,
50 DHD_PREALLOC_MEMDUMP_RAM = 11,
51 DHD_PREALLOC_DHD_WLFC_HANGER = 12,
52 DHD_PREALLOC_PKTID_MAP = 13,
53 DHD_PREALLOC_PKTID_MAP_IOCTL = 14,
54 DHD_PREALLOC_DHD_LOG_DUMP_BUF = 15,
55 DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX = 16,
56 DHD_PREALLOC_DHD_PKTLOG_DUMP_BUF = 17,
57 DHD_PREALLOC_STAT_REPORT_BUF = 18,
58 DHD_PREALLOC_WL_WEXT_INFO = 19,
59 DHD_PREALLOC_FW_VERBOSE_RING = 20,
60 DHD_PREALLOC_FW_EVENT_RING = 21,
61 DHD_PREALLOC_DHD_EVENT_RING = 22,
62 DHD_PREALLOC_NAN_EVENT_RING = 23,
63 DHD_PREALLOC_MAX
64 };
65
66 #define STATIC_BUF_MAX_NUM 20
67 #define STATIC_BUF_SIZE (PAGE_SIZE * 2)
68 #define CUSTOM_LOG_DUMP_BUFSIZE_MB 4
69 #define DHD_PREALLOC_PROT_SIZE (16 * 1024)
70 #define DHD_PREALLOC_RXBUF_SIZE (24 * 1024)
71 #define DHD_PREALLOC_DATABUF_SIZE (64 * 1024)
72 #define DHD_PREALLOC_OSL_BUF_SIZE (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)
73 #define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024)
74 #define DHD_PREALLOC_DHD_INFO_SIZE (32 * 1024)
75 #define DHD_PREALLOC_MEMDUMP_RAM_SIZE (1290 * 1024)
76 #define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024)
77 #define DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE (1024 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB)
78 #define DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE (8 * 1024)
79 #define DHD_PREALLOC_WL_WEXT_INFO_SIZE (70 * 1024)
80 #ifdef CONFIG_64BIT
81 #define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2)
82 #else
83 #define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024)
84 #endif
85 #define FW_VERBOSE_RING_SIZE (256 * 1024)
86 #define FW_EVENT_RING_SIZE (64 * 1024)
87 #define DHD_EVENT_RING_SIZE (64 * 1024)
88 #define NAN_EVENT_RING_SIZE (64 * 1024)
89
90 #if defined(CONFIG_64BIT)
91 #define WLAN_DHD_INFO_BUF_SIZE (24 * 1024)
92 #define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024)
93 #define WLAN_DHD_IF_FLOW_LKUP_SIZE (64 * 1024)
94 #else
95 #define WLAN_DHD_INFO_BUF_SIZE (16 * 1024)
96 #define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024)
97 #define WLAN_DHD_IF_FLOW_LKUP_SIZE (20 * 1024)
98 #endif /* CONFIG_64BIT */
99 #define WLAN_DHD_MEMDUMP_SIZE (800 * 1024)
100
101 #define DHD_SKB_1PAGE_BUFSIZE (PAGE_SIZE * 1)
102 #define DHD_SKB_2PAGE_BUFSIZE (PAGE_SIZE * 2)
103 #define DHD_SKB_4PAGE_BUFSIZE (PAGE_SIZE * 4)
104
105 #define DHD_SKB_1PAGE_BUF_NUM 8
106 #define DHD_SKB_2PAGE_BUF_NUM 64
107 #define DHD_SKB_4PAGE_BUF_NUM 1
108
109 /* The number is defined in linux_osl.c
110 * WLAN_SKB_1_2PAGE_BUF_NUM => STATIC_PKT_1_2PAGE_NUM
111 * WLAN_SKB_BUF_NUM => STATIC_PKT_MAX_NUM
112 */
113 #define WLAN_SKB_1_2PAGE_BUF_NUM ((DHD_SKB_1PAGE_BUF_NUM) + (DHD_SKB_2PAGE_BUF_NUM))
114 #define WLAN_SKB_BUF_NUM ((WLAN_SKB_1_2PAGE_BUF_NUM) + (DHD_SKB_4PAGE_BUF_NUM))
115
116 void *wlan_static_prot;
117 void *wlan_static_rxbuf;
118 void *wlan_static_databuf;
119 void *wlan_static_osl_buf;
120 void *wlan_static_scan_buf0;
121 void *wlan_static_scan_buf1;
122 void *wlan_static_dhd_info_buf;
123 void *wlan_static_dhd_wlfc_info_buf;
124 void *wlan_static_if_flow_lkup;
125 void *wlan_static_dhd_memdump_ram_buf;
126 void *wlan_static_dhd_wlfc_hanger_buf;
127 void *wlan_static_dhd_log_dump_buf;
128 void *wlan_static_dhd_log_dump_buf_ex;
129 void *wlan_static_wl_escan_info_buf;
130 void *wlan_static_fw_verbose_ring_buf;
131 void *wlan_static_fw_event_ring_buf;
132 void *wlan_static_dhd_event_ring_buf;
133 void *wlan_static_nan_event_ring_buf;
134
135 static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
136
bcmdhd_mem_prealloc(int section,unsigned long size)137 void *bcmdhd_mem_prealloc(int section, unsigned long size)
138 {
139 pr_info("sectoin %d, size %ld\n", section, size);
140 if (section == DHD_PREALLOC_PROT) {
141 return wlan_static_prot;
142 }
143
144 #if defined(BCMDHD_SDIO)
145 if (section == DHD_PREALLOC_RXBUF) {
146 return wlan_static_rxbuf;
147 }
148
149 if (section == DHD_PREALLOC_DATABUF) {
150 return wlan_static_databuf;
151 }
152 #endif /* BCMDHD_SDIO */
153
154 if (section == DHD_PREALLOC_SKB_BUF) {
155 return wlan_static_skb;
156 }
157
158 if (section == DHD_PREALLOC_WIPHY_ESCAN0) {
159 return wlan_static_scan_buf0;
160 }
161
162 if (section == DHD_PREALLOC_WIPHY_ESCAN1) {
163 return wlan_static_scan_buf1;
164 }
165
166 if (section == DHD_PREALLOC_OSL_BUF) {
167 if (size > DHD_PREALLOC_OSL_BUF_SIZE) {
168 pr_err("request OSL_BUF(%lu) > %ld\n", size, DHD_PREALLOC_OSL_BUF_SIZE);
169 return NULL;
170 }
171 return wlan_static_osl_buf;
172 }
173
174 if (section == DHD_PREALLOC_DHD_INFO) {
175 if (size > DHD_PREALLOC_DHD_INFO_SIZE) {
176 pr_err("request DHD_INFO size(%lu) > %d\n", size, DHD_PREALLOC_DHD_INFO_SIZE);
177 return NULL;
178 }
179 return wlan_static_dhd_info_buf;
180 }
181 if (section == DHD_PREALLOC_DHD_WLFC_INFO) {
182 if (size > WLAN_DHD_WLFC_BUF_SIZE) {
183 pr_err("request DHD_WLFC_INFO size(%lu) > %d\n", size, WLAN_DHD_WLFC_BUF_SIZE);
184 return NULL;
185 }
186 return wlan_static_dhd_wlfc_info_buf;
187 }
188 #ifdef BCMDHD_PCIE
189 if (section == DHD_PREALLOC_IF_FLOW_LKUP) {
190 if (size > DHD_PREALLOC_IF_FLOW_LKUP_SIZE) {
191 pr_err("request DHD_IF_FLOW_LKUP size(%lu) > %d\n", size, DHD_PREALLOC_IF_FLOW_LKUP_SIZE);
192 return NULL;
193 }
194
195 return wlan_static_if_flow_lkup;
196 }
197 #endif /* BCMDHD_PCIE */
198 if (section == DHD_PREALLOC_MEMDUMP_RAM) {
199 if (size > DHD_PREALLOC_MEMDUMP_RAM_SIZE) {
200 pr_err("request DHD_PREALLOC_MEMDUMP_RAM_SIZE(%lu) > %d\n", size, DHD_PREALLOC_MEMDUMP_RAM_SIZE);
201 return NULL;
202 }
203
204 return wlan_static_dhd_memdump_ram_buf;
205 }
206 if (section == DHD_PREALLOC_DHD_WLFC_HANGER) {
207 if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) {
208 pr_err("request DHD_WLFC_HANGER size(%lu) > %d\n", size, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);
209 return NULL;
210 }
211 return wlan_static_dhd_wlfc_hanger_buf;
212 }
213 if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF) {
214 if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE) {
215 pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE(%lu) > %d\n", size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE);
216 return NULL;
217 }
218
219 return wlan_static_dhd_log_dump_buf;
220 }
221 if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX) {
222 if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE) {
223 pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE(%lu) > %d\n", size,
224 DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE);
225 return NULL;
226 }
227
228 return wlan_static_dhd_log_dump_buf_ex;
229 }
230 if (section == DHD_PREALLOC_WL_WEXT_INFO) {
231 if (size > DHD_PREALLOC_WL_WEXT_INFO_SIZE) {
232 pr_err("request DHD_PREALLOC_WL_WEXT_INFO_SIZE(%lu) > %d\n", size, DHD_PREALLOC_WL_WEXT_INFO_SIZE);
233 return NULL;
234 }
235
236 return wlan_static_wl_escan_info_buf;
237 }
238 if (section == DHD_PREALLOC_FW_VERBOSE_RING) {
239 if (size > FW_VERBOSE_RING_SIZE) {
240 pr_err("request DHD_PREALLOC_FW_VERBOSE_RING(%lu) > %d\n", size, FW_VERBOSE_RING_SIZE);
241 return NULL;
242 }
243
244 return wlan_static_fw_verbose_ring_buf;
245 }
246 if (section == DHD_PREALLOC_FW_EVENT_RING) {
247 if (size > FW_EVENT_RING_SIZE) {
248 pr_err("request DHD_PREALLOC_FW_EVENT_RING(%lu) > %d\n", size, FW_EVENT_RING_SIZE);
249 return NULL;
250 }
251
252 return wlan_static_fw_event_ring_buf;
253 }
254 if (section == DHD_PREALLOC_DHD_EVENT_RING) {
255 if (size > DHD_EVENT_RING_SIZE) {
256 pr_err("request DHD_PREALLOC_DHD_EVENT_RING(%lu) > %d\n", size, DHD_EVENT_RING_SIZE);
257 return NULL;
258 }
259
260 return wlan_static_dhd_event_ring_buf;
261 }
262 if (section == DHD_PREALLOC_NAN_EVENT_RING) {
263 if (size > NAN_EVENT_RING_SIZE) {
264 pr_err("request DHD_PREALLOC_NAN_EVENT_RING(%lu) > %d\n", size, NAN_EVENT_RING_SIZE);
265 return NULL;
266 }
267
268 return wlan_static_nan_event_ring_buf;
269 }
270 if ((section < 0) || (section > DHD_PREALLOC_MAX)) {
271 pr_err("request section id(%d) is out of max index %d\n", section, DHD_PREALLOC_MAX);
272 }
273
274 pr_err("%s: failed to alloc section %d, size=%ld\n", __func__, section, size);
275
276 return NULL;
277 }
278 EXPORT_SYMBOL(bcmdhd_mem_prealloc);
279
bcmdhd_init_wlan_mem(void)280 int bcmdhd_init_wlan_mem(void)
281 {
282 int i;
283 int j;
284 pr_info("%s(): %s\n", __func__, DHD_STATIC_VERSION_STR);
285
286 for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {
287 wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE);
288 if (!wlan_static_skb[i]) {
289 goto err_skb_alloc;
290 }
291 }
292
293 for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) {
294 wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_2PAGE_BUFSIZE);
295 if (!wlan_static_skb[i]) {
296 goto err_skb_alloc;
297 }
298 }
299
300 #if defined(BCMDHD_SDIO)
301 wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_4PAGE_BUFSIZE);
302 if (!wlan_static_skb[i]) {
303 goto err_skb_alloc;
304 }
305 #endif /* BCMDHD_SDIO */
306
307 wlan_static_prot = kmalloc(DHD_PREALLOC_PROT_SIZE, GFP_KERNEL);
308 if (!wlan_static_prot) {
309 goto err_mem_alloc;
310 }
311
312 #if defined(BCMDHD_SDIO)
313 wlan_static_rxbuf = kmalloc(DHD_PREALLOC_RXBUF_SIZE, GFP_KERNEL);
314 if (!wlan_static_rxbuf) {
315 goto err_mem_alloc;
316 }
317
318 wlan_static_databuf = kmalloc(DHD_PREALLOC_DATABUF_SIZE, GFP_KERNEL);
319 if (!wlan_static_databuf) {
320 goto err_mem_alloc;
321 }
322 #endif /* BCMDHD_SDIO */
323
324 wlan_static_osl_buf = kmalloc(DHD_PREALLOC_OSL_BUF_SIZE, GFP_KERNEL);
325 if (!wlan_static_osl_buf) {
326 goto err_mem_alloc;
327 }
328
329 wlan_static_scan_buf0 = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);
330 if (!wlan_static_scan_buf0) {
331 goto err_mem_alloc;
332 }
333
334 wlan_static_dhd_info_buf = kmalloc(DHD_PREALLOC_DHD_INFO_SIZE, GFP_KERNEL);
335 if (!wlan_static_dhd_info_buf) {
336 goto err_mem_alloc;
337 }
338
339 wlan_static_dhd_wlfc_info_buf = kmalloc(WLAN_DHD_WLFC_BUF_SIZE, GFP_KERNEL);
340 if (!wlan_static_dhd_wlfc_info_buf) {
341 goto err_mem_alloc;
342 }
343
344 #ifdef BCMDHD_PCIE
345 wlan_static_if_flow_lkup = kmalloc(DHD_PREALLOC_IF_FLOW_LKUP_SIZE, GFP_KERNEL);
346 if (!wlan_static_if_flow_lkup) {
347 goto err_mem_alloc;
348 }
349 #endif /* BCMDHD_PCIE */
350
351 wlan_static_dhd_memdump_ram_buf = kmalloc(DHD_PREALLOC_MEMDUMP_RAM_SIZE, GFP_KERNEL);
352 if (!wlan_static_dhd_memdump_ram_buf) {
353 goto err_mem_alloc;
354 }
355
356 wlan_static_dhd_wlfc_hanger_buf = kmalloc(DHD_PREALLOC_DHD_WLFC_HANGER_SIZE, GFP_KERNEL);
357 if (!wlan_static_dhd_wlfc_hanger_buf) {
358 goto err_mem_alloc;
359 }
360
361 wlan_static_dhd_log_dump_buf = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE, GFP_KERNEL);
362 if (!wlan_static_dhd_log_dump_buf) {
363 goto err_mem_alloc;
364 }
365
366 wlan_static_dhd_log_dump_buf_ex = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE, GFP_KERNEL);
367 if (!wlan_static_dhd_log_dump_buf_ex) {
368 goto err_mem_alloc;
369 }
370
371 wlan_static_wl_escan_info_buf = kmalloc(DHD_PREALLOC_WL_WEXT_INFO_SIZE, GFP_KERNEL);
372 if (!wlan_static_wl_escan_info_buf) {
373 goto err_mem_alloc;
374 }
375
376 wlan_static_fw_verbose_ring_buf = kmalloc(FW_VERBOSE_RING_SIZE, GFP_KERNEL);
377 if (!wlan_static_fw_verbose_ring_buf) {
378 goto err_mem_alloc;
379 }
380
381 wlan_static_fw_event_ring_buf = kmalloc(FW_EVENT_RING_SIZE, GFP_KERNEL);
382 if (!wlan_static_fw_event_ring_buf) {
383 goto err_mem_alloc;
384 }
385
386 wlan_static_dhd_event_ring_buf = kmalloc(DHD_EVENT_RING_SIZE, GFP_KERNEL);
387 if (!wlan_static_dhd_event_ring_buf) {
388 goto err_mem_alloc;
389 }
390
391 wlan_static_nan_event_ring_buf = kmalloc(NAN_EVENT_RING_SIZE, GFP_KERNEL);
392 if (!wlan_static_nan_event_ring_buf) {
393 goto err_mem_alloc;
394 }
395
396 pr_info("bcmdhd_init_wlan_mem prealloc ok\n");
397 return 0;
398
399 err_mem_alloc:
400
401 if (wlan_static_prot) {
402 kfree(wlan_static_prot);
403 }
404
405 #if defined(BCMDHD_SDIO)
406 if (wlan_static_rxbuf) {
407 kfree(wlan_static_rxbuf);
408 }
409
410 if (wlan_static_databuf) {
411 kfree(wlan_static_databuf);
412 }
413 #endif /* BCMDHD_SDIO */
414
415 if (wlan_static_osl_buf) {
416 kfree(wlan_static_osl_buf);
417 }
418
419 if (wlan_static_scan_buf0) {
420 kfree(wlan_static_scan_buf0);
421 }
422
423 if (wlan_static_scan_buf1) {
424 kfree(wlan_static_scan_buf1);
425 }
426
427 if (wlan_static_dhd_info_buf) {
428 kfree(wlan_static_dhd_info_buf);
429 }
430
431 if (wlan_static_dhd_wlfc_info_buf) {
432 kfree(wlan_static_dhd_wlfc_info_buf);
433 }
434
435 #ifdef BCMDHD_PCIE
436 if (wlan_static_if_flow_lkup) {
437 kfree(wlan_static_if_flow_lkup);
438 }
439 #endif /* BCMDHD_PCIE */
440
441 if (wlan_static_dhd_memdump_ram_buf) {
442 kfree(wlan_static_dhd_memdump_ram_buf);
443 }
444
445 if (wlan_static_dhd_wlfc_hanger_buf) {
446 kfree(wlan_static_dhd_wlfc_hanger_buf);
447 }
448
449 if (wlan_static_dhd_log_dump_buf) {
450 kfree(wlan_static_dhd_log_dump_buf);
451 }
452
453 if (wlan_static_dhd_log_dump_buf_ex) {
454 kfree(wlan_static_dhd_log_dump_buf_ex);
455 }
456
457 if (wlan_static_wl_escan_info_buf) {
458 kfree(wlan_static_wl_escan_info_buf);
459 }
460
461 #ifdef BCMDHD_PCIE
462 if (wlan_static_fw_verbose_ring_buf) {
463 kfree(wlan_static_fw_verbose_ring_buf);
464 }
465
466 if (wlan_static_fw_event_ring_buf) {
467 kfree(wlan_static_fw_event_ring_buf);
468 }
469
470 if (wlan_static_dhd_event_ring_buf) {
471 kfree(wlan_static_dhd_event_ring_buf);
472 }
473
474 if (wlan_static_nan_event_ring_buf) {
475 kfree(wlan_static_nan_event_ring_buf);
476 }
477 #endif /* BCMDHD_PCIE */
478
479 pr_err("%s: Failed to mem_alloc for WLAN\n", __func__);
480
481 i = WLAN_SKB_BUF_NUM;
482
483 err_skb_alloc:
484 pr_err("%s: Failed to skb_alloc for WLAN\n", __func__);
485 for (j = 0; j < i; j++) {
486 dev_kfree_skb(wlan_static_skb[j]);
487 }
488
489 return -ENOMEM;
490 }
491 EXPORT_SYMBOL(bcmdhd_init_wlan_mem);
492 MODULE_LICENSE("GPL");
493 MODULE_AUTHOR("AMLOGIC");
494 MODULE_DESCRIPTION("wifi device tree driver");
495