brcmfmac: remove unnecessary EXPORT_SYMBOL() usage
[deliverable/linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / fwil.c
CommitLineData
81f5dcb8
HM
1/*
2 * Copyright (c) 2012 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/* FWIL is the Firmware Interface Layer. In this module the support functions
18 * are located to set and get variables to and from the firmware.
19 */
20
21#include <linux/kernel.h>
22#include <linux/netdevice.h>
81f5dcb8
HM
23#include <brcmu_utils.h>
24#include <brcmu_wifi.h>
25#include "dhd.h"
26#include "dhd_bus.h"
27#include "dhd_dbg.h"
40c1c249 28#include "tracepoint.h"
ec5a07d5 29#include "fwil.h"
85b84133 30#include "proto.h"
81f5dcb8
HM
31
32
5a7a59d2
HM
33#define MAX_HEX_DUMP_LEN 64
34
35
81f5dcb8
HM
36static s32
37brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
38{
39 struct brcmf_pub *drvr = ifp->drvr;
40 s32 err;
41
6034d0a1 42 if (drvr->bus_if->state != BRCMF_BUS_DATA) {
5e8149f5 43 brcmf_err("bus is down. we have nothing to do.\n");
81f5dcb8
HM
44 return -EIO;
45 }
46
47 if (data != NULL)
48 len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
49 if (set)
85b84133 50 err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len);
81f5dcb8 51 else
85b84133 52 err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len);
81f5dcb8
HM
53
54 if (err >= 0)
55 err = 0;
56 else
5e8149f5 57 brcmf_err("Failed err=%d\n", err);
81f5dcb8
HM
58
59 return err;
60}
61
62s32
ac24be6f 63brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
81f5dcb8 64{
81f5dcb8
HM
65 s32 err;
66
67 mutex_lock(&ifp->drvr->proto_block);
68
69 brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
5a7a59d2
HM
70 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
71 min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
81f5dcb8
HM
72
73 err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
74 mutex_unlock(&ifp->drvr->proto_block);
75
76 return err;
77}
78
79s32
ac24be6f 80brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
81f5dcb8 81{
81f5dcb8
HM
82 s32 err;
83
84 mutex_lock(&ifp->drvr->proto_block);
85 err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);
86
87 brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
5a7a59d2
HM
88 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
89 min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
81f5dcb8
HM
90
91 mutex_unlock(&ifp->drvr->proto_block);
92
93 return err;
94}
95
96
97s32
ac24be6f 98brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data)
81f5dcb8 99{
81f5dcb8
HM
100 s32 err;
101 __le32 data_le = cpu_to_le32(data);
102
103 mutex_lock(&ifp->drvr->proto_block);
659c84ff 104 brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, data);
81f5dcb8
HM
105 err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
106 mutex_unlock(&ifp->drvr->proto_block);
107
108 return err;
109}
110
111s32
ac24be6f 112brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
81f5dcb8 113{
81f5dcb8
HM
114 s32 err;
115 __le32 data_le = cpu_to_le32(*data);
116
117 mutex_lock(&ifp->drvr->proto_block);
118 err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
119 mutex_unlock(&ifp->drvr->proto_block);
120 *data = le32_to_cpu(data_le);
659c84ff 121 brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, *data);
81f5dcb8
HM
122
123 return err;
124}
125
126static u32
127brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
128{
129 u32 len;
130
131 len = strlen(name) + 1;
132
133 if ((len + datalen) > buflen)
134 return 0;
135
136 memcpy(buf, name, len);
137
138 /* append data onto the end of the name string */
139 if (data && datalen)
140 memcpy(&buf[len], data, datalen);
141
142 return len + datalen;
143}
144
145
146s32
ac24be6f 147brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
81f5dcb8
HM
148 u32 len)
149{
81f5dcb8
HM
150 struct brcmf_pub *drvr = ifp->drvr;
151 s32 err;
152 u32 buflen;
153
154 mutex_lock(&drvr->proto_block);
155
156 brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
5a7a59d2
HM
157 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
158 min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
81f5dcb8
HM
159
160 buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
161 sizeof(drvr->proto_buf));
162 if (buflen) {
163 err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
164 buflen, true);
165 } else {
166 err = -EPERM;
5e8149f5 167 brcmf_err("Creating iovar failed\n");
81f5dcb8
HM
168 }
169
170 mutex_unlock(&drvr->proto_block);
171 return err;
172}
173
174s32
ac24be6f 175brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
81f5dcb8
HM
176 u32 len)
177{
81f5dcb8
HM
178 struct brcmf_pub *drvr = ifp->drvr;
179 s32 err;
180 u32 buflen;
181
182 mutex_lock(&drvr->proto_block);
183
184 buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
185 sizeof(drvr->proto_buf));
186 if (buflen) {
187 err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
188 buflen, false);
189 if (err == 0)
190 memcpy(data, drvr->proto_buf, len);
191 } else {
192 err = -EPERM;
5e8149f5 193 brcmf_err("Creating iovar failed\n");
81f5dcb8
HM
194 }
195
196 brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
5a7a59d2
HM
197 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
198 min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
81f5dcb8
HM
199
200 mutex_unlock(&drvr->proto_block);
201 return err;
202}
203
204s32
ac24be6f 205brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data)
81f5dcb8
HM
206{
207 __le32 data_le = cpu_to_le32(data);
208
ac24be6f 209 return brcmf_fil_iovar_data_set(ifp, name, &data_le, sizeof(data_le));
81f5dcb8
HM
210}
211
212s32
ac24be6f 213brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data)
81f5dcb8
HM
214{
215 __le32 data_le = cpu_to_le32(*data);
216 s32 err;
217
ac24be6f 218 err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le));
81f5dcb8
HM
219 if (err == 0)
220 *data = le32_to_cpu(data_le);
221 return err;
222}
223
224static u32
225brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf,
226 u32 buflen)
227{
228 const s8 *prefix = "bsscfg:";
229 s8 *p;
230 u32 prefixlen;
231 u32 namelen;
232 u32 iolen;
233 __le32 bssidx_le;
234
235 if (bssidx == 0)
236 return brcmf_create_iovar(name, data, datalen, buf, buflen);
237
238 prefixlen = strlen(prefix);
239 namelen = strlen(name) + 1; /* lengh of iovar name + null */
240 iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen;
241
242 if (buflen < iolen) {
5e8149f5 243 brcmf_err("buffer is too short\n");
81f5dcb8
HM
244 return 0;
245 }
246
247 p = buf;
248
249 /* copy prefix, no null */
250 memcpy(p, prefix, prefixlen);
251 p += prefixlen;
252
253 /* copy iovar name including null */
254 memcpy(p, name, namelen);
255 p += namelen;
256
257 /* bss config index as first data */
258 bssidx_le = cpu_to_le32(bssidx);
259 memcpy(p, &bssidx_le, sizeof(bssidx_le));
260 p += sizeof(bssidx_le);
261
262 /* parameter buffer follows */
263 if (datalen)
264 memcpy(p, data, datalen);
265
266 return iolen;
267}
268
269s32
ac24be6f 270brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
81f5dcb8
HM
271 void *data, u32 len)
272{
81f5dcb8
HM
273 struct brcmf_pub *drvr = ifp->drvr;
274 s32 err;
275 u32 buflen;
276
277 mutex_lock(&drvr->proto_block);
278
ec5a07d5 279 brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
5a7a59d2
HM
280 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
281 min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
81f5dcb8 282
ec5a07d5
AS
283 buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
284 drvr->proto_buf, sizeof(drvr->proto_buf));
81f5dcb8
HM
285 if (buflen) {
286 err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
287 buflen, true);
288 } else {
289 err = -EPERM;
5e8149f5 290 brcmf_err("Creating bsscfg failed\n");
81f5dcb8
HM
291 }
292
293 mutex_unlock(&drvr->proto_block);
294 return err;
295}
296
297s32
ac24be6f 298brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
81f5dcb8
HM
299 void *data, u32 len)
300{
81f5dcb8
HM
301 struct brcmf_pub *drvr = ifp->drvr;
302 s32 err;
303 u32 buflen;
304
305 mutex_lock(&drvr->proto_block);
306
bb451c83 307 buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
ec5a07d5 308 drvr->proto_buf, sizeof(drvr->proto_buf));
81f5dcb8
HM
309 if (buflen) {
310 err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
311 buflen, false);
312 if (err == 0)
313 memcpy(data, drvr->proto_buf, len);
314 } else {
315 err = -EPERM;
5e8149f5 316 brcmf_err("Creating bsscfg failed\n");
81f5dcb8 317 }
ec5a07d5 318 brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
5a7a59d2
HM
319 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
320 min_t(uint, len, MAX_HEX_DUMP_LEN), "data");
81f5dcb8
HM
321
322 mutex_unlock(&drvr->proto_block);
323 return err;
324
325}
326
327s32
ac24be6f 328brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data)
81f5dcb8
HM
329{
330 __le32 data_le = cpu_to_le32(data);
331
ac24be6f 332 return brcmf_fil_bsscfg_data_set(ifp, name, &data_le,
81f5dcb8
HM
333 sizeof(data_le));
334}
335
336s32
ac24be6f 337brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data)
81f5dcb8
HM
338{
339 __le32 data_le = cpu_to_le32(*data);
340 s32 err;
341
ac24be6f 342 err = brcmf_fil_bsscfg_data_get(ifp, name, &data_le,
81f5dcb8
HM
343 sizeof(data_le));
344 if (err == 0)
345 *data = le32_to_cpu(data_le);
346 return err;
347}
This page took 0.120957 seconds and 5 git commands to generate.