brcmfmac: use bssidx from struct brcmf_if for bsscfg specific commands
[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>
23#include <defs.h>
24#include <brcmu_utils.h>
25#include <brcmu_wifi.h>
26#include "dhd.h"
27#include "dhd_bus.h"
28#include "dhd_dbg.h"
ec5a07d5 29#include "fwil.h"
81f5dcb8
HM
30
31
32static s32
33brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
34{
35 struct brcmf_pub *drvr = ifp->drvr;
36 s32 err;
37
38 if (drvr->bus_if->state == BRCMF_BUS_DOWN) {
39 brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n");
40 return -EIO;
41 }
42
43 if (data != NULL)
44 len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
45 if (set)
46 err = brcmf_proto_cdc_set_dcmd(drvr, ifp->idx, cmd, data, len);
47 else
48 err = brcmf_proto_cdc_query_dcmd(drvr, ifp->idx, cmd, data,
49 len);
50
51 if (err >= 0)
52 err = 0;
53 else
54 brcmf_dbg(ERROR, "Failed err=%d\n", err);
55
56 return err;
57}
58
59s32
60brcmf_fil_cmd_data_set(struct net_device *ndev, u32 cmd, void *data, u32 len)
61{
62 struct brcmf_if *ifp = netdev_priv(ndev);
63 s32 err;
64
65 mutex_lock(&ifp->drvr->proto_block);
66
67 brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
68 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
69
70 err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
71 mutex_unlock(&ifp->drvr->proto_block);
72
73 return err;
74}
75
76s32
77brcmf_fil_cmd_data_get(struct net_device *ndev, u32 cmd, void *data, u32 len)
78{
79 struct brcmf_if *ifp = netdev_priv(ndev);
80 s32 err;
81
82 mutex_lock(&ifp->drvr->proto_block);
83 err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);
84
85 brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
86 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
87
88 mutex_unlock(&ifp->drvr->proto_block);
89
90 return err;
91}
92
93
94s32
95brcmf_fil_cmd_int_set(struct net_device *ndev, u32 cmd, u32 data)
96{
97 struct brcmf_if *ifp = netdev_priv(ndev);
98 s32 err;
99 __le32 data_le = cpu_to_le32(data);
100
101 mutex_lock(&ifp->drvr->proto_block);
102 err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
103 mutex_unlock(&ifp->drvr->proto_block);
104
105 return err;
106}
107
108s32
109brcmf_fil_cmd_int_get(struct net_device *ndev, u32 cmd, u32 *data)
110{
111 struct brcmf_if *ifp = netdev_priv(ndev);
112 s32 err;
113 __le32 data_le = cpu_to_le32(*data);
114
115 mutex_lock(&ifp->drvr->proto_block);
116 err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
117 mutex_unlock(&ifp->drvr->proto_block);
118 *data = le32_to_cpu(data_le);
119
120 return err;
121}
122
123static u32
124brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
125{
126 u32 len;
127
128 len = strlen(name) + 1;
129
130 if ((len + datalen) > buflen)
131 return 0;
132
133 memcpy(buf, name, len);
134
135 /* append data onto the end of the name string */
136 if (data && datalen)
137 memcpy(&buf[len], data, datalen);
138
139 return len + datalen;
140}
141
142
143s32
144brcmf_fil_iovar_data_set(struct net_device *ndev, char *name, void *data,
145 u32 len)
146{
147 struct brcmf_if *ifp = netdev_priv(ndev);
148 struct brcmf_pub *drvr = ifp->drvr;
149 s32 err;
150 u32 buflen;
151
152 mutex_lock(&drvr->proto_block);
153
154 brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
155 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
156
157 buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
158 sizeof(drvr->proto_buf));
159 if (buflen) {
160 err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
161 buflen, true);
162 } else {
163 err = -EPERM;
164 brcmf_dbg(ERROR, "Creating iovar failed\n");
165 }
166
167 mutex_unlock(&drvr->proto_block);
168 return err;
169}
170
171s32
172brcmf_fil_iovar_data_get(struct net_device *ndev, char *name, void *data,
173 u32 len)
174{
175 struct brcmf_if *ifp = netdev_priv(ndev);
176 struct brcmf_pub *drvr = ifp->drvr;
177 s32 err;
178 u32 buflen;
179
180 mutex_lock(&drvr->proto_block);
181
182 buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
183 sizeof(drvr->proto_buf));
184 if (buflen) {
185 err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
186 buflen, false);
187 if (err == 0)
188 memcpy(data, drvr->proto_buf, len);
189 } else {
190 err = -EPERM;
191 brcmf_dbg(ERROR, "Creating iovar failed\n");
192 }
193
194 brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
195 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
196
197 mutex_unlock(&drvr->proto_block);
198 return err;
199}
200
201s32
202brcmf_fil_iovar_int_set(struct net_device *ndev, char *name, u32 data)
203{
204 __le32 data_le = cpu_to_le32(data);
205
206 return brcmf_fil_iovar_data_set(ndev, name, &data_le, sizeof(data_le));
207}
208
209s32
210brcmf_fil_iovar_int_get(struct net_device *ndev, char *name, u32 *data)
211{
212 __le32 data_le = cpu_to_le32(*data);
213 s32 err;
214
215 err = brcmf_fil_iovar_data_get(ndev, name, &data_le, sizeof(data_le));
216 if (err == 0)
217 *data = le32_to_cpu(data_le);
218 return err;
219}
220
221static u32
222brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf,
223 u32 buflen)
224{
225 const s8 *prefix = "bsscfg:";
226 s8 *p;
227 u32 prefixlen;
228 u32 namelen;
229 u32 iolen;
230 __le32 bssidx_le;
231
232 if (bssidx == 0)
233 return brcmf_create_iovar(name, data, datalen, buf, buflen);
234
235 prefixlen = strlen(prefix);
236 namelen = strlen(name) + 1; /* lengh of iovar name + null */
237 iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen;
238
239 if (buflen < iolen) {
240 brcmf_dbg(ERROR, "buffer is too short\n");
241 return 0;
242 }
243
244 p = buf;
245
246 /* copy prefix, no null */
247 memcpy(p, prefix, prefixlen);
248 p += prefixlen;
249
250 /* copy iovar name including null */
251 memcpy(p, name, namelen);
252 p += namelen;
253
254 /* bss config index as first data */
255 bssidx_le = cpu_to_le32(bssidx);
256 memcpy(p, &bssidx_le, sizeof(bssidx_le));
257 p += sizeof(bssidx_le);
258
259 /* parameter buffer follows */
260 if (datalen)
261 memcpy(p, data, datalen);
262
263 return iolen;
264}
265
266s32
ec5a07d5 267brcmf_fil_bsscfg_data_set(struct net_device *ndev, char *name,
81f5dcb8
HM
268 void *data, u32 len)
269{
270 struct brcmf_if *ifp = netdev_priv(ndev);
271 struct brcmf_pub *drvr = ifp->drvr;
272 s32 err;
273 u32 buflen;
274
275 mutex_lock(&drvr->proto_block);
276
ec5a07d5 277 brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
81f5dcb8
HM
278 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
279
ec5a07d5
AS
280 buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
281 drvr->proto_buf, sizeof(drvr->proto_buf));
81f5dcb8
HM
282 if (buflen) {
283 err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
284 buflen, true);
285 } else {
286 err = -EPERM;
287 brcmf_dbg(ERROR, "Creating bsscfg failed\n");
288 }
289
290 mutex_unlock(&drvr->proto_block);
291 return err;
292}
293
294s32
ec5a07d5 295brcmf_fil_bsscfg_data_get(struct net_device *ndev, char *name,
81f5dcb8
HM
296 void *data, u32 len)
297{
298 struct brcmf_if *ifp = netdev_priv(ndev);
299 struct brcmf_pub *drvr = ifp->drvr;
300 s32 err;
301 u32 buflen;
302
303 mutex_lock(&drvr->proto_block);
304
ec5a07d5
AS
305 buflen = brcmf_create_bsscfg(ifp->bssidx, name, NULL, len,
306 drvr->proto_buf, sizeof(drvr->proto_buf));
81f5dcb8
HM
307 if (buflen) {
308 err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
309 buflen, false);
310 if (err == 0)
311 memcpy(data, drvr->proto_buf, len);
312 } else {
313 err = -EPERM;
314 brcmf_dbg(ERROR, "Creating bsscfg failed\n");
315 }
ec5a07d5 316 brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
81f5dcb8
HM
317 brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
318
319 mutex_unlock(&drvr->proto_block);
320 return err;
321
322}
323
324s32
ec5a07d5 325brcmf_fil_bsscfg_int_set(struct net_device *ndev, char *name, u32 data)
81f5dcb8
HM
326{
327 __le32 data_le = cpu_to_le32(data);
328
ec5a07d5 329 return brcmf_fil_bsscfg_data_set(ndev, name, &data_le,
81f5dcb8
HM
330 sizeof(data_le));
331}
332
333s32
ec5a07d5 334brcmf_fil_bsscfg_int_get(struct net_device *ndev, char *name, u32 *data)
81f5dcb8
HM
335{
336 __le32 data_le = cpu_to_le32(*data);
337 s32 err;
338
ec5a07d5 339 err = brcmf_fil_bsscfg_data_get(ndev, name, &data_le,
81f5dcb8
HM
340 sizeof(data_le));
341 if (err == 0)
342 *data = le32_to_cpu(data_le);
343 return err;
344}
This page took 0.037688 seconds and 5 git commands to generate.