blob: 7d1065798a92273e291d0f2467333e0a55eaa58a [file] [log] [blame]
Sameer Thalappil24db5282012-09-10 11:58:33 -07001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#include <linux/module.h>
13#include <linux/slab.h>
14#include <linux/err.h>
15#include <linux/wcnss_wlan.h>
16
17static DEFINE_MUTEX(alloc_lock);
18
19struct wcnss_prealloc {
20 int occupied;
21 unsigned int size;
22 void *ptr;
23};
24
25/* pre-alloced mem for WLAN driver */
26static struct wcnss_prealloc wcnss_allocs[] = {
27 {0, 8 * 1024, NULL},
28 {0, 8 * 1024, NULL},
29 {0, 8 * 1024, NULL},
30 {0, 8 * 1024, NULL},
31 {0, 32 * 1024, NULL},
32 {0, 32 * 1024, NULL},
33 {0, 32 * 1024, NULL},
34 {0, 32 * 1024, NULL},
35 {0, 32 * 1024, NULL},
36 {0, 32 * 1024, NULL},
37 {0, 32 * 1024, NULL},
38 {0, 64 * 1024, NULL},
39 {0, 64 * 1024, NULL},
40};
41
42int wcnss_prealloc_init(void)
43{
44 int i;
45
46 for (i = 0; i < ARRAY_SIZE(wcnss_allocs); i++) {
47 wcnss_allocs[i].occupied = 0;
48 wcnss_allocs[i].ptr = kmalloc(wcnss_allocs[i].size, GFP_KERNEL);
49 if (wcnss_allocs[i].ptr == NULL)
50 return -ENOMEM;
51 }
52
53 return 0;
54}
55
56void wcnss_prealloc_deinit(void)
57{
58 int i = 0;
59
60 for (i = 0; i < ARRAY_SIZE(wcnss_allocs); i++)
61 kfree(wcnss_allocs[i].ptr);
62}
63
64void *wcnss_prealloc_get(unsigned int size)
65{
66 int i = 0;
67
68 mutex_lock(&alloc_lock);
69 for (i = 0; i < ARRAY_SIZE(wcnss_allocs); i++) {
70 if (wcnss_allocs[i].occupied)
71 continue;
72
73 if (wcnss_allocs[i].size > size) {
74 /* we found the slot */
75 wcnss_allocs[i].occupied = 1;
76 mutex_unlock(&alloc_lock);
77 return wcnss_allocs[i].ptr;
78 }
79 }
80 pr_err("wcnss: %s: prealloc not available\n", __func__);
81 mutex_unlock(&alloc_lock);
82
83 return NULL;
84}
85EXPORT_SYMBOL(wcnss_prealloc_get);
86
87int wcnss_prealloc_put(void *ptr)
88{
89 int i = 0;
90
91 mutex_lock(&alloc_lock);
92 for (i = 0; i < ARRAY_SIZE(wcnss_allocs); i++) {
93 if (wcnss_allocs[i].ptr == ptr) {
94 wcnss_allocs[i].occupied = 0;
95 mutex_unlock(&alloc_lock);
96 return 1;
97 }
98 }
99 mutex_unlock(&alloc_lock);
100
101 return 0;
102}
103EXPORT_SYMBOL(wcnss_prealloc_put);