aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/brcm80211/brcmfmac
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/brcm80211/brcmfmac')
-rw-r--r--drivers/staging/brcm80211/brcmfmac/Makefile39
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmchip.h32
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdh.c642
-rw-r--r--drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c1196
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd.h904
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_bus.h78
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_cdc.c502
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_common.c1196
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_dbg.h70
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_linux.c1736
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_proto.h75
-rw-r--r--drivers/staging/brcm80211/brcmfmac/dhd_sdio.c6772
-rw-r--r--drivers/staging/brcm80211/brcmfmac/sdio_host.h347
-rw-r--r--drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c4152
-rw-r--r--drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h356
15 files changed, 18097 insertions, 0 deletions
diff --git a/drivers/staging/brcm80211/brcmfmac/Makefile b/drivers/staging/brcm80211/brcmfmac/Makefile
new file mode 100644
index 00000000000..da3c8057590
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/Makefile
@@ -0,0 +1,39 @@
1#
2# Makefile fragment for Broadcom 802.11n Networking Device Driver
3#
4# Copyright (c) 2010 Broadcom Corporation
5#
6# Permission to use, copy, modify, and/or distribute this software for any
7# purpose with or without fee is hereby granted, provided that the above
8# copyright notice and this permission notice appear in all copies.
9#
10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18ccflags-y := \
19 -DBRCMF_FIRSTREAD=64 \
20 -DBRCMF_SDALIGN=64 \
21 -DMAX_HDR_READ=64
22
23ccflags-$(CONFIG_BRCMDBG) += -DSHOW_EVENTS
24
25ccflags-y += \
26 -Idrivers/staging/brcm80211/brcmfmac \
27 -Idrivers/staging/brcm80211/include
28
29DHDOFILES = \
30 wl_cfg80211.o \
31 dhd_cdc.o \
32 dhd_common.o \
33 dhd_sdio.o \
34 dhd_linux.o \
35 bcmsdh.o \
36 bcmsdh_sdmmc.o
37
38obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
39brcmfmac-objs += $(DHDOFILES)
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmchip.h b/drivers/staging/brcm80211/brcmfmac/bcmchip.h
new file mode 100644
index 00000000000..d7d3afd5a10
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/bcmchip.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright (c) 2011 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#ifndef _bcmchip_h_
18#define _bcmchip_h_
19
20/* bcm4329 */
21/* SDIO device core, ID 0x829 */
22#define BCM4329_CORE_BUS_BASE 0x18011000
23/* internal memory core, ID 0x80e */
24#define BCM4329_CORE_SOCRAM_BASE 0x18003000
25/* ARM Cortex M3 core, ID 0x82a */
26#define BCM4329_CORE_ARM_BASE 0x18002000
27#define BCM4329_RAMSIZE 0x48000
28/* firmware name */
29#define BCM4329_FW_NAME "brcm/bcm4329-fullmac-4.bin"
30#define BCM4329_NV_NAME "brcm/bcm4329-fullmac-4.txt"
31
32#endif /* _bcmchip_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
new file mode 100644
index 00000000000..f4e72ed126b
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
@@ -0,0 +1,642 @@
1/*
2 * Copyright (c) 2010 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/* ****************** SDIO CARD Interface Functions **************************/
17
18#include <linux/types.h>
19#include <linux/netdevice.h>
20#include <linux/pci.h>
21#include <linux/pci_ids.h>
22#include <linux/sched.h>
23#include <linux/completion.h>
24
25#include <defs.h>
26#include <brcm_hw_ids.h>
27#include <brcmu_utils.h>
28#include <brcmu_wifi.h>
29#include <soc.h>
30#include "dhd.h"
31#include "dhd_bus.h"
32#include "sdio_host.h"
33
34#define SDIOH_API_ACCESS_RETRY_LIMIT 2
35
36#define BRCMF_SD_ERROR_VAL 0x0001 /* Error */
37#define BRCMF_SD_INFO_VAL 0x0002 /* Info */
38
39
40#ifdef BCMDBG
41#define BRCMF_SD_ERROR(x) \
42 do { \
43 if ((brcmf_sdio_msglevel & BRCMF_SD_ERROR_VAL) && \
44 net_ratelimit()) \
45 printk x; \
46 } while (0)
47#define BRCMF_SD_INFO(x) \
48 do { \
49 if ((brcmf_sdio_msglevel & BRCMF_SD_INFO_VAL) && \
50 net_ratelimit()) \
51 printk x; \
52 } while (0)
53#else /* BCMDBG */
54#define BRCMF_SD_ERROR(x)
55#define BRCMF_SD_INFO(x)
56#endif /* BCMDBG */
57
58/* debugging macros */
59#define SDLX_MSG(x)
60
61#define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */
62#define SDIOH_CMD_TYPE_APPEND 1 /* Append command */
63#define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */
64
65#define SDIOH_DATA_PIO 0 /* PIO mode */
66#define SDIOH_DATA_DMA 1 /* DMA mode */
67
68struct brcmf_sdio_card {
69 bool init_success; /* underlying driver successfully attached */
70 void *sdioh; /* handler for sdioh */
71 u32 vendevid; /* Target Vendor and Device ID on SD bus */
72 bool regfail; /* Save status of last
73 reg_read/reg_write call */
74 u32 sbwad; /* Save backplane window address */
75};
76
77/**
78 * SDIO Host Controller info
79 */
80struct sdio_hc {
81 struct sdio_hc *next;
82 struct device *dev; /* platform device handle */
83 void *regs; /* SDIO Host Controller address */
84 struct brcmf_sdio_card *card;
85 void *ch;
86 unsigned int oob_irq;
87 unsigned long oob_flags; /* OOB Host specifiction
88 as edge and etc */
89 bool oob_irq_registered;
90};
91
92/* local copy of bcm sd handler */
93static struct brcmf_sdio_card *l_card;
94
95const uint brcmf_sdio_msglevel = BRCMF_SD_ERROR_VAL;
96
97static struct sdio_hc *sdhcinfo;
98
99/* driver info, initialized when brcmf_sdio_register is called */
100static struct brcmf_sdioh_driver drvinfo = { NULL, NULL };
101
102/* Module parameters specific to each host-controller driver */
103
104module_param(sd_msglevel, uint, 0);
105
106extern uint sd_f2_blocksize;
107module_param(sd_f2_blocksize, int, 0);
108
109/* forward declarations */
110int brcmf_sdio_probe(struct device *dev);
111EXPORT_SYMBOL(brcmf_sdio_probe);
112
113int brcmf_sdio_remove(struct device *dev);
114EXPORT_SYMBOL(brcmf_sdio_remove);
115
116struct brcmf_sdio_card*
117brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq)
118{
119 struct brcmf_sdio_card *card;
120
121 card = kzalloc(sizeof(struct brcmf_sdio_card), GFP_ATOMIC);
122 if (card == NULL) {
123 BRCMF_SD_ERROR(("sdcard_attach: out of memory"));
124 return NULL;
125 }
126
127 /* save the handler locally */
128 l_card = card;
129
130 card->sdioh = brcmf_sdioh_attach(cfghdl, irq);
131 if (!card->sdioh) {
132 brcmf_sdcard_detach(card);
133 return NULL;
134 }
135
136 card->init_success = true;
137
138 *regsva = SI_ENUM_BASE;
139
140 /* Report the BAR, to fix if needed */
141 card->sbwad = SI_ENUM_BASE;
142 return card;
143}
144
145int brcmf_sdcard_detach(struct brcmf_sdio_card *card)
146{
147 if (card != NULL) {
148 if (card->sdioh) {
149 brcmf_sdioh_detach(card->sdioh);
150 card->sdioh = NULL;
151 }
152 kfree(card);
153 }
154
155 l_card = NULL;
156 return 0;
157}
158
159int
160brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
161 void *params, int plen, void *arg, int len, bool set)
162{
163 return brcmf_sdioh_iovar_op(card->sdioh, name, params, plen, arg,
164 len, set);
165}
166
167int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card)
168{
169 return brcmf_sdioh_interrupt_set(card->sdioh, true);
170}
171
172int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card)
173{
174 return brcmf_sdioh_interrupt_set(card->sdioh, false);
175}
176
177int brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
178 void (*fn)(void *), void *argh)
179{
180 return brcmf_sdioh_interrupt_register(card->sdioh, fn, argh);
181}
182
183int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card)
184{
185 return brcmf_sdioh_interrupt_deregister(card->sdioh);
186}
187
188u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
189 int *err)
190{
191 int status;
192 s32 retry = 0;
193 u8 data = 0;
194
195 if (!card)
196 card = l_card;
197
198 do {
199 if (retry) /* wait for 1 ms till bus get settled down */
200 udelay(1000);
201 status =
202 brcmf_sdioh_cfg_read(card->sdioh, fnc_num, addr,
203 (u8 *) &data);
204 } while (status != 0
205 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
206 if (err)
207 *err = status;
208
209 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
210 __func__, fnc_num, addr, data));
211
212 return data;
213}
214
215void
216brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
217 u8 data, int *err)
218{
219 int status;
220 s32 retry = 0;
221
222 if (!card)
223 card = l_card;
224
225 do {
226 if (retry) /* wait for 1 ms till bus get settled down */
227 udelay(1000);
228 status =
229 brcmf_sdioh_cfg_write(card->sdioh, fnc_num, addr,
230 (u8 *) &data);
231 } while (status != 0
232 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
233 if (err)
234 *err = status;
235
236 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
237 __func__, fnc_num, addr, data));
238}
239
240u32 brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
241 u32 addr, int *err)
242{
243 int status;
244 u32 data = 0;
245
246 if (!card)
247 card = l_card;
248
249 status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
250 SDIOH_READ, fnc_num, addr, &data, 4);
251
252 if (err)
253 *err = status;
254
255 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
256 __func__, fnc_num, addr, data));
257
258 return data;
259}
260
261void
262brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card, uint fnc_num,
263 u32 addr, u32 data, int *err)
264{
265 int status;
266
267 if (!card)
268 card = l_card;
269
270 status =
271 brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
272 SDIOH_WRITE, fnc_num, addr, &data, 4);
273
274 if (err)
275 *err = status;
276
277 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
278 __func__, fnc_num, addr, data));
279}
280
281int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func, u8 * cis,
282 uint length)
283{
284 int status;
285
286 u8 *tmp_buf, *tmp_ptr;
287 u8 *ptr;
288 bool ascii = func & ~0xf;
289 func &= 0x7;
290
291 if (!card)
292 card = l_card;
293
294 status = brcmf_sdioh_cis_read(card->sdioh, func, cis, length);
295
296 if (ascii) {
297 /* Move binary bits to tmp and format them
298 into the provided buffer. */
299 tmp_buf = kmalloc(length, GFP_ATOMIC);
300 if (tmp_buf == NULL) {
301 BRCMF_SD_ERROR(("%s: out of memory\n", __func__));
302 return -ENOMEM;
303 }
304 memcpy(tmp_buf, cis, length);
305 for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
306 tmp_ptr++) {
307 ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
308 if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
309 ptr += sprintf((char *)ptr, "\n");
310 }
311 kfree(tmp_buf);
312 }
313
314 return status;
315}
316
317static int
318brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card *card, u32 address)
319{
320 int err = 0;
321 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
322 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
323 if (!err)
324 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
325 SBSDIO_FUNC1_SBADDRMID,
326 (address >> 16) & SBSDIO_SBADDRMID_MASK,
327 &err);
328 if (!err)
329 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
330 SBSDIO_FUNC1_SBADDRHIGH,
331 (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
332 &err);
333
334 return err;
335}
336
337u32 brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size)
338{
339 int status;
340 u32 word = 0;
341 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
342
343 BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
344
345 if (!card)
346 card = l_card;
347
348 if (bar0 != card->sbwad) {
349 if (brcmf_sdcard_set_sbaddr_window(card, bar0))
350 return 0xFFFFFFFF;
351
352 card->sbwad = bar0;
353 }
354
355 addr &= SBSDIO_SB_OFT_ADDR_MASK;
356 if (size == 4)
357 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
358
359 status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
360 SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
361
362 card->regfail = (status != 0);
363
364 BRCMF_SD_INFO(("u32data = 0x%x\n", word));
365
366 /* if ok, return appropriately masked word */
367 if (status == 0) {
368 switch (size) {
369 case sizeof(u8):
370 return word & 0xff;
371 case sizeof(u16):
372 return word & 0xffff;
373 case sizeof(u32):
374 return word;
375 default:
376 card->regfail = true;
377
378 }
379 }
380
381 /* otherwise, bad sdio access or invalid size */
382 BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
383 addr, size));
384 return 0xFFFFFFFF;
385}
386
387u32 brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
388 u32 data)
389{
390 int status;
391 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
392 int err = 0;
393
394 BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
395 __func__, addr, size * 8, data));
396
397 if (!card)
398 card = l_card;
399
400 if (bar0 != card->sbwad) {
401 err = brcmf_sdcard_set_sbaddr_window(card, bar0);
402 if (err)
403 return err;
404
405 card->sbwad = bar0;
406 }
407
408 addr &= SBSDIO_SB_OFT_ADDR_MASK;
409 if (size == 4)
410 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
411 status =
412 brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
413 SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
414 card->regfail = (status != 0);
415
416 if (status == 0)
417 return 0;
418
419 BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
420 __func__, data, addr, size));
421 return 0xFFFFFFFF;
422}
423
424bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card)
425{
426 return card->regfail;
427}
428
429int
430brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
431 uint flags,
432 u8 *buf, uint nbytes, struct sk_buff *pkt,
433 void (*complete)(void *handle, int status,
434 bool sync_waiting),
435 void *handle)
436{
437 int status;
438 uint incr_fix;
439 uint width;
440 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
441 int err = 0;
442
443 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
444 __func__, fn, addr, nbytes));
445
446 /* Async not implemented yet */
447 if (flags & SDIO_REQ_ASYNC)
448 return -ENOTSUPP;
449
450 if (bar0 != card->sbwad) {
451 err = brcmf_sdcard_set_sbaddr_window(card, bar0);
452 if (err)
453 return err;
454
455 card->sbwad = bar0;
456 }
457
458 addr &= SBSDIO_SB_OFT_ADDR_MASK;
459
460 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
461 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
462 if (width == 4)
463 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
464
465 status = brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
466 incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
467
468 return status;
469}
470
471int
472brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
473 uint flags, u8 *buf, uint nbytes, void *pkt,
474 void (*complete)(void *handle, int status,
475 bool sync_waiting),
476 void *handle)
477{
478 uint incr_fix;
479 uint width;
480 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
481 int err = 0;
482
483 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
484 __func__, fn, addr, nbytes));
485
486 /* Async not implemented yet */
487 if (flags & SDIO_REQ_ASYNC)
488 return -ENOTSUPP;
489
490 if (bar0 != card->sbwad) {
491 err = brcmf_sdcard_set_sbaddr_window(card, bar0);
492 if (err)
493 return err;
494
495 card->sbwad = bar0;
496 }
497
498 addr &= SBSDIO_SB_OFT_ADDR_MASK;
499
500 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
501 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
502 if (width == 4)
503 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
504
505 return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
506 incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
507}
508
509int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
510 u8 *buf, uint nbytes)
511{
512 addr &= SBSDIO_SB_OFT_ADDR_MASK;
513 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
514
515 return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
516 SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
517 addr, 4, nbytes, buf, NULL);
518}
519
520int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn)
521{
522 return brcmf_sdioh_abort(card->sdioh, fn);
523}
524
525int brcmf_sdcard_query_device(struct brcmf_sdio_card *card)
526{
527 card->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0;
528 return card->vendevid;
529}
530
531u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card)
532{
533 if (!card)
534 card = l_card;
535
536 return card->sbwad;
537}
538
539int brcmf_sdio_probe(struct device *dev)
540{
541 struct sdio_hc *sdhc = NULL;
542 u32 regs = 0;
543 struct brcmf_sdio_card *card = NULL;
544 int irq = 0;
545 u32 vendevid;
546 unsigned long irq_flags = 0;
547
548 /* allocate SDIO Host Controller state info */
549 sdhc = kzalloc(sizeof(struct sdio_hc), GFP_ATOMIC);
550 if (!sdhc) {
551 SDLX_MSG(("%s: out of memory\n", __func__));
552 goto err;
553 }
554 sdhc->dev = (void *)dev;
555
556 card = brcmf_sdcard_attach((void *)0, &regs, irq);
557 if (!card) {
558 SDLX_MSG(("%s: attach failed\n", __func__));
559 goto err;
560 }
561
562 sdhc->card = card;
563 sdhc->oob_irq = irq;
564 sdhc->oob_flags = irq_flags;
565 sdhc->oob_irq_registered = false; /* to make sure.. */
566
567 /* chain SDIO Host Controller info together */
568 sdhc->next = sdhcinfo;
569 sdhcinfo = sdhc;
570 /* Read the vendor/device ID from the CIS */
571 vendevid = brcmf_sdcard_query_device(card);
572
573 /* try to attach to the target device */
574 sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
575 0, 0, 0, 0, regs, card);
576 if (!sdhc->ch) {
577 SDLX_MSG(("%s: device attach failed\n", __func__));
578 goto err;
579 }
580
581 return 0;
582
583 /* error handling */
584err:
585 if (sdhc) {
586 if (sdhc->card)
587 brcmf_sdcard_detach(sdhc->card);
588 kfree(sdhc);
589 }
590
591 return -ENODEV;
592}
593
594int brcmf_sdio_remove(struct device *dev)
595{
596 struct sdio_hc *sdhc, *prev;
597
598 sdhc = sdhcinfo;
599 drvinfo.detach(sdhc->ch);
600 brcmf_sdcard_detach(sdhc->card);
601 /* find the SDIO Host Controller state for this pdev
602 and take it out from the list */
603 for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
604 if (sdhc->dev == (void *)dev) {
605 if (prev)
606 prev->next = sdhc->next;
607 else
608 sdhcinfo = NULL;
609 break;
610 }
611 prev = sdhc;
612 }
613 if (!sdhc) {
614 SDLX_MSG(("%s: failed\n", __func__));
615 return 0;
616 }
617
618 /* release SDIO Host Controller info */
619 kfree(sdhc);
620 return 0;
621}
622
623int brcmf_sdio_register(struct brcmf_sdioh_driver *driver)
624{
625 drvinfo = *driver;
626
627 SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
628 return brcmf_sdio_function_init();
629}
630
631void brcmf_sdio_unregister(void)
632{
633 brcmf_sdio_function_cleanup();
634}
635
636void brcmf_sdio_wdtmr_enable(bool enable)
637{
638 if (enable)
639 brcmf_sdbrcm_wd_timer(sdhcinfo->ch, brcmf_watchdog_ms);
640 else
641 brcmf_sdbrcm_wd_timer(sdhcinfo->ch, 0);
642}
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
new file mode 100644
index 00000000000..38bd9ba3096
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -0,0 +1,1196 @@
1/*
2 * Copyright (c) 2010 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#include <linux/types.h>
17#include <linux/netdevice.h>
18#include <linux/mmc/sdio.h>
19#include <linux/mmc/core.h>
20#include <linux/mmc/sdio_func.h>
21#include <linux/mmc/sdio_ids.h>
22#include <linux/mmc/card.h>
23#include <linux/suspend.h>
24#include <linux/errno.h>
25#include <linux/sched.h> /* request_irq() */
26#include <net/cfg80211.h>
27
28#include <defs.h>
29#include <brcm_hw_ids.h>
30#include <brcmu_utils.h>
31#include <brcmu_wifi.h>
32#include "sdio_host.h"
33#include "dhd.h"
34#include "dhd_dbg.h"
35#include "wl_cfg80211.h"
36
37#define BLOCK_SIZE_64 64
38#define BLOCK_SIZE_512 512
39#define BLOCK_SIZE_4318 64
40#define BLOCK_SIZE_4328 512
41
42/* private bus modes */
43#define SDIOH_MODE_SD4 2
44
45#define CLIENT_INTR 0x100 /* Get rid of this! */
46
47#if !defined(SDIO_VENDOR_ID_BROADCOM)
48#define SDIO_VENDOR_ID_BROADCOM 0x02d0
49#endif /* !defined(SDIO_VENDOR_ID_BROADCOM) */
50
51#define SDIO_DEVICE_ID_BROADCOM_DEFAULT 0x0000
52
53#define DMA_ALIGN_MASK 0x03
54
55#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)
56#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB 0x0492 /* BCM94325SDGWB */
57#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */
58#if !defined(SDIO_DEVICE_ID_BROADCOM_4325)
59#define SDIO_DEVICE_ID_BROADCOM_4325 0x0493
60#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */
61#if !defined(SDIO_DEVICE_ID_BROADCOM_4329)
62#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
63#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
64#if !defined(SDIO_DEVICE_ID_BROADCOM_4319)
65#define SDIO_DEVICE_ID_BROADCOM_4319 0x4319
66#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
67
68/* Common msglevel constants */
69#define SDH_ERROR_VAL 0x0001 /* Error */
70#define SDH_TRACE_VAL 0x0002 /* Trace */
71#define SDH_INFO_VAL 0x0004 /* Info */
72#define SDH_DEBUG_VAL 0x0008 /* Debug */
73#define SDH_DATA_VAL 0x0010 /* Data */
74#define SDH_CTRL_VAL 0x0020 /* Control Regs */
75#define SDH_LOG_VAL 0x0040 /* Enable bcmlog */
76#define SDH_DMA_VAL 0x0080 /* DMA */
77
78#ifdef BCMDBG
79#define sd_err(x) \
80 do { \
81 if ((sd_msglevel & SDH_ERROR_VAL) && net_ratelimit()) \
82 printk x; \
83 } while (0)
84#define sd_trace(x) \
85 do { \
86 if ((sd_msglevel & SDH_TRACE_VAL) && net_ratelimit()) \
87 printk x; \
88 } while (0)
89#define sd_info(x) \
90 do { \
91 if ((sd_msglevel & SDH_INFO_VAL) && net_ratelimit()) \
92 printk x; \
93 } while (0)
94#define sd_debug(x) \
95 do { \
96 if ((sd_msglevel & SDH_DEBUG_VAL) && net_ratelimit()) \
97 printk x; \
98 } while (0)
99#define sd_data(x) \
100 do { \
101 if ((sd_msglevel & SDH_DATA_VAL) && net_ratelimit()) \
102 printk x; \
103 } while (0)
104#define sd_ctrl(x) \
105 do { \
106 if ((sd_msglevel & SDH_CTRL_VAL) && net_ratelimit()) \
107 printk x; \
108 } while (0)
109#else
110#define sd_err(x)
111#define sd_trace(x)
112#define sd_info(x)
113#define sd_debug(x)
114#define sd_data(x)
115#define sd_ctrl(x)
116#endif
117
118struct sdos_info {
119 struct sdioh_info *sd;
120 spinlock_t lock;
121};
122
123static void brcmf_sdioh_irqhandler(struct sdio_func *func);
124static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func);
125static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr);
126static int brcmf_ops_sdio_probe(struct sdio_func *func,
127 const struct sdio_device_id *id);
128static void brcmf_ops_sdio_remove(struct sdio_func *func);
129
130#ifdef CONFIG_PM
131static int brcmf_sdio_suspend(struct device *dev);
132static int brcmf_sdio_resume(struct device *dev);
133#endif /* CONFIG_PM */
134
135uint sd_f2_blocksize = 512; /* Default blocksize */
136
137uint sd_msglevel = 0x01;
138
139/* module param defaults */
140static int clockoverride;
141
142module_param(clockoverride, int, 0644);
143MODULE_PARM_DESC(clockoverride, "SDIO card clock override");
144
145struct brcmf_sdmmc_instance *gInstance;
146
147struct device sdmmc_dev;
148
149/* devices we support, null terminated */
150static const struct sdio_device_id brcmf_sdmmc_ids[] = {
151 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT)},
152 {SDIO_DEVICE
153 (SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)},
154 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325)},
155 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
156 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319)},
157 { /* end: all zeroes */ },
158};
159
160#ifdef CONFIG_PM
161static const struct dev_pm_ops brcmf_sdio_pm_ops = {
162 .suspend = brcmf_sdio_suspend,
163 .resume = brcmf_sdio_resume,
164};
165#endif /* CONFIG_PM */
166
167static struct sdio_driver brcmf_sdmmc_driver = {
168 .probe = brcmf_ops_sdio_probe,
169 .remove = brcmf_ops_sdio_remove,
170 .name = "brcmfmac",
171 .id_table = brcmf_sdmmc_ids,
172#ifdef CONFIG_PM
173 .drv = {
174 .pm = &brcmf_sdio_pm_ops,
175 },
176#endif /* CONFIG_PM */
177};
178
179MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
180
181BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
182BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
183BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
184BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
185
186static int
187brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
188 int regsize, u32 *data);
189
190static int brcmf_sdioh_enablefuncs(struct sdioh_info *sd)
191{
192 int err_ret;
193 u32 fbraddr;
194 u8 func;
195
196 sd_trace(("%s\n", __func__));
197
198 /* Get the Card's common CIS address */
199 sd->com_cis_ptr = brcmf_sdioh_get_cisaddr(sd, SDIO_CCCR_CIS);
200 sd->func_cis_ptr[0] = sd->com_cis_ptr;
201 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
202 sd->com_cis_ptr));
203
204 /* Get the Card's function CIS (for each function) */
205 for (fbraddr = SDIO_FBR_BASE(1), func = 1;
206 func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
207 sd->func_cis_ptr[func] =
208 brcmf_sdioh_get_cisaddr(sd, SDIO_FBR_CIS + fbraddr);
209 sd_info(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func,
210 sd->func_cis_ptr[func]));
211 }
212
213 sd->func_cis_ptr[0] = sd->com_cis_ptr;
214 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
215 sd->com_cis_ptr));
216
217 /* Enable Function 1 */
218 sdio_claim_host(gInstance->func[1]);
219 err_ret = sdio_enable_func(gInstance->func[1]);
220 sdio_release_host(gInstance->func[1]);
221 if (err_ret) {
222 sd_err(("brcmf_sdioh_enablefuncs: Failed to enable F1 "
223 "Err: 0x%08x\n", err_ret));
224 }
225
226 return false;
227}
228
229/*
230 * Public entry points & extern's
231 */
232struct sdioh_info *brcmf_sdioh_attach(void *bar0, uint irq)
233{
234 struct sdioh_info *sd;
235 int err_ret;
236
237 sd_trace(("%s\n", __func__));
238
239 if (gInstance == NULL) {
240 sd_err(("%s: SDIO Device not present\n", __func__));
241 return NULL;
242 }
243
244 sd = kzalloc(sizeof(struct sdioh_info), GFP_ATOMIC);
245 if (sd == NULL) {
246 sd_err(("sdioh_attach: out of memory\n"));
247 return NULL;
248 }
249 if (brcmf_sdioh_osinit(sd) != 0) {
250 sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
251 kfree(sd);
252 return NULL;
253 }
254
255 sd->num_funcs = 2;
256 sd->use_client_ints = true;
257 sd->client_block_size[0] = 64;
258
259 gInstance->sd = sd;
260
261 /* Claim host controller */
262 sdio_claim_host(gInstance->func[1]);
263
264 sd->client_block_size[1] = 64;
265 err_ret = sdio_set_block_size(gInstance->func[1], 64);
266 if (err_ret)
267 sd_err(("brcmf_sdioh_attach: Failed to set F1 blocksize\n"));
268
269 /* Release host controller F1 */
270 sdio_release_host(gInstance->func[1]);
271
272 if (gInstance->func[2]) {
273 /* Claim host controller F2 */
274 sdio_claim_host(gInstance->func[2]);
275
276 sd->client_block_size[2] = sd_f2_blocksize;
277 err_ret =
278 sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
279 if (err_ret)
280 sd_err(("brcmf_sdioh_attach: Failed to set F2 blocksize"
281 " to %d\n", sd_f2_blocksize));
282
283 /* Release host controller F2 */
284 sdio_release_host(gInstance->func[2]);
285 }
286
287 brcmf_sdioh_enablefuncs(sd);
288
289 sd_trace(("%s: Done\n", __func__));
290 return sd;
291}
292
293extern int brcmf_sdioh_detach(struct sdioh_info *sd)
294{
295 sd_trace(("%s\n", __func__));
296
297 if (sd) {
298
299 /* Disable Function 2 */
300 sdio_claim_host(gInstance->func[2]);
301 sdio_disable_func(gInstance->func[2]);
302 sdio_release_host(gInstance->func[2]);
303
304 /* Disable Function 1 */
305 sdio_claim_host(gInstance->func[1]);
306 sdio_disable_func(gInstance->func[1]);
307 sdio_release_host(gInstance->func[1]);
308
309 /* deregister irq */
310 brcmf_sdioh_osfree(sd);
311
312 kfree(sd);
313 }
314 return 0;
315}
316
317/* Configure callback to client when we receive client interrupt */
318extern int
319brcmf_sdioh_interrupt_register(struct sdioh_info *sd, void (*fn)(void *),
320 void *argh)
321{
322 sd_trace(("%s: Entering\n", __func__));
323 if (fn == NULL) {
324 sd_err(("%s: interrupt handler is NULL, not registering\n",
325 __func__));
326 return -EINVAL;
327 }
328
329 sd->intr_handler = fn;
330 sd->intr_handler_arg = argh;
331 sd->intr_handler_valid = true;
332
333 /* register and unmask irq */
334 if (gInstance->func[2]) {
335 sdio_claim_host(gInstance->func[2]);
336 sdio_claim_irq(gInstance->func[2], brcmf_sdioh_irqhandler_f2);
337 sdio_release_host(gInstance->func[2]);
338 }
339
340 if (gInstance->func[1]) {
341 sdio_claim_host(gInstance->func[1]);
342 sdio_claim_irq(gInstance->func[1], brcmf_sdioh_irqhandler);
343 sdio_release_host(gInstance->func[1]);
344 }
345
346 return 0;
347}
348
349extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *sd)
350{
351 sd_trace(("%s: Entering\n", __func__));
352
353 if (gInstance->func[1]) {
354 /* register and unmask irq */
355 sdio_claim_host(gInstance->func[1]);
356 sdio_release_irq(gInstance->func[1]);
357 sdio_release_host(gInstance->func[1]);
358 }
359
360 if (gInstance->func[2]) {
361 /* Claim host controller F2 */
362 sdio_claim_host(gInstance->func[2]);
363 sdio_release_irq(gInstance->func[2]);
364 /* Release host controller F2 */
365 sdio_release_host(gInstance->func[2]);
366 }
367
368 sd->intr_handler_valid = false;
369 sd->intr_handler = NULL;
370 sd->intr_handler_arg = NULL;
371
372 return 0;
373}
374
375/* IOVar table */
376enum {
377 IOV_MSGLEVEL = 1,
378 IOV_BLOCKSIZE,
379 IOV_USEINTS,
380 IOV_NUMINTS,
381 IOV_DEVREG,
382 IOV_HCIREGS,
383 IOV_RXCHAIN
384};
385
386const struct brcmu_iovar sdioh_iovars[] = {
387 {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0},
388 {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) |
389 size) */
390 {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0},
391 {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0},
392 {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
393 ,
394 {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
395 ,
396 {NULL, 0, 0, 0, 0}
397};
398
399int
400brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
401 void *params, int plen, void *arg, int len, bool set)
402{
403 const struct brcmu_iovar *vi = NULL;
404 int bcmerror = 0;
405 int val_size;
406 s32 int_val = 0;
407 bool bool_val;
408 u32 actionid;
409
410 if (name == NULL || len <= 0)
411 return -EINVAL;
412
413 /* Set does not take qualifiers */
414 if (set && (params || plen))
415 return -EINVAL;
416
417 /* Get must have return space;*/
418 if (!set && !(arg && len))
419 return -EINVAL;
420
421 sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"),
422 name));
423
424 vi = brcmu_iovar_lookup(sdioh_iovars, name);
425 if (vi == NULL) {
426 bcmerror = -ENOTSUPP;
427 goto exit;
428 }
429
430 bcmerror = brcmu_iovar_lencheck(vi, arg, len, set);
431 if (bcmerror != 0)
432 goto exit;
433
434 /* Set up params so get and set can share the convenience variables */
435 if (params == NULL) {
436 params = arg;
437 plen = len;
438 }
439
440 if (vi->type == IOVT_VOID)
441 val_size = 0;
442 else if (vi->type == IOVT_BUFFER)
443 val_size = len;
444 else
445 val_size = sizeof(int);
446
447 if (plen >= (int)sizeof(int_val))
448 memcpy(&int_val, params, sizeof(int_val));
449
450 bool_val = (int_val != 0) ? true : false;
451
452 actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
453 switch (actionid) {
454 case IOV_GVAL(IOV_MSGLEVEL):
455 int_val = (s32) sd_msglevel;
456 memcpy(arg, &int_val, val_size);
457 break;
458
459 case IOV_SVAL(IOV_MSGLEVEL):
460 sd_msglevel = int_val;
461 break;
462
463 case IOV_GVAL(IOV_BLOCKSIZE):
464 if ((u32) int_val > si->num_funcs) {
465 bcmerror = -EINVAL;
466 break;
467 }
468 int_val = (s32) si->client_block_size[int_val];
469 memcpy(arg, &int_val, val_size);
470 break;
471
472 case IOV_SVAL(IOV_BLOCKSIZE):
473 {
474 uint func = ((u32) int_val >> 16);
475 uint blksize = (u16) int_val;
476 uint maxsize;
477
478 if (func > si->num_funcs) {
479 bcmerror = -EINVAL;
480 break;
481 }
482
483 switch (func) {
484 case 0:
485 maxsize = 32;
486 break;
487 case 1:
488 maxsize = BLOCK_SIZE_4318;
489 break;
490 case 2:
491 maxsize = BLOCK_SIZE_4328;
492 break;
493 default:
494 maxsize = 0;
495 }
496 if (blksize > maxsize) {
497 bcmerror = -EINVAL;
498 break;
499 }
500 if (!blksize)
501 blksize = maxsize;
502
503 /* Now set it */
504 si->client_block_size[func] = blksize;
505
506 break;
507 }
508
509 case IOV_GVAL(IOV_RXCHAIN):
510 int_val = false;
511 memcpy(arg, &int_val, val_size);
512 break;
513
514 case IOV_GVAL(IOV_USEINTS):
515 int_val = (s32) si->use_client_ints;
516 memcpy(arg, &int_val, val_size);
517 break;
518
519 case IOV_SVAL(IOV_USEINTS):
520 si->use_client_ints = (bool) int_val;
521 if (si->use_client_ints)
522 si->intmask |= CLIENT_INTR;
523 else
524 si->intmask &= ~CLIENT_INTR;
525
526 break;
527
528 case IOV_GVAL(IOV_NUMINTS):
529 int_val = (s32) si->intrcount;
530 memcpy(arg, &int_val, val_size);
531 break;
532
533 case IOV_GVAL(IOV_DEVREG):
534 {
535 struct brcmf_sdreg *sd_ptr =
536 (struct brcmf_sdreg *) params;
537 u8 data = 0;
538
539 if (brcmf_sdioh_cfg_read
540 (si, sd_ptr->func, sd_ptr->offset, &data)) {
541 bcmerror = -EIO;
542 break;
543 }
544
545 int_val = (int)data;
546 memcpy(arg, &int_val, sizeof(int_val));
547 break;
548 }
549
550 case IOV_SVAL(IOV_DEVREG):
551 {
552 struct brcmf_sdreg *sd_ptr =
553 (struct brcmf_sdreg *) params;
554 u8 data = (u8) sd_ptr->value;
555
556 if (brcmf_sdioh_cfg_write
557 (si, sd_ptr->func, sd_ptr->offset, &data)) {
558 bcmerror = -EIO;
559 break;
560 }
561 break;
562 }
563
564 default:
565 bcmerror = -ENOTSUPP;
566 break;
567 }
568exit:
569
570 return bcmerror;
571}
572
573extern int
574brcmf_sdioh_cfg_read(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
575{
576 int status;
577 /* No lock needed since brcmf_sdioh_request_byte does locking */
578 status = brcmf_sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
579 return status;
580}
581
582extern int
583brcmf_sdioh_cfg_write(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
584{
585 /* No lock needed since brcmf_sdioh_request_byte does locking */
586 int status;
587 status = brcmf_sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
588 return status;
589}
590
591static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr)
592{
593 /* read 24 bits and return valid 17 bit addr */
594 int i;
595 u32 scratch, regdata;
596 u8 *ptr = (u8 *)&scratch;
597 for (i = 0; i < 3; i++) {
598 if ((brcmf_sdioh_card_regread(sd, 0, regaddr, 1, &regdata)) !=
599 SUCCESS)
600 sd_err(("%s: Can't read!\n", __func__));
601
602 *ptr++ = (u8) regdata;
603 regaddr++;
604 }
605
606 /* Only the lower 17-bits are valid */
607 scratch = le32_to_cpu(scratch);
608 scratch &= 0x0001FFFF;
609 return scratch;
610}
611
612extern int
613brcmf_sdioh_cis_read(struct sdioh_info *sd, uint func, u8 *cisd, u32 length)
614{
615 u32 count;
616 int offset;
617 u32 foo;
618 u8 *cis = cisd;
619
620 sd_trace(("%s: Func = %d\n", __func__, func));
621
622 if (!sd->func_cis_ptr[func]) {
623 memset(cis, 0, length);
624 sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func));
625 return -ENOTSUPP;
626 }
627
628 sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func,
629 sd->func_cis_ptr[func]));
630
631 for (count = 0; count < length; count++) {
632 offset = sd->func_cis_ptr[func] + count;
633 if (brcmf_sdioh_card_regread(sd, 0, offset, 1, &foo) < 0) {
634 sd_err(("%s: regread failed: Can't read CIS\n",
635 __func__));
636 return -EIO;
637 }
638
639 *cis = (u8) (foo & 0xff);
640 cis++;
641 }
642
643 return 0;
644}
645
646extern int
647brcmf_sdioh_request_byte(struct sdioh_info *sd, uint rw, uint func,
648 uint regaddr, u8 *byte)
649{
650 int err_ret;
651
652 sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func,
653 regaddr));
654
655 BRCMF_PM_RESUME_WAIT(sdioh_request_byte_wait);
656 BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
657 if (rw) { /* CMD52 Write */
658 if (func == 0) {
659 /* Can only directly write to some F0 registers.
660 * Handle F2 enable
661 * as a special case.
662 */
663 if (regaddr == SDIO_CCCR_IOEx) {
664 if (gInstance->func[2]) {
665 sdio_claim_host(gInstance->func[2]);
666 if (*byte & SDIO_FUNC_ENABLE_2) {
667 /* Enable Function 2 */
668 err_ret =
669 sdio_enable_func
670 (gInstance->func[2]);
671 if (err_ret)
672 sd_err(("request_byte: "
673 "enable F2 "
674 "failed:%d\n",
675 err_ret));
676 } else {
677 /* Disable Function 2 */
678 err_ret =
679 sdio_disable_func
680 (gInstance->func[2]);
681 if (err_ret)
682 sd_err(("request_byte: "
683 "Disab F2 "
684 "failed:%d\n",
685 err_ret));
686 }
687 sdio_release_host(gInstance->func[2]);
688 }
689 }
690 /* to allow abort command through F1 */
691 else if (regaddr == SDIO_CCCR_ABORT) {
692 sdio_claim_host(gInstance->func[func]);
693 /*
694 * this sdio_f0_writeb() can be replaced
695 * with another api
696 * depending upon MMC driver change.
697 * As of this time, this is temporaray one
698 */
699 sdio_writeb(gInstance->func[func], *byte,
700 regaddr, &err_ret);
701 sdio_release_host(gInstance->func[func]);
702 } else if (regaddr < 0xF0) {
703 sd_err(("brcmf: F0 Wr:0x%02x: write "
704 "disallowed\n", regaddr));
705 } else {
706 /* Claim host controller, perform F0 write,
707 and release */
708 sdio_claim_host(gInstance->func[func]);
709 sdio_f0_writeb(gInstance->func[func], *byte,
710 regaddr, &err_ret);
711 sdio_release_host(gInstance->func[func]);
712 }
713 } else {
714 /* Claim host controller, perform Fn write,
715 and release */
716 sdio_claim_host(gInstance->func[func]);
717 sdio_writeb(gInstance->func[func], *byte, regaddr,
718 &err_ret);
719 sdio_release_host(gInstance->func[func]);
720 }
721 } else { /* CMD52 Read */
722 /* Claim host controller, perform Fn read, and release */
723 sdio_claim_host(gInstance->func[func]);
724
725 if (func == 0) {
726 *byte =
727 sdio_f0_readb(gInstance->func[func], regaddr,
728 &err_ret);
729 } else {
730 *byte =
731 sdio_readb(gInstance->func[func], regaddr,
732 &err_ret);
733 }
734
735 sdio_release_host(gInstance->func[func]);
736 }
737
738 if (err_ret)
739 sd_err(("brcmf: Failed to %s byte F%d:@0x%05x=%02x, "
740 "Err: %d\n", rw ? "Write" : "Read", func, regaddr,
741 *byte, err_ret));
742
743 return err_ret;
744}
745
746extern int
747brcmf_sdioh_request_word(struct sdioh_info *sd, uint cmd_type, uint rw,
748 uint func, uint addr, u32 *word, uint nbytes)
749{
750 int err_ret = -EIO;
751
752 if (func == 0) {
753 sd_err(("%s: Only CMD52 allowed to F0.\n", __func__));
754 return -EINVAL;
755 }
756
757 sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
758 __func__, cmd_type, rw, func, addr, nbytes));
759
760 BRCMF_PM_RESUME_WAIT(sdioh_request_word_wait);
761 BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
762 /* Claim host controller */
763 sdio_claim_host(gInstance->func[func]);
764
765 if (rw) { /* CMD52 Write */
766 if (nbytes == 4) {
767 sdio_writel(gInstance->func[func], *word, addr,
768 &err_ret);
769 } else if (nbytes == 2) {
770 sdio_writew(gInstance->func[func], (*word & 0xFFFF),
771 addr, &err_ret);
772 } else {
773 sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
774 }
775 } else { /* CMD52 Read */
776 if (nbytes == 4) {
777 *word =
778 sdio_readl(gInstance->func[func], addr, &err_ret);
779 } else if (nbytes == 2) {
780 *word =
781 sdio_readw(gInstance->func[func], addr,
782 &err_ret) & 0xFFFF;
783 } else {
784 sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
785 }
786 }
787
788 /* Release host controller */
789 sdio_release_host(gInstance->func[func]);
790
791 if (err_ret) {
792 sd_err(("brcmf: Failed to %s word, Err: 0x%08x\n",
793 rw ? "Write" : "Read", err_ret));
794 }
795
796 return err_ret;
797}
798
799static int
800brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write,
801 uint func, uint addr, struct sk_buff *pkt)
802{
803 bool fifo = (fix_inc == SDIOH_DATA_FIX);
804 u32 SGCount = 0;
805 int err_ret = 0;
806
807 struct sk_buff *pnext;
808
809 sd_trace(("%s: Enter\n", __func__));
810
811 BRCMF_PM_RESUME_WAIT(sdioh_request_packet_wait);
812 BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
813
814 /* Claim host controller */
815 sdio_claim_host(gInstance->func[func]);
816 for (pnext = pkt; pnext; pnext = pnext->next) {
817 uint pkt_len = pnext->len;
818 pkt_len += 3;
819 pkt_len &= 0xFFFFFFFC;
820
821 if ((write) && (!fifo)) {
822 err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
823 ((u8 *) (pnext->data)),
824 pkt_len);
825 } else if (write) {
826 err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
827 ((u8 *) (pnext->data)),
828 pkt_len);
829 } else if (fifo) {
830 err_ret = sdio_readsb(gInstance->func[func],
831 ((u8 *) (pnext->data)),
832 addr, pkt_len);
833 } else {
834 err_ret = sdio_memcpy_fromio(gInstance->func[func],
835 ((u8 *) (pnext->data)),
836 addr, pkt_len);
837 }
838
839 if (err_ret) {
840 sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d,"
841 "ERR=0x%08x\n", __func__,
842 (write) ? "TX" : "RX",
843 pnext, SGCount, addr, pkt_len, err_ret));
844 } else {
845 sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
846 __func__,
847 (write) ? "TX" : "RX",
848 pnext, SGCount, addr, pkt_len));
849 }
850
851 if (!fifo)
852 addr += pkt_len;
853 SGCount++;
854
855 }
856
857 /* Release host controller */
858 sdio_release_host(gInstance->func[func]);
859
860 sd_trace(("%s: Exit\n", __func__));
861 return err_ret;
862}
863
864/*
865 * This function takes a buffer or packet, and fixes everything up
866 * so that in the end, a DMA-able packet is created.
867 *
868 * A buffer does not have an associated packet pointer,
869 * and may or may not be aligned.
870 * A packet may consist of a single packet, or a packet chain.
871 * If it is a packet chain, then all the packets in the chain
872 * must be properly aligned.
873 *
874 * If the packet data is not aligned, then there may only be
875 * one packet, and in this case, it is copied to a new
876 * aligned packet.
877 *
878 */
879extern int
880brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc,
881 uint write, uint func, uint addr, uint reg_width,
882 uint buflen_u, u8 *buffer, struct sk_buff *pkt)
883{
884 int Status;
885 struct sk_buff *mypkt = NULL;
886
887 sd_trace(("%s: Enter\n", __func__));
888
889 BRCMF_PM_RESUME_WAIT(sdioh_request_buffer_wait);
890 BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
891 /* Case 1: we don't have a packet. */
892 if (pkt == NULL) {
893 sd_data(("%s: Creating new %s Packet, len=%d\n",
894 __func__, write ? "TX" : "RX", buflen_u));
895 mypkt = brcmu_pkt_buf_get_skb(buflen_u);
896 if (!mypkt) {
897 sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
898 __func__, buflen_u));
899 return -EIO;
900 }
901
902 /* For a write, copy the buffer data into the packet. */
903 if (write)
904 memcpy(mypkt->data, buffer, buflen_u);
905
906 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
907 addr, mypkt);
908
909 /* For a read, copy the packet data back to the buffer. */
910 if (!write)
911 memcpy(buffer, mypkt->data, buflen_u);
912
913 brcmu_pkt_buf_free_skb(mypkt);
914 } else if (((ulong) (pkt->data) & DMA_ALIGN_MASK) != 0) {
915 /*
916 * Case 2: We have a packet, but it is unaligned.
917 * In this case, we cannot have a chain (pkt->next == NULL)
918 */
919 sd_data(("%s: Creating aligned %s Packet, len=%d\n",
920 __func__, write ? "TX" : "RX", pkt->len));
921 mypkt = brcmu_pkt_buf_get_skb(pkt->len);
922 if (!mypkt) {
923 sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
924 __func__, pkt->len));
925 return -EIO;
926 }
927
928 /* For a write, copy the buffer data into the packet. */
929 if (write)
930 memcpy(mypkt->data, pkt->data, pkt->len);
931
932 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
933 addr, mypkt);
934
935 /* For a read, copy the packet data back to the buffer. */
936 if (!write)
937 memcpy(pkt->data, mypkt->data, mypkt->len);
938
939 brcmu_pkt_buf_free_skb(mypkt);
940 } else { /* case 3: We have a packet and
941 it is aligned. */
942 sd_data(("%s: Aligned %s Packet, direct DMA\n",
943 __func__, write ? "Tx" : "Rx"));
944 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
945 addr, pkt);
946 }
947
948 return Status;
949}
950
951/* this function performs "abort" for both of host & device */
952extern int brcmf_sdioh_abort(struct sdioh_info *sd, uint func)
953{
954 char t_func = (char)func;
955 sd_trace(("%s: Enter\n", __func__));
956
957 /* issue abort cmd52 command through F0 */
958 brcmf_sdioh_request_byte(sd, SDIOH_WRITE, SDIO_FUNC_0, SDIO_CCCR_ABORT,
959 &t_func);
960
961 sd_trace(("%s: Exit\n", __func__));
962 return 0;
963}
964
965/* Disable device interrupt */
966void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd)
967{
968 sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
969 sd->intmask &= ~CLIENT_INTR;
970}
971
972/* Enable device interrupt */
973void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd)
974{
975 sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
976 sd->intmask |= CLIENT_INTR;
977}
978
979/* Read client card reg */
980int
981brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
982 int regsize, u32 *data)
983{
984
985 if ((func == 0) || (regsize == 1)) {
986 u8 temp = 0;
987
988 brcmf_sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
989 *data = temp;
990 *data &= 0xff;
991 sd_data(("%s: byte read data=0x%02x\n", __func__, *data));
992 } else {
993 brcmf_sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
994 regsize);
995 if (regsize == 2)
996 *data &= 0xffff;
997
998 sd_data(("%s: word read data=0x%08x\n", __func__, *data));
999 }
1000
1001 return SUCCESS;
1002}
1003
1004static void brcmf_sdioh_irqhandler(struct sdio_func *func)
1005{
1006 struct sdioh_info *sd;
1007
1008 sd_trace(("brcmf: ***IRQHandler\n"));
1009 sd = gInstance->sd;
1010
1011 sdio_release_host(gInstance->func[0]);
1012
1013 if (sd->use_client_ints) {
1014 sd->intrcount++;
1015 (sd->intr_handler) (sd->intr_handler_arg);
1016 } else {
1017 sd_err(("brcmf: ***IRQHandler\n"));
1018
1019 sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
1020 __func__, sd->client_intr_enabled, sd->intr_handler));
1021 }
1022
1023 sdio_claim_host(gInstance->func[0]);
1024}
1025
1026/* interrupt handler for F2 (dummy handler) */
1027static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func)
1028{
1029 struct sdioh_info *sd;
1030
1031 sd_trace(("brcmf: ***IRQHandlerF2\n"));
1032
1033 sd = gInstance->sd;
1034}
1035
1036static int brcmf_ops_sdio_probe(struct sdio_func *func,
1037 const struct sdio_device_id *id)
1038{
1039 int ret = 0;
1040 static struct sdio_func sdio_func_0;
1041 sd_trace(("sdio_probe: %s Enter\n", __func__));
1042 sd_trace(("sdio_probe: func->class=%x\n", func->class));
1043 sd_trace(("sdio_vendor: 0x%04x\n", func->vendor));
1044 sd_trace(("sdio_device: 0x%04x\n", func->device));
1045 sd_trace(("Function#: 0x%04x\n", func->num));
1046
1047 if (func->num == 1) {
1048 sdio_func_0.num = 0;
1049 sdio_func_0.card = func->card;
1050 gInstance->func[0] = &sdio_func_0;
1051 if (func->device == 0x4) { /* 4318 */
1052 gInstance->func[2] = NULL;
1053 sd_trace(("NIC found, calling brcmf_sdio_probe...\n"));
1054 ret = brcmf_sdio_probe(&sdmmc_dev);
1055 }
1056 }
1057
1058 gInstance->func[func->num] = func;
1059
1060 if (func->num == 2) {
1061 brcmf_cfg80211_sdio_func(func);
1062 sd_trace(("F2 found, calling brcmf_sdio_probe...\n"));
1063 ret = brcmf_sdio_probe(&sdmmc_dev);
1064 }
1065
1066 return ret;
1067}
1068
1069static void brcmf_ops_sdio_remove(struct sdio_func *func)
1070{
1071 sd_trace(("%s Enter\n", __func__));
1072 sd_info(("func->class=%x\n", func->class));
1073 sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
1074 sd_info(("sdio_device: 0x%04x\n", func->device));
1075 sd_info(("Function#: 0x%04x\n", func->num));
1076
1077 if (func->num == 2) {
1078 sd_trace(("F2 found, calling brcmf_sdio_remove...\n"));
1079 brcmf_sdio_remove(&sdmmc_dev);
1080 }
1081}
1082
1083
1084#ifdef CONFIG_PM
1085static int brcmf_sdio_suspend(struct device *dev)
1086{
1087 mmc_pm_flag_t sdio_flags;
1088 int ret = 0;
1089
1090 sd_trace(("%s\n", __func__));
1091
1092 sdio_flags = sdio_get_host_pm_caps(gInstance->func[1]);
1093 if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
1094 sd_err(("Host can't keep power while suspended\n"));
1095 return -EINVAL;
1096 }
1097
1098 ret = sdio_set_host_pm_flags(gInstance->func[1], MMC_PM_KEEP_POWER);
1099 if (ret) {
1100 sd_err(("Failed to set pm_flags\n"));
1101 return ret;
1102 }
1103
1104 brcmf_sdio_wdtmr_enable(false);
1105
1106 return ret;
1107}
1108
1109static int brcmf_sdio_resume(struct device *dev)
1110{
1111 brcmf_sdio_wdtmr_enable(true);
1112 return 0;
1113}
1114#endif /* CONFIG_PM */
1115
1116int brcmf_sdioh_osinit(struct sdioh_info *sd)
1117{
1118 struct sdos_info *sdos;
1119
1120 sdos = kmalloc(sizeof(struct sdos_info), GFP_ATOMIC);
1121 sd->sdos_info = (void *)sdos;
1122 if (sdos == NULL)
1123 return -ENOMEM;
1124
1125 sdos->sd = sd;
1126 spin_lock_init(&sdos->lock);
1127 return 0;
1128}
1129
1130void brcmf_sdioh_osfree(struct sdioh_info *sd)
1131{
1132 struct sdos_info *sdos;
1133
1134 sdos = (struct sdos_info *)sd->sdos_info;
1135 kfree(sdos);
1136}
1137
1138/* Interrupt enable/disable */
1139int brcmf_sdioh_interrupt_set(struct sdioh_info *sd, bool enable)
1140{
1141 unsigned long flags;
1142 struct sdos_info *sdos;
1143
1144 sd_trace(("%s: %s\n", __func__, enable ? "Enabling" : "Disabling"));
1145
1146 sdos = (struct sdos_info *)sd->sdos_info;
1147
1148 if (enable && !(sd->intr_handler && sd->intr_handler_arg)) {
1149 sd_err(("%s: no handler registered, will not enable\n",
1150 __func__));
1151 return -EINVAL;
1152 }
1153
1154 /* Ensure atomicity for enable/disable calls */
1155 spin_lock_irqsave(&sdos->lock, flags);
1156
1157 sd->client_intr_enabled = enable;
1158 if (enable)
1159 brcmf_sdioh_dev_intr_on(sd);
1160 else
1161 brcmf_sdioh_dev_intr_off(sd);
1162
1163 spin_unlock_irqrestore(&sdos->lock, flags);
1164
1165 return 0;
1166}
1167
1168/*
1169 * module init
1170*/
1171int brcmf_sdio_function_init(void)
1172{
1173 int error = 0;
1174 sd_trace(("brcmf_sdio_function_init: %s Enter\n", __func__));
1175
1176 gInstance = kzalloc(sizeof(struct brcmf_sdmmc_instance), GFP_KERNEL);
1177 if (!gInstance)
1178 return -ENOMEM;
1179
1180 memset(&sdmmc_dev, 0, sizeof(sdmmc_dev));
1181 error = sdio_register_driver(&brcmf_sdmmc_driver);
1182
1183 return error;
1184}
1185
1186/*
1187 * module cleanup
1188*/
1189void brcmf_sdio_function_cleanup(void)
1190{
1191 sd_trace(("%s Enter\n", __func__));
1192
1193 sdio_unregister_driver(&brcmf_sdmmc_driver);
1194
1195 kfree(gInstance);
1196}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd.h b/drivers/staging/brcm80211/brcmfmac/dhd.h
new file mode 100644
index 00000000000..82bf04df16d
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/dhd.h
@@ -0,0 +1,904 @@
1/*
2 * Copyright (c) 2010 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/****************
18 * Common types *
19 */
20
21#ifndef _BRCMF_H_
22#define _BRCMF_H_
23
24#define BRCMF_VERSION_STR "4.218.248.5"
25
26#define BRCMF_C_IOCTL_SMLEN 256 /* "small" ioctl buffer required */
27#define BRCMF_C_IOCTL_MEDLEN 1536 /* "med" ioctl buffer required */
28#define BRCMF_C_IOCTL_MAXLEN 8192
29
30#define BRCMF_C_UP 2
31#define BRCMF_C_SET_PROMISC 10
32#define BRCMF_C_GET_RATE 12
33#define BRCMF_C_GET_INFRA 19
34#define BRCMF_C_SET_INFRA 20
35#define BRCMF_C_GET_AUTH 21
36#define BRCMF_C_SET_AUTH 22
37#define BRCMF_C_GET_BSSID 23
38#define BRCMF_C_GET_SSID 25
39#define BRCMF_C_SET_SSID 26
40#define BRCMF_C_GET_CHANNEL 29
41#define BRCMF_C_GET_SRL 31
42#define BRCMF_C_GET_LRL 33
43#define BRCMF_C_GET_RADIO 37
44#define BRCMF_C_SET_RADIO 38
45#define BRCMF_C_GET_PHYTYPE 39
46#define BRCMF_C_SET_KEY 45
47#define BRCMF_C_SET_PASSIVE_SCAN 49
48#define BRCMF_C_SCAN 50
49#define BRCMF_C_SCAN_RESULTS 51
50#define BRCMF_C_DISASSOC 52
51#define BRCMF_C_REASSOC 53
52#define BRCMF_C_SET_ROAM_TRIGGER 55
53#define BRCMF_C_SET_ROAM_DELTA 57
54#define BRCMF_C_GET_DTIMPRD 77
55#define BRCMF_C_SET_COUNTRY 84
56#define BRCMF_C_GET_PM 85
57#define BRCMF_C_SET_PM 86
58#define BRCMF_C_GET_AP 117
59#define BRCMF_C_SET_AP 118
60#define BRCMF_C_GET_RSSI 127
61#define BRCMF_C_GET_WSEC 133
62#define BRCMF_C_SET_WSEC 134
63#define BRCMF_C_GET_PHY_NOISE 135
64#define BRCMF_C_GET_BSS_INFO 136
65#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
66#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187
67#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201
68#define BRCMF_C_GET_VALID_CHANNELS 217
69#define BRCMF_C_GET_KEY_PRIMARY 235
70#define BRCMF_C_SET_KEY_PRIMARY 236
71#define BRCMF_C_SET_SCAN_PASSIVE_TIME 258
72#define BRCMF_C_GET_VAR 262
73#define BRCMF_C_SET_VAR 263
74
75/* phy types (returned by WLC_GET_PHYTPE) */
76#define WLC_PHY_TYPE_A 0
77#define WLC_PHY_TYPE_B 1
78#define WLC_PHY_TYPE_G 2
79#define WLC_PHY_TYPE_N 4
80#define WLC_PHY_TYPE_LP 5
81#define WLC_PHY_TYPE_SSN 6
82#define WLC_PHY_TYPE_HT 7
83#define WLC_PHY_TYPE_LCN 8
84#define WLC_PHY_TYPE_NULL 0xf
85
86#define BRCMF_PKT_FILTER_FIXED_LEN offsetof(struct brcmf_pkt_filter, u)
87#define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \
88 offsetof(struct brcmf_pkt_filter_pattern, mask_and_pattern)
89
90#define BRCMF_EVENTING_MASK_LEN 16
91
92#define TOE_TX_CSUM_OL 0x00000001
93#define TOE_RX_CSUM_OL 0x00000002
94
95/* maximum channels returned by the get valid channels iovar */
96#define WL_NUMCHANNELS 64
97
98#define BRCMF_BSS_INFO_VERSION 108 /* current ver of brcmf_bss_info struct */
99
100/* size of brcmf_scan_params not including variable length array */
101#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
102
103/* masks for channel and ssid count */
104#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
105#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16
106
107#define BRCMF_SCAN_ACTION_START 1
108#define BRCMF_SCAN_ACTION_CONTINUE 2
109#define WL_SCAN_ACTION_ABORT 3
110
111#define BRCMF_ISCAN_REQ_VERSION 1
112
113/* brcmf_iscan_results status values */
114#define BRCMF_SCAN_RESULTS_SUCCESS 0
115#define BRCMF_SCAN_RESULTS_PARTIAL 1
116#define BRCMF_SCAN_RESULTS_PENDING 2
117#define BRCMF_SCAN_RESULTS_ABORTED 3
118#define BRCMF_SCAN_RESULTS_NO_MEM 4
119
120#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */
121#define BRCMF_PRIMARY_KEY (1 << 1) /* primary (ie tx) key */
122#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */
123#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */
124#define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */
125
126/* For supporting multiple interfaces */
127#define BRCMF_MAX_IFS 16
128#define BRCMF_DEL_IF -0xe
129#define BRCMF_BAD_IF -0xf
130
131#define DOT11_BSSTYPE_ANY 2
132#define DOT11_MAX_DEFAULT_KEYS 4
133
134#define BRCMF_EVENT_MSG_LINK 0x01
135#define BRCMF_EVENT_MSG_FLUSHTXQ 0x02
136#define BRCMF_EVENT_MSG_GROUP 0x04
137
138struct brcmf_event_msg {
139 u16 version;
140 u16 flags;
141 u32 event_type;
142 u32 status;
143 u32 reason;
144 u32 auth_type;
145 u32 datalen;
146 u8 addr[ETH_ALEN];
147 char ifname[IFNAMSIZ];
148} __packed;
149
150struct brcm_ethhdr {
151 u16 subtype;
152 u16 length;
153 u8 version;
154 u8 oui[3];
155 u16 usr_subtype;
156} __packed;
157
158struct brcmf_event {
159 struct ethhdr eth;
160 struct brcm_ethhdr hdr;
161 struct brcmf_event_msg msg;
162} __packed;
163
164struct dngl_stats {
165 unsigned long rx_packets; /* total packets received */
166 unsigned long tx_packets; /* total packets transmitted */
167 unsigned long rx_bytes; /* total bytes received */
168 unsigned long tx_bytes; /* total bytes transmitted */
169 unsigned long rx_errors; /* bad packets received */
170 unsigned long tx_errors; /* packet transmit problems */
171 unsigned long rx_dropped; /* packets dropped by dongle */
172 unsigned long tx_dropped; /* packets dropped by dongle */
173 unsigned long multicast; /* multicast packets received */
174};
175
176#define BRCMF_E_SET_SSID 0
177#define BRCMF_E_JOIN 1
178#define BRCMF_E_START 2
179#define BRCMF_E_AUTH 3
180#define BRCMF_E_AUTH_IND 4
181#define BRCMF_E_DEAUTH 5
182#define BRCMF_E_DEAUTH_IND 6
183#define BRCMF_E_ASSOC 7
184#define BRCMF_E_ASSOC_IND 8
185#define BRCMF_E_REASSOC 9
186#define BRCMF_E_REASSOC_IND 10
187#define BRCMF_E_DISASSOC 11
188#define BRCMF_E_DISASSOC_IND 12
189#define BRCMF_E_QUIET_START 13
190#define BRCMF_E_QUIET_END 14
191#define BRCMF_E_BEACON_RX 15
192#define BRCMF_E_LINK 16
193#define BRCMF_E_MIC_ERROR 17
194#define BRCMF_E_NDIS_LINK 18
195#define BRCMF_E_ROAM 19
196#define BRCMF_E_TXFAIL 20
197#define BRCMF_E_PMKID_CACHE 21
198#define BRCMF_E_RETROGRADE_TSF 22
199#define BRCMF_E_PRUNE 23
200#define BRCMF_E_AUTOAUTH 24
201#define BRCMF_E_EAPOL_MSG 25
202#define BRCMF_E_SCAN_COMPLETE 26
203#define BRCMF_E_ADDTS_IND 27
204#define BRCMF_E_DELTS_IND 28
205#define BRCMF_E_BCNSENT_IND 29
206#define BRCMF_E_BCNRX_MSG 30
207#define BRCMF_E_BCNLOST_MSG 31
208#define BRCMF_E_ROAM_PREP 32
209#define BRCMF_E_PFN_NET_FOUND 33
210#define BRCMF_E_PFN_NET_LOST 34
211#define BRCMF_E_RESET_COMPLETE 35
212#define BRCMF_E_JOIN_START 36
213#define BRCMF_E_ROAM_START 37
214#define BRCMF_E_ASSOC_START 38
215#define BRCMF_E_IBSS_ASSOC 39
216#define BRCMF_E_RADIO 40
217#define BRCMF_E_PSM_WATCHDOG 41
218#define BRCMF_E_PROBREQ_MSG 44
219#define BRCMF_E_SCAN_CONFIRM_IND 45
220#define BRCMF_E_PSK_SUP 46
221#define BRCMF_E_COUNTRY_CODE_CHANGED 47
222#define BRCMF_E_EXCEEDED_MEDIUM_TIME 48
223#define BRCMF_E_ICV_ERROR 49
224#define BRCMF_E_UNICAST_DECODE_ERROR 50
225#define BRCMF_E_MULTICAST_DECODE_ERROR 51
226#define BRCMF_E_TRACE 52
227#define BRCMF_E_IF 54
228#define BRCMF_E_RSSI 56
229#define BRCMF_E_PFN_SCAN_COMPLETE 57
230#define BRCMF_E_EXTLOG_MSG 58
231#define BRCMF_E_ACTION_FRAME 59
232#define BRCMF_E_ACTION_FRAME_COMPLETE 60
233#define BRCMF_E_PRE_ASSOC_IND 61
234#define BRCMF_E_PRE_REASSOC_IND 62
235#define BRCMF_E_CHANNEL_ADOPTED 63
236#define BRCMF_E_AP_STARTED 64
237#define BRCMF_E_DFS_AP_STOP 65
238#define BRCMF_E_DFS_AP_RESUME 66
239#define BRCMF_E_RESERVED1 67
240#define BRCMF_E_RESERVED2 68
241#define BRCMF_E_ESCAN_RESULT 69
242#define BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70
243#define BRCMF_E_DCS_REQUEST 73
244
245#define BRCMF_E_FIFO_CREDIT_MAP 74
246
247#define BRCMF_E_LAST 75
248
249#define BRCMF_E_STATUS_SUCCESS 0
250#define BRCMF_E_STATUS_FAIL 1
251#define BRCMF_E_STATUS_TIMEOUT 2
252#define BRCMF_E_STATUS_NO_NETWORKS 3
253#define BRCMF_E_STATUS_ABORT 4
254#define BRCMF_E_STATUS_NO_ACK 5
255#define BRCMF_E_STATUS_UNSOLICITED 6
256#define BRCMF_E_STATUS_ATTEMPT 7
257#define BRCMF_E_STATUS_PARTIAL 8
258#define BRCMF_E_STATUS_NEWSCAN 9
259#define BRCMF_E_STATUS_NEWASSOC 10
260#define BRCMF_E_STATUS_11HQUIET 11
261#define BRCMF_E_STATUS_SUPPRESS 12
262#define BRCMF_E_STATUS_NOCHANS 13
263#define BRCMF_E_STATUS_CS_ABORT 15
264#define BRCMF_E_STATUS_ERROR 16
265
266#define BRCMF_E_REASON_INITIAL_ASSOC 0
267#define BRCMF_E_REASON_LOW_RSSI 1
268#define BRCMF_E_REASON_DEAUTH 2
269#define BRCMF_E_REASON_DISASSOC 3
270#define BRCMF_E_REASON_BCNS_LOST 4
271#define BRCMF_E_REASON_MINTXRATE 9
272#define BRCMF_E_REASON_TXFAIL 10
273
274#define BRCMF_E_REASON_FAST_ROAM_FAILED 5
275#define BRCMF_E_REASON_DIRECTED_ROAM 6
276#define BRCMF_E_REASON_TSPEC_REJECTED 7
277#define BRCMF_E_REASON_BETTER_AP 8
278
279#define BRCMF_E_PRUNE_ENCR_MISMATCH 1
280#define BRCMF_E_PRUNE_BCAST_BSSID 2
281#define BRCMF_E_PRUNE_MAC_DENY 3
282#define BRCMF_E_PRUNE_MAC_NA 4
283#define BRCMF_E_PRUNE_REG_PASSV 5
284#define BRCMF_E_PRUNE_SPCT_MGMT 6
285#define BRCMF_E_PRUNE_RADAR 7
286#define BRCMF_E_RSN_MISMATCH 8
287#define BRCMF_E_PRUNE_NO_COMMON_RATES 9
288#define BRCMF_E_PRUNE_BASIC_RATES 10
289#define BRCMF_E_PRUNE_CIPHER_NA 12
290#define BRCMF_E_PRUNE_KNOWN_STA 13
291#define BRCMF_E_PRUNE_WDS_PEER 15
292#define BRCMF_E_PRUNE_QBSS_LOAD 16
293#define BRCMF_E_PRUNE_HOME_AP 17
294
295#define BRCMF_E_SUP_OTHER 0
296#define BRCMF_E_SUP_DECRYPT_KEY_DATA 1
297#define BRCMF_E_SUP_BAD_UCAST_WEP128 2
298#define BRCMF_E_SUP_BAD_UCAST_WEP40 3
299#define BRCMF_E_SUP_UNSUP_KEY_LEN 4
300#define BRCMF_E_SUP_PW_KEY_CIPHER 5
301#define BRCMF_E_SUP_MSG3_TOO_MANY_IE 6
302#define BRCMF_E_SUP_MSG3_IE_MISMATCH 7
303#define BRCMF_E_SUP_NO_INSTALL_FLAG 8
304#define BRCMF_E_SUP_MSG3_NO_GTK 9
305#define BRCMF_E_SUP_GRP_KEY_CIPHER 10
306#define BRCMF_E_SUP_GRP_MSG1_NO_GTK 11
307#define BRCMF_E_SUP_GTK_DECRYPT_FAIL 12
308#define BRCMF_E_SUP_SEND_FAIL 13
309#define BRCMF_E_SUP_DEAUTH 14
310
311#define BRCMF_E_IF_ADD 1
312#define BRCMF_E_IF_DEL 2
313#define BRCMF_E_IF_CHANGE 3
314
315#define BRCMF_E_IF_ROLE_STA 0
316#define BRCMF_E_IF_ROLE_AP 1
317#define BRCMF_E_IF_ROLE_WDS 2
318
319#define BRCMF_E_LINK_BCN_LOSS 1
320#define BRCMF_E_LINK_DISASSOC 2
321#define BRCMF_E_LINK_ASSOC_REC 3
322#define BRCMF_E_LINK_BSSCFG_DIS 4
323
324/* The level of bus communication with the dongle */
325enum brcmf_bus_state {
326 BRCMF_BUS_DOWN, /* Not ready for frame transfers */
327 BRCMF_BUS_LOAD, /* Download access only (CPU reset) */
328 BRCMF_BUS_DATA /* Ready for frame transfers */
329};
330
331/* Pattern matching filter. Specifies an offset within received packets to
332 * start matching, the pattern to match, the size of the pattern, and a bitmask
333 * that indicates which bits within the pattern should be matched.
334 */
335struct brcmf_pkt_filter_pattern {
336 u32 offset; /* Offset within received packet to start pattern matching.
337 * Offset '0' is the first byte of the ethernet header.
338 */
339 u32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */
340 u8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts
341 * at offset 0. Pattern immediately follows mask.
342 */
343};
344
345/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
346struct brcmf_pkt_filter {
347 u32 id; /* Unique filter id, specified by app. */
348 u32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */
349 u32 negate_match; /* Negate the result of filter matches */
350 union { /* Filter definitions */
351 struct brcmf_pkt_filter_pattern pattern; /* Filter pattern */
352 } u;
353};
354
355/* IOVAR "pkt_filter_enable" parameter. */
356struct brcmf_pkt_filter_enable {
357 u32 id; /* Unique filter id */
358 u32 enable; /* Enable/disable bool */
359};
360
361/* BSS info structure
362 * Applications MUST CHECK ie_offset field and length field to access IEs and
363 * next bss_info structure in a vector (in struct brcmf_scan_results)
364 */
365struct brcmf_bss_info {
366 u32 version; /* version field */
367 u32 length; /* byte length of data in this record,
368 * starting at version and including IEs
369 */
370 u8 BSSID[ETH_ALEN];
371 u16 beacon_period; /* units are Kusec */
372 u16 capability; /* Capability information */
373 u8 SSID_len;
374 u8 SSID[32];
375 struct {
376 uint count; /* # rates in this set */
377 u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
378 } rateset; /* supported rates */
379 chanspec_t chanspec; /* chanspec for bss */
380 u16 atim_window; /* units are Kusec */
381 u8 dtim_period; /* DTIM period */
382 s16 RSSI; /* receive signal strength (in dBm) */
383 s8 phy_noise; /* noise (in dBm) */
384
385 u8 n_cap; /* BSS is 802.11N Capable */
386 u32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */
387 u8 ctl_ch; /* 802.11N BSS control channel number */
388 u32 reserved32[1]; /* Reserved for expansion of BSS properties */
389 u8 flags; /* flags */
390 u8 reserved[3]; /* Reserved for expansion of BSS properties */
391 u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */
392
393 u16 ie_offset; /* offset at which IEs start, from beginning */
394 u32 ie_length; /* byte length of Information Elements */
395 s16 SNR; /* average SNR of during frame reception */
396 /* Add new fields here */
397 /* variable length Information Elements */
398};
399
400struct brcmf_ssid {
401 u32 SSID_len;
402 unsigned char SSID[32];
403};
404
405struct brcmf_scan_params {
406 struct brcmf_ssid ssid; /* default: {0, ""} */
407 u8 bssid[ETH_ALEN]; /* default: bcast */
408 s8 bss_type; /* default: any,
409 * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
410 */
411 u8 scan_type; /* flags, 0 use default */
412 s32 nprobes; /* -1 use default, number of probes per channel */
413 s32 active_time; /* -1 use default, dwell time per channel for
414 * active scanning
415 */
416 s32 passive_time; /* -1 use default, dwell time per channel
417 * for passive scanning
418 */
419 s32 home_time; /* -1 use default, dwell time for the home channel
420 * between channel scans
421 */
422 s32 channel_num; /* count of channels and ssids that follow
423 *
424 * low half is count of channels in
425 * channel_list, 0 means default (use all
426 * available channels)
427 *
428 * high half is entries in struct brcmf_ssid
429 * array that follows channel_list, aligned for
430 * s32 (4 bytes) meaning an odd channel count
431 * implies a 2-byte pad between end of
432 * channel_list and first ssid
433 *
434 * if ssid count is zero, single ssid in the
435 * fixed parameter portion is assumed, otherwise
436 * ssid in the fixed portion is ignored
437 */
438 u16 channel_list[1]; /* list of chanspecs */
439};
440
441/* incremental scan struct */
442struct brcmf_iscan_params {
443 u32 version;
444 u16 action;
445 u16 scan_duration;
446 struct brcmf_scan_params params;
447};
448
449/* 3 fields + size of brcmf_scan_params, not including variable length array */
450#define BRCMF_ISCAN_PARAMS_FIXED_SIZE \
451 (offsetof(struct brcmf_iscan_params, params) + \
452 sizeof(struct brcmf_ssid))
453
454struct brcmf_scan_results {
455 u32 buflen;
456 u32 version;
457 u32 count;
458 struct brcmf_bss_info bss_info[1];
459};
460
461/* used for association with a specific BSSID and chanspec list */
462struct brcmf_assoc_params {
463 u8 bssid[ETH_ALEN]; /* 00:00:00:00:00:00: broadcast scan */
464 s32 chanspec_num; /* 0: all available channels,
465 * otherwise count of chanspecs in chanspec_list
466 */
467 chanspec_t chanspec_list[1]; /* list of chanspecs */
468};
469#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
470 (sizeof(struct brcmf_assoc_params) - sizeof(chanspec_t))
471
472/* used for join with or without a specific bssid and channel list */
473struct brcmf_join_params {
474 struct brcmf_ssid ssid;
475 struct brcmf_assoc_params params;
476};
477
478/* size of brcmf_scan_results not including variable length array */
479#define BRCMF_SCAN_RESULTS_FIXED_SIZE \
480 (sizeof(struct brcmf_scan_results) - sizeof(struct brcmf_bss_info))
481
482/* incremental scan results struct */
483struct brcmf_iscan_results {
484 u32 status;
485 struct brcmf_scan_results results;
486};
487
488/* size of brcmf_iscan_results not including variable length array */
489#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \
490 (BRCMF_SCAN_RESULTS_FIXED_SIZE + \
491 offsetof(struct brcmf_iscan_results, results))
492
493struct brcmf_wsec_key {
494 u32 index; /* key index */
495 u32 len; /* key length */
496 u8 data[WLAN_MAX_KEY_LEN]; /* key data */
497 u32 pad_1[18];
498 u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
499 u32 flags; /* misc flags */
500 u32 pad_2[2];
501 int pad_3;
502 int iv_initialized; /* has IV been initialized already? */
503 int pad_4;
504 /* Rx IV */
505 struct {
506 u32 hi; /* upper 32 bits of IV */
507 u16 lo; /* lower 16 bits of IV */
508 } rxiv;
509 u32 pad_5[2];
510 u8 ea[ETH_ALEN]; /* per station */
511};
512
513/* Used to get specific STA parameters */
514struct brcmf_scb_val {
515 u32 val;
516 u8 ea[ETH_ALEN];
517};
518
519/* channel encoding */
520struct brcmf_channel_info {
521 int hw_channel;
522 int target_channel;
523 int scan_channel;
524};
525
526/* Linux network driver ioctl encoding */
527struct brcmf_ioctl {
528 uint cmd; /* common ioctl definition */
529 void *buf; /* pointer to user buffer */
530 uint len; /* length of user buffer */
531 u8 set; /* get or set request (optional) */
532 uint used; /* bytes read or written (optional) */
533 uint needed; /* bytes needed (optional) */
534};
535
536/* Forward decls for struct brcmf_pub (see below) */
537struct brcmf_bus; /* device bus info */
538struct brcmf_proto; /* device communication protocol info */
539struct brcmf_info; /* device driver info */
540
541/* Common structure for module and instance linkage */
542struct brcmf_pub {
543 /* Linkage ponters */
544 struct brcmf_bus *bus;
545 struct brcmf_proto *prot;
546 struct brcmf_info *info;
547
548 /* Internal brcmf items */
549 bool up; /* Driver up/down (to OS) */
550 bool txoff; /* Transmit flow-controlled */
551 bool dongle_reset; /* true = DEVRESET put dongle into reset */
552 enum brcmf_bus_state busstate;
553 uint hdrlen; /* Total BRCMF header length (proto + bus) */
554 uint maxctl; /* Max size rxctl request from proto to bus */
555 uint rxsz; /* Rx buffer size bus module should use */
556 u8 wme_dp; /* wme discard priority */
557
558 /* Dongle media info */
559 bool iswl; /* Dongle-resident driver is wl */
560 unsigned long drv_version; /* Version of dongle-resident driver */
561 u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
562 struct dngl_stats dstats; /* Stats for dongle-based data */
563
564 /* Additional stats for the bus level */
565 unsigned long tx_packets; /* Data packets sent to dongle */
566 unsigned long tx_multicast; /* Multicast data packets sent to dongle */
567 unsigned long tx_errors; /* Errors in sending data to dongle */
568 unsigned long tx_ctlpkts; /* Control packets sent to dongle */
569 unsigned long tx_ctlerrs; /* Errors sending control frames to dongle */
570 unsigned long rx_packets; /* Packets sent up the network interface */
571 unsigned long rx_multicast; /* Multicast packets sent up the network
572 interface */
573 unsigned long rx_errors; /* Errors processing rx data packets */
574 unsigned long rx_ctlpkts; /* Control frames processed from dongle */
575 unsigned long rx_ctlerrs; /* Errors in processing rx control frames */
576 unsigned long rx_dropped; /* Packets dropped locally (no memory) */
577 unsigned long rx_flushed; /* Packets flushed due to
578 unscheduled sendup thread */
579 unsigned long wd_dpc_sched; /* Number of times dpc scheduled by
580 watchdog timer */
581
582 unsigned long rx_readahead_cnt; /* Number of packets where header read-ahead
583 was used. */
584 unsigned long tx_realloc; /* Number of tx packets we had to realloc for
585 headroom */
586 unsigned long fc_packets; /* Number of flow control pkts recvd */
587
588 /* Last error return */
589 int bcmerror;
590 uint tickcnt;
591
592 /* Last error from dongle */
593 int dongle_error;
594
595 /* Suspend disable flag flag */
596 int suspend_disable_flag; /* "1" to disable all extra powersaving
597 during suspend */
598 int in_suspend; /* flag set to 1 when early suspend called */
599 int dtim_skip; /* dtim skip , default 0 means wake each dtim */
600
601 /* Pkt filter defination */
602 char *pktfilter[100];
603 int pktfilter_count;
604
605 u8 country_code[BRCM_CNTRY_BUF_SZ];
606 char eventmask[BRCMF_EVENTING_MASK_LEN];
607
608};
609
610struct brcmf_if_event {
611 u8 ifidx;
612 u8 action;
613 u8 flags;
614 u8 bssidx;
615};
616
617struct brcmf_timeout {
618 u32 limit; /* Expiration time (usec) */
619 u32 increment; /* Current expiration increment (usec) */
620 u32 elapsed; /* Current elapsed time (usec) */
621 u32 tick; /* O/S tick time (usec) */
622};
623
624struct bcmevent_name {
625 uint event;
626 const char *name;
627};
628
629#if defined(CONFIG_PM_SLEEP)
630extern atomic_t brcmf_mmc_suspend;
631#define BRCMF_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
632#define _BRCMF_PM_RESUME_WAIT(a, b) do { \
633 int retry = 0; \
634 while (atomic_read(&brcmf_mmc_suspend) && retry++ != b) { \
635 wait_event_timeout(a, false, HZ/100); \
636 } \
637 } while (0)
638#define BRCMF_PM_RESUME_WAIT(a) _BRCMF_PM_RESUME_WAIT(a, 30)
639#define BRCMF_PM_RESUME_RETURN_ERROR(a) \
640 do { if (atomic_read(&brcmf_mmc_suspend)) return a; } while (0)
641
642#define BRCMF_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
643#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \
644 uint countdown = (us) + 9999; \
645 while ((exp) && (countdown >= 10000)) { \
646 wait_event_timeout(a, false, HZ/100); \
647 countdown -= 10000; \
648 } \
649 } while (0)
650
651#else
652
653#define BRCMF_PM_RESUME_WAIT_INIT(a)
654#define BRCMF_PM_RESUME_WAIT(a)
655#define BRCMF_PM_RESUME_RETURN_ERROR(a)
656
657#define BRCMF_SPINWAIT_SLEEP_INIT(a)
658#define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \
659 uint countdown = (us) + 9; \
660 while ((exp) && (countdown >= 10)) { \
661 udelay(10); \
662 countdown -= 10; \
663 } \
664 } while (0)
665
666#endif /* defined(CONFIG_PM_SLEEP) */
667
668/*
669 * Insmod parameters for debug/test
670 */
671
672/* Use interrupts */
673extern uint brcmf_intr;
674
675/* Use polling */
676extern uint brcmf_poll;
677
678/* ARP offload agent mode */
679extern uint brcmf_arp_mode;
680
681/* ARP offload enable */
682extern uint brcmf_arp_enable;
683
684/* Pkt filte enable control */
685extern uint brcmf_pkt_filter_enable;
686
687/* Pkt filter init setup */
688extern uint brcmf_pkt_filter_init;
689
690/* Pkt filter mode control */
691extern uint brcmf_master_mode;
692
693/* Roaming mode control */
694extern uint brcmf_roam;
695
696/* Roaming mode control */
697extern uint brcmf_radio_up;
698
699/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
700extern int brcmf_idletime;
701#define BRCMF_IDLETIME_TICKS 1
702
703/* SDIO Drive Strength */
704extern uint brcmf_sdiod_drive_strength;
705
706/* Override to force tx queueing all the time */
707extern uint brcmf_force_tx_queueing;
708
709#ifdef SDTEST
710/* Echo packet generator (SDIO), pkts/s */
711extern uint brcmf_pktgen;
712
713/* Echo packet len (0 => sawtooth, max 1800) */
714extern uint brcmf_pktgen_len;
715#define BRCMF_MAX_PKTGEN_LEN 1800
716#endif
717
718extern const struct bcmevent_name bcmevent_names[];
719extern const int bcmevent_names_size;
720
721
722static inline void MUTEX_LOCK_INIT(struct brcmf_pub *drvr)
723{
724}
725
726static inline void MUTEX_LOCK(struct brcmf_pub *drvr)
727{
728}
729
730static inline void MUTEX_UNLOCK(struct brcmf_pub *drvr)
731{
732}
733
734static inline void MUTEX_LOCK_SOFTAP_SET_INIT(struct brcmf_pub *drvr)
735{
736}
737
738static inline void MUTEX_LOCK_SOFTAP_SET(struct brcmf_pub *drvr)
739{
740}
741
742static inline void MUTEX_UNLOCK_SOFTAP_SET(struct brcmf_pub *drvr)
743{
744}
745
746static inline void MUTEX_LOCK_WL_SCAN_SET_INIT(void)
747{
748}
749
750static inline void MUTEX_LOCK_WL_SCAN_SET(void)
751{
752}
753
754static inline void MUTEX_UNLOCK_WL_SCAN_SET(void)
755{
756}
757
758/* Indication from bus module regarding presence/insertion of dongle.
759 * Return struct brcmf_pub pointer, used as handle to OS module in later calls.
760 * Returned structure should have bus and prot pointers filled in.
761 * bus_hdrlen specifies required headroom for bus module header.
762 */
763extern struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus,
764 uint bus_hdrlen);
765extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx);
766extern int brcmf_netdev_wait_pend8021x(struct net_device *dev);
767
768/* Indication from bus module regarding removal/absence of dongle */
769extern void brcmf_detach(struct brcmf_pub *drvr);
770
771/* Indication from bus module to change flow-control state */
772extern void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool on);
773
774extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
775 struct sk_buff *pkt, int prec);
776
777/* Receive frame for delivery to OS. Callee disposes of rxp. */
778extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
779 struct sk_buff *rxp, int numpkt);
780
781/* Return pointer to interface name */
782extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
783
784/* Notify tx completion */
785extern void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp,
786 bool success);
787
788/* Query ioctl */
789extern int brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx,
790 uint cmd, void *buf, uint len);
791
792/* OS independent layer functions */
793extern int brcmf_os_proto_block(struct brcmf_pub *drvr);
794extern int brcmf_os_proto_unblock(struct brcmf_pub *drvr);
795extern int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition,
796 bool *pending);
797extern int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr);
798extern unsigned int brcmf_os_get_ioctl_resp_timeout(void);
799extern void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec);
800#ifdef BCMDBG
801extern int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size);
802#endif /* BCMDBG */
803
804extern void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec);
805extern int brcmf_timeout_expired(struct brcmf_timeout *tmo);
806
807extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name);
808extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx,
809 void *pktdata, struct brcmf_event_msg *,
810 void **data_ptr);
811
812extern void brcmf_c_init(void);
813
814extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle,
815 char *name, u8 *mac_addr, u32 flags, u8 bssidx);
816extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx);
817
818/* Send packet to dongle via data channel */
819extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\
820 struct sk_buff *pkt);
821
822extern int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag);
823extern int brcmf_bus_start(struct brcmf_pub *drvr);
824
825extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg);
826extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg,
827 int enable, int master_mode);
828
829/* Linux network driver ioctl encoding */
830struct brcmf_c_ioctl {
831 uint cmd; /* common ioctl definition */
832 void *buf; /* pointer to user buffer */
833 uint len; /* length of user buffer */
834 bool set; /* get or set request (optional) */
835 uint used; /* bytes read or written (optional) */
836 uint needed; /* bytes needed (optional) */
837 uint driver; /* to identify target driver */
838};
839
840/* per-driver magic numbers */
841#define BRCMF_IOCTL_MAGIC 0x00444944
842
843/* bump this number if you change the ioctl interface */
844#define BRCMF_IOCTL_VERSION 1
845#define BRCMF_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */
846
847/* common ioctl definitions */
848#define BRCMF_GET_MAGIC 0
849#define BRCMF_GET_VERSION 1
850#define BRCMF_GET_VAR 2
851#define BRCMF_SET_VAR 3
852
853/* message levels */
854#define BRCMF_ERROR_VAL 0x0001
855#define BRCMF_TRACE_VAL 0x0002
856#define BRCMF_INFO_VAL 0x0004
857#define BRCMF_DATA_VAL 0x0008
858#define BRCMF_CTL_VAL 0x0010
859#define BRCMF_TIMER_VAL 0x0020
860#define BRCMF_HDRS_VAL 0x0040
861#define BRCMF_BYTES_VAL 0x0080
862#define BRCMF_INTR_VAL 0x0100
863#define BRCMF_GLOM_VAL 0x0400
864#define BRCMF_EVENT_VAL 0x0800
865#define BRCMF_BTA_VAL 0x1000
866#define BRCMF_ISCAN_VAL 0x2000
867
868#ifdef SDTEST
869/* For pktgen iovar */
870struct brcmf_pktgen {
871 uint version; /* To allow structure change tracking */
872 uint freq; /* Max ticks between tx/rx attempts */
873 uint count; /* Test packets to send/rcv each attempt */
874 uint print; /* Print counts every <print> attempts */
875 uint total; /* Total packets (or bursts) */
876 uint minlen; /* Minimum length of packets to send */
877 uint maxlen; /* Maximum length of packets to send */
878 uint numsent; /* Count of test packets sent */
879 uint numrcvd; /* Count of test packets received */
880 uint numfail; /* Count of test send failures */
881 uint mode; /* Test mode (type of test packets) */
882 uint stop; /* Stop after this many tx failures */
883};
884
885/* Version in case structure changes */
886#define BRCMF_PKTGEN_VERSION 2
887
888/* Type of test packets to use */
889#define BRCMF_PKTGEN_ECHO 1 /* Send echo requests */
890#define BRCMF_PKTGEN_SEND 2 /* Send discard packets */
891#define BRCMF_PKTGEN_RXBURST 3 /* Request dongle send N packets */
892#define BRCMF_PKTGEN_RECV 4 /* Continuous rx from continuous
893 tx dongle */
894#endif /* SDTEST */
895
896/* Enter idle immediately (no timeout) */
897#define BRCMF_IDLE_IMMEDIATE (-1)
898
899/* Values for idleclock iovar: other values are the sd_divisor to use
900 when idle */
901#define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change
902 when idle */
903
904#endif /* _BRCMF_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h b/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
new file mode 100644
index 00000000000..653cf0daa0e
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
@@ -0,0 +1,78 @@
1/*
2 * Copyright (c) 2010 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#ifndef _BRCMF_BUS_H_
18#define _BRCMF_BUS_H_
19
20/* Packet alignment for most efficient SDIO (can change based on platform) */
21#ifndef BRCMF_SDALIGN
22#define BRCMF_SDALIGN 32
23#endif
24#if !ISPOWEROF2(BRCMF_SDALIGN)
25#error BRCMF_SDALIGN is not a power of 2!
26#endif
27
28/*
29 * Exported from brcmf bus module (brcmf_usb, brcmf_sdio)
30 */
31
32/* dongle ram module parameter */
33extern int brcmf_dongle_memsize;
34
35/* Tx/Rx bounds module parameters */
36extern uint brcmf_txbound;
37extern uint brcmf_rxbound;
38
39/* Watchdog timer interval */
40extern uint brcmf_watchdog_ms;
41
42/* Indicate (dis)interest in finding dongles. */
43extern int brcmf_bus_register(void);
44extern void brcmf_bus_unregister(void);
45
46/* Stop bus module: clear pending frames, disable data flow */
47extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex);
48
49/* Initialize bus module: prepare for communication w/dongle */
50extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex);
51
52/* Send a data frame to the dongle. Callee disposes of txp. */
53extern int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *txp);
54
55/* Send/receive a control message to/from the dongle.
56 * Expects caller to enforce a single outstanding transaction.
57 */
58extern int
59brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen);
60
61extern int
62brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen);
63
64/* Check for and handle local prot-specific iovar commands */
65extern int brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name,
66 void *params, int plen, void *arg, int len,
67 bool set);
68
69/* Add bus dump output to a buffer */
70extern void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr,
71 struct brcmu_strbuf *strbuf);
72
73/* Clear any bus counters */
74extern void brcmf_bus_clearcounts(struct brcmf_pub *drvr);
75
76extern void brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick);
77
78#endif /* _BRCMF_BUS_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
new file mode 100644
index 00000000000..345acabe935
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
@@ -0,0 +1,502 @@
1/*
2 * Copyright (c) 2010 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#include <linux/types.h>
18#include <linux/netdevice.h>
19#include <linux/sched.h>
20#include <defs.h>
21
22#include <brcmu_utils.h>
23#include <brcmu_wifi.h>
24
25#include "dhd.h"
26#include "dhd_proto.h"
27#include "dhd_bus.h"
28#include "dhd_dbg.h"
29
30struct brcmf_proto_cdc_ioctl {
31 u32 cmd; /* ioctl command value */
32 u32 len; /* lower 16: output buflen;
33 * upper 16: input buflen (excludes header) */
34 u32 flags; /* flag defns given below */
35 u32 status; /* status code returned from the device */
36};
37
38/* Max valid buffer size that can be sent to the dongle */
39#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN)
40
41/* CDC flag definitions */
42#define CDCF_IOC_ERROR 0x01 /* 1=ioctl cmd failed */
43#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */
44#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */
45#define CDCF_IOC_IF_SHIFT 12
46#define CDCF_IOC_ID_MASK 0xFFFF0000 /* id an ioctl pairing */
47#define CDCF_IOC_ID_SHIFT 16 /* ID Mask shift bits */
48#define CDC_IOC_ID(flags) \
49 (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
50#define CDC_SET_IF_IDX(hdr, idx) \
51 ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \
52 ((idx) << CDCF_IOC_IF_SHIFT)))
53
54/*
55 * BDC header - Broadcom specific extension of CDC.
56 * Used on data packets to convey priority across USB.
57 */
58#define BDC_HEADER_LEN 4
59#define BDC_PROTO_VER 1 /* Protocol version */
60#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */
61#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */
62#define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */
63#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */
64#define BDC_PRIORITY_MASK 0x7
65#define BDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */
66#define BDC_FLAG2_IF_SHIFT 0
67
68#define BDC_GET_IF_IDX(hdr) \
69 ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
70#define BDC_SET_IF_IDX(hdr, idx) \
71 ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
72 ((idx) << BDC_FLAG2_IF_SHIFT)))
73
74struct brcmf_proto_bdc_header {
75 u8 flags;
76 u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */
77 u8 flags2;
78 u8 rssi;
79};
80
81
82#define RETRIES 2 /* # of retries to retrieve matching ioctl response */
83#define BUS_HEADER_LEN (16+BRCMF_SDALIGN) /* Must be atleast SDPCM_RESERVE
84 * (amount of header tha might be added)
85 * plus any space that might be needed
86 * for alignment padding.
87 */
88#define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for
89 * round off at the end of buffer
90 */
91
92struct brcmf_proto {
93 u16 reqid;
94 u8 pending;
95 u32 lastcmd;
96 u8 bus_header[BUS_HEADER_LEN];
97 struct brcmf_proto_cdc_ioctl msg;
98 unsigned char buf[BRCMF_C_IOCTL_MAXLEN + ROUND_UP_MARGIN];
99};
100
101static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)
102{
103 struct brcmf_proto *prot = drvr->prot;
104 int len = le32_to_cpu(prot->msg.len) +
105 sizeof(struct brcmf_proto_cdc_ioctl);
106
107 BRCMF_TRACE(("%s: Enter\n", __func__));
108
109 /* NOTE : cdc->msg.len holds the desired length of the buffer to be
110 * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
111 * is actually sent to the dongle
112 */
113 if (len > CDC_MAX_MSG_SIZE)
114 len = CDC_MAX_MSG_SIZE;
115
116 /* Send request */
117 return brcmf_sdbrcm_bus_txctl(drvr->bus, (unsigned char *)&prot->msg,
118 len);
119}
120
121static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
122{
123 int ret;
124 struct brcmf_proto *prot = drvr->prot;
125
126 BRCMF_TRACE(("%s: Enter\n", __func__));
127
128 do {
129 ret = brcmf_sdbrcm_bus_rxctl(drvr->bus,
130 (unsigned char *)&prot->msg,
131 len + sizeof(struct brcmf_proto_cdc_ioctl));
132 if (ret < 0)
133 break;
134 } while (CDC_IOC_ID(le32_to_cpu(prot->msg.flags)) != id);
135
136 return ret;
137}
138
139int
140brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
141 void *buf, uint len)
142{
143 struct brcmf_proto *prot = drvr->prot;
144 struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
145 void *info;
146 int ret = 0, retries = 0;
147 u32 id, flags = 0;
148
149 BRCMF_TRACE(("%s: Enter\n", __func__));
150 BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
151
152 /* Respond "bcmerror" and "bcmerrorstr" with local cache */
153 if (cmd == BRCMF_C_GET_VAR && buf) {
154 if (!strcmp((char *)buf, "bcmerrorstr")) {
155 strncpy((char *)buf, "bcm_error",
156 BCME_STRLEN);
157 goto done;
158 } else if (!strcmp((char *)buf, "bcmerror")) {
159 *(int *)buf = drvr->dongle_error;
160 goto done;
161 }
162 }
163
164 memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
165
166 msg->cmd = cpu_to_le32(cmd);
167 msg->len = cpu_to_le32(len);
168 msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
169 CDC_SET_IF_IDX(msg, ifidx);
170 msg->flags = cpu_to_le32(msg->flags);
171
172 if (buf)
173 memcpy(prot->buf, buf, len);
174
175 ret = brcmf_proto_cdc_msg(drvr);
176 if (ret < 0) {
177 BRCMF_ERROR(("brcmf_proto_cdc_query_ioctl: brcmf_proto_cdc_msg "
178 "failed w/status %d\n", ret));
179 goto done;
180 }
181
182retry:
183 /* wait for interrupt and get first fragment */
184 ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len);
185 if (ret < 0)
186 goto done;
187
188 flags = le32_to_cpu(msg->flags);
189 id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
190
191 if ((id < prot->reqid) && (++retries < RETRIES))
192 goto retry;
193 if (id != prot->reqid) {
194 BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
195 brcmf_ifname(drvr, ifidx), __func__, id,
196 prot->reqid));
197 ret = -EINVAL;
198 goto done;
199 }
200
201 /* Check info buffer */
202 info = (void *)&msg[1];
203
204 /* Copy info buffer */
205 if (buf) {
206 if (ret < (int)len)
207 len = ret;
208 memcpy(buf, info, len);
209 }
210
211 /* Check the ERROR flag */
212 if (flags & CDCF_IOC_ERROR) {
213 ret = le32_to_cpu(msg->status);
214 /* Cache error from dongle */
215 drvr->dongle_error = ret;
216 }
217
218done:
219 return ret;
220}
221
222int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd,
223 void *buf, uint len)
224{
225 struct brcmf_proto *prot = drvr->prot;
226 struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
227 int ret = 0;
228 u32 flags, id;
229
230 BRCMF_TRACE(("%s: Enter\n", __func__));
231 BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
232
233 memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl));
234
235 msg->cmd = cpu_to_le32(cmd);
236 msg->len = cpu_to_le32(len);
237 msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET;
238 CDC_SET_IF_IDX(msg, ifidx);
239 msg->flags = cpu_to_le32(msg->flags);
240
241 if (buf)
242 memcpy(prot->buf, buf, len);
243
244 ret = brcmf_proto_cdc_msg(drvr);
245 if (ret < 0)
246 goto done;
247
248 ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len);
249 if (ret < 0)
250 goto done;
251
252 flags = le32_to_cpu(msg->flags);
253 id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
254
255 if (id != prot->reqid) {
256 BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
257 brcmf_ifname(drvr, ifidx), __func__, id,
258 prot->reqid));
259 ret = -EINVAL;
260 goto done;
261 }
262
263 /* Check the ERROR flag */
264 if (flags & CDCF_IOC_ERROR) {
265 ret = le32_to_cpu(msg->status);
266 /* Cache error from dongle */
267 drvr->dongle_error = ret;
268 }
269
270done:
271 return ret;
272}
273
274int
275brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx, struct brcmf_ioctl *ioc,
276 void *buf, int len)
277{
278 struct brcmf_proto *prot = drvr->prot;
279 int ret = -1;
280
281 if (drvr->busstate == BRCMF_BUS_DOWN) {
282 BRCMF_ERROR(("%s : bus is down. we have nothing to do\n",
283 __func__));
284 return ret;
285 }
286 brcmf_os_proto_block(drvr);
287
288 BRCMF_TRACE(("%s: Enter\n", __func__));
289
290 if (len > BRCMF_C_IOCTL_MAXLEN)
291 goto done;
292
293 if (prot->pending == true) {
294 BRCMF_TRACE(("CDC packet is pending!!!! cmd=0x%x (%lu) "
295 "lastcmd=0x%x (%lu)\n",
296 ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd,
297 (unsigned long)prot->lastcmd));
298 if ((ioc->cmd == BRCMF_C_SET_VAR) ||
299 (ioc->cmd == BRCMF_C_GET_VAR))
300 BRCMF_TRACE(("iovar cmd=%s\n", (char *)buf));
301
302 goto done;
303 }
304
305 prot->pending = true;
306 prot->lastcmd = ioc->cmd;
307 if (ioc->set)
308 ret = brcmf_proto_cdc_set_ioctl(drvr, ifidx, ioc->cmd,
309 buf, len);
310 else {
311 ret = brcmf_proto_cdc_query_ioctl(drvr, ifidx, ioc->cmd,
312 buf, len);
313 if (ret > 0)
314 ioc->used = ret - sizeof(struct brcmf_proto_cdc_ioctl);
315 }
316
317 /* Too many programs assume ioctl() returns 0 on success */
318 if (ret >= 0)
319 ret = 0;
320 else {
321 struct brcmf_proto_cdc_ioctl *msg = &prot->msg;
322 /* len == needed when set/query fails from dongle */
323 ioc->needed = le32_to_cpu(msg->len);
324 }
325
326 /* Intercept the wme_dp ioctl here */
327 if (!ret && ioc->cmd == BRCMF_C_SET_VAR &&
328 !strcmp(buf, "wme_dp")) {
329 int slen, val = 0;
330
331 slen = strlen("wme_dp") + 1;
332 if (len >= (int)(slen + sizeof(int)))
333 memcpy(&val, (char *)buf + slen, sizeof(int));
334 drvr->wme_dp = (u8) le32_to_cpu(val);
335 }
336
337 prot->pending = false;
338
339done:
340 brcmf_os_proto_unblock(drvr);
341
342 return ret;
343}
344
345#define PKTSUMNEEDED(skb) \
346 (((struct sk_buff *)(skb))->ip_summed == CHECKSUM_PARTIAL)
347#define PKTSETSUMGOOD(skb, x) \
348 (((struct sk_buff *)(skb))->ip_summed = \
349 ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE))
350
351void brcmf_proto_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf)
352{
353 brcmu_bprintf(strbuf, "Protocol CDC: reqid %d\n", drvr->prot->reqid);
354}
355
356void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
357 struct sk_buff *pktbuf)
358{
359 struct brcmf_proto_bdc_header *h;
360
361 BRCMF_TRACE(("%s: Enter\n", __func__));
362
363 /* Push BDC header used to convey priority for buses that don't */
364
365 skb_push(pktbuf, BDC_HEADER_LEN);
366
367 h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
368
369 h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
370 if (PKTSUMNEEDED(pktbuf))
371 h->flags |= BDC_FLAG_SUM_NEEDED;
372
373 h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
374 h->flags2 = 0;
375 h->rssi = 0;
376 BDC_SET_IF_IDX(h, ifidx);
377}
378
379int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx,
380 struct sk_buff *pktbuf)
381{
382 struct brcmf_proto_bdc_header *h;
383
384 BRCMF_TRACE(("%s: Enter\n", __func__));
385
386 /* Pop BDC header used to convey priority for buses that don't */
387
388 if (pktbuf->len < BDC_HEADER_LEN) {
389 BRCMF_ERROR(("%s: rx data too short (%d < %d)\n", __func__,
390 pktbuf->len, BDC_HEADER_LEN));
391 return -EBADE;
392 }
393
394 h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
395
396 *ifidx = BDC_GET_IF_IDX(h);
397 if (*ifidx >= BRCMF_MAX_IFS) {
398 BRCMF_ERROR(("%s: rx data ifnum out of range (%d)\n",
399 __func__, *ifidx));
400 return -EBADE;
401 }
402
403 if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
404 BDC_PROTO_VER) {
405 BRCMF_ERROR(("%s: non-BDC packet received, flags 0x%x\n",
406 brcmf_ifname(drvr, *ifidx), h->flags));
407 return -EBADE;
408 }
409
410 if (h->flags & BDC_FLAG_SUM_GOOD) {
411 BRCMF_INFO(("%s: BDC packet received with good rx-csum, "
412 "flags 0x%x\n",
413 brcmf_ifname(drvr, *ifidx), h->flags));
414 PKTSETSUMGOOD(pktbuf, true);
415 }
416
417 pktbuf->priority = h->priority & BDC_PRIORITY_MASK;
418
419 skb_pull(pktbuf, BDC_HEADER_LEN);
420
421 return 0;
422}
423
424int brcmf_proto_attach(struct brcmf_pub *drvr)
425{
426 struct brcmf_proto *cdc;
427
428 cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC);
429 if (!cdc) {
430 BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
431 goto fail;
432 }
433
434 /* ensure that the msg buf directly follows the cdc msg struct */
435 if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) {
436 BRCMF_ERROR(("struct brcmf_proto is not correctly defined\n"));
437 goto fail;
438 }
439
440 drvr->prot = cdc;
441 drvr->hdrlen += BDC_HEADER_LEN;
442 drvr->maxctl = BRCMF_C_IOCTL_MAXLEN +
443 sizeof(struct brcmf_proto_cdc_ioctl) + ROUND_UP_MARGIN;
444 return 0;
445
446fail:
447 kfree(cdc);
448 return -ENOMEM;
449}
450
451/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */
452void brcmf_proto_detach(struct brcmf_pub *drvr)
453{
454 kfree(drvr->prot);
455 drvr->prot = NULL;
456}
457
458void brcmf_proto_dstats(struct brcmf_pub *drvr)
459{
460 /* No stats from dongle added yet, copy bus stats */
461 drvr->dstats.tx_packets = drvr->tx_packets;
462 drvr->dstats.tx_errors = drvr->tx_errors;
463 drvr->dstats.rx_packets = drvr->rx_packets;
464 drvr->dstats.rx_errors = drvr->rx_errors;
465 drvr->dstats.rx_dropped = drvr->rx_dropped;
466 drvr->dstats.multicast = drvr->rx_multicast;
467 return;
468}
469
470int brcmf_proto_init(struct brcmf_pub *drvr)
471{
472 int ret = 0;
473 char buf[128];
474
475 BRCMF_TRACE(("%s: Enter\n", __func__));
476
477 brcmf_os_proto_block(drvr);
478
479 /* Get the device MAC address */
480 strcpy(buf, "cur_etheraddr");
481 ret = brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR,
482 buf, sizeof(buf));
483 if (ret < 0) {
484 brcmf_os_proto_unblock(drvr);
485 return ret;
486 }
487 memcpy(drvr->mac, buf, ETH_ALEN);
488
489 brcmf_os_proto_unblock(drvr);
490
491 ret = brcmf_c_preinit_ioctls(drvr);
492
493 /* Always assumes wl for now */
494 drvr->iswl = true;
495
496 return ret;
497}
498
499void brcmf_proto_stop(struct brcmf_pub *drvr)
500{
501 /* Nothing to do for CDC */
502}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_common.c b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
new file mode 100644
index 00000000000..fdec4683c42
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
@@ -0,0 +1,1196 @@
1/*
2 * Copyright (c) 2010 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#include <linux/kernel.h>
17#include <linux/string.h>
18#include <linux/sched.h>
19#include <linux/netdevice.h>
20#include <asm/unaligned.h>
21#include <defs.h>
22#include <brcmu_wifi.h>
23#include <brcmu_utils.h>
24#include "dhd.h"
25#include "dhd_bus.h"
26#include "dhd_proto.h"
27#include "dhd_dbg.h"
28
29#define BRCM_OUI "\x00\x10\x18"
30#define DOT11_OUI_LEN 3
31#define BCMILCP_BCM_SUBTYPE_EVENT 1
32#define PKTFILTER_BUF_SIZE 2048
33
34int brcmf_msg_level;
35
36#define MSGTRACE_VERSION 1
37
38#ifdef BCMDBG
39const char brcmf_version[] =
40"Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on " __DATE__
41" at " __TIME__;
42#else
43const char brcmf_version[] = "Dongle Host Driver, version " BRCMF_VERSION_STR;
44#endif
45
46/* IOVar table */
47enum {
48 IOV_VERSION = 1,
49 IOV_MSGLEVEL,
50 IOV_BCMERRORSTR,
51 IOV_BCMERROR,
52 IOV_DUMP,
53 IOV_CLEARCOUNTS,
54 IOV_LOGDUMP,
55 IOV_LOGCAL,
56 IOV_LOGSTAMP,
57 IOV_GPIOOB,
58 IOV_IOCTLTIMEOUT,
59 IOV_LAST
60};
61
62const struct brcmu_iovar brcmf_iovars[] = {
63 {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(brcmf_version)}
64 ,
65#ifdef BCMDBG
66 {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0}
67 ,
68#endif /* BCMDBG */
69 {"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN}
70 ,
71 {"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0}
72 ,
73 {"dump", IOV_DUMP, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN}
74 ,
75 {"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0}
76 ,
77 {"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0}
78 ,
79 {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0}
80 ,
81 {NULL, 0, 0, 0, 0}
82};
83
84/* Message trace header */
85struct msgtrace_hdr {
86 u8 version;
87 u8 spare;
88 u16 len; /* Len of the trace */
89 u32 seqnum; /* Sequence number of message. Useful
90 * if the messsage has been lost
91 * because of DMA error or a bus reset
92 * (ex: SDIO Func2)
93 */
94 u32 discarded_bytes; /* Number of discarded bytes because of
95 trace overflow */
96 u32 discarded_printf; /* Number of discarded printf
97 because of trace overflow */
98} __packed;
99
100void brcmf_c_init(void)
101{
102 /* Init global variables at run-time, not as part of the declaration.
103 * This is required to support init/de-init of the driver.
104 * Initialization
105 * of globals as part of the declaration results in non-deterministic
106 * behaviour since the value of the globals may be different on the
107 * first time that the driver is initialized vs subsequent
108 * initializations.
109 */
110 brcmf_msg_level = BRCMF_ERROR_VAL;
111}
112
113static int brcmf_c_dump(struct brcmf_pub *drvr, char *buf, int buflen)
114{
115 struct brcmu_strbuf b;
116 struct brcmu_strbuf *strbuf = &b;
117
118 brcmu_binit(strbuf, buf, buflen);
119
120 /* Base info */
121 brcmu_bprintf(strbuf, "%s\n", brcmf_version);
122 brcmu_bprintf(strbuf, "\n");
123 brcmu_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n",
124 drvr->up, drvr->txoff, drvr->busstate);
125 brcmu_bprintf(strbuf, "pub.hdrlen %d pub.maxctl %d pub.rxsz %d\n",
126 drvr->hdrlen, drvr->maxctl, drvr->rxsz);
127 brcmu_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %pM\n",
128 drvr->iswl, drvr->drv_version, &drvr->mac);
129 brcmu_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", drvr->bcmerror,
130 drvr->tickcnt);
131
132 brcmu_bprintf(strbuf, "dongle stats:\n");
133 brcmu_bprintf(strbuf,
134 "tx_packets %ld tx_bytes %ld tx_errors %ld tx_dropped %ld\n",
135 drvr->dstats.tx_packets, drvr->dstats.tx_bytes,
136 drvr->dstats.tx_errors, drvr->dstats.tx_dropped);
137 brcmu_bprintf(strbuf,
138 "rx_packets %ld rx_bytes %ld rx_errors %ld rx_dropped %ld\n",
139 drvr->dstats.rx_packets, drvr->dstats.rx_bytes,
140 drvr->dstats.rx_errors, drvr->dstats.rx_dropped);
141 brcmu_bprintf(strbuf, "multicast %ld\n", drvr->dstats.multicast);
142
143 brcmu_bprintf(strbuf, "bus stats:\n");
144 brcmu_bprintf(strbuf, "tx_packets %ld tx_multicast %ld tx_errors %ld\n",
145 drvr->tx_packets, drvr->tx_multicast, drvr->tx_errors);
146 brcmu_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n",
147 drvr->tx_ctlpkts, drvr->tx_ctlerrs);
148 brcmu_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld\n",
149 drvr->rx_packets, drvr->rx_multicast, drvr->rx_errors);
150 brcmu_bprintf(strbuf,
151 "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld rx_flushed %ld\n",
152 drvr->rx_ctlpkts, drvr->rx_ctlerrs, drvr->rx_dropped,
153 drvr->rx_flushed);
154 brcmu_bprintf(strbuf,
155 "rx_readahead_cnt %ld tx_realloc %ld fc_packets %ld\n",
156 drvr->rx_readahead_cnt, drvr->tx_realloc, drvr->fc_packets);
157 brcmu_bprintf(strbuf, "wd_dpc_sched %ld\n", drvr->wd_dpc_sched);
158 brcmu_bprintf(strbuf, "\n");
159
160 /* Add any prot info */
161 brcmf_proto_dump(drvr, strbuf);
162 brcmu_bprintf(strbuf, "\n");
163
164 /* Add any bus info */
165 brcmf_sdbrcm_bus_dump(drvr, strbuf);
166
167 return !strbuf->size ? -EOVERFLOW : 0;
168}
169
170static int
171brcmf_c_doiovar(struct brcmf_pub *drvr, const struct brcmu_iovar *vi,
172 u32 actionid, const char *name, void *params, int plen,
173 void *arg, int len, int val_size)
174{
175 int bcmerror = 0;
176 s32 int_val = 0;
177
178 BRCMF_TRACE(("%s: Enter\n", __func__));
179
180 bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
181 if (bcmerror != 0)
182 goto exit;
183
184 if (plen >= (int)sizeof(int_val))
185 memcpy(&int_val, params, sizeof(int_val));
186
187 switch (actionid) {
188 case IOV_GVAL(IOV_VERSION):
189 /* Need to have checked buffer length */
190 strncpy((char *)arg, brcmf_version, len);
191 break;
192
193 case IOV_GVAL(IOV_MSGLEVEL):
194 int_val = (s32) brcmf_msg_level;
195 memcpy(arg, &int_val, val_size);
196 break;
197
198 case IOV_SVAL(IOV_MSGLEVEL):
199 brcmf_msg_level = int_val;
200 break;
201
202 case IOV_GVAL(IOV_BCMERRORSTR):
203 strncpy((char *)arg, "bcm_error",
204 BCME_STRLEN);
205 ((char *)arg)[BCME_STRLEN - 1] = 0x00;
206 break;
207
208 case IOV_GVAL(IOV_BCMERROR):
209 int_val = (s32) drvr->bcmerror;
210 memcpy(arg, &int_val, val_size);
211 break;
212
213 case IOV_GVAL(IOV_DUMP):
214 bcmerror = brcmf_c_dump(drvr, arg, len);
215 break;
216
217 case IOV_SVAL(IOV_CLEARCOUNTS):
218 drvr->tx_packets = drvr->rx_packets = 0;
219 drvr->tx_errors = drvr->rx_errors = 0;
220 drvr->tx_ctlpkts = drvr->rx_ctlpkts = 0;
221 drvr->tx_ctlerrs = drvr->rx_ctlerrs = 0;
222 drvr->rx_dropped = 0;
223 drvr->rx_readahead_cnt = 0;
224 drvr->tx_realloc = 0;
225 drvr->wd_dpc_sched = 0;
226 memset(&drvr->dstats, 0, sizeof(drvr->dstats));
227 brcmf_bus_clearcounts(drvr);
228 break;
229
230 case IOV_GVAL(IOV_IOCTLTIMEOUT):{
231 int_val = (s32) brcmf_os_get_ioctl_resp_timeout();
232 memcpy(arg, &int_val, sizeof(int_val));
233 break;
234 }
235
236 case IOV_SVAL(IOV_IOCTLTIMEOUT):{
237 if (int_val <= 0)
238 bcmerror = -EINVAL;
239 else
240 brcmf_os_set_ioctl_resp_timeout((unsigned int)
241 int_val);
242 break;
243 }
244
245 default:
246 bcmerror = -ENOTSUPP;
247 break;
248 }
249
250exit:
251 return bcmerror;
252}
253
254bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
255 struct sk_buff *pkt, int prec)
256{
257 struct sk_buff *p;
258 int eprec = -1; /* precedence to evict from */
259 bool discard_oldest;
260
261 /* Fast case, precedence queue is not full and we are also not
262 * exceeding total queue length
263 */
264 if (!pktq_pfull(q, prec) && !pktq_full(q)) {
265 brcmu_pktq_penq(q, prec, pkt);
266 return true;
267 }
268
269 /* Determine precedence from which to evict packet, if any */
270 if (pktq_pfull(q, prec))
271 eprec = prec;
272 else if (pktq_full(q)) {
273 p = brcmu_pktq_peek_tail(q, &eprec);
274 if (eprec > prec)
275 return false;
276 }
277
278 /* Evict if needed */
279 if (eprec >= 0) {
280 /* Detect queueing to unconfigured precedence */
281 discard_oldest = AC_BITMAP_TST(drvr->wme_dp, eprec);
282 if (eprec == prec && !discard_oldest)
283 return false; /* refuse newer (incoming) packet */
284 /* Evict packet according to discard policy */
285 p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
286 brcmu_pktq_pdeq_tail(q, eprec);
287 if (p == NULL) {
288 BRCMF_ERROR(("%s: brcmu_pktq_penq() failed, oldest %d.",
289 __func__, discard_oldest));
290 }
291 brcmu_pkt_buf_free_skb(p);
292 }
293
294 /* Enqueue */
295 p = brcmu_pktq_penq(q, prec, pkt);
296 if (p == NULL) {
297 BRCMF_ERROR(("%s: brcmu_pktq_penq() failed.", __func__));
298 }
299
300 return p != NULL;
301}
302
303static int
304brcmf_c_iovar_op(struct brcmf_pub *drvr, const char *name,
305 void *params, int plen, void *arg, int len, bool set)
306{
307 int bcmerror = 0;
308 int val_size;
309 const struct brcmu_iovar *vi = NULL;
310 u32 actionid;
311
312 BRCMF_TRACE(("%s: Enter\n", __func__));
313
314 if (name == NULL || len <= 0)
315 return -EINVAL;
316
317 /* Set does not take qualifiers */
318 if (set && (params || plen))
319 return -EINVAL;
320
321 /* Get must have return space;*/
322 if (!set && !(arg && len))
323 return -EINVAL;
324
325 vi = brcmu_iovar_lookup(brcmf_iovars, name);
326 if (vi == NULL) {
327 bcmerror = -ENOTSUPP;
328 goto exit;
329 }
330
331 BRCMF_CTL(("%s: %s %s, len %d plen %d\n", __func__,
332 name, (set ? "set" : "get"), len, plen));
333
334 /* set up 'params' pointer in case this is a set command so that
335 * the convenience int and bool code can be common to set and get
336 */
337 if (params == NULL) {
338 params = arg;
339 plen = len;
340 }
341
342 if (vi->type == IOVT_VOID)
343 val_size = 0;
344 else if (vi->type == IOVT_BUFFER)
345 val_size = len;
346 else
347 /* all other types are integer sized */
348 val_size = sizeof(int);
349
350 actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
351 bcmerror =
352 brcmf_c_doiovar(drvr, vi, actionid, name, params, plen, arg, len,
353 val_size);
354
355exit:
356 return bcmerror;
357}
358
359int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc, void *buf,
360 uint buflen)
361{
362 int bcmerror = 0;
363
364 BRCMF_TRACE(("%s: Enter\n", __func__));
365
366 if (!buf)
367 return -EINVAL;
368
369 switch (ioc->cmd) {
370 case BRCMF_GET_MAGIC:
371 if (buflen < sizeof(int))
372 bcmerror = -EOVERFLOW;
373 else
374 *(int *)buf = BRCMF_IOCTL_MAGIC;
375 break;
376
377 case BRCMF_GET_VERSION:
378 if (buflen < sizeof(int))
379 bcmerror = -EOVERFLOW;
380 else
381 *(int *)buf = BRCMF_IOCTL_VERSION;
382 break;
383
384 case BRCMF_GET_VAR:
385 case BRCMF_SET_VAR:{
386 char *arg;
387 uint arglen;
388
389 /* scan past the name to any arguments */
390 for (arg = buf, arglen = buflen; *arg && arglen;
391 arg++, arglen--)
392 ;
393
394 if (*arg) {
395 bcmerror = -EOVERFLOW;
396 break;
397 }
398
399 /* account for the NUL terminator */
400 arg++, arglen--;
401
402 /* call with the appropriate arguments */
403 if (ioc->cmd == BRCMF_GET_VAR)
404 bcmerror = brcmf_c_iovar_op(drvr, buf, arg,
405 arglen, buf, buflen, IOV_GET);
406 else
407 bcmerror =
408 brcmf_c_iovar_op(drvr, buf, NULL, 0, arg,
409 arglen, IOV_SET);
410 if (bcmerror != -ENOTSUPP)
411 break;
412
413 /* if still not found, try bus module */
414 if (ioc->cmd == BRCMF_GET_VAR)
415 bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr,
416 buf, arg, arglen, buf, buflen,
417 IOV_GET);
418 else
419 bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr,
420 buf, NULL, 0, arg, arglen,
421 IOV_SET);
422
423 break;
424 }
425
426 default:
427 bcmerror = -ENOTSUPP;
428 }
429
430 return bcmerror;
431}
432
433#ifdef SHOW_EVENTS
434static void
435brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data)
436{
437 uint i, status, reason;
438 bool group = false, flush_txq = false, link = false;
439 char *auth_str, *event_name;
440 unsigned char *buf;
441 char err_msg[256], eabuf[ETHER_ADDR_STR_LEN];
442 static struct {
443 uint event;
444 char *event_name;
445 } event_names[] = {
446 {
447 BRCMF_E_SET_SSID, "SET_SSID"}, {
448 BRCMF_E_JOIN, "JOIN"}, {
449 BRCMF_E_START, "START"}, {
450 BRCMF_E_AUTH, "AUTH"}, {
451 BRCMF_E_AUTH_IND, "AUTH_IND"}, {
452 BRCMF_E_DEAUTH, "DEAUTH"}, {
453 BRCMF_E_DEAUTH_IND, "DEAUTH_IND"}, {
454 BRCMF_E_ASSOC, "ASSOC"}, {
455 BRCMF_E_ASSOC_IND, "ASSOC_IND"}, {
456 BRCMF_E_REASSOC, "REASSOC"}, {
457 BRCMF_E_REASSOC_IND, "REASSOC_IND"}, {
458 BRCMF_E_DISASSOC, "DISASSOC"}, {
459 BRCMF_E_DISASSOC_IND, "DISASSOC_IND"}, {
460 BRCMF_E_QUIET_START, "START_QUIET"}, {
461 BRCMF_E_QUIET_END, "END_QUIET"}, {
462 BRCMF_E_BEACON_RX, "BEACON_RX"}, {
463 BRCMF_E_LINK, "LINK"}, {
464 BRCMF_E_MIC_ERROR, "MIC_ERROR"}, {
465 BRCMF_E_NDIS_LINK, "NDIS_LINK"}, {
466 BRCMF_E_ROAM, "ROAM"}, {
467 BRCMF_E_TXFAIL, "TXFAIL"}, {
468 BRCMF_E_PMKID_CACHE, "PMKID_CACHE"}, {
469 BRCMF_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, {
470 BRCMF_E_PRUNE, "PRUNE"}, {
471 BRCMF_E_AUTOAUTH, "AUTOAUTH"}, {
472 BRCMF_E_EAPOL_MSG, "EAPOL_MSG"}, {
473 BRCMF_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
474 BRCMF_E_ADDTS_IND, "ADDTS_IND"}, {
475 BRCMF_E_DELTS_IND, "DELTS_IND"}, {
476 BRCMF_E_BCNSENT_IND, "BCNSENT_IND"}, {
477 BRCMF_E_BCNRX_MSG, "BCNRX_MSG"}, {
478 BRCMF_E_BCNLOST_MSG, "BCNLOST_MSG"}, {
479 BRCMF_E_ROAM_PREP, "ROAM_PREP"}, {
480 BRCMF_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, {
481 BRCMF_E_PFN_NET_LOST, "PNO_NET_LOST"}, {
482 BRCMF_E_RESET_COMPLETE, "RESET_COMPLETE"}, {
483 BRCMF_E_JOIN_START, "JOIN_START"}, {
484 BRCMF_E_ROAM_START, "ROAM_START"}, {
485 BRCMF_E_ASSOC_START, "ASSOC_START"}, {
486 BRCMF_E_IBSS_ASSOC, "IBSS_ASSOC"}, {
487 BRCMF_E_RADIO, "RADIO"}, {
488 BRCMF_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, {
489 BRCMF_E_PROBREQ_MSG, "PROBREQ_MSG"}, {
490 BRCMF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, {
491 BRCMF_E_PSK_SUP, "PSK_SUP"}, {
492 BRCMF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, {
493 BRCMF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, {
494 BRCMF_E_ICV_ERROR, "ICV_ERROR"}, {
495 BRCMF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, {
496 BRCMF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, {
497 BRCMF_E_TRACE, "TRACE"}, {
498 BRCMF_E_ACTION_FRAME, "ACTION FRAME"}, {
499 BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, {
500 BRCMF_E_IF, "IF"}, {
501 BRCMF_E_RSSI, "RSSI"}, {
502 BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}
503 };
504 uint event_type, flags, auth_type, datalen;
505 event_type = be32_to_cpu(event->event_type);
506 flags = be16_to_cpu(event->flags);
507 status = be32_to_cpu(event->status);
508 reason = be32_to_cpu(event->reason);
509 auth_type = be32_to_cpu(event->auth_type);
510 datalen = be32_to_cpu(event->datalen);
511 /* debug dump of event messages */
512 sprintf(eabuf, "%pM", event->addr);
513
514 event_name = "UNKNOWN";
515 for (i = 0; i < ARRAY_SIZE(event_names); i++) {
516 if (event_names[i].event == event_type)
517 event_name = event_names[i].event_name;
518 }
519
520 BRCMF_EVENT(("EVENT: %s, event ID = %d\n", event_name, event_type));
521 BRCMF_EVENT(("flags 0x%04x, status %d, reason %d, auth_type %d"
522 " MAC %s\n", flags, status, reason, auth_type, eabuf));
523
524 if (flags & BRCMF_EVENT_MSG_LINK)
525 link = true;
526 if (flags & BRCMF_EVENT_MSG_GROUP)
527 group = true;
528 if (flags & BRCMF_EVENT_MSG_FLUSHTXQ)
529 flush_txq = true;
530
531 switch (event_type) {
532 case BRCMF_E_START:
533 case BRCMF_E_DEAUTH:
534 case BRCMF_E_DISASSOC:
535 BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
536 break;
537
538 case BRCMF_E_ASSOC_IND:
539 case BRCMF_E_REASSOC_IND:
540 BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
541 break;
542
543 case BRCMF_E_ASSOC:
544 case BRCMF_E_REASSOC:
545 if (status == BRCMF_E_STATUS_SUCCESS) {
546 BRCMF_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n",
547 event_name, eabuf));
548 } else if (status == BRCMF_E_STATUS_TIMEOUT) {
549 BRCMF_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n",
550 event_name, eabuf));
551 } else if (status == BRCMF_E_STATUS_FAIL) {
552 BRCMF_EVENT(("MACEVENT: %s, MAC %s, FAILURE,"
553 " reason %d\n", event_name, eabuf,
554 (int)reason));
555 } else {
556 BRCMF_EVENT(("MACEVENT: %s, MAC %s, unexpected status "
557 "%d\n", event_name, eabuf, (int)status));
558 }
559 break;
560
561 case BRCMF_E_DEAUTH_IND:
562 case BRCMF_E_DISASSOC_IND:
563 BRCMF_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name,
564 eabuf, (int)reason));
565 break;
566
567 case BRCMF_E_AUTH:
568 case BRCMF_E_AUTH_IND:
569 if (auth_type == WLAN_AUTH_OPEN)
570 auth_str = "Open System";
571 else if (auth_type == WLAN_AUTH_SHARED_KEY)
572 auth_str = "Shared Key";
573 else {
574 sprintf(err_msg, "AUTH unknown: %d", (int)auth_type);
575 auth_str = err_msg;
576 }
577 if (event_type == BRCMF_E_AUTH_IND) {
578 BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name,
579 eabuf, auth_str));
580 } else if (status == BRCMF_E_STATUS_SUCCESS) {
581 BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n",
582 event_name, eabuf, auth_str));
583 } else if (status == BRCMF_E_STATUS_TIMEOUT) {
584 BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
585 event_name, eabuf, auth_str));
586 } else if (status == BRCMF_E_STATUS_FAIL) {
587 BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, "
588 "reason %d\n",
589 event_name, eabuf, auth_str, (int)reason));
590 }
591
592 break;
593
594 case BRCMF_E_JOIN:
595 case BRCMF_E_ROAM:
596 case BRCMF_E_SET_SSID:
597 if (status == BRCMF_E_STATUS_SUCCESS) {
598 BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name,
599 eabuf));
600 } else if (status == BRCMF_E_STATUS_FAIL) {
601 BRCMF_EVENT(("MACEVENT: %s, failed\n", event_name));
602 } else if (status == BRCMF_E_STATUS_NO_NETWORKS) {
603 BRCMF_EVENT(("MACEVENT: %s, no networks found\n",
604 event_name));
605 } else {
606 BRCMF_EVENT(("MACEVENT: %s, unexpected status %d\n",
607 event_name, (int)status));
608 }
609 break;
610
611 case BRCMF_E_BEACON_RX:
612 if (status == BRCMF_E_STATUS_SUCCESS) {
613 BRCMF_EVENT(("MACEVENT: %s, SUCCESS\n", event_name));
614 } else if (status == BRCMF_E_STATUS_FAIL) {
615 BRCMF_EVENT(("MACEVENT: %s, FAIL\n", event_name));
616 } else {
617 BRCMF_EVENT(("MACEVENT: %s, status %d\n", event_name,
618 status));
619 }
620 break;
621
622 case BRCMF_E_LINK:
623 BRCMF_EVENT(("MACEVENT: %s %s\n", event_name,
624 link ? "UP" : "DOWN"));
625 break;
626
627 case BRCMF_E_MIC_ERROR:
628 BRCMF_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
629 event_name, eabuf, group, flush_txq));
630 break;
631
632 case BRCMF_E_ICV_ERROR:
633 case BRCMF_E_UNICAST_DECODE_ERROR:
634 case BRCMF_E_MULTICAST_DECODE_ERROR:
635 BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
636 break;
637
638 case BRCMF_E_TXFAIL:
639 BRCMF_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf));
640 break;
641
642 case BRCMF_E_SCAN_COMPLETE:
643 case BRCMF_E_PMKID_CACHE:
644 BRCMF_EVENT(("MACEVENT: %s\n", event_name));
645 break;
646
647 case BRCMF_E_PFN_NET_FOUND:
648 case BRCMF_E_PFN_NET_LOST:
649 case BRCMF_E_PFN_SCAN_COMPLETE:
650 BRCMF_EVENT(("PNOEVENT: %s\n", event_name));
651 break;
652
653 case BRCMF_E_PSK_SUP:
654 case BRCMF_E_PRUNE:
655 BRCMF_EVENT(("MACEVENT: %s, status %d, reason %d\n",
656 event_name, (int)status, (int)reason));
657 break;
658
659 case BRCMF_E_TRACE:
660 {
661 static u32 seqnum_prev;
662 struct msgtrace_hdr hdr;
663 u32 nblost;
664 char *s, *p;
665
666 buf = (unsigned char *) event_data;
667 memcpy(&hdr, buf, sizeof(struct msgtrace_hdr));
668
669 if (hdr.version != MSGTRACE_VERSION) {
670 BRCMF_ERROR(
671 ("\nMACEVENT: %s [unsupported version --> "
672 "brcmf version:%d dongle version:%d]\n",
673 event_name, MSGTRACE_VERSION, hdr.version)
674 );
675 /* Reset datalen to avoid display below */
676 datalen = 0;
677 break;
678 }
679
680 /* There are 2 bytes available at the end of data */
681 *(buf + sizeof(struct msgtrace_hdr)
682 + be16_to_cpu(hdr.len)) = '\0';
683
684 if (be32_to_cpu(hdr.discarded_bytes)
685 || be32_to_cpu(hdr.discarded_printf)) {
686 BRCMF_ERROR(
687 ("\nWLC_E_TRACE: [Discarded traces in dongle -->"
688 "discarded_bytes %d discarded_printf %d]\n",
689 be32_to_cpu(hdr.discarded_bytes),
690 be32_to_cpu(hdr.discarded_printf)));
691 }
692
693 nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1;
694 if (nblost > 0) {
695 BRCMF_ERROR(
696 ("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n",
697 be32_to_cpu(hdr.seqnum), nblost));
698 }
699 seqnum_prev = be32_to_cpu(hdr.seqnum);
700
701 /* Display the trace buffer. Advance from \n to \n to
702 * avoid display big
703 * printf (issue with Linux printk )
704 */
705 p = (char *)&buf[sizeof(struct msgtrace_hdr)];
706 while ((s = strstr(p, "\n")) != NULL) {
707 *s = '\0';
708 printk(KERN_DEBUG"%s\n", p);
709 p = s + 1;
710 }
711 printk(KERN_DEBUG "%s\n", p);
712
713 /* Reset datalen to avoid display below */
714 datalen = 0;
715 }
716 break;
717
718 case BRCMF_E_RSSI:
719 BRCMF_EVENT(("MACEVENT: %s %d\n", event_name,
720 be32_to_cpu(*((int *)event_data))));
721 break;
722
723 default:
724 BRCMF_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, "
725 "auth %d\n", event_name, event_type, eabuf,
726 (int)status, (int)reason, (int)auth_type));
727 break;
728 }
729
730 /* show any appended data */
731 if (datalen) {
732 buf = (unsigned char *) event_data;
733 BRCMF_EVENT((" data (%d) : ", datalen));
734 for (i = 0; i < datalen; i++)
735 BRCMF_EVENT((" 0x%02x ", *buf++));
736 BRCMF_EVENT(("\n"));
737 }
738}
739#endif /* SHOW_EVENTS */
740
741int
742brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
743 struct brcmf_event_msg *event, void **data_ptr)
744{
745 /* check whether packet is a BRCM event pkt */
746 struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata;
747 char *event_data;
748 u32 type, status;
749 u16 flags;
750 int evlen;
751
752 if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) {
753 BRCMF_ERROR(("%s: mismatched OUI, bailing\n", __func__));
754 return -EBADE;
755 }
756
757 /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
758 if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) !=
759 BCMILCP_BCM_SUBTYPE_EVENT) {
760 BRCMF_ERROR(("%s: mismatched subtype, bailing\n", __func__));
761 return -EBADE;
762 }
763
764 *data_ptr = &pvt_data[1];
765 event_data = *data_ptr;
766
767 /* memcpy since BRCM event pkt may be unaligned. */
768 memcpy(event, &pvt_data->msg, sizeof(struct brcmf_event_msg));
769
770 type = get_unaligned_be32(&event->event_type);
771 flags = get_unaligned_be16(&event->flags);
772 status = get_unaligned_be32(&event->status);
773 evlen = get_unaligned_be32(&event->datalen) +
774 sizeof(struct brcmf_event);
775
776 switch (type) {
777 case BRCMF_E_IF:
778 {
779 struct brcmf_if_event *ifevent =
780 (struct brcmf_if_event *) event_data;
781 BRCMF_TRACE(("%s: if event\n", __func__));
782
783 if (ifevent->ifidx > 0 &&
784 ifevent->ifidx < BRCMF_MAX_IFS) {
785 if (ifevent->action == BRCMF_E_IF_ADD)
786 brcmf_add_if(drvr_priv, ifevent->ifidx,
787 NULL, event->ifname,
788 pvt_data->eth.h_dest,
789 ifevent->flags,
790 ifevent->bssidx);
791 else
792 brcmf_del_if(drvr_priv, ifevent->ifidx);
793 } else {
794 BRCMF_ERROR(("%s: Invalid ifidx %d for %s\n",
795 __func__, ifevent->ifidx,
796 event->ifname));
797 }
798 }
799 /* send up the if event: btamp user needs it */
800 *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname);
801 break;
802
803 /* These are what external supplicant/authenticator wants */
804 case BRCMF_E_LINK:
805 case BRCMF_E_ASSOC_IND:
806 case BRCMF_E_REASSOC_IND:
807 case BRCMF_E_DISASSOC_IND:
808 case BRCMF_E_MIC_ERROR:
809 default:
810 /* Fall through: this should get _everything_ */
811
812 *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname);
813 BRCMF_TRACE(("%s: MAC event %d, flags %x, status %x\n",
814 __func__, type, flags, status));
815
816 /* put it back to BRCMF_E_NDIS_LINK */
817 if (type == BRCMF_E_NDIS_LINK) {
818 u32 temp;
819
820 temp = get_unaligned_be32(&event->event_type);
821 BRCMF_TRACE(("Converted to WLC_E_LINK type %d\n",
822 temp));
823
824 temp = be32_to_cpu(BRCMF_E_NDIS_LINK);
825 memcpy((void *)(&pvt_data->msg.event_type), &temp,
826 sizeof(pvt_data->msg.event_type));
827 }
828 break;
829 }
830
831#ifdef SHOW_EVENTS
832 brcmf_c_show_host_event(event, event_data);
833#endif /* SHOW_EVENTS */
834
835 return 0;
836}
837
838/* Convert user's input in hex pattern to byte-size mask */
839static int brcmf_c_pattern_atoh(char *src, char *dst)
840{
841 int i;
842 if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
843 BRCMF_ERROR(("Mask invalid format. Needs to start with 0x\n"));
844 return -1;
845 }
846 src = src + 2; /* Skip past 0x */
847 if (strlen(src) % 2 != 0) {
848 BRCMF_ERROR(("Mask invalid format. Length must be even.\n"));
849 return -1;
850 }
851 for (i = 0; *src != '\0'; i++) {
852 char num[3];
853 strncpy(num, src, 2);
854 num[2] = '\0';
855 dst[i] = (u8) simple_strtoul(num, NULL, 16);
856 src += 2;
857 }
858 return i;
859}
860
861void
862brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
863 int master_mode)
864{
865 char *argv[8];
866 int i = 0;
867 const char *str;
868 int buf_len;
869 int str_len;
870 char *arg_save = 0, *arg_org = 0;
871 int rc;
872 char buf[128];
873 struct brcmf_pkt_filter_enable enable_parm;
874 struct brcmf_pkt_filter_enable *pkt_filterp;
875
876 arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
877 if (!arg_save) {
878 BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
879 goto fail;
880 }
881 arg_org = arg_save;
882 memcpy(arg_save, arg, strlen(arg) + 1);
883
884 argv[i] = strsep(&arg_save, " ");
885
886 i = 0;
887 if (NULL == argv[i]) {
888 BRCMF_ERROR(("No args provided\n"));
889 goto fail;
890 }
891
892 str = "pkt_filter_enable";
893 str_len = strlen(str);
894 strncpy(buf, str, str_len);
895 buf[str_len] = '\0';
896 buf_len = str_len + 1;
897
898 pkt_filterp = (struct brcmf_pkt_filter_enable *) (buf + str_len + 1);
899
900 /* Parse packet filter id. */
901 enable_parm.id = simple_strtoul(argv[i], NULL, 0);
902
903 /* Parse enable/disable value. */
904 enable_parm.enable = enable;
905
906 buf_len += sizeof(enable_parm);
907 memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
908
909 /* Enable/disable the specified filter. */
910 rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
911 rc = rc >= 0 ? 0 : rc;
912 if (rc)
913 BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
914 __func__, arg, rc));
915 else
916 BRCMF_TRACE(("%s: successfully added pktfilter %s\n",
917 __func__, arg));
918
919 /* Contorl the master mode */
920 brcmu_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf,
921 sizeof(buf));
922 rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf,
923 sizeof(buf));
924 rc = rc >= 0 ? 0 : rc;
925 if (rc)
926 BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
927 __func__, arg, rc));
928
929fail:
930 kfree(arg_org);
931}
932
933void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
934{
935 const char *str;
936 struct brcmf_pkt_filter pkt_filter;
937 struct brcmf_pkt_filter *pkt_filterp;
938 int buf_len;
939 int str_len;
940 int rc;
941 u32 mask_size;
942 u32 pattern_size;
943 char *argv[8], *buf = 0;
944 int i = 0;
945 char *arg_save = 0, *arg_org = 0;
946
947 arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
948 if (!arg_save) {
949 BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
950 goto fail;
951 }
952
953 arg_org = arg_save;
954
955 buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC);
956 if (!buf) {
957 BRCMF_ERROR(("%s: kmalloc failed\n", __func__));
958 goto fail;
959 }
960
961 strcpy(arg_save, arg);
962
963 argv[i] = strsep(&arg_save, " ");
964 while (argv[i++])
965 argv[i] = strsep(&arg_save, " ");
966
967 i = 0;
968 if (NULL == argv[i]) {
969 BRCMF_ERROR(("No args provided\n"));
970 goto fail;
971 }
972
973 str = "pkt_filter_add";
974 strcpy(buf, str);
975 str_len = strlen(str);
976 buf_len = str_len + 1;
977
978 pkt_filterp = (struct brcmf_pkt_filter *) (buf + str_len + 1);
979
980 /* Parse packet filter id. */
981 pkt_filter.id = simple_strtoul(argv[i], NULL, 0);
982
983 if (NULL == argv[++i]) {
984 BRCMF_ERROR(("Polarity not provided\n"));
985 goto fail;
986 }
987
988 /* Parse filter polarity. */
989 pkt_filter.negate_match = simple_strtoul(argv[i], NULL, 0);
990
991 if (NULL == argv[++i]) {
992 BRCMF_ERROR(("Filter type not provided\n"));
993 goto fail;
994 }
995
996 /* Parse filter type. */
997 pkt_filter.type = simple_strtoul(argv[i], NULL, 0);
998
999 if (NULL == argv[++i]) {
1000 BRCMF_ERROR(("Offset not provided\n"));
1001 goto fail;
1002 }
1003
1004 /* Parse pattern filter offset. */
1005 pkt_filter.u.pattern.offset = simple_strtoul(argv[i], NULL, 0);
1006
1007 if (NULL == argv[++i]) {
1008 BRCMF_ERROR(("Bitmask not provided\n"));
1009 goto fail;
1010 }
1011
1012 /* Parse pattern filter mask. */
1013 mask_size =
1014 brcmf_c_pattern_atoh
1015 (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern);
1016
1017 if (NULL == argv[++i]) {
1018 BRCMF_ERROR(("Pattern not provided\n"));
1019 goto fail;
1020 }
1021
1022 /* Parse pattern filter pattern. */
1023 pattern_size =
1024 brcmf_c_pattern_atoh(argv[i],
1025 (char *)&pkt_filterp->u.pattern.
1026 mask_and_pattern[mask_size]);
1027
1028 if (mask_size != pattern_size) {
1029 BRCMF_ERROR(("Mask and pattern not the same size\n"));
1030 goto fail;
1031 }
1032
1033 pkt_filter.u.pattern.size_bytes = mask_size;
1034 buf_len += BRCMF_PKT_FILTER_FIXED_LEN;
1035 buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
1036
1037 /* Keep-alive attributes are set in local
1038 * variable (keep_alive_pkt), and
1039 ** then memcpy'ed into buffer (keep_alive_pktp) since there is no
1040 ** guarantee that the buffer is properly aligned.
1041 */
1042 memcpy((char *)pkt_filterp,
1043 &pkt_filter,
1044 BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN);
1045
1046 rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
1047 rc = rc >= 0 ? 0 : rc;
1048
1049 if (rc)
1050 BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
1051 __func__, arg, rc));
1052 else
1053 BRCMF_TRACE(("%s: successfully added pktfilter %s\n",
1054 __func__, arg));
1055
1056fail:
1057 kfree(arg_org);
1058
1059 kfree(buf);
1060}
1061
1062void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
1063{
1064 char iovbuf[32];
1065 int retcode;
1066
1067 brcmu_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
1068 retcode = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR,
1069 iovbuf, sizeof(iovbuf));
1070 retcode = retcode >= 0 ? 0 : retcode;
1071 if (retcode)
1072 BRCMF_TRACE(("%s: failed to set ARP offload mode to 0x%x, "
1073 "retcode = %d\n", __func__, arp_mode, retcode));
1074 else
1075 BRCMF_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
1076 __func__, arp_mode));
1077}
1078
1079void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
1080{
1081 char iovbuf[32];
1082 int retcode;
1083
1084 brcmu_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
1085 retcode = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR,
1086 iovbuf, sizeof(iovbuf));
1087 retcode = retcode >= 0 ? 0 : retcode;
1088 if (retcode)
1089 BRCMF_TRACE(("%s: failed to enabe ARP offload to %d, "
1090 "retcode = %d\n", __func__, arp_enable, retcode));
1091 else
1092 BRCMF_TRACE(("%s: successfully enabed ARP offload to %d\n",
1093 __func__, arp_enable));
1094}
1095
1096int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr)
1097{
1098 char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for
1099 "event_msgs" + '\0' + bitvec */
1100 uint up = 0;
1101 char buf[128], *ptr;
1102 uint power_mode = PM_FAST;
1103 u32 dongle_align = BRCMF_SDALIGN;
1104 u32 glom = 0;
1105 uint bcn_timeout = 3;
1106 int scan_assoc_time = 40;
1107 int scan_unassoc_time = 40;
1108 int i;
1109
1110 brcmf_os_proto_block(drvr);
1111
1112 /* Set Country code */
1113 if (drvr->country_code[0] != 0) {
1114 if (brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_COUNTRY,
1115 drvr->country_code,
1116 sizeof(drvr->country_code)) < 0) {
1117 BRCMF_ERROR(("%s: country code setting failed\n",
1118 __func__));
1119 }
1120 }
1121
1122 /* query for 'ver' to get version info from firmware */
1123 memset(buf, 0, sizeof(buf));
1124 ptr = buf;
1125 brcmu_mkiovar("ver", 0, 0, buf, sizeof(buf));
1126 brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf));
1127 strsep(&ptr, "\n");
1128 /* Print fw version info */
1129 BRCMF_ERROR(("Firmware version = %s\n", buf));
1130
1131 /* Set PowerSave mode */
1132 brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_PM, (char *)&power_mode,
1133 sizeof(power_mode));
1134
1135 /* Match Host and Dongle rx alignment */
1136 brcmu_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
1137 sizeof(iovbuf));
1138 brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
1139 sizeof(iovbuf));
1140
1141 /* disable glom option per default */
1142 brcmu_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
1143 brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
1144 sizeof(iovbuf));
1145
1146 /* Setup timeout if Beacons are lost and roam is off to report
1147 link down */
1148 brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
1149 sizeof(iovbuf));
1150 brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
1151 sizeof(iovbuf));
1152
1153 /* Enable/Disable build-in roaming to allowed ext supplicant to take
1154 of romaing */
1155 brcmu_mkiovar("roam_off", (char *)&brcmf_roam, 4,
1156 iovbuf, sizeof(iovbuf));
1157 brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
1158 sizeof(iovbuf));
1159
1160 /* Force STA UP */
1161 if (brcmf_radio_up)
1162 brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_UP, (char *)&up,
1163 sizeof(up));
1164
1165 /* Setup event_msgs */
1166 brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
1167 iovbuf, sizeof(iovbuf));
1168 brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
1169 sizeof(iovbuf));
1170
1171 brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME,
1172 (char *)&scan_assoc_time, sizeof(scan_assoc_time));
1173 brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
1174 (char *)&scan_unassoc_time, sizeof(scan_unassoc_time));
1175
1176 /* Set and enable ARP offload feature */
1177 if (brcmf_arp_enable)
1178 brcmf_c_arp_offload_set(drvr, brcmf_arp_mode);
1179 brcmf_c_arp_offload_enable(drvr, brcmf_arp_enable);
1180
1181 /* Set up pkt filter */
1182 if (brcmf_pkt_filter_enable) {
1183 for (i = 0; i < drvr->pktfilter_count; i++) {
1184 brcmf_c_pktfilter_offload_set(drvr,
1185 drvr->pktfilter[i]);
1186 brcmf_c_pktfilter_offload_enable(drvr,
1187 drvr->pktfilter[i],
1188 brcmf_pkt_filter_init,
1189 brcmf_master_mode);
1190 }
1191 }
1192
1193 brcmf_os_proto_unblock(drvr);
1194
1195 return 0;
1196}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h b/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
new file mode 100644
index 00000000000..5be4d7a609c
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
@@ -0,0 +1,70 @@
1/*
2 * Copyright (c) 2010 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#ifndef _BRCMF_DBG_H_
18#define _BRCMF_DBG_H_
19
20#if defined(BCMDBG)
21
22#define BRCMF_ERROR(args) \
23 do {if ((brcmf_msg_level & BRCMF_ERROR_VAL) && (net_ratelimit())) \
24 printk args; } while (0)
25#define BRCMF_TRACE(args) do {if (brcmf_msg_level & BRCMF_TRACE_VAL) \
26 printk args; } while (0)
27#define BRCMF_INFO(args) do {if (brcmf_msg_level & BRCMF_INFO_VAL) \
28 printk args; } while (0)
29#define BRCMF_DATA(args) do {if (brcmf_msg_level & BRCMF_DATA_VAL) \
30 printk args; } while (0)
31#define BRCMF_CTL(args) do {if (brcmf_msg_level & BRCMF_CTL_VAL) \
32 printk args; } while (0)
33#define BRCMF_TIMER(args) do {if (brcmf_msg_level & BRCMF_TIMER_VAL) \
34 printk args; } while (0)
35#define BRCMF_INTR(args) do {if (brcmf_msg_level & BRCMF_INTR_VAL) \
36 printk args; } while (0)
37#define BRCMF_GLOM(args) do {if (brcmf_msg_level & BRCMF_GLOM_VAL) \
38 printk args; } while (0)
39#define BRCMF_EVENT(args) do {if (brcmf_msg_level & BRCMF_EVENT_VAL) \
40 printk args; } while (0)
41
42#define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL)
43#define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL)
44#define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL)
45#define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL)
46#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL)
47
48#else /* (defined BCMDBG) || (defined BCMDBG) */
49
50#define BRCMF_ERROR(args) do {if (net_ratelimit()) printk args; } while (0)
51#define BRCMF_TRACE(args)
52#define BRCMF_INFO(args)
53#define BRCMF_DATA(args)
54#define BRCMF_CTL(args)
55#define BRCMF_TIMER(args)
56#define BRCMF_INTR(args)
57#define BRCMF_GLOM(args)
58#define BRCMF_EVENT(args)
59
60#define BRCMF_DATA_ON() 0
61#define BRCMF_CTL_ON() 0
62#define BRCMF_HDRS_ON() 0
63#define BRCMF_BYTES_ON() 0
64#define BRCMF_GLOM_ON() 0
65
66#endif /* defined(BCMDBG) */
67
68extern int brcmf_msg_level;
69
70#endif /* _BRCMF_DBG_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
new file mode 100644
index 00000000000..05dada98eb6
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
@@ -0,0 +1,1736 @@
1/*
2 * Copyright (c) 2010 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#include <linux/init.h>
18#include <linux/kernel.h>
19#include <linux/kthread.h>
20#include <linux/slab.h>
21#include <linux/skbuff.h>
22#include <linux/netdevice.h>
23#include <linux/etherdevice.h>
24#include <linux/mmc/sdio_func.h>
25#include <linux/random.h>
26#include <linux/spinlock.h>
27#include <linux/ethtool.h>
28#include <linux/fcntl.h>
29#include <linux/fs.h>
30#include <linux/uaccess.h>
31#include <linux/interrupt.h>
32#include <linux/hardirq.h>
33#include <net/cfg80211.h>
34#include <defs.h>
35#include <brcmu_utils.h>
36#include <brcmu_wifi.h>
37
38#include "dhd.h"
39#include "dhd_bus.h"
40#include "dhd_proto.h"
41#include "dhd_dbg.h"
42#include "wl_cfg80211.h"
43#include "bcmchip.h"
44
45#if defined(CONFIG_PM_SLEEP)
46#include <linux/suspend.h>
47atomic_t brcmf_mmc_suspend;
48#endif /* defined(CONFIG_PM_SLEEP) */
49
50MODULE_AUTHOR("Broadcom Corporation");
51MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver.");
52MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards");
53MODULE_LICENSE("Dual BSD/GPL");
54
55
56/* Interface control information */
57struct brcmf_if {
58 struct brcmf_info *info; /* back pointer to brcmf_info */
59 /* OS/stack specifics */
60 struct net_device *net;
61 struct net_device_stats stats;
62 int idx; /* iface idx in dongle */
63 int state; /* interface state */
64 uint subunit; /* subunit */
65 u8 mac_addr[ETH_ALEN]; /* assigned MAC address */
66 bool attached; /* Delayed attachment when unset */
67 bool txflowcontrol; /* Per interface flow control indicator */
68 char name[IFNAMSIZ]; /* linux interface name */
69};
70
71/* Local private structure (extension of pub) */
72struct brcmf_info {
73 struct brcmf_pub pub;
74
75 /* OS/stack specifics */
76 struct brcmf_if *iflist[BRCMF_MAX_IFS];
77
78 struct semaphore proto_sem;
79 wait_queue_head_t ioctl_resp_wait;
80
81 /* Thread to issue ioctl for multicast */
82 struct task_struct *sysioc_tsk;
83 struct semaphore sysioc_sem;
84 bool set_multicast;
85 bool set_macaddress;
86 u8 macvalue[ETH_ALEN];
87 atomic_t pend_8021x_cnt;
88};
89
90/* Error bits */
91module_param(brcmf_msg_level, int, 0);
92
93/* Spawn a thread for system ioctls (set mac, set mcast) */
94uint brcmf_sysioc = true;
95module_param(brcmf_sysioc, uint, 0);
96
97/* ARP offload agent mode : Enable ARP Host Auto-Reply
98and ARP Peer Auto-Reply */
99uint brcmf_arp_mode = 0xb;
100module_param(brcmf_arp_mode, uint, 0);
101
102/* ARP offload enable */
103uint brcmf_arp_enable = true;
104module_param(brcmf_arp_enable, uint, 0);
105
106/* Global Pkt filter enable control */
107uint brcmf_pkt_filter_enable = true;
108module_param(brcmf_pkt_filter_enable, uint, 0);
109
110/* Pkt filter init setup */
111uint brcmf_pkt_filter_init;
112module_param(brcmf_pkt_filter_init, uint, 0);
113
114/* Pkt filter mode control */
115uint brcmf_master_mode = true;
116module_param(brcmf_master_mode, uint, 0);
117
118module_param(brcmf_dongle_memsize, int, 0);
119
120/* Contorl fw roaming */
121uint brcmf_roam = 1;
122
123/* Control radio state */
124uint brcmf_radio_up = 1;
125
126/* Network inteface name */
127char iface_name[IFNAMSIZ] = "wlan";
128module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
129
130/* The following are specific to the SDIO dongle */
131
132/* IOCTL response timeout */
133int brcmf_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT;
134
135/* Idle timeout for backplane clock */
136int brcmf_idletime = BRCMF_IDLETIME_TICKS;
137module_param(brcmf_idletime, int, 0);
138
139/* Use polling */
140uint brcmf_poll;
141module_param(brcmf_poll, uint, 0);
142
143/* Use interrupts */
144uint brcmf_intr = true;
145module_param(brcmf_intr, uint, 0);
146
147/* SDIO Drive Strength (in milliamps) */
148uint brcmf_sdiod_drive_strength = 6;
149module_param(brcmf_sdiod_drive_strength, uint, 0);
150
151/* Tx/Rx bounds */
152module_param(brcmf_txbound, uint, 0);
153module_param(brcmf_rxbound, uint, 0);
154
155#ifdef SDTEST
156/* Echo packet generator (pkts/s) */
157uint brcmf_pktgen;
158module_param(brcmf_pktgen, uint, 0);
159
160/* Echo packet len (0 => sawtooth, max 2040) */
161uint brcmf_pktgen_len;
162module_param(brcmf_pktgen_len, uint, 0);
163#endif
164
165static int brcmf_toe_get(struct brcmf_info *drvr_priv, int idx, u32 *toe_ol);
166static int brcmf_toe_set(struct brcmf_info *drvr_priv, int idx, u32 toe_ol);
167static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
168 struct brcmf_event_msg *event_ptr,
169 void **data_ptr);
170
171/*
172 * Generalized timeout mechanism. Uses spin sleep with exponential
173 * back-off until
174 * the sleep time reaches one jiffy, then switches over to task delay. Usage:
175 *
176 * brcmf_timeout_start(&tmo, usec);
177 * while (!brcmf_timeout_expired(&tmo))
178 * if (poll_something())
179 * break;
180 * if (brcmf_timeout_expired(&tmo))
181 * fatal();
182 */
183
184void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec)
185{
186 tmo->limit = usec;
187 tmo->increment = 0;
188 tmo->elapsed = 0;
189 tmo->tick = 1000000 / HZ;
190}
191
192int brcmf_timeout_expired(struct brcmf_timeout *tmo)
193{
194 /* Does nothing the first call */
195 if (tmo->increment == 0) {
196 tmo->increment = 1;
197 return 0;
198 }
199
200 if (tmo->elapsed >= tmo->limit)
201 return 1;
202
203 /* Add the delay that's about to take place */
204 tmo->elapsed += tmo->increment;
205
206 if (tmo->increment < tmo->tick) {
207 udelay(tmo->increment);
208 tmo->increment *= 2;
209 if (tmo->increment > tmo->tick)
210 tmo->increment = tmo->tick;
211 } else {
212 wait_queue_head_t delay_wait;
213 DECLARE_WAITQUEUE(wait, current);
214 int pending;
215 init_waitqueue_head(&delay_wait);
216 add_wait_queue(&delay_wait, &wait);
217 set_current_state(TASK_INTERRUPTIBLE);
218 schedule_timeout(1);
219 pending = signal_pending(current);
220 remove_wait_queue(&delay_wait, &wait);
221 set_current_state(TASK_RUNNING);
222 if (pending)
223 return 1; /* Interrupted */
224 }
225
226 return 0;
227}
228
229static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *net)
230{
231 int i = 0;
232
233 while (i < BRCMF_MAX_IFS) {
234 if (drvr_priv->iflist[i] && (drvr_priv->iflist[i]->net == net))
235 return i;
236 i++;
237 }
238
239 return BRCMF_BAD_IF;
240}
241
242int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
243{
244 int i = BRCMF_MAX_IFS;
245
246 if (name == NULL || *name == '\0')
247 return 0;
248
249 while (--i > 0)
250 if (drvr_priv->iflist[i]
251 && !strncmp(drvr_priv->iflist[i]->name, name, IFNAMSIZ))
252 break;
253
254 BRCMF_TRACE(("%s: return idx %d for \"%s\"\n", __func__, i, name));
255
256 return i; /* default - the primary interface */
257}
258
259char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
260{
261 struct brcmf_info *drvr_priv = drvr->info;
262
263 if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
264 BRCMF_ERROR(("%s: ifidx %d out of range\n", __func__, ifidx));
265 return "<if_bad>";
266 }
267
268 if (drvr_priv->iflist[ifidx] == NULL) {
269 BRCMF_ERROR(("%s: null i/f %d\n", __func__, ifidx));
270 return "<if_null>";
271 }
272
273 if (drvr_priv->iflist[ifidx]->net)
274 return drvr_priv->iflist[ifidx]->net->name;
275
276 return "<if_none>";
277}
278
279static void _brcmf_set_multicast_list(struct brcmf_info *drvr_priv, int ifidx)
280{
281 struct net_device *dev;
282 struct netdev_hw_addr *ha;
283 u32 allmulti, cnt;
284
285 struct brcmf_ioctl ioc;
286 char *buf, *bufp;
287 uint buflen;
288 int ret;
289
290 dev = drvr_priv->iflist[ifidx]->net;
291 cnt = netdev_mc_count(dev);
292
293 /* Determine initial value of allmulti flag */
294 allmulti = (dev->flags & IFF_ALLMULTI) ? true : false;
295
296 /* Send down the multicast list first. */
297
298 buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN);
299 bufp = buf = kmalloc(buflen, GFP_ATOMIC);
300 if (!bufp) {
301 BRCMF_ERROR(("%s: out of memory for mcast_list, cnt %d\n",
302 brcmf_ifname(&drvr_priv->pub, ifidx), cnt));
303 return;
304 }
305
306 strcpy(bufp, "mcast_list");
307 bufp += strlen("mcast_list") + 1;
308
309 cnt = cpu_to_le32(cnt);
310 memcpy(bufp, &cnt, sizeof(cnt));
311 bufp += sizeof(cnt);
312
313 netdev_for_each_mc_addr(ha, dev) {
314 if (!cnt)
315 break;
316 memcpy(bufp, ha->addr, ETH_ALEN);
317 bufp += ETH_ALEN;
318 cnt--;
319 }
320
321 memset(&ioc, 0, sizeof(ioc));
322 ioc.cmd = BRCMF_C_SET_VAR;
323 ioc.buf = buf;
324 ioc.len = buflen;
325 ioc.set = true;
326
327 ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
328 if (ret < 0) {
329 BRCMF_ERROR(("%s: set mcast_list failed, cnt %d\n",
330 brcmf_ifname(&drvr_priv->pub, ifidx), cnt));
331 allmulti = cnt ? true : allmulti;
332 }
333
334 kfree(buf);
335
336 /* Now send the allmulti setting. This is based on the setting in the
337 * net_device flags, but might be modified above to be turned on if we
338 * were trying to set some addresses and dongle rejected it...
339 */
340
341 buflen = sizeof("allmulti") + sizeof(allmulti);
342 buf = kmalloc(buflen, GFP_ATOMIC);
343 if (!buf) {
344 BRCMF_ERROR(("%s: out of memory for allmulti\n",
345 brcmf_ifname(&drvr_priv->pub, ifidx)));
346 return;
347 }
348 allmulti = cpu_to_le32(allmulti);
349
350 if (!brcmu_mkiovar
351 ("allmulti", (void *)&allmulti, sizeof(allmulti), buf, buflen)) {
352 BRCMF_ERROR(("%s: mkiovar failed for allmulti, datalen %d "
353 "buflen %u\n",
354 brcmf_ifname(&drvr_priv->pub, ifidx),
355 (int)sizeof(allmulti), buflen));
356 kfree(buf);
357 return;
358 }
359
360 memset(&ioc, 0, sizeof(ioc));
361 ioc.cmd = BRCMF_C_SET_VAR;
362 ioc.buf = buf;
363 ioc.len = buflen;
364 ioc.set = true;
365
366 ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
367 if (ret < 0) {
368 BRCMF_ERROR(("%s: set allmulti %d failed\n",
369 brcmf_ifname(&drvr_priv->pub, ifidx),
370 le32_to_cpu(allmulti)));
371 }
372
373 kfree(buf);
374
375 /* Finally, pick up the PROMISC flag as well, like the NIC
376 driver does */
377
378 allmulti = (dev->flags & IFF_PROMISC) ? true : false;
379 allmulti = cpu_to_le32(allmulti);
380
381 memset(&ioc, 0, sizeof(ioc));
382 ioc.cmd = BRCMF_C_SET_PROMISC;
383 ioc.buf = &allmulti;
384 ioc.len = sizeof(allmulti);
385 ioc.set = true;
386
387 ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
388 if (ret < 0) {
389 BRCMF_ERROR(("%s: set promisc %d failed\n",
390 brcmf_ifname(&drvr_priv->pub, ifidx),
391 le32_to_cpu(allmulti)));
392 }
393}
394
395static int _brcmf_set_mac_address(struct brcmf_info *drvr_priv, int ifidx, u8 *addr)
396{
397 char buf[32];
398 struct brcmf_ioctl ioc;
399 int ret;
400
401 BRCMF_TRACE(("%s enter\n", __func__));
402 if (!brcmu_mkiovar
403 ("cur_etheraddr", (char *)addr, ETH_ALEN, buf, 32)) {
404 BRCMF_ERROR(("%s: mkiovar failed for cur_etheraddr\n",
405 brcmf_ifname(&drvr_priv->pub, ifidx)));
406 return -1;
407 }
408 memset(&ioc, 0, sizeof(ioc));
409 ioc.cmd = BRCMF_C_SET_VAR;
410 ioc.buf = buf;
411 ioc.len = 32;
412 ioc.set = true;
413
414 ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
415 if (ret < 0) {
416 BRCMF_ERROR(("%s: set cur_etheraddr failed\n",
417 brcmf_ifname(&drvr_priv->pub, ifidx)));
418 } else {
419 memcpy(drvr_priv->iflist[ifidx]->net->dev_addr, addr, ETH_ALEN);
420 }
421
422 return ret;
423}
424
425#ifdef SOFTAP
426extern struct net_device *ap_net_dev;
427#endif
428
429/* Virtual interfaces only ((ifp && ifp->info && ifp->idx == true) */
430static void brcmf_op_if(struct brcmf_if *ifp)
431{
432 struct brcmf_info *drvr_priv;
433 int ret = 0, err = 0;
434
435 drvr_priv = ifp->info;
436
437 BRCMF_TRACE(("%s: idx %d, state %d\n", __func__, ifp->idx, ifp->state));
438
439 switch (ifp->state) {
440 case BRCMF_E_IF_ADD:
441 /*
442 * Delete the existing interface before overwriting it
443 * in case we missed the BRCMF_E_IF_DEL event.
444 */
445 if (ifp->net != NULL) {
446 BRCMF_ERROR(("%s: ERROR: netdev:%s already exists, "
447 "try free & unregister\n",
448 __func__, ifp->net->name));
449 netif_stop_queue(ifp->net);
450 unregister_netdev(ifp->net);
451 free_netdev(ifp->net);
452 }
453 /* Allocate etherdev, including space for private structure */
454 ifp->net = alloc_etherdev(sizeof(drvr_priv));
455 if (!ifp->net) {
456 BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
457 ret = -ENOMEM;
458 }
459 if (ret == 0) {
460 strcpy(ifp->net->name, ifp->name);
461 memcpy(netdev_priv(ifp->net), &drvr_priv, sizeof(drvr_priv));
462 err = brcmf_net_attach(&drvr_priv->pub, ifp->idx);
463 if (err != 0) {
464 BRCMF_ERROR(("%s: brcmf_net_attach failed, "
465 "err %d\n",
466 __func__, err));
467 ret = -EOPNOTSUPP;
468 } else {
469#ifdef SOFTAP
470 /* semaphore that the soft AP CODE
471 waits on */
472 extern struct semaphore ap_eth_sema;
473
474 /* save ptr to wl0.1 netdev for use
475 in wl_iw.c */
476 ap_net_dev = ifp->net;
477 /* signal to the SOFTAP 'sleeper' thread,
478 wl0.1 is ready */
479 up(&ap_eth_sema);
480#endif
481 BRCMF_TRACE(("\n ==== pid:%x, net_device for "
482 "if:%s created ===\n\n",
483 current->pid, ifp->net->name));
484 ifp->state = 0;
485 }
486 }
487 break;
488 case BRCMF_E_IF_DEL:
489 if (ifp->net != NULL) {
490 BRCMF_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n",
491 __func__));
492 netif_stop_queue(ifp->net);
493 unregister_netdev(ifp->net);
494 ret = BRCMF_DEL_IF; /* Make sure the free_netdev()
495 is called */
496 }
497 break;
498 default:
499 BRCMF_ERROR(("%s: bad op %d\n", __func__, ifp->state));
500 break;
501 }
502
503 if (ret < 0) {
504 if (ifp->net)
505 free_netdev(ifp->net);
506
507 drvr_priv->iflist[ifp->idx] = NULL;
508 kfree(ifp);
509#ifdef SOFTAP
510 if (ifp->net == ap_net_dev)
511 ap_net_dev = NULL; /* NULL SOFTAP global
512 wl0.1 as well */
513#endif /* SOFTAP */
514 }
515}
516
517static int _brcmf_sysioc_thread(void *data)
518{
519 struct brcmf_info *drvr_priv = (struct brcmf_info *) data;
520 int i;
521#ifdef SOFTAP
522 bool in_ap = false;
523#endif
524
525 allow_signal(SIGTERM);
526
527 while (down_interruptible(&drvr_priv->sysioc_sem) == 0) {
528 if (kthread_should_stop())
529 break;
530 for (i = 0; i < BRCMF_MAX_IFS; i++) {
531 struct brcmf_if *ifentry = drvr_priv->iflist[i];
532 if (ifentry) {
533#ifdef SOFTAP
534 in_ap = (ap_net_dev != NULL);
535#endif /* SOFTAP */
536 if (ifentry->state)
537 brcmf_op_if(ifentry);
538#ifdef SOFTAP
539 if (drvr_priv->iflist[i] == NULL) {
540 BRCMF_TRACE(("\n\n %s: interface %d "
541 "removed!\n", __func__,
542 i));
543 continue;
544 }
545
546 if (in_ap && drvr_priv->set_macaddress) {
547 BRCMF_TRACE(("attempt to set MAC for"
548 " %s in AP Mode,"
549 " blocked.\n",
550 ifentry->net->name));
551 drvr_priv->set_macaddress = false;
552 continue;
553 }
554
555 if (in_ap && drvr_priv->set_multicast) {
556 BRCMF_TRACE(("attempt to set MULTICAST "
557 "list for %s in AP Mode, "
558 "blocked.\n",
559 ifentry->net->name));
560 drvr_priv->set_multicast = false;
561 continue;
562 }
563#endif /* SOFTAP */
564 if (drvr_priv->set_multicast) {
565 drvr_priv->set_multicast = false;
566 _brcmf_set_multicast_list(drvr_priv, i);
567 }
568 if (drvr_priv->set_macaddress) {
569 drvr_priv->set_macaddress = false;
570 _brcmf_set_mac_address(drvr_priv, i,
571 drvr_priv->macvalue);
572 }
573 }
574 }
575 }
576 return 0;
577}
578
579static int brcmf_netdev_set_mac_address(struct net_device *dev, void *addr)
580{
581 int ret = 0;
582
583 struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev);
584 struct sockaddr *sa = (struct sockaddr *)addr;
585 int ifidx;
586
587 ifidx = brcmf_net2idx(drvr_priv, dev);
588 if (ifidx == BRCMF_BAD_IF)
589 return -1;
590
591 memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
592 drvr_priv->set_macaddress = true;
593 up(&drvr_priv->sysioc_sem);
594
595 return ret;
596}
597
598static void brcmf_netdev_set_multicast_list(struct net_device *dev)
599{
600 struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev);
601 int ifidx;
602
603 ifidx = brcmf_net2idx(drvr_priv, dev);
604 if (ifidx == BRCMF_BAD_IF)
605 return;
606
607 drvr_priv->set_multicast = true;
608 up(&drvr_priv->sysioc_sem);
609}
610
611int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
612{
613 struct brcmf_info *drvr_priv = drvr->info;
614
615 /* Reject if down */
616 if (!drvr->up || (drvr->busstate == BRCMF_BUS_DOWN))
617 return -ENODEV;
618
619 /* Update multicast statistic */
620 if (pktbuf->len >= ETH_ALEN) {
621 u8 *pktdata = (u8 *) (pktbuf->data);
622 struct ethhdr *eh = (struct ethhdr *)pktdata;
623
624 if (is_multicast_ether_addr(eh->h_dest))
625 drvr->tx_multicast++;
626 if (ntohs(eh->h_proto) == ETH_P_PAE)
627 atomic_inc(&drvr_priv->pend_8021x_cnt);
628 }
629
630 /* If the protocol uses a data header, apply it */
631 brcmf_proto_hdrpush(drvr, ifidx, pktbuf);
632
633 /* Use bus module to send data frame */
634 return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf);
635}
636
637static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *net)
638{
639 int ret;
640 struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
641 int ifidx;
642
643 BRCMF_TRACE(("%s: Enter\n", __func__));
644
645 /* Reject if down */
646 if (!drvr_priv->pub.up || (drvr_priv->pub.busstate == BRCMF_BUS_DOWN)) {
647 BRCMF_ERROR(("%s: xmit rejected pub.up=%d busstate=%d\n",
648 __func__, drvr_priv->pub.up,
649 drvr_priv->pub.busstate));
650 netif_stop_queue(net);
651 return -ENODEV;
652 }
653
654 ifidx = brcmf_net2idx(drvr_priv, net);
655 if (ifidx == BRCMF_BAD_IF) {
656 BRCMF_ERROR(("%s: bad ifidx %d\n", __func__, ifidx));
657 netif_stop_queue(net);
658 return -ENODEV;
659 }
660
661 /* Make sure there's enough room for any header */
662 if (skb_headroom(skb) < drvr_priv->pub.hdrlen) {
663 struct sk_buff *skb2;
664
665 BRCMF_INFO(("%s: insufficient headroom\n",
666 brcmf_ifname(&drvr_priv->pub, ifidx)));
667 drvr_priv->pub.tx_realloc++;
668 skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
669 dev_kfree_skb(skb);
670 skb = skb2;
671 if (skb == NULL) {
672 BRCMF_ERROR(("%s: skb_realloc_headroom failed\n",
673 brcmf_ifname(&drvr_priv->pub, ifidx)));
674 ret = -ENOMEM;
675 goto done;
676 }
677 }
678
679 ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb);
680
681done:
682 if (ret)
683 drvr_priv->pub.dstats.tx_dropped++;
684 else
685 drvr_priv->pub.tx_packets++;
686
687 /* Return ok: we always eat the packet */
688 return 0;
689}
690
691void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool state)
692{
693 struct net_device *net;
694 struct brcmf_info *drvr_priv = drvr->info;
695
696 BRCMF_TRACE(("%s: Enter\n", __func__));
697
698 drvr->txoff = state;
699 net = drvr_priv->iflist[ifidx]->net;
700 if (state == ON)
701 netif_stop_queue(net);
702 else
703 netif_wake_queue(net);
704}
705
706void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
707 int numpkt)
708{
709 struct brcmf_info *drvr_priv = drvr->info;
710 unsigned char *eth;
711 uint len;
712 void *data;
713 struct sk_buff *pnext, *save_pktbuf;
714 int i;
715 struct brcmf_if *ifp;
716 struct brcmf_event_msg event;
717
718 BRCMF_TRACE(("%s: Enter\n", __func__));
719
720 save_pktbuf = skb;
721
722 for (i = 0; skb && i < numpkt; i++, skb = pnext) {
723
724 pnext = skb->next;
725 skb->next = NULL;
726
727 /* Get the protocol, maintain skb around eth_type_trans()
728 * The main reason for this hack is for the limitation of
729 * Linux 2.4 where 'eth_type_trans' uses the
730 * 'net->hard_header_len'
731 * to perform skb_pull inside vs ETH_HLEN. Since to avoid
732 * coping of the packet coming from the network stack to add
733 * BDC, Hardware header etc, during network interface
734 * registration
735 * we set the 'net->hard_header_len' to ETH_HLEN + extra space
736 * required
737 * for BDC, Hardware header etc. and not just the ETH_HLEN
738 */
739 eth = skb->data;
740 len = skb->len;
741
742 ifp = drvr_priv->iflist[ifidx];
743 if (ifp == NULL)
744 ifp = drvr_priv->iflist[0];
745
746 skb->dev = ifp->net;
747 skb->protocol = eth_type_trans(skb, skb->dev);
748
749 if (skb->pkt_type == PACKET_MULTICAST)
750 drvr_priv->pub.rx_multicast++;
751
752 skb->data = eth;
753 skb->len = len;
754
755 /* Strip header, count, deliver upward */
756 skb_pull(skb, ETH_HLEN);
757
758 /* Process special event packets and then discard them */
759 if (ntohs(skb->protocol) == ETH_P_LINK_CTL)
760 brcmf_host_event(drvr_priv, &ifidx,
761 skb_mac_header(skb),
762 &event, &data);
763
764 if (drvr_priv->iflist[ifidx] &&
765 !drvr_priv->iflist[ifidx]->state)
766 ifp = drvr_priv->iflist[ifidx];
767
768 if (ifp->net)
769 ifp->net->last_rx = jiffies;
770
771 drvr->dstats.rx_bytes += skb->len;
772 drvr->rx_packets++; /* Local count */
773
774 if (in_interrupt()) {
775 netif_rx(skb);
776 } else {
777 /* If the receive is not processed inside an ISR,
778 * the softirqd must be woken explicitly to service
779 * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled
780 * by netif_rx_ni(), but in earlier kernels, we need
781 * to do it manually.
782 */
783 netif_rx_ni(skb);
784 }
785 }
786}
787
788void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success)
789{
790 uint ifidx;
791 struct brcmf_info *drvr_priv = drvr->info;
792 struct ethhdr *eh;
793 u16 type;
794
795 brcmf_proto_hdrpull(drvr, &ifidx, txp);
796
797 eh = (struct ethhdr *)(txp->data);
798 type = ntohs(eh->h_proto);
799
800 if (type == ETH_P_PAE)
801 atomic_dec(&drvr_priv->pend_8021x_cnt);
802
803}
804
805static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *net)
806{
807 struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
808 struct brcmf_if *ifp;
809 int ifidx;
810
811 BRCMF_TRACE(("%s: Enter\n", __func__));
812
813 ifidx = brcmf_net2idx(drvr_priv, net);
814 if (ifidx == BRCMF_BAD_IF)
815 return NULL;
816
817 ifp = drvr_priv->iflist[ifidx];
818
819 if (drvr_priv->pub.up) {
820 /* Use the protocol to get dongle stats */
821 brcmf_proto_dstats(&drvr_priv->pub);
822 }
823
824 /* Copy dongle stats to net device stats */
825 ifp->stats.rx_packets = drvr_priv->pub.dstats.rx_packets;
826 ifp->stats.tx_packets = drvr_priv->pub.dstats.tx_packets;
827 ifp->stats.rx_bytes = drvr_priv->pub.dstats.rx_bytes;
828 ifp->stats.tx_bytes = drvr_priv->pub.dstats.tx_bytes;
829 ifp->stats.rx_errors = drvr_priv->pub.dstats.rx_errors;
830 ifp->stats.tx_errors = drvr_priv->pub.dstats.tx_errors;
831 ifp->stats.rx_dropped = drvr_priv->pub.dstats.rx_dropped;
832 ifp->stats.tx_dropped = drvr_priv->pub.dstats.tx_dropped;
833 ifp->stats.multicast = drvr_priv->pub.dstats.multicast;
834
835 return &ifp->stats;
836}
837
838/* Retrieve current toe component enables, which are kept
839 as a bitmap in toe_ol iovar */
840static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol)
841{
842 struct brcmf_ioctl ioc;
843 char buf[32];
844 int ret;
845
846 memset(&ioc, 0, sizeof(ioc));
847
848 ioc.cmd = BRCMF_C_GET_VAR;
849 ioc.buf = buf;
850 ioc.len = (uint) sizeof(buf);
851 ioc.set = false;
852
853 strcpy(buf, "toe_ol");
854 ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
855 if (ret < 0) {
856 /* Check for older dongle image that doesn't support toe_ol */
857 if (ret == -EIO) {
858 BRCMF_ERROR(("%s: toe not supported by device\n",
859 brcmf_ifname(&drvr_priv->pub, ifidx)));
860 return -EOPNOTSUPP;
861 }
862
863 BRCMF_INFO(("%s: could not get toe_ol: ret=%d\n",
864 brcmf_ifname(&drvr_priv->pub, ifidx), ret));
865 return ret;
866 }
867
868 memcpy(toe_ol, buf, sizeof(u32));
869 return 0;
870}
871
872/* Set current toe component enables in toe_ol iovar,
873 and set toe global enable iovar */
874static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
875{
876 struct brcmf_ioctl ioc;
877 char buf[32];
878 int toe, ret;
879
880 memset(&ioc, 0, sizeof(ioc));
881
882 ioc.cmd = BRCMF_C_SET_VAR;
883 ioc.buf = buf;
884 ioc.len = (uint) sizeof(buf);
885 ioc.set = true;
886
887 /* Set toe_ol as requested */
888
889 strcpy(buf, "toe_ol");
890 memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(u32));
891
892 ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
893 if (ret < 0) {
894 BRCMF_ERROR(("%s: could not set toe_ol: ret=%d\n",
895 brcmf_ifname(&drvr_priv->pub, ifidx), ret));
896 return ret;
897 }
898
899 /* Enable toe globally only if any components are enabled. */
900
901 toe = (toe_ol != 0);
902
903 strcpy(buf, "toe");
904 memcpy(&buf[sizeof("toe")], &toe, sizeof(u32));
905
906 ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len);
907 if (ret < 0) {
908 BRCMF_ERROR(("%s: could not set toe: ret=%d\n",
909 brcmf_ifname(&drvr_priv->pub, ifidx), ret));
910 return ret;
911 }
912
913 return 0;
914}
915
916static void brcmf_ethtool_get_drvinfo(struct net_device *net,
917 struct ethtool_drvinfo *info)
918{
919 struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
920
921 sprintf(info->driver, KBUILD_MODNAME);
922 sprintf(info->version, "%lu", drvr_priv->pub.drv_version);
923 sprintf(info->fw_version, "%s", BCM4329_FW_NAME);
924 sprintf(info->bus_info, "%s",
925 dev_name(&brcmf_cfg80211_get_sdio_func()->dev));
926}
927
928struct ethtool_ops brcmf_ethtool_ops = {
929 .get_drvinfo = brcmf_ethtool_get_drvinfo
930};
931
932static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr)
933{
934 struct ethtool_drvinfo info;
935 char drvname[sizeof(info.driver)];
936 u32 cmd;
937 struct ethtool_value edata;
938 u32 toe_cmpnt, csum_dir;
939 int ret;
940
941 BRCMF_TRACE(("%s: Enter\n", __func__));
942
943 /* all ethtool calls start with a cmd word */
944 if (copy_from_user(&cmd, uaddr, sizeof(u32)))
945 return -EFAULT;
946
947 switch (cmd) {
948 case ETHTOOL_GDRVINFO:
949 /* Copy out any request driver name */
950 if (copy_from_user(&info, uaddr, sizeof(info)))
951 return -EFAULT;
952 strncpy(drvname, info.driver, sizeof(info.driver));
953 drvname[sizeof(info.driver) - 1] = '\0';
954
955 /* clear struct for return */
956 memset(&info, 0, sizeof(info));
957 info.cmd = cmd;
958
959 /* if requested, identify ourselves */
960 if (strcmp(drvname, "?dhd") == 0) {
961 sprintf(info.driver, "dhd");
962 strcpy(info.version, BRCMF_VERSION_STR);
963 }
964
965 /* otherwise, require dongle to be up */
966 else if (!drvr_priv->pub.up) {
967 BRCMF_ERROR(("%s: dongle is not up\n", __func__));
968 return -ENODEV;
969 }
970
971 /* finally, report dongle driver type */
972 else if (drvr_priv->pub.iswl)
973 sprintf(info.driver, "wl");
974 else
975 sprintf(info.driver, "xx");
976
977 sprintf(info.version, "%lu", drvr_priv->pub.drv_version);
978 if (copy_to_user(uaddr, &info, sizeof(info)))
979 return -EFAULT;
980 BRCMF_CTL(("%s: given %*s, returning %s\n", __func__,
981 (int)sizeof(drvname), drvname, info.driver));
982 break;
983
984 /* Get toe offload components from dongle */
985 case ETHTOOL_GRXCSUM:
986 case ETHTOOL_GTXCSUM:
987 ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
988 if (ret < 0)
989 return ret;
990
991 csum_dir =
992 (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
993
994 edata.cmd = cmd;
995 edata.data = (toe_cmpnt & csum_dir) ? 1 : 0;
996
997 if (copy_to_user(uaddr, &edata, sizeof(edata)))
998 return -EFAULT;
999 break;
1000
1001 /* Set toe offload components in dongle */
1002 case ETHTOOL_SRXCSUM:
1003 case ETHTOOL_STXCSUM:
1004 if (copy_from_user(&edata, uaddr, sizeof(edata)))
1005 return -EFAULT;
1006
1007 /* Read the current settings, update and write back */
1008 ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt);
1009 if (ret < 0)
1010 return ret;
1011
1012 csum_dir =
1013 (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
1014
1015 if (edata.data != 0)
1016 toe_cmpnt |= csum_dir;
1017 else
1018 toe_cmpnt &= ~csum_dir;
1019
1020 ret = brcmf_toe_set(drvr_priv, 0, toe_cmpnt);
1021 if (ret < 0)
1022 return ret;
1023
1024 /* If setting TX checksum mode, tell Linux the new mode */
1025 if (cmd == ETHTOOL_STXCSUM) {
1026 if (edata.data)
1027 drvr_priv->iflist[0]->net->features |=
1028 NETIF_F_IP_CSUM;
1029 else
1030 drvr_priv->iflist[0]->net->features &=
1031 ~NETIF_F_IP_CSUM;
1032 }
1033
1034 break;
1035
1036 default:
1037 return -EOPNOTSUPP;
1038 }
1039
1040 return 0;
1041}
1042
1043static int brcmf_netdev_ioctl_entry(struct net_device *net, struct ifreq *ifr,
1044 int cmd)
1045{
1046 struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
1047 struct brcmf_c_ioctl ioc;
1048 int bcmerror = 0;
1049 int buflen = 0;
1050 void *buf = NULL;
1051 uint driver = 0;
1052 int ifidx;
1053 bool is_set_key_cmd;
1054
1055 ifidx = brcmf_net2idx(drvr_priv, net);
1056 BRCMF_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __func__, ifidx, cmd));
1057
1058 if (ifidx == BRCMF_BAD_IF)
1059 return -1;
1060
1061 if (cmd == SIOCETHTOOL)
1062 return brcmf_ethtool(drvr_priv, (void *)ifr->ifr_data);
1063
1064 if (cmd != SIOCDEVPRIVATE)
1065 return -EOPNOTSUPP;
1066
1067 memset(&ioc, 0, sizeof(ioc));
1068
1069 /* Copy the ioc control structure part of ioctl request */
1070 if (copy_from_user(&ioc, ifr->ifr_data, sizeof(struct brcmf_ioctl))) {
1071 bcmerror = -EINVAL;
1072 goto done;
1073 }
1074
1075 /* Copy out any buffer passed */
1076 if (ioc.buf) {
1077 buflen = min_t(int, ioc.len, BRCMF_IOCTL_MAXLEN);
1078 /* optimization for direct ioctl calls from kernel */
1079 /*
1080 if (segment_eq(get_fs(), KERNEL_DS)) {
1081 buf = ioc.buf;
1082 } else {
1083 */
1084 {
1085 buf = kmalloc(buflen, GFP_ATOMIC);
1086 if (!buf) {
1087 bcmerror = -ENOMEM;
1088 goto done;
1089 }
1090 if (copy_from_user(buf, ioc.buf, buflen)) {
1091 bcmerror = -EINVAL;
1092 goto done;
1093 }
1094 }
1095 }
1096
1097 /* To differentiate read 4 more byes */
1098 if ((copy_from_user(&driver, (char *)ifr->ifr_data +
1099 sizeof(struct brcmf_ioctl), sizeof(uint)) != 0)) {
1100 bcmerror = -EINVAL;
1101 goto done;
1102 }
1103
1104 if (!capable(CAP_NET_ADMIN)) {
1105 bcmerror = -EPERM;
1106 goto done;
1107 }
1108
1109 /* check for local brcmf ioctl and handle it */
1110 if (driver == BRCMF_IOCTL_MAGIC) {
1111 bcmerror = brcmf_c_ioctl((void *)&drvr_priv->pub, &ioc, buf, buflen);
1112 if (bcmerror)
1113 drvr_priv->pub.bcmerror = bcmerror;
1114 goto done;
1115 }
1116
1117 /* send to dongle (must be up, and wl) */
1118 if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) {
1119 BRCMF_ERROR(("%s DONGLE_DOWN,__func__\n", __func__));
1120 bcmerror = -EIO;
1121 goto done;
1122 }
1123
1124 if (!drvr_priv->pub.iswl) {
1125 bcmerror = -EIO;
1126 goto done;
1127 }
1128
1129 /*
1130 * Intercept BRCMF_C_SET_KEY IOCTL - serialize M4 send and
1131 * set key IOCTL to prevent M4 encryption.
1132 */
1133 is_set_key_cmd = ((ioc.cmd == BRCMF_C_SET_KEY) ||
1134 ((ioc.cmd == BRCMF_C_SET_VAR) &&
1135 !(strncmp("wsec_key", ioc.buf, 9))) ||
1136 ((ioc.cmd == BRCMF_C_SET_VAR) &&
1137 !(strncmp("bsscfg:wsec_key", ioc.buf, 15))));
1138 if (is_set_key_cmd)
1139 brcmf_netdev_wait_pend8021x(net);
1140
1141 bcmerror =
1142 brcmf_proto_ioctl(&drvr_priv->pub, ifidx, (struct brcmf_ioctl *)&ioc,
1143 buf, buflen);
1144
1145done:
1146 if (!bcmerror && buf && ioc.buf) {
1147 if (copy_to_user(ioc.buf, buf, buflen))
1148 bcmerror = -EFAULT;
1149 }
1150
1151 kfree(buf);
1152
1153 if (bcmerror > 0)
1154 bcmerror = 0;
1155
1156 return bcmerror;
1157}
1158
1159static int brcmf_netdev_stop(struct net_device *net)
1160{
1161#if !defined(IGNORE_ETH0_DOWN)
1162 struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
1163
1164 BRCMF_TRACE(("%s: Enter\n", __func__));
1165 brcmf_cfg80211_down();
1166 if (drvr_priv->pub.up == 0)
1167 return 0;
1168
1169 /* Set state and stop OS transmissions */
1170 drvr_priv->pub.up = 0;
1171 netif_stop_queue(net);
1172#else
1173 BRCMF_ERROR(("BYPASS %s:due to BRCM compilation: under investigation\n",
1174 __func__));
1175#endif /* !defined(IGNORE_ETH0_DOWN) */
1176
1177 return 0;
1178}
1179
1180static int brcmf_netdev_open(struct net_device *net)
1181{
1182 struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net);
1183 u32 toe_ol;
1184 int ifidx = brcmf_net2idx(drvr_priv, net);
1185 s32 ret = 0;
1186
1187 BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx));
1188
1189 if (ifidx == 0) { /* do it only for primary eth0 */
1190
1191 /* try to bring up bus */
1192 ret = brcmf_bus_start(&drvr_priv->pub);
1193 if (ret != 0) {
1194 BRCMF_ERROR(("%s: failed with code %d\n",
1195 __func__, ret));
1196 return -1;
1197 }
1198 atomic_set(&drvr_priv->pend_8021x_cnt, 0);
1199
1200 memcpy(net->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
1201
1202 /* Get current TOE mode from dongle */
1203 if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0
1204 && (toe_ol & TOE_TX_CSUM_OL) != 0)
1205 drvr_priv->iflist[ifidx]->net->features |=
1206 NETIF_F_IP_CSUM;
1207 else
1208 drvr_priv->iflist[ifidx]->net->features &=
1209 ~NETIF_F_IP_CSUM;
1210 }
1211 /* Allow transmit calls */
1212 netif_start_queue(net);
1213 drvr_priv->pub.up = 1;
1214 if (unlikely(brcmf_cfg80211_up())) {
1215 BRCMF_ERROR(("%s: failed to bring up cfg80211\n",
1216 __func__));
1217 return -1;
1218 }
1219
1220 return ret;
1221}
1222
1223int
1224brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle, char *name,
1225 u8 *mac_addr, u32 flags, u8 bssidx)
1226{
1227 struct brcmf_if *ifp;
1228
1229 BRCMF_TRACE(("%s: idx %d, handle->%p\n", __func__, ifidx, handle));
1230
1231 ifp = drvr_priv->iflist[ifidx];
1232 if (!ifp) {
1233 ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC);
1234 if (!ifp) {
1235 BRCMF_ERROR(("%s: OOM - struct brcmf_if\n", __func__));
1236 return -ENOMEM;
1237 }
1238 }
1239
1240 memset(ifp, 0, sizeof(struct brcmf_if));
1241 ifp->info = drvr_priv;
1242 drvr_priv->iflist[ifidx] = ifp;
1243 strlcpy(ifp->name, name, IFNAMSIZ);
1244 if (mac_addr != NULL)
1245 memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
1246
1247 if (handle == NULL) {
1248 ifp->state = BRCMF_E_IF_ADD;
1249 ifp->idx = ifidx;
1250 up(&drvr_priv->sysioc_sem);
1251 } else
1252 ifp->net = (struct net_device *)handle;
1253
1254 return 0;
1255}
1256
1257void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
1258{
1259 struct brcmf_if *ifp;
1260
1261 BRCMF_TRACE(("%s: idx %d\n", __func__, ifidx));
1262
1263 ifp = drvr_priv->iflist[ifidx];
1264 if (!ifp) {
1265 BRCMF_ERROR(("%s: Null interface\n", __func__));
1266 return;
1267 }
1268
1269 ifp->state = BRCMF_E_IF_DEL;
1270 ifp->idx = ifidx;
1271 up(&drvr_priv->sysioc_sem);
1272}
1273
1274struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
1275{
1276 struct brcmf_info *drvr_priv = NULL;
1277 struct net_device *net;
1278
1279 BRCMF_TRACE(("%s: Enter\n", __func__));
1280
1281 /* Allocate etherdev, including space for private structure */
1282 net = alloc_etherdev(sizeof(drvr_priv));
1283 if (!net) {
1284 BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
1285 goto fail;
1286 }
1287
1288 /* Allocate primary brcmf_info */
1289 drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC);
1290 if (!drvr_priv) {
1291 BRCMF_ERROR(("%s: OOM - alloc brcmf_info\n", __func__));
1292 goto fail;
1293 }
1294
1295 /*
1296 * Save the brcmf_info into the priv
1297 */
1298 memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv));
1299
1300 /* Set network interface name if it was provided as module parameter */
1301 if (iface_name[0]) {
1302 int len;
1303 char ch;
1304 strncpy(net->name, iface_name, IFNAMSIZ);
1305 net->name[IFNAMSIZ - 1] = 0;
1306 len = strlen(net->name);
1307 ch = net->name[len - 1];
1308 if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2))
1309 strcat(net->name, "%d");
1310 }
1311
1312 if (brcmf_add_if(drvr_priv, 0, (void *)net, net->name, NULL, 0, 0) ==
1313 BRCMF_BAD_IF)
1314 goto fail;
1315
1316 net->netdev_ops = NULL;
1317 sema_init(&drvr_priv->proto_sem, 1);
1318 /* Initialize other structure content */
1319 init_waitqueue_head(&drvr_priv->ioctl_resp_wait);
1320
1321 /* Link to info module */
1322 drvr_priv->pub.info = drvr_priv;
1323
1324 /* Link to bus module */
1325 drvr_priv->pub.bus = bus;
1326 drvr_priv->pub.hdrlen = bus_hdrlen;
1327
1328 /* Attach and link in the protocol */
1329 if (brcmf_proto_attach(&drvr_priv->pub) != 0) {
1330 BRCMF_ERROR(("brcmf_prot_attach failed\n"));
1331 goto fail;
1332 }
1333
1334 /* Attach and link in the cfg80211 */
1335 if (unlikely(brcmf_cfg80211_attach(net, &drvr_priv->pub))) {
1336 BRCMF_ERROR(("wl_cfg80211_attach failed\n"));
1337 goto fail;
1338 }
1339
1340 if (brcmf_sysioc) {
1341 sema_init(&drvr_priv->sysioc_sem, 0);
1342 drvr_priv->sysioc_tsk = kthread_run(_brcmf_sysioc_thread, drvr_priv,
1343 "_brcmf_sysioc");
1344 if (IS_ERR(drvr_priv->sysioc_tsk)) {
1345 printk(KERN_WARNING
1346 "_brcmf_sysioc thread failed to start\n");
1347 drvr_priv->sysioc_tsk = NULL;
1348 }
1349 } else
1350 drvr_priv->sysioc_tsk = NULL;
1351
1352 /*
1353 * Save the brcmf_info into the priv
1354 */
1355 memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv));
1356
1357#if defined(CONFIG_PM_SLEEP)
1358 atomic_set(&brcmf_mmc_suspend, false);
1359#endif /* defined(CONFIG_PM_SLEEP) */
1360 return &drvr_priv->pub;
1361
1362fail:
1363 if (net)
1364 free_netdev(net);
1365 if (drvr_priv)
1366 brcmf_detach(&drvr_priv->pub);
1367
1368 return NULL;
1369}
1370
1371int brcmf_bus_start(struct brcmf_pub *drvr)
1372{
1373 int ret = -1;
1374 struct brcmf_info *drvr_priv = drvr->info;
1375 /* Room for "event_msgs" + '\0' + bitvec */
1376 char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
1377
1378 BRCMF_TRACE(("%s:\n", __func__));
1379
1380 /* Bring up the bus */
1381 ret = brcmf_sdbrcm_bus_init(&drvr_priv->pub, true);
1382 if (ret != 0) {
1383 BRCMF_ERROR(("%s, brcmf_sdbrcm_bus_init failed %d\n", __func__,
1384 ret));
1385 return ret;
1386 }
1387
1388 /* If bus is not ready, can't come up */
1389 if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) {
1390 BRCMF_ERROR(("%s failed bus is not ready\n", __func__));
1391 return -ENODEV;
1392 }
1393
1394 brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
1395 iovbuf, sizeof(iovbuf));
1396 brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR, iovbuf,
1397 sizeof(iovbuf));
1398 memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
1399
1400 setbit(drvr->eventmask, BRCMF_E_SET_SSID);
1401 setbit(drvr->eventmask, BRCMF_E_PRUNE);
1402 setbit(drvr->eventmask, BRCMF_E_AUTH);
1403 setbit(drvr->eventmask, BRCMF_E_REASSOC);
1404 setbit(drvr->eventmask, BRCMF_E_REASSOC_IND);
1405 setbit(drvr->eventmask, BRCMF_E_DEAUTH_IND);
1406 setbit(drvr->eventmask, BRCMF_E_DISASSOC_IND);
1407 setbit(drvr->eventmask, BRCMF_E_DISASSOC);
1408 setbit(drvr->eventmask, BRCMF_E_JOIN);
1409 setbit(drvr->eventmask, BRCMF_E_ASSOC_IND);
1410 setbit(drvr->eventmask, BRCMF_E_PSK_SUP);
1411 setbit(drvr->eventmask, BRCMF_E_LINK);
1412 setbit(drvr->eventmask, BRCMF_E_NDIS_LINK);
1413 setbit(drvr->eventmask, BRCMF_E_MIC_ERROR);
1414 setbit(drvr->eventmask, BRCMF_E_PMKID_CACHE);
1415 setbit(drvr->eventmask, BRCMF_E_TXFAIL);
1416 setbit(drvr->eventmask, BRCMF_E_JOIN_START);
1417 setbit(drvr->eventmask, BRCMF_E_SCAN_COMPLETE);
1418
1419/* enable dongle roaming event */
1420
1421 drvr->pktfilter_count = 1;
1422 /* Setup filter to allow only unicast */
1423 drvr->pktfilter[0] = "100 0 0 0 0x01 0x00";
1424
1425 /* Bus is ready, do any protocol initialization */
1426 ret = brcmf_proto_init(&drvr_priv->pub);
1427 if (ret < 0)
1428 return ret;
1429
1430 return 0;
1431}
1432
1433static struct net_device_ops brcmf_netdev_ops_pri = {
1434 .ndo_open = brcmf_netdev_open,
1435 .ndo_stop = brcmf_netdev_stop,
1436 .ndo_get_stats = brcmf_netdev_get_stats,
1437 .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
1438 .ndo_start_xmit = brcmf_netdev_start_xmit,
1439 .ndo_set_mac_address = brcmf_netdev_set_mac_address,
1440 .ndo_set_multicast_list = brcmf_netdev_set_multicast_list
1441};
1442
1443int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
1444{
1445 struct brcmf_info *drvr_priv = drvr->info;
1446 struct net_device *net;
1447 u8 temp_addr[ETH_ALEN] = {
1448 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33};
1449
1450 BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx));
1451
1452 net = drvr_priv->iflist[ifidx]->net;
1453 net->netdev_ops = &brcmf_netdev_ops_pri;
1454
1455 /*
1456 * We have to use the primary MAC for virtual interfaces
1457 */
1458 if (ifidx != 0) {
1459 /* for virtual interfaces use the primary MAC */
1460 memcpy(temp_addr, drvr_priv->pub.mac, ETH_ALEN);
1461
1462 }
1463
1464 if (ifidx == 1) {
1465 BRCMF_TRACE(("%s ACCESS POINT MAC:\n", __func__));
1466 /* ACCESSPOINT INTERFACE CASE */
1467 temp_addr[0] |= 0X02; /* set bit 2 ,
1468 - Locally Administered address */
1469
1470 }
1471 net->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen;
1472 net->ethtool_ops = &brcmf_ethtool_ops;
1473
1474 drvr_priv->pub.rxsz = net->mtu + net->hard_header_len +
1475 drvr_priv->pub.hdrlen;
1476
1477 memcpy(net->dev_addr, temp_addr, ETH_ALEN);
1478
1479 if (register_netdev(net) != 0) {
1480 BRCMF_ERROR(("%s: couldn't register the net device\n",
1481 __func__));
1482 goto fail;
1483 }
1484
1485 BRCMF_INFO(("%s: Broadcom Dongle Host Driver\n", net->name));
1486
1487 return 0;
1488
1489fail:
1490 net->netdev_ops = NULL;
1491 return -EBADE;
1492}
1493
1494static void brcmf_bus_detach(struct brcmf_pub *drvr)
1495{
1496 struct brcmf_info *drvr_priv;
1497
1498 BRCMF_TRACE(("%s: Enter\n", __func__));
1499
1500 if (drvr) {
1501 drvr_priv = drvr->info;
1502 if (drvr_priv) {
1503 /* Stop the protocol module */
1504 brcmf_proto_stop(&drvr_priv->pub);
1505
1506 /* Stop the bus module */
1507 brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus, true);
1508 }
1509 }
1510}
1511
1512void brcmf_detach(struct brcmf_pub *drvr)
1513{
1514 struct brcmf_info *drvr_priv;
1515
1516 BRCMF_TRACE(("%s: Enter\n", __func__));
1517
1518 if (drvr) {
1519 drvr_priv = drvr->info;
1520 if (drvr_priv) {
1521 struct brcmf_if *ifp;
1522 int i;
1523
1524 for (i = 1; i < BRCMF_MAX_IFS; i++)
1525 if (drvr_priv->iflist[i])
1526 brcmf_del_if(drvr_priv, i);
1527
1528 ifp = drvr_priv->iflist[0];
1529 if (ifp->net->netdev_ops == &brcmf_netdev_ops_pri) {
1530 brcmf_netdev_stop(ifp->net);
1531 unregister_netdev(ifp->net);
1532 }
1533
1534 if (drvr_priv->sysioc_tsk) {
1535 send_sig(SIGTERM, drvr_priv->sysioc_tsk, 1);
1536 kthread_stop(drvr_priv->sysioc_tsk);
1537 drvr_priv->sysioc_tsk = NULL;
1538 }
1539
1540 brcmf_bus_detach(drvr);
1541
1542 if (drvr->prot)
1543 brcmf_proto_detach(drvr);
1544
1545 brcmf_cfg80211_detach();
1546
1547 free_netdev(ifp->net);
1548 kfree(ifp);
1549 kfree(drvr_priv);
1550 }
1551 }
1552}
1553
1554static void __exit brcmf_module_cleanup(void)
1555{
1556 BRCMF_TRACE(("%s: Enter\n", __func__));
1557
1558 brcmf_bus_unregister();
1559}
1560
1561static int __init brcmf_module_init(void)
1562{
1563 int error;
1564
1565 BRCMF_TRACE(("%s: Enter\n", __func__));
1566
1567 error = brcmf_bus_register();
1568
1569 if (error) {
1570 BRCMF_ERROR(("%s: brcmf_bus_register failed\n", __func__));
1571 goto failed;
1572 }
1573 return 0;
1574
1575failed:
1576 return -EINVAL;
1577}
1578
1579module_init(brcmf_module_init);
1580module_exit(brcmf_module_cleanup);
1581
1582int brcmf_os_proto_block(struct brcmf_pub *drvr)
1583{
1584 struct brcmf_info *drvr_priv = drvr->info;
1585
1586 if (drvr_priv) {
1587 down(&drvr_priv->proto_sem);
1588 return 1;
1589 }
1590 return 0;
1591}
1592
1593int brcmf_os_proto_unblock(struct brcmf_pub *drvr)
1594{
1595 struct brcmf_info *drvr_priv = drvr->info;
1596
1597 if (drvr_priv) {
1598 up(&drvr_priv->proto_sem);
1599 return 1;
1600 }
1601
1602 return 0;
1603}
1604
1605unsigned int brcmf_os_get_ioctl_resp_timeout(void)
1606{
1607 return (unsigned int)brcmf_ioctl_timeout_msec;
1608}
1609
1610void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec)
1611{
1612 brcmf_ioctl_timeout_msec = (int)timeout_msec;
1613}
1614
1615int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition,
1616 bool *pending)
1617{
1618 struct brcmf_info *drvr_priv = drvr->info;
1619 DECLARE_WAITQUEUE(wait, current);
1620 int timeout = brcmf_ioctl_timeout_msec;
1621
1622 /* Convert timeout in millsecond to jiffies */
1623 timeout = timeout * HZ / 1000;
1624
1625 /* Wait until control frame is available */
1626 add_wait_queue(&drvr_priv->ioctl_resp_wait, &wait);
1627 set_current_state(TASK_INTERRUPTIBLE);
1628
1629 while (!(*condition) && (!signal_pending(current) && timeout))
1630 timeout = schedule_timeout(timeout);
1631
1632 if (signal_pending(current))
1633 *pending = true;
1634
1635 set_current_state(TASK_RUNNING);
1636 remove_wait_queue(&drvr_priv->ioctl_resp_wait, &wait);
1637
1638 return timeout;
1639}
1640
1641int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr)
1642{
1643 struct brcmf_info *drvr_priv = drvr->info;
1644
1645 if (waitqueue_active(&drvr_priv->ioctl_resp_wait))
1646 wake_up_interruptible(&drvr_priv->ioctl_resp_wait);
1647
1648 return 0;
1649}
1650
1651static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
1652 struct brcmf_event_msg *event, void **data)
1653{
1654 int bcmerror = 0;
1655
1656 bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data);
1657 if (bcmerror != 0)
1658 return bcmerror;
1659
1660 if (drvr_priv->iflist[*ifidx]->net)
1661 brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->net,
1662 event, *data);
1663
1664 return bcmerror;
1665}
1666
1667int brcmf_netdev_reset(struct net_device *dev, u8 flag)
1668{
1669 struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev);
1670
1671 brcmf_bus_devreset(&drvr_priv->pub, flag);
1672
1673 return 1;
1674}
1675
1676static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
1677{
1678 return atomic_read(&drvr_priv->pend_8021x_cnt);
1679}
1680
1681#define MAX_WAIT_FOR_8021X_TX 10
1682
1683int brcmf_netdev_wait_pend8021x(struct net_device *dev)
1684{
1685 struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev);
1686 int timeout = 10 * HZ / 1000;
1687 int ntimes = MAX_WAIT_FOR_8021X_TX;
1688 int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
1689
1690 while (ntimes && pend) {
1691 if (pend) {
1692 set_current_state(TASK_INTERRUPTIBLE);
1693 schedule_timeout(timeout);
1694 set_current_state(TASK_RUNNING);
1695 ntimes--;
1696 }
1697 pend = brcmf_get_pend_8021x_cnt(drvr_priv);
1698 }
1699 return pend;
1700}
1701
1702#ifdef BCMDBG
1703int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size)
1704{
1705 int ret = 0;
1706 struct file *fp;
1707 mm_segment_t old_fs;
1708 loff_t pos = 0;
1709
1710 /* change to KERNEL_DS address limit */
1711 old_fs = get_fs();
1712 set_fs(KERNEL_DS);
1713
1714 /* open file to write */
1715 fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640);
1716 if (!fp) {
1717 BRCMF_ERROR(("%s: open file error\n", __func__));
1718 ret = -1;
1719 goto exit;
1720 }
1721
1722 /* Write buf to file */
1723 fp->f_op->write(fp, buf, size, &pos);
1724
1725exit:
1726 /* free buf before return */
1727 kfree(buf);
1728 /* close file before return */
1729 if (fp)
1730 filp_close(fp, current->files);
1731 /* restore previous address limit */
1732 set_fs(old_fs);
1733
1734 return ret;
1735}
1736#endif /* BCMDBG */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h b/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
new file mode 100644
index 00000000000..ff788b37afd
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
@@ -0,0 +1,75 @@
1/*
2 * Copyright (c) 2010 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#ifndef _BRCMF_PROTO_H_
18#define _BRCMF_PROTO_H_
19
20#ifndef IOCTL_RESP_TIMEOUT
21#define IOCTL_RESP_TIMEOUT 2000 /* In milli second */
22#endif
23
24#ifndef IOCTL_CHIP_ACTIVE_TIMEOUT
25#define IOCTL_CHIP_ACTIVE_TIMEOUT 10 /* In milli second */
26#endif
27
28/*
29 * Exported from the brcmf protocol module (brcmf_cdc)
30 */
31
32/* Linkage, sets prot link and updates hdrlen in pub */
33extern int brcmf_proto_attach(struct brcmf_pub *drvr);
34
35/* Unlink, frees allocated protocol memory (including brcmf_proto) */
36extern void brcmf_proto_detach(struct brcmf_pub *drvr);
37
38/* Initialize protocol: sync w/dongle state.
39 * Sets dongle media info (iswl, drv_version, mac address).
40 */
41extern int brcmf_proto_init(struct brcmf_pub *drvr);
42
43/* Stop protocol: sync w/dongle state. */
44extern void brcmf_proto_stop(struct brcmf_pub *drvr);
45
46/* Add any protocol-specific data header.
47 * Caller must reserve prot_hdrlen prepend space.
48 */
49extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
50 struct sk_buff *txp);
51
52/* Remove any protocol-specific data header. */
53extern int brcmf_proto_hdrpull(struct brcmf_pub *, int *ifidx,
54 struct sk_buff *rxp);
55
56/* Use protocol to issue ioctl to dongle */
57extern int brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx,
58 struct brcmf_ioctl *ioc, void *buf, int len);
59
60/* Add prot dump output to a buffer */
61extern void brcmf_proto_dump(struct brcmf_pub *drvr,
62 struct brcmu_strbuf *strbuf);
63
64/* Update local copy of dongle statistics */
65extern void brcmf_proto_dstats(struct brcmf_pub *drvr);
66
67extern int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc,
68 void *buf, uint buflen);
69
70extern int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr);
71
72extern int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx,
73 uint cmd, void *buf, uint len);
74
75#endif /* _BRCMF_PROTO_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
new file mode 100644
index 00000000000..7fa95b6213c
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
@@ -0,0 +1,6772 @@
1/*
2 * Copyright (c) 2010 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#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/kthread.h>
20#include <linux/printk.h>
21#include <linux/pci_ids.h>
22#include <linux/netdevice.h>
23#include <linux/interrupt.h>
24#include <linux/sched.h>
25#include <linux/mmc/sdio.h>
26#include <linux/mmc/sdio_func.h>
27#include <linux/semaphore.h>
28#include <linux/firmware.h>
29#include <asm/unaligned.h>
30#include <defs.h>
31#include <brcmu_wifi.h>
32#include <brcmu_utils.h>
33#include <brcm_hw_ids.h>
34#include <soc.h>
35#include "sdio_host.h"
36
37/* register access macros */
38#ifndef __BIG_ENDIAN
39#ifndef __mips__
40#define R_REG(r, typ) \
41 brcmf_sdcard_reg_read(NULL, (r), sizeof(typ))
42#else /* __mips__ */
43#define R_REG(r, typ) \
44 ({ \
45 __typeof(*(r)) __osl_v; \
46 __asm__ __volatile__("sync"); \
47 __osl_v = brcmf_sdcard_reg_read(NULL, (r),\
48 sizeof(typ)); \
49 __asm__ __volatile__("sync"); \
50 __osl_v; \
51 })
52#endif /* __mips__ */
53
54#else /* __BIG_ENDIAN */
55#define R_REG(r, typ) \
56 brcmf_sdcard_reg_read(NULL, (r), sizeof(typ))
57#endif /* __BIG_ENDIAN */
58
59#define OR_REG(r, v, typ) \
60 brcmf_sdcard_reg_write(NULL, (r), sizeof(typ), R_REG(r, typ) | (v))
61
62#ifdef BCMDBG
63
64/* ARM trap handling */
65
66/* Trap types defined by ARM (see arminc.h) */
67
68#if defined(__ARM_ARCH_4T__)
69#define MAX_TRAP_TYPE (TR_FIQ + 1)
70#elif defined(__ARM_ARCH_7M__)
71#define MAX_TRAP_TYPE (TR_ISR + ARMCM3_NUMINTS)
72#endif /* __ARM_ARCH_7M__ */
73
74/* The trap structure is defined here as offsets for assembly */
75#define TR_TYPE 0x00
76#define TR_EPC 0x04
77#define TR_CPSR 0x08
78#define TR_SPSR 0x0c
79#define TR_REGS 0x10
80#define TR_REG(n) (TR_REGS + (n) * 4)
81#define TR_SP TR_REG(13)
82#define TR_LR TR_REG(14)
83#define TR_PC TR_REG(15)
84
85#define TRAP_T_SIZE 80
86
87struct brcmf_trap {
88 u32 type;
89 u32 epc;
90 u32 cpsr;
91 u32 spsr;
92 u32 r0;
93 u32 r1;
94 u32 r2;
95 u32 r3;
96 u32 r4;
97 u32 r5;
98 u32 r6;
99 u32 r7;
100 u32 r8;
101 u32 r9;
102 u32 r10;
103 u32 r11;
104 u32 r12;
105 u32 r13;
106 u32 r14;
107 u32 pc;
108};
109
110#define CBUF_LEN (128)
111
112struct rte_log {
113 u32 buf; /* Can't be pointer on (64-bit) hosts */
114 uint buf_size;
115 uint idx;
116 char *_buf_compat; /* Redundant pointer for backward compat. */
117};
118
119struct rte_console {
120 /* Virtual UART
121 * When there is no UART (e.g. Quickturn),
122 * the host should write a complete
123 * input line directly into cbuf and then write
124 * the length into vcons_in.
125 * This may also be used when there is a real UART
126 * (at risk of conflicting with
127 * the real UART). vcons_out is currently unused.
128 */
129 volatile uint vcons_in;
130 volatile uint vcons_out;
131
132 /* Output (logging) buffer
133 * Console output is written to a ring buffer log_buf at index log_idx.
134 * The host may read the output when it sees log_idx advance.
135 * Output will be lost if the output wraps around faster than the host
136 * polls.
137 */
138 struct rte_log log;
139
140 /* Console input line buffer
141 * Characters are read one at a time into cbuf
142 * until <CR> is received, then
143 * the buffer is processed as a command line.
144 * Also used for virtual UART.
145 */
146 uint cbuf_idx;
147 char cbuf[CBUF_LEN];
148};
149
150#endif /* BCMDBG */
151#include <chipcommon.h>
152
153#include "dhd.h"
154#include "dhd_bus.h"
155#include "dhd_proto.h"
156#include "dhd_dbg.h"
157#include <bcmchip.h>
158
159#define TXQLEN 2048 /* bulk tx queue length */
160#define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */
161#define TXLOW (TXHI - 256) /* turn off flow control below TXLOW */
162#define PRIOMASK 7
163
164#define TXRETRIES 2 /* # of retries for tx frames */
165
166#define BRCMF_RXBOUND 50 /* Default for max rx frames in
167 one scheduling */
168
169#define BRCMF_TXBOUND 20 /* Default for max tx frames in
170 one scheduling */
171
172#define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */
173
174#define MEMBLOCK 2048 /* Block size used for downloading
175 of dongle image */
176#define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold
177 biggest possible glom */
178
179#ifndef BRCMF_FIRSTREAD
180#define BRCMF_FIRSTREAD 32
181#endif
182
183#if !ISPOWEROF2(BRCMF_FIRSTREAD)
184#error BRCMF_FIRSTREAD is not a power of 2!
185#endif
186
187/* SBSDIO_DEVICE_CTL */
188#define SBSDIO_DEVCTL_SETBUSY 0x01 /* 1: device will assert busy signal when
189 * receiving CMD53
190 */
191#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 /* 1: assertion of sdio interrupt is
192 * synchronous to the sdio clock
193 */
194#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 /* 1: mask all interrupts to host
195 * except the chipActive (rev 8)
196 */
197#define SBSDIO_DEVCTL_PADS_ISO 0x08 /* 1: isolate internal sdio signals, put
198 * external pads in tri-state; requires
199 * sdio bus power cycle to clear (rev 9)
200 */
201#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 /* Force SD->SB reset mapping (rev 11) */
202#define SBSDIO_DEVCTL_RST_CORECTL 0x00 /* Determined by CoreControl bit */
203#define SBSDIO_DEVCTL_RST_BPRESET 0x10 /* Force backplane reset */
204#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 /* Force no backplane reset */
205
206/* SBSDIO_FUNC1_CHIPCLKCSR */
207#define SBSDIO_FORCE_ALP 0x01 /* Force ALP request to backplane */
208#define SBSDIO_FORCE_HT 0x02 /* Force HT request to backplane */
209#define SBSDIO_FORCE_ILP 0x04 /* Force ILP request to backplane */
210#define SBSDIO_ALP_AVAIL_REQ 0x08 /* Make ALP ready (power up xtal) */
211#define SBSDIO_HT_AVAIL_REQ 0x10 /* Make HT ready (power up PLL) */
212#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 /* Squelch clock requests from HW */
213#define SBSDIO_ALP_AVAIL 0x40 /* Status: ALP is ready */
214#define SBSDIO_HT_AVAIL 0x80 /* Status: HT is ready */
215
216#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
217#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS)
218#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
219#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
220#define SBSDIO_CLKAV(regval, alponly) (SBSDIO_ALPAV(regval) && \
221 (alponly ? 1 : SBSDIO_HTAV(regval)))
222/* direct(mapped) cis space */
223#define SBSDIO_CIS_BASE_COMMON 0x1000 /* MAPPED common CIS address */
224#define SBSDIO_CIS_SIZE_LIMIT 0x200 /* maximum bytes in one CIS */
225#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF /* cis offset addr is < 17 bits */
226
227#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 /* manfid tuple length, include tuple,
228 * link bytes
229 */
230
231/* intstatus */
232#define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */
233#define I_SMB_SW1 (1 << 1) /* To SB Mail S/W interrupt 1 */
234#define I_SMB_SW2 (1 << 2) /* To SB Mail S/W interrupt 2 */
235#define I_SMB_SW3 (1 << 3) /* To SB Mail S/W interrupt 3 */
236#define I_SMB_SW_MASK 0x0000000f /* To SB Mail S/W interrupts mask */
237#define I_SMB_SW_SHIFT 0 /* To SB Mail S/W interrupts shift */
238#define I_HMB_SW0 (1 << 4) /* To Host Mail S/W interrupt 0 */
239#define I_HMB_SW1 (1 << 5) /* To Host Mail S/W interrupt 1 */
240#define I_HMB_SW2 (1 << 6) /* To Host Mail S/W interrupt 2 */
241#define I_HMB_SW3 (1 << 7) /* To Host Mail S/W interrupt 3 */
242#define I_HMB_SW_MASK 0x000000f0 /* To Host Mail S/W interrupts mask */
243#define I_HMB_SW_SHIFT 4 /* To Host Mail S/W interrupts shift */
244#define I_WR_OOSYNC (1 << 8) /* Write Frame Out Of Sync */
245#define I_RD_OOSYNC (1 << 9) /* Read Frame Out Of Sync */
246#define I_PC (1 << 10) /* descriptor error */
247#define I_PD (1 << 11) /* data error */
248#define I_DE (1 << 12) /* Descriptor protocol Error */
249#define I_RU (1 << 13) /* Receive descriptor Underflow */
250#define I_RO (1 << 14) /* Receive fifo Overflow */
251#define I_XU (1 << 15) /* Transmit fifo Underflow */
252#define I_RI (1 << 16) /* Receive Interrupt */
253#define I_BUSPWR (1 << 17) /* SDIO Bus Power Change (rev 9) */
254#define I_XMTDATA_AVAIL (1 << 23) /* bits in fifo */
255#define I_XI (1 << 24) /* Transmit Interrupt */
256#define I_RF_TERM (1 << 25) /* Read Frame Terminate */
257#define I_WF_TERM (1 << 26) /* Write Frame Terminate */
258#define I_PCMCIA_XU (1 << 27) /* PCMCIA Transmit FIFO Underflow */
259#define I_SBINT (1 << 28) /* sbintstatus Interrupt */
260#define I_CHIPACTIVE (1 << 29) /* chip from doze to active state */
261#define I_SRESET (1 << 30) /* CCCR RES interrupt */
262#define I_IOE2 (1U << 31) /* CCCR IOE2 Bit Changed */
263#define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU)
264#define I_DMA (I_RI | I_XI | I_ERRORS)
265
266/* corecontrol */
267#define CC_CISRDY (1 << 0) /* CIS Ready */
268#define CC_BPRESEN (1 << 1) /* CCCR RES signal */
269#define CC_F2RDY (1 << 2) /* set CCCR IOR2 bit */
270#define CC_CLRPADSISO (1 << 3) /* clear SDIO pads isolation */
271#define CC_XMTDATAAVAIL_MODE (1 << 4)
272#define CC_XMTDATAAVAIL_CTRL (1 << 5)
273
274/* SDA_FRAMECTRL */
275#define SFC_RF_TERM (1 << 0) /* Read Frame Terminate */
276#define SFC_WF_TERM (1 << 1) /* Write Frame Terminate */
277#define SFC_CRC4WOOS (1 << 2) /* CRC error for write out of sync */
278#define SFC_ABORTALL (1 << 3) /* Abort all in-progress frames */
279
280/* HW frame tag */
281#define SDPCM_FRAMETAG_LEN 4 /* 2 bytes len, 2 bytes check val */
282
283/* Total length of frame header for dongle protocol */
284#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
285#ifdef SDTEST
286#define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN)
287#else
288#define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN)
289#endif
290
291/*
292 * Software allocation of To SB Mailbox resources
293 */
294
295/* tosbmailbox bits corresponding to intstatus bits */
296#define SMB_NAK (1 << 0) /* Frame NAK */
297#define SMB_INT_ACK (1 << 1) /* Host Interrupt ACK */
298#define SMB_USE_OOB (1 << 2) /* Use OOB Wakeup */
299#define SMB_DEV_INT (1 << 3) /* Miscellaneous Interrupt */
300
301/* tosbmailboxdata */
302#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version */
303
304/*
305 * Software allocation of To Host Mailbox resources
306 */
307
308/* intstatus bits */
309#define I_HMB_FC_STATE I_HMB_SW0 /* Flow Control State */
310#define I_HMB_FC_CHANGE I_HMB_SW1 /* Flow Control State Changed */
311#define I_HMB_FRAME_IND I_HMB_SW2 /* Frame Indication */
312#define I_HMB_HOST_INT I_HMB_SW3 /* Miscellaneous Interrupt */
313
314/* tohostmailboxdata */
315#define HMB_DATA_NAKHANDLED 1 /* retransmit NAK'd frame */
316#define HMB_DATA_DEVREADY 2 /* talk to host after enable */
317#define HMB_DATA_FC 4 /* per prio flowcontrol update flag */
318#define HMB_DATA_FWREADY 8 /* fw ready for protocol activity */
319
320#define HMB_DATA_FCDATA_MASK 0xff000000
321#define HMB_DATA_FCDATA_SHIFT 24
322
323#define HMB_DATA_VERSION_MASK 0x00ff0000
324#define HMB_DATA_VERSION_SHIFT 16
325
326/*
327 * Software-defined protocol header
328 */
329
330/* Current protocol version */
331#define SDPCM_PROT_VERSION 4
332
333/* SW frame header */
334#define SDPCM_PACKET_SEQUENCE(p) (((u8 *)p)[0] & 0xff)
335
336#define SDPCM_CHANNEL_MASK 0x00000f00
337#define SDPCM_CHANNEL_SHIFT 8
338#define SDPCM_PACKET_CHANNEL(p) (((u8 *)p)[1] & 0x0f)
339
340#define SDPCM_NEXTLEN_OFFSET 2
341
342/* Data Offset from SOF (HW Tag, SW Tag, Pad) */
343#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */
344#define SDPCM_DOFFSET_VALUE(p) (((u8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff)
345#define SDPCM_DOFFSET_MASK 0xff000000
346#define SDPCM_DOFFSET_SHIFT 24
347#define SDPCM_FCMASK_OFFSET 4 /* Flow control */
348#define SDPCM_FCMASK_VALUE(p) (((u8 *)p)[SDPCM_FCMASK_OFFSET] & 0xff)
349#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */
350#define SDPCM_WINDOW_VALUE(p) (((u8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff)
351
352#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */
353
354/* logical channel numbers */
355#define SDPCM_CONTROL_CHANNEL 0 /* Control channel Id */
356#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */
357#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */
358#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets */
359#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */
360
361#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for 8bit frame seq */
362
363#define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80)
364
365/* For TEST_CHANNEL packets, define another 4-byte header */
366#define SDPCM_TEST_HDRLEN 4 /*
367 * Generally: Cmd(1), Ext(1), Len(2);
368 * Semantics of Ext byte depend on
369 * command. Len is current or requested
370 * frame length, not including test
371 * header; sent little-endian.
372 */
373#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext:pattern id. */
374#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext:pattern id. */
375#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext:pattern id. */
376#define SDPCM_TEST_BURST 0x04 /*
377 * Receiver to send a burst.
378 * Ext is a frame count
379 */
380#define SDPCM_TEST_SEND 0x05 /*
381 * Receiver sets send mode.
382 * Ext is boolean on/off
383 */
384
385/* Handy macro for filling in datagen packets with a pattern */
386#define SDPCM_TEST_FILL(byteno, id) ((u8)(id + byteno))
387
388/*
389 * Shared structure between dongle and the host.
390 * The structure contains pointers to trap or assert information.
391 */
392#define SDPCM_SHARED_VERSION 0x0002
393#define SDPCM_SHARED_VERSION_MASK 0x00FF
394#define SDPCM_SHARED_ASSERT_BUILT 0x0100
395#define SDPCM_SHARED_ASSERT 0x0200
396#define SDPCM_SHARED_TRAP 0x0400
397
398
399/* Space for header read, limit for data packets */
400#ifndef MAX_HDR_READ
401#define MAX_HDR_READ 32
402#endif
403#if !ISPOWEROF2(MAX_HDR_READ)
404#error MAX_HDR_READ is not a power of 2!
405#endif
406
407#define MAX_RX_DATASZ 2048
408
409/* Maximum milliseconds to wait for F2 to come up */
410#define BRCMF_WAIT_F2RDY 3000
411
412/* Bump up limit on waiting for HT to account for first startup;
413 * if the image is doing a CRC calculation before programming the PMU
414 * for HT availability, it could take a couple hundred ms more, so
415 * max out at a 1 second (1000000us).
416 */
417#if (PMU_MAX_TRANSITION_DLY <= 1000000)
418#undef PMU_MAX_TRANSITION_DLY
419#define PMU_MAX_TRANSITION_DLY 1000000
420#endif
421
422/* Value for ChipClockCSR during initial setup */
423#define BRCMF_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | \
424 SBSDIO_ALP_AVAIL_REQ)
425
426/* Flags for SDH calls */
427#define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
428
429/* sbimstate */
430#define SBIM_IBE 0x20000 /* inbanderror */
431#define SBIM_TO 0x40000 /* timeout */
432#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */
433#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */
434
435/* sbtmstatelow */
436#define SBTML_RESET 0x0001 /* reset */
437#define SBTML_REJ_MASK 0x0006 /* reject field */
438#define SBTML_REJ 0x0002 /* reject */
439#define SBTML_TMPREJ 0x0004 /* temporary reject, for error recovery */
440
441#define SBTML_SICF_SHIFT 16 /* Shift to locate the SI control flags in sbtml */
442
443/* sbtmstatehigh */
444#define SBTMH_SERR 0x0001 /* serror */
445#define SBTMH_INT 0x0002 /* interrupt */
446#define SBTMH_BUSY 0x0004 /* busy */
447#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */
448
449#define SBTMH_SISF_SHIFT 16 /* Shift to locate the SI status flags in sbtmh */
450
451/* sbidlow */
452#define SBIDL_INIT 0x80 /* initiator */
453
454/* sbidhigh */
455#define SBIDH_RC_MASK 0x000f /* revision code */
456#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */
457#define SBIDH_RCE_SHIFT 8
458#define SBCOREREV(sbidh) \
459 ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK))
460#define SBIDH_CC_MASK 0x8ff0 /* core code */
461#define SBIDH_CC_SHIFT 4
462#define SBIDH_VC_MASK 0xffff0000 /* vendor code */
463#define SBIDH_VC_SHIFT 16
464
465/*
466 * Conversion of 802.1D priority to precedence level
467 */
468#define PRIO2PREC(prio) \
469 (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \
470 ((prio^2)) : (prio))
471
472BRCMF_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
473
474/*
475 * Core reg address translation.
476 * Both macro's returns a 32 bits byte address on the backplane bus.
477 */
478#define CORE_CC_REG(base, field) (base + offsetof(chipcregs_t, field))
479#define CORE_BUS_REG(base, field) \
480 (base + offsetof(struct sdpcmd_regs, field))
481#define CORE_SB(base, field) \
482 (base + SBCONFIGOFF + offsetof(struct sbconfig, field))
483
484/* core registers */
485struct sdpcmd_regs {
486 u32 corecontrol; /* 0x00, rev8 */
487 u32 corestatus; /* rev8 */
488 u32 PAD[1];
489 u32 biststatus; /* rev8 */
490
491 /* PCMCIA access */
492 u16 pcmciamesportaladdr; /* 0x010, rev8 */
493 u16 PAD[1];
494 u16 pcmciamesportalmask; /* rev8 */
495 u16 PAD[1];
496 u16 pcmciawrframebc; /* rev8 */
497 u16 PAD[1];
498 u16 pcmciaunderflowtimer; /* rev8 */
499 u16 PAD[1];
500
501 /* interrupt */
502 u32 intstatus; /* 0x020, rev8 */
503 u32 hostintmask; /* rev8 */
504 u32 intmask; /* rev8 */
505 u32 sbintstatus; /* rev8 */
506 u32 sbintmask; /* rev8 */
507 u32 funcintmask; /* rev4 */
508 u32 PAD[2];
509 u32 tosbmailbox; /* 0x040, rev8 */
510 u32 tohostmailbox; /* rev8 */
511 u32 tosbmailboxdata; /* rev8 */
512 u32 tohostmailboxdata; /* rev8 */
513
514 /* synchronized access to registers in SDIO clock domain */
515 u32 sdioaccess; /* 0x050, rev8 */
516 u32 PAD[3];
517
518 /* PCMCIA frame control */
519 u8 pcmciaframectrl; /* 0x060, rev8 */
520 u8 PAD[3];
521 u8 pcmciawatermark; /* rev8 */
522 u8 PAD[155];
523
524 /* interrupt batching control */
525 u32 intrcvlazy; /* 0x100, rev8 */
526 u32 PAD[3];
527
528 /* counters */
529 u32 cmd52rd; /* 0x110, rev8 */
530 u32 cmd52wr; /* rev8 */
531 u32 cmd53rd; /* rev8 */
532 u32 cmd53wr; /* rev8 */
533 u32 abort; /* rev8 */
534 u32 datacrcerror; /* rev8 */
535 u32 rdoutofsync; /* rev8 */
536 u32 wroutofsync; /* rev8 */
537 u32 writebusy; /* rev8 */
538 u32 readwait; /* rev8 */
539 u32 readterm; /* rev8 */
540 u32 writeterm; /* rev8 */
541 u32 PAD[40];
542 u32 clockctlstatus; /* rev8 */
543 u32 PAD[7];
544
545 u32 PAD[128]; /* DMA engines */
546
547 /* SDIO/PCMCIA CIS region */
548 char cis[512]; /* 0x400-0x5ff, rev6 */
549
550 /* PCMCIA function control registers */
551 char pcmciafcr[256]; /* 0x600-6ff, rev6 */
552 u16 PAD[55];
553
554 /* PCMCIA backplane access */
555 u16 backplanecsr; /* 0x76E, rev6 */
556 u16 backplaneaddr0; /* rev6 */
557 u16 backplaneaddr1; /* rev6 */
558 u16 backplaneaddr2; /* rev6 */
559 u16 backplaneaddr3; /* rev6 */
560 u16 backplanedata0; /* rev6 */
561 u16 backplanedata1; /* rev6 */
562 u16 backplanedata2; /* rev6 */
563 u16 backplanedata3; /* rev6 */
564 u16 PAD[31];
565
566 /* sprom "size" & "blank" info */
567 u16 spromstatus; /* 0x7BE, rev2 */
568 u32 PAD[464];
569
570 u16 PAD[0x80];
571};
572
573#ifdef BCMDBG
574/* Device console log buffer state */
575struct brcmf_console {
576 uint count; /* Poll interval msec counter */
577 uint log_addr; /* Log struct address (fixed) */
578 struct rte_log log; /* Log struct (host copy) */
579 uint bufsize; /* Size of log buffer */
580 u8 *buf; /* Log buffer (host copy) */
581 uint last; /* Last buffer read index */
582};
583#endif /* BCMDBG */
584
585struct sdpcm_shared {
586 u32 flags;
587 u32 trap_addr;
588 u32 assert_exp_addr;
589 u32 assert_file_addr;
590 u32 assert_line;
591 u32 console_addr; /* Address of struct rte_console */
592 u32 msgtrace_addr;
593 u8 tag[32];
594};
595
596
597/* misc chip info needed by some of the routines */
598struct chip_info {
599 u32 chip;
600 u32 chiprev;
601 u32 cccorebase;
602 u32 ccrev;
603 u32 cccaps;
604 u32 buscorebase; /* 32 bits backplane bus address */
605 u32 buscorerev;
606 u32 buscoretype;
607 u32 ramcorebase;
608 u32 armcorebase;
609 u32 pmurev;
610 u32 ramsize;
611};
612
613/* Private data for SDIO bus interaction */
614struct brcmf_bus {
615 struct brcmf_pub *drvr;
616
617 struct brcmf_sdio_card *card; /* Handle for sdio card calls */
618 struct chip_info *ci; /* Chip info struct */
619 char *vars; /* Variables (from CIS and/or other) */
620 uint varsz; /* Size of variables buffer */
621
622 u32 ramsize; /* Size of RAM in SOCRAM (bytes) */
623 u32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */
624
625 u32 bus; /* gSPI or SDIO bus */
626 u32 hostintmask; /* Copy of Host Interrupt Mask */
627 u32 intstatus; /* Intstatus bits (events) pending */
628 bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
629 bool fcstate; /* State of dongle flow-control */
630
631 u16 cl_devid; /* cached devid for brcmf_sdio_probe_attach() */
632
633 uint blocksize; /* Block size of SDIO transfers */
634 uint roundup; /* Max roundup limit */
635
636 struct pktq txq; /* Queue length used for flow-control */
637 u8 flowcontrol; /* per prio flow control bitmask */
638 u8 tx_seq; /* Transmit sequence number (next) */
639 u8 tx_max; /* Maximum transmit sequence allowed */
640
641 u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN];
642 u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */
643 u16 nextlen; /* Next Read Len from last header */
644 u8 rx_seq; /* Receive sequence number (expected) */
645 bool rxskip; /* Skip receive (awaiting NAK ACK) */
646
647 struct sk_buff *glomd; /* Packet containing glomming descriptor */
648 struct sk_buff *glom; /* Packet chain for glommed superframe */
649 uint glomerr; /* Glom packet read errors */
650
651 u8 *rxbuf; /* Buffer for receiving control packets */
652 uint rxblen; /* Allocated length of rxbuf */
653 u8 *rxctl; /* Aligned pointer into rxbuf */
654 u8 *databuf; /* Buffer for receiving big glom packet */
655 u8 *dataptr; /* Aligned pointer into databuf */
656 uint rxlen; /* Length of valid data in buffer */
657
658 u8 sdpcm_ver; /* Bus protocol reported by dongle */
659
660 bool intr; /* Use interrupts */
661 bool poll; /* Use polling */
662 bool ipend; /* Device interrupt is pending */
663 bool intdis; /* Interrupts disabled by isr */
664 uint intrcount; /* Count of device interrupt callbacks */
665 uint lastintrs; /* Count as of last watchdog timer */
666 uint spurious; /* Count of spurious interrupts */
667 uint pollrate; /* Ticks between device polls */
668 uint polltick; /* Tick counter */
669 uint pollcnt; /* Count of active polls */
670
671#ifdef BCMDBG
672 struct brcmf_console console; /* Console output polling support */
673 uint console_addr; /* Console address from shared struct */
674#endif /* BCMDBG */
675
676 uint regfails; /* Count of R_REG failures */
677
678 uint clkstate; /* State of sd and backplane clock(s) */
679 bool activity; /* Activity flag for clock down */
680 s32 idletime; /* Control for activity timeout */
681 s32 idlecount; /* Activity timeout counter */
682 s32 idleclock; /* How to set bus driver when idle */
683 s32 sd_rxchain;
684 bool use_rxchain; /* If brcmf should use PKT chains */
685 bool sleeping; /* Is SDIO bus sleeping? */
686 bool rxflow_mode; /* Rx flow control mode */
687 bool rxflow; /* Is rx flow control on */
688 bool alp_only; /* Don't use HT clock (ALP only) */
689/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
690 bool usebufpool;
691
692#ifdef SDTEST
693 /* external loopback */
694 bool ext_loop;
695 u8 loopid;
696
697 /* pktgen configuration */
698 uint pktgen_freq; /* Ticks between bursts */
699 uint pktgen_count; /* Packets to send each burst */
700 uint pktgen_print; /* Bursts between count displays */
701 uint pktgen_total; /* Stop after this many */
702 uint pktgen_minlen; /* Minimum packet data len */
703 uint pktgen_maxlen; /* Maximum packet data len */
704 uint pktgen_mode; /* Configured mode: tx, rx, or echo */
705 uint pktgen_stop; /* Number of tx failures causing stop */
706
707 /* active pktgen fields */
708 uint pktgen_tick; /* Tick counter for bursts */
709 uint pktgen_ptick; /* Burst counter for printing */
710 uint pktgen_sent; /* Number of test packets generated */
711 uint pktgen_rcvd; /* Number of test packets received */
712 uint pktgen_fail; /* Number of failed send attempts */
713 u16 pktgen_len; /* Length of next packet to send */
714#endif /* SDTEST */
715
716 /* Some additional counters */
717 uint tx_sderrs; /* Count of tx attempts with sd errors */
718 uint fcqueued; /* Tx packets that got queued */
719 uint rxrtx; /* Count of rtx requests (NAK to dongle) */
720 uint rx_toolong; /* Receive frames too long to receive */
721 uint rxc_errors; /* SDIO errors when reading control frames */
722 uint rx_hdrfail; /* SDIO errors on header reads */
723 uint rx_badhdr; /* Bad received headers (roosync?) */
724 uint rx_badseq; /* Mismatched rx sequence number */
725 uint fc_rcvd; /* Number of flow-control events received */
726 uint fc_xoff; /* Number which turned on flow-control */
727 uint fc_xon; /* Number which turned off flow-control */
728 uint rxglomfail; /* Failed deglom attempts */
729 uint rxglomframes; /* Number of glom frames (superframes) */
730 uint rxglompkts; /* Number of packets from glom frames */
731 uint f2rxhdrs; /* Number of header reads */
732 uint f2rxdata; /* Number of frame data reads */
733 uint f2txdata; /* Number of f2 frame writes */
734 uint f1regdata; /* Number of f1 register accesses */
735
736 u8 *ctrl_frame_buf;
737 u32 ctrl_frame_len;
738 bool ctrl_frame_stat;
739
740 spinlock_t txqlock;
741 wait_queue_head_t ctrl_wait;
742
743 struct timer_list timer;
744 struct completion watchdog_wait;
745 struct task_struct *watchdog_tsk;
746 bool wd_timer_valid;
747
748 struct tasklet_struct tasklet;
749 struct task_struct *dpc_tsk;
750 struct completion dpc_wait;
751
752 bool threads_only;
753 struct semaphore sdsem;
754 spinlock_t sdlock;
755
756 const char *fw_name;
757 const struct firmware *firmware;
758 const char *nv_name;
759 u32 fw_ptr;
760};
761
762struct sbconfig {
763 u32 PAD[2];
764 u32 sbipsflag; /* initiator port ocp slave flag */
765 u32 PAD[3];
766 u32 sbtpsflag; /* target port ocp slave flag */
767 u32 PAD[11];
768 u32 sbtmerrloga; /* (sonics >= 2.3) */
769 u32 PAD;
770 u32 sbtmerrlog; /* (sonics >= 2.3) */
771 u32 PAD[3];
772 u32 sbadmatch3; /* address match3 */
773 u32 PAD;
774 u32 sbadmatch2; /* address match2 */
775 u32 PAD;
776 u32 sbadmatch1; /* address match1 */
777 u32 PAD[7];
778 u32 sbimstate; /* initiator agent state */
779 u32 sbintvec; /* interrupt mask */
780 u32 sbtmstatelow; /* target state */
781 u32 sbtmstatehigh; /* target state */
782 u32 sbbwa0; /* bandwidth allocation table0 */
783 u32 PAD;
784 u32 sbimconfiglow; /* initiator configuration */
785 u32 sbimconfighigh; /* initiator configuration */
786 u32 sbadmatch0; /* address match0 */
787 u32 PAD;
788 u32 sbtmconfiglow; /* target configuration */
789 u32 sbtmconfighigh; /* target configuration */
790 u32 sbbconfig; /* broadcast configuration */
791 u32 PAD;
792 u32 sbbstate; /* broadcast state */
793 u32 PAD[3];
794 u32 sbactcnfg; /* activate configuration */
795 u32 PAD[3];
796 u32 sbflagst; /* current sbflags */
797 u32 PAD[3];
798 u32 sbidlow; /* identification */
799 u32 sbidhigh; /* identification */
800};
801
802/* clkstate */
803#define CLK_NONE 0
804#define CLK_SDONLY 1
805#define CLK_PENDING 2 /* Not used yet */
806#define CLK_AVAIL 3
807
808#define BRCMF_NOPMU(brcmf) (false)
809
810#ifdef BCMDBG
811static int qcount[NUMPRIO];
812static int tx_packets[NUMPRIO];
813#endif /* BCMDBG */
814
815/* Deferred transmit */
816uint brcmf_deferred_tx = 1;
817module_param(brcmf_deferred_tx, uint, 0);
818
819/* Watchdog thread priority, -1 to use kernel timer */
820int brcmf_watchdog_prio = 97;
821module_param(brcmf_watchdog_prio, int, 0);
822
823/* Watchdog interval */
824uint brcmf_watchdog_ms = 10;
825module_param(brcmf_watchdog_ms, uint, 0);
826
827/* DPC thread priority, -1 to use tasklet */
828int brcmf_dpc_prio = 98;
829module_param(brcmf_dpc_prio, int, 0);
830
831#ifdef BCMDBG
832/* Console poll interval */
833uint brcmf_console_ms;
834module_param(brcmf_console_ms, uint, 0);
835#endif /* BCMDBG */
836
837/* Tx/Rx bounds */
838uint brcmf_txbound;
839uint brcmf_rxbound;
840uint brcmf_txminmax;
841
842/* override the RAM size if possible */
843#define DONGLE_MIN_MEMSIZE (128 * 1024)
844int brcmf_dongle_memsize;
845
846static bool brcmf_alignctl;
847
848static bool sd1idle;
849
850static bool retrydata;
851#define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
852
853static const uint watermark = 8;
854static const uint firstread = BRCMF_FIRSTREAD;
855
856/* Retry count for register access failures */
857static const uint retry_limit = 2;
858
859/* Force even SD lengths (some host controllers mess up on odd bytes) */
860static bool forcealign;
861
862#define ALIGNMENT 4
863
864#define PKTALIGN(_p, _len, _align) \
865 do { \
866 uint datalign; \
867 datalign = (unsigned long)((_p)->data); \
868 datalign = roundup(datalign, (_align)) - datalign; \
869 if (datalign) \
870 skb_pull((_p), datalign); \
871 __skb_trim((_p), (_len)); \
872 } while (0)
873
874/* Limit on rounding up frames */
875static const uint max_roundup = 512;
876
877/* Try doing readahead */
878static bool brcmf_readahead;
879
880/* To check if there's window offered */
881#define DATAOK(bus) \
882 (((u8)(bus->tx_max - bus->tx_seq) != 0) && \
883 (((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
884
885/*
886 * Reads a register in the SDIO hardware block. This block occupies a series of
887 * adresses on the 32 bit backplane bus.
888 */
889static void
890r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
891{
892 *retryvar = 0;
893 do {
894 *regvar = R_REG(bus->ci->buscorebase + reg_offset, u32);
895 } while (brcmf_sdcard_regfail(bus->card) &&
896 (++(*retryvar) <= retry_limit));
897 if (*retryvar) {
898 bus->regfails += (*retryvar-1);
899 if (*retryvar > retry_limit) {
900 BRCMF_ERROR(("FAILED READ %Xh\n", reg_offset));
901 *regvar = 0;
902 }
903 }
904}
905
906static void
907w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar)
908{
909 *retryvar = 0;
910 do {
911 brcmf_sdcard_reg_write(NULL, bus->ci->buscorebase + reg_offset,
912 sizeof(u32), regval);
913 } while (brcmf_sdcard_regfail(bus->card) &&
914 (++(*retryvar) <= retry_limit));
915 if (*retryvar) {
916 bus->regfails += (*retryvar-1);
917 if (*retryvar > retry_limit)
918 BRCMF_ERROR(("FAILED REGISTER WRITE"
919 " %Xh\n", reg_offset));
920 }
921}
922
923#define BRCMF_BUS SDIO_BUS
924
925#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
926
927#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
928
929#ifdef SDTEST
930static void brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, void *pkt, uint seq);
931static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start);
932#endif
933
934#ifdef BCMDBG
935static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr,
936 unsigned char *msg, uint msglen);
937static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size);
938static int brcmf_sdbrcm_mem_dump(struct brcmf_bus *bus);
939#endif /* BCMDBG */
940static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter);
941
942static void brcmf_sdbrcm_release(struct brcmf_bus *bus);
943static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus);
944static void brcmf_sdbrcm_disconnect(void *ptr);
945static bool brcmf_sdbrcm_chipmatch(u16 chipid);
946static bool brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card,
947 u32 regsva, u16 devid);
948static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card);
949static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card);
950static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus);
951
952static uint brcmf_process_nvram_vars(char *varbuf, uint len);
953
954static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size);
955static int brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn,
956 uint flags, u8 *buf, uint nbytes,
957 struct sk_buff *pkt,
958 void (*complete)(void *handle, int status,
959 bool sync_waiting),
960 void *handle);
961
962static bool brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card);
963static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus);
964
965static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus);
966static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus);
967
968static void
969brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase);
970
971static int brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs);
972
973static void
974brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase);
975
976static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus,
977 u32 drivestrength);
978static void brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus);
979static void brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar);
980static void brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus);
981static void brcmf_sdbrcm_watchdog(unsigned long data);
982static int brcmf_sdbrcm_watchdog_thread(void *data);
983static int brcmf_sdbrcm_dpc_thread(void *data);
984static void brcmf_sdbrcm_dpc_tasklet(unsigned long data);
985static void brcmf_sdbrcm_sched_dpc(struct brcmf_bus *bus);
986static void brcmf_sdbrcm_sdlock(struct brcmf_bus *bus);
987static void brcmf_sdbrcm_sdunlock(struct brcmf_bus *bus);
988static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus);
989
990/* Packet free applicable unconditionally for sdio and sdspi.
991 * Conditional if bufpool was present for gspi bus.
992 */
993static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt)
994{
995 if ((bus->bus != SPI_BUS) || bus->usebufpool)
996 brcmu_pkt_buf_free_skb(pkt);
997}
998
999static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size)
1000{
1001 s32 min_size = DONGLE_MIN_MEMSIZE;
1002 /* Restrict the memsize to user specified limit */
1003 BRCMF_ERROR(("user: Restrict the dongle ram size to %d, min %d\n",
1004 brcmf_dongle_memsize, min_size));
1005 if ((brcmf_dongle_memsize > min_size) &&
1006 (brcmf_dongle_memsize < (s32) bus->orig_ramsize))
1007 bus->ramsize = brcmf_dongle_memsize;
1008}
1009
1010static int brcmf_sdbrcm_set_siaddr_window(struct brcmf_bus *bus, u32 address)
1011{
1012 int err = 0;
1013 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
1014 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
1015 if (!err)
1016 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
1017 SBSDIO_FUNC1_SBADDRMID,
1018 (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
1019 if (!err)
1020 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
1021 SBSDIO_FUNC1_SBADDRHIGH,
1022 (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
1023 &err);
1024 return err;
1025}
1026
1027/* Turn backplane clock on or off */
1028static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
1029{
1030 int err;
1031 u8 clkctl, clkreq, devctl;
1032 struct brcmf_sdio_card *card;
1033
1034 BRCMF_TRACE(("%s: Enter\n", __func__));
1035
1036 clkctl = 0;
1037 card = bus->card;
1038
1039 if (on) {
1040 /* Request HT Avail */
1041 clkreq =
1042 bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
1043
1044 if ((bus->ci->chip == BCM4329_CHIP_ID)
1045 && (bus->ci->chiprev == 0))
1046 clkreq |= SBSDIO_FORCE_ALP;
1047
1048 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
1049 SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
1050 if (err) {
1051 BRCMF_ERROR(("%s: HT Avail request error: %d\n",
1052 __func__, err));
1053 return -EBADE;
1054 }
1055
1056 if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID)
1057 && (bus->ci->buscorerev == 9))) {
1058 u32 dummy, retries;
1059 r_sdreg32(bus, &dummy,
1060 offsetof(struct sdpcmd_regs, clockctlstatus),
1061 &retries);
1062 }
1063
1064 /* Check current status */
1065 clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
1066 SBSDIO_FUNC1_CHIPCLKCSR, &err);
1067 if (err) {
1068 BRCMF_ERROR(("%s: HT Avail read error: %d\n",
1069 __func__, err));
1070 return -EBADE;
1071 }
1072
1073 /* Go to pending and await interrupt if appropriate */
1074 if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
1075 /* Allow only clock-available interrupt */
1076 devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
1077 SBSDIO_DEVICE_CTL, &err);
1078 if (err) {
1079 BRCMF_ERROR(("%s: Devctl error setting CA:"
1080 " %d\n", __func__, err));
1081 return -EBADE;
1082 }
1083
1084 devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
1085 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
1086 SBSDIO_DEVICE_CTL, devctl, &err);
1087 BRCMF_INFO(("CLKCTL: set PENDING\n"));
1088 bus->clkstate = CLK_PENDING;
1089
1090 return 0;
1091 } else if (bus->clkstate == CLK_PENDING) {
1092 /* Cancel CA-only interrupt filter */
1093 devctl =
1094 brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
1095 SBSDIO_DEVICE_CTL, &err);
1096 devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
1097 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
1098 SBSDIO_DEVICE_CTL, devctl, &err);
1099 }
1100
1101 /* Otherwise, wait here (polling) for HT Avail */
1102 if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
1103 BRCMF_SPINWAIT_SLEEP(sdioh_spinwait_sleep,
1104 ((clkctl =
1105 brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
1106 SBSDIO_FUNC1_CHIPCLKCSR,
1107 &err)),
1108 !SBSDIO_CLKAV(clkctl, bus->alp_only)),
1109 PMU_MAX_TRANSITION_DLY);
1110 }
1111 if (err) {
1112 BRCMF_ERROR(("%s: HT Avail request error: %d\n",
1113 __func__, err));
1114 return -EBADE;
1115 }
1116 if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
1117 BRCMF_ERROR(("%s: HT Avail timeout (%d): "
1118 "clkctl 0x%02x\n", __func__,
1119 PMU_MAX_TRANSITION_DLY, clkctl));
1120 return -EBADE;
1121 }
1122
1123 /* Mark clock available */
1124 bus->clkstate = CLK_AVAIL;
1125 BRCMF_INFO(("CLKCTL: turned ON\n"));
1126
1127#if defined(BCMDBG)
1128 if (bus->alp_only != true) {
1129 if (SBSDIO_ALPONLY(clkctl)) {
1130 BRCMF_ERROR(("%s: HT Clock should be on.\n",
1131 __func__));
1132 }
1133 }
1134#endif /* defined (BCMDBG) */
1135
1136 bus->activity = true;
1137 } else {
1138 clkreq = 0;
1139
1140 if (bus->clkstate == CLK_PENDING) {
1141 /* Cancel CA-only interrupt filter */
1142 devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
1143 SBSDIO_DEVICE_CTL, &err);
1144 devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
1145 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
1146 SBSDIO_DEVICE_CTL, devctl, &err);
1147 }
1148
1149 bus->clkstate = CLK_SDONLY;
1150 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
1151 SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
1152 BRCMF_INFO(("CLKCTL: turned OFF\n"));
1153 if (err) {
1154 BRCMF_ERROR(("%s: Failed access turning clock off:"
1155 " %d\n", __func__, err));
1156 return -EBADE;
1157 }
1158 }
1159 return 0;
1160}
1161
1162/* Change idle/active SD state */
1163static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on)
1164{
1165 BRCMF_TRACE(("%s: Enter\n", __func__));
1166
1167 if (on)
1168 bus->clkstate = CLK_SDONLY;
1169 else
1170 bus->clkstate = CLK_NONE;
1171
1172 return 0;
1173}
1174
1175/* Transition SD and backplane clock readiness */
1176static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok)
1177{
1178#ifdef BCMDBG
1179 uint oldstate = bus->clkstate;
1180#endif /* BCMDBG */
1181
1182 BRCMF_TRACE(("%s: Enter\n", __func__));
1183
1184 /* Early exit if we're already there */
1185 if (bus->clkstate == target) {
1186 if (target == CLK_AVAIL) {
1187 brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
1188 bus->activity = true;
1189 }
1190 return 0;
1191 }
1192
1193 switch (target) {
1194 case CLK_AVAIL:
1195 /* Make sure SD clock is available */
1196 if (bus->clkstate == CLK_NONE)
1197 brcmf_sdbrcm_sdclk(bus, true);
1198 /* Now request HT Avail on the backplane */
1199 brcmf_sdbrcm_htclk(bus, true, pendok);
1200 brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
1201 bus->activity = true;
1202 break;
1203
1204 case CLK_SDONLY:
1205 /* Remove HT request, or bring up SD clock */
1206 if (bus->clkstate == CLK_NONE)
1207 brcmf_sdbrcm_sdclk(bus, true);
1208 else if (bus->clkstate == CLK_AVAIL)
1209 brcmf_sdbrcm_htclk(bus, false, false);
1210 else
1211 BRCMF_ERROR(("brcmf_sdbrcm_clkctl: request for %d -> %d"
1212 "\n", bus->clkstate, target));
1213 brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
1214 break;
1215
1216 case CLK_NONE:
1217 /* Make sure to remove HT request */
1218 if (bus->clkstate == CLK_AVAIL)
1219 brcmf_sdbrcm_htclk(bus, false, false);
1220 /* Now remove the SD clock */
1221 brcmf_sdbrcm_sdclk(bus, false);
1222 brcmf_sdbrcm_wd_timer(bus, 0);
1223 break;
1224 }
1225#ifdef BCMDBG
1226 BRCMF_INFO(("brcmf_sdbrcm_clkctl: %d -> %d\n",
1227 oldstate, bus->clkstate));
1228#endif /* BCMDBG */
1229
1230 return 0;
1231}
1232
1233int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
1234{
1235 struct brcmf_sdio_card *card = bus->card;
1236 uint retries = 0;
1237
1238 BRCMF_INFO(("brcmf_sdbrcm_bussleep: request %s (currently %s)\n",
1239 (sleep ? "SLEEP" : "WAKE"),
1240 (bus->sleeping ? "SLEEP" : "WAKE")));
1241
1242 /* Done if we're already in the requested state */
1243 if (sleep == bus->sleeping)
1244 return 0;
1245
1246 /* Going to sleep: set the alarm and turn off the lights... */
1247 if (sleep) {
1248 /* Don't sleep if something is pending */
1249 if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
1250 return -EBUSY;
1251
1252 /* Disable SDIO interrupts (no longer interested) */
1253 brcmf_sdcard_intr_disable(bus->card);
1254
1255 /* Make sure the controller has the bus up */
1256 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
1257
1258 /* Tell device to start using OOB wakeup */
1259 w_sdreg32(bus, SMB_USE_OOB,
1260 offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
1261 if (retries > retry_limit)
1262 BRCMF_ERROR(("CANNOT SIGNAL CHIP, "
1263 "WILL NOT WAKE UP!!\n"));
1264
1265 /* Turn off our contribution to the HT clock request */
1266 brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
1267
1268 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
1269 SBSDIO_FUNC1_CHIPCLKCSR,
1270 SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
1271
1272 /* Isolate the bus */
1273 if (bus->ci->chip != BCM4329_CHIP_ID
1274 && bus->ci->chip != BCM4319_CHIP_ID) {
1275 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
1276 SBSDIO_DEVICE_CTL,
1277 SBSDIO_DEVCTL_PADS_ISO, NULL);
1278 }
1279
1280 /* Change state */
1281 bus->sleeping = true;
1282
1283 } else {
1284 /* Waking up: bus power up is ok, set local state */
1285
1286 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
1287 SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
1288
1289 /* Force pad isolation off if possible
1290 (in case power never toggled) */
1291 if ((bus->ci->buscoretype == PCMCIA_CORE_ID)
1292 && (bus->ci->buscorerev >= 10))
1293 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
1294 SBSDIO_DEVICE_CTL, 0, NULL);
1295
1296 /* Make sure the controller has the bus up */
1297 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
1298
1299 /* Send misc interrupt to indicate OOB not needed */
1300 w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata),
1301 &retries);
1302 if (retries <= retry_limit)
1303 w_sdreg32(bus, SMB_DEV_INT,
1304 offsetof(struct sdpcmd_regs, tosbmailbox),
1305 &retries);
1306
1307 if (retries > retry_limit)
1308 BRCMF_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
1309
1310 /* Make sure we have SD bus access */
1311 brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
1312
1313 /* Change state */
1314 bus->sleeping = false;
1315
1316 /* Enable interrupts again */
1317 if (bus->intr && (bus->drvr->busstate == BRCMF_BUS_DATA)) {
1318 bus->intdis = false;
1319 brcmf_sdcard_intr_enable(bus->card);
1320 }
1321 }
1322
1323 return 0;
1324}
1325
1326#define BUS_WAKE(bus) \
1327 do { \
1328 if ((bus)->sleeping) \
1329 brcmf_sdbrcm_bussleep((bus), false); \
1330 } while (0);
1331
1332/* Writes a HW/SW header into the packet and sends it. */
1333/* Assumes: (a) header space already there, (b) caller holds lock */
1334static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, uint chan,
1335 bool free_pkt)
1336{
1337 int ret;
1338 u8 *frame;
1339 u16 len, pad = 0;
1340 u32 swheader;
1341 uint retries = 0;
1342 struct brcmf_sdio_card *card;
1343 struct sk_buff *new;
1344 int i;
1345
1346 BRCMF_TRACE(("%s: Enter\n", __func__));
1347
1348 card = bus->card;
1349
1350 if (bus->drvr->dongle_reset) {
1351 ret = -EPERM;
1352 goto done;
1353 }
1354
1355 frame = (u8 *) (pkt->data);
1356
1357 /* Add alignment padding, allocate new packet if needed */
1358 pad = ((unsigned long)frame % BRCMF_SDALIGN);
1359 if (pad) {
1360 if (skb_headroom(pkt) < pad) {
1361 BRCMF_INFO(("%s: insufficient headroom %d for %d pad\n",
1362 __func__, skb_headroom(pkt), pad));
1363 bus->drvr->tx_realloc++;
1364 new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN);
1365 if (!new) {
1366 BRCMF_ERROR(("%s: couldn't allocate new "
1367 "%d-byte packet\n", __func__,
1368 pkt->len + BRCMF_SDALIGN));
1369 ret = -ENOMEM;
1370 goto done;
1371 }
1372
1373 PKTALIGN(new, pkt->len, BRCMF_SDALIGN);
1374 memcpy(new->data, pkt->data, pkt->len);
1375 if (free_pkt)
1376 brcmu_pkt_buf_free_skb(pkt);
1377 /* free the pkt if canned one is not used */
1378 free_pkt = true;
1379 pkt = new;
1380 frame = (u8 *) (pkt->data);
1381 /* precondition: (frame % BRCMF_SDALIGN) == 0) */
1382 pad = 0;
1383 } else {
1384 skb_push(pkt, pad);
1385 frame = (u8 *) (pkt->data);
1386 /* precondition: pad + SDPCM_HDRLEN <= pkt->len */
1387 memset(frame, 0, pad + SDPCM_HDRLEN);
1388 }
1389 }
1390 /* precondition: pad < BRCMF_SDALIGN */
1391
1392 /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
1393 len = (u16) (pkt->len);
1394 *(u16 *) frame = cpu_to_le16(len);
1395 *(((u16 *) frame) + 1) = cpu_to_le16(~len);
1396
1397 /* Software tag: channel, sequence number, data offset */
1398 swheader =
1399 ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
1400 (((pad +
1401 SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
1402
1403 put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
1404 put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
1405
1406#ifdef BCMDBG
1407 tx_packets[pkt->priority]++;
1408 if (BRCMF_BYTES_ON() &&
1409 (((BRCMF_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
1410 (BRCMF_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
1411 printk(KERN_DEBUG "Tx Frame:\n");
1412 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len);
1413 } else if (BRCMF_HDRS_ON()) {
1414 printk(KERN_DEBUG "TxHdr:\n");
1415 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
1416 frame, min_t(u16, len, 16));
1417 }
1418#endif
1419
1420 /* Raise len to next SDIO block to eliminate tail command */
1421 if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
1422 u16 pad = bus->blocksize - (len % bus->blocksize);
1423 if ((pad <= bus->roundup) && (pad < bus->blocksize))
1424 len += pad;
1425 } else if (len % BRCMF_SDALIGN) {
1426 len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
1427 }
1428
1429 /* Some controllers have trouble with odd bytes -- round to even */
1430 if (forcealign && (len & (ALIGNMENT - 1))) {
1431 len = roundup(len, ALIGNMENT);
1432 }
1433
1434 do {
1435 ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card),
1436 SDIO_FUNC_2, F2SYNC, frame, len, pkt, NULL, NULL);
1437 bus->f2txdata++;
1438
1439 if (ret < 0) {
1440 /* On failure, abort the command
1441 and terminate the frame */
1442 BRCMF_INFO(("%s: sdio error %d, abort command and "
1443 "terminate frame.\n", __func__, ret));
1444 bus->tx_sderrs++;
1445
1446 brcmf_sdcard_abort(card, SDIO_FUNC_2);
1447 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
1448 SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
1449 NULL);
1450 bus->f1regdata++;
1451
1452 for (i = 0; i < 3; i++) {
1453 u8 hi, lo;
1454 hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
1455 SBSDIO_FUNC1_WFRAMEBCHI,
1456 NULL);
1457 lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
1458 SBSDIO_FUNC1_WFRAMEBCLO,
1459 NULL);
1460 bus->f1regdata += 2;
1461 if ((hi == 0) && (lo == 0))
1462 break;
1463 }
1464
1465 }
1466 if (ret == 0)
1467 bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
1468
1469 } while ((ret < 0) && retrydata && retries++ < TXRETRIES);
1470
1471done:
1472 /* restore pkt buffer pointer before calling tx complete routine */
1473 skb_pull(pkt, SDPCM_HDRLEN + pad);
1474 brcmf_sdbrcm_sdunlock(bus);
1475 brcmf_txcomplete(bus->drvr, pkt, ret != 0);
1476 brcmf_sdbrcm_sdlock(bus);
1477
1478 if (free_pkt)
1479 brcmu_pkt_buf_free_skb(pkt);
1480
1481 return ret;
1482}
1483
1484int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt)
1485{
1486 int ret = -EBADE;
1487 uint datalen, prec;
1488
1489 BRCMF_TRACE(("%s: Enter\n", __func__));
1490
1491 datalen = pkt->len;
1492
1493#ifdef SDTEST
1494 /* Push the test header if doing loopback */
1495 if (bus->ext_loop) {
1496 u8 *data;
1497 skb_push(pkt, SDPCM_TEST_HDRLEN);
1498 data = pkt->data;
1499 *data++ = SDPCM_TEST_ECHOREQ;
1500 *data++ = (u8) bus->loopid++;
1501 *data++ = (datalen >> 0);
1502 *data++ = (datalen >> 8);
1503 datalen += SDPCM_TEST_HDRLEN;
1504 }
1505#endif /* SDTEST */
1506
1507 /* Add space for the header */
1508 skb_push(pkt, SDPCM_HDRLEN);
1509 /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */
1510
1511 prec = PRIO2PREC((pkt->priority & PRIOMASK));
1512
1513 /* Check for existing queue, current flow-control,
1514 pending event, or pending clock */
1515 if (brcmf_deferred_tx || bus->fcstate || pktq_len(&bus->txq)
1516 || bus->dpc_sched || (!DATAOK(bus))
1517 || (bus->flowcontrol & NBITVAL(prec))
1518 || (bus->clkstate != CLK_AVAIL)) {
1519 BRCMF_TRACE(("%s: deferring pktq len %d\n", __func__,
1520 pktq_len(&bus->txq)));
1521 bus->fcqueued++;
1522
1523 /* Priority based enq */
1524 spin_lock_bh(&bus->txqlock);
1525 if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) {
1526 skb_pull(pkt, SDPCM_HDRLEN);
1527 brcmf_txcomplete(bus->drvr, pkt, false);
1528 brcmu_pkt_buf_free_skb(pkt);
1529 BRCMF_ERROR(("%s: out of bus->txq !!!\n", __func__));
1530 ret = -ENOSR;
1531 } else {
1532 ret = 0;
1533 }
1534 spin_unlock_bh(&bus->txqlock);
1535
1536 if (pktq_len(&bus->txq) >= TXHI)
1537 brcmf_txflowcontrol(bus->drvr, 0, ON);
1538
1539#ifdef BCMDBG
1540 if (pktq_plen(&bus->txq, prec) > qcount[prec])
1541 qcount[prec] = pktq_plen(&bus->txq, prec);
1542#endif
1543 /* Schedule DPC if needed to send queued packet(s) */
1544 if (brcmf_deferred_tx && !bus->dpc_sched) {
1545 bus->dpc_sched = true;
1546 brcmf_sdbrcm_sched_dpc(bus);
1547 }
1548 } else {
1549 /* Lock: we're about to use shared data/code (and SDIO) */
1550 brcmf_sdbrcm_sdlock(bus);
1551
1552 /* Otherwise, send it now */
1553 BUS_WAKE(bus);
1554 /* Make sure back plane ht clk is on, no pending allowed */
1555 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
1556
1557#ifndef SDTEST
1558 BRCMF_TRACE(("%s: calling txpkt\n", __func__));
1559 ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
1560#else
1561 ret = brcmf_sdbrcm_txpkt(bus, pkt,
1562 (bus->ext_loop ? SDPCM_TEST_CHANNEL :
1563 SDPCM_DATA_CHANNEL), true);
1564#endif
1565 if (ret)
1566 bus->drvr->tx_errors++;
1567 else
1568 bus->drvr->dstats.tx_bytes += datalen;
1569
1570 if (bus->idletime == BRCMF_IDLE_IMMEDIATE &&
1571 !bus->dpc_sched) {
1572 bus->activity = false;
1573 brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
1574 }
1575
1576 brcmf_sdbrcm_sdunlock(bus);
1577 }
1578
1579 return ret;
1580}
1581
1582static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes)
1583{
1584 struct sk_buff *pkt;
1585 u32 intstatus = 0;
1586 uint retries = 0;
1587 int ret = 0, prec_out;
1588 uint cnt = 0;
1589 uint datalen;
1590 u8 tx_prec_map;
1591
1592 struct brcmf_pub *drvr = bus->drvr;
1593
1594 BRCMF_TRACE(("%s: Enter\n", __func__));
1595
1596 tx_prec_map = ~bus->flowcontrol;
1597
1598 /* Send frames until the limit or some other event */
1599 for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) {
1600 spin_lock_bh(&bus->txqlock);
1601 pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
1602 if (pkt == NULL) {
1603 spin_unlock_bh(&bus->txqlock);
1604 break;
1605 }
1606 spin_unlock_bh(&bus->txqlock);
1607 datalen = pkt->len - SDPCM_HDRLEN;
1608
1609#ifndef SDTEST
1610 ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
1611#else
1612 ret = brcmf_sdbrcm_txpkt(bus, pkt,
1613 (bus->ext_loop ? SDPCM_TEST_CHANNEL :
1614 SDPCM_DATA_CHANNEL), true);
1615#endif
1616 if (ret)
1617 bus->drvr->tx_errors++;
1618 else
1619 bus->drvr->dstats.tx_bytes += datalen;
1620
1621 /* In poll mode, need to check for other events */
1622 if (!bus->intr && cnt) {
1623 /* Check device status, signal pending interrupt */
1624 r_sdreg32(bus, &intstatus,
1625 offsetof(struct sdpcmd_regs, intstatus),
1626 &retries);
1627 bus->f2txdata++;
1628 if (brcmf_sdcard_regfail(bus->card))
1629 break;
1630 if (intstatus & bus->hostintmask)
1631 bus->ipend = true;
1632 }
1633 }
1634
1635 /* Deflow-control stack if needed */
1636 if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) &&
1637 drvr->txoff && (pktq_len(&bus->txq) < TXLOW))
1638 brcmf_txflowcontrol(drvr, 0, OFF);
1639
1640 return cnt;
1641}
1642
1643int
1644brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
1645{
1646 u8 *frame;
1647 u16 len;
1648 u32 swheader;
1649 uint retries = 0;
1650 struct brcmf_sdio_card *card = bus->card;
1651 u8 doff = 0;
1652 int ret = -1;
1653 int i;
1654
1655 BRCMF_TRACE(("%s: Enter\n", __func__));
1656
1657 if (bus->drvr->dongle_reset)
1658 return -EIO;
1659
1660 /* Back the pointer to make a room for bus header */
1661 frame = msg - SDPCM_HDRLEN;
1662 len = (msglen += SDPCM_HDRLEN);
1663
1664 /* Add alignment padding (optional for ctl frames) */
1665 if (brcmf_alignctl) {
1666 doff = ((unsigned long)frame % BRCMF_SDALIGN);
1667 if (doff) {
1668 frame -= doff;
1669 len += doff;
1670 msglen += doff;
1671 memset(frame, 0, doff + SDPCM_HDRLEN);
1672 }
1673 /* precondition: doff < BRCMF_SDALIGN */
1674 }
1675 doff += SDPCM_HDRLEN;
1676
1677 /* Round send length to next SDIO block */
1678 if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
1679 u16 pad = bus->blocksize - (len % bus->blocksize);
1680 if ((pad <= bus->roundup) && (pad < bus->blocksize))
1681 len += pad;
1682 } else if (len % BRCMF_SDALIGN) {
1683 len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
1684 }
1685
1686 /* Satisfy length-alignment requirements */
1687 if (forcealign && (len & (ALIGNMENT - 1)))
1688 len = roundup(len, ALIGNMENT);
1689
1690 /* precondition: IS_ALIGNED((unsigned long)frame, 2) */
1691
1692 /* Need to lock here to protect txseq and SDIO tx calls */
1693 brcmf_sdbrcm_sdlock(bus);
1694
1695 BUS_WAKE(bus);
1696
1697 /* Make sure backplane clock is on */
1698 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
1699
1700 /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
1701 *(u16 *) frame = cpu_to_le16((u16) msglen);
1702 *(((u16 *) frame) + 1) = cpu_to_le16(~msglen);
1703
1704 /* Software tag: channel, sequence number, data offset */
1705 swheader =
1706 ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) &
1707 SDPCM_CHANNEL_MASK)
1708 | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) &
1709 SDPCM_DOFFSET_MASK);
1710 put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
1711 put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
1712
1713 if (!DATAOK(bus)) {
1714 BRCMF_INFO(("%s: No bus credit bus->tx_max %d,"
1715 " bus->tx_seq %d\n", __func__,
1716 bus->tx_max, bus->tx_seq));
1717 bus->ctrl_frame_stat = true;
1718 /* Send from dpc */
1719 bus->ctrl_frame_buf = frame;
1720 bus->ctrl_frame_len = len;
1721
1722 brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat);
1723
1724 if (bus->ctrl_frame_stat == false) {
1725 BRCMF_INFO(("%s: ctrl_frame_stat == false\n",
1726 __func__));
1727 ret = 0;
1728 } else {
1729 BRCMF_INFO(("%s: ctrl_frame_stat == true\n", __func__));
1730 ret = -1;
1731 }
1732 }
1733
1734 if (ret == -1) {
1735#ifdef BCMDBG
1736 if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
1737 printk(KERN_DEBUG "Tx Frame:\n");
1738 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
1739 frame, len);
1740 } else if (BRCMF_HDRS_ON()) {
1741 printk(KERN_DEBUG "TxHdr:\n");
1742 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
1743 frame, min_t(u16, len, 16));
1744 }
1745#endif
1746
1747 do {
1748 bus->ctrl_frame_stat = false;
1749 ret = brcmf_sdbrcm_send_buf(bus,
1750 brcmf_sdcard_cur_sbwad(card), SDIO_FUNC_2,
1751 F2SYNC, frame, len, NULL, NULL, NULL);
1752
1753 if (ret < 0) {
1754 /* On failure, abort the command and
1755 terminate the frame */
1756 BRCMF_INFO(("%s: sdio error %d, abort command "
1757 "and terminate frame.\n",
1758 __func__, ret));
1759 bus->tx_sderrs++;
1760
1761 brcmf_sdcard_abort(card, SDIO_FUNC_2);
1762
1763 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
1764 SBSDIO_FUNC1_FRAMECTRL,
1765 SFC_WF_TERM, NULL);
1766 bus->f1regdata++;
1767
1768 for (i = 0; i < 3; i++) {
1769 u8 hi, lo;
1770 hi = brcmf_sdcard_cfg_read(card,
1771 SDIO_FUNC_1,
1772 SBSDIO_FUNC1_WFRAMEBCHI,
1773 NULL);
1774 lo = brcmf_sdcard_cfg_read(card,
1775 SDIO_FUNC_1,
1776 SBSDIO_FUNC1_WFRAMEBCLO,
1777 NULL);
1778 bus->f1regdata += 2;
1779 if ((hi == 0) && (lo == 0))
1780 break;
1781 }
1782
1783 }
1784 if (ret == 0) {
1785 bus->tx_seq =
1786 (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
1787 }
1788 } while ((ret < 0) && retries++ < TXRETRIES);
1789 }
1790
1791 if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
1792 bus->activity = false;
1793 brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
1794 }
1795
1796 brcmf_sdbrcm_sdunlock(bus);
1797
1798 if (ret)
1799 bus->drvr->tx_ctlerrs++;
1800 else
1801 bus->drvr->tx_ctlpkts++;
1802
1803 return ret ? -EIO : 0;
1804}
1805
1806int brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen)
1807{
1808 int timeleft;
1809 uint rxlen = 0;
1810 bool pending;
1811
1812 BRCMF_TRACE(("%s: Enter\n", __func__));
1813
1814 if (bus->drvr->dongle_reset)
1815 return -EIO;
1816
1817 /* Wait until control frame is available */
1818 timeleft = brcmf_os_ioctl_resp_wait(bus->drvr, &bus->rxlen, &pending);
1819
1820 brcmf_sdbrcm_sdlock(bus);
1821 rxlen = bus->rxlen;
1822 memcpy(msg, bus->rxctl, min(msglen, rxlen));
1823 bus->rxlen = 0;
1824 brcmf_sdbrcm_sdunlock(bus);
1825
1826 if (rxlen) {
1827 BRCMF_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
1828 __func__, rxlen, msglen));
1829 } else if (timeleft == 0) {
1830 BRCMF_ERROR(("%s: resumed on timeout\n", __func__));
1831#ifdef BCMDBG
1832 brcmf_sdbrcm_sdlock(bus);
1833 brcmf_sdbrcm_checkdied(bus, NULL, 0);
1834 brcmf_sdbrcm_sdunlock(bus);
1835#endif /* BCMDBG */
1836 } else if (pending == true) {
1837 BRCMF_CTL(("%s: cancelled\n", __func__));
1838 return -ERESTARTSYS;
1839 } else {
1840 BRCMF_CTL(("%s: resumed for unknown reason?\n", __func__));
1841#ifdef BCMDBG
1842 brcmf_sdbrcm_sdlock(bus);
1843 brcmf_sdbrcm_checkdied(bus, NULL, 0);
1844 brcmf_sdbrcm_sdunlock(bus);
1845#endif /* BCMDBG */
1846 }
1847
1848 if (rxlen)
1849 bus->drvr->rx_ctlpkts++;
1850 else
1851 bus->drvr->rx_ctlerrs++;
1852
1853 return rxlen ? (int)rxlen : -ETIMEDOUT;
1854}
1855
1856/* IOVar table */
1857enum {
1858 IOV_INTR = 1,
1859 IOV_POLLRATE,
1860 IOV_SDREG,
1861 IOV_SBREG,
1862 IOV_SDCIS,
1863 IOV_MEMBYTES,
1864 IOV_MEMSIZE,
1865#ifdef BCMDBG
1866 IOV_CHECKDIED,
1867 IOV_CONS,
1868 IOV_DCONSOLE_POLL,
1869#endif
1870 IOV_DOWNLOAD,
1871 IOV_FORCEEVEN,
1872 IOV_SDIOD_DRIVE,
1873 IOV_READAHEAD,
1874 IOV_SDRXCHAIN,
1875 IOV_ALIGNCTL,
1876 IOV_SDALIGN,
1877 IOV_DEVRESET,
1878 IOV_CPU,
1879#ifdef SDTEST
1880 IOV_PKTGEN,
1881 IOV_EXTLOOP,
1882#endif /* SDTEST */
1883 IOV_SPROM,
1884 IOV_TXBOUND,
1885 IOV_RXBOUND,
1886 IOV_TXMINMAX,
1887 IOV_IDLETIME,
1888 IOV_IDLECLOCK,
1889 IOV_SD1IDLE,
1890 IOV_SLEEP,
1891 IOV_WDTICK,
1892 IOV_VARS
1893};
1894
1895const struct brcmu_iovar brcmf_sdio_iovars[] = {
1896 {"intr", IOV_INTR, 0, IOVT_BOOL, 0},
1897 {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0},
1898 {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0},
1899 {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0},
1900 {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0},
1901 {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0},
1902 {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int)},
1903 {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0},
1904 {"download", IOV_DOWNLOAD, 0, IOVT_BOOL, 0},
1905 {"vars", IOV_VARS, 0, IOVT_BUFFER, 0},
1906 {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0},
1907 {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0},
1908 {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0},
1909 {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0},
1910 {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0},
1911 {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0},
1912 {"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0},
1913#ifdef BCMDBG
1914 {"cons", IOV_CONS, 0, IOVT_BUFFER, 0}
1915 ,
1916 {"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0}
1917 ,
1918 {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
1919 ,
1920 {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
1921 ,
1922 {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN}
1923 ,
1924 {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0}
1925 ,
1926 {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0}
1927 ,
1928 {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0}
1929 ,
1930 {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0}
1931 ,
1932 {"cpu", IOV_CPU, 0, IOVT_BOOL, 0}
1933 ,
1934 {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0}
1935 ,
1936#endif /* BCMDBG */
1937#ifdef SDTEST
1938 {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0}
1939 ,
1940 {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(struct brcmf_pktgen)}
1941 ,
1942#endif /* SDTEST */
1943
1944 {NULL, 0, 0, 0, 0}
1945};
1946
1947static void
1948brcmf_dump_pct(struct brcmu_strbuf *strbuf, char *desc, uint num, uint div)
1949{
1950 uint q1, q2;
1951
1952 if (!div) {
1953 brcmu_bprintf(strbuf, "%s N/A", desc);
1954 } else {
1955 q1 = num / div;
1956 q2 = (100 * (num - (q1 * div))) / div;
1957 brcmu_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
1958 }
1959}
1960
1961void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf)
1962{
1963 struct brcmf_bus *bus = drvr->bus;
1964
1965 brcmu_bprintf(strbuf, "Bus SDIO structure:\n");
1966 brcmu_bprintf(strbuf,
1967 "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
1968 bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
1969 brcmu_bprintf(strbuf,
1970 "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n",
1971 bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max,
1972 bus->rxskip, bus->rxlen, bus->rx_seq);
1973 brcmu_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n",
1974 bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
1975 brcmu_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n",
1976 bus->pollrate, bus->pollcnt, bus->regfails);
1977
1978 brcmu_bprintf(strbuf, "\nAdditional counters:\n");
1979 brcmu_bprintf(strbuf,
1980 "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n",
1981 bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
1982 bus->rxc_errors);
1983 brcmu_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n",
1984 bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
1985 brcmu_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n",
1986 bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
1987 brcmu_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n",
1988 bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
1989 brcmu_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs"
1990 " %d\n",
1991 (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs,
1992 bus->f2rxdata, bus->f2txdata, bus->f1regdata);
1993 {
1994 brcmf_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->drvr->rx_packets,
1995 (bus->f2rxhdrs + bus->f2rxdata));
1996 brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->rx_packets,
1997 bus->f1regdata);
1998 brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->rx_packets,
1999 (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
2000 brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->rx_packets,
2001 bus->intrcount);
2002 brcmu_bprintf(strbuf, "\n");
2003
2004 brcmf_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
2005 bus->drvr->rx_packets);
2006 brcmf_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts,
2007 bus->rxglomframes);
2008 brcmu_bprintf(strbuf, "\n");
2009
2010 brcmf_dump_pct(strbuf, "Tx: pkts/f2wr", bus->drvr->tx_packets,
2011 bus->f2txdata);
2012 brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->tx_packets,
2013 bus->f1regdata);
2014 brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->tx_packets,
2015 (bus->f2txdata + bus->f1regdata));
2016 brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->tx_packets,
2017 bus->intrcount);
2018 brcmu_bprintf(strbuf, "\n");
2019
2020 brcmf_dump_pct(strbuf, "Total: pkts/f2rw",
2021 (bus->drvr->tx_packets + bus->drvr->rx_packets),
2022 (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
2023 brcmf_dump_pct(strbuf, ", pkts/f1sd",
2024 (bus->drvr->tx_packets + bus->drvr->rx_packets),
2025 bus->f1regdata);
2026 brcmf_dump_pct(strbuf, ", pkts/sd",
2027 (bus->drvr->tx_packets + bus->drvr->rx_packets),
2028 (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata +
2029 bus->f1regdata));
2030 brcmf_dump_pct(strbuf, ", pkts/int",
2031 (bus->drvr->tx_packets + bus->drvr->rx_packets),
2032 bus->intrcount);
2033 brcmu_bprintf(strbuf, "\n\n");
2034 }
2035
2036#ifdef SDTEST
2037 if (bus->pktgen_count) {
2038 brcmu_bprintf(strbuf, "pktgen config and count:\n");
2039 brcmu_bprintf(strbuf,
2040 "freq %d count %d print %d total %d min %d len %d\n",
2041 bus->pktgen_freq, bus->pktgen_count,
2042 bus->pktgen_print, bus->pktgen_total,
2043 bus->pktgen_minlen, bus->pktgen_maxlen);
2044 brcmu_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n",
2045 bus->pktgen_sent, bus->pktgen_rcvd,
2046 bus->pktgen_fail);
2047 }
2048#endif /* SDTEST */
2049#ifdef BCMDBG
2050 brcmu_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
2051 bus->dpc_sched, " not ");
2052 brcmu_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize,
2053 bus->roundup);
2054#endif /* BCMDBG */
2055 brcmu_bprintf(strbuf,
2056 "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
2057 bus->clkstate, bus->activity, bus->idletime, bus->idlecount,
2058 bus->sleeping);
2059}
2060
2061void brcmf_bus_clearcounts(struct brcmf_pub *drvr)
2062{
2063 struct brcmf_bus *bus = (struct brcmf_bus *) drvr->bus;
2064
2065 bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
2066 bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
2067 bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
2068 bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
2069 bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
2070 bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
2071}
2072
2073#ifdef SDTEST
2074static int brcmf_sdbrcm_pktgen_get(struct brcmf_bus *bus, u8 *arg)
2075{
2076 struct brcmf_pktgen pktgen;
2077
2078 pktgen.version = BRCMF_PKTGEN_VERSION;
2079 pktgen.freq = bus->pktgen_freq;
2080 pktgen.count = bus->pktgen_count;
2081 pktgen.print = bus->pktgen_print;
2082 pktgen.total = bus->pktgen_total;
2083 pktgen.minlen = bus->pktgen_minlen;
2084 pktgen.maxlen = bus->pktgen_maxlen;
2085 pktgen.numsent = bus->pktgen_sent;
2086 pktgen.numrcvd = bus->pktgen_rcvd;
2087 pktgen.numfail = bus->pktgen_fail;
2088 pktgen.mode = bus->pktgen_mode;
2089 pktgen.stop = bus->pktgen_stop;
2090
2091 memcpy(arg, &pktgen, sizeof(pktgen));
2092
2093 return 0;
2094}
2095
2096static int brcmf_sdbrcm_pktgen_set(struct brcmf_bus *bus, u8 *arg)
2097{
2098 struct brcmf_pktgen pktgen;
2099 uint oldcnt, oldmode;
2100
2101 memcpy(&pktgen, arg, sizeof(pktgen));
2102 if (pktgen.version != BRCMF_PKTGEN_VERSION)
2103 return -EINVAL;
2104
2105 oldcnt = bus->pktgen_count;
2106 oldmode = bus->pktgen_mode;
2107
2108 bus->pktgen_freq = pktgen.freq;
2109 bus->pktgen_count = pktgen.count;
2110 bus->pktgen_print = pktgen.print;
2111 bus->pktgen_total = pktgen.total;
2112 bus->pktgen_minlen = pktgen.minlen;
2113 bus->pktgen_maxlen = pktgen.maxlen;
2114 bus->pktgen_mode = pktgen.mode;
2115 bus->pktgen_stop = pktgen.stop;
2116
2117 bus->pktgen_tick = bus->pktgen_ptick = 0;
2118 bus->pktgen_len = max(bus->pktgen_len, bus->pktgen_minlen);
2119 bus->pktgen_len = min(bus->pktgen_len, bus->pktgen_maxlen);
2120
2121 /* Clear counts for a new pktgen (mode change, or was stopped) */
2122 if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode))
2123 bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0;
2124
2125 return 0;
2126}
2127#endif /* SDTEST */
2128
2129static int
2130brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data,
2131 uint size)
2132{
2133 int bcmerror = 0;
2134 u32 sdaddr;
2135 uint dsize;
2136
2137 /* Determine initial transfer parameters */
2138 sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
2139 if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
2140 dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
2141 else
2142 dsize = size;
2143
2144 /* Set the backplane window to include the start address */
2145 bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address);
2146 if (bcmerror) {
2147 BRCMF_ERROR(("%s: window change failed\n", __func__));
2148 goto xfer_done;
2149 }
2150
2151 /* Do the transfer(s) */
2152 while (size) {
2153 BRCMF_INFO(("%s: %s %d bytes at offset 0x%08x in window"
2154 " 0x%08x\n", __func__, (write ? "write" : "read"),
2155 dsize, sdaddr, (address & SBSDIO_SBWINDOW_MASK)));
2156 bcmerror =
2157 brcmf_sdcard_rwdata(bus->card, write, sdaddr, data, dsize);
2158 if (bcmerror) {
2159 BRCMF_ERROR(("%s: membytes transfer failed\n",
2160 __func__));
2161 break;
2162 }
2163
2164 /* Adjust for next transfer (if any) */
2165 size -= dsize;
2166 if (size) {
2167 data += dsize;
2168 address += dsize;
2169 bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address);
2170 if (bcmerror) {
2171 BRCMF_ERROR(("%s: window change failed\n",
2172 __func__));
2173 break;
2174 }
2175 sdaddr = 0;
2176 dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
2177 }
2178 }
2179
2180xfer_done:
2181 /* Return the window to backplane enumeration space for core access */
2182 if (brcmf_sdbrcm_set_siaddr_window(bus,
2183 brcmf_sdcard_cur_sbwad(bus->card))) {
2184 BRCMF_ERROR(("%s: FAILED to set window back to 0x%x\n",
2185 __func__, brcmf_sdcard_cur_sbwad(bus->card)));
2186 }
2187
2188 return bcmerror;
2189}
2190
2191#ifdef BCMDBG
2192static int brcmf_sdbrcm_readshared(struct brcmf_bus *bus, struct sdpcm_shared *sh)
2193{
2194 u32 addr;
2195 int rv;
2196
2197 /* Read last word in memory to determine address of
2198 sdpcm_shared structure */
2199 rv = brcmf_sdbrcm_membytes(bus, false, bus->ramsize - 4, (u8 *)&addr,
2200 4);
2201 if (rv < 0)
2202 return rv;
2203
2204 addr = le32_to_cpu(addr);
2205
2206 BRCMF_INFO(("sdpcm_shared address 0x%08X\n", addr));
2207
2208 /*
2209 * Check if addr is valid.
2210 * NVRAM length at the end of memory should have been overwritten.
2211 */
2212 if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
2213 BRCMF_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
2214 __func__, addr));
2215 return -EBADE;
2216 }
2217
2218 /* Read rte_shared structure */
2219 rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *) sh,
2220 sizeof(struct sdpcm_shared));
2221 if (rv < 0)
2222 return rv;
2223
2224 /* Endianness */
2225 sh->flags = le32_to_cpu(sh->flags);
2226 sh->trap_addr = le32_to_cpu(sh->trap_addr);
2227 sh->assert_exp_addr = le32_to_cpu(sh->assert_exp_addr);
2228 sh->assert_file_addr = le32_to_cpu(sh->assert_file_addr);
2229 sh->assert_line = le32_to_cpu(sh->assert_line);
2230 sh->console_addr = le32_to_cpu(sh->console_addr);
2231 sh->msgtrace_addr = le32_to_cpu(sh->msgtrace_addr);
2232
2233 if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
2234 BRCMF_ERROR(("%s: sdpcm_shared version %d in brcmf "
2235 "is different than sdpcm_shared version %d in dongle\n",
2236 __func__, SDPCM_SHARED_VERSION,
2237 sh->flags & SDPCM_SHARED_VERSION_MASK));
2238 return -EBADE;
2239 }
2240
2241 return 0;
2242}
2243
2244static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size)
2245{
2246 int bcmerror = 0;
2247 uint msize = 512;
2248 char *mbuffer = NULL;
2249 uint maxstrlen = 256;
2250 char *str = NULL;
2251 struct brcmf_trap tr;
2252 struct sdpcm_shared sdpcm_shared;
2253 struct brcmu_strbuf strbuf;
2254
2255 BRCMF_TRACE(("%s: Enter\n", __func__));
2256
2257 if (data == NULL) {
2258 /*
2259 * Called after a rx ctrl timeout. "data" is NULL.
2260 * allocate memory to trace the trap or assert.
2261 */
2262 size = msize;
2263 mbuffer = data = kmalloc(msize, GFP_ATOMIC);
2264 if (mbuffer == NULL) {
2265 BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__,
2266 msize));
2267 bcmerror = -ENOMEM;
2268 goto done;
2269 }
2270 }
2271
2272 str = kmalloc(maxstrlen, GFP_ATOMIC);
2273 if (str == NULL) {
2274 BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__, maxstrlen));
2275 bcmerror = -ENOMEM;
2276 goto done;
2277 }
2278
2279 bcmerror = brcmf_sdbrcm_readshared(bus, &sdpcm_shared);
2280 if (bcmerror < 0)
2281 goto done;
2282
2283 brcmu_binit(&strbuf, data, size);
2284
2285 brcmu_bprintf(&strbuf,
2286 "msgtrace address : 0x%08X\nconsole address : 0x%08X\n",
2287 sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
2288
2289 if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
2290 /* NOTE: Misspelled assert is intentional - DO NOT FIX.
2291 * (Avoids conflict with real asserts for programmatic
2292 * parsing of output.)
2293 */
2294 brcmu_bprintf(&strbuf, "Assrt not built in dongle\n");
2295 }
2296
2297 if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) ==
2298 0) {
2299 /* NOTE: Misspelled assert is intentional - DO NOT FIX.
2300 * (Avoids conflict with real asserts for programmatic
2301 * parsing of output.)
2302 */
2303 brcmu_bprintf(&strbuf, "No trap%s in dongle",
2304 (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
2305 ? "/assrt" : "");
2306 } else {
2307 if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
2308 /* Download assert */
2309 brcmu_bprintf(&strbuf, "Dongle assert");
2310 if (sdpcm_shared.assert_exp_addr != 0) {
2311 str[0] = '\0';
2312 bcmerror = brcmf_sdbrcm_membytes(bus, false,
2313 sdpcm_shared.assert_exp_addr,
2314 (u8 *) str, maxstrlen);
2315 if (bcmerror < 0)
2316 goto done;
2317
2318 str[maxstrlen - 1] = '\0';
2319 brcmu_bprintf(&strbuf, " expr \"%s\"", str);
2320 }
2321
2322 if (sdpcm_shared.assert_file_addr != 0) {
2323 str[0] = '\0';
2324 bcmerror = brcmf_sdbrcm_membytes(bus, false,
2325 sdpcm_shared.assert_file_addr,
2326 (u8 *) str, maxstrlen);
2327 if (bcmerror < 0)
2328 goto done;
2329
2330 str[maxstrlen - 1] = '\0';
2331 brcmu_bprintf(&strbuf, " file \"%s\"", str);
2332 }
2333
2334 brcmu_bprintf(&strbuf, " line %d ",
2335 sdpcm_shared.assert_line);
2336 }
2337
2338 if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
2339 bcmerror = brcmf_sdbrcm_membytes(bus, false,
2340 sdpcm_shared.trap_addr, (u8 *)&tr,
2341 sizeof(struct brcmf_trap));
2342 if (bcmerror < 0)
2343 goto done;
2344
2345 brcmu_bprintf(&strbuf,
2346 "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
2347 "lp 0x%x, rpc 0x%x Trap offset 0x%x, "
2348 "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n",
2349 tr.type, tr.epc, tr.cpsr, tr.spsr, tr.r13,
2350 tr.r14, tr.pc, sdpcm_shared.trap_addr,
2351 tr.r0, tr.r1, tr.r2, tr.r3, tr.r4, tr.r5,
2352 tr.r6, tr.r7);
2353 }
2354 }
2355
2356 if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP))
2357 BRCMF_ERROR(("%s: %s\n", __func__, strbuf.origbuf));
2358
2359#ifdef BCMDBG
2360 if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
2361 /* Mem dump to a file on device */
2362 brcmf_sdbrcm_mem_dump(bus);
2363 }
2364#endif /* BCMDBG */
2365
2366done:
2367 kfree(mbuffer);
2368 kfree(str);
2369
2370 return bcmerror;
2371}
2372
2373static int brcmf_sdbrcm_mem_dump(struct brcmf_bus *bus)
2374{
2375 int ret = 0;
2376 int size; /* Full mem size */
2377 int start = 0; /* Start address */
2378 int read_size = 0; /* Read size of each iteration */
2379 u8 *buf = NULL, *databuf = NULL;
2380
2381 /* Get full mem size */
2382 size = bus->ramsize;
2383 buf = kmalloc(size, GFP_ATOMIC);
2384 if (!buf) {
2385 BRCMF_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size));
2386 return -1;
2387 }
2388
2389 /* Read mem content */
2390 printk(KERN_DEBUG "Dump dongle memory");
2391 databuf = buf;
2392 while (size) {
2393 read_size = min(MEMBLOCK, size);
2394 ret = brcmf_sdbrcm_membytes(bus, false, start, databuf,
2395 read_size);
2396 if (ret) {
2397 BRCMF_ERROR(("%s: Error membytes %d\n", __func__, ret));
2398 kfree(buf);
2399 return -1;
2400 }
2401 printk(".");
2402
2403 /* Decrement size and increment start address */
2404 size -= read_size;
2405 start += read_size;
2406 databuf += read_size;
2407 }
2408 printk(KERN_DEBUG "Done\n");
2409
2410 /* free buf before return !!! */
2411 if (brcmf_write_to_file(bus->drvr, buf, bus->ramsize)) {
2412 BRCMF_ERROR(("%s: Error writing to files\n", __func__));
2413 return -1;
2414 }
2415
2416 /* buf free handled in brcmf_write_to_file, not here */
2417 return 0;
2418}
2419
2420#define CONSOLE_LINE_MAX 192
2421
2422static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus)
2423{
2424 struct brcmf_console *c = &bus->console;
2425 u8 line[CONSOLE_LINE_MAX], ch;
2426 u32 n, idx, addr;
2427 int rv;
2428
2429 /* Don't do anything until FWREADY updates console address */
2430 if (bus->console_addr == 0)
2431 return 0;
2432
2433 /* Read console log struct */
2434 addr = bus->console_addr + offsetof(struct rte_console, log);
2435 rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log,
2436 sizeof(c->log));
2437 if (rv < 0)
2438 return rv;
2439
2440 /* Allocate console buffer (one time only) */
2441 if (c->buf == NULL) {
2442 c->bufsize = le32_to_cpu(c->log.buf_size);
2443 c->buf = kmalloc(c->bufsize, GFP_ATOMIC);
2444 if (c->buf == NULL)
2445 return -ENOMEM;
2446 }
2447
2448 idx = le32_to_cpu(c->log.idx);
2449
2450 /* Protect against corrupt value */
2451 if (idx > c->bufsize)
2452 return -EBADE;
2453
2454 /* Skip reading the console buffer if the index pointer
2455 has not moved */
2456 if (idx == c->last)
2457 return 0;
2458
2459 /* Read the console buffer */
2460 addr = le32_to_cpu(c->log.buf);
2461 rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize);
2462 if (rv < 0)
2463 return rv;
2464
2465 while (c->last != idx) {
2466 for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
2467 if (c->last == idx) {
2468 /* This would output a partial line.
2469 * Instead, back up
2470 * the buffer pointer and output this
2471 * line next time around.
2472 */
2473 if (c->last >= n)
2474 c->last -= n;
2475 else
2476 c->last = c->bufsize - n;
2477 goto break2;
2478 }
2479 ch = c->buf[c->last];
2480 c->last = (c->last + 1) % c->bufsize;
2481 if (ch == '\n')
2482 break;
2483 line[n] = ch;
2484 }
2485
2486 if (n > 0) {
2487 if (line[n - 1] == '\r')
2488 n--;
2489 line[n] = 0;
2490 printk(KERN_DEBUG "CONSOLE: %s\n", line);
2491 }
2492 }
2493break2:
2494
2495 return 0;
2496}
2497#endif /* BCMDBG */
2498
2499int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len)
2500{
2501 int bcmerror = 0;
2502
2503 BRCMF_TRACE(("%s: Enter\n", __func__));
2504
2505 /* Basic sanity checks */
2506 if (bus->drvr->up) {
2507 bcmerror = -EISCONN;
2508 goto err;
2509 }
2510 if (!len) {
2511 bcmerror = -EOVERFLOW;
2512 goto err;
2513 }
2514
2515 /* Free the old ones and replace with passed variables */
2516 kfree(bus->vars);
2517
2518 bus->vars = kmalloc(len, GFP_ATOMIC);
2519 bus->varsz = bus->vars ? len : 0;
2520 if (bus->vars == NULL) {
2521 bcmerror = -ENOMEM;
2522 goto err;
2523 }
2524
2525 /* Copy the passed variables, which should include the
2526 terminating double-null */
2527 memcpy(bus->vars, arg, bus->varsz);
2528err:
2529 return bcmerror;
2530}
2531
2532static int
2533brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, const struct brcmu_iovar *vi, u32 actionid,
2534 const char *name, void *params, int plen, void *arg, int len,
2535 int val_size)
2536{
2537 int bcmerror = 0;
2538 s32 int_val = 0;
2539 bool bool_val = 0;
2540
2541 BRCMF_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p "
2542 "len %d val_size %d\n", __func__, actionid, name, params,
2543 plen, arg, len, val_size));
2544
2545 bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
2546 if (bcmerror != 0)
2547 goto exit;
2548
2549 if (plen >= (int)sizeof(int_val))
2550 memcpy(&int_val, params, sizeof(int_val));
2551
2552 bool_val = (int_val != 0) ? true : false;
2553
2554 /* Some ioctls use the bus */
2555 brcmf_sdbrcm_sdlock(bus);
2556
2557 /* Check if dongle is in reset. If so, only allow DEVRESET iovars */
2558 if (bus->drvr->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
2559 actionid == IOV_GVAL(IOV_DEVRESET))) {
2560 bcmerror = -EPERM;
2561 goto exit;
2562 }
2563
2564 /* Handle sleep stuff before any clock mucking */
2565 if (vi->varid == IOV_SLEEP) {
2566 if (IOV_ISSET(actionid)) {
2567 bcmerror = brcmf_sdbrcm_bussleep(bus, bool_val);
2568 } else {
2569 int_val = (s32) bus->sleeping;
2570 memcpy(arg, &int_val, val_size);
2571 }
2572 goto exit;
2573 }
2574
2575 /* Request clock to allow SDIO accesses */
2576 if (!bus->drvr->dongle_reset) {
2577 BUS_WAKE(bus);
2578 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
2579 }
2580
2581 switch (actionid) {
2582 case IOV_GVAL(IOV_INTR):
2583 int_val = (s32) bus->intr;
2584 memcpy(arg, &int_val, val_size);
2585 break;
2586
2587 case IOV_SVAL(IOV_INTR):
2588 bus->intr = bool_val;
2589 bus->intdis = false;
2590 if (bus->drvr->up) {
2591 BRCMF_INTR(("%s: %s SDIO interrupts\n", __func__,
2592 bus->intr ? "enable" : "disable"));
2593 if (bus->intr) {
2594 brcmf_sdcard_intr_enable(bus->card);
2595 } else {
2596 brcmf_sdcard_intr_disable(bus->card);
2597 }
2598 }
2599 break;
2600
2601 case IOV_GVAL(IOV_POLLRATE):
2602 int_val = (s32) bus->pollrate;
2603 memcpy(arg, &int_val, val_size);
2604 break;
2605
2606 case IOV_SVAL(IOV_POLLRATE):
2607 bus->pollrate = (uint) int_val;
2608 bus->poll = (bus->pollrate != 0);
2609 break;
2610
2611 case IOV_GVAL(IOV_IDLETIME):
2612 int_val = bus->idletime;
2613 memcpy(arg, &int_val, val_size);
2614 break;
2615
2616 case IOV_SVAL(IOV_IDLETIME):
2617 if ((int_val < 0) && (int_val != BRCMF_IDLE_IMMEDIATE))
2618 bcmerror = -EINVAL;
2619 else
2620 bus->idletime = int_val;
2621 break;
2622
2623 case IOV_GVAL(IOV_IDLECLOCK):
2624 int_val = (s32) bus->idleclock;
2625 memcpy(arg, &int_val, val_size);
2626 break;
2627
2628 case IOV_SVAL(IOV_IDLECLOCK):
2629 bus->idleclock = int_val;
2630 break;
2631
2632 case IOV_GVAL(IOV_SD1IDLE):
2633 int_val = (s32) sd1idle;
2634 memcpy(arg, &int_val, val_size);
2635 break;
2636
2637 case IOV_SVAL(IOV_SD1IDLE):
2638 sd1idle = bool_val;
2639 break;
2640
2641 case IOV_SVAL(IOV_MEMBYTES):
2642 case IOV_GVAL(IOV_MEMBYTES):
2643 {
2644 u32 address;
2645 uint size, dsize;
2646 u8 *data;
2647
2648 bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
2649
2650 address = (u32) int_val;
2651 memcpy(&int_val, (char *)params + sizeof(int_val),
2652 sizeof(int_val));
2653 size = (uint) int_val;
2654
2655 /* Do some validation */
2656 dsize = set ? plen - (2 * sizeof(int)) : len;
2657 if (dsize < size) {
2658 BRCMF_ERROR(("%s: error on %s membytes, addr "
2659 "0x%08x size %d dsize %d\n",
2660 __func__, (set ? "set" : "get"),
2661 address, size, dsize));
2662 bcmerror = -EINVAL;
2663 break;
2664 }
2665
2666 BRCMF_INFO(("%s: Request to %s %d bytes at address "
2667 "0x%08x\n", __func__,
2668 (set ? "write" : "read"), size, address));
2669
2670 /* If we know about SOCRAM, check for a fit */
2671 if ((bus->orig_ramsize) &&
2672 ((address > bus->orig_ramsize)
2673 || (address + size > bus->orig_ramsize))) {
2674 BRCMF_ERROR(("%s: ramsize 0x%08x doesn't have"
2675 " %d bytes at 0x%08x\n", __func__,
2676 bus->orig_ramsize, size, address));
2677 bcmerror = -EINVAL;
2678 break;
2679 }
2680
2681 /* Generate the actual data pointer */
2682 data =
2683 set ? (u8 *) params +
2684 2 * sizeof(int) : (u8 *) arg;
2685
2686 /* Call to do the transfer */
2687 bcmerror = brcmf_sdbrcm_membytes(bus, set, address,
2688 data, size);
2689
2690 break;
2691 }
2692
2693 case IOV_GVAL(IOV_MEMSIZE):
2694 int_val = (s32) bus->ramsize;
2695 memcpy(arg, &int_val, val_size);
2696 break;
2697
2698 case IOV_GVAL(IOV_SDIOD_DRIVE):
2699 int_val = (s32) brcmf_sdiod_drive_strength;
2700 memcpy(arg, &int_val, val_size);
2701 break;
2702
2703 case IOV_SVAL(IOV_SDIOD_DRIVE):
2704 brcmf_sdiod_drive_strength = int_val;
2705 brcmf_sdbrcm_sdiod_drive_strength_init(bus,
2706 brcmf_sdiod_drive_strength);
2707 break;
2708
2709 case IOV_SVAL(IOV_DOWNLOAD):
2710 bcmerror = brcmf_sdbrcm_download_state(bus, bool_val);
2711 break;
2712
2713 case IOV_SVAL(IOV_VARS):
2714 bcmerror = brcmf_sdbrcm_downloadvars(bus, arg, len);
2715 break;
2716
2717 case IOV_GVAL(IOV_READAHEAD):
2718 int_val = (s32) brcmf_readahead;
2719 memcpy(arg, &int_val, val_size);
2720 break;
2721
2722 case IOV_SVAL(IOV_READAHEAD):
2723 if (bool_val && !brcmf_readahead)
2724 bus->nextlen = 0;
2725 brcmf_readahead = bool_val;
2726 break;
2727
2728 case IOV_GVAL(IOV_SDRXCHAIN):
2729 int_val = (s32) bus->use_rxchain;
2730 memcpy(arg, &int_val, val_size);
2731 break;
2732
2733 case IOV_SVAL(IOV_SDRXCHAIN):
2734 if (bool_val && !bus->sd_rxchain)
2735 bcmerror = -ENOTSUPP;
2736 else
2737 bus->use_rxchain = bool_val;
2738 break;
2739 case IOV_GVAL(IOV_ALIGNCTL):
2740 int_val = (s32) brcmf_alignctl;
2741 memcpy(arg, &int_val, val_size);
2742 break;
2743
2744 case IOV_SVAL(IOV_ALIGNCTL):
2745 brcmf_alignctl = bool_val;
2746 break;
2747
2748 case IOV_GVAL(IOV_SDALIGN):
2749 int_val = BRCMF_SDALIGN;
2750 memcpy(arg, &int_val, val_size);
2751 break;
2752
2753#ifdef BCMDBG
2754 case IOV_GVAL(IOV_VARS):
2755 if (bus->varsz < (uint) len)
2756 memcpy(arg, bus->vars, bus->varsz);
2757 else
2758 bcmerror = -EOVERFLOW;
2759 break;
2760#endif /* BCMDBG */
2761
2762#ifdef BCMDBG
2763 case IOV_GVAL(IOV_DCONSOLE_POLL):
2764 int_val = (s32) brcmf_console_ms;
2765 memcpy(arg, &int_val, val_size);
2766 break;
2767
2768 case IOV_SVAL(IOV_DCONSOLE_POLL):
2769 brcmf_console_ms = (uint) int_val;
2770 break;
2771
2772 case IOV_SVAL(IOV_CONS):
2773 if (len > 0)
2774 bcmerror = brcmf_sdbrcm_bus_console_in(bus->drvr,
2775 arg, len - 1);
2776 break;
2777
2778 case IOV_GVAL(IOV_SDREG):
2779 {
2780 struct brcmf_sdreg *sd_ptr;
2781 u32 addr, size;
2782
2783 sd_ptr = (struct brcmf_sdreg *) params;
2784
2785 addr = bus->ci->buscorebase + sd_ptr->offset;
2786 size = sd_ptr->func;
2787 int_val = (s32) brcmf_sdcard_reg_read(bus->card, addr,
2788 size);
2789 if (brcmf_sdcard_regfail(bus->card))
2790 bcmerror = -EIO;
2791 memcpy(arg, &int_val, sizeof(s32));
2792 break;
2793 }
2794
2795 case IOV_SVAL(IOV_SDREG):
2796 {
2797 struct brcmf_sdreg *sd_ptr;
2798 u32 addr, size;
2799
2800 sd_ptr = (struct brcmf_sdreg *) params;
2801
2802 addr = bus->ci->buscorebase + sd_ptr->offset;
2803 size = sd_ptr->func;
2804 brcmf_sdcard_reg_write(bus->card, addr, size,
2805 sd_ptr->value);
2806 if (brcmf_sdcard_regfail(bus->card))
2807 bcmerror = -EIO;
2808 break;
2809 }
2810
2811 /* Same as above, but offset is not backplane
2812 (not SDIO core) */
2813 case IOV_GVAL(IOV_SBREG):
2814 {
2815 struct brcmf_sdreg sdreg;
2816 u32 addr, size;
2817
2818 memcpy(&sdreg, params, sizeof(sdreg));
2819
2820 addr = SI_ENUM_BASE + sdreg.offset;
2821 size = sdreg.func;
2822 int_val = (s32) brcmf_sdcard_reg_read(bus->card, addr,
2823 size);
2824 if (brcmf_sdcard_regfail(bus->card))
2825 bcmerror = -EIO;
2826 memcpy(arg, &int_val, sizeof(s32));
2827 break;
2828 }
2829
2830 case IOV_SVAL(IOV_SBREG):
2831 {
2832 struct brcmf_sdreg sdreg;
2833 u32 addr, size;
2834
2835 memcpy(&sdreg, params, sizeof(sdreg));
2836
2837 addr = SI_ENUM_BASE + sdreg.offset;
2838 size = sdreg.func;
2839 brcmf_sdcard_reg_write(bus->card, addr, size,
2840 sdreg.value);
2841 if (brcmf_sdcard_regfail(bus->card))
2842 bcmerror = -EIO;
2843 break;
2844 }
2845
2846 case IOV_GVAL(IOV_SDCIS):
2847 {
2848 *(char *)arg = 0;
2849
2850 strcat(arg, "\nFunc 0\n");
2851 brcmf_sdcard_cis_read(bus->card, 0x10,
2852 (u8 *) arg + strlen(arg),
2853 SBSDIO_CIS_SIZE_LIMIT);
2854 strcat(arg, "\nFunc 1\n");
2855 brcmf_sdcard_cis_read(bus->card, 0x11,
2856 (u8 *) arg + strlen(arg),
2857 SBSDIO_CIS_SIZE_LIMIT);
2858 strcat(arg, "\nFunc 2\n");
2859 brcmf_sdcard_cis_read(bus->card, 0x12,
2860 (u8 *) arg + strlen(arg),
2861 SBSDIO_CIS_SIZE_LIMIT);
2862 break;
2863 }
2864
2865 case IOV_GVAL(IOV_FORCEEVEN):
2866 int_val = (s32) forcealign;
2867 memcpy(arg, &int_val, val_size);
2868 break;
2869
2870 case IOV_SVAL(IOV_FORCEEVEN):
2871 forcealign = bool_val;
2872 break;
2873
2874 case IOV_GVAL(IOV_TXBOUND):
2875 int_val = (s32) brcmf_txbound;
2876 memcpy(arg, &int_val, val_size);
2877 break;
2878
2879 case IOV_SVAL(IOV_TXBOUND):
2880 brcmf_txbound = (uint) int_val;
2881 break;
2882
2883 case IOV_GVAL(IOV_RXBOUND):
2884 int_val = (s32) brcmf_rxbound;
2885 memcpy(arg, &int_val, val_size);
2886 break;
2887
2888 case IOV_SVAL(IOV_RXBOUND):
2889 brcmf_rxbound = (uint) int_val;
2890 break;
2891
2892 case IOV_GVAL(IOV_TXMINMAX):
2893 int_val = (s32) brcmf_txminmax;
2894 memcpy(arg, &int_val, val_size);
2895 break;
2896
2897 case IOV_SVAL(IOV_TXMINMAX):
2898 brcmf_txminmax = (uint) int_val;
2899 break;
2900#endif /* BCMDBG */
2901
2902#ifdef SDTEST
2903 case IOV_GVAL(IOV_EXTLOOP):
2904 int_val = (s32) bus->ext_loop;
2905 memcpy(arg, &int_val, val_size);
2906 break;
2907
2908 case IOV_SVAL(IOV_EXTLOOP):
2909 bus->ext_loop = bool_val;
2910 break;
2911
2912 case IOV_GVAL(IOV_PKTGEN):
2913 bcmerror = brcmf_sdbrcm_pktgen_get(bus, arg);
2914 break;
2915
2916 case IOV_SVAL(IOV_PKTGEN):
2917 bcmerror = brcmf_sdbrcm_pktgen_set(bus, arg);
2918 break;
2919#endif /* SDTEST */
2920
2921 case IOV_SVAL(IOV_DEVRESET):
2922 BRCMF_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d "
2923 "busstate=%d\n",
2924 __func__, bool_val, bus->drvr->dongle_reset,
2925 bus->drvr->busstate));
2926
2927 brcmf_bus_devreset(bus->drvr, (u8) bool_val);
2928
2929 break;
2930
2931 case IOV_GVAL(IOV_DEVRESET):
2932 BRCMF_TRACE(("%s: Called get IOV_DEVRESET\n", __func__));
2933
2934 /* Get its status */
2935 int_val = (bool) bus->drvr->dongle_reset;
2936 memcpy(arg, &int_val, val_size);
2937
2938 break;
2939
2940 case IOV_GVAL(IOV_WDTICK):
2941 int_val = (s32) brcmf_watchdog_ms;
2942 memcpy(arg, &int_val, val_size);
2943 break;
2944
2945 case IOV_SVAL(IOV_WDTICK):
2946 if (!bus->drvr->up) {
2947 bcmerror = -ENOLINK;
2948 break;
2949 }
2950 brcmf_sdbrcm_wd_timer(bus, (uint) int_val);
2951 break;
2952
2953 default:
2954 bcmerror = -ENOTSUPP;
2955 break;
2956 }
2957
2958exit:
2959 if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
2960 bus->activity = false;
2961 brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
2962 }
2963
2964 brcmf_sdbrcm_sdunlock(bus);
2965
2966 if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == false)
2967 brcmf_c_preinit_ioctls(bus->drvr);
2968
2969 return bcmerror;
2970}
2971
2972static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus)
2973{
2974 int bcmerror = 0;
2975 u32 varsize;
2976 u32 varaddr;
2977 u8 *vbuffer;
2978 u32 varsizew;
2979#ifdef BCMDBG
2980 char *nvram_ularray;
2981#endif /* BCMDBG */
2982
2983 /* Even if there are no vars are to be written, we still
2984 need to set the ramsize. */
2985 varsize = bus->varsz ? roundup(bus->varsz, 4) : 0;
2986 varaddr = (bus->ramsize - 4) - varsize;
2987
2988 if (bus->vars) {
2989 vbuffer = kzalloc(varsize, GFP_ATOMIC);
2990 if (!vbuffer)
2991 return -ENOMEM;
2992
2993 memcpy(vbuffer, bus->vars, bus->varsz);
2994
2995 /* Write the vars list */
2996 bcmerror =
2997 brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize);
2998#ifdef BCMDBG
2999 /* Verify NVRAM bytes */
3000 BRCMF_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
3001 nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
3002 if (!nvram_ularray)
3003 return -ENOMEM;
3004
3005 /* Upload image to verify downloaded contents. */
3006 memset(nvram_ularray, 0xaa, varsize);
3007
3008 /* Read the vars list to temp buffer for comparison */
3009 bcmerror =
3010 brcmf_sdbrcm_membytes(bus, false, varaddr, nvram_ularray,
3011 varsize);
3012 if (bcmerror) {
3013 BRCMF_ERROR(("%s: error %d on reading %d nvram bytes"
3014 " at 0x%08x\n", __func__, bcmerror,
3015 varsize, varaddr));
3016 }
3017 /* Compare the org NVRAM with the one read from RAM */
3018 if (memcmp(vbuffer, nvram_ularray, varsize)) {
3019 BRCMF_ERROR(("%s: Downloaded NVRAM image is "
3020 "corrupted.\n", __func__));
3021 } else
3022 BRCMF_ERROR(("%s: Download/Upload/Compare of"
3023 " NVRAM ok.\n", __func__));
3024
3025 kfree(nvram_ularray);
3026#endif /* BCMDBG */
3027
3028 kfree(vbuffer);
3029 }
3030
3031 /* adjust to the user specified RAM */
3032 BRCMF_INFO(("Physical memory size: %d, usable memory size: %d\n",
3033 bus->orig_ramsize, bus->ramsize));
3034 BRCMF_INFO(("Vars are at %d, orig varsize is %d\n", varaddr, varsize));
3035 varsize = ((bus->orig_ramsize - 4) - varaddr);
3036
3037 /*
3038 * Determine the length token:
3039 * Varsize, converted to words, in lower 16-bits, checksum
3040 * in upper 16-bits.
3041 */
3042 if (bcmerror) {
3043 varsizew = 0;
3044 } else {
3045 varsizew = varsize / 4;
3046 varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
3047 varsizew = cpu_to_le32(varsizew);
3048 }
3049
3050 BRCMF_INFO(("New varsize is %d, length token=0x%08x\n", varsize,
3051 varsizew));
3052
3053 /* Write the length token to the last word */
3054 bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->orig_ramsize - 4),
3055 (u8 *)&varsizew, 4);
3056
3057 return bcmerror;
3058}
3059
3060static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
3061{
3062 uint retries;
3063 u32 regdata;
3064 int bcmerror = 0;
3065
3066 /* To enter download state, disable ARM and reset SOCRAM.
3067 * To exit download state, simply reset ARM (default is RAM boot).
3068 */
3069 if (enter) {
3070 bus->alp_only = true;
3071
3072 brcmf_sdbrcm_chip_disablecore(bus->card, bus->ci->armcorebase);
3073
3074 brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->ramcorebase);
3075
3076 /* Clear the top bit of memory */
3077 if (bus->ramsize) {
3078 u32 zeros = 0;
3079 brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4,
3080 (u8 *)&zeros, 4);
3081 }
3082 } else {
3083 regdata = brcmf_sdcard_reg_read(bus->card,
3084 CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4);
3085 regdata &= (SBTML_RESET | SBTML_REJ_MASK |
3086 (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
3087 if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) {
3088 BRCMF_ERROR(("%s: SOCRAM core is down after reset?\n",
3089 __func__));
3090 bcmerror = -EBADE;
3091 goto fail;
3092 }
3093
3094 bcmerror = brcmf_sdbrcm_write_vars(bus);
3095 if (bcmerror) {
3096 BRCMF_ERROR(("%s: no vars written to RAM\n", __func__));
3097 bcmerror = 0;
3098 }
3099
3100 w_sdreg32(bus, 0xFFFFFFFF,
3101 offsetof(struct sdpcmd_regs, intstatus), &retries);
3102
3103 brcmf_sdbrcm_chip_resetcore(bus->card, bus->ci->armcorebase);
3104
3105 /* Allow HT Clock now that the ARM is running. */
3106 bus->alp_only = false;
3107
3108 bus->drvr->busstate = BRCMF_BUS_LOAD;
3109 }
3110fail:
3111 return bcmerror;
3112}
3113
3114int
3115brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name,
3116 void *params, int plen, void *arg, int len, bool set)
3117{
3118 struct brcmf_bus *bus = drvr->bus;
3119 const struct brcmu_iovar *vi = NULL;
3120 int bcmerror = 0;
3121 int val_size;
3122 u32 actionid;
3123
3124 BRCMF_TRACE(("%s: Enter\n", __func__));
3125
3126 if (name == NULL || len <= 0)
3127 return -EINVAL;
3128
3129 /* Set does not take qualifiers */
3130 if (set && (params || plen))
3131 return -EINVAL;
3132
3133 /* Get must have return space;*/
3134 if (!set && !(arg && len))
3135 return -EINVAL;
3136
3137 /* Look up var locally; if not found pass to host driver */
3138 vi = brcmu_iovar_lookup(brcmf_sdio_iovars, name);
3139 if (vi == NULL) {
3140 brcmf_sdbrcm_sdlock(bus);
3141
3142 BUS_WAKE(bus);
3143
3144 /* Turn on clock in case SD command needs backplane */
3145 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
3146
3147 bcmerror = brcmf_sdcard_iovar_op(bus->card, name, params, plen,
3148 arg, len, set);
3149
3150 /* Similar check for blocksize change */
3151 if (set && strcmp(name, "sd_blocksize") == 0) {
3152 s32 fnum = 2;
3153 if (brcmf_sdcard_iovar_op
3154 (bus->card, "sd_blocksize", &fnum, sizeof(s32),
3155 &bus->blocksize, sizeof(s32),
3156 false) != 0) {
3157 bus->blocksize = 0;
3158 BRCMF_ERROR(("%s: fail on %s get\n", __func__,
3159 "sd_blocksize"));
3160 } else {
3161 BRCMF_INFO(("%s: noted sd_blocksize update,"
3162 " value now %d\n", __func__,
3163 bus->blocksize));
3164 }
3165 }
3166 bus->roundup = min(max_roundup, bus->blocksize);
3167
3168 if (bus->idletime == BRCMF_IDLE_IMMEDIATE &&
3169 !bus->dpc_sched) {
3170 bus->activity = false;
3171 brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
3172 }
3173
3174 brcmf_sdbrcm_sdunlock(bus);
3175 goto exit;
3176 }
3177
3178 BRCMF_CTL(("%s: %s %s, len %d plen %d\n", __func__,
3179 name, (set ? "set" : "get"), len, plen));
3180
3181 /* set up 'params' pointer in case this is a set command so that
3182 * the convenience int and bool code can be common to set and get
3183 */
3184 if (params == NULL) {
3185 params = arg;
3186 plen = len;
3187 }
3188
3189 if (vi->type == IOVT_VOID)
3190 val_size = 0;
3191 else if (vi->type == IOVT_BUFFER)
3192 val_size = len;
3193 else
3194 /* all other types are integer sized */
3195 val_size = sizeof(int);
3196
3197 actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
3198 bcmerror = brcmf_sdbrcm_doiovar(bus, vi, actionid, name, params, plen,
3199 arg, len, val_size);
3200
3201exit:
3202 return bcmerror;
3203}
3204
3205void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex)
3206{
3207 u32 local_hostintmask;
3208 u8 saveclk;
3209 uint retries;
3210 int err;
3211
3212 BRCMF_TRACE(("%s: Enter\n", __func__));
3213
3214 if (enforce_mutex)
3215 brcmf_sdbrcm_sdlock(bus);
3216
3217 BUS_WAKE(bus);
3218
3219 /* Enable clock for device interrupts */
3220 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
3221
3222 if (bus->watchdog_tsk) {
3223 send_sig(SIGTERM, bus->watchdog_tsk, 1);
3224 kthread_stop(bus->watchdog_tsk);
3225 bus->watchdog_tsk = NULL;
3226 }
3227
3228 if (bus->dpc_tsk) {
3229 send_sig(SIGTERM, bus->dpc_tsk, 1);
3230 kthread_stop(bus->dpc_tsk);
3231 bus->dpc_tsk = NULL;
3232 } else
3233 tasklet_kill(&bus->tasklet);
3234
3235 /* Disable and clear interrupts at the chip level also */
3236 w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries);
3237 local_hostintmask = bus->hostintmask;
3238 bus->hostintmask = 0;
3239
3240 /* Change our idea of bus state */
3241 bus->drvr->busstate = BRCMF_BUS_DOWN;
3242
3243 /* Force clocks on backplane to be sure F2 interrupt propagates */
3244 saveclk = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
3245 SBSDIO_FUNC1_CHIPCLKCSR, &err);
3246 if (!err) {
3247 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
3248 SBSDIO_FUNC1_CHIPCLKCSR,
3249 (saveclk | SBSDIO_FORCE_HT), &err);
3250 }
3251 if (err) {
3252 BRCMF_ERROR(("%s: Failed to force clock for F2: err %d\n",
3253 __func__, err));
3254 }
3255
3256 /* Turn off the bus (F2), free any pending packets */
3257 BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
3258 brcmf_sdcard_intr_disable(bus->card);
3259 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
3260 SDIO_FUNC_ENABLE_1, NULL);
3261
3262 /* Clear any pending interrupts now that F2 is disabled */
3263 w_sdreg32(bus, local_hostintmask,
3264 offsetof(struct sdpcmd_regs, intstatus), &retries);
3265
3266 /* Turn off the backplane clock (only) */
3267 brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
3268
3269 /* Clear the data packet queues */
3270 brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
3271
3272 /* Clear any held glomming stuff */
3273 if (bus->glomd)
3274 brcmu_pkt_buf_free_skb(bus->glomd);
3275
3276 if (bus->glom)
3277 brcmu_pkt_buf_free_skb(bus->glom);
3278
3279 bus->glom = bus->glomd = NULL;
3280
3281 /* Clear rx control and wake any waiters */
3282 bus->rxlen = 0;
3283 brcmf_os_ioctl_resp_wake(bus->drvr);
3284
3285 /* Reset some F2 state stuff */
3286 bus->rxskip = false;
3287 bus->tx_seq = bus->rx_seq = 0;
3288
3289 if (enforce_mutex)
3290 brcmf_sdbrcm_sdunlock(bus);
3291}
3292
3293int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex)
3294{
3295 struct brcmf_bus *bus = drvr->bus;
3296 struct brcmf_timeout tmo;
3297 uint retries = 0;
3298 u8 ready, enable;
3299 int err, ret = 0;
3300 u8 saveclk;
3301
3302 BRCMF_TRACE(("%s: Enter\n", __func__));
3303
3304 /* try to download image and nvram to the dongle */
3305 if (drvr->busstate == BRCMF_BUS_DOWN) {
3306 if (!(brcmf_sdbrcm_download_firmware(bus, bus->card)))
3307 return -1;
3308 }
3309
3310 if (!bus->drvr)
3311 return 0;
3312
3313 /* Start the watchdog timer */
3314 bus->drvr->tickcnt = 0;
3315 brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
3316
3317 if (enforce_mutex)
3318 brcmf_sdbrcm_sdlock(bus);
3319
3320 /* Make sure backplane clock is on, needed to generate F2 interrupt */
3321 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
3322 if (bus->clkstate != CLK_AVAIL)
3323 goto exit;
3324
3325 /* Force clocks on backplane to be sure F2 interrupt propagates */
3326 saveclk =
3327 brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
3328 SBSDIO_FUNC1_CHIPCLKCSR, &err);
3329 if (!err) {
3330 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
3331 SBSDIO_FUNC1_CHIPCLKCSR,
3332 (saveclk | SBSDIO_FORCE_HT), &err);
3333 }
3334 if (err) {
3335 BRCMF_ERROR(("%s: Failed to force clock for F2: err %d\n",
3336 __func__, err));
3337 goto exit;
3338 }
3339
3340 /* Enable function 2 (frame transfers) */
3341 w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
3342 offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries);
3343 enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
3344
3345 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx, enable,
3346 NULL);
3347
3348 /* Give the dongle some time to do its thing and set IOR2 */
3349 brcmf_timeout_start(&tmo, BRCMF_WAIT_F2RDY * 1000);
3350
3351 ready = 0;
3352 while (ready != enable && !brcmf_timeout_expired(&tmo))
3353 ready = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_0,
3354 SDIO_CCCR_IORx, NULL);
3355
3356 BRCMF_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
3357 __func__, enable, ready, tmo.elapsed));
3358
3359 /* If F2 successfully enabled, set core and enable interrupts */
3360 if (ready == enable) {
3361 /* Set up the interrupt mask and enable interrupts */
3362 bus->hostintmask = HOSTINTMASK;
3363 w_sdreg32(bus, bus->hostintmask,
3364 offsetof(struct sdpcmd_regs, hostintmask), &retries);
3365
3366 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_WATERMARK,
3367 (u8) watermark, &err);
3368
3369 /* Set bus state according to enable result */
3370 drvr->busstate = BRCMF_BUS_DATA;
3371
3372 bus->intdis = false;
3373 if (bus->intr) {
3374 BRCMF_INTR(("%s: enable SDIO device interrupts\n",
3375 __func__));
3376 brcmf_sdcard_intr_enable(bus->card);
3377 } else {
3378 BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
3379 brcmf_sdcard_intr_disable(bus->card);
3380 }
3381
3382 }
3383
3384 else {
3385 /* Disable F2 again */
3386 enable = SDIO_FUNC_ENABLE_1;
3387 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
3388 enable, NULL);
3389 }
3390
3391 /* Restore previous clock setting */
3392 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
3393 saveclk, &err);
3394
3395#if defined(OOB_INTR_ONLY)
3396 /* Host registration for OOB interrupt */
3397 if (brcmf_sdio_register_oob_intr(bus->dhd)) {
3398 brcmf_sdbrcm_wd_timer(bus, 0);
3399 BRCMF_ERROR(("%s Host failed to resgister for OOB\n",
3400 __func__));
3401 ret = -ENODEV;
3402 goto exit;
3403 }
3404
3405 /* Enable oob at firmware */
3406 brcmf_sdbrcm_enable_oob_intr(bus, true);
3407#endif /* defined(OOB_INTR_ONLY) */
3408
3409 /* If we didn't come up, turn off backplane clock */
3410 if (drvr->busstate != BRCMF_BUS_DATA)
3411 brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
3412
3413exit:
3414 if (enforce_mutex)
3415 brcmf_sdbrcm_sdunlock(bus);
3416
3417 return ret;
3418}
3419
3420static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
3421{
3422 struct brcmf_sdio_card *card = bus->card;
3423 uint retries = 0;
3424 u16 lastrbc;
3425 u8 hi, lo;
3426 int err;
3427
3428 BRCMF_ERROR(("%s: %sterminate frame%s\n", __func__,
3429 (abort ? "abort command, " : ""),
3430 (rtx ? ", send NAK" : "")));
3431
3432 if (abort)
3433 brcmf_sdcard_abort(card, SDIO_FUNC_2);
3434
3435 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
3436 SFC_RF_TERM, &err);
3437 bus->f1regdata++;
3438
3439 /* Wait until the packet has been flushed (device/FIFO stable) */
3440 for (lastrbc = retries = 0xffff; retries > 0; retries--) {
3441 hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
3442 SBSDIO_FUNC1_RFRAMEBCHI, NULL);
3443 lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
3444 SBSDIO_FUNC1_RFRAMEBCLO, NULL);
3445 bus->f1regdata += 2;
3446
3447 if ((hi == 0) && (lo == 0))
3448 break;
3449
3450 if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
3451 BRCMF_ERROR(("%s: count growing: last 0x%04x now "
3452 "0x%04x\n",
3453 __func__, lastrbc, ((hi << 8) + lo)));
3454 }
3455 lastrbc = (hi << 8) + lo;
3456 }
3457
3458 if (!retries) {
3459 BRCMF_ERROR(("%s: count never zeroed: last 0x%04x\n",
3460 __func__, lastrbc));
3461 } else {
3462 BRCMF_INFO(("%s: flush took %d iterations\n", __func__,
3463 (0xffff - retries)));
3464 }
3465
3466 if (rtx) {
3467 bus->rxrtx++;
3468 w_sdreg32(bus, SMB_NAK,
3469 offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
3470
3471 bus->f1regdata++;
3472 if (retries <= retry_limit)
3473 bus->rxskip = true;
3474 }
3475
3476 /* Clear partial in any case */
3477 bus->nextlen = 0;
3478
3479 /* If we can't reach the device, signal failure */
3480 if (err || brcmf_sdcard_regfail(card))
3481 bus->drvr->busstate = BRCMF_BUS_DOWN;
3482}
3483
3484static void
3485brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff)
3486{
3487 struct brcmf_sdio_card *card = bus->card;
3488 uint rdlen, pad;
3489
3490 int sdret;
3491
3492 BRCMF_TRACE(("%s: Enter\n", __func__));
3493
3494 /* Control data already received in aligned rxctl */
3495 if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
3496 goto gotpkt;
3497
3498 /* Set rxctl for frame (w/optional alignment) */
3499 bus->rxctl = bus->rxbuf;
3500 if (brcmf_alignctl) {
3501 bus->rxctl += firstread;
3502 pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN);
3503 if (pad)
3504 bus->rxctl += (BRCMF_SDALIGN - pad);
3505 bus->rxctl -= firstread;
3506 }
3507
3508 /* Copy the already-read portion over */
3509 memcpy(bus->rxctl, hdr, firstread);
3510 if (len <= firstread)
3511 goto gotpkt;
3512
3513 /* Copy the full data pkt in gSPI case and process ioctl. */
3514 if (bus->bus == SPI_BUS) {
3515 memcpy(bus->rxctl, hdr, len);
3516 goto gotpkt;
3517 }
3518
3519 /* Raise rdlen to next SDIO block to avoid tail command */
3520 rdlen = len - firstread;
3521 if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
3522 pad = bus->blocksize - (rdlen % bus->blocksize);
3523 if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
3524 ((len + pad) < bus->drvr->maxctl))
3525 rdlen += pad;
3526 } else if (rdlen % BRCMF_SDALIGN) {
3527 rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
3528 }
3529
3530 /* Satisfy length-alignment requirements */
3531 if (forcealign && (rdlen & (ALIGNMENT - 1)))
3532 rdlen = roundup(rdlen, ALIGNMENT);
3533
3534 /* Drop if the read is too big or it exceeds our maximum */
3535 if ((rdlen + firstread) > bus->drvr->maxctl) {
3536 BRCMF_ERROR(("%s: %d-byte control read exceeds %d-byte"
3537 " buffer\n", __func__, rdlen, bus->drvr->maxctl));
3538 bus->drvr->rx_errors++;
3539 brcmf_sdbrcm_rxfail(bus, false, false);
3540 goto done;
3541 }
3542
3543 if ((len - doff) > bus->drvr->maxctl) {
3544 BRCMF_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds "
3545 "%d-byte limit\n",
3546 __func__, len, (len - doff), bus->drvr->maxctl));
3547 bus->drvr->rx_errors++;
3548 bus->rx_toolong++;
3549 brcmf_sdbrcm_rxfail(bus, false, false);
3550 goto done;
3551 }
3552
3553 /* Read remainder of frame body into the rxctl buffer */
3554 sdret = brcmf_sdcard_recv_buf(card, brcmf_sdcard_cur_sbwad(card),
3555 SDIO_FUNC_2,
3556 F2SYNC, (bus->rxctl + firstread), rdlen,
3557 NULL, NULL, NULL);
3558 bus->f2rxdata++;
3559
3560 /* Control frame failures need retransmission */
3561 if (sdret < 0) {
3562 BRCMF_ERROR(("%s: read %d control bytes failed: %d\n",
3563 __func__, rdlen, sdret));
3564 bus->rxc_errors++;
3565 brcmf_sdbrcm_rxfail(bus, true, true);
3566 goto done;
3567 }
3568
3569gotpkt:
3570
3571#ifdef BCMDBG
3572 if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) {
3573 printk(KERN_DEBUG "RxCtrl:\n");
3574 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len);
3575 }
3576#endif
3577
3578 /* Point to valid data and indicate its length */
3579 bus->rxctl += doff;
3580 bus->rxlen = len - doff;
3581
3582done:
3583 /* Awake any waiters */
3584 brcmf_os_ioctl_resp_wake(bus->drvr);
3585}
3586
3587static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
3588{
3589 u16 dlen, totlen;
3590 u8 *dptr, num = 0;
3591
3592 u16 sublen, check;
3593 struct sk_buff *pfirst, *plast, *pnext, *save_pfirst;
3594
3595 int errcode;
3596 u8 chan, seq, doff, sfdoff;
3597 u8 txmax;
3598
3599 int ifidx = 0;
3600 bool usechain = bus->use_rxchain;
3601
3602 /* If packets, issue read(s) and send up packet chain */
3603 /* Return sequence numbers consumed? */
3604
3605 BRCMF_TRACE(("brcmf_sdbrcm_rxglom: start: glomd %p glom %p\n",
3606 bus->glomd, bus->glom));
3607
3608 /* If there's a descriptor, generate the packet chain */
3609 if (bus->glomd) {
3610 pfirst = plast = pnext = NULL;
3611 dlen = (u16) (bus->glomd->len);
3612 dptr = bus->glomd->data;
3613 if (!dlen || (dlen & 1)) {
3614 BRCMF_ERROR(("%s: bad glomd len(%d),"
3615 " ignore descriptor\n",
3616 __func__, dlen));
3617 dlen = 0;
3618 }
3619
3620 for (totlen = num = 0; dlen; num++) {
3621 /* Get (and move past) next length */
3622 sublen = get_unaligned_le16(dptr);
3623 dlen -= sizeof(u16);
3624 dptr += sizeof(u16);
3625 if ((sublen < SDPCM_HDRLEN) ||
3626 ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
3627 BRCMF_ERROR(("%s: descriptor len %d bad: %d\n",
3628 __func__, num, sublen));
3629 pnext = NULL;
3630 break;
3631 }
3632 if (sublen % BRCMF_SDALIGN) {
3633 BRCMF_ERROR(("%s: sublen %d not multiple of"
3634 " %d\n", __func__, sublen,
3635 BRCMF_SDALIGN));
3636 usechain = false;
3637 }
3638 totlen += sublen;
3639
3640 /* For last frame, adjust read len so total
3641 is a block multiple */
3642 if (!dlen) {
3643 sublen +=
3644 (roundup(totlen, bus->blocksize) - totlen);
3645 totlen = roundup(totlen, bus->blocksize);
3646 }
3647
3648 /* Allocate/chain packet for next subframe */
3649 pnext = brcmu_pkt_buf_get_skb(sublen + BRCMF_SDALIGN);
3650 if (pnext == NULL) {
3651 BRCMF_ERROR(("%s: bcm_pkt_buf_get_skb failed, "
3652 "num %d len %d\n", __func__,
3653 num, sublen));
3654 break;
3655 }
3656 if (!pfirst) {
3657 pfirst = plast = pnext;
3658 } else {
3659 plast->next = pnext;
3660 plast = pnext;
3661 }
3662
3663 /* Adhere to start alignment requirements */
3664 PKTALIGN(pnext, sublen, BRCMF_SDALIGN);
3665 }
3666
3667 /* If all allocations succeeded, save packet chain
3668 in bus structure */
3669 if (pnext) {
3670 BRCMF_GLOM(("%s: allocated %d-byte packet chain for %d "
3671 "subframes\n", __func__, totlen, num));
3672 if (BRCMF_GLOM_ON() && bus->nextlen) {
3673 if (totlen != bus->nextlen) {
3674 BRCMF_GLOM(("%s: glomdesc mismatch: "
3675 "nextlen %d glomdesc %d "
3676 "rxseq %d\n", __func__,
3677 bus->nextlen,
3678 totlen, rxseq));
3679 }
3680 }
3681 bus->glom = pfirst;
3682 pfirst = pnext = NULL;
3683 } else {
3684 if (pfirst)
3685 brcmu_pkt_buf_free_skb(pfirst);
3686 bus->glom = NULL;
3687 num = 0;
3688 }
3689
3690 /* Done with descriptor packet */
3691 brcmu_pkt_buf_free_skb(bus->glomd);
3692 bus->glomd = NULL;
3693 bus->nextlen = 0;
3694 }
3695
3696 /* Ok -- either we just generated a packet chain,
3697 or had one from before */
3698 if (bus->glom) {
3699 if (BRCMF_GLOM_ON()) {
3700 BRCMF_GLOM(("%s: try superframe read, packet chain:\n",
3701 __func__));
3702 for (pnext = bus->glom; pnext; pnext = pnext->next) {
3703 BRCMF_GLOM((" %p: %p len 0x%04x (%d)\n",
3704 pnext, (u8 *) (pnext->data),
3705 pnext->len, pnext->len));
3706 }
3707 }
3708
3709 pfirst = bus->glom;
3710 dlen = (u16) brcmu_pkttotlen(pfirst);
3711
3712 /* Do an SDIO read for the superframe. Configurable iovar to
3713 * read directly into the chained packet, or allocate a large
3714 * packet and and copy into the chain.
3715 */
3716 if (usechain) {
3717 errcode = brcmf_sdcard_recv_buf(bus->card,
3718 brcmf_sdcard_cur_sbwad(bus->card),
3719 SDIO_FUNC_2,
3720 F2SYNC, (u8 *) pfirst->data, dlen,
3721 pfirst, NULL, NULL);
3722 } else if (bus->dataptr) {
3723 errcode = brcmf_sdcard_recv_buf(bus->card,
3724 brcmf_sdcard_cur_sbwad(bus->card),
3725 SDIO_FUNC_2,
3726 F2SYNC, bus->dataptr, dlen,
3727 NULL, NULL, NULL);
3728 sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen,
3729 bus->dataptr);
3730 if (sublen != dlen) {
3731 BRCMF_ERROR(("%s: FAILED TO COPY, dlen %d "
3732 "sublen %d\n",
3733 __func__, dlen, sublen));
3734 errcode = -1;
3735 }
3736 pnext = NULL;
3737 } else {
3738 BRCMF_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, "
3739 "FORCE FAILURE\n", dlen));
3740 errcode = -1;
3741 }
3742 bus->f2rxdata++;
3743
3744 /* On failure, kill the superframe, allow a couple retries */
3745 if (errcode < 0) {
3746 BRCMF_ERROR(("%s: glom read of %d bytes failed: %d\n",
3747 __func__, dlen, errcode));
3748 bus->drvr->rx_errors++;
3749
3750 if (bus->glomerr++ < 3) {
3751 brcmf_sdbrcm_rxfail(bus, true, true);
3752 } else {
3753 bus->glomerr = 0;
3754 brcmf_sdbrcm_rxfail(bus, true, false);
3755 brcmu_pkt_buf_free_skb(bus->glom);
3756 bus->rxglomfail++;
3757 bus->glom = NULL;
3758 }
3759 return 0;
3760 }
3761#ifdef BCMDBG
3762 if (BRCMF_GLOM_ON()) {
3763 printk(KERN_DEBUG "SUPERFRAME:\n");
3764 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
3765 pfirst->data, min_t(int, pfirst->len, 48));
3766 }
3767#endif
3768
3769 /* Validate the superframe header */
3770 dptr = (u8 *) (pfirst->data);
3771 sublen = get_unaligned_le16(dptr);
3772 check = get_unaligned_le16(dptr + sizeof(u16));
3773
3774 chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
3775 seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
3776 bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
3777 if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
3778 BRCMF_INFO(("%s: nextlen too large (%d) seq %d\n",
3779 __func__, bus->nextlen, seq));
3780 bus->nextlen = 0;
3781 }
3782 doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
3783 txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
3784
3785 errcode = 0;
3786 if ((u16)~(sublen ^ check)) {
3787 BRCMF_ERROR(("%s (superframe): HW hdr error: len/check "
3788 "0x%04x/0x%04x\n", __func__, sublen,
3789 check));
3790 errcode = -1;
3791 } else if (roundup(sublen, bus->blocksize) != dlen) {
3792 BRCMF_ERROR(("%s (superframe): len 0x%04x, rounded "
3793 "0x%04x, expect 0x%04x\n",
3794 __func__, sublen,
3795 roundup(sublen, bus->blocksize), dlen));
3796 errcode = -1;
3797 } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) !=
3798 SDPCM_GLOM_CHANNEL) {
3799 BRCMF_ERROR(("%s (superframe): bad channel %d\n",
3800 __func__,
3801 SDPCM_PACKET_CHANNEL(&dptr
3802 [SDPCM_FRAMETAG_LEN])));
3803 errcode = -1;
3804 } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
3805 BRCMF_ERROR(("%s (superframe): got 2nd descriptor?\n",
3806 __func__));
3807 errcode = -1;
3808 } else if ((doff < SDPCM_HDRLEN) ||
3809 (doff > (pfirst->len - SDPCM_HDRLEN))) {
3810 BRCMF_ERROR(("%s (superframe): Bad data offset %d: "
3811 "HW %d pkt %d min %d\n",
3812 __func__, doff, sublen,
3813 pfirst->len, SDPCM_HDRLEN));
3814 errcode = -1;
3815 }
3816
3817 /* Check sequence number of superframe SW header */
3818 if (rxseq != seq) {
3819 BRCMF_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
3820 __func__, seq, rxseq));
3821 bus->rx_badseq++;
3822 rxseq = seq;
3823 }
3824
3825 /* Check window for sanity */
3826 if ((u8) (txmax - bus->tx_seq) > 0x40) {
3827 BRCMF_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
3828 __func__, txmax, bus->tx_seq));
3829 txmax = bus->tx_seq + 2;
3830 }
3831 bus->tx_max = txmax;
3832
3833 /* Remove superframe header, remember offset */
3834 skb_pull(pfirst, doff);
3835 sfdoff = doff;
3836
3837 /* Validate all the subframe headers */
3838 for (num = 0, pnext = pfirst; pnext && !errcode;
3839 num++, pnext = pnext->next) {
3840 dptr = (u8 *) (pnext->data);
3841 dlen = (u16) (pnext->len);
3842 sublen = get_unaligned_le16(dptr);
3843 check = get_unaligned_le16(dptr + sizeof(u16));
3844 chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
3845 doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
3846#ifdef BCMDBG
3847 if (BRCMF_GLOM_ON()) {
3848 printk(KERN_DEBUG "subframe:\n");
3849 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
3850 dptr, 32);
3851 }
3852#endif
3853
3854 if ((u16)~(sublen ^ check)) {
3855 BRCMF_ERROR(("%s (subframe %d): HW hdr error: "
3856 "len/check 0x%04x/0x%04x\n",
3857 __func__, num, sublen, check));
3858 errcode = -1;
3859 } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
3860 BRCMF_ERROR(("%s (subframe %d): length mismatch"
3861 ": len 0x%04x, expect 0x%04x\n",
3862 __func__, num, sublen, dlen));
3863 errcode = -1;
3864 } else if ((chan != SDPCM_DATA_CHANNEL) &&
3865 (chan != SDPCM_EVENT_CHANNEL)) {
3866 BRCMF_ERROR(("%s (subframe %d): bad channel"
3867 " %d\n", __func__, num, chan));
3868 errcode = -1;
3869 } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
3870 BRCMF_ERROR(("%s (subframe %d): Bad data offset"
3871 " %d: HW %d min %d\n",
3872 __func__, num, doff, sublen,
3873 SDPCM_HDRLEN));
3874 errcode = -1;
3875 }
3876 }
3877
3878 if (errcode) {
3879 /* Terminate frame on error, request
3880 a couple retries */
3881 if (bus->glomerr++ < 3) {
3882 /* Restore superframe header space */
3883 skb_push(pfirst, sfdoff);
3884 brcmf_sdbrcm_rxfail(bus, true, true);
3885 } else {
3886 bus->glomerr = 0;
3887 brcmf_sdbrcm_rxfail(bus, true, false);
3888 brcmu_pkt_buf_free_skb(bus->glom);
3889 bus->rxglomfail++;
3890 bus->glom = NULL;
3891 }
3892 bus->nextlen = 0;
3893 return 0;
3894 }
3895
3896 /* Basic SD framing looks ok - process each packet (header) */
3897 save_pfirst = pfirst;
3898 bus->glom = NULL;
3899 plast = NULL;
3900
3901 for (num = 0; pfirst; rxseq++, pfirst = pnext) {
3902 pnext = pfirst->next;
3903 pfirst->next = NULL;
3904
3905 dptr = (u8 *) (pfirst->data);
3906 sublen = get_unaligned_le16(dptr);
3907 chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
3908 seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
3909 doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
3910
3911 BRCMF_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d "
3912 "chan %d seq %d\n",
3913 __func__, num, pfirst, pfirst->data,
3914 pfirst->len, sublen, chan, seq));
3915
3916 /* precondition: chan == SDPCM_DATA_CHANNEL ||
3917 chan == SDPCM_EVENT_CHANNEL */
3918
3919 if (rxseq != seq) {
3920 BRCMF_GLOM(("%s: rx_seq %d, expected %d\n",
3921 __func__, seq, rxseq));
3922 bus->rx_badseq++;
3923 rxseq = seq;
3924 }
3925#ifdef BCMDBG
3926 if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
3927 printk(KERN_DEBUG "Rx Subframe Data:\n");
3928 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
3929 dptr, dlen);
3930 }
3931#endif
3932
3933 __skb_trim(pfirst, sublen);
3934 skb_pull(pfirst, doff);
3935
3936 if (pfirst->len == 0) {
3937 brcmu_pkt_buf_free_skb(pfirst);
3938 if (plast) {
3939 plast->next = pnext;
3940 } else {
3941 save_pfirst = pnext;
3942 }
3943 continue;
3944 } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pfirst)
3945 != 0) {
3946 BRCMF_ERROR(("%s: rx protocol error\n",
3947 __func__));
3948 bus->drvr->rx_errors++;
3949 brcmu_pkt_buf_free_skb(pfirst);
3950 if (plast) {
3951 plast->next = pnext;
3952 } else {
3953 save_pfirst = pnext;
3954 }
3955 continue;
3956 }
3957
3958 /* this packet will go up, link back into
3959 chain and count it */
3960 pfirst->next = pnext;
3961 plast = pfirst;
3962 num++;
3963
3964#ifdef BCMDBG
3965 if (BRCMF_GLOM_ON()) {
3966 BRCMF_GLOM(("%s subframe %d to stack, %p"
3967 "(%p/%d) nxt/lnk %p/%p\n",
3968 __func__, num, pfirst, pfirst->data,
3969 pfirst->len, pfirst->next,
3970 pfirst->prev));
3971 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
3972 pfirst->data,
3973 min_t(int, pfirst->len, 32));
3974 }
3975#endif /* BCMDBG */
3976 }
3977 if (num) {
3978 brcmf_sdbrcm_sdunlock(bus);
3979 brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num);
3980 brcmf_sdbrcm_sdlock(bus);
3981 }
3982
3983 bus->rxglomframes++;
3984 bus->rxglompkts += num;
3985 }
3986 return num;
3987}
3988
3989/* Return true if there may be more frames to read */
3990static uint
3991brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
3992{
3993 struct brcmf_sdio_card *card = bus->card;
3994
3995 u16 len, check; /* Extracted hardware header fields */
3996 u8 chan, seq, doff; /* Extracted software header fields */
3997 u8 fcbits; /* Extracted fcbits from software header */
3998
3999 struct sk_buff *pkt; /* Packet for event or data frames */
4000 u16 pad; /* Number of pad bytes to read */
4001 u16 rdlen; /* Total number of bytes to read */
4002 u8 rxseq; /* Next sequence number to expect */
4003 uint rxleft = 0; /* Remaining number of frames allowed */
4004 int sdret; /* Return code from calls */
4005 u8 txmax; /* Maximum tx sequence offered */
4006 bool len_consistent; /* Result of comparing readahead len and
4007 len from hw-hdr */
4008 u8 *rxbuf;
4009 int ifidx = 0;
4010 uint rxcount = 0; /* Total frames read */
4011
4012#if defined(BCMDBG) || defined(SDTEST)
4013 bool sdtest = false; /* To limit message spew from test mode */
4014#endif
4015
4016 BRCMF_TRACE(("%s: Enter\n", __func__));
4017
4018#ifdef SDTEST
4019 /* Allow pktgen to override maxframes */
4020 if (bus->pktgen_count && (bus->pktgen_mode == BRCMF_PKTGEN_RECV)) {
4021 maxframes = bus->pktgen_count;
4022 sdtest = true;
4023 }
4024#endif
4025
4026 /* Not finished unless we encounter no more frames indication */
4027 *finished = false;
4028
4029 for (rxseq = bus->rx_seq, rxleft = maxframes;
4030 !bus->rxskip && rxleft && bus->drvr->busstate != BRCMF_BUS_DOWN;
4031 rxseq++, rxleft--) {
4032
4033 /* Handle glomming separately */
4034 if (bus->glom || bus->glomd) {
4035 u8 cnt;
4036 BRCMF_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
4037 __func__, bus->glomd, bus->glom));
4038 cnt = brcmf_sdbrcm_rxglom(bus, rxseq);
4039 BRCMF_GLOM(("%s: rxglom returned %d\n", __func__, cnt));
4040 rxseq += cnt - 1;
4041 rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
4042 continue;
4043 }
4044
4045 /* Try doing single read if we can */
4046 if (brcmf_readahead && bus->nextlen) {
4047 u16 nextlen = bus->nextlen;
4048 bus->nextlen = 0;
4049
4050 if (bus->bus == SPI_BUS) {
4051 rdlen = len = nextlen;
4052 } else {
4053 rdlen = len = nextlen << 4;
4054
4055 /* Pad read to blocksize for efficiency */
4056 if (bus->roundup && bus->blocksize
4057 && (rdlen > bus->blocksize)) {
4058 pad =
4059 bus->blocksize -
4060 (rdlen % bus->blocksize);
4061 if ((pad <= bus->roundup)
4062 && (pad < bus->blocksize)
4063 && ((rdlen + pad + firstread) <
4064 MAX_RX_DATASZ))
4065 rdlen += pad;
4066 } else if (rdlen % BRCMF_SDALIGN) {
4067 rdlen +=
4068 BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
4069 }
4070 }
4071
4072 /* We use bus->rxctl buffer in WinXP for initial
4073 * control pkt receives.
4074 * Later we use buffer-poll for data as well
4075 * as control packets.
4076 * This is required because dhd receives full
4077 * frame in gSPI unlike SDIO.
4078 * After the frame is received we have to
4079 * distinguish whether it is data
4080 * or non-data frame.
4081 */
4082 /* Allocate a packet buffer */
4083 pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN);
4084 if (!pkt) {
4085 if (bus->bus == SPI_BUS) {
4086 bus->usebufpool = false;
4087 bus->rxctl = bus->rxbuf;
4088 if (brcmf_alignctl) {
4089 bus->rxctl += firstread;
4090 pad = ((unsigned long)bus->rxctl %
4091 BRCMF_SDALIGN);
4092 if (pad)
4093 bus->rxctl +=
4094 (BRCMF_SDALIGN - pad);
4095 bus->rxctl -= firstread;
4096 }
4097 rxbuf = bus->rxctl;
4098 /* Read the entire frame */
4099 sdret = brcmf_sdcard_recv_buf(card,
4100 brcmf_sdcard_cur_sbwad(card),
4101 SDIO_FUNC_2, F2SYNC,
4102 rxbuf, rdlen,
4103 NULL, NULL, NULL);
4104 bus->f2rxdata++;
4105
4106 /* Control frame failures need
4107 retransmission */
4108 if (sdret < 0) {
4109 BRCMF_ERROR(("%s: read %d "
4110 "control bytes "
4111 "failed: %d\n",
4112 __func__,
4113 rdlen, sdret));
4114 /* dhd.rx_ctlerrs is higher */
4115 bus->rxc_errors++;
4116 brcmf_sdbrcm_rxfail(bus, true,
4117 (bus->bus ==
4118 SPI_BUS) ? false
4119 : true);
4120 continue;
4121 }
4122 } else {
4123 /* Give up on data,
4124 request rtx of events */
4125 BRCMF_ERROR(("%s (nextlen): "
4126 "brcmu_pkt_buf_get_skb "
4127 "failed:"
4128 " len %d rdlen %d expected"
4129 " rxseq %d\n", __func__,
4130 len, rdlen, rxseq));
4131 continue;
4132 }
4133 } else {
4134 if (bus->bus == SPI_BUS)
4135 bus->usebufpool = true;
4136
4137 PKTALIGN(pkt, rdlen, BRCMF_SDALIGN);
4138 rxbuf = (u8 *) (pkt->data);
4139 /* Read the entire frame */
4140 sdret = brcmf_sdcard_recv_buf(card,
4141 brcmf_sdcard_cur_sbwad(card),
4142 SDIO_FUNC_2, F2SYNC,
4143 rxbuf, rdlen,
4144 pkt, NULL, NULL);
4145 bus->f2rxdata++;
4146
4147 if (sdret < 0) {
4148 BRCMF_ERROR(("%s (nextlen): read %d"
4149 " bytes failed: %d\n",
4150 __func__, rdlen, sdret));
4151 brcmu_pkt_buf_free_skb(pkt);
4152 bus->drvr->rx_errors++;
4153 /* Force retry w/normal header read.
4154 * Don't attempt NAK for
4155 * gSPI
4156 */
4157 brcmf_sdbrcm_rxfail(bus, true,
4158 (bus->bus ==
4159 SPI_BUS) ? false :
4160 true);
4161 continue;
4162 }
4163 }
4164
4165 /* Now check the header */
4166 memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN);
4167
4168 /* Extract hardware header fields */
4169 len = get_unaligned_le16(bus->rxhdr);
4170 check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
4171
4172 /* All zeros means readahead info was bad */
4173 if (!(len | check)) {
4174 BRCMF_INFO(("%s (nextlen): read zeros in HW "
4175 "header???\n", __func__));
4176 brcmf_sdbrcm_pktfree2(bus, pkt);
4177 continue;
4178 }
4179
4180 /* Validate check bytes */
4181 if ((u16)~(len ^ check)) {
4182 BRCMF_ERROR(("%s (nextlen): HW hdr error:"
4183 " nextlen/len/check"
4184 " 0x%04x/0x%04x/0x%04x\n",
4185 __func__, nextlen, len, check));
4186 bus->rx_badhdr++;
4187 brcmf_sdbrcm_rxfail(bus, false, false);
4188 brcmf_sdbrcm_pktfree2(bus, pkt);
4189 continue;
4190 }
4191
4192 /* Validate frame length */
4193 if (len < SDPCM_HDRLEN) {
4194 BRCMF_ERROR(("%s (nextlen): HW hdr length "
4195 "invalid: %d\n", __func__, len));
4196 brcmf_sdbrcm_pktfree2(bus, pkt);
4197 continue;
4198 }
4199
4200 /* Check for consistency withreadahead info */
4201 len_consistent = (nextlen != (roundup(len, 16) >> 4));
4202 if (len_consistent) {
4203 /* Mismatch, force retry w/normal
4204 header (may be >4K) */
4205 BRCMF_ERROR(("%s (nextlen): mismatch, "
4206 "nextlen %d len %d rnd %d; "
4207 "expected rxseq %d\n",
4208 __func__, nextlen,
4209 len, roundup(len, 16), rxseq));
4210 brcmf_sdbrcm_rxfail(bus, true,
4211 bus->bus != SPI_BUS);
4212 brcmf_sdbrcm_pktfree2(bus, pkt);
4213 continue;
4214 }
4215
4216 /* Extract software header fields */
4217 chan = SDPCM_PACKET_CHANNEL(
4218 &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4219 seq = SDPCM_PACKET_SEQUENCE(
4220 &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4221 doff = SDPCM_DOFFSET_VALUE(
4222 &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4223 txmax = SDPCM_WINDOW_VALUE(
4224 &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4225
4226 bus->nextlen =
4227 bus->rxhdr[SDPCM_FRAMETAG_LEN +
4228 SDPCM_NEXTLEN_OFFSET];
4229 if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
4230 BRCMF_INFO(("%s (nextlen): got frame w/nextlen"
4231 " too large (%d), seq %d\n",
4232 __func__, bus->nextlen, seq));
4233 bus->nextlen = 0;
4234 }
4235
4236 bus->drvr->rx_readahead_cnt++;
4237
4238 /* Handle Flow Control */
4239 fcbits = SDPCM_FCMASK_VALUE(
4240 &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4241
4242 if (bus->flowcontrol != fcbits) {
4243 if (~bus->flowcontrol & fcbits)
4244 bus->fc_xoff++;
4245
4246 if (bus->flowcontrol & ~fcbits)
4247 bus->fc_xon++;
4248
4249 bus->fc_rcvd++;
4250 bus->flowcontrol = fcbits;
4251 }
4252
4253 /* Check and update sequence number */
4254 if (rxseq != seq) {
4255 BRCMF_INFO(("%s (nextlen): rx_seq %d, expected "
4256 "%d\n", __func__, seq, rxseq));
4257 bus->rx_badseq++;
4258 rxseq = seq;
4259 }
4260
4261 /* Check window for sanity */
4262 if ((u8) (txmax - bus->tx_seq) > 0x40) {
4263 BRCMF_ERROR(("%s: got unlikely tx max %d with "
4264 "tx_seq %d\n",
4265 __func__, txmax, bus->tx_seq));
4266 txmax = bus->tx_seq + 2;
4267 }
4268 bus->tx_max = txmax;
4269
4270#ifdef BCMDBG
4271 if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
4272 printk(KERN_DEBUG "Rx Data:\n");
4273 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
4274 rxbuf, len);
4275 } else if (BRCMF_HDRS_ON()) {
4276 printk(KERN_DEBUG "RxHdr:\n");
4277 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
4278 bus->rxhdr, SDPCM_HDRLEN);
4279 }
4280#endif
4281
4282 if (chan == SDPCM_CONTROL_CHANNEL) {
4283 if (bus->bus == SPI_BUS) {
4284 brcmf_sdbrcm_read_control(bus, rxbuf,
4285 len, doff);
4286 } else {
4287 BRCMF_ERROR(("%s (nextlen): readahead"
4288 " on control packet %d?\n",
4289 __func__, seq));
4290 /* Force retry w/normal header read */
4291 bus->nextlen = 0;
4292 brcmf_sdbrcm_rxfail(bus, false, true);
4293 }
4294 brcmf_sdbrcm_pktfree2(bus, pkt);
4295 continue;
4296 }
4297
4298 if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
4299 BRCMF_ERROR(("Received %d bytes on %d channel."
4300 " Running out of " "rx pktbuf's or"
4301 " not yet malloced.\n",
4302 len, chan));
4303 continue;
4304 }
4305
4306 /* Validate data offset */
4307 if ((doff < SDPCM_HDRLEN) || (doff > len)) {
4308 BRCMF_ERROR(("%s (nextlen): bad data offset %d:"
4309 " HW len %d min %d\n", __func__,
4310 doff, len, SDPCM_HDRLEN));
4311 brcmf_sdbrcm_rxfail(bus, false, false);
4312 brcmf_sdbrcm_pktfree2(bus, pkt);
4313 continue;
4314 }
4315
4316 /* All done with this one -- now deliver the packet */
4317 goto deliver;
4318 }
4319 /* gSPI frames should not be handled in fractions */
4320 if (bus->bus == SPI_BUS)
4321 break;
4322
4323 /* Read frame header (hardware and software) */
4324 sdret = brcmf_sdcard_recv_buf(card,
4325 brcmf_sdcard_cur_sbwad(card),
4326 SDIO_FUNC_2, F2SYNC, bus->rxhdr, firstread,
4327 NULL, NULL, NULL);
4328 bus->f2rxhdrs++;
4329
4330 if (sdret < 0) {
4331 BRCMF_ERROR(("%s: RXHEADER FAILED: %d\n", __func__,
4332 sdret));
4333 bus->rx_hdrfail++;
4334 brcmf_sdbrcm_rxfail(bus, true, true);
4335 continue;
4336 }
4337#ifdef BCMDBG
4338 if (BRCMF_BYTES_ON() || BRCMF_HDRS_ON()) {
4339 printk(KERN_DEBUG "RxHdr:\n");
4340 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
4341 bus->rxhdr, SDPCM_HDRLEN);
4342 }
4343#endif
4344
4345 /* Extract hardware header fields */
4346 len = get_unaligned_le16(bus->rxhdr);
4347 check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
4348
4349 /* All zeros means no more frames */
4350 if (!(len | check)) {
4351 *finished = true;
4352 break;
4353 }
4354
4355 /* Validate check bytes */
4356 if ((u16) ~(len ^ check)) {
4357 BRCMF_ERROR(("%s: HW hdr err: len/check "
4358 "0x%04x/0x%04x\n", __func__, len, check));
4359 bus->rx_badhdr++;
4360 brcmf_sdbrcm_rxfail(bus, false, false);
4361 continue;
4362 }
4363
4364 /* Validate frame length */
4365 if (len < SDPCM_HDRLEN) {
4366 BRCMF_ERROR(("%s: HW hdr length invalid: %d\n",
4367 __func__, len));
4368 continue;
4369 }
4370
4371 /* Extract software header fields */
4372 chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4373 seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4374 doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4375 txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4376
4377 /* Validate data offset */
4378 if ((doff < SDPCM_HDRLEN) || (doff > len)) {
4379 BRCMF_ERROR(("%s: Bad data offset %d: HW len %d,"
4380 " min %d seq %d\n", __func__, doff,
4381 len, SDPCM_HDRLEN, seq));
4382 bus->rx_badhdr++;
4383 brcmf_sdbrcm_rxfail(bus, false, false);
4384 continue;
4385 }
4386
4387 /* Save the readahead length if there is one */
4388 bus->nextlen =
4389 bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
4390 if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
4391 BRCMF_INFO(("%s (nextlen): got frame w/nextlen too"
4392 " large (%d), seq %d\n",
4393 __func__, bus->nextlen, seq));
4394 bus->nextlen = 0;
4395 }
4396
4397 /* Handle Flow Control */
4398 fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4399
4400 if (bus->flowcontrol != fcbits) {
4401 if (~bus->flowcontrol & fcbits)
4402 bus->fc_xoff++;
4403
4404 if (bus->flowcontrol & ~fcbits)
4405 bus->fc_xon++;
4406
4407 bus->fc_rcvd++;
4408 bus->flowcontrol = fcbits;
4409 }
4410
4411 /* Check and update sequence number */
4412 if (rxseq != seq) {
4413 BRCMF_INFO(("%s: rx_seq %d, expected %d\n", __func__,
4414 seq, rxseq));
4415 bus->rx_badseq++;
4416 rxseq = seq;
4417 }
4418
4419 /* Check window for sanity */
4420 if ((u8) (txmax - bus->tx_seq) > 0x40) {
4421 BRCMF_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
4422 __func__, txmax, bus->tx_seq));
4423 txmax = bus->tx_seq + 2;
4424 }
4425 bus->tx_max = txmax;
4426
4427 /* Call a separate function for control frames */
4428 if (chan == SDPCM_CONTROL_CHANNEL) {
4429 brcmf_sdbrcm_read_control(bus, bus->rxhdr, len, doff);
4430 continue;
4431 }
4432
4433 /* precondition: chan is either SDPCM_DATA_CHANNEL,
4434 SDPCM_EVENT_CHANNEL, SDPCM_TEST_CHANNEL or
4435 SDPCM_GLOM_CHANNEL */
4436
4437 /* Length to read */
4438 rdlen = (len > firstread) ? (len - firstread) : 0;
4439
4440 /* May pad read to blocksize for efficiency */
4441 if (bus->roundup && bus->blocksize &&
4442 (rdlen > bus->blocksize)) {
4443 pad = bus->blocksize - (rdlen % bus->blocksize);
4444 if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
4445 ((rdlen + pad + firstread) < MAX_RX_DATASZ))
4446 rdlen += pad;
4447 } else if (rdlen % BRCMF_SDALIGN) {
4448 rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
4449 }
4450
4451 /* Satisfy length-alignment requirements */
4452 if (forcealign && (rdlen & (ALIGNMENT - 1)))
4453 rdlen = roundup(rdlen, ALIGNMENT);
4454
4455 if ((rdlen + firstread) > MAX_RX_DATASZ) {
4456 /* Too long -- skip this frame */
4457 BRCMF_ERROR(("%s: too long: len %d rdlen %d\n",
4458 __func__, len, rdlen));
4459 bus->drvr->rx_errors++;
4460 bus->rx_toolong++;
4461 brcmf_sdbrcm_rxfail(bus, false, false);
4462 continue;
4463 }
4464
4465 pkt = brcmu_pkt_buf_get_skb(rdlen + firstread + BRCMF_SDALIGN);
4466 if (!pkt) {
4467 /* Give up on data, request rtx of events */
4468 BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed:"
4469 " rdlen %d chan %d\n", __func__, rdlen,
4470 chan));
4471 bus->drvr->rx_dropped++;
4472 brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan));
4473 continue;
4474 }
4475
4476 /* Leave room for what we already read, and align remainder */
4477 skb_pull(pkt, firstread);
4478 PKTALIGN(pkt, rdlen, BRCMF_SDALIGN);
4479
4480 /* Read the remaining frame data */
4481 sdret = brcmf_sdcard_recv_buf(card,
4482 brcmf_sdcard_cur_sbwad(card),
4483 SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)),
4484 rdlen, pkt, NULL, NULL);
4485 bus->f2rxdata++;
4486
4487 if (sdret < 0) {
4488 BRCMF_ERROR(("%s: read %d %s bytes failed: %d\n",
4489 __func__, rdlen,
4490 ((chan == SDPCM_EVENT_CHANNEL) ? "event"
4491 : ((chan == SDPCM_DATA_CHANNEL) ? "data"
4492 : "test")), sdret));
4493 brcmu_pkt_buf_free_skb(pkt);
4494 bus->drvr->rx_errors++;
4495 brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan));
4496 continue;
4497 }
4498
4499 /* Copy the already-read portion */
4500 skb_push(pkt, firstread);
4501 memcpy(pkt->data, bus->rxhdr, firstread);
4502
4503#ifdef BCMDBG
4504 if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
4505 printk(KERN_DEBUG "Rx Data:\n");
4506 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
4507 pkt->data, len);
4508 }
4509#endif
4510
4511deliver:
4512 /* Save superframe descriptor and allocate packet frame */
4513 if (chan == SDPCM_GLOM_CHANNEL) {
4514 if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
4515 BRCMF_GLOM(("%s: glom descriptor, %d bytes:\n",
4516 __func__, len));
4517#ifdef BCMDBG
4518 if (BRCMF_GLOM_ON()) {
4519 printk(KERN_DEBUG "Glom Data:\n");
4520 print_hex_dump_bytes("",
4521 DUMP_PREFIX_OFFSET,
4522 pkt->data, len);
4523 }
4524#endif
4525 __skb_trim(pkt, len);
4526 skb_pull(pkt, SDPCM_HDRLEN);
4527 bus->glomd = pkt;
4528 } else {
4529 BRCMF_ERROR(("%s: glom superframe w/o "
4530 "descriptor!\n", __func__));
4531 brcmf_sdbrcm_rxfail(bus, false, false);
4532 }
4533 continue;
4534 }
4535
4536 /* Fill in packet len and prio, deliver upward */
4537 __skb_trim(pkt, len);
4538 skb_pull(pkt, doff);
4539
4540#ifdef SDTEST
4541 /* Test channel packets are processed separately */
4542 if (chan == SDPCM_TEST_CHANNEL) {
4543 brcmf_sdbrcm_checkdied(bus, pkt, seq);
4544 continue;
4545 }
4546#endif /* SDTEST */
4547
4548 if (pkt->len == 0) {
4549 brcmu_pkt_buf_free_skb(pkt);
4550 continue;
4551 } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, pkt) != 0) {
4552 BRCMF_ERROR(("%s: rx protocol error\n", __func__));
4553 brcmu_pkt_buf_free_skb(pkt);
4554 bus->drvr->rx_errors++;
4555 continue;
4556 }
4557
4558 /* Unlock during rx call */
4559 brcmf_sdbrcm_sdunlock(bus);
4560 brcmf_rx_frame(bus->drvr, ifidx, pkt, 1);
4561 brcmf_sdbrcm_sdlock(bus);
4562 }
4563 rxcount = maxframes - rxleft;
4564#ifdef BCMDBG
4565 /* Message if we hit the limit */
4566 if (!rxleft && !sdtest)
4567 BRCMF_DATA(("%s: hit rx limit of %d frames\n", __func__,
4568 maxframes));
4569 else
4570#endif /* BCMDBG */
4571 BRCMF_DATA(("%s: processed %d frames\n", __func__, rxcount));
4572 /* Back off rxseq if awaiting rtx, update rx_seq */
4573 if (bus->rxskip)
4574 rxseq--;
4575 bus->rx_seq = rxseq;
4576
4577 return rxcount;
4578}
4579
4580static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus)
4581{
4582 u32 intstatus = 0;
4583 u32 hmb_data;
4584 u8 fcbits;
4585 uint retries = 0;
4586
4587 BRCMF_TRACE(("%s: Enter\n", __func__));
4588
4589 /* Read mailbox data and ack that we did so */
4590 r_sdreg32(bus, &hmb_data,
4591 offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries);
4592
4593 if (retries <= retry_limit)
4594 w_sdreg32(bus, SMB_INT_ACK,
4595 offsetof(struct sdpcmd_regs, tosbmailbox), &retries);
4596 bus->f1regdata += 2;
4597
4598 /* Dongle recomposed rx frames, accept them again */
4599 if (hmb_data & HMB_DATA_NAKHANDLED) {
4600 BRCMF_INFO(("Dongle reports NAK handled, expect rtx of %d\n",
4601 bus->rx_seq));
4602 if (!bus->rxskip)
4603 BRCMF_ERROR(("%s: unexpected NAKHANDLED!\n", __func__));
4604
4605 bus->rxskip = false;
4606 intstatus |= I_HMB_FRAME_IND;
4607 }
4608
4609 /*
4610 * DEVREADY does not occur with gSPI.
4611 */
4612 if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
4613 bus->sdpcm_ver =
4614 (hmb_data & HMB_DATA_VERSION_MASK) >>
4615 HMB_DATA_VERSION_SHIFT;
4616 if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
4617 BRCMF_ERROR(("Version mismatch, dongle reports %d, "
4618 "expecting %d\n",
4619 bus->sdpcm_ver, SDPCM_PROT_VERSION));
4620 else
4621 BRCMF_INFO(("Dongle ready, protocol version %d\n",
4622 bus->sdpcm_ver));
4623 }
4624
4625 /*
4626 * Flow Control has been moved into the RX headers and this out of band
4627 * method isn't used any more.
4628 * remaining backward compatible with older dongles.
4629 */
4630 if (hmb_data & HMB_DATA_FC) {
4631 fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >>
4632 HMB_DATA_FCDATA_SHIFT;
4633
4634 if (fcbits & ~bus->flowcontrol)
4635 bus->fc_xoff++;
4636
4637 if (bus->flowcontrol & ~fcbits)
4638 bus->fc_xon++;
4639
4640 bus->fc_rcvd++;
4641 bus->flowcontrol = fcbits;
4642 }
4643
4644 /* Shouldn't be any others */
4645 if (hmb_data & ~(HMB_DATA_DEVREADY |
4646 HMB_DATA_NAKHANDLED |
4647 HMB_DATA_FC |
4648 HMB_DATA_FWREADY |
4649 HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) {
4650 BRCMF_ERROR(("Unknown mailbox data content: 0x%02x\n",
4651 hmb_data));
4652 }
4653
4654 return intstatus;
4655}
4656
4657static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus)
4658{
4659 struct brcmf_sdio_card *card = bus->card;
4660 u32 intstatus, newstatus = 0;
4661 uint retries = 0;
4662 uint rxlimit = brcmf_rxbound; /* Rx frames to read before resched */
4663 uint txlimit = brcmf_txbound; /* Tx frames to send before resched */
4664 uint framecnt = 0; /* Temporary counter of tx/rx frames */
4665 bool rxdone = true; /* Flag for no more read data */
4666 bool resched = false; /* Flag indicating resched wanted */
4667
4668 BRCMF_TRACE(("%s: Enter\n", __func__));
4669
4670 /* Start with leftover status bits */
4671 intstatus = bus->intstatus;
4672
4673 brcmf_sdbrcm_sdlock(bus);
4674
4675 /* If waiting for HTAVAIL, check status */
4676 if (bus->clkstate == CLK_PENDING) {
4677 int err;
4678 u8 clkctl, devctl = 0;
4679
4680#ifdef BCMDBG
4681 /* Check for inconsistent device control */
4682 devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
4683 SBSDIO_DEVICE_CTL, &err);
4684 if (err) {
4685 BRCMF_ERROR(("%s: error reading DEVCTL: %d\n",
4686 __func__, err));
4687 bus->drvr->busstate = BRCMF_BUS_DOWN;
4688 }
4689#endif /* BCMDBG */
4690
4691 /* Read CSR, if clock on switch to AVAIL, else ignore */
4692 clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
4693 SBSDIO_FUNC1_CHIPCLKCSR, &err);
4694 if (err) {
4695 BRCMF_ERROR(("%s: error reading CSR: %d\n", __func__,
4696 err));
4697 bus->drvr->busstate = BRCMF_BUS_DOWN;
4698 }
4699
4700 BRCMF_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
4701 devctl, clkctl));
4702
4703 if (SBSDIO_HTAV(clkctl)) {
4704 devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
4705 SBSDIO_DEVICE_CTL, &err);
4706 if (err) {
4707 BRCMF_ERROR(("%s: error reading DEVCTL: %d\n",
4708 __func__, err));
4709 bus->drvr->busstate = BRCMF_BUS_DOWN;
4710 }
4711 devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
4712 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
4713 SBSDIO_DEVICE_CTL, devctl, &err);
4714 if (err) {
4715 BRCMF_ERROR(("%s: error writing DEVCTL: %d\n",
4716 __func__, err));
4717 bus->drvr->busstate = BRCMF_BUS_DOWN;
4718 }
4719 bus->clkstate = CLK_AVAIL;
4720 } else {
4721 goto clkwait;
4722 }
4723 }
4724
4725 BUS_WAKE(bus);
4726
4727 /* Make sure backplane clock is on */
4728 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
4729 if (bus->clkstate == CLK_PENDING)
4730 goto clkwait;
4731
4732 /* Pending interrupt indicates new device status */
4733 if (bus->ipend) {
4734 bus->ipend = false;
4735 r_sdreg32(bus, &newstatus,
4736 offsetof(struct sdpcmd_regs, intstatus), &retries);
4737 bus->f1regdata++;
4738 if (brcmf_sdcard_regfail(bus->card))
4739 newstatus = 0;
4740 newstatus &= bus->hostintmask;
4741 bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
4742 if (newstatus) {
4743 w_sdreg32(bus, newstatus,
4744 offsetof(struct sdpcmd_regs, intstatus),
4745 &retries);
4746 bus->f1regdata++;
4747 }
4748 }
4749
4750 /* Merge new bits with previous */
4751 intstatus |= newstatus;
4752 bus->intstatus = 0;
4753
4754 /* Handle flow-control change: read new state in case our ack
4755 * crossed another change interrupt. If change still set, assume
4756 * FC ON for safety, let next loop through do the debounce.
4757 */
4758 if (intstatus & I_HMB_FC_CHANGE) {
4759 intstatus &= ~I_HMB_FC_CHANGE;
4760 w_sdreg32(bus, I_HMB_FC_CHANGE,
4761 offsetof(struct sdpcmd_regs, intstatus), &retries);
4762
4763 r_sdreg32(bus, &newstatus,
4764 offsetof(struct sdpcmd_regs, intstatus), &retries);
4765 bus->f1regdata += 2;
4766 bus->fcstate =
4767 !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
4768 intstatus |= (newstatus & bus->hostintmask);
4769 }
4770
4771 /* Handle host mailbox indication */
4772 if (intstatus & I_HMB_HOST_INT) {
4773 intstatus &= ~I_HMB_HOST_INT;
4774 intstatus |= brcmf_sdbrcm_hostmail(bus);
4775 }
4776
4777 /* Generally don't ask for these, can get CRC errors... */
4778 if (intstatus & I_WR_OOSYNC) {
4779 BRCMF_ERROR(("Dongle reports WR_OOSYNC\n"));
4780 intstatus &= ~I_WR_OOSYNC;
4781 }
4782
4783 if (intstatus & I_RD_OOSYNC) {
4784 BRCMF_ERROR(("Dongle reports RD_OOSYNC\n"));
4785 intstatus &= ~I_RD_OOSYNC;
4786 }
4787
4788 if (intstatus & I_SBINT) {
4789 BRCMF_ERROR(("Dongle reports SBINT\n"));
4790 intstatus &= ~I_SBINT;
4791 }
4792
4793 /* Would be active due to wake-wlan in gSPI */
4794 if (intstatus & I_CHIPACTIVE) {
4795 BRCMF_INFO(("Dongle reports CHIPACTIVE\n"));
4796 intstatus &= ~I_CHIPACTIVE;
4797 }
4798
4799 /* Ignore frame indications if rxskip is set */
4800 if (bus->rxskip)
4801 intstatus &= ~I_HMB_FRAME_IND;
4802
4803 /* On frame indication, read available frames */
4804 if (PKT_AVAILABLE()) {
4805 framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone);
4806 if (rxdone || bus->rxskip)
4807 intstatus &= ~I_HMB_FRAME_IND;
4808 rxlimit -= min(framecnt, rxlimit);
4809 }
4810
4811 /* Keep still-pending events for next scheduling */
4812 bus->intstatus = intstatus;
4813
4814clkwait:
4815 /* Re-enable interrupts to detect new device events (mailbox, rx frame)
4816 * or clock availability. (Allows tx loop to check ipend if desired.)
4817 * (Unless register access seems hosed, as we may not be able to ACK...)
4818 */
4819 if (bus->intr && bus->intdis && !brcmf_sdcard_regfail(card)) {
4820 BRCMF_INTR(("%s: enable SDIO interrupts, rxdone %d"
4821 " framecnt %d\n", __func__, rxdone, framecnt));
4822 bus->intdis = false;
4823 brcmf_sdcard_intr_enable(card);
4824 }
4825
4826 if (DATAOK(bus) && bus->ctrl_frame_stat &&
4827 (bus->clkstate == CLK_AVAIL)) {
4828 int ret, i;
4829
4830 ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card),
4831 SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf,
4832 (u32) bus->ctrl_frame_len, NULL, NULL, NULL);
4833
4834 if (ret < 0) {
4835 /* On failure, abort the command and
4836 terminate the frame */
4837 BRCMF_INFO(("%s: sdio error %d, abort command and "
4838 "terminate frame.\n", __func__, ret));
4839 bus->tx_sderrs++;
4840
4841 brcmf_sdcard_abort(card, SDIO_FUNC_2);
4842
4843 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
4844 SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
4845 NULL);
4846 bus->f1regdata++;
4847
4848 for (i = 0; i < 3; i++) {
4849 u8 hi, lo;
4850 hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
4851 SBSDIO_FUNC1_WFRAMEBCHI,
4852 NULL);
4853 lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
4854 SBSDIO_FUNC1_WFRAMEBCLO,
4855 NULL);
4856 bus->f1regdata += 2;
4857 if ((hi == 0) && (lo == 0))
4858 break;
4859 }
4860
4861 }
4862 if (ret == 0)
4863 bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
4864
4865 BRCMF_INFO(("Return_dpc value is : %d\n", ret));
4866 bus->ctrl_frame_stat = false;
4867 brcmf_sdbrcm_wait_event_wakeup(bus);
4868 }
4869 /* Send queued frames (limit 1 if rx may still be pending) */
4870 else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
4871 brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
4872 && DATAOK(bus)) {
4873 framecnt = rxdone ? txlimit : min(txlimit, brcmf_txminmax);
4874 framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt);
4875 txlimit -= framecnt;
4876 }
4877
4878 /* Resched if events or tx frames are pending,
4879 else await next interrupt */
4880 /* On failed register access, all bets are off:
4881 no resched or interrupts */
4882 if ((bus->drvr->busstate == BRCMF_BUS_DOWN) ||
4883 brcmf_sdcard_regfail(card)) {
4884 BRCMF_ERROR(("%s: failed backplane access over SDIO, halting "
4885 "operation %d\n", __func__,
4886 brcmf_sdcard_regfail(card)));
4887 bus->drvr->busstate = BRCMF_BUS_DOWN;
4888 bus->intstatus = 0;
4889 } else if (bus->clkstate == CLK_PENDING) {
4890 BRCMF_INFO(("%s: rescheduled due to CLK_PENDING awaiting "
4891 "I_CHIPACTIVE interrupt\n", __func__));
4892 resched = true;
4893 } else if (bus->intstatus || bus->ipend ||
4894 (!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)
4895 && DATAOK(bus)) || PKT_AVAILABLE()) {
4896 resched = true;
4897 }
4898
4899 bus->dpc_sched = resched;
4900
4901 /* If we're done for now, turn off clock request. */
4902 if ((bus->clkstate != CLK_PENDING)
4903 && bus->idletime == BRCMF_IDLE_IMMEDIATE) {
4904 bus->activity = false;
4905 brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
4906 }
4907
4908 brcmf_sdbrcm_sdunlock(bus);
4909
4910 return resched;
4911}
4912
4913void brcmf_sdbrcm_isr(void *arg)
4914{
4915 struct brcmf_bus *bus = (struct brcmf_bus *) arg;
4916 struct brcmf_sdio_card *card;
4917
4918 BRCMF_TRACE(("%s: Enter\n", __func__));
4919
4920 if (!bus) {
4921 BRCMF_ERROR(("%s : bus is null pointer , exit\n", __func__));
4922 return;
4923 }
4924 card = bus->card;
4925
4926 if (bus->drvr->busstate == BRCMF_BUS_DOWN) {
4927 BRCMF_ERROR(("%s : bus is down. we have nothing to do\n",
4928 __func__));
4929 return;
4930 }
4931 /* Count the interrupt call */
4932 bus->intrcount++;
4933 bus->ipend = true;
4934
4935 /* Shouldn't get this interrupt if we're sleeping? */
4936 if (bus->sleeping) {
4937 BRCMF_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
4938 return;
4939 }
4940
4941 /* Disable additional interrupts (is this needed now)? */
4942 if (bus->intr)
4943 BRCMF_INTR(("%s: disable SDIO interrupts\n", __func__));
4944 else
4945 BRCMF_ERROR(("brcmf_sdbrcm_isr() w/o interrupt configured!\n"));
4946
4947 brcmf_sdcard_intr_disable(card);
4948 bus->intdis = true;
4949
4950#if defined(SDIO_ISR_THREAD)
4951 BRCMF_TRACE(("Calling brcmf_sdbrcm_dpc() from %s\n", __func__));
4952 while (brcmf_sdbrcm_dpc(bus))
4953 ;
4954#else
4955 bus->dpc_sched = true;
4956 brcmf_sdbrcm_sched_dpc(bus);
4957#endif
4958
4959}
4960
4961#ifdef SDTEST
4962static void brcmf_sdbrcm_pktgen_init(struct brcmf_bus *bus)
4963{
4964 /* Default to specified length, or full range */
4965 if (brcmf_pktgen_len) {
4966 bus->pktgen_maxlen = min(brcmf_pktgen_len,
4967 BRCMF_MAX_PKTGEN_LEN);
4968 bus->pktgen_minlen = bus->pktgen_maxlen;
4969 } else {
4970 bus->pktgen_maxlen = BRCMF_MAX_PKTGEN_LEN;
4971 bus->pktgen_minlen = 0;
4972 }
4973 bus->pktgen_len = (u16) bus->pktgen_minlen;
4974
4975 /* Default to per-watchdog burst with 10s print time */
4976 bus->pktgen_freq = 1;
4977 bus->pktgen_print = 10000 / brcmf_watchdog_ms;
4978 bus->pktgen_count = (brcmf_pktgen * brcmf_watchdog_ms + 999) / 1000;
4979
4980 /* Default to echo mode */
4981 bus->pktgen_mode = BRCMF_PKTGEN_ECHO;
4982 bus->pktgen_stop = 1;
4983}
4984
4985static void brcmf_sdbrcm_pktgen(struct brcmf_bus *bus)
4986{
4987 struct sk_buff *pkt;
4988 u8 *data;
4989 uint pktcount;
4990 uint fillbyte;
4991 u16 len;
4992
4993 /* Display current count if appropriate */
4994 if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
4995 bus->pktgen_ptick = 0;
4996 printk(KERN_DEBUG "%s: send attempts %d rcvd %d\n",
4997 __func__, bus->pktgen_sent, bus->pktgen_rcvd);
4998 }
4999
5000 /* For recv mode, just make sure dongle has started sending */
5001 if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) {
5002 if (!bus->pktgen_rcvd)
5003 brcmf_sdbrcm_sdtest_set(bus, true);
5004 return;
5005 }
5006
5007 /* Otherwise, generate or request the specified number of packets */
5008 for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
5009 /* Stop if total has been reached */
5010 if (bus->pktgen_total
5011 && (bus->pktgen_sent >= bus->pktgen_total)) {
5012 bus->pktgen_count = 0;
5013 break;
5014 }
5015
5016 /* Allocate an appropriate-sized packet */
5017 len = bus->pktgen_len;
5018 pkt = brcmu_pkt_buf_get_skb(
5019 len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN,
5020 true);
5021 if (!pkt) {
5022 BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n",
5023 __func__));
5024 break;
5025 }
5026 PKTALIGN(pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN),
5027 BRCMF_SDALIGN);
5028 data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
5029
5030 /* Write test header cmd and extra based on mode */
5031 switch (bus->pktgen_mode) {
5032 case BRCMF_PKTGEN_ECHO:
5033 *data++ = SDPCM_TEST_ECHOREQ;
5034 *data++ = (u8) bus->pktgen_sent;
5035 break;
5036
5037 case BRCMF_PKTGEN_SEND:
5038 *data++ = SDPCM_TEST_DISCARD;
5039 *data++ = (u8) bus->pktgen_sent;
5040 break;
5041
5042 case BRCMF_PKTGEN_RXBURST:
5043 *data++ = SDPCM_TEST_BURST;
5044 *data++ = (u8) bus->pktgen_count;
5045 break;
5046
5047 default:
5048 BRCMF_ERROR(("Unrecognized pktgen mode %d\n",
5049 bus->pktgen_mode));
5050 brcmu_pkt_buf_free_skb(pkt, true);
5051 bus->pktgen_count = 0;
5052 return;
5053 }
5054
5055 /* Write test header length field */
5056 *data++ = (len >> 0);
5057 *data++ = (len >> 8);
5058
5059 /* Then fill in the remainder -- N/A for burst,
5060 but who cares... */
5061 for (fillbyte = 0; fillbyte < len; fillbyte++)
5062 *data++ =
5063 SDPCM_TEST_FILL(fillbyte, (u8) bus->pktgen_sent);
5064
5065#ifdef BCMDBG
5066 if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
5067 data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
5068 printk(KERN_DEBUG "brcmf_sdbrcm_pktgen: Tx Data:\n");
5069 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data,
5070 pkt->len - SDPCM_HDRLEN);
5071 }
5072#endif
5073
5074 /* Send it */
5075 if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true)) {
5076 bus->pktgen_fail++;
5077 if (bus->pktgen_stop
5078 && bus->pktgen_stop == bus->pktgen_fail)
5079 bus->pktgen_count = 0;
5080 }
5081 bus->pktgen_sent++;
5082
5083 /* Bump length if not fixed, wrap at max */
5084 if (++bus->pktgen_len > bus->pktgen_maxlen)
5085 bus->pktgen_len = (u16) bus->pktgen_minlen;
5086
5087 /* Special case for burst mode: just send one request! */
5088 if (bus->pktgen_mode == BRCMF_PKTGEN_RXBURST)
5089 break;
5090 }
5091}
5092
5093static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start)
5094{
5095 struct sk_buff *pkt;
5096 u8 *data;
5097
5098 /* Allocate the packet */
5099 pkt = brcmu_pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
5100 BRCMF_SDALIGN, true);
5101 if (!pkt) {
5102 BRCMF_ERROR(("%s: brcmu_pkt_buf_get_skb failed!\n", __func__));
5103 return;
5104 }
5105 PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), BRCMF_SDALIGN);
5106 data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
5107
5108 /* Fill in the test header */
5109 *data++ = SDPCM_TEST_SEND;
5110 *data++ = start;
5111 *data++ = (bus->pktgen_maxlen >> 0);
5112 *data++ = (bus->pktgen_maxlen >> 8);
5113
5114 /* Send it */
5115 if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true))
5116 bus->pktgen_fail++;
5117}
5118
5119static void
5120brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, struct sk_buff *pkt, uint seq)
5121{
5122 u8 *data;
5123 uint pktlen;
5124
5125 u8 cmd;
5126 u8 extra;
5127 u16 len;
5128 u16 offset;
5129
5130 /* Check for min length */
5131 pktlen = pkt->len;
5132 if (pktlen < SDPCM_TEST_HDRLEN) {
5133 BRCMF_ERROR(("brcmf_sdbrcm_checkdied: toss runt frame, pktlen "
5134 "%d\n", pktlen));
5135 brcmu_pkt_buf_free_skb(pkt, false);
5136 return;
5137 }
5138
5139 /* Extract header fields */
5140 data = pkt->data;
5141 cmd = *data++;
5142 extra = *data++;
5143 len = *data++;
5144 len += *data++ << 8;
5145
5146 /* Check length for relevant commands */
5147 if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ
5148 || cmd == SDPCM_TEST_ECHORSP) {
5149 if (pktlen != len + SDPCM_TEST_HDRLEN) {
5150 BRCMF_ERROR(("brcmf_sdbrcm_checkdied: frame length "
5151 "mismatch, pktlen %d seq %d"
5152 " cmd %d extra %d len %d\n",
5153 pktlen, seq, cmd, extra, len));
5154 brcmu_pkt_buf_free_skb(pkt, false);
5155 return;
5156 }
5157 }
5158
5159 /* Process as per command */
5160 switch (cmd) {
5161 case SDPCM_TEST_ECHOREQ:
5162 /* Rx->Tx turnaround ok (even on NDIS w/current
5163 implementation) */
5164 *(u8 *) (pkt->data) = SDPCM_TEST_ECHORSP;
5165 if (brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true) == 0)
5166 bus->pktgen_sent++;
5167 else {
5168 bus->pktgen_fail++;
5169 brcmu_pkt_buf_free_skb(pkt, false);
5170 }
5171 bus->pktgen_rcvd++;
5172 break;
5173
5174 case SDPCM_TEST_ECHORSP:
5175 if (bus->ext_loop) {
5176 brcmu_pkt_buf_free_skb(pkt, false);
5177 bus->pktgen_rcvd++;
5178 break;
5179 }
5180
5181 for (offset = 0; offset < len; offset++, data++) {
5182 if (*data != SDPCM_TEST_FILL(offset, extra)) {
5183 BRCMF_ERROR(("brcmf_sdbrcm_checkdied: echo"
5184 " data mismatch: "
5185 "offset %d (len %d) "
5186 "expect 0x%02x rcvd 0x%02x\n",
5187 offset, len,
5188 SDPCM_TEST_FILL(offset, extra),
5189 *data));
5190 break;
5191 }
5192 }
5193 brcmu_pkt_buf_free_skb(pkt, false);
5194 bus->pktgen_rcvd++;
5195 break;
5196
5197 case SDPCM_TEST_DISCARD:
5198 brcmu_pkt_buf_free_skb(pkt, false);
5199 bus->pktgen_rcvd++;
5200 break;
5201
5202 case SDPCM_TEST_BURST:
5203 case SDPCM_TEST_SEND:
5204 default:
5205 BRCMF_INFO(("brcmf_sdbrcm_checkdied: unsupported or unknown "
5206 "command, pktlen %d seq %d" " cmd %d extra %d"
5207 " len %d\n", pktlen, seq, cmd, extra, len));
5208 brcmu_pkt_buf_free_skb(pkt, false);
5209 break;
5210 }
5211
5212 /* For recv mode, stop at limie (and tell dongle to stop sending) */
5213 if (bus->pktgen_mode == BRCMF_PKTGEN_RECV) {
5214 if (bus->pktgen_total
5215 && (bus->pktgen_rcvd >= bus->pktgen_total)) {
5216 bus->pktgen_count = 0;
5217 brcmf_sdbrcm_sdtest_set(bus, false);
5218 }
5219 }
5220}
5221#endif /* SDTEST */
5222
5223extern bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr)
5224{
5225 struct brcmf_bus *bus;
5226
5227 BRCMF_TIMER(("%s: Enter\n", __func__));
5228
5229 bus = drvr->bus;
5230
5231 if (bus->drvr->dongle_reset)
5232 return false;
5233
5234 /* Ignore the timer if simulating bus down */
5235 if (bus->sleeping)
5236 return false;
5237
5238 brcmf_sdbrcm_sdlock(bus);
5239
5240 /* Poll period: check device if appropriate. */
5241 if (bus->poll && (++bus->polltick >= bus->pollrate)) {
5242 u32 intstatus = 0;
5243
5244 /* Reset poll tick */
5245 bus->polltick = 0;
5246
5247 /* Check device if no interrupts */
5248 if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
5249
5250 if (!bus->dpc_sched) {
5251 u8 devpend;
5252 devpend = brcmf_sdcard_cfg_read(bus->card,
5253 SDIO_FUNC_0, SDIO_CCCR_INTx,
5254 NULL);
5255 intstatus =
5256 devpend & (INTR_STATUS_FUNC1 |
5257 INTR_STATUS_FUNC2);
5258 }
5259
5260 /* If there is something, make like the ISR and
5261 schedule the DPC */
5262 if (intstatus) {
5263 bus->pollcnt++;
5264 bus->ipend = true;
5265 if (bus->intr)
5266 brcmf_sdcard_intr_disable(bus->card);
5267
5268 bus->dpc_sched = true;
5269 brcmf_sdbrcm_sched_dpc(bus);
5270
5271 }
5272 }
5273
5274 /* Update interrupt tracking */
5275 bus->lastintrs = bus->intrcount;
5276 }
5277#ifdef BCMDBG
5278 /* Poll for console output periodically */
5279 if (drvr->busstate == BRCMF_BUS_DATA && brcmf_console_ms != 0) {
5280 bus->console.count += brcmf_watchdog_ms;
5281 if (bus->console.count >= brcmf_console_ms) {
5282 bus->console.count -= brcmf_console_ms;
5283 /* Make sure backplane clock is on */
5284 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
5285 if (brcmf_sdbrcm_readconsole(bus) < 0)
5286 brcmf_console_ms = 0; /* On error,
5287 stop trying */
5288 }
5289 }
5290#endif /* BCMDBG */
5291
5292#ifdef SDTEST
5293 /* Generate packets if configured */
5294 if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
5295 /* Make sure backplane clock is on */
5296 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
5297 bus->pktgen_tick = 0;
5298 brcmf_sdbrcm_pktgen(bus);
5299 }
5300#endif
5301
5302 /* On idle timeout clear activity flag and/or turn off clock */
5303 if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
5304 if (++bus->idlecount >= bus->idletime) {
5305 bus->idlecount = 0;
5306 if (bus->activity) {
5307 bus->activity = false;
5308 brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
5309 } else {
5310 brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
5311 }
5312 }
5313 }
5314
5315 brcmf_sdbrcm_sdunlock(bus);
5316
5317 return bus->ipend;
5318}
5319
5320#ifdef BCMDBG
5321static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr,
5322 unsigned char *msg, uint msglen)
5323{
5324 struct brcmf_bus *bus = drvr->bus;
5325 u32 addr, val;
5326 int rv;
5327 struct sk_buff *pkt;
5328
5329 /* Address could be zero if CONSOLE := 0 in dongle Makefile */
5330 if (bus->console_addr == 0)
5331 return -ENOTSUPP;
5332
5333 /* Exclusive bus access */
5334 brcmf_sdbrcm_sdlock(bus);
5335
5336 /* Don't allow input if dongle is in reset */
5337 if (bus->drvr->dongle_reset) {
5338 brcmf_sdbrcm_sdunlock(bus);
5339 return -EPERM;
5340 }
5341
5342 /* Request clock to allow SDIO accesses */
5343 BUS_WAKE(bus);
5344 /* No pend allowed since txpkt is called later, ht clk has to be on */
5345 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
5346
5347 /* Zero cbuf_index */
5348 addr = bus->console_addr + offsetof(struct rte_console, cbuf_idx);
5349 val = cpu_to_le32(0);
5350 rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
5351 if (rv < 0)
5352 goto done;
5353
5354 /* Write message into cbuf */
5355 addr = bus->console_addr + offsetof(struct rte_console, cbuf);
5356 rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)msg, msglen);
5357 if (rv < 0)
5358 goto done;
5359
5360 /* Write length into vcons_in */
5361 addr = bus->console_addr + offsetof(struct rte_console, vcons_in);
5362 val = cpu_to_le32(msglen);
5363 rv = brcmf_sdbrcm_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
5364 if (rv < 0)
5365 goto done;
5366
5367 /* Bump dongle by sending an empty event pkt.
5368 * sdpcm_sendup (RX) checks for virtual console input.
5369 */
5370 pkt = brcmu_pkt_buf_get_skb(4 + SDPCM_RESERVE);
5371 if ((pkt != NULL) && bus->clkstate == CLK_AVAIL)
5372 brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, true);
5373
5374done:
5375 if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
5376 bus->activity = false;
5377 brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
5378 }
5379
5380 brcmf_sdbrcm_sdunlock(bus);
5381
5382 return rv;
5383}
5384#endif /* BCMDBG */
5385
5386static bool brcmf_sdbrcm_chipmatch(u16 chipid)
5387{
5388 if (chipid == BCM4325_CHIP_ID)
5389 return true;
5390 if (chipid == BCM4329_CHIP_ID)
5391 return true;
5392 if (chipid == BCM4319_CHIP_ID)
5393 return true;
5394 return false;
5395}
5396
5397static void *brcmf_sdbrcm_probe(u16 venid, u16 devid, u16 bus_no,
5398 u16 slot, u16 func, uint bustype, u32 regsva,
5399 void *card)
5400{
5401 int ret;
5402 struct brcmf_bus *bus;
5403
5404 /* Init global variables at run-time, not as part of the declaration.
5405 * This is required to support init/de-init of the driver.
5406 * Initialization
5407 * of globals as part of the declaration results in non-deterministic
5408 * behavior since the value of the globals may be different on the
5409 * first time that the driver is initialized vs subsequent
5410 * initializations.
5411 */
5412 brcmf_txbound = BRCMF_TXBOUND;
5413 brcmf_rxbound = BRCMF_RXBOUND;
5414 brcmf_alignctl = true;
5415 sd1idle = true;
5416 brcmf_readahead = true;
5417 retrydata = false;
5418 brcmf_dongle_memsize = 0;
5419 brcmf_txminmax = BRCMF_TXMINMAX;
5420
5421 forcealign = true;
5422
5423 brcmf_c_init();
5424
5425 BRCMF_TRACE(("%s: Enter\n", __func__));
5426 BRCMF_INFO(("%s: venid 0x%04x devid 0x%04x\n", __func__, venid, devid));
5427
5428 /* We make an assumption about address window mappings:
5429 * regsva == SI_ENUM_BASE*/
5430
5431 /* SDIO car passes venid and devid based on CIS parsing -- but
5432 * low-power start
5433 * means early parse could fail, so here we should get either an ID
5434 * we recognize OR (-1) indicating we must request power first.
5435 */
5436 /* Check the Vendor ID */
5437 switch (venid) {
5438 case 0x0000:
5439 case PCI_VENDOR_ID_BROADCOM:
5440 break;
5441 default:
5442 BRCMF_ERROR(("%s: unknown vendor: 0x%04x\n", __func__, venid));
5443 return NULL;
5444 }
5445
5446 /* Check the Device ID and make sure it's one that we support */
5447 switch (devid) {
5448 case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */
5449 case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */
5450 case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */
5451 BRCMF_INFO(("%s: found 4325 Dongle\n", __func__));
5452 break;
5453 case BCM4329_D11NDUAL_ID: /* 4329 802.11n dualband device */
5454 case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */
5455 case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */
5456 case 0x4329:
5457 BRCMF_INFO(("%s: found 4329 Dongle\n", __func__));
5458 break;
5459 case BCM4319_D11N_ID: /* 4319 802.11n id */
5460 case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */
5461 case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */
5462 BRCMF_INFO(("%s: found 4319 Dongle\n", __func__));
5463 break;
5464 case 0:
5465 BRCMF_INFO(("%s: allow device id 0, will check chip"
5466 " internals\n", __func__));
5467 break;
5468
5469 default:
5470 BRCMF_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
5471 __func__, venid, devid));
5472 return NULL;
5473 }
5474
5475 /* Allocate private bus interface state */
5476 bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
5477 if (!bus) {
5478 BRCMF_ERROR(("%s: kmalloc of struct dhd_bus failed\n",
5479 __func__));
5480 goto fail;
5481 }
5482 bus->card = card;
5483 bus->cl_devid = (u16) devid;
5484 bus->bus = BRCMF_BUS;
5485 bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
5486 bus->usebufpool = false; /* Use bufpool if allocated,
5487 else use locally malloced rxbuf */
5488
5489 /* attempt to attach to the dongle */
5490 if (!(brcmf_sdbrcm_probe_attach(bus, card, regsva, devid))) {
5491 BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_attach failed\n",
5492 __func__));
5493 goto fail;
5494 }
5495
5496 spin_lock_init(&bus->txqlock);
5497 init_waitqueue_head(&bus->ctrl_wait);
5498
5499 /* Set up the watchdog timer */
5500 init_timer(&bus->timer);
5501 bus->timer.data = (unsigned long)bus;
5502 bus->timer.function = brcmf_sdbrcm_watchdog;
5503
5504 /* Initialize thread based operation and lock */
5505 if ((brcmf_watchdog_prio >= 0) && (brcmf_dpc_prio >= 0)) {
5506 bus->threads_only = true;
5507 sema_init(&bus->sdsem, 1);
5508 } else {
5509 bus->threads_only = false;
5510 spin_lock_init(&bus->sdlock);
5511 }
5512
5513 if (brcmf_dpc_prio >= 0) {
5514 /* Initialize watchdog thread */
5515 init_completion(&bus->watchdog_wait);
5516 bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread,
5517 bus, "brcmf_watchdog");
5518 if (IS_ERR(bus->watchdog_tsk)) {
5519 printk(KERN_WARNING
5520 "brcmf_watchdog thread failed to start\n");
5521 bus->watchdog_tsk = NULL;
5522 }
5523 } else
5524 bus->watchdog_tsk = NULL;
5525
5526 /* Set up the bottom half handler */
5527 if (brcmf_dpc_prio >= 0) {
5528 /* Initialize DPC thread */
5529 init_completion(&bus->dpc_wait);
5530 bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
5531 bus, "brcmf_dpc");
5532 if (IS_ERR(bus->dpc_tsk)) {
5533 printk(KERN_WARNING
5534 "brcmf_dpc thread failed to start\n");
5535 bus->dpc_tsk = NULL;
5536 }
5537 } else {
5538 tasklet_init(&bus->tasklet, brcmf_sdbrcm_dpc_tasklet,
5539 (unsigned long)bus);
5540 bus->dpc_tsk = NULL;
5541 }
5542
5543 /* Attach to the brcmf/OS/network interface */
5544 bus->drvr = brcmf_attach(bus, SDPCM_RESERVE);
5545 if (!bus->drvr) {
5546 BRCMF_ERROR(("%s: brcmf_attach failed\n", __func__));
5547 goto fail;
5548 }
5549
5550 /* Allocate buffers */
5551 if (!(brcmf_sdbrcm_probe_malloc(bus, card))) {
5552 BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_malloc failed\n",
5553 __func__));
5554 goto fail;
5555 }
5556
5557 if (!(brcmf_sdbrcm_probe_init(bus, card))) {
5558 BRCMF_ERROR(("%s: brcmf_sdbrcm_probe_init failed\n", __func__));
5559 goto fail;
5560 }
5561
5562 /* Register interrupt callback, but mask it (not operational yet). */
5563 BRCMF_INTR(("%s: disable SDIO interrupts (not interested yet)\n",
5564 __func__));
5565 brcmf_sdcard_intr_disable(card);
5566 ret = brcmf_sdcard_intr_reg(card, brcmf_sdbrcm_isr, bus);
5567 if (ret != 0) {
5568 BRCMF_ERROR(("%s: FAILED: sdcard_intr_reg returned %d\n",
5569 __func__, ret));
5570 goto fail;
5571 }
5572 BRCMF_INTR(("%s: registered SDIO interrupt function ok\n", __func__));
5573
5574 BRCMF_INFO(("%s: completed!!\n", __func__));
5575
5576 /* if firmware path present try to download and bring up bus */
5577 ret = brcmf_bus_start(bus->drvr);
5578 if (ret != 0) {
5579 if (ret == -ENOLINK) {
5580 BRCMF_ERROR(("%s: dongle is not responding\n",
5581 __func__));
5582 goto fail;
5583 }
5584 }
5585 /* Ok, have the per-port tell the stack we're open for business */
5586 if (brcmf_net_attach(bus->drvr, 0) != 0) {
5587 BRCMF_ERROR(("%s: Net attach failed!!\n", __func__));
5588 goto fail;
5589 }
5590
5591 return bus;
5592
5593fail:
5594 brcmf_sdbrcm_release(bus);
5595 return NULL;
5596}
5597
5598static bool
5599brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card, u32 regsva,
5600 u16 devid)
5601{
5602 u8 clkctl = 0;
5603 int err = 0;
5604
5605 bus->alp_only = true;
5606
5607 /* Return the window to backplane enumeration space for core access */
5608 if (brcmf_sdbrcm_set_siaddr_window(bus, SI_ENUM_BASE))
5609 BRCMF_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n",
5610 __func__));
5611
5612#ifdef BCMDBG
5613 printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n",
5614 brcmf_sdcard_reg_read(bus->card, SI_ENUM_BASE, 4));
5615
5616#endif /* BCMDBG */
5617
5618 /*
5619 * Force PLL off until brcmf_sdbrcm_chip_attach()
5620 * programs PLL control regs
5621 */
5622
5623 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5624 BRCMF_INIT_CLKCTL1, &err);
5625 if (!err)
5626 clkctl =
5627 brcmf_sdcard_cfg_read(card, SDIO_FUNC_1,
5628 SBSDIO_FUNC1_CHIPCLKCSR, &err);
5629
5630 if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
5631 BRCMF_ERROR(("brcmf_sdbrcm_probe: ChipClkCSR access: err %d"
5632 " wrote 0x%02x read 0x%02x\n",
5633 err, BRCMF_INIT_CLKCTL1, clkctl));
5634 goto fail;
5635 }
5636
5637 if (brcmf_sdbrcm_chip_attach(bus, regsva)) {
5638 BRCMF_ERROR(("%s: brcmf_sdbrcm_chip_attach failed!\n",
5639 __func__));
5640 goto fail;
5641 }
5642
5643 if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) {
5644 BRCMF_ERROR(("%s: unsupported chip: 0x%04x\n",
5645 __func__, bus->ci->chip));
5646 goto fail;
5647 }
5648
5649 brcmf_sdbrcm_sdiod_drive_strength_init(bus, brcmf_sdiod_drive_strength);
5650
5651 /* Get info on the ARM and SOCRAM cores... */
5652 if (!BRCMF_NOPMU(bus)) {
5653 brcmf_sdcard_reg_read(bus->card,
5654 CORE_SB(bus->ci->armcorebase, sbidhigh), 4);
5655 bus->orig_ramsize = bus->ci->ramsize;
5656 if (!(bus->orig_ramsize)) {
5657 BRCMF_ERROR(("%s: failed to find SOCRAM memory!\n",
5658 __func__));
5659 goto fail;
5660 }
5661 bus->ramsize = bus->orig_ramsize;
5662 if (brcmf_dongle_memsize)
5663 brcmf_sdbrcm_setmemsize(bus, brcmf_dongle_memsize);
5664
5665 BRCMF_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n",
5666 bus->ramsize, bus->orig_ramsize));
5667 }
5668
5669 /* Set core control so an SDIO reset does a backplane reset */
5670 OR_REG(bus->ci->buscorebase + offsetof(struct sdpcmd_regs,
5671 corecontrol),
5672 CC_BPRESEN, u32);
5673
5674 brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
5675
5676 /* Locate an appropriately-aligned portion of hdrbuf */
5677 bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0],
5678 BRCMF_SDALIGN);
5679
5680 /* Set the poll and/or interrupt flags */
5681 bus->intr = (bool) brcmf_intr;
5682 bus->poll = (bool) brcmf_poll;
5683 if (bus->poll)
5684 bus->pollrate = 1;
5685
5686 return true;
5687
5688fail:
5689 return false;
5690}
5691
5692static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card)
5693{
5694 BRCMF_TRACE(("%s: Enter\n", __func__));
5695
5696 if (bus->drvr->maxctl) {
5697 bus->rxblen =
5698 roundup((bus->drvr->maxctl + SDPCM_HDRLEN),
5699 ALIGNMENT) + BRCMF_SDALIGN;
5700 bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
5701 if (!(bus->rxbuf)) {
5702 BRCMF_ERROR(("%s: kmalloc of %d-byte rxbuf failed\n",
5703 __func__, bus->rxblen));
5704 goto fail;
5705 }
5706 }
5707
5708 /* Allocate buffer to receive glomed packet */
5709 bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC);
5710 if (!(bus->databuf)) {
5711 BRCMF_ERROR(("%s: kmalloc of %d-byte databuf failed\n",
5712 __func__, MAX_DATA_BUF));
5713 /* release rxbuf which was already located as above */
5714 if (!bus->rxblen)
5715 kfree(bus->rxbuf);
5716 goto fail;
5717 }
5718
5719 /* Align the buffer */
5720 if ((unsigned long)bus->databuf % BRCMF_SDALIGN)
5721 bus->dataptr = bus->databuf + (BRCMF_SDALIGN -
5722 ((unsigned long)bus->databuf % BRCMF_SDALIGN));
5723 else
5724 bus->dataptr = bus->databuf;
5725
5726 return true;
5727
5728fail:
5729 return false;
5730}
5731
5732static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card)
5733{
5734 s32 fnum;
5735
5736 BRCMF_TRACE(("%s: Enter\n", __func__));
5737
5738#ifdef SDTEST
5739 brcmf_sdbrcm_pktgen_init(bus);
5740#endif /* SDTEST */
5741
5742 /* Disable F2 to clear any intermediate frame state on the dongle */
5743 brcmf_sdcard_cfg_write(card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
5744 SDIO_FUNC_ENABLE_1, NULL);
5745
5746 bus->drvr->busstate = BRCMF_BUS_DOWN;
5747 bus->sleeping = false;
5748 bus->rxflow = false;
5749
5750 /* Done with backplane-dependent accesses, can drop clock... */
5751 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0,
5752 NULL);
5753
5754 /* ...and initialize clock/power states */
5755 bus->clkstate = CLK_SDONLY;
5756 bus->idletime = (s32) brcmf_idletime;
5757 bus->idleclock = BRCMF_IDLE_ACTIVE;
5758
5759 /* Query the F2 block size, set roundup accordingly */
5760 fnum = 2;
5761 if (brcmf_sdcard_iovar_op(card, "sd_blocksize", &fnum, sizeof(s32),
5762 &bus->blocksize, sizeof(s32), false) != 0) {
5763 bus->blocksize = 0;
5764 BRCMF_ERROR(("%s: fail on %s get\n", __func__, "sd_blocksize"));
5765 } else {
5766 BRCMF_INFO(("%s: Initial value for %s is %d\n",
5767 __func__, "sd_blocksize", bus->blocksize));
5768 }
5769 bus->roundup = min(max_roundup, bus->blocksize);
5770
5771 /* Query if bus module supports packet chaining,
5772 default to use if supported */
5773 if (brcmf_sdcard_iovar_op(card, "sd_rxchain", NULL, 0,
5774 &bus->sd_rxchain, sizeof(s32),
5775 false) != 0) {
5776 bus->sd_rxchain = false;
5777 } else {
5778 BRCMF_INFO(("%s: bus module (through sdiocard API) %s"
5779 " chaining\n", __func__, bus->sd_rxchain
5780 ? "supports" : "does not support"));
5781 }
5782 bus->use_rxchain = (bool) bus->sd_rxchain;
5783
5784 return true;
5785}
5786
5787static bool
5788brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card)
5789{
5790 bool ret;
5791
5792 /* Download the firmware */
5793 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
5794
5795 ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
5796
5797 brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
5798
5799 return ret;
5800}
5801
5802/* Detach and free everything */
5803static void brcmf_sdbrcm_release(struct brcmf_bus *bus)
5804{
5805 BRCMF_TRACE(("%s: Enter\n", __func__));
5806
5807 if (bus) {
5808 /* De-register interrupt handler */
5809 brcmf_sdcard_intr_disable(bus->card);
5810 brcmf_sdcard_intr_dereg(bus->card);
5811
5812 if (bus->drvr) {
5813 brcmf_detach(bus->drvr);
5814 brcmf_sdbrcm_release_dongle(bus);
5815 bus->drvr = NULL;
5816 }
5817
5818 brcmf_sdbrcm_release_malloc(bus);
5819
5820 kfree(bus);
5821 }
5822
5823 BRCMF_TRACE(("%s: Disconnected\n", __func__));
5824}
5825
5826static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus)
5827{
5828 BRCMF_TRACE(("%s: Enter\n", __func__));
5829
5830 if (bus->drvr && bus->drvr->dongle_reset)
5831 return;
5832
5833 kfree(bus->rxbuf);
5834 bus->rxctl = bus->rxbuf = NULL;
5835 bus->rxlen = 0;
5836
5837 kfree(bus->databuf);
5838 bus->databuf = NULL;
5839}
5840
5841static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
5842{
5843 BRCMF_TRACE(("%s: Enter\n", __func__));
5844
5845 if (bus->drvr && bus->drvr->dongle_reset)
5846 return;
5847
5848 if (bus->ci) {
5849 brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
5850 brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
5851 brcmf_sdbrcm_chip_detach(bus);
5852 if (bus->vars && bus->varsz)
5853 kfree(bus->vars);
5854 bus->vars = NULL;
5855 }
5856
5857 BRCMF_TRACE(("%s: Disconnected\n", __func__));
5858}
5859
5860static void brcmf_sdbrcm_disconnect(void *ptr)
5861{
5862 struct brcmf_bus *bus = (struct brcmf_bus *)ptr;
5863
5864 BRCMF_TRACE(("%s: Enter\n", __func__));
5865
5866 if (bus) {
5867 brcmf_sdbrcm_release(bus);
5868 }
5869
5870 BRCMF_TRACE(("%s: Disconnected\n", __func__));
5871}
5872
5873/* Register/Unregister functions are called by the main DHD entry
5874 * point (e.g. module insertion) to link with the bus driver, in
5875 * order to look for or await the device.
5876 */
5877
5878static struct brcmf_sdioh_driver brcmf_sdio = {
5879 brcmf_sdbrcm_probe,
5880 brcmf_sdbrcm_disconnect
5881};
5882
5883int brcmf_bus_register(void)
5884{
5885 BRCMF_TRACE(("%s: Enter\n", __func__));
5886
5887 /* Sanity check on the module parameters */
5888 do {
5889 /* Both watchdog and DPC as tasklets are ok */
5890 if ((brcmf_watchdog_prio < 0) && (brcmf_dpc_prio < 0))
5891 break;
5892
5893 /* If both watchdog and DPC are threads, TX must be deferred */
5894 if ((brcmf_watchdog_prio >= 0) && (brcmf_dpc_prio >= 0)
5895 && brcmf_deferred_tx)
5896 break;
5897
5898 BRCMF_ERROR(("Invalid module parameters.\n"));
5899 return -EINVAL;
5900 } while (0);
5901
5902 return brcmf_sdio_register(&brcmf_sdio);
5903}
5904
5905void brcmf_bus_unregister(void)
5906{
5907 BRCMF_TRACE(("%s: Enter\n", __func__));
5908
5909 brcmf_sdio_unregister();
5910}
5911
5912static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus)
5913{
5914 int offset = 0;
5915 uint len;
5916 u8 *memblock = NULL, *memptr;
5917 int ret;
5918
5919 BRCMF_INFO(("%s: Enter\n", __func__));
5920
5921 bus->fw_name = BCM4329_FW_NAME;
5922 ret = request_firmware(&bus->firmware, bus->fw_name,
5923 &gInstance->func[2]->dev);
5924 if (ret) {
5925 BRCMF_ERROR(("%s: Fail to request firmware %d\n",
5926 __func__, ret));
5927 return ret;
5928 }
5929 bus->fw_ptr = 0;
5930
5931 memptr = memblock = kmalloc(MEMBLOCK + BRCMF_SDALIGN, GFP_ATOMIC);
5932 if (memblock == NULL) {
5933 BRCMF_ERROR(("%s: Failed to allocate memory %d bytes\n",
5934 __func__, MEMBLOCK));
5935 ret = -ENOMEM;
5936 goto err;
5937 }
5938 if ((u32)(unsigned long)memblock % BRCMF_SDALIGN)
5939 memptr += (BRCMF_SDALIGN -
5940 ((u32)(unsigned long)memblock % BRCMF_SDALIGN));
5941
5942 /* Download image */
5943 while ((len =
5944 brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) {
5945 ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len);
5946 if (ret) {
5947 BRCMF_ERROR(("%s: error %d on writing %d membytes at "
5948 "0x%08x\n", __func__, ret, MEMBLOCK,
5949 offset));
5950 goto err;
5951 }
5952
5953 offset += MEMBLOCK;
5954 }
5955
5956err:
5957 kfree(memblock);
5958
5959 release_firmware(bus->firmware);
5960 bus->fw_ptr = 0;
5961
5962 return ret;
5963}
5964
5965/*
5966 * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file
5967 * and ending in a NUL.
5968 * Removes carriage returns, empty lines, comment lines, and converts
5969 * newlines to NULs.
5970 * Shortens buffer as needed and pads with NULs. End of buffer is marked
5971 * by two NULs.
5972*/
5973
5974static uint brcmf_process_nvram_vars(char *varbuf, uint len)
5975{
5976 char *dp;
5977 bool findNewline;
5978 int column;
5979 uint buf_len, n;
5980
5981 dp = varbuf;
5982
5983 findNewline = false;
5984 column = 0;
5985
5986 for (n = 0; n < len; n++) {
5987 if (varbuf[n] == 0)
5988 break;
5989 if (varbuf[n] == '\r')
5990 continue;
5991 if (findNewline && varbuf[n] != '\n')
5992 continue;
5993 findNewline = false;
5994 if (varbuf[n] == '#') {
5995 findNewline = true;
5996 continue;
5997 }
5998 if (varbuf[n] == '\n') {
5999 if (column == 0)
6000 continue;
6001 *dp++ = 0;
6002 column = 0;
6003 continue;
6004 }
6005 *dp++ = varbuf[n];
6006 column++;
6007 }
6008 buf_len = dp - varbuf;
6009
6010 while (dp < varbuf + n)
6011 *dp++ = 0;
6012
6013 return buf_len;
6014}
6015
6016static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus)
6017{
6018 uint len;
6019 char *memblock = NULL;
6020 char *bufp;
6021 int ret;
6022
6023 bus->nv_name = BCM4329_NV_NAME;
6024 ret = request_firmware(&bus->firmware, bus->nv_name,
6025 &gInstance->func[2]->dev);
6026 if (ret) {
6027 BRCMF_ERROR(("%s: Fail to request nvram %d\n", __func__, ret));
6028 return ret;
6029 }
6030 bus->fw_ptr = 0;
6031
6032 memblock = kmalloc(MEMBLOCK, GFP_ATOMIC);
6033 if (memblock == NULL) {
6034 BRCMF_ERROR(("%s: Failed to allocate memory %d bytes\n",
6035 __func__, MEMBLOCK));
6036 ret = -ENOMEM;
6037 goto err;
6038 }
6039
6040 len = brcmf_sdbrcm_get_image(memblock, MEMBLOCK, bus);
6041
6042 if (len > 0 && len < MEMBLOCK) {
6043 bufp = (char *)memblock;
6044 bufp[len] = 0;
6045 len = brcmf_process_nvram_vars(bufp, len);
6046 bufp += len;
6047 *bufp++ = 0;
6048 if (len)
6049 ret = brcmf_sdbrcm_downloadvars(bus, memblock, len + 1);
6050 if (ret)
6051 BRCMF_ERROR(("%s: error downloading vars: %d\n",
6052 __func__, ret));
6053 } else {
6054 BRCMF_ERROR(("%s: error reading nvram file: %d\n",
6055 __func__, len));
6056 ret = -EIO;
6057 }
6058
6059err:
6060 kfree(memblock);
6061
6062 release_firmware(bus->firmware);
6063 bus->fw_ptr = 0;
6064
6065 return ret;
6066}
6067
6068static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus)
6069{
6070 int bcmerror = -1;
6071
6072 /* Keep arm in reset */
6073 if (brcmf_sdbrcm_download_state(bus, true)) {
6074 BRCMF_ERROR(("%s: error placing ARM core in reset\n",
6075 __func__));
6076 goto err;
6077 }
6078
6079 /* External image takes precedence if specified */
6080 if (brcmf_sdbrcm_download_code_file(bus)) {
6081 BRCMF_ERROR(("%s: dongle image file download failed\n",
6082 __func__));
6083 goto err;
6084 }
6085
6086 /* External nvram takes precedence if specified */
6087 if (brcmf_sdbrcm_download_nvram(bus)) {
6088 BRCMF_ERROR(("%s: dongle nvram file download failed\n",
6089 __func__));
6090 }
6091
6092 /* Take arm out of reset */
6093 if (brcmf_sdbrcm_download_state(bus, false)) {
6094 BRCMF_ERROR(("%s: error getting out of ARM core reset\n",
6095 __func__));
6096 goto err;
6097 }
6098
6099 bcmerror = 0;
6100
6101err:
6102 return bcmerror;
6103}
6104
6105
6106static int
6107brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, uint flags,
6108 u8 *buf, uint nbytes, struct sk_buff *pkt,
6109 void (*complete)(void *handle, int status,
6110 bool sync_waiting),
6111 void *handle)
6112{
6113 return brcmf_sdcard_send_buf
6114 (bus->card, addr, fn, flags, buf, nbytes, pkt, complete,
6115 handle);
6116}
6117
6118int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag)
6119{
6120 int bcmerror = 0;
6121 struct brcmf_bus *bus;
6122
6123 bus = drvr->bus;
6124
6125 if (flag == true) {
6126 brcmf_sdbrcm_wd_timer(bus, 0);
6127 if (!bus->drvr->dongle_reset) {
6128 /* Expect app to have torn down any
6129 connection before calling */
6130 /* Stop the bus, disable F2 */
6131 brcmf_sdbrcm_bus_stop(bus, false);
6132
6133 /* Clean tx/rx buffer pointers,
6134 detach from the dongle */
6135 brcmf_sdbrcm_release_dongle(bus);
6136
6137 bus->drvr->dongle_reset = true;
6138 bus->drvr->up = false;
6139
6140 BRCMF_TRACE(("%s: WLAN OFF DONE\n", __func__));
6141 /* App can now remove power from device */
6142 } else
6143 bcmerror = -EIO;
6144 } else {
6145 /* App must have restored power to device before calling */
6146
6147 BRCMF_TRACE(("\n\n%s: == WLAN ON ==\n", __func__));
6148
6149 if (bus->drvr->dongle_reset) {
6150 /* Turn on WLAN */
6151
6152 /* Attempt to re-attach & download */
6153 if (brcmf_sdbrcm_probe_attach(bus, bus->card,
6154 SI_ENUM_BASE,
6155 bus->cl_devid)) {
6156 /* Attempt to download binary to the dongle */
6157 if (brcmf_sdbrcm_probe_init(bus, bus->card)) {
6158 /* Re-init bus, enable F2 transfer */
6159 brcmf_sdbrcm_bus_init(bus->drvr, false);
6160
6161 bus->drvr->dongle_reset = false;
6162 bus->drvr->up = true;
6163
6164 BRCMF_TRACE(("%s: WLAN ON DONE\n",
6165 __func__));
6166 } else
6167 bcmerror = -EIO;
6168 } else
6169 bcmerror = -EIO;
6170 } else {
6171 bcmerror = -EISCONN;
6172 BRCMF_ERROR(("%s: Set DEVRESET=false invoked when"
6173 " device is on\n", __func__));
6174 bcmerror = -EIO;
6175 }
6176 brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
6177 }
6178 return bcmerror;
6179}
6180
6181static int
6182brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_card *card,
6183 struct chip_info *ci, u32 regs)
6184{
6185 u32 regdata;
6186
6187 /*
6188 * Get CC core rev
6189 * Chipid is assume to be at offset 0 from regs arg
6190 * For different chiptypes or old sdio hosts w/o chipcommon,
6191 * other ways of recognition should be added here.
6192 */
6193 ci->cccorebase = regs;
6194 regdata = brcmf_sdcard_reg_read(card,
6195 CORE_CC_REG(ci->cccorebase, chipid), 4);
6196 ci->chip = regdata & CID_ID_MASK;
6197 ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
6198
6199 BRCMF_INFO(("%s: chipid=0x%x chiprev=%d\n",
6200 __func__, ci->chip, ci->chiprev));
6201
6202 /* Address of cores for new chips should be added here */
6203 switch (ci->chip) {
6204 case BCM4329_CHIP_ID:
6205 ci->buscorebase = BCM4329_CORE_BUS_BASE;
6206 ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
6207 ci->armcorebase = BCM4329_CORE_ARM_BASE;
6208 ci->ramsize = BCM4329_RAMSIZE;
6209 break;
6210 default:
6211 BRCMF_ERROR(("%s: chipid 0x%x is not supported\n",
6212 __func__, ci->chip));
6213 return -ENODEV;
6214 }
6215
6216 regdata = brcmf_sdcard_reg_read(card,
6217 CORE_SB(ci->cccorebase, sbidhigh), 4);
6218 ci->ccrev = SBCOREREV(regdata);
6219
6220 regdata = brcmf_sdcard_reg_read(card,
6221 CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
6222 ci->pmurev = regdata & PCAP_REV_MASK;
6223
6224 regdata = brcmf_sdcard_reg_read(card,
6225 CORE_SB(ci->buscorebase, sbidhigh), 4);
6226 ci->buscorerev = SBCOREREV(regdata);
6227 ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
6228
6229 BRCMF_INFO(("%s: ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
6230 __func__, ci->ccrev, ci->pmurev,
6231 ci->buscorerev, ci->buscoretype));
6232
6233 /* get chipcommon capabilites */
6234 ci->cccaps = brcmf_sdcard_reg_read(card,
6235 CORE_CC_REG(ci->cccorebase, capabilities), 4);
6236
6237 return 0;
6238}
6239
6240static void
6241brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase)
6242{
6243 u32 regdata;
6244
6245 regdata = brcmf_sdcard_reg_read(card,
6246 CORE_SB(corebase, sbtmstatelow), 4);
6247 if (regdata & SBTML_RESET)
6248 return;
6249
6250 regdata = brcmf_sdcard_reg_read(card,
6251 CORE_SB(corebase, sbtmstatelow), 4);
6252 if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
6253 /*
6254 * set target reject and spin until busy is clear
6255 * (preserve core-specific bits)
6256 */
6257 regdata = brcmf_sdcard_reg_read(card,
6258 CORE_SB(corebase, sbtmstatelow), 4);
6259 brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
6260 regdata | SBTML_REJ);
6261
6262 regdata = brcmf_sdcard_reg_read(card,
6263 CORE_SB(corebase, sbtmstatelow), 4);
6264 udelay(1);
6265 SPINWAIT((brcmf_sdcard_reg_read(card,
6266 CORE_SB(corebase, sbtmstatehigh), 4) &
6267 SBTMH_BUSY), 100000);
6268
6269 regdata = brcmf_sdcard_reg_read(card,
6270 CORE_SB(corebase, sbtmstatehigh), 4);
6271 if (regdata & SBTMH_BUSY)
6272 BRCMF_ERROR(("%s: ARM core still busy\n", __func__));
6273
6274 regdata = brcmf_sdcard_reg_read(card,
6275 CORE_SB(corebase, sbidlow), 4);
6276 if (regdata & SBIDL_INIT) {
6277 regdata = brcmf_sdcard_reg_read(card,
6278 CORE_SB(corebase, sbimstate), 4) |
6279 SBIM_RJ;
6280 brcmf_sdcard_reg_write(card,
6281 CORE_SB(corebase, sbimstate), 4,
6282 regdata);
6283 regdata = brcmf_sdcard_reg_read(card,
6284 CORE_SB(corebase, sbimstate), 4);
6285 udelay(1);
6286 SPINWAIT((brcmf_sdcard_reg_read(card,
6287 CORE_SB(corebase, sbimstate), 4) &
6288 SBIM_BY), 100000);
6289 }
6290
6291 /* set reset and reject while enabling the clocks */
6292 brcmf_sdcard_reg_write(card,
6293 CORE_SB(corebase, sbtmstatelow), 4,
6294 (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
6295 SBTML_REJ | SBTML_RESET));
6296 regdata = brcmf_sdcard_reg_read(card,
6297 CORE_SB(corebase, sbtmstatelow), 4);
6298 udelay(10);
6299
6300 /* clear the initiator reject bit */
6301 regdata = brcmf_sdcard_reg_read(card,
6302 CORE_SB(corebase, sbidlow), 4);
6303 if (regdata & SBIDL_INIT) {
6304 regdata = brcmf_sdcard_reg_read(card,
6305 CORE_SB(corebase, sbimstate), 4) &
6306 ~SBIM_RJ;
6307 brcmf_sdcard_reg_write(card,
6308 CORE_SB(corebase, sbimstate), 4,
6309 regdata);
6310 }
6311 }
6312
6313 /* leave reset and reject asserted */
6314 brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
6315 (SBTML_REJ | SBTML_RESET));
6316 udelay(1);
6317}
6318
6319static int
6320brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs)
6321{
6322 struct chip_info *ci;
6323 int err;
6324 u8 clkval, clkset;
6325
6326 BRCMF_TRACE(("%s: Enter\n", __func__));
6327
6328 /* alloc chip_info_t */
6329 ci = kmalloc(sizeof(struct chip_info), GFP_ATOMIC);
6330 if (NULL == ci) {
6331 BRCMF_ERROR(("%s: malloc failed!\n", __func__));
6332 return -ENOMEM;
6333 }
6334
6335 memset((unsigned char *)ci, 0, sizeof(struct chip_info));
6336
6337 /* bus/core/clk setup for register access */
6338 /* Try forcing SDIO core to do ALPAvail request only */
6339 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
6340 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
6341 clkset, &err);
6342 if (err) {
6343 BRCMF_ERROR(("%s: error writing for HT off\n", __func__));
6344 goto fail;
6345 }
6346
6347 /* If register supported, wait for ALPAvail and then force ALP */
6348 /* This may take up to 15 milliseconds */
6349 clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
6350 SBSDIO_FUNC1_CHIPCLKCSR, NULL);
6351 if ((clkval & ~SBSDIO_AVBITS) == clkset) {
6352 SPINWAIT(((clkval =
6353 brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
6354 SBSDIO_FUNC1_CHIPCLKCSR,
6355 NULL)),
6356 !SBSDIO_ALPAV(clkval)),
6357 PMU_MAX_TRANSITION_DLY);
6358 if (!SBSDIO_ALPAV(clkval)) {
6359 BRCMF_ERROR(("%s: timeout on ALPAV wait,"
6360 " clkval 0x%02x\n", __func__, clkval));
6361 err = -EBUSY;
6362 goto fail;
6363 }
6364 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF |
6365 SBSDIO_FORCE_ALP;
6366 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1,
6367 SBSDIO_FUNC1_CHIPCLKCSR,
6368 clkset, &err);
6369 udelay(65);
6370 } else {
6371 BRCMF_ERROR(("%s: ChipClkCSR access: wrote 0x%02x"
6372 " read 0x%02x\n", __func__, clkset, clkval));
6373 err = -EACCES;
6374 goto fail;
6375 }
6376
6377 /* Also, disable the extra SDIO pull-ups */
6378 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP,
6379 0, NULL);
6380
6381 err = brcmf_sdbrcm_chip_recognition(bus->card, ci, regs);
6382 if (err)
6383 goto fail;
6384
6385 /*
6386 * Make sure any on-chip ARM is off (in case strapping is wrong),
6387 * or downloaded code was already running.
6388 */
6389 brcmf_sdbrcm_chip_disablecore(bus->card, ci->armcorebase);
6390
6391 brcmf_sdcard_reg_write(bus->card,
6392 CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
6393 brcmf_sdcard_reg_write(bus->card,
6394 CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
6395
6396 /* Disable F2 to clear any intermediate frame state on the dongle */
6397 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx,
6398 SDIO_FUNC_ENABLE_1, NULL);
6399
6400 /* WAR: cmd52 backplane read so core HW will drop ALPReq */
6401 clkval = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_1,
6402 0, NULL);
6403
6404 /* Done with backplane-dependent accesses, can drop clock... */
6405 brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
6406 0, NULL);
6407
6408 bus->ci = ci;
6409 return 0;
6410fail:
6411 bus->ci = NULL;
6412 kfree(ci);
6413 return err;
6414}
6415
6416static void
6417brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase)
6418{
6419 u32 regdata;
6420
6421 /*
6422 * Must do the disable sequence first to work for
6423 * arbitrary current core state.
6424 */
6425 brcmf_sdbrcm_chip_disablecore(card, corebase);
6426
6427 /*
6428 * Now do the initialization sequence.
6429 * set reset while enabling the clock and
6430 * forcing them on throughout the core
6431 */
6432 brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
6433 ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
6434 SBTML_RESET);
6435 udelay(1);
6436
6437 regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbtmstatehigh),
6438 4);
6439 if (regdata & SBTMH_SERR)
6440 brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatehigh),
6441 4, 0);
6442
6443 regdata = brcmf_sdcard_reg_read(card, CORE_SB(corebase, sbimstate), 4);
6444 if (regdata & (SBIM_IBE | SBIM_TO))
6445 brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbimstate), 4,
6446 regdata & ~(SBIM_IBE | SBIM_TO));
6447
6448 /* clear reset and allow it to propagate throughout the core */
6449 brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
6450 (SICF_FGC << SBTML_SICF_SHIFT) |
6451 (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
6452 udelay(1);
6453
6454 /* leave clock enabled */
6455 brcmf_sdcard_reg_write(card, CORE_SB(corebase, sbtmstatelow), 4,
6456 (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
6457 udelay(1);
6458}
6459
6460/* SDIO Pad drive strength to select value mappings */
6461struct sdiod_drive_str {
6462 u8 strength; /* Pad Drive Strength in mA */
6463 u8 sel; /* Chip-specific select value */
6464};
6465
6466/* SDIO Drive Strength to sel value table for PMU Rev 1 */
6467static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
6468 {
6469 4, 0x2}, {
6470 2, 0x3}, {
6471 1, 0x0}, {
6472 0, 0x0}
6473 };
6474
6475/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
6476static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
6477 {
6478 12, 0x7}, {
6479 10, 0x6}, {
6480 8, 0x5}, {
6481 6, 0x4}, {
6482 4, 0x2}, {
6483 2, 0x1}, {
6484 0, 0x0}
6485 };
6486
6487/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
6488static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
6489 {
6490 32, 0x7}, {
6491 26, 0x6}, {
6492 22, 0x5}, {
6493 16, 0x4}, {
6494 12, 0x3}, {
6495 8, 0x2}, {
6496 4, 0x1}, {
6497 0, 0x0}
6498 };
6499
6500#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
6501
6502static void
6503brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, u32 drivestrength) {
6504 struct sdiod_drive_str *str_tab = NULL;
6505 u32 str_mask = 0;
6506 u32 str_shift = 0;
6507 char chn[8];
6508
6509 if (!(bus->ci->cccaps & CC_CAP_PMU))
6510 return;
6511
6512 switch (SDIOD_DRVSTR_KEY(bus->ci->chip, bus->ci->pmurev)) {
6513 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
6514 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
6515 str_mask = 0x30000000;
6516 str_shift = 28;
6517 break;
6518 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
6519 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
6520 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
6521 str_mask = 0x00003800;
6522 str_shift = 11;
6523 break;
6524 case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
6525 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
6526 str_mask = 0x00003800;
6527 str_shift = 11;
6528 break;
6529 default:
6530 BRCMF_ERROR(("No SDIO Drive strength init"
6531 "done for chip %s rev %d pmurev %d\n",
6532 brcmu_chipname(bus->ci->chip, chn, 8),
6533 bus->ci->chiprev, bus->ci->pmurev));
6534 break;
6535 }
6536
6537 if (str_tab != NULL) {
6538 u32 drivestrength_sel = 0;
6539 u32 cc_data_temp;
6540 int i;
6541
6542 for (i = 0; str_tab[i].strength != 0; i++) {
6543 if (drivestrength >= str_tab[i].strength) {
6544 drivestrength_sel = str_tab[i].sel;
6545 break;
6546 }
6547 }
6548
6549 brcmf_sdcard_reg_write(bus->card,
6550 CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
6551 4, 1);
6552 cc_data_temp = brcmf_sdcard_reg_read(bus->card,
6553 CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4);
6554 cc_data_temp &= ~str_mask;
6555 drivestrength_sel <<= str_shift;
6556 cc_data_temp |= drivestrength_sel;
6557 brcmf_sdcard_reg_write(bus->card,
6558 CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
6559 4, cc_data_temp);
6560
6561 BRCMF_INFO(("SDIO: %dmA drive strength selected, "
6562 "set to 0x%08x\n", drivestrength, cc_data_temp));
6563 }
6564}
6565
6566static void
6567brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus)
6568{
6569 BRCMF_TRACE(("%s: Enter\n", __func__));
6570
6571 kfree(bus->ci);
6572 bus->ci = NULL;
6573}
6574
6575static void
6576brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar)
6577{
6578 brcmf_sdbrcm_sdunlock(bus);
6579 wait_event_interruptible_timeout(bus->ctrl_wait,
6580 (*lockvar == false), HZ * 2);
6581 brcmf_sdbrcm_sdlock(bus);
6582 return;
6583}
6584
6585static void
6586brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus)
6587{
6588 if (waitqueue_active(&bus->ctrl_wait))
6589 wake_up_interruptible(&bus->ctrl_wait);
6590 return;
6591}
6592
6593static int
6594brcmf_sdbrcm_watchdog_thread(void *data)
6595{
6596 struct brcmf_bus *bus = (struct brcmf_bus *)data;
6597
6598 /* This thread doesn't need any user-level access,
6599 * so get rid of all our resources
6600 */
6601 if (brcmf_watchdog_prio > 0) {
6602 struct sched_param param;
6603 param.sched_priority = (brcmf_watchdog_prio < MAX_RT_PRIO) ?
6604 brcmf_watchdog_prio : (MAX_RT_PRIO - 1);
6605 sched_setscheduler(current, SCHED_FIFO, &param);
6606 }
6607
6608 allow_signal(SIGTERM);
6609 /* Run until signal received */
6610 while (1) {
6611 if (kthread_should_stop())
6612 break;
6613 if (!wait_for_completion_interruptible(&bus->watchdog_wait)) {
6614 if (bus->drvr->dongle_reset == false)
6615 brcmf_sdbrcm_bus_watchdog(bus->drvr);
6616 /* Count the tick for reference */
6617 bus->drvr->tickcnt++;
6618 } else
6619 break;
6620 }
6621 return 0;
6622}
6623
6624static void
6625brcmf_sdbrcm_watchdog(unsigned long data)
6626{
6627 struct brcmf_bus *bus = (struct brcmf_bus *)data;
6628
6629 if (brcmf_watchdog_prio >= 0) {
6630 if (bus->watchdog_tsk)
6631 complete(&bus->watchdog_wait);
6632 else
6633 return;
6634 } else {
6635 brcmf_sdbrcm_bus_watchdog(bus->drvr);
6636
6637 /* Count the tick for reference */
6638 bus->drvr->tickcnt++;
6639 }
6640
6641 /* Reschedule the watchdog */
6642 if (bus->wd_timer_valid)
6643 mod_timer(&bus->timer, jiffies + brcmf_watchdog_ms * HZ / 1000);
6644}
6645
6646void
6647brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
6648{
6649 static uint save_ms;
6650
6651 /* don't start the wd until fw is loaded */
6652 if (bus->drvr->busstate == BRCMF_BUS_DOWN)
6653 return;
6654
6655 /* Totally stop the timer */
6656 if (!wdtick && bus->wd_timer_valid == true) {
6657 del_timer_sync(&bus->timer);
6658 bus->wd_timer_valid = false;
6659 save_ms = wdtick;
6660 return;
6661 }
6662
6663 if (wdtick) {
6664 brcmf_watchdog_ms = (uint) wdtick;
6665
6666 if (save_ms != brcmf_watchdog_ms) {
6667 if (bus->wd_timer_valid == true)
6668 /* Stop timer and restart at new value */
6669 del_timer_sync(&bus->timer);
6670
6671 /* Create timer again when watchdog period is
6672 dynamically changed or in the first instance
6673 */
6674 bus->timer.expires =
6675 jiffies + brcmf_watchdog_ms * HZ / 1000;
6676 add_timer(&bus->timer);
6677
6678 } else {
6679 /* Re arm the timer, at last watchdog period */
6680 mod_timer(&bus->timer,
6681 jiffies + brcmf_watchdog_ms * HZ / 1000);
6682 }
6683
6684 bus->wd_timer_valid = true;
6685 save_ms = wdtick;
6686 }
6687}
6688
6689static int brcmf_sdbrcm_dpc_thread(void *data)
6690{
6691 struct brcmf_bus *bus = (struct brcmf_bus *) data;
6692
6693 /* This thread doesn't need any user-level access,
6694 * so get rid of all our resources
6695 */
6696 if (brcmf_dpc_prio > 0) {
6697 struct sched_param param;
6698 param.sched_priority = (brcmf_dpc_prio < MAX_RT_PRIO) ?
6699 brcmf_dpc_prio : (MAX_RT_PRIO - 1);
6700 sched_setscheduler(current, SCHED_FIFO, &param);
6701 }
6702
6703 allow_signal(SIGTERM);
6704 /* Run until signal received */
6705 while (1) {
6706 if (kthread_should_stop())
6707 break;
6708 if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
6709 /* Call bus dpc unless it indicated down
6710 (then clean stop) */
6711 if (bus->drvr->busstate != BRCMF_BUS_DOWN) {
6712 if (brcmf_sdbrcm_dpc(bus))
6713 complete(&bus->dpc_wait);
6714 } else {
6715 brcmf_sdbrcm_bus_stop(bus, true);
6716 }
6717 } else
6718 break;
6719 }
6720 return 0;
6721}
6722
6723static void brcmf_sdbrcm_dpc_tasklet(unsigned long data)
6724{
6725 struct brcmf_bus *bus = (struct brcmf_bus *) data;
6726
6727 /* Call bus dpc unless it indicated down (then clean stop) */
6728 if (bus->drvr->busstate != BRCMF_BUS_DOWN) {
6729 if (brcmf_sdbrcm_dpc(bus))
6730 tasklet_schedule(&bus->tasklet);
6731 } else
6732 brcmf_sdbrcm_bus_stop(bus, true);
6733}
6734
6735static void brcmf_sdbrcm_sched_dpc(struct brcmf_bus *bus)
6736{
6737 if (bus->dpc_tsk) {
6738 complete(&bus->dpc_wait);
6739 return;
6740 }
6741
6742 tasklet_schedule(&bus->tasklet);
6743}
6744
6745static void brcmf_sdbrcm_sdlock(struct brcmf_bus *bus)
6746{
6747 if (bus->threads_only)
6748 down(&bus->sdsem);
6749 else
6750 spin_lock_bh(&bus->sdlock);
6751}
6752
6753static void brcmf_sdbrcm_sdunlock(struct brcmf_bus *bus)
6754{
6755 if (bus->threads_only)
6756 up(&bus->sdsem);
6757 else
6758 spin_unlock_bh(&bus->sdlock);
6759}
6760
6761static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus)
6762{
6763 if (bus->firmware->size < bus->fw_ptr + len)
6764 len = bus->firmware->size - bus->fw_ptr;
6765
6766 memcpy(buf, &bus->firmware->data[bus->fw_ptr], len);
6767 bus->fw_ptr += len;
6768 return len;
6769}
6770
6771MODULE_FIRMWARE(BCM4329_FW_NAME);
6772MODULE_FIRMWARE(BCM4329_NV_NAME);
diff --git a/drivers/staging/brcm80211/brcmfmac/sdio_host.h b/drivers/staging/brcm80211/brcmfmac/sdio_host.h
new file mode 100644
index 00000000000..d3454721506
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/sdio_host.h
@@ -0,0 +1,347 @@
1/*
2 * Copyright (c) 2010 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#ifndef _BRCM_SDH_H_
18#define _BRCM_SDH_H_
19
20#include <linux/skbuff.h>
21extern const uint brcmf_sdio_msglevel;
22
23#define SDIO_FUNC_0 0
24#define SDIO_FUNC_1 1
25#define SDIO_FUNC_2 2
26
27#define SDIOD_FBR_SIZE 0x100
28
29/* io_en */
30#define SDIO_FUNC_ENABLE_1 0x02
31#define SDIO_FUNC_ENABLE_2 0x04
32
33/* io_rdys */
34#define SDIO_FUNC_READY_1 0x02
35#define SDIO_FUNC_READY_2 0x04
36
37/* intr_status */
38#define INTR_STATUS_FUNC1 0x2
39#define INTR_STATUS_FUNC2 0x4
40
41/* Maximum number of I/O funcs */
42#define SDIOD_MAX_IOFUNCS 7
43
44#define SBSDIO_NUM_FUNCTION 3 /* as of sdiod rev 0, supports 3 functions */
45
46/* function 1 miscellaneous registers */
47#define SBSDIO_SPROM_CS 0x10000 /* sprom command and status */
48#define SBSDIO_SPROM_INFO 0x10001 /* sprom info register */
49#define SBSDIO_SPROM_DATA_LOW 0x10002 /* sprom indirect access data byte 0 */
50#define SBSDIO_SPROM_DATA_HIGH 0x10003 /* sprom indirect access data byte 1 */
51#define SBSDIO_SPROM_ADDR_LOW 0x10004 /* sprom indirect access addr byte 0 */
52#define SBSDIO_SPROM_ADDR_HIGH 0x10005 /* sprom indirect access addr byte 0 */
53#define SBSDIO_CHIP_CTRL_DATA 0x10006 /* xtal_pu (gpio) output */
54#define SBSDIO_CHIP_CTRL_EN 0x10007 /* xtal_pu (gpio) enable */
55#define SBSDIO_WATERMARK 0x10008 /* rev < 7, watermark for sdio device */
56#define SBSDIO_DEVICE_CTL 0x10009 /* control busy signal generation */
57
58/* registers introduced in rev 8, some content (mask/bits) defs in sbsdpcmdev.h */
59#define SBSDIO_FUNC1_SBADDRLOW 0x1000A /* SB Address Window Low (b15) */
60#define SBSDIO_FUNC1_SBADDRMID 0x1000B /* SB Address Window Mid (b23:b16) */
61#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C /* SB Address Window High (b31:b24) */
62#define SBSDIO_FUNC1_FRAMECTRL 0x1000D /* Frame Control (frame term/abort) */
63#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E /* ChipClockCSR (ALP/HT ctl/status) */
64#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F /* SdioPullUp (on cmd, d0-d2) */
65#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 /* Write Frame Byte Count Low */
66#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A /* Write Frame Byte Count High */
67#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B /* Read Frame Byte Count Low */
68#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C /* Read Frame Byte Count High */
69
70#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
71#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */
72
73/* function 1 OCP space */
74#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF /* sb offset addr is <= 15 bits, 32k */
75#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000
76#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 /* with b15, maps to 32-bit SB access */
77
78/* some duplication with sbsdpcmdev.h here */
79/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
80#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */
81#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */
82#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */
83#define SBSDIO_SBWINDOW_MASK 0xffff8000 /* Address bits from SBADDR regs */
84
85#define SDIOH_READ 0 /* Read request */
86#define SDIOH_WRITE 1 /* Write request */
87
88#define SDIOH_DATA_FIX 0 /* Fixed addressing */
89#define SDIOH_DATA_INC 1 /* Incremental addressing */
90
91/* internal return code */
92#define SUCCESS 0
93#define ERROR 1
94
95/* forward declarations */
96struct brcmf_sdio_card;
97
98struct brcmf_sdreg {
99 int func;
100 int offset;
101 int value;
102};
103
104struct sdioh_info {
105 struct osl_info *osh; /* osh handler */
106 bool client_intr_enabled; /* interrupt connnected flag */
107 bool intr_handler_valid; /* client driver interrupt handler valid */
108 void (*intr_handler)(void *); /* registered interrupt handler */
109 void *intr_handler_arg; /* argument to call interrupt handler */
110 u16 intmask; /* Current active interrupts */
111 void *sdos_info; /* Pointer to per-OS private data */
112
113 uint irq; /* Client irq */
114 int intrcount; /* Client interrupts */
115 bool sd_blockmode; /* sd_blockmode == false => 64 Byte Cmd 53s. */
116 /* Must be on for sd_multiblock to be effective */
117 bool use_client_ints; /* If this is false, make sure to restore */
118 int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
119 u8 num_funcs; /* Supported funcs on client */
120 u32 com_cis_ptr;
121 u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
122 uint max_dma_len;
123 uint max_dma_descriptors; /* DMA Descriptors supported by this controller. */
124 /* SDDMA_DESCRIPTOR SGList[32]; *//* Scatter/Gather DMA List */
125};
126
127struct brcmf_sdmmc_instance {
128 struct sdioh_info *sd;
129 struct sdio_func *func[SDIOD_MAX_IOFUNCS];
130 u32 host_claimed;
131};
132
133/* Attach and build an interface to the underlying SD host driver.
134 * - Allocates resources (structs, arrays, mem, OS handles, etc) needed by
135 * brcmf_sdcard.
136 * - Returns the sdio card handle and virtual address base for register access.
137 * The returned handle should be used in all subsequent calls, but the bcmsh
138 * implementation may maintain a single "default" handle (e.g. the first or
139 * most recent one) to enable single-instance implementations to pass NULL.
140 */
141extern struct brcmf_sdio_card*
142brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq);
143
144/* Detach - freeup resources allocated in attach */
145extern int brcmf_sdcard_detach(struct brcmf_sdio_card *card);
146
147/* Enable/disable SD interrupt */
148extern int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card);
149extern int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card);
150
151/* Register/deregister device interrupt handler. */
152extern int
153brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
154 void (*fn)(void *), void *argh);
155
156extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card);
157
158/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
159 * fn: function number
160 * addr: unmodified SDIO-space address
161 * data: data byte to write
162 * err: pointer to error code (or NULL)
163 */
164extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint func,
165 u32 addr, int *err);
166extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint func,
167 u32 addr, u8 data, int *err);
168
169/* Read/Write 4bytes from/to cfg space */
170extern u32
171brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
172 u32 addr, int *err);
173
174extern void brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card,
175 uint fnc_num, u32 addr,
176 u32 data, int *err);
177
178/* Read CIS content for specified function.
179 * fn: function whose CIS is being requested (0 is common CIS)
180 * cis: pointer to memory location to place results
181 * length: number of bytes to read
182 * Internally, this routine uses the values from the cis base regs (0x9-0xB)
183 * to form an SDIO-space address to read the data from.
184 */
185extern int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func,
186 u8 *cis, uint length);
187
188/* Synchronous access to device (client) core registers via CMD53 to F1.
189 * addr: backplane address (i.e. >= regsva from attach)
190 * size: register width in bytes (2 or 4)
191 * data: data for register write
192 */
193extern u32
194brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size);
195
196extern u32
197brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
198 u32 data);
199
200/* Indicate if last reg read/write failed */
201extern bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card);
202
203/* Buffer transfer to/from device (client) core via cmd53.
204 * fn: function number
205 * addr: backplane address (i.e. >= regsva from attach)
206 * flags: backplane width, address increment, sync/async
207 * buf: pointer to memory data buffer
208 * nbytes: number of bytes to transfer to/from buf
209 * pkt: pointer to packet associated with buf (if any)
210 * complete: callback function for command completion (async only)
211 * handle: handle for completion callback (first arg in callback)
212 * Returns 0 or error code.
213 * NOTE: Async operation is not currently supported.
214 */
215extern int
216brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
217 uint flags, u8 *buf, uint nbytes, void *pkt,
218 void (*complete)(void *handle, int status,
219 bool sync_waiting),
220 void *handle);
221extern int
222brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
223 uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt,
224 void (*complete)(void *handle, int status,
225 bool sync_waiting),
226 void *handle);
227
228/* Flags bits */
229#define SDIO_REQ_4BYTE 0x1 /* Four-byte target (backplane) width (vs. two-byte) */
230#define SDIO_REQ_FIXED 0x2 /* Fixed address (FIFO) (vs. incrementing address) */
231#define SDIO_REQ_ASYNC 0x4 /* Async request (vs. sync request) */
232
233/* Pending (non-error) return code */
234#define BCME_PENDING 1
235
236/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
237 * rw: read or write (0/1)
238 * addr: direct SDIO address
239 * buf: pointer to memory data buffer
240 * nbytes: number of bytes to transfer to/from buf
241 * Returns 0 or error code.
242 */
243extern int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
244 u8 *buf, uint nbytes);
245
246/* Issue an abort to the specified function */
247extern int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn);
248
249/* Returns the "Device ID" of target device on the SDIO bus. */
250extern int brcmf_sdcard_query_device(struct brcmf_sdio_card *card);
251
252/* Miscellaneous knob tweaker. */
253extern int brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
254 void *params, int plen, void *arg, int len,
255 bool set);
256
257/* helper functions */
258
259/* callback functions */
260struct brcmf_sdioh_driver {
261 /* attach to device */
262 void *(*attach) (u16 vend_id, u16 dev_id, u16 bus, u16 slot,
263 u16 func, uint bustype, u32 regsva, void *param);
264 /* detach from device */
265 void (*detach) (void *ch);
266};
267
268struct sdioh_info;
269
270/* platform specific/high level functions */
271extern int brcmf_sdio_function_init(void);
272extern int brcmf_sdio_register(struct brcmf_sdioh_driver *driver);
273extern void brcmf_sdio_unregister(void);
274extern void brcmf_sdio_function_cleanup(void);
275extern int brcmf_sdio_probe(struct device *dev);
276extern int brcmf_sdio_remove(struct device *dev);
277
278/* Function to return current window addr */
279extern u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card);
280
281/* Allocate/init/free per-OS private data */
282extern int brcmf_sdioh_osinit(struct sdioh_info *sd);
283extern void brcmf_sdioh_osfree(struct sdioh_info *sd);
284
285/* Core interrupt enable/disable of device interrupts */
286extern void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd);
287extern void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd);
288
289/* attach, return handler on success, NULL if failed.
290 * The handler shall be provided by all subsequent calls. No local cache
291 * cfghdl points to the starting address of pci device mapped memory
292 */
293extern struct sdioh_info *brcmf_sdioh_attach(void *cfghdl, uint irq);
294extern int brcmf_sdioh_detach(struct sdioh_info *si);
295
296extern int
297brcmf_sdioh_interrupt_register(struct sdioh_info *si,
298 void (*sdioh_cb_fn)(void *), void *argh);
299
300extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *si);
301
302/* enable or disable SD interrupt */
303extern int
304brcmf_sdioh_interrupt_set(struct sdioh_info *si, bool enable_disable);
305
306/* read or write one byte using cmd52 */
307extern int
308brcmf_sdioh_request_byte(struct sdioh_info *si, uint rw, uint fnc, uint addr,
309 u8 *byte);
310
311/* read or write 2/4 bytes using cmd53 */
312extern int
313brcmf_sdioh_request_word(struct sdioh_info *si, uint cmd_type,
314 uint rw, uint fnc, uint addr,
315 u32 *word, uint nbyte);
316
317/* read or write any buffer using cmd53 */
318extern int
319brcmf_sdioh_request_buffer(struct sdioh_info *si, uint pio_dma,
320 uint fix_inc, uint rw, uint fnc_num,
321 u32 addr, uint regwidth,
322 u32 buflen, u8 *buffer, struct sk_buff *pkt);
323
324/* get cis data */
325extern int
326brcmf_sdioh_cis_read(struct sdioh_info *si, uint fuc, u8 *cis, u32 length);
327
328extern int
329brcmf_sdioh_cfg_read(struct sdioh_info *si, uint fuc, u32 addr, u8 *data);
330extern int
331brcmf_sdioh_cfg_write(struct sdioh_info *si, uint fuc, u32 addr, u8 *data);
332
333/* handle iovars */
334extern int brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
335 void *params, int plen, void *arg, int len, bool set);
336
337/* Issue abort to the specified function and clear controller as needed */
338extern int brcmf_sdioh_abort(struct sdioh_info *si, uint fnc);
339
340/* Watchdog timer interface for pm ops */
341extern void brcmf_sdio_wdtmr_enable(bool enable);
342
343extern uint sd_msglevel; /* Debug message level */
344
345extern struct brcmf_sdmmc_instance *gInstance;
346
347#endif /* _BRCM_SDH_H_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
new file mode 100644
index 00000000000..821206d3e53
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
@@ -0,0 +1,4152 @@
1/*
2 * Copyright (c) 2010 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#include <linux/kernel.h>
18#include <linux/if_arp.h>
19#include <linux/sched.h>
20#include <linux/kthread.h>
21#include <linux/netdevice.h>
22#include <linux/sched.h>
23#include <linux/etherdevice.h>
24#include <linux/wireless.h>
25#include <linux/ieee80211.h>
26#include <linux/mmc/sdio_func.h>
27#include <linux/uaccess.h>
28#include <net/cfg80211.h>
29#include <net/rtnetlink.h>
30
31#include <brcmu_utils.h>
32#include <defs.h>
33#include <brcmu_wifi.h>
34#include "dhd.h"
35#include "wl_cfg80211.h"
36
37static struct sdio_func *cfg80211_sdio_func;
38static struct brcmf_cfg80211_dev *cfg80211_dev;
39static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
40
41u32 brcmf_dbg_level = WL_DBG_ERR;
42
43/*
44** cfg80211_ops api/callback list
45*/
46static s32 brcmf_cfg80211_change_iface(struct wiphy *wiphy,
47 struct net_device *ndev,
48 enum nl80211_iftype type, u32 *flags,
49 struct vif_params *params);
50static s32 __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
51 struct cfg80211_scan_request *request,
52 struct cfg80211_ssid *this_ssid);
53static s32 brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
54 struct cfg80211_scan_request *request);
55static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
56static s32 brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
57 struct cfg80211_ibss_params *params);
58static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy,
59 struct net_device *dev);
60static s32 brcmf_cfg80211_get_station(struct wiphy *wiphy,
61 struct net_device *dev, u8 *mac,
62 struct station_info *sinfo);
63static s32 brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy,
64 struct net_device *dev, bool enabled,
65 s32 timeout);
66static s32 brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
67 struct net_device *dev,
68 const u8 *addr,
69 const struct cfg80211_bitrate_mask
70 *mask);
71static int brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
72 struct cfg80211_connect_params *sme);
73static s32 brcmf_cfg80211_disconnect(struct wiphy *wiphy,
74 struct net_device *dev,
75 u16 reason_code);
76static s32 brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
77 enum nl80211_tx_power_setting type,
78 s32 dbm);
79static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
80static s32 brcmf_cfg80211_config_default_key(struct wiphy *wiphy,
81 struct net_device *dev, u8 key_idx,
82 bool unicast, bool multicast);
83static s32 brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
84 u8 key_idx, bool pairwise, const u8 *mac_addr,
85 struct key_params *params);
86static s32 brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
87 u8 key_idx, bool pairwise, const u8 *mac_addr);
88static s32 brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
89 u8 key_idx, bool pairwise, const u8 *mac_addr,
90 void *cookie, void (*callback) (void *cookie,
91 struct
92 key_params *
93 params));
94static s32 brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
95 struct net_device *dev,
96 u8 key_idx);
97static s32 brcmf_cfg80211_resume(struct wiphy *wiphy);
98static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
99 struct cfg80211_wowlan *wow);
100static s32 brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
101 struct cfg80211_pmksa *pmksa);
102static s32 brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
103 struct cfg80211_pmksa *pmksa);
104static s32 brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy,
105 struct net_device *dev);
106/*
107** event & event Q handlers for cfg80211 interfaces
108*/
109static s32 brcmf_create_event_handler(struct brcmf_cfg80211_priv *cfg_priv);
110static void brcmf_destroy_event_handler(struct brcmf_cfg80211_priv *cfg_priv);
111static s32 brcmf_event_handler(void *data);
112static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv);
113static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv);
114static void brcmf_lock_eq(struct brcmf_cfg80211_priv *cfg_priv);
115static void brcmf_unlock_eq(struct brcmf_cfg80211_priv *cfg_priv);
116static void brcmf_init_eq_lock(struct brcmf_cfg80211_priv *cfg_priv);
117static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el);
118static struct brcmf_cfg80211_event_q *
119brcmf_deq_event(struct brcmf_cfg80211_priv *cfg_priv);
120static s32 brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 type,
121 const struct brcmf_event_msg *msg, void *data);
122static void brcmf_put_event(struct brcmf_cfg80211_event_q *e);
123static void brcmf_wakeup_event(struct brcmf_cfg80211_priv *cfg_priv);
124static s32 brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
125 struct net_device *ndev,
126 const struct brcmf_event_msg *e,
127 void *data);
128static s32 brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
129 struct net_device *ndev,
130 const struct brcmf_event_msg *e,
131 void *data);
132static s32 brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
133 struct net_device *ndev,
134 const struct brcmf_event_msg *e,
135 void *data);
136static s32 brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
137 struct net_device *ndev,
138 const struct brcmf_event_msg *e, void *data,
139 bool completed);
140static s32 brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
141 struct net_device *ndev,
142 const struct brcmf_event_msg *e, void *data);
143static s32 brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
144 struct net_device *ndev,
145 const struct brcmf_event_msg *e, void *data);
146
147/*
148** register/deregister sdio function
149*/
150static void brcmf_clear_sdio_func(void);
151
152/*
153** ioctl utilites
154*/
155static s32 brcmf_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
156 s32 buf_len);
157static __used s32 brcmf_dev_bufvar_set(struct net_device *dev, s8 *name,
158 s8 *buf, s32 len);
159static s32 brcmf_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
160static s32 brcmf_dev_intvar_get(struct net_device *dev, s8 *name,
161 s32 *retval);
162static s32 brcmf_dev_ioctl(struct net_device *dev, u32 cmd, void *arg,
163 u32 len);
164
165/*
166** cfg80211 set_wiphy_params utilities
167*/
168static s32 brcmf_set_frag(struct net_device *dev, u32 frag_threshold);
169static s32 brcmf_set_rts(struct net_device *dev, u32 frag_threshold);
170static s32 brcmf_set_retry(struct net_device *dev, u32 retry, bool l);
171
172/*
173** wl profile utilities
174*/
175static s32 brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
176 const struct brcmf_event_msg *e,
177 void *data, s32 item);
178static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item);
179static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof);
180
181/*
182** cfg80211 connect utilites
183*/
184static s32 brcmf_set_wpa_version(struct net_device *dev,
185 struct cfg80211_connect_params *sme);
186static s32 brcmf_set_auth_type(struct net_device *dev,
187 struct cfg80211_connect_params *sme);
188static s32 brcmf_set_set_cipher(struct net_device *dev,
189 struct cfg80211_connect_params *sme);
190static s32 brcmf_set_key_mgmt(struct net_device *dev,
191 struct cfg80211_connect_params *sme);
192static s32 brcmf_set_set_sharedkey(struct net_device *dev,
193 struct cfg80211_connect_params *sme);
194static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv);
195static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv);
196static void brcmf_ch_to_chanspec(int ch,
197 struct brcmf_join_params *join_params, size_t *join_params_size);
198
199/*
200** information element utilities
201*/
202static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
203 u8 t, u8 l, u8 *v);
204static s32 brcmf_mode_to_nl80211_iftype(s32 mode);
205static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
206 struct device *dev);
207static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv);
208static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv);
209static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
210 struct brcmf_bss_info *bi);
211static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv);
212static s32 brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
213 u8 key_idx, const u8 *mac_addr,
214 struct key_params *params);
215
216/*
217** key indianess swap utilities
218*/
219static void swap_key_from_BE(struct brcmf_wsec_key *key);
220static void swap_key_to_BE(struct brcmf_wsec_key *key);
221
222/*
223** brcmf_cfg80211_priv memory init/deinit utilities
224*/
225static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv);
226static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv);
227
228static void brcmf_delay(u32 ms);
229
230/*
231** store/restore cfg80211 instance data
232*/
233static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data);
234static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev);
235
236/*
237** ibss mode utilities
238*/
239static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv);
240
241/*
242** dongle up/down , default configuration utilities
243*/
244static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
245 const struct brcmf_event_msg *e);
246static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
247 const struct brcmf_event_msg *e);
248static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
249 const struct brcmf_event_msg *e);
250static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv);
251static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype);
252static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv);
253static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv);
254static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv);
255static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf);
256
257/*
258** dongle configuration utilities
259*/
260static s32 brcmf_dongle_eventmsg(struct net_device *ndev);
261static s32 brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
262 s32 scan_unassoc_time, s32 scan_passive_time);
263static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv,
264 bool need_lock);
265static s32 brcmf_dongle_roam(struct net_device *ndev, u32 roamvar,
266 u32 bcn_timeout);
267
268/*
269** iscan handler
270*/
271static void brcmf_iscan_timer(unsigned long data);
272static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv);
273static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv);
274static s32 brcmf_iscan_thread(void *data);
275static s32 brcmf_dev_iovar_setbuf(struct net_device *dev, s8 *iovar,
276 void *param, s32 paramlen, void *bufptr,
277 s32 buflen);
278static s32 brcmf_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
279 void *param, s32 paramlen, void *bufptr,
280 s32 buflen);
281static s32 brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
282 struct brcmf_ssid *ssid, u16 action);
283static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv);
284static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan);
285static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv);
286static s32 brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan,
287 u32 *status,
288 struct brcmf_scan_results **bss_list);
289static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
290 bool aborted);
291static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el);
292static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv);
293static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv);
294static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv);
295static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv);
296
297/*
298* find most significant bit set
299*/
300static __used u32 brcmf_find_msb(u16 bit16);
301
302/*
303* update pmklist to dongle
304*/
305static __used s32 brcmf_update_pmklist(struct net_device *dev,
306 struct brcmf_cfg80211_pmk_list *pmk_list,
307 s32 err);
308
309static void brcmf_set_mpc(struct net_device *ndev, int mpc);
310
311/*
312* debufs support
313*/
314static int
315brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv);
316static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv);
317
318#define WL_PRIV_GET() \
319 ({ \
320 struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg80211_dev); \
321 if (unlikely(!ci)) { \
322 WL_ERR("wl_cfg80211_dev is unavailable\n"); \
323 BUG(); \
324 } \
325 ci->cfg_priv; \
326})
327
328#define CHECK_SYS_UP() \
329do { \
330 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); \
331 if (unlikely(!test_bit(WL_STATUS_READY, &cfg_priv->status))) { \
332 WL_INFO("device is not ready : status (%d)\n", \
333 (int)cfg_priv->status); \
334 return -EIO; \
335 } \
336} while (0)
337
338#define CHAN2G(_channel, _freq, _flags) { \
339 .band = IEEE80211_BAND_2GHZ, \
340 .center_freq = (_freq), \
341 .hw_value = (_channel), \
342 .flags = (_flags), \
343 .max_antenna_gain = 0, \
344 .max_power = 30, \
345}
346
347#define CHAN5G(_channel, _flags) { \
348 .band = IEEE80211_BAND_5GHZ, \
349 .center_freq = 5000 + (5 * (_channel)), \
350 .hw_value = (_channel), \
351 .flags = (_flags), \
352 .max_antenna_gain = 0, \
353 .max_power = 30, \
354}
355
356#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
357#define RATETAB_ENT(_rateid, _flags) \
358 { \
359 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
360 .hw_value = (_rateid), \
361 .flags = (_flags), \
362 }
363
364static struct ieee80211_rate __wl_rates[] = {
365 RATETAB_ENT(BRCM_RATE_1M, 0),
366 RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
367 RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
368 RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
369 RATETAB_ENT(BRCM_RATE_6M, 0),
370 RATETAB_ENT(BRCM_RATE_9M, 0),
371 RATETAB_ENT(BRCM_RATE_12M, 0),
372 RATETAB_ENT(BRCM_RATE_18M, 0),
373 RATETAB_ENT(BRCM_RATE_24M, 0),
374 RATETAB_ENT(BRCM_RATE_36M, 0),
375 RATETAB_ENT(BRCM_RATE_48M, 0),
376 RATETAB_ENT(BRCM_RATE_54M, 0),
377};
378
379#define wl_a_rates (__wl_rates + 4)
380#define wl_a_rates_size 8
381#define wl_g_rates (__wl_rates + 0)
382#define wl_g_rates_size 12
383
384static struct ieee80211_channel __wl_2ghz_channels[] = {
385 CHAN2G(1, 2412, 0),
386 CHAN2G(2, 2417, 0),
387 CHAN2G(3, 2422, 0),
388 CHAN2G(4, 2427, 0),
389 CHAN2G(5, 2432, 0),
390 CHAN2G(6, 2437, 0),
391 CHAN2G(7, 2442, 0),
392 CHAN2G(8, 2447, 0),
393 CHAN2G(9, 2452, 0),
394 CHAN2G(10, 2457, 0),
395 CHAN2G(11, 2462, 0),
396 CHAN2G(12, 2467, 0),
397 CHAN2G(13, 2472, 0),
398 CHAN2G(14, 2484, 0),
399};
400
401static struct ieee80211_channel __wl_5ghz_a_channels[] = {
402 CHAN5G(34, 0), CHAN5G(36, 0),
403 CHAN5G(38, 0), CHAN5G(40, 0),
404 CHAN5G(42, 0), CHAN5G(44, 0),
405 CHAN5G(46, 0), CHAN5G(48, 0),
406 CHAN5G(52, 0), CHAN5G(56, 0),
407 CHAN5G(60, 0), CHAN5G(64, 0),
408 CHAN5G(100, 0), CHAN5G(104, 0),
409 CHAN5G(108, 0), CHAN5G(112, 0),
410 CHAN5G(116, 0), CHAN5G(120, 0),
411 CHAN5G(124, 0), CHAN5G(128, 0),
412 CHAN5G(132, 0), CHAN5G(136, 0),
413 CHAN5G(140, 0), CHAN5G(149, 0),
414 CHAN5G(153, 0), CHAN5G(157, 0),
415 CHAN5G(161, 0), CHAN5G(165, 0),
416 CHAN5G(184, 0), CHAN5G(188, 0),
417 CHAN5G(192, 0), CHAN5G(196, 0),
418 CHAN5G(200, 0), CHAN5G(204, 0),
419 CHAN5G(208, 0), CHAN5G(212, 0),
420 CHAN5G(216, 0),
421};
422
423static struct ieee80211_channel __wl_5ghz_n_channels[] = {
424 CHAN5G(32, 0), CHAN5G(34, 0),
425 CHAN5G(36, 0), CHAN5G(38, 0),
426 CHAN5G(40, 0), CHAN5G(42, 0),
427 CHAN5G(44, 0), CHAN5G(46, 0),
428 CHAN5G(48, 0), CHAN5G(50, 0),
429 CHAN5G(52, 0), CHAN5G(54, 0),
430 CHAN5G(56, 0), CHAN5G(58, 0),
431 CHAN5G(60, 0), CHAN5G(62, 0),
432 CHAN5G(64, 0), CHAN5G(66, 0),
433 CHAN5G(68, 0), CHAN5G(70, 0),
434 CHAN5G(72, 0), CHAN5G(74, 0),
435 CHAN5G(76, 0), CHAN5G(78, 0),
436 CHAN5G(80, 0), CHAN5G(82, 0),
437 CHAN5G(84, 0), CHAN5G(86, 0),
438 CHAN5G(88, 0), CHAN5G(90, 0),
439 CHAN5G(92, 0), CHAN5G(94, 0),
440 CHAN5G(96, 0), CHAN5G(98, 0),
441 CHAN5G(100, 0), CHAN5G(102, 0),
442 CHAN5G(104, 0), CHAN5G(106, 0),
443 CHAN5G(108, 0), CHAN5G(110, 0),
444 CHAN5G(112, 0), CHAN5G(114, 0),
445 CHAN5G(116, 0), CHAN5G(118, 0),
446 CHAN5G(120, 0), CHAN5G(122, 0),
447 CHAN5G(124, 0), CHAN5G(126, 0),
448 CHAN5G(128, 0), CHAN5G(130, 0),
449 CHAN5G(132, 0), CHAN5G(134, 0),
450 CHAN5G(136, 0), CHAN5G(138, 0),
451 CHAN5G(140, 0), CHAN5G(142, 0),
452 CHAN5G(144, 0), CHAN5G(145, 0),
453 CHAN5G(146, 0), CHAN5G(147, 0),
454 CHAN5G(148, 0), CHAN5G(149, 0),
455 CHAN5G(150, 0), CHAN5G(151, 0),
456 CHAN5G(152, 0), CHAN5G(153, 0),
457 CHAN5G(154, 0), CHAN5G(155, 0),
458 CHAN5G(156, 0), CHAN5G(157, 0),
459 CHAN5G(158, 0), CHAN5G(159, 0),
460 CHAN5G(160, 0), CHAN5G(161, 0),
461 CHAN5G(162, 0), CHAN5G(163, 0),
462 CHAN5G(164, 0), CHAN5G(165, 0),
463 CHAN5G(166, 0), CHAN5G(168, 0),
464 CHAN5G(170, 0), CHAN5G(172, 0),
465 CHAN5G(174, 0), CHAN5G(176, 0),
466 CHAN5G(178, 0), CHAN5G(180, 0),
467 CHAN5G(182, 0), CHAN5G(184, 0),
468 CHAN5G(186, 0), CHAN5G(188, 0),
469 CHAN5G(190, 0), CHAN5G(192, 0),
470 CHAN5G(194, 0), CHAN5G(196, 0),
471 CHAN5G(198, 0), CHAN5G(200, 0),
472 CHAN5G(202, 0), CHAN5G(204, 0),
473 CHAN5G(206, 0), CHAN5G(208, 0),
474 CHAN5G(210, 0), CHAN5G(212, 0),
475 CHAN5G(214, 0), CHAN5G(216, 0),
476 CHAN5G(218, 0), CHAN5G(220, 0),
477 CHAN5G(222, 0), CHAN5G(224, 0),
478 CHAN5G(226, 0), CHAN5G(228, 0),
479};
480
481static struct ieee80211_supported_band __wl_band_2ghz = {
482 .band = IEEE80211_BAND_2GHZ,
483 .channels = __wl_2ghz_channels,
484 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
485 .bitrates = wl_g_rates,
486 .n_bitrates = wl_g_rates_size,
487};
488
489static struct ieee80211_supported_band __wl_band_5ghz_a = {
490 .band = IEEE80211_BAND_5GHZ,
491 .channels = __wl_5ghz_a_channels,
492 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
493 .bitrates = wl_a_rates,
494 .n_bitrates = wl_a_rates_size,
495};
496
497static struct ieee80211_supported_band __wl_band_5ghz_n = {
498 .band = IEEE80211_BAND_5GHZ,
499 .channels = __wl_5ghz_n_channels,
500 .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
501 .bitrates = wl_a_rates,
502 .n_bitrates = wl_a_rates_size,
503};
504
505static const u32 __wl_cipher_suites[] = {
506 WLAN_CIPHER_SUITE_WEP40,
507 WLAN_CIPHER_SUITE_WEP104,
508 WLAN_CIPHER_SUITE_TKIP,
509 WLAN_CIPHER_SUITE_CCMP,
510 WLAN_CIPHER_SUITE_AES_CMAC,
511};
512
513static void swap_key_from_BE(struct brcmf_wsec_key *key)
514{
515 key->index = cpu_to_le32(key->index);
516 key->len = cpu_to_le32(key->len);
517 key->algo = cpu_to_le32(key->algo);
518 key->flags = cpu_to_le32(key->flags);
519 key->rxiv.hi = cpu_to_le32(key->rxiv.hi);
520 key->rxiv.lo = cpu_to_le16(key->rxiv.lo);
521 key->iv_initialized = cpu_to_le32(key->iv_initialized);
522}
523
524static void swap_key_to_BE(struct brcmf_wsec_key *key)
525{
526 key->index = le32_to_cpu(key->index);
527 key->len = le32_to_cpu(key->len);
528 key->algo = le32_to_cpu(key->algo);
529 key->flags = le32_to_cpu(key->flags);
530 key->rxiv.hi = le32_to_cpu(key->rxiv.hi);
531 key->rxiv.lo = le16_to_cpu(key->rxiv.lo);
532 key->iv_initialized = le32_to_cpu(key->iv_initialized);
533}
534
535static s32
536brcmf_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
537{
538 struct ifreq ifr;
539 struct brcmf_ioctl ioc;
540 mm_segment_t fs;
541 s32 err = 0;
542
543 memset(&ioc, 0, sizeof(ioc));
544 ioc.cmd = cmd;
545 ioc.buf = arg;
546 ioc.len = len;
547 strcpy(ifr.ifr_name, dev->name);
548 ifr.ifr_data = (caddr_t)&ioc;
549
550 fs = get_fs();
551 set_fs(get_ds());
552 err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
553 set_fs(fs);
554
555 return err;
556}
557
558static s32
559brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
560 enum nl80211_iftype type, u32 *flags,
561 struct vif_params *params)
562{
563 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
564 struct wireless_dev *wdev;
565 s32 infra = 0;
566 s32 err = 0;
567
568 WL_TRACE("Enter\n");
569 CHECK_SYS_UP();
570
571 switch (type) {
572 case NL80211_IFTYPE_MONITOR:
573 case NL80211_IFTYPE_WDS:
574 WL_ERR("type (%d) : currently we do not support this type\n",
575 type);
576 return -EOPNOTSUPP;
577 case NL80211_IFTYPE_ADHOC:
578 cfg_priv->conf->mode = WL_MODE_IBSS;
579 infra = 0;
580 break;
581 case NL80211_IFTYPE_STATION:
582 cfg_priv->conf->mode = WL_MODE_BSS;
583 infra = 1;
584 break;
585 default:
586 err = -EINVAL;
587 goto done;
588 }
589
590 infra = cpu_to_le32(infra);
591 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_INFRA, &infra, sizeof(infra));
592 if (unlikely(err)) {
593 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
594 err = -EAGAIN;
595 } else {
596 wdev = ndev->ieee80211_ptr;
597 wdev->iftype = type;
598 }
599
600 WL_INFO("IF Type = %s\n",
601 (cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra");
602
603done:
604 WL_TRACE("Exit\n");
605
606 return err;
607}
608
609static void wl_iscan_prep(struct brcmf_scan_params *params,
610 struct brcmf_ssid *ssid)
611{
612 memcpy(params->bssid, ether_bcast, ETH_ALEN);
613 params->bss_type = DOT11_BSSTYPE_ANY;
614 params->scan_type = 0;
615 params->nprobes = -1;
616 params->active_time = -1;
617 params->passive_time = -1;
618 params->home_time = -1;
619 params->channel_num = 0;
620
621 params->nprobes = cpu_to_le32(params->nprobes);
622 params->active_time = cpu_to_le32(params->active_time);
623 params->passive_time = cpu_to_le32(params->passive_time);
624 params->home_time = cpu_to_le32(params->home_time);
625 if (ssid && ssid->SSID_len)
626 memcpy(&params->ssid, ssid, sizeof(struct brcmf_ssid));
627
628}
629
630static s32
631brcmf_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
632 s32 paramlen, void *bufptr, s32 buflen)
633{
634 s32 iolen;
635
636 iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
637 BUG_ON(!iolen);
638
639 return brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, bufptr, iolen);
640}
641
642static s32
643brcmf_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
644 s32 paramlen, void *bufptr, s32 buflen)
645{
646 s32 iolen;
647
648 iolen = brcmu_mkiovar(iovar, param, paramlen, bufptr, buflen);
649 BUG_ON(!iolen);
650
651 return brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, bufptr, buflen);
652}
653
654static s32
655brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
656 struct brcmf_ssid *ssid, u16 action)
657{
658 s32 params_size = (BRCMF_SCAN_PARAMS_FIXED_SIZE +
659 offsetof(struct brcmf_iscan_params, params));
660 struct brcmf_iscan_params *params;
661 s32 err = 0;
662
663 if (ssid && ssid->SSID_len)
664 params_size += sizeof(struct brcmf_ssid);
665 params = kzalloc(params_size, GFP_KERNEL);
666 if (unlikely(!params))
667 return -ENOMEM;
668 BUG_ON(params_size >= BRCMF_C_IOCTL_SMLEN);
669
670 wl_iscan_prep(&params->params, ssid);
671
672 params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
673 params->action = cpu_to_le16(action);
674 params->scan_duration = cpu_to_le16(0);
675
676 /* params_size += offsetof(struct brcmf_iscan_params, params); */
677 err = brcmf_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
678 iscan->ioctl_buf, BRCMF_C_IOCTL_SMLEN);
679 if (unlikely(err)) {
680 if (err == -EBUSY) {
681 WL_INFO("system busy : iscan canceled\n");
682 } else {
683 WL_ERR("error (%d)\n", err);
684 }
685 }
686 kfree(params);
687 return err;
688}
689
690static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
691{
692 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
693 struct net_device *ndev = cfg_to_ndev(cfg_priv);
694 struct brcmf_ssid ssid;
695 s32 passive_scan;
696 s32 err = 0;
697
698 /* Broadcast scan by default */
699 memset(&ssid, 0, sizeof(ssid));
700
701 iscan->state = WL_ISCAN_STATE_SCANING;
702
703 passive_scan = cfg_priv->active_scan ? 0 : 1;
704 err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
705 &passive_scan, sizeof(passive_scan));
706 if (unlikely(err)) {
707 WL_ERR("error (%d)\n", err);
708 return err;
709 }
710 brcmf_set_mpc(ndev, 0);
711 cfg_priv->iscan_kickstart = true;
712 brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
713 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
714 iscan->timer_on = 1;
715
716 return err;
717}
718
719static s32
720__brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
721 struct cfg80211_scan_request *request,
722 struct cfg80211_ssid *this_ssid)
723{
724 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
725 struct cfg80211_ssid *ssids;
726 struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
727 s32 passive_scan;
728 bool iscan_req;
729 bool spec_scan;
730 s32 err = 0;
731
732 if (unlikely(test_bit(WL_STATUS_SCANNING, &cfg_priv->status))) {
733 WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
734 return -EAGAIN;
735 }
736 if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status))) {
737 WL_ERR("Scanning being aborted : status (%lu)\n",
738 cfg_priv->status);
739 return -EAGAIN;
740 }
741 if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
742 WL_ERR("Connecting : status (%lu)\n",
743 cfg_priv->status);
744 return -EAGAIN;
745 }
746
747 iscan_req = false;
748 spec_scan = false;
749 if (request) {
750 /* scan bss */
751 ssids = request->ssids;
752 if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len))
753 iscan_req = true;
754 } else {
755 /* scan in ibss */
756 /* we don't do iscan in ibss */
757 ssids = this_ssid;
758 }
759
760 cfg_priv->scan_request = request;
761 set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
762 if (iscan_req) {
763 err = brcmf_do_iscan(cfg_priv);
764 if (likely(!err))
765 return err;
766 else
767 goto scan_out;
768 } else {
769 WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
770 ssids->ssid, ssids->ssid_len);
771 memset(&sr->ssid, 0, sizeof(sr->ssid));
772 sr->ssid.SSID_len =
773 min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
774 if (sr->ssid.SSID_len) {
775 memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
776 sr->ssid.SSID_len = cpu_to_le32(sr->ssid.SSID_len);
777 spec_scan = true;
778 } else {
779 WL_SCAN("Broadcast scan\n");
780 }
781
782 passive_scan = cfg_priv->active_scan ? 0 : 1;
783 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_PASSIVE_SCAN,
784 &passive_scan, sizeof(passive_scan));
785 if (unlikely(err)) {
786 WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
787 goto scan_out;
788 }
789 brcmf_set_mpc(ndev, 0);
790 err = brcmf_dev_ioctl(ndev, BRCMF_C_SCAN, &sr->ssid,
791 sizeof(sr->ssid));
792 if (err) {
793 if (err == -EBUSY) {
794 WL_INFO("system busy : scan for \"%s\" canceled\n",
795 sr->ssid.SSID);
796 } else {
797 WL_ERR("WLC_SCAN error (%d)\n", err);
798 }
799 brcmf_set_mpc(ndev, 1);
800 goto scan_out;
801 }
802 }
803
804 return 0;
805
806scan_out:
807 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
808 cfg_priv->scan_request = NULL;
809 return err;
810}
811
812static s32
813brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
814 struct cfg80211_scan_request *request)
815{
816 s32 err = 0;
817
818 WL_TRACE("Enter\n");
819
820 CHECK_SYS_UP();
821
822 err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL);
823 if (unlikely(err))
824 WL_ERR("scan error (%d)\n", err);
825
826 WL_TRACE("Exit\n");
827 return err;
828}
829
830static s32 brcmf_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
831{
832 s8 buf[BRCMF_C_IOCTL_SMLEN];
833 u32 len;
834 s32 err = 0;
835
836 val = cpu_to_le32(val);
837 len = brcmu_mkiovar(name, (char *)(&val), sizeof(val), buf,
838 sizeof(buf));
839 BUG_ON(!len);
840
841 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, buf, len);
842 if (unlikely(err))
843 WL_ERR("error (%d)\n", err);
844
845 return err;
846}
847
848static s32
849brcmf_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
850{
851 union {
852 s8 buf[BRCMF_C_IOCTL_SMLEN];
853 s32 val;
854 } var;
855 u32 len;
856 u32 data_null;
857 s32 err = 0;
858
859 len =
860 brcmu_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
861 sizeof(var.buf));
862 BUG_ON(!len);
863 err = brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, &var, len);
864 if (unlikely(err))
865 WL_ERR("error (%d)\n", err);
866
867 *retval = le32_to_cpu(var.val);
868
869 return err;
870}
871
872static s32 brcmf_set_rts(struct net_device *dev, u32 rts_threshold)
873{
874 s32 err = 0;
875
876 err = brcmf_dev_intvar_set(dev, "rtsthresh", rts_threshold);
877 if (unlikely(err))
878 WL_ERR("Error (%d)\n", err);
879
880 return err;
881}
882
883static s32 brcmf_set_frag(struct net_device *dev, u32 frag_threshold)
884{
885 s32 err = 0;
886
887 err = brcmf_dev_intvar_set(dev, "fragthresh", frag_threshold);
888 if (unlikely(err))
889 WL_ERR("Error (%d)\n", err);
890
891 return err;
892}
893
894static s32 brcmf_set_retry(struct net_device *dev, u32 retry, bool l)
895{
896 s32 err = 0;
897 u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
898
899 retry = cpu_to_le32(retry);
900 err = brcmf_dev_ioctl(dev, cmd, &retry, sizeof(retry));
901 if (unlikely(err)) {
902 WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
903 return err;
904 }
905 return err;
906}
907
908static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
909{
910 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
911 struct net_device *ndev = cfg_to_ndev(cfg_priv);
912 s32 err = 0;
913
914 WL_TRACE("Enter\n");
915 CHECK_SYS_UP();
916
917 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
918 (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) {
919 cfg_priv->conf->rts_threshold = wiphy->rts_threshold;
920 err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold);
921 if (!err)
922 goto done;
923 }
924 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
925 (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) {
926 cfg_priv->conf->frag_threshold = wiphy->frag_threshold;
927 err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold);
928 if (!err)
929 goto done;
930 }
931 if (changed & WIPHY_PARAM_RETRY_LONG
932 && (cfg_priv->conf->retry_long != wiphy->retry_long)) {
933 cfg_priv->conf->retry_long = wiphy->retry_long;
934 err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true);
935 if (!err)
936 goto done;
937 }
938 if (changed & WIPHY_PARAM_RETRY_SHORT
939 && (cfg_priv->conf->retry_short != wiphy->retry_short)) {
940 cfg_priv->conf->retry_short = wiphy->retry_short;
941 err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false);
942 if (!err)
943 goto done;
944 }
945
946done:
947 WL_TRACE("Exit\n");
948 return err;
949}
950
951static s32
952brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
953 struct cfg80211_ibss_params *params)
954{
955 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
956 struct brcmf_join_params join_params;
957 size_t join_params_size = 0;
958 s32 err = 0;
959 s32 wsec = 0;
960 s32 bcnprd;
961
962 WL_TRACE("Enter\n");
963 CHECK_SYS_UP();
964
965 if (params->ssid)
966 WL_CONN("SSID: %s\n", params->ssid);
967 else {
968 WL_CONN("SSID: NULL, Not supported\n");
969 return -EOPNOTSUPP;
970 }
971
972 set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
973
974 if (params->bssid)
975 WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n",
976 params->bssid[0], params->bssid[1], params->bssid[2],
977 params->bssid[3], params->bssid[4], params->bssid[5]);
978 else
979 WL_CONN("No BSSID specified\n");
980
981 if (params->channel)
982 WL_CONN("channel: %d\n", params->channel->center_freq);
983 else
984 WL_CONN("no channel specified\n");
985
986 if (params->channel_fixed)
987 WL_CONN("fixed channel required\n");
988 else
989 WL_CONN("no fixed channel required\n");
990
991 if (params->ie && params->ie_len)
992 WL_CONN("ie len: %d\n", params->ie_len);
993 else
994 WL_CONN("no ie specified\n");
995
996 if (params->beacon_interval)
997 WL_CONN("beacon interval: %d\n", params->beacon_interval);
998 else
999 WL_CONN("no beacon interval specified\n");
1000
1001 if (params->basic_rates)
1002 WL_CONN("basic rates: %08X\n", params->basic_rates);
1003 else
1004 WL_CONN("no basic rates specified\n");
1005
1006 if (params->privacy)
1007 WL_CONN("privacy required\n");
1008 else
1009 WL_CONN("no privacy required\n");
1010
1011 /* Configure Privacy for starter */
1012 if (params->privacy)
1013 wsec |= WEP_ENABLED;
1014
1015 err = brcmf_dev_intvar_set(dev, "wsec", wsec);
1016 if (unlikely(err)) {
1017 WL_ERR("wsec failed (%d)\n", err);
1018 goto done;
1019 }
1020
1021 /* Configure Beacon Interval for starter */
1022 if (params->beacon_interval)
1023 bcnprd = cpu_to_le32(params->beacon_interval);
1024 else
1025 bcnprd = cpu_to_le32(100);
1026
1027 err = brcmf_dev_ioctl(dev, BRCM_SET_BCNPRD, &bcnprd, sizeof(bcnprd));
1028 if (unlikely(err)) {
1029 WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
1030 goto done;
1031 }
1032
1033 /* Configure required join parameter */
1034 memset(&join_params, 0, sizeof(struct brcmf_join_params));
1035
1036 /* SSID */
1037 join_params.ssid.SSID_len =
1038 (params->ssid_len > 32) ? 32 : params->ssid_len;
1039 memcpy(join_params.ssid.SSID, params->ssid, join_params.ssid.SSID_len);
1040 join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
1041 join_params_size = sizeof(join_params.ssid);
1042 brcmf_update_prof(cfg_priv, NULL, &join_params.ssid, WL_PROF_SSID);
1043
1044 /* BSSID */
1045 if (params->bssid) {
1046 memcpy(join_params.params.bssid, params->bssid, ETH_ALEN);
1047 join_params_size = sizeof(join_params.ssid) +
1048 BRCMF_ASSOC_PARAMS_FIXED_SIZE;
1049 } else {
1050 memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
1051 }
1052 brcmf_update_prof(cfg_priv, NULL,
1053 &join_params.params.bssid, WL_PROF_BSSID);
1054
1055 /* Channel */
1056 if (params->channel) {
1057 u32 target_channel;
1058
1059 cfg_priv->channel =
1060 ieee80211_frequency_to_channel(
1061 params->channel->center_freq);
1062 if (params->channel_fixed) {
1063 /* adding chanspec */
1064 brcmf_ch_to_chanspec(cfg_priv->channel,
1065 &join_params, &join_params_size);
1066 }
1067
1068 /* set channel for starter */
1069 target_channel = cpu_to_le32(cfg_priv->channel);
1070 err = brcmf_dev_ioctl(dev, BRCM_SET_CHANNEL,
1071 &target_channel, sizeof(target_channel));
1072 if (unlikely(err)) {
1073 WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
1074 goto done;
1075 }
1076 } else
1077 cfg_priv->channel = 0;
1078
1079 cfg_priv->ibss_starter = false;
1080
1081
1082 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_SSID,
1083 &join_params, join_params_size);
1084 if (unlikely(err)) {
1085 WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1086 goto done;
1087 }
1088
1089done:
1090 if (err)
1091 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1092 WL_TRACE("Exit\n");
1093 return err;
1094}
1095
1096static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1097{
1098 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1099 s32 err = 0;
1100
1101 WL_TRACE("Enter\n");
1102 CHECK_SYS_UP();
1103
1104 brcmf_link_down(cfg_priv);
1105
1106 WL_TRACE("Exit\n");
1107
1108 return err;
1109}
1110
1111static s32
1112brcmf_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
1113{
1114 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
1115 struct brcmf_cfg80211_security *sec;
1116 s32 val = 0;
1117 s32 err = 0;
1118
1119 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1120 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1121 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1122 val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1123 else
1124 val = WPA_AUTH_DISABLED;
1125 WL_CONN("setting wpa_auth to 0x%0x\n", val);
1126 err = brcmf_dev_intvar_set(dev, "wpa_auth", val);
1127 if (unlikely(err)) {
1128 WL_ERR("set wpa_auth failed (%d)\n", err);
1129 return err;
1130 }
1131 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1132 sec->wpa_versions = sme->crypto.wpa_versions;
1133 return err;
1134}
1135
1136static s32
1137brcmf_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
1138{
1139 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
1140 struct brcmf_cfg80211_security *sec;
1141 s32 val = 0;
1142 s32 err = 0;
1143
1144 switch (sme->auth_type) {
1145 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1146 val = 0;
1147 WL_CONN("open system\n");
1148 break;
1149 case NL80211_AUTHTYPE_SHARED_KEY:
1150 val = 1;
1151 WL_CONN("shared key\n");
1152 break;
1153 case NL80211_AUTHTYPE_AUTOMATIC:
1154 val = 2;
1155 WL_CONN("automatic\n");
1156 break;
1157 case NL80211_AUTHTYPE_NETWORK_EAP:
1158 WL_CONN("network eap\n");
1159 default:
1160 val = 2;
1161 WL_ERR("invalid auth type (%d)\n", sme->auth_type);
1162 break;
1163 }
1164
1165 err = brcmf_dev_intvar_set(dev, "auth", val);
1166 if (unlikely(err)) {
1167 WL_ERR("set auth failed (%d)\n", err);
1168 return err;
1169 }
1170 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1171 sec->auth_type = sme->auth_type;
1172 return err;
1173}
1174
1175static s32
1176brcmf_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
1177{
1178 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
1179 struct brcmf_cfg80211_security *sec;
1180 s32 pval = 0;
1181 s32 gval = 0;
1182 s32 err = 0;
1183
1184 if (sme->crypto.n_ciphers_pairwise) {
1185 switch (sme->crypto.ciphers_pairwise[0]) {
1186 case WLAN_CIPHER_SUITE_WEP40:
1187 case WLAN_CIPHER_SUITE_WEP104:
1188 pval = WEP_ENABLED;
1189 break;
1190 case WLAN_CIPHER_SUITE_TKIP:
1191 pval = TKIP_ENABLED;
1192 break;
1193 case WLAN_CIPHER_SUITE_CCMP:
1194 pval = AES_ENABLED;
1195 break;
1196 case WLAN_CIPHER_SUITE_AES_CMAC:
1197 pval = AES_ENABLED;
1198 break;
1199 default:
1200 WL_ERR("invalid cipher pairwise (%d)\n",
1201 sme->crypto.ciphers_pairwise[0]);
1202 return -EINVAL;
1203 }
1204 }
1205 if (sme->crypto.cipher_group) {
1206 switch (sme->crypto.cipher_group) {
1207 case WLAN_CIPHER_SUITE_WEP40:
1208 case WLAN_CIPHER_SUITE_WEP104:
1209 gval = WEP_ENABLED;
1210 break;
1211 case WLAN_CIPHER_SUITE_TKIP:
1212 gval = TKIP_ENABLED;
1213 break;
1214 case WLAN_CIPHER_SUITE_CCMP:
1215 gval = AES_ENABLED;
1216 break;
1217 case WLAN_CIPHER_SUITE_AES_CMAC:
1218 gval = AES_ENABLED;
1219 break;
1220 default:
1221 WL_ERR("invalid cipher group (%d)\n",
1222 sme->crypto.cipher_group);
1223 return -EINVAL;
1224 }
1225 }
1226
1227 WL_CONN("pval (%d) gval (%d)\n", pval, gval);
1228 err = brcmf_dev_intvar_set(dev, "wsec", pval | gval);
1229 if (unlikely(err)) {
1230 WL_ERR("error (%d)\n", err);
1231 return err;
1232 }
1233
1234 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1235 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
1236 sec->cipher_group = sme->crypto.cipher_group;
1237
1238 return err;
1239}
1240
1241static s32
1242brcmf_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
1243{
1244 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
1245 struct brcmf_cfg80211_security *sec;
1246 s32 val = 0;
1247 s32 err = 0;
1248
1249 if (sme->crypto.n_akm_suites) {
1250 err = brcmf_dev_intvar_get(dev, "wpa_auth", &val);
1251 if (unlikely(err)) {
1252 WL_ERR("could not get wpa_auth (%d)\n", err);
1253 return err;
1254 }
1255 if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
1256 switch (sme->crypto.akm_suites[0]) {
1257 case WLAN_AKM_SUITE_8021X:
1258 val = WPA_AUTH_UNSPECIFIED;
1259 break;
1260 case WLAN_AKM_SUITE_PSK:
1261 val = WPA_AUTH_PSK;
1262 break;
1263 default:
1264 WL_ERR("invalid cipher group (%d)\n",
1265 sme->crypto.cipher_group);
1266 return -EINVAL;
1267 }
1268 } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
1269 switch (sme->crypto.akm_suites[0]) {
1270 case WLAN_AKM_SUITE_8021X:
1271 val = WPA2_AUTH_UNSPECIFIED;
1272 break;
1273 case WLAN_AKM_SUITE_PSK:
1274 val = WPA2_AUTH_PSK;
1275 break;
1276 default:
1277 WL_ERR("invalid cipher group (%d)\n",
1278 sme->crypto.cipher_group);
1279 return -EINVAL;
1280 }
1281 }
1282
1283 WL_CONN("setting wpa_auth to %d\n", val);
1284 err = brcmf_dev_intvar_set(dev, "wpa_auth", val);
1285 if (unlikely(err)) {
1286 WL_ERR("could not set wpa_auth (%d)\n", err);
1287 return err;
1288 }
1289 }
1290 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1291 sec->wpa_auth = sme->crypto.akm_suites[0];
1292
1293 return err;
1294}
1295
1296static s32
1297brcmf_set_set_sharedkey(struct net_device *dev,
1298 struct cfg80211_connect_params *sme)
1299{
1300 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
1301 struct brcmf_cfg80211_security *sec;
1302 struct brcmf_wsec_key key;
1303 s32 val;
1304 s32 err = 0;
1305
1306 WL_CONN("key len (%d)\n", sme->key_len);
1307 if (sme->key_len) {
1308 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1309 WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n",
1310 sec->wpa_versions, sec->cipher_pairwise);
1311 if (!
1312 (sec->wpa_versions & (NL80211_WPA_VERSION_1 |
1313 NL80211_WPA_VERSION_2))
1314&& (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
1315 WLAN_CIPHER_SUITE_WEP104))) {
1316 memset(&key, 0, sizeof(key));
1317 key.len = (u32) sme->key_len;
1318 key.index = (u32) sme->key_idx;
1319 if (unlikely(key.len > sizeof(key.data))) {
1320 WL_ERR("Too long key length (%u)\n", key.len);
1321 return -EINVAL;
1322 }
1323 memcpy(key.data, sme->key, key.len);
1324 key.flags = BRCMF_PRIMARY_KEY;
1325 switch (sec->cipher_pairwise) {
1326 case WLAN_CIPHER_SUITE_WEP40:
1327 key.algo = CRYPTO_ALGO_WEP1;
1328 break;
1329 case WLAN_CIPHER_SUITE_WEP104:
1330 key.algo = CRYPTO_ALGO_WEP128;
1331 break;
1332 default:
1333 WL_ERR("Invalid algorithm (%d)\n",
1334 sme->crypto.ciphers_pairwise[0]);
1335 return -EINVAL;
1336 }
1337 /* Set the new key/index */
1338 WL_CONN("key length (%d) key index (%d) algo (%d)\n",
1339 key.len, key.index, key.algo);
1340 WL_CONN("key \"%s\"\n", key.data);
1341 swap_key_from_BE(&key);
1342 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key,
1343 sizeof(key));
1344 if (unlikely(err)) {
1345 WL_ERR("WLC_SET_KEY error (%d)\n", err);
1346 return err;
1347 }
1348 if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
1349 WL_CONN("set auth_type to shared key\n");
1350 val = 1; /* shared key */
1351 err = brcmf_dev_intvar_set(dev, "auth", val);
1352 if (unlikely(err)) {
1353 WL_ERR("set auth failed (%d)\n", err);
1354 return err;
1355 }
1356 }
1357 }
1358 }
1359 return err;
1360}
1361
1362static s32
1363brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
1364 struct cfg80211_connect_params *sme)
1365{
1366 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1367 struct ieee80211_channel *chan = sme->channel;
1368 struct brcmf_join_params join_params;
1369 size_t join_params_size;
1370
1371 s32 err = 0;
1372
1373 WL_TRACE("Enter\n");
1374 CHECK_SYS_UP();
1375
1376 if (unlikely(!sme->ssid)) {
1377 WL_ERR("Invalid ssid\n");
1378 return -EOPNOTSUPP;
1379 }
1380
1381 set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1382
1383 if (chan) {
1384 cfg_priv->channel =
1385 ieee80211_frequency_to_channel(chan->center_freq);
1386 WL_CONN("channel (%d), center_req (%d)\n",
1387 cfg_priv->channel, chan->center_freq);
1388 } else
1389 cfg_priv->channel = 0;
1390
1391 WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
1392
1393 err = brcmf_set_wpa_version(dev, sme);
1394 if (err) {
1395 WL_ERR("wl_set_wpa_version failed (%d)\n", err);
1396 goto done;
1397 }
1398
1399 err = brcmf_set_auth_type(dev, sme);
1400 if (err) {
1401 WL_ERR("wl_set_auth_type failed (%d)\n", err);
1402 goto done;
1403 }
1404
1405 err = brcmf_set_set_cipher(dev, sme);
1406 if (err) {
1407 WL_ERR("wl_set_set_cipher failed (%d)\n", err);
1408 goto done;
1409 }
1410
1411 err = brcmf_set_key_mgmt(dev, sme);
1412 if (err) {
1413 WL_ERR("wl_set_key_mgmt failed (%d)\n", err);
1414 goto done;
1415 }
1416
1417 err = brcmf_set_set_sharedkey(dev, sme);
1418 if (err) {
1419 WL_ERR("wl_set_set_sharedkey failed (%d)\n", err);
1420 goto done;
1421 }
1422
1423 brcmf_update_prof(cfg_priv, NULL, sme->bssid, WL_PROF_BSSID);
1424 /*
1425 ** Join with specific BSSID and cached SSID
1426 ** If SSID is zero join based on BSSID only
1427 */
1428 memset(&join_params, 0, sizeof(join_params));
1429 join_params_size = sizeof(join_params.ssid);
1430
1431 join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
1432 memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
1433 join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
1434 brcmf_update_prof(cfg_priv, NULL, &join_params.ssid, WL_PROF_SSID);
1435
1436 if (sme->bssid)
1437 memcpy(join_params.params.bssid, sme->bssid, ETH_ALEN);
1438 else
1439 memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
1440
1441 if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
1442 WL_CONN("ssid \"%s\", len (%d)\n",
1443 join_params.ssid.SSID, join_params.ssid.SSID_len);
1444 }
1445
1446 brcmf_ch_to_chanspec(cfg_priv->channel,
1447 &join_params, &join_params_size);
1448 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_SSID,
1449 &join_params, join_params_size);
1450 if (err)
1451 WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1452
1453done:
1454 if (err)
1455 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1456 WL_TRACE("Exit\n");
1457 return err;
1458}
1459
1460static s32
1461brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
1462 u16 reason_code)
1463{
1464 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1465 struct brcmf_scb_val scbval;
1466 s32 err = 0;
1467
1468 WL_TRACE("Enter. Reason code = %d\n", reason_code);
1469 CHECK_SYS_UP();
1470
1471 clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
1472
1473 scbval.val = reason_code;
1474 memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN);
1475 scbval.val = cpu_to_le32(scbval.val);
1476 err = brcmf_dev_ioctl(dev, BRCMF_C_DISASSOC, &scbval,
1477 sizeof(struct brcmf_scb_val));
1478 if (unlikely(err))
1479 WL_ERR("error (%d)\n", err);
1480
1481 cfg_priv->link_up = false;
1482
1483 WL_TRACE("Exit\n");
1484 return err;
1485}
1486
1487static s32
1488brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
1489 enum nl80211_tx_power_setting type, s32 dbm)
1490{
1491
1492 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1493 struct net_device *ndev = cfg_to_ndev(cfg_priv);
1494 u16 txpwrmw;
1495 s32 err = 0;
1496 s32 disable = 0;
1497
1498 WL_TRACE("Enter\n");
1499 CHECK_SYS_UP();
1500
1501 switch (type) {
1502 case NL80211_TX_POWER_AUTOMATIC:
1503 break;
1504 case NL80211_TX_POWER_LIMITED:
1505 if (dbm < 0) {
1506 WL_ERR("TX_POWER_LIMITED - dbm is negative\n");
1507 err = -EINVAL;
1508 goto done;
1509 }
1510 break;
1511 case NL80211_TX_POWER_FIXED:
1512 if (dbm < 0) {
1513 WL_ERR("TX_POWER_FIXED - dbm is negative\n");
1514 err = -EINVAL;
1515 goto done;
1516 }
1517 break;
1518 }
1519 /* Make sure radio is off or on as far as software is concerned */
1520 disable = WL_RADIO_SW_DISABLE << 16;
1521 disable = cpu_to_le32(disable);
1522 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_RADIO, &disable, sizeof(disable));
1523 if (unlikely(err))
1524 WL_ERR("WLC_SET_RADIO error (%d)\n", err);
1525
1526 if (dbm > 0xffff)
1527 txpwrmw = 0xffff;
1528 else
1529 txpwrmw = (u16) dbm;
1530 err = brcmf_dev_intvar_set(ndev, "qtxpower",
1531 (s32) (brcmu_mw_to_qdbm(txpwrmw)));
1532 if (unlikely(err))
1533 WL_ERR("qtxpower error (%d)\n", err);
1534 cfg_priv->conf->tx_power = dbm;
1535
1536done:
1537 WL_TRACE("Exit\n");
1538 return err;
1539}
1540
1541static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
1542{
1543 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1544 struct net_device *ndev = cfg_to_ndev(cfg_priv);
1545 s32 txpwrdbm;
1546 u8 result;
1547 s32 err = 0;
1548
1549 WL_TRACE("Enter\n");
1550 CHECK_SYS_UP();
1551
1552 err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
1553 if (unlikely(err)) {
1554 WL_ERR("error (%d)\n", err);
1555 goto done;
1556 }
1557
1558 result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
1559 *dbm = (s32) brcmu_qdbm_to_mw(result);
1560
1561done:
1562 WL_TRACE("Exit\n");
1563 return err;
1564}
1565
1566static s32
1567brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
1568 u8 key_idx, bool unicast, bool multicast)
1569{
1570 u32 index;
1571 s32 wsec;
1572 s32 err = 0;
1573
1574 WL_TRACE("Enter\n");
1575 WL_CONN("key index (%d)\n", key_idx);
1576 CHECK_SYS_UP();
1577
1578 err = brcmf_dev_ioctl(dev, BRCMF_C_GET_WSEC, &wsec, sizeof(wsec));
1579 if (unlikely(err)) {
1580 WL_ERR("WLC_GET_WSEC error (%d)\n", err);
1581 goto done;
1582 }
1583
1584 wsec = le32_to_cpu(wsec);
1585 if (wsec & WEP_ENABLED) {
1586 /* Just select a new current key */
1587 index = (u32) key_idx;
1588 index = cpu_to_le32(index);
1589 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY_PRIMARY, &index,
1590 sizeof(index));
1591 if (unlikely(err))
1592 WL_ERR("error (%d)\n", err);
1593 }
1594done:
1595 WL_TRACE("Exit\n");
1596 return err;
1597}
1598
1599static s32
1600brcmf_add_keyext(struct wiphy *wiphy, struct net_device *dev,
1601 u8 key_idx, const u8 *mac_addr, struct key_params *params)
1602{
1603 struct brcmf_wsec_key key;
1604 s32 err = 0;
1605
1606 memset(&key, 0, sizeof(key));
1607 key.index = (u32) key_idx;
1608 /* Instead of bcast for ea address for default wep keys,
1609 driver needs it to be Null */
1610 if (!is_multicast_ether_addr(mac_addr))
1611 memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN);
1612 key.len = (u32) params->key_len;
1613 /* check for key index change */
1614 if (key.len == 0) {
1615 /* key delete */
1616 swap_key_from_BE(&key);
1617 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
1618 if (unlikely(err)) {
1619 WL_ERR("key delete error (%d)\n", err);
1620 return err;
1621 }
1622 } else {
1623 if (key.len > sizeof(key.data)) {
1624 WL_ERR("Invalid key length (%d)\n", key.len);
1625 return -EINVAL;
1626 }
1627
1628 WL_CONN("Setting the key index %d\n", key.index);
1629 memcpy(key.data, params->key, key.len);
1630
1631 if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1632 u8 keybuf[8];
1633 memcpy(keybuf, &key.data[24], sizeof(keybuf));
1634 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1635 memcpy(&key.data[16], keybuf, sizeof(keybuf));
1636 }
1637
1638 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
1639 if (params->seq && params->seq_len == 6) {
1640 /* rx iv */
1641 u8 *ivptr;
1642 ivptr = (u8 *) params->seq;
1643 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
1644 (ivptr[3] << 8) | ivptr[2];
1645 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
1646 key.iv_initialized = true;
1647 }
1648
1649 switch (params->cipher) {
1650 case WLAN_CIPHER_SUITE_WEP40:
1651 key.algo = CRYPTO_ALGO_WEP1;
1652 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
1653 break;
1654 case WLAN_CIPHER_SUITE_WEP104:
1655 key.algo = CRYPTO_ALGO_WEP128;
1656 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
1657 break;
1658 case WLAN_CIPHER_SUITE_TKIP:
1659 key.algo = CRYPTO_ALGO_TKIP;
1660 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
1661 break;
1662 case WLAN_CIPHER_SUITE_AES_CMAC:
1663 key.algo = CRYPTO_ALGO_AES_CCM;
1664 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
1665 break;
1666 case WLAN_CIPHER_SUITE_CCMP:
1667 key.algo = CRYPTO_ALGO_AES_CCM;
1668 WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
1669 break;
1670 default:
1671 WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
1672 return -EINVAL;
1673 }
1674 swap_key_from_BE(&key);
1675
1676 brcmf_netdev_wait_pend8021x(dev);
1677 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
1678 if (unlikely(err)) {
1679 WL_ERR("WLC_SET_KEY error (%d)\n", err);
1680 return err;
1681 }
1682 }
1683 return err;
1684}
1685
1686static s32
1687brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
1688 u8 key_idx, bool pairwise, const u8 *mac_addr,
1689 struct key_params *params)
1690{
1691 struct brcmf_wsec_key key;
1692 s32 val;
1693 s32 wsec;
1694 s32 err = 0;
1695 u8 keybuf[8];
1696
1697 WL_TRACE("Enter\n");
1698 WL_CONN("key index (%d)\n", key_idx);
1699 CHECK_SYS_UP();
1700
1701 if (mac_addr) {
1702 WL_TRACE("Exit");
1703 return brcmf_add_keyext(wiphy, dev, key_idx, mac_addr, params);
1704 }
1705 memset(&key, 0, sizeof(key));
1706
1707 key.len = (u32) params->key_len;
1708 key.index = (u32) key_idx;
1709
1710 if (unlikely(key.len > sizeof(key.data))) {
1711 WL_ERR("Too long key length (%u)\n", key.len);
1712 err = -EINVAL;
1713 goto done;
1714 }
1715 memcpy(key.data, params->key, key.len);
1716
1717 key.flags = BRCMF_PRIMARY_KEY;
1718 switch (params->cipher) {
1719 case WLAN_CIPHER_SUITE_WEP40:
1720 key.algo = CRYPTO_ALGO_WEP1;
1721 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
1722 break;
1723 case WLAN_CIPHER_SUITE_WEP104:
1724 key.algo = CRYPTO_ALGO_WEP128;
1725 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
1726 break;
1727 case WLAN_CIPHER_SUITE_TKIP:
1728 memcpy(keybuf, &key.data[24], sizeof(keybuf));
1729 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1730 memcpy(&key.data[16], keybuf, sizeof(keybuf));
1731 key.algo = CRYPTO_ALGO_TKIP;
1732 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
1733 break;
1734 case WLAN_CIPHER_SUITE_AES_CMAC:
1735 key.algo = CRYPTO_ALGO_AES_CCM;
1736 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
1737 break;
1738 case WLAN_CIPHER_SUITE_CCMP:
1739 key.algo = CRYPTO_ALGO_AES_CCM;
1740 WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
1741 break;
1742 default:
1743 WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
1744 err = -EINVAL;
1745 goto done;
1746 }
1747
1748 /* Set the new key/index */
1749 swap_key_from_BE(&key);
1750 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
1751 if (unlikely(err)) {
1752 WL_ERR("WLC_SET_KEY error (%d)\n", err);
1753 goto done;
1754 }
1755
1756 val = WEP_ENABLED;
1757 err = brcmf_dev_intvar_get(dev, "wsec", &wsec);
1758 if (unlikely(err)) {
1759 WL_ERR("get wsec error (%d)\n", err);
1760 goto done;
1761 }
1762 wsec &= ~(WEP_ENABLED);
1763 wsec |= val;
1764 err = brcmf_dev_intvar_set(dev, "wsec", wsec);
1765 if (unlikely(err)) {
1766 WL_ERR("set wsec error (%d)\n", err);
1767 goto done;
1768 }
1769
1770 val = 1; /* assume shared key. otherwise 0 */
1771 val = cpu_to_le32(val);
1772 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_AUTH, &val, sizeof(val));
1773 if (unlikely(err))
1774 WL_ERR("WLC_SET_AUTH error (%d)\n", err);
1775done:
1776 WL_TRACE("Exit\n");
1777 return err;
1778}
1779
1780static s32
1781brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
1782 u8 key_idx, bool pairwise, const u8 *mac_addr)
1783{
1784 struct brcmf_wsec_key key;
1785 s32 err = 0;
1786 s32 val;
1787 s32 wsec;
1788
1789 WL_TRACE("Enter\n");
1790 CHECK_SYS_UP();
1791 memset(&key, 0, sizeof(key));
1792
1793 key.index = (u32) key_idx;
1794 key.flags = BRCMF_PRIMARY_KEY;
1795 key.algo = CRYPTO_ALGO_OFF;
1796
1797 WL_CONN("key index (%d)\n", key_idx);
1798 /* Set the new key/index */
1799 swap_key_from_BE(&key);
1800 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_KEY, &key, sizeof(key));
1801 if (unlikely(err)) {
1802 if (err == -EINVAL) {
1803 if (key.index >= DOT11_MAX_DEFAULT_KEYS)
1804 /* we ignore this key index in this case */
1805 WL_ERR("invalid key index (%d)\n", key_idx);
1806 } else
1807 WL_ERR("WLC_SET_KEY error (%d)\n", err);
1808
1809 /* Ignore this error, may happen during DISASSOC */
1810 err = -EAGAIN;
1811 goto done;
1812 }
1813
1814 val = 0;
1815 err = brcmf_dev_intvar_get(dev, "wsec", &wsec);
1816 if (unlikely(err)) {
1817 WL_ERR("get wsec error (%d)\n", err);
1818 /* Ignore this error, may happen during DISASSOC */
1819 err = -EAGAIN;
1820 goto done;
1821 }
1822 wsec &= ~(WEP_ENABLED);
1823 wsec |= val;
1824 err = brcmf_dev_intvar_set(dev, "wsec", wsec);
1825 if (unlikely(err)) {
1826 WL_ERR("set wsec error (%d)\n", err);
1827 /* Ignore this error, may happen during DISASSOC */
1828 err = -EAGAIN;
1829 goto done;
1830 }
1831
1832 val = 0; /* assume open key. otherwise 1 */
1833 val = cpu_to_le32(val);
1834 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_AUTH, &val, sizeof(val));
1835 if (unlikely(err)) {
1836 WL_ERR("WLC_SET_AUTH error (%d)\n", err);
1837 /* Ignore this error, may happen during DISASSOC */
1838 err = -EAGAIN;
1839 }
1840done:
1841 WL_TRACE("Exit\n");
1842 return err;
1843}
1844
1845static s32
1846brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
1847 u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
1848 void (*callback) (void *cookie, struct key_params * params))
1849{
1850 struct key_params params;
1851 struct brcmf_wsec_key key;
1852 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1853 struct brcmf_cfg80211_security *sec;
1854 s32 wsec;
1855 s32 err = 0;
1856
1857 WL_TRACE("Enter\n");
1858 WL_CONN("key index (%d)\n", key_idx);
1859 CHECK_SYS_UP();
1860
1861 memset(&key, 0, sizeof(key));
1862 key.index = key_idx;
1863 swap_key_to_BE(&key);
1864 memset(&params, 0, sizeof(params));
1865 params.key_len = (u8) min_t(u8, WLAN_MAX_KEY_LEN, key.len);
1866 memcpy(params.key, key.data, params.key_len);
1867
1868 err = brcmf_dev_ioctl(dev, BRCMF_C_GET_WSEC, &wsec, sizeof(wsec));
1869 if (unlikely(err)) {
1870 WL_ERR("WLC_GET_WSEC error (%d)\n", err);
1871 /* Ignore this error, may happen during DISASSOC */
1872 err = -EAGAIN;
1873 goto done;
1874 }
1875 wsec = le32_to_cpu(wsec);
1876 switch (wsec) {
1877 case WEP_ENABLED:
1878 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1879 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
1880 params.cipher = WLAN_CIPHER_SUITE_WEP40;
1881 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
1882 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
1883 params.cipher = WLAN_CIPHER_SUITE_WEP104;
1884 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
1885 }
1886 break;
1887 case TKIP_ENABLED:
1888 params.cipher = WLAN_CIPHER_SUITE_TKIP;
1889 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
1890 break;
1891 case AES_ENABLED:
1892 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
1893 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
1894 break;
1895 default:
1896 WL_ERR("Invalid algo (0x%x)\n", wsec);
1897 err = -EINVAL;
1898 goto done;
1899 }
1900 callback(cookie, &params);
1901
1902done:
1903 WL_TRACE("Exit\n");
1904 return err;
1905}
1906
1907static s32
1908brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
1909 struct net_device *dev, u8 key_idx)
1910{
1911 WL_INFO("Not supported\n");
1912
1913 CHECK_SYS_UP();
1914 return -EOPNOTSUPP;
1915}
1916
1917static s32
1918brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
1919 u8 *mac, struct station_info *sinfo)
1920{
1921 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1922 struct brcmf_scb_val scb_val;
1923 int rssi;
1924 s32 rate;
1925 s32 err = 0;
1926 u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID);
1927
1928 WL_TRACE("Enter\n");
1929 CHECK_SYS_UP();
1930
1931 if (unlikely
1932 (memcmp(mac, bssid, ETH_ALEN))) {
1933 WL_ERR("Wrong Mac address cfg_mac-%X:%X:%X:%X:%X:%X"
1934 "wl_bssid-%X:%X:%X:%X:%X:%X\n",
1935 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
1936 bssid[0], bssid[1], bssid[2], bssid[3],
1937 bssid[4], bssid[5]);
1938 err = -ENOENT;
1939 goto done;
1940 }
1941
1942 /* Report the current tx rate */
1943 err = brcmf_dev_ioctl(dev, BRCMF_C_GET_RATE, &rate, sizeof(rate));
1944 if (err) {
1945 WL_ERR("Could not get rate (%d)\n", err);
1946 } else {
1947 rate = le32_to_cpu(rate);
1948 sinfo->filled |= STATION_INFO_TX_BITRATE;
1949 sinfo->txrate.legacy = rate * 5;
1950 WL_CONN("Rate %d Mbps\n", rate / 2);
1951 }
1952
1953 if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
1954 scb_val.val = 0;
1955 err = brcmf_dev_ioctl(dev, BRCMF_C_GET_RSSI, &scb_val,
1956 sizeof(struct brcmf_scb_val));
1957 if (unlikely(err)) {
1958 WL_ERR("Could not get rssi (%d)\n", err);
1959 }
1960 rssi = le32_to_cpu(scb_val.val);
1961 sinfo->filled |= STATION_INFO_SIGNAL;
1962 sinfo->signal = rssi;
1963 WL_CONN("RSSI %d dBm\n", rssi);
1964 }
1965
1966done:
1967 WL_TRACE("Exit\n");
1968 return err;
1969}
1970
1971static s32
1972brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1973 bool enabled, s32 timeout)
1974{
1975 s32 pm;
1976 s32 err = 0;
1977
1978 WL_TRACE("Enter\n");
1979 CHECK_SYS_UP();
1980
1981 pm = enabled ? PM_FAST : PM_OFF;
1982 pm = cpu_to_le32(pm);
1983 WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
1984
1985 err = brcmf_dev_ioctl(dev, BRCMF_C_SET_PM, &pm, sizeof(pm));
1986 if (unlikely(err)) {
1987 if (err == -ENODEV)
1988 WL_ERR("net_device is not ready yet\n");
1989 else
1990 WL_ERR("error (%d)\n", err);
1991 }
1992 WL_TRACE("Exit\n");
1993 return err;
1994}
1995
1996static __used u32 brcmf_find_msb(u16 bit16)
1997{
1998 u32 ret = 0;
1999
2000 if (bit16 & 0xff00) {
2001 ret += 8;
2002 bit16 >>= 8;
2003 }
2004
2005 if (bit16 & 0xf0) {
2006 ret += 4;
2007 bit16 >>= 4;
2008 }
2009
2010 if (bit16 & 0xc) {
2011 ret += 2;
2012 bit16 >>= 2;
2013 }
2014
2015 if (bit16 & 2)
2016 ret += bit16 & 2;
2017 else if (bit16)
2018 ret += bit16;
2019
2020 return ret;
2021}
2022
2023static s32
2024brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
2025 const u8 *addr,
2026 const struct cfg80211_bitrate_mask *mask)
2027{
2028 struct wl_rateset rateset;
2029 s32 rate;
2030 s32 val;
2031 s32 err_bg;
2032 s32 err_a;
2033 u32 legacy;
2034 s32 err = 0;
2035
2036 WL_TRACE("Enter\n");
2037 CHECK_SYS_UP();
2038
2039 /* addr param is always NULL. ignore it */
2040 /* Get current rateset */
2041 err = brcmf_dev_ioctl(dev, BRCM_GET_CURR_RATESET, &rateset,
2042 sizeof(rateset));
2043 if (unlikely(err)) {
2044 WL_ERR("could not get current rateset (%d)\n", err);
2045 goto done;
2046 }
2047
2048 rateset.count = le32_to_cpu(rateset.count);
2049
2050 legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy);
2051 if (!legacy)
2052 legacy = brcmf_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy);
2053
2054 val = wl_g_rates[legacy - 1].bitrate * 100000;
2055
2056 if (val < rateset.count)
2057 /* Select rate by rateset index */
2058 rate = rateset.rates[val] & 0x7f;
2059 else
2060 /* Specified rate in bps */
2061 rate = val / 500000;
2062
2063 WL_CONN("rate %d mbps\n", rate / 2);
2064
2065 /*
2066 *
2067 * Set rate override,
2068 * Since the is a/b/g-blind, both a/bg_rate are enforced.
2069 */
2070 err_bg = brcmf_dev_intvar_set(dev, "bg_rate", rate);
2071 err_a = brcmf_dev_intvar_set(dev, "a_rate", rate);
2072 if (unlikely(err_bg && err_a)) {
2073 WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
2074 err = err_bg | err_a;
2075 }
2076
2077done:
2078 WL_TRACE("Exit\n");
2079 return err;
2080}
2081
2082static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
2083{
2084 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2085
2086 /*
2087 * Check for WL_STATUS_READY before any function call which
2088 * could result is bus access. Don't block the resume for
2089 * any driver error conditions
2090 */
2091 WL_TRACE("Enter\n");
2092
2093#if defined(CONFIG_PM_SLEEP)
2094 atomic_set(&brcmf_mmc_suspend, false);
2095#endif /* defined(CONFIG_PM_SLEEP) */
2096
2097 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
2098 brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
2099
2100 WL_TRACE("Exit\n");
2101 return 0;
2102}
2103
2104static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
2105 struct cfg80211_wowlan *wow)
2106{
2107 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2108 struct net_device *ndev = cfg_to_ndev(cfg_priv);
2109
2110 WL_TRACE("Enter\n");
2111
2112 /*
2113 * Check for WL_STATUS_READY before any function call which
2114 * could result is bus access. Don't block the suspend for
2115 * any driver error conditions
2116 */
2117
2118 /*
2119 * While going to suspend if associated with AP disassociate
2120 * from AP to save power while system is in suspended state
2121 */
2122 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
2123 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
2124 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
2125 WL_INFO("Disassociating from AP"
2126 " while entering suspend state\n");
2127 brcmf_link_down(cfg_priv);
2128
2129 /*
2130 * Make sure WPA_Supplicant receives all the event
2131 * generated due to DISASSOC call to the fw to keep
2132 * the state fw and WPA_Supplicant state consistent
2133 */
2134 rtnl_unlock();
2135 brcmf_delay(500);
2136 rtnl_lock();
2137 }
2138
2139 set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
2140 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
2141 brcmf_term_iscan(cfg_priv);
2142
2143 if (cfg_priv->scan_request) {
2144 /* Indidate scan abort to cfg80211 layer */
2145 WL_INFO("Terminating scan in progress\n");
2146 cfg80211_scan_done(cfg_priv->scan_request, true);
2147 cfg_priv->scan_request = NULL;
2148 }
2149 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
2150 clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
2151
2152 /* Turn off watchdog timer */
2153 if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
2154 WL_INFO("Enable MPC\n");
2155 brcmf_set_mpc(ndev, 1);
2156 }
2157
2158#if defined(CONFIG_PM_SLEEP)
2159 atomic_set(&brcmf_mmc_suspend, true);
2160#endif /* defined(CONFIG_PM_SLEEP) */
2161
2162 WL_TRACE("Exit\n");
2163
2164 return 0;
2165}
2166
2167static __used s32
2168brcmf_update_pmklist(struct net_device *dev,
2169 struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
2170{
2171 int i, j;
2172
2173 WL_CONN("No of elements %d\n", pmk_list->pmkids.npmkid);
2174 for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
2175 WL_CONN("PMKID[%d]: %pM =\n", i,
2176 &pmk_list->pmkids.pmkid[i].BSSID);
2177 for (j = 0; j < WLAN_PMKID_LEN; j++)
2178 WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
2179 }
2180
2181 if (likely(!err))
2182 brcmf_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list,
2183 sizeof(*pmk_list));
2184
2185 return err;
2186}
2187
2188static s32
2189brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
2190 struct cfg80211_pmksa *pmksa)
2191{
2192 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2193 struct _pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
2194 s32 err = 0;
2195 int i;
2196
2197 WL_TRACE("Enter\n");
2198 CHECK_SYS_UP();
2199
2200 for (i = 0; i < pmkids->npmkid; i++)
2201 if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
2202 break;
2203 if (i < WL_NUM_PMKIDS_MAX) {
2204 memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
2205 memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2206 if (i == pmkids->npmkid)
2207 pmkids->npmkid++;
2208 } else
2209 err = -EINVAL;
2210
2211 WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
2212 pmkids->pmkid[pmkids->npmkid].BSSID);
2213 for (i = 0; i < WLAN_PMKID_LEN; i++)
2214 WL_CONN("%02x\n", pmkids->pmkid[pmkids->npmkid].PMKID[i]);
2215
2216 err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
2217
2218 WL_TRACE("Exit\n");
2219 return err;
2220}
2221
2222static s32
2223brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
2224 struct cfg80211_pmksa *pmksa)
2225{
2226 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2227 struct _pmkid_list pmkid;
2228 s32 err = 0;
2229 int i;
2230
2231 WL_TRACE("Enter\n");
2232 CHECK_SYS_UP();
2233 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
2234 memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2235
2236 WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
2237 &pmkid.pmkid[0].BSSID);
2238 for (i = 0; i < WLAN_PMKID_LEN; i++)
2239 WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
2240
2241 for (i = 0; i < cfg_priv->pmk_list->pmkids.npmkid; i++)
2242 if (!memcmp
2243 (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
2244 ETH_ALEN))
2245 break;
2246
2247 if ((cfg_priv->pmk_list->pmkids.npmkid > 0)
2248 && (i < cfg_priv->pmk_list->pmkids.npmkid)) {
2249 memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
2250 sizeof(pmkid_t));
2251 for (; i < (cfg_priv->pmk_list->pmkids.npmkid - 1); i++) {
2252 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
2253 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
2254 ETH_ALEN);
2255 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID,
2256 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
2257 WLAN_PMKID_LEN);
2258 }
2259 cfg_priv->pmk_list->pmkids.npmkid--;
2260 } else
2261 err = -EINVAL;
2262
2263 err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
2264
2265 WL_TRACE("Exit\n");
2266 return err;
2267
2268}
2269
2270static s32
2271brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
2272{
2273 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2274 s32 err = 0;
2275
2276 WL_TRACE("Enter\n");
2277 CHECK_SYS_UP();
2278
2279 memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
2280 err = brcmf_update_pmklist(dev, cfg_priv->pmk_list, err);
2281
2282 WL_TRACE("Exit\n");
2283 return err;
2284
2285}
2286
2287static struct cfg80211_ops wl_cfg80211_ops = {
2288 .change_virtual_intf = brcmf_cfg80211_change_iface,
2289 .scan = brcmf_cfg80211_scan,
2290 .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
2291 .join_ibss = brcmf_cfg80211_join_ibss,
2292 .leave_ibss = brcmf_cfg80211_leave_ibss,
2293 .get_station = brcmf_cfg80211_get_station,
2294 .set_tx_power = brcmf_cfg80211_set_tx_power,
2295 .get_tx_power = brcmf_cfg80211_get_tx_power,
2296 .add_key = brcmf_cfg80211_add_key,
2297 .del_key = brcmf_cfg80211_del_key,
2298 .get_key = brcmf_cfg80211_get_key,
2299 .set_default_key = brcmf_cfg80211_config_default_key,
2300 .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
2301 .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
2302 .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
2303 .connect = brcmf_cfg80211_connect,
2304 .disconnect = brcmf_cfg80211_disconnect,
2305 .suspend = brcmf_cfg80211_suspend,
2306 .resume = brcmf_cfg80211_resume,
2307 .set_pmksa = brcmf_cfg80211_set_pmksa,
2308 .del_pmksa = brcmf_cfg80211_del_pmksa,
2309 .flush_pmksa = brcmf_cfg80211_flush_pmksa
2310};
2311
2312static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
2313{
2314 s32 err = 0;
2315
2316 switch (mode) {
2317 case WL_MODE_BSS:
2318 return NL80211_IFTYPE_STATION;
2319 case WL_MODE_IBSS:
2320 return NL80211_IFTYPE_ADHOC;
2321 default:
2322 return NL80211_IFTYPE_UNSPECIFIED;
2323 }
2324
2325 return err;
2326}
2327
2328static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
2329 struct device *dev)
2330{
2331 struct wireless_dev *wdev;
2332 s32 err = 0;
2333
2334 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
2335 if (unlikely(!wdev)) {
2336 WL_ERR("Could not allocate wireless device\n");
2337 return ERR_PTR(-ENOMEM);
2338 }
2339 wdev->wiphy =
2340 wiphy_new(&wl_cfg80211_ops,
2341 sizeof(struct brcmf_cfg80211_priv) + sizeof_iface);
2342 if (unlikely(!wdev->wiphy)) {
2343 WL_ERR("Couldn not allocate wiphy device\n");
2344 err = -ENOMEM;
2345 goto wiphy_new_out;
2346 }
2347 set_wiphy_dev(wdev->wiphy, dev);
2348 wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
2349 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
2350 wdev->wiphy->interface_modes =
2351 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
2352 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
2353 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
2354 * it as 11a by default.
2355 * This will be updated with
2356 * 11n phy tables in
2357 * "ifconfig up"
2358 * if phy has 11n capability
2359 */
2360 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2361 wdev->wiphy->cipher_suites = __wl_cipher_suites;
2362 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
2363#ifndef WL_POWERSAVE_DISABLED
2364 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
2365 * save mode
2366 * by default
2367 */
2368#else
2369 wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
2370#endif /* !WL_POWERSAVE_DISABLED */
2371 err = wiphy_register(wdev->wiphy);
2372 if (unlikely(err < 0)) {
2373 WL_ERR("Couldn not register wiphy device (%d)\n", err);
2374 goto wiphy_register_out;
2375 }
2376 return wdev;
2377
2378wiphy_register_out:
2379 wiphy_free(wdev->wiphy);
2380
2381wiphy_new_out:
2382 kfree(wdev);
2383
2384 return ERR_PTR(err);
2385}
2386
2387static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
2388{
2389 struct wireless_dev *wdev = cfg_to_wdev(cfg_priv);
2390
2391 if (unlikely(!wdev)) {
2392 WL_ERR("wdev is invalid\n");
2393 return;
2394 }
2395 wiphy_unregister(wdev->wiphy);
2396 wiphy_free(wdev->wiphy);
2397 kfree(wdev);
2398 cfg_to_wdev(cfg_priv) = NULL;
2399}
2400
2401static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
2402{
2403 struct brcmf_scan_results *bss_list;
2404 struct brcmf_bss_info *bi = NULL; /* must be initialized */
2405 s32 err = 0;
2406 int i;
2407
2408 bss_list = cfg_priv->bss_list;
2409 if (unlikely(bss_list->version != BRCMF_BSS_INFO_VERSION)) {
2410 WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
2411 bss_list->version);
2412 return -EOPNOTSUPP;
2413 }
2414 WL_SCAN("scanned AP count (%d)\n", bss_list->count);
2415 bi = next_bss(bss_list, bi);
2416 for_each_bss(bss_list, bi, i) {
2417 err = brcmf_inform_single_bss(cfg_priv, bi);
2418 if (unlikely(err))
2419 break;
2420 }
2421 return err;
2422}
2423
2424
2425static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
2426 struct brcmf_bss_info *bi)
2427{
2428 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2429 struct ieee80211_channel *notify_channel;
2430 struct cfg80211_bss *bss;
2431 struct ieee80211_supported_band *band;
2432 s32 err = 0;
2433 u16 channel;
2434 u32 freq;
2435 u64 notify_timestamp;
2436 u16 notify_capability;
2437 u16 notify_interval;
2438 u8 *notify_ie;
2439 size_t notify_ielen;
2440 s32 notify_signal;
2441
2442 if (unlikely(le32_to_cpu(bi->length) > WL_BSS_INFO_MAX)) {
2443 WL_ERR("Bss info is larger than buffer. Discarding\n");
2444 return 0;
2445 }
2446
2447 channel = bi->ctl_ch ? bi->ctl_ch :
2448 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2449
2450 if (channel <= CH_MAX_2G_CHANNEL)
2451 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2452 else
2453 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2454
2455 freq = ieee80211_channel_to_frequency(channel, band->band);
2456 notify_channel = ieee80211_get_channel(wiphy, freq);
2457
2458 notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
2459 notify_capability = le16_to_cpu(bi->capability);
2460 notify_interval = le16_to_cpu(bi->beacon_period);
2461 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2462 notify_ielen = le16_to_cpu(bi->ie_length);
2463 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2464
2465 WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
2466 bi->BSSID[0], bi->BSSID[1], bi->BSSID[2],
2467 bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]);
2468 WL_CONN("Channel: %d(%d)\n", channel, freq);
2469 WL_CONN("Capability: %X\n", notify_capability);
2470 WL_CONN("Beacon interval: %d\n", notify_interval);
2471 WL_CONN("Signal: %d\n", notify_signal);
2472 WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
2473
2474 bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
2475 notify_timestamp, notify_capability, notify_interval, notify_ie,
2476 notify_ielen, notify_signal, GFP_KERNEL);
2477
2478 if (unlikely(!bss)) {
2479 WL_ERR("cfg80211_inform_bss_frame error\n");
2480 return -EINVAL;
2481 }
2482
2483 return err;
2484}
2485
2486static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
2487 struct net_device *dev, const u8 *bssid)
2488{
2489 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2490 struct ieee80211_channel *notify_channel;
2491 struct brcmf_bss_info *bi = NULL;
2492 struct ieee80211_supported_band *band;
2493 u8 *buf = NULL;
2494 s32 err = 0;
2495 u16 channel;
2496 u32 freq;
2497 u64 notify_timestamp;
2498 u16 notify_capability;
2499 u16 notify_interval;
2500 u8 *notify_ie;
2501 size_t notify_ielen;
2502 s32 notify_signal;
2503
2504 WL_TRACE("Enter\n");
2505
2506 buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2507 if (buf == NULL) {
2508 WL_ERR("kzalloc() failed\n");
2509 err = -ENOMEM;
2510 goto CleanUp;
2511 }
2512
2513 *(u32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
2514
2515 err = brcmf_dev_ioctl(dev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
2516 if (unlikely(err)) {
2517 WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
2518 goto CleanUp;
2519 }
2520
2521 bi = (struct brcmf_bss_info *)(buf + 4);
2522
2523 channel = bi->ctl_ch ? bi->ctl_ch :
2524 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2525
2526 if (channel <= CH_MAX_2G_CHANNEL)
2527 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2528 else
2529 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2530
2531 freq = ieee80211_channel_to_frequency(channel, band->band);
2532 notify_channel = ieee80211_get_channel(wiphy, freq);
2533
2534 notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
2535 notify_capability = le16_to_cpu(bi->capability);
2536 notify_interval = le16_to_cpu(bi->beacon_period);
2537 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2538 notify_ielen = le16_to_cpu(bi->ie_length);
2539 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2540
2541 WL_CONN("channel: %d(%d)\n", channel, freq);
2542 WL_CONN("capability: %X\n", notify_capability);
2543 WL_CONN("beacon interval: %d\n", notify_interval);
2544 WL_CONN("signal: %d\n", notify_signal);
2545 WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
2546
2547 cfg80211_inform_bss(wiphy, notify_channel, bssid,
2548 notify_timestamp, notify_capability, notify_interval,
2549 notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
2550
2551CleanUp:
2552
2553 kfree(buf);
2554
2555 WL_TRACE("Exit\n");
2556
2557 return err;
2558}
2559
2560static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
2561 const struct brcmf_event_msg *e)
2562{
2563 u32 event = be32_to_cpu(e->event_type);
2564 u32 status = be32_to_cpu(e->status);
2565
2566 if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
2567 WL_CONN("Processing set ssid\n");
2568 cfg_priv->link_up = true;
2569 return true;
2570 }
2571
2572 return false;
2573}
2574
2575static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
2576 const struct brcmf_event_msg *e)
2577{
2578 u32 event = be32_to_cpu(e->event_type);
2579 u16 flags = be16_to_cpu(e->flags);
2580
2581 if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
2582 WL_CONN("Processing link down\n");
2583 return true;
2584 }
2585 return false;
2586}
2587
2588static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
2589 const struct brcmf_event_msg *e)
2590{
2591 u32 event = be32_to_cpu(e->event_type);
2592 u32 status = be32_to_cpu(e->status);
2593
2594 if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
2595 WL_CONN("Processing Link %s & no network found\n",
2596 be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
2597 "up" : "down");
2598 return true;
2599 }
2600
2601 if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
2602 WL_CONN("Processing connecting & no network found\n");
2603 return true;
2604 }
2605
2606 return false;
2607}
2608
2609static s32
2610brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
2611 struct net_device *ndev,
2612 const struct brcmf_event_msg *e, void *data)
2613{
2614 s32 err = 0;
2615
2616 if (brcmf_is_linkup(cfg_priv, e)) {
2617 WL_CONN("Linkup\n");
2618 if (brcmf_is_ibssmode(cfg_priv)) {
2619 brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
2620 WL_PROF_BSSID);
2621 wl_inform_ibss(cfg_priv, ndev, e->addr);
2622 cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
2623 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
2624 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
2625 } else
2626 brcmf_bss_connect_done(cfg_priv, ndev, e, data, true);
2627 } else if (brcmf_is_linkdown(cfg_priv, e)) {
2628 WL_CONN("Linkdown\n");
2629 if (brcmf_is_ibssmode(cfg_priv)) {
2630 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
2631 if (test_and_clear_bit(WL_STATUS_CONNECTED,
2632 &cfg_priv->status))
2633 brcmf_link_down(cfg_priv);
2634 } else {
2635 brcmf_bss_connect_done(cfg_priv, ndev, e, data, false);
2636 if (test_and_clear_bit(WL_STATUS_CONNECTED,
2637 &cfg_priv->status)) {
2638 cfg80211_disconnected(ndev, 0, NULL, 0,
2639 GFP_KERNEL);
2640 brcmf_link_down(cfg_priv);
2641 }
2642 }
2643 brcmf_init_prof(cfg_priv->profile);
2644 } else if (brcmf_is_nonetwork(cfg_priv, e)) {
2645 if (brcmf_is_ibssmode(cfg_priv))
2646 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
2647 else
2648 brcmf_bss_connect_done(cfg_priv, ndev, e, data, false);
2649 }
2650
2651 return err;
2652}
2653
2654static s32
2655brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
2656 struct net_device *ndev,
2657 const struct brcmf_event_msg *e, void *data)
2658{
2659 s32 err = 0;
2660 u32 event = be32_to_cpu(e->event_type);
2661 u32 status = be32_to_cpu(e->status);
2662
2663 if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
2664 if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
2665 brcmf_bss_roaming_done(cfg_priv, ndev, e, data);
2666 else
2667 brcmf_bss_connect_done(cfg_priv, ndev, e, data, true);
2668 }
2669
2670 return err;
2671}
2672
2673static __used s32
2674brcmf_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
2675{
2676 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
2677 u32 buflen;
2678
2679 buflen = brcmu_mkiovar(name, buf, len, cfg_priv->ioctl_buf,
2680 WL_IOCTL_LEN_MAX);
2681 BUG_ON(!buflen);
2682
2683 return brcmf_dev_ioctl(dev, BRCMF_C_SET_VAR, cfg_priv->ioctl_buf,
2684 buflen);
2685}
2686
2687static s32
2688brcmf_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
2689 s32 buf_len)
2690{
2691 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(dev);
2692 u32 len;
2693 s32 err = 0;
2694
2695 len = brcmu_mkiovar(name, NULL, 0, cfg_priv->ioctl_buf,
2696 WL_IOCTL_LEN_MAX);
2697 BUG_ON(!len);
2698 err = brcmf_dev_ioctl(dev, BRCMF_C_GET_VAR, (void *)cfg_priv->ioctl_buf,
2699 WL_IOCTL_LEN_MAX);
2700 if (unlikely(err)) {
2701 WL_ERR("error (%d)\n", err);
2702 return err;
2703 }
2704 memcpy(buf, cfg_priv->ioctl_buf, buf_len);
2705
2706 return err;
2707}
2708
2709static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
2710{
2711 struct net_device *ndev = cfg_to_ndev(cfg_priv);
2712 struct brcmf_cfg80211_assoc_ielen *assoc_info;
2713 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2714 u32 req_len;
2715 u32 resp_len;
2716 s32 err = 0;
2717
2718 brcmf_clear_assoc_ies(cfg_priv);
2719
2720 err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf,
2721 WL_ASSOC_INFO_MAX);
2722 if (unlikely(err)) {
2723 WL_ERR("could not get assoc info (%d)\n", err);
2724 return err;
2725 }
2726 assoc_info = (struct brcmf_cfg80211_assoc_ielen *)cfg_priv->extra_buf;
2727 req_len = assoc_info->req_len;
2728 resp_len = assoc_info->resp_len;
2729 if (req_len) {
2730 err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
2731 cfg_priv->extra_buf,
2732 WL_ASSOC_INFO_MAX);
2733 if (unlikely(err)) {
2734 WL_ERR("could not get assoc req (%d)\n", err);
2735 return err;
2736 }
2737 conn_info->req_ie_len = req_len;
2738 conn_info->req_ie =
2739 kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len,
2740 GFP_KERNEL);
2741 } else {
2742 conn_info->req_ie_len = 0;
2743 conn_info->req_ie = NULL;
2744 }
2745 if (resp_len) {
2746 err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
2747 cfg_priv->extra_buf,
2748 WL_ASSOC_INFO_MAX);
2749 if (unlikely(err)) {
2750 WL_ERR("could not get assoc resp (%d)\n", err);
2751 return err;
2752 }
2753 conn_info->resp_ie_len = resp_len;
2754 conn_info->resp_ie =
2755 kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len,
2756 GFP_KERNEL);
2757 } else {
2758 conn_info->resp_ie_len = 0;
2759 conn_info->resp_ie = NULL;
2760 }
2761 WL_CONN("req len (%d) resp len (%d)\n",
2762 conn_info->req_ie_len, conn_info->resp_ie_len);
2763
2764 return err;
2765}
2766
2767static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
2768{
2769 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2770
2771 kfree(conn_info->req_ie);
2772 conn_info->req_ie = NULL;
2773 conn_info->req_ie_len = 0;
2774 kfree(conn_info->resp_ie);
2775 conn_info->resp_ie = NULL;
2776 conn_info->resp_ie_len = 0;
2777}
2778
2779
2780static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
2781 size_t *join_params_size)
2782{
2783 chanspec_t chanspec = 0;
2784
2785 if (ch != 0) {
2786 join_params->params.chanspec_num = 1;
2787 join_params->params.chanspec_list[0] = ch;
2788
2789 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
2790 chanspec |= WL_CHANSPEC_BAND_2G;
2791 else
2792 chanspec |= WL_CHANSPEC_BAND_5G;
2793
2794 chanspec |= WL_CHANSPEC_BW_20;
2795 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
2796
2797 *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
2798 join_params->params.chanspec_num * sizeof(chanspec_t);
2799
2800 join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
2801 join_params->params.chanspec_list[0] |= chanspec;
2802 join_params->params.chanspec_list[0] =
2803 cpu_to_le16(join_params->params.chanspec_list[0]);
2804
2805 join_params->params.chanspec_num =
2806 cpu_to_le32(join_params->params.chanspec_num);
2807
2808 WL_CONN("join_params->params.chanspec_list[0]= %#X,"
2809 "channel %d, chanspec %#X\n",
2810 join_params->params.chanspec_list[0], ch, chanspec);
2811 }
2812}
2813
2814static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
2815{
2816 struct brcmf_bss_info *bi;
2817 struct brcmf_ssid *ssid;
2818 struct brcmu_tlv *tim;
2819 u16 beacon_interval;
2820 u8 dtim_period;
2821 size_t ie_len;
2822 u8 *ie;
2823 s32 err = 0;
2824
2825 WL_TRACE("Enter\n");
2826 if (brcmf_is_ibssmode(cfg_priv))
2827 return err;
2828
2829 ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID);
2830
2831 *(u32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
2832 err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO,
2833 cfg_priv->extra_buf, WL_EXTRA_BUF_MAX);
2834 if (unlikely(err)) {
2835 WL_ERR("Could not get bss info %d\n", err);
2836 goto update_bss_info_out;
2837 }
2838
2839 bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4);
2840 err = brcmf_inform_single_bss(cfg_priv, bi);
2841 if (unlikely(err))
2842 goto update_bss_info_out;
2843
2844 ie = ((u8 *)bi) + bi->ie_offset;
2845 ie_len = bi->ie_length;
2846 beacon_interval = cpu_to_le16(bi->beacon_period);
2847
2848 tim = brcmu_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
2849 if (tim)
2850 dtim_period = tim->data[1];
2851 else {
2852 /*
2853 * active scan was done so we could not get dtim
2854 * information out of probe response.
2855 * so we speficially query dtim information to dongle.
2856 */
2857 u32 var;
2858 err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv),
2859 "dtim_assoc", &var);
2860 if (unlikely(err)) {
2861 WL_ERR("wl dtim_assoc failed (%d)\n", err);
2862 goto update_bss_info_out;
2863 }
2864 dtim_period = (u8)var;
2865 }
2866
2867 brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT);
2868 brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
2869
2870update_bss_info_out:
2871 WL_TRACE("Exit");
2872 return err;
2873}
2874
2875static s32
2876brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
2877 struct net_device *ndev,
2878 const struct brcmf_event_msg *e, void *data)
2879{
2880 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2881 s32 err = 0;
2882
2883 WL_TRACE("Enter\n");
2884
2885 brcmf_get_assoc_ies(cfg_priv);
2886 brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
2887 brcmf_update_bss_info(cfg_priv);
2888
2889 cfg80211_roamed(ndev, NULL,
2890 (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
2891 conn_info->req_ie, conn_info->req_ie_len,
2892 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
2893 WL_CONN("Report roaming result\n");
2894
2895 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
2896 WL_TRACE("Exit\n");
2897 return err;
2898}
2899
2900static s32
2901brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
2902 struct net_device *ndev, const struct brcmf_event_msg *e,
2903 void *data, bool completed)
2904{
2905 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2906 s32 err = 0;
2907
2908 WL_TRACE("Enter\n");
2909
2910 if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
2911 if (completed) {
2912 brcmf_get_assoc_ies(cfg_priv);
2913 brcmf_update_prof(cfg_priv, NULL, &e->addr,
2914 WL_PROF_BSSID);
2915 brcmf_update_bss_info(cfg_priv);
2916 }
2917 cfg80211_connect_result(ndev,
2918 (u8 *)brcmf_read_prof(cfg_priv,
2919 WL_PROF_BSSID),
2920 conn_info->req_ie,
2921 conn_info->req_ie_len,
2922 conn_info->resp_ie,
2923 conn_info->resp_ie_len,
2924 completed ? WLAN_STATUS_SUCCESS :
2925 WLAN_STATUS_AUTH_TIMEOUT,
2926 GFP_KERNEL);
2927 if (completed)
2928 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
2929 WL_CONN("Report connect result - connection %s\n",
2930 completed ? "succeeded" : "failed");
2931 }
2932 WL_TRACE("Exit\n");
2933 return err;
2934}
2935
2936static s32
2937brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
2938 struct net_device *ndev,
2939 const struct brcmf_event_msg *e, void *data)
2940{
2941 u16 flags = be16_to_cpu(e->flags);
2942 enum nl80211_key_type key_type;
2943
2944 rtnl_lock();
2945 if (flags & BRCMF_EVENT_MSG_GROUP)
2946 key_type = NL80211_KEYTYPE_GROUP;
2947 else
2948 key_type = NL80211_KEYTYPE_PAIRWISE;
2949
2950 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
2951 NULL, GFP_KERNEL);
2952 rtnl_unlock();
2953
2954 return 0;
2955}
2956
2957static s32
2958brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
2959 struct net_device *ndev,
2960 const struct brcmf_event_msg *e, void *data)
2961{
2962 struct brcmf_channel_info channel_inform;
2963 struct brcmf_scan_results *bss_list;
2964 u32 len = WL_SCAN_BUF_MAX;
2965 s32 err = 0;
2966 bool scan_abort = false;
2967
2968 WL_TRACE("Enter\n");
2969
2970 if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) {
2971 WL_TRACE("Exit\n");
2972 return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
2973 }
2974
2975 if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING,
2976 &cfg_priv->status))) {
2977 WL_ERR("Scan complete while device not scanning\n");
2978 scan_abort = true;
2979 err = -EINVAL;
2980 goto scan_done_out;
2981 }
2982
2983 err = brcmf_dev_ioctl(ndev, BRCMF_C_GET_CHANNEL, &channel_inform,
2984 sizeof(channel_inform));
2985 if (unlikely(err)) {
2986 WL_ERR("scan busy (%d)\n", err);
2987 scan_abort = true;
2988 goto scan_done_out;
2989 }
2990 channel_inform.scan_channel = le32_to_cpu(channel_inform.scan_channel);
2991 if (unlikely(channel_inform.scan_channel)) {
2992
2993 WL_CONN("channel_inform.scan_channel (%d)\n",
2994 channel_inform.scan_channel);
2995 }
2996 cfg_priv->bss_list = cfg_priv->scan_results;
2997 bss_list = cfg_priv->bss_list;
2998 memset(bss_list, 0, len);
2999 bss_list->buflen = cpu_to_le32(len);
3000
3001 err = brcmf_dev_ioctl(ndev, BRCMF_C_SCAN_RESULTS, bss_list, len);
3002 if (unlikely(err)) {
3003 WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
3004 err = -EINVAL;
3005 scan_abort = true;
3006 goto scan_done_out;
3007 }
3008 bss_list->buflen = le32_to_cpu(bss_list->buflen);
3009 bss_list->version = le32_to_cpu(bss_list->version);
3010 bss_list->count = le32_to_cpu(bss_list->count);
3011
3012 err = brcmf_inform_bss(cfg_priv);
3013 if (err) {
3014 scan_abort = true;
3015 goto scan_done_out;
3016 }
3017
3018scan_done_out:
3019 if (cfg_priv->scan_request) {
3020 WL_SCAN("calling cfg80211_scan_done\n");
3021 cfg80211_scan_done(cfg_priv->scan_request, scan_abort);
3022 brcmf_set_mpc(ndev, 1);
3023 cfg_priv->scan_request = NULL;
3024 }
3025
3026 WL_TRACE("Exit\n");
3027
3028 return err;
3029}
3030
3031static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
3032{
3033 conf->mode = (u32)-1;
3034 conf->frag_threshold = (u32)-1;
3035 conf->rts_threshold = (u32)-1;
3036 conf->retry_short = (u32)-1;
3037 conf->retry_long = (u32)-1;
3038 conf->tx_power = -1;
3039}
3040
3041static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
3042{
3043 memset(prof, 0, sizeof(*prof));
3044}
3045
3046static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
3047{
3048 memset(el, 0, sizeof(*el));
3049 el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
3050 el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
3051 el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
3052 el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
3053 el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
3054}
3055
3056static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3057{
3058 cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
3059 if (unlikely(!cfg_priv->scan_results)) {
3060 WL_ERR("Scan results alloc failed\n");
3061 goto init_priv_mem_out;
3062 }
3063 cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
3064 if (unlikely(!cfg_priv->conf)) {
3065 WL_ERR("wl_conf alloc failed\n");
3066 goto init_priv_mem_out;
3067 }
3068 cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
3069 if (unlikely(!cfg_priv->profile)) {
3070 WL_ERR("wl_profile alloc failed\n");
3071 goto init_priv_mem_out;
3072 }
3073 cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
3074 if (unlikely(!cfg_priv->bss_info)) {
3075 WL_ERR("Bss information alloc failed\n");
3076 goto init_priv_mem_out;
3077 }
3078 cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
3079 GFP_KERNEL);
3080 if (unlikely(!cfg_priv->scan_req_int)) {
3081 WL_ERR("Scan req alloc failed\n");
3082 goto init_priv_mem_out;
3083 }
3084 cfg_priv->ioctl_buf = kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
3085 if (unlikely(!cfg_priv->ioctl_buf)) {
3086 WL_ERR("Ioctl buf alloc failed\n");
3087 goto init_priv_mem_out;
3088 }
3089 cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
3090 if (unlikely(!cfg_priv->extra_buf)) {
3091 WL_ERR("Extra buf alloc failed\n");
3092 goto init_priv_mem_out;
3093 }
3094 cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
3095 if (unlikely(!cfg_priv->iscan)) {
3096 WL_ERR("Iscan buf alloc failed\n");
3097 goto init_priv_mem_out;
3098 }
3099 cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
3100 if (unlikely(!cfg_priv->pmk_list)) {
3101 WL_ERR("pmk list alloc failed\n");
3102 goto init_priv_mem_out;
3103 }
3104
3105 return 0;
3106
3107init_priv_mem_out:
3108 brcmf_deinit_priv_mem(cfg_priv);
3109
3110 return -ENOMEM;
3111}
3112
3113static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3114{
3115 kfree(cfg_priv->scan_results);
3116 cfg_priv->scan_results = NULL;
3117 kfree(cfg_priv->bss_info);
3118 cfg_priv->bss_info = NULL;
3119 kfree(cfg_priv->conf);
3120 cfg_priv->conf = NULL;
3121 kfree(cfg_priv->profile);
3122 cfg_priv->profile = NULL;
3123 kfree(cfg_priv->scan_req_int);
3124 cfg_priv->scan_req_int = NULL;
3125 kfree(cfg_priv->ioctl_buf);
3126 cfg_priv->ioctl_buf = NULL;
3127 kfree(cfg_priv->extra_buf);
3128 cfg_priv->extra_buf = NULL;
3129 kfree(cfg_priv->iscan);
3130 cfg_priv->iscan = NULL;
3131 kfree(cfg_priv->pmk_list);
3132 cfg_priv->pmk_list = NULL;
3133}
3134
3135static s32 brcmf_create_event_handler(struct brcmf_cfg80211_priv *cfg_priv)
3136{
3137 sema_init(&cfg_priv->event_sync, 0);
3138 cfg_priv->event_tsk = kthread_run(brcmf_event_handler, cfg_priv,
3139 "wl_event_handler");
3140 if (IS_ERR(cfg_priv->event_tsk)) {
3141 cfg_priv->event_tsk = NULL;
3142 WL_ERR("failed to create event thread\n");
3143 return -ENOMEM;
3144 }
3145 return 0;
3146}
3147
3148static void brcmf_destroy_event_handler(struct brcmf_cfg80211_priv *cfg_priv)
3149{
3150 if (cfg_priv->event_tsk) {
3151 send_sig(SIGTERM, cfg_priv->event_tsk, 1);
3152 kthread_stop(cfg_priv->event_tsk);
3153 cfg_priv->event_tsk = NULL;
3154 }
3155}
3156
3157static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv)
3158{
3159 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
3160
3161 if (cfg_priv->iscan_on && iscan->tsk) {
3162 iscan->state = WL_ISCAN_STATE_IDLE;
3163 send_sig(SIGTERM, iscan->tsk, 1);
3164 kthread_stop(iscan->tsk);
3165 iscan->tsk = NULL;
3166 }
3167}
3168
3169static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
3170 bool aborted)
3171{
3172 struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
3173 struct net_device *ndev = cfg_to_ndev(cfg_priv);
3174
3175 if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING,
3176 &cfg_priv->status))) {
3177 WL_ERR("Scan complete while device not scanning\n");
3178 return;
3179 }
3180 if (likely(cfg_priv->scan_request)) {
3181 WL_SCAN("ISCAN Completed scan: %s\n",
3182 aborted ? "Aborted" : "Done");
3183 cfg80211_scan_done(cfg_priv->scan_request, aborted);
3184 brcmf_set_mpc(ndev, 1);
3185 cfg_priv->scan_request = NULL;
3186 }
3187 cfg_priv->iscan_kickstart = false;
3188}
3189
3190static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
3191{
3192 if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
3193 WL_SCAN("wake up iscan\n");
3194 up(&iscan->sync);
3195 return 0;
3196 }
3197
3198 return -EIO;
3199}
3200
3201static s32
3202brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
3203 struct brcmf_scan_results **bss_list)
3204{
3205 struct brcmf_iscan_results list;
3206 struct brcmf_scan_results *results;
3207 struct brcmf_iscan_results *list_buf;
3208 s32 err = 0;
3209
3210 memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
3211 list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
3212 results = &list_buf->results;
3213 results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
3214 results->version = 0;
3215 results->count = 0;
3216
3217 memset(&list, 0, sizeof(list));
3218 list.results.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
3219 err = brcmf_dev_iovar_getbuf(iscan->dev, "iscanresults", &list,
3220 BRCMF_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
3221 WL_ISCAN_BUF_MAX);
3222 if (unlikely(err)) {
3223 WL_ERR("error (%d)\n", err);
3224 return err;
3225 }
3226 results->buflen = le32_to_cpu(results->buflen);
3227 results->version = le32_to_cpu(results->version);
3228 results->count = le32_to_cpu(results->count);
3229 WL_SCAN("results->count = %d\n", results->count);
3230 WL_SCAN("results->buflen = %d\n", results->buflen);
3231 *status = le32_to_cpu(list_buf->status);
3232 *bss_list = results;
3233
3234 return err;
3235}
3236
3237static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv)
3238{
3239 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
3240 s32 err = 0;
3241
3242 iscan->state = WL_ISCAN_STATE_IDLE;
3243 rtnl_lock();
3244 brcmf_inform_bss(cfg_priv);
3245 brcmf_notify_iscan_complete(iscan, false);
3246 rtnl_unlock();
3247
3248 return err;
3249}
3250
3251static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
3252{
3253 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
3254 s32 err = 0;
3255
3256 /* Reschedule the timer */
3257 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
3258 iscan->timer_on = 1;
3259
3260 return err;
3261}
3262
3263static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv)
3264{
3265 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
3266 s32 err = 0;
3267
3268 rtnl_lock();
3269 brcmf_inform_bss(cfg_priv);
3270 brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
3271 rtnl_unlock();
3272 /* Reschedule the timer */
3273 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
3274 iscan->timer_on = 1;
3275
3276 return err;
3277}
3278
3279static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv)
3280{
3281 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
3282 s32 err = 0;
3283
3284 iscan->state = WL_ISCAN_STATE_IDLE;
3285 rtnl_lock();
3286 brcmf_notify_iscan_complete(iscan, true);
3287 rtnl_unlock();
3288
3289 return err;
3290}
3291
3292static s32 brcmf_iscan_thread(void *data)
3293{
3294 struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
3295 struct brcmf_cfg80211_iscan_ctrl *iscan =
3296 (struct brcmf_cfg80211_iscan_ctrl *)data;
3297 struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
3298 struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
3299 u32 status;
3300 int err = 0;
3301
3302 sched_setscheduler(current, SCHED_FIFO, &param);
3303 allow_signal(SIGTERM);
3304 status = BRCMF_SCAN_RESULTS_PARTIAL;
3305 while (likely(!down_interruptible(&iscan->sync))) {
3306 if (kthread_should_stop())
3307 break;
3308 if (iscan->timer_on) {
3309 del_timer_sync(&iscan->timer);
3310 iscan->timer_on = 0;
3311 }
3312 rtnl_lock();
3313 err = brcmf_get_iscan_results(iscan, &status,
3314 &cfg_priv->bss_list);
3315 if (unlikely(err)) {
3316 status = BRCMF_SCAN_RESULTS_ABORTED;
3317 WL_ERR("Abort iscan\n");
3318 }
3319 rtnl_unlock();
3320 el->handler[status](cfg_priv);
3321 }
3322 if (iscan->timer_on) {
3323 del_timer_sync(&iscan->timer);
3324 iscan->timer_on = 0;
3325 }
3326 WL_SCAN("ISCAN thread terminated\n");
3327
3328 return 0;
3329}
3330
3331static void brcmf_iscan_timer(unsigned long data)
3332{
3333 struct brcmf_cfg80211_iscan_ctrl *iscan =
3334 (struct brcmf_cfg80211_iscan_ctrl *)data;
3335
3336 if (iscan) {
3337 iscan->timer_on = 0;
3338 WL_SCAN("timer expired\n");
3339 brcmf_wakeup_iscan(iscan);
3340 }
3341}
3342
3343static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv)
3344{
3345 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
3346 int err = 0;
3347
3348 if (cfg_priv->iscan_on && !iscan->tsk) {
3349 iscan->state = WL_ISCAN_STATE_IDLE;
3350 sema_init(&iscan->sync, 0);
3351 iscan->tsk = kthread_run(brcmf_iscan_thread, iscan, "wl_iscan");
3352 if (IS_ERR(iscan->tsk)) {
3353 WL_ERR("Could not create iscan thread\n");
3354 iscan->tsk = NULL;
3355 return -ENOMEM;
3356 }
3357 }
3358
3359 return err;
3360}
3361
3362static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
3363{
3364 memset(el, 0, sizeof(*el));
3365 el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
3366 el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
3367 el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
3368 el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
3369 el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
3370}
3371
3372static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
3373{
3374 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
3375 int err = 0;
3376
3377 if (cfg_priv->iscan_on) {
3378 iscan->dev = cfg_to_ndev(cfg_priv);
3379 iscan->state = WL_ISCAN_STATE_IDLE;
3380 brcmf_init_iscan_eloop(&iscan->el);
3381 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
3382 init_timer(&iscan->timer);
3383 iscan->timer.data = (unsigned long) iscan;
3384 iscan->timer.function = brcmf_iscan_timer;
3385 sema_init(&iscan->sync, 0);
3386 iscan->tsk = kthread_run(brcmf_iscan_thread, iscan, "wl_iscan");
3387 if (IS_ERR(iscan->tsk)) {
3388 WL_ERR("Could not create iscan thread\n");
3389 iscan->tsk = NULL;
3390 return -ENOMEM;
3391 }
3392 iscan->data = cfg_priv;
3393 }
3394
3395 return err;
3396}
3397
3398static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
3399{
3400 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
3401 s32 err = 0;
3402
3403 cfg_priv->scan_request = NULL;
3404 cfg_priv->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
3405 cfg_priv->iscan_on = true; /* iscan on & off switch.
3406 we enable iscan per default */
3407 cfg_priv->roam_on = false; /* roam on & off switch.
3408 we enable roam per default */
3409
3410 cfg_priv->iscan_kickstart = false;
3411 cfg_priv->active_scan = true; /* we do active scan for
3412 specific scan per default */
3413 cfg_priv->dongle_up = false; /* dongle is not up yet */
3414 brcmf_init_eq(cfg_priv);
3415 err = brcmf_init_priv_mem(cfg_priv);
3416 if (unlikely(err))
3417 return err;
3418 if (unlikely(brcmf_create_event_handler(cfg_priv)))
3419 return -ENOMEM;
3420 brcmf_init_eloop_handler(&cfg_priv->el);
3421 mutex_init(&cfg_priv->usr_sync);
3422 err = brcmf_init_iscan(cfg_priv);
3423 if (unlikely(err))
3424 return err;
3425 brcmf_init_conf(cfg_priv->conf);
3426 brcmf_init_prof(cfg_priv->profile);
3427 brcmf_link_down(cfg_priv);
3428
3429 return err;
3430}
3431
3432static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
3433{
3434 brcmf_destroy_event_handler(cfg_priv);
3435 cfg_priv->dongle_up = false; /* dongle down */
3436 brcmf_flush_eq(cfg_priv);
3437 brcmf_link_down(cfg_priv);
3438 brcmf_term_iscan(cfg_priv);
3439 brcmf_deinit_priv_mem(cfg_priv);
3440}
3441
3442s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data)
3443{
3444 struct wireless_dev *wdev;
3445 struct brcmf_cfg80211_priv *cfg_priv;
3446 struct brcmf_cfg80211_iface *ci;
3447 s32 err = 0;
3448
3449 if (unlikely(!ndev)) {
3450 WL_ERR("ndev is invalid\n");
3451 return -ENODEV;
3452 }
3453 cfg80211_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
3454 if (unlikely(!cfg80211_dev)) {
3455 WL_ERR("wl_cfg80211_dev is invalid\n");
3456 return -ENOMEM;
3457 }
3458 WL_INFO("func %p\n", brcmf_cfg80211_get_sdio_func());
3459 wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface),
3460 &brcmf_cfg80211_get_sdio_func()->dev);
3461 if (IS_ERR(wdev))
3462 return -ENOMEM;
3463
3464 wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
3465 cfg_priv = wdev_to_cfg(wdev);
3466 cfg_priv->wdev = wdev;
3467 cfg_priv->pub = data;
3468 ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci;
3469 ci->cfg_priv = cfg_priv;
3470 ndev->ieee80211_ptr = wdev;
3471 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
3472 wdev->netdev = ndev;
3473 err = wl_init_priv(cfg_priv);
3474 if (unlikely(err)) {
3475 WL_ERR("Failed to init iwm_priv (%d)\n", err);
3476 goto cfg80211_attach_out;
3477 }
3478 brcmf_set_drvdata(cfg80211_dev, ci);
3479
3480 return err;
3481
3482cfg80211_attach_out:
3483 brcmf_free_wdev(cfg_priv);
3484 return err;
3485}
3486
3487void brcmf_cfg80211_detach(void)
3488{
3489 struct brcmf_cfg80211_priv *cfg_priv;
3490
3491 cfg_priv = WL_PRIV_GET();
3492
3493 wl_deinit_priv(cfg_priv);
3494 brcmf_free_wdev(cfg_priv);
3495 brcmf_set_drvdata(cfg80211_dev, NULL);
3496 kfree(cfg80211_dev);
3497 cfg80211_dev = NULL;
3498 brcmf_clear_sdio_func();
3499}
3500
3501static void brcmf_wakeup_event(struct brcmf_cfg80211_priv *cfg_priv)
3502{
3503 up(&cfg_priv->event_sync);
3504}
3505
3506static s32 brcmf_event_handler(void *data)
3507{
3508 struct brcmf_cfg80211_priv *cfg_priv =
3509 (struct brcmf_cfg80211_priv *)data;
3510 struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
3511 struct brcmf_cfg80211_event_q *e;
3512
3513 sched_setscheduler(current, SCHED_FIFO, &param);
3514 allow_signal(SIGTERM);
3515 while (likely(!down_interruptible(&cfg_priv->event_sync))) {
3516 if (kthread_should_stop())
3517 break;
3518 e = brcmf_deq_event(cfg_priv);
3519 if (unlikely(!e)) {
3520 WL_ERR("event queue empty...\n");
3521 BUG();
3522 }
3523 WL_INFO("event type (%d)\n", e->etype);
3524 if (cfg_priv->el.handler[e->etype]) {
3525 cfg_priv->el.handler[e->etype](cfg_priv,
3526 cfg_to_ndev(cfg_priv),
3527 &e->emsg, e->edata);
3528 } else {
3529 WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
3530 }
3531 brcmf_put_event(e);
3532 }
3533 WL_INFO("was terminated\n");
3534 return 0;
3535}
3536
3537void
3538brcmf_cfg80211_event(struct net_device *ndev,
3539 const struct brcmf_event_msg *e, void *data)
3540{
3541 u32 event_type = be32_to_cpu(e->event_type);
3542 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3543
3544 if (likely(!brcmf_enq_event(cfg_priv, event_type, e, data)))
3545 brcmf_wakeup_event(cfg_priv);
3546}
3547
3548static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
3549{
3550 brcmf_init_eq_lock(cfg_priv);
3551 INIT_LIST_HEAD(&cfg_priv->eq_list);
3552}
3553
3554static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
3555{
3556 struct brcmf_cfg80211_event_q *e;
3557
3558 brcmf_lock_eq(cfg_priv);
3559 while (!list_empty(&cfg_priv->eq_list)) {
3560 e = list_first_entry(&cfg_priv->eq_list,
3561 struct brcmf_cfg80211_event_q, eq_list);
3562 list_del(&e->eq_list);
3563 kfree(e);
3564 }
3565 brcmf_unlock_eq(cfg_priv);
3566}
3567
3568/*
3569* retrieve first queued event from head
3570*/
3571
3572static struct brcmf_cfg80211_event_q *brcmf_deq_event(
3573 struct brcmf_cfg80211_priv *cfg_priv)
3574{
3575 struct brcmf_cfg80211_event_q *e = NULL;
3576
3577 brcmf_lock_eq(cfg_priv);
3578 if (likely(!list_empty(&cfg_priv->eq_list))) {
3579 e = list_first_entry(&cfg_priv->eq_list,
3580 struct brcmf_cfg80211_event_q, eq_list);
3581 list_del(&e->eq_list);
3582 }
3583 brcmf_unlock_eq(cfg_priv);
3584
3585 return e;
3586}
3587
3588/*
3589** push event to tail of the queue
3590*/
3591
3592static s32
3593brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
3594 const struct brcmf_event_msg *msg, void *data)
3595{
3596 struct brcmf_cfg80211_event_q *e;
3597 s32 err = 0;
3598
3599 e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL);
3600 if (unlikely(!e)) {
3601 WL_ERR("event alloc failed\n");
3602 return -ENOMEM;
3603 }
3604
3605 e->etype = event;
3606 memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
3607
3608 brcmf_lock_eq(cfg_priv);
3609 list_add_tail(&e->eq_list, &cfg_priv->eq_list);
3610 brcmf_unlock_eq(cfg_priv);
3611
3612 return err;
3613}
3614
3615static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
3616{
3617 kfree(e);
3618}
3619
3620void brcmf_cfg80211_sdio_func(void *func)
3621{
3622 cfg80211_sdio_func = (struct sdio_func *)func;
3623}
3624
3625static void brcmf_clear_sdio_func(void)
3626{
3627 cfg80211_sdio_func = NULL;
3628}
3629
3630struct sdio_func *brcmf_cfg80211_get_sdio_func(void)
3631{
3632 return cfg80211_sdio_func;
3633}
3634
3635static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
3636{
3637 s32 infra = 0;
3638 s32 err = 0;
3639
3640 switch (iftype) {
3641 case NL80211_IFTYPE_MONITOR:
3642 case NL80211_IFTYPE_WDS:
3643 WL_ERR("type (%d) : currently we do not support this mode\n",
3644 iftype);
3645 err = -EINVAL;
3646 return err;
3647 case NL80211_IFTYPE_ADHOC:
3648 infra = 0;
3649 break;
3650 case NL80211_IFTYPE_STATION:
3651 infra = 1;
3652 break;
3653 default:
3654 err = -EINVAL;
3655 WL_ERR("invalid type (%d)\n", iftype);
3656 return err;
3657 }
3658 infra = cpu_to_le32(infra);
3659 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_INFRA, &infra, sizeof(infra));
3660 if (unlikely(err)) {
3661 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
3662 return err;
3663 }
3664
3665 return 0;
3666}
3667
3668static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
3669{
3670 /* Room for "event_msgs" + '\0' + bitvec */
3671 s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
3672 s8 eventmask[BRCMF_EVENTING_MASK_LEN];
3673 s32 err = 0;
3674
3675 WL_TRACE("Enter\n");
3676
3677 /* Setup event_msgs */
3678 brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
3679 sizeof(iovbuf));
3680 err = brcmf_dev_ioctl(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
3681 if (unlikely(err)) {
3682 WL_ERR("Get event_msgs error (%d)\n", err);
3683 goto dongle_eventmsg_out;
3684 }
3685 memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
3686
3687 setbit(eventmask, BRCMF_E_SET_SSID);
3688 setbit(eventmask, BRCMF_E_ROAM);
3689 setbit(eventmask, BRCMF_E_PRUNE);
3690 setbit(eventmask, BRCMF_E_AUTH);
3691 setbit(eventmask, BRCMF_E_REASSOC);
3692 setbit(eventmask, BRCMF_E_REASSOC_IND);
3693 setbit(eventmask, BRCMF_E_DEAUTH_IND);
3694 setbit(eventmask, BRCMF_E_DISASSOC_IND);
3695 setbit(eventmask, BRCMF_E_DISASSOC);
3696 setbit(eventmask, BRCMF_E_JOIN);
3697 setbit(eventmask, BRCMF_E_ASSOC_IND);
3698 setbit(eventmask, BRCMF_E_PSK_SUP);
3699 setbit(eventmask, BRCMF_E_LINK);
3700 setbit(eventmask, BRCMF_E_NDIS_LINK);
3701 setbit(eventmask, BRCMF_E_MIC_ERROR);
3702 setbit(eventmask, BRCMF_E_PMKID_CACHE);
3703 setbit(eventmask, BRCMF_E_TXFAIL);
3704 setbit(eventmask, BRCMF_E_JOIN_START);
3705 setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
3706
3707 brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
3708 sizeof(iovbuf));
3709 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3710 if (unlikely(err)) {
3711 WL_ERR("Set event_msgs error (%d)\n", err);
3712 goto dongle_eventmsg_out;
3713 }
3714
3715dongle_eventmsg_out:
3716 WL_TRACE("Exit\n");
3717 return err;
3718}
3719
3720static s32
3721brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
3722{
3723 s8 iovbuf[32];
3724 s32 roamtrigger[2];
3725 s32 roam_delta[2];
3726 s32 err = 0;
3727
3728 /*
3729 * Setup timeout if Beacons are lost and roam is
3730 * off to report link down
3731 */
3732 if (roamvar) {
3733 brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout,
3734 sizeof(bcn_timeout), iovbuf, sizeof(iovbuf));
3735 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR,
3736 iovbuf, sizeof(iovbuf));
3737 if (unlikely(err)) {
3738 WL_ERR("bcn_timeout error (%d)\n", err);
3739 goto dongle_rom_out;
3740 }
3741 }
3742
3743 /*
3744 * Enable/Disable built-in roaming to allow supplicant
3745 * to take care of roaming
3746 */
3747 WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
3748 brcmu_mkiovar("roam_off", (char *)&roamvar,
3749 sizeof(roamvar), iovbuf, sizeof(iovbuf));
3750 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3751 if (unlikely(err)) {
3752 WL_ERR("roam_off error (%d)\n", err);
3753 goto dongle_rom_out;
3754 }
3755
3756 roamtrigger[0] = WL_ROAM_TRIGGER_LEVEL;
3757 roamtrigger[1] = BRCM_BAND_ALL;
3758 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_ROAM_TRIGGER,
3759 (void *)roamtrigger, sizeof(roamtrigger));
3760 if (unlikely(err)) {
3761 WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
3762 goto dongle_rom_out;
3763 }
3764
3765 roam_delta[0] = WL_ROAM_DELTA;
3766 roam_delta[1] = BRCM_BAND_ALL;
3767 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_ROAM_DELTA,
3768 (void *)roam_delta, sizeof(roam_delta));
3769 if (unlikely(err)) {
3770 WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
3771 goto dongle_rom_out;
3772 }
3773
3774dongle_rom_out:
3775 return err;
3776}
3777
3778static s32
3779brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
3780 s32 scan_unassoc_time, s32 scan_passive_time)
3781{
3782 s32 err = 0;
3783
3784 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
3785 &scan_assoc_time, sizeof(scan_assoc_time));
3786 if (err) {
3787 if (err == -EOPNOTSUPP)
3788 WL_INFO("Scan assoc time is not supported\n");
3789 else
3790 WL_ERR("Scan assoc time error (%d)\n", err);
3791 goto dongle_scantime_out;
3792 }
3793 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
3794 &scan_unassoc_time, sizeof(scan_unassoc_time));
3795 if (err) {
3796 if (err == -EOPNOTSUPP)
3797 WL_INFO("Scan unassoc time is not supported\n");
3798 else
3799 WL_ERR("Scan unassoc time error (%d)\n", err);
3800 goto dongle_scantime_out;
3801 }
3802
3803 err = brcmf_dev_ioctl(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
3804 &scan_passive_time, sizeof(scan_passive_time));
3805 if (err) {
3806 if (err == -EOPNOTSUPP)
3807 WL_INFO("Scan passive time is not supported\n");
3808 else
3809 WL_ERR("Scan passive time error (%d)\n", err);
3810 goto dongle_scantime_out;
3811 }
3812
3813dongle_scantime_out:
3814 return err;
3815}
3816
3817s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv, bool need_lock)
3818{
3819 struct net_device *ndev;
3820 struct wireless_dev *wdev;
3821 s32 err = 0;
3822
3823 if (cfg_priv->dongle_up)
3824 return err;
3825
3826 ndev = cfg_to_ndev(cfg_priv);
3827 wdev = ndev->ieee80211_ptr;
3828 if (need_lock)
3829 rtnl_lock();
3830
3831 brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
3832 WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
3833
3834 err = brcmf_dongle_eventmsg(ndev);
3835 if (unlikely(err))
3836 goto default_conf_out;
3837 err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
3838 WL_BEACON_TIMEOUT);
3839 if (unlikely(err))
3840 goto default_conf_out;
3841 err = brcmf_dongle_mode(ndev, wdev->iftype);
3842 if (unlikely(err && err != -EINPROGRESS))
3843 goto default_conf_out;
3844 err = brcmf_dongle_probecap(cfg_priv);
3845 if (unlikely(err))
3846 goto default_conf_out;
3847
3848 /* -EINPROGRESS: Call commit handler */
3849
3850default_conf_out:
3851 if (need_lock)
3852 rtnl_unlock();
3853
3854 cfg_priv->dongle_up = true;
3855
3856 return err;
3857
3858}
3859
3860static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
3861{
3862 struct wiphy *wiphy;
3863 s32 phy_list;
3864 s8 phy;
3865 s32 err = 0;
3866
3867 err = brcmf_dev_ioctl(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
3868 &phy_list, sizeof(phy_list));
3869 if (unlikely(err)) {
3870 WL_ERR("error (%d)\n", err);
3871 return err;
3872 }
3873
3874 phy = ((char *)&phy_list)[1];
3875 WL_INFO("%c phy\n", phy);
3876 if (phy == 'n' || phy == 'a') {
3877 wiphy = cfg_to_wiphy(cfg_priv);
3878 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
3879 }
3880
3881 return err;
3882}
3883
3884static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
3885{
3886 s32 err = 0;
3887
3888 set_bit(WL_STATUS_READY, &cfg_priv->status);
3889
3890 brcmf_debugfs_add_netdev_params(cfg_priv);
3891
3892 err = brcmf_config_dongle(cfg_priv, false);
3893 if (unlikely(err))
3894 return err;
3895
3896 brcmf_invoke_iscan(cfg_priv);
3897
3898 return err;
3899}
3900
3901static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
3902{
3903 /*
3904 * While going down, if associated with AP disassociate
3905 * from AP to save power
3906 */
3907 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
3908 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
3909 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
3910 WL_INFO("Disassociating from AP");
3911 brcmf_link_down(cfg_priv);
3912
3913 /* Make sure WPA_Supplicant receives all the event
3914 generated due to DISASSOC call to the fw to keep
3915 the state fw and WPA_Supplicant state consistent
3916 */
3917 rtnl_unlock();
3918 brcmf_delay(500);
3919 rtnl_lock();
3920 }
3921
3922 set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3923 brcmf_term_iscan(cfg_priv);
3924 if (cfg_priv->scan_request) {
3925 cfg80211_scan_done(cfg_priv->scan_request, true);
3926 /* May need to perform this to cover rmmod */
3927 /* wl_set_mpc(cfg_to_ndev(wl), 1); */
3928 cfg_priv->scan_request = NULL;
3929 }
3930 clear_bit(WL_STATUS_READY, &cfg_priv->status);
3931 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
3932 clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3933
3934 brcmf_debugfs_remove_netdev(cfg_priv);
3935
3936 return 0;
3937}
3938
3939s32 brcmf_cfg80211_up(void)
3940{
3941 struct brcmf_cfg80211_priv *cfg_priv;
3942 s32 err = 0;
3943
3944 cfg_priv = WL_PRIV_GET();
3945 mutex_lock(&cfg_priv->usr_sync);
3946 err = __brcmf_cfg80211_up(cfg_priv);
3947 mutex_unlock(&cfg_priv->usr_sync);
3948
3949 return err;
3950}
3951
3952s32 brcmf_cfg80211_down(void)
3953{
3954 struct brcmf_cfg80211_priv *cfg_priv;
3955 s32 err = 0;
3956
3957 cfg_priv = WL_PRIV_GET();
3958 mutex_lock(&cfg_priv->usr_sync);
3959 err = __brcmf_cfg80211_down(cfg_priv);
3960 mutex_unlock(&cfg_priv->usr_sync);
3961
3962 return err;
3963}
3964
3965static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
3966{
3967 return wl_update_wiphybands(cfg_priv);
3968}
3969
3970static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item)
3971{
3972 switch (item) {
3973 case WL_PROF_SEC:
3974 return &cfg_priv->profile->sec;
3975 case WL_PROF_BSSID:
3976 return &cfg_priv->profile->bssid;
3977 case WL_PROF_SSID:
3978 return &cfg_priv->profile->ssid;
3979 }
3980 WL_ERR("invalid item (%d)\n", item);
3981 return NULL;
3982}
3983
3984static s32
3985brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
3986 const struct brcmf_event_msg *e, void *data, s32 item)
3987{
3988 s32 err = 0;
3989 struct brcmf_ssid *ssid;
3990
3991 switch (item) {
3992 case WL_PROF_SSID:
3993 ssid = (struct brcmf_ssid *) data;
3994 memset(cfg_priv->profile->ssid.SSID, 0,
3995 sizeof(cfg_priv->profile->ssid.SSID));
3996 memcpy(cfg_priv->profile->ssid.SSID,
3997 ssid->SSID, ssid->SSID_len);
3998 cfg_priv->profile->ssid.SSID_len = ssid->SSID_len;
3999 break;
4000 case WL_PROF_BSSID:
4001 if (data)
4002 memcpy(cfg_priv->profile->bssid, data, ETH_ALEN);
4003 else
4004 memset(cfg_priv->profile->bssid, 0, ETH_ALEN);
4005 break;
4006 case WL_PROF_SEC:
4007 memcpy(&cfg_priv->profile->sec, data,
4008 sizeof(cfg_priv->profile->sec));
4009 break;
4010 case WL_PROF_BEACONINT:
4011 cfg_priv->profile->beacon_interval = *(u16 *)data;
4012 break;
4013 case WL_PROF_DTIMPERIOD:
4014 cfg_priv->profile->dtim_period = *(u8 *)data;
4015 break;
4016 default:
4017 WL_ERR("unsupported item (%d)\n", item);
4018 err = -EOPNOTSUPP;
4019 break;
4020 }
4021
4022 return err;
4023}
4024
4025static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
4026{
4027 return cfg_priv->conf->mode == WL_MODE_IBSS;
4028}
4029
4030static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
4031 u8 t, u8 l, u8 *v)
4032{
4033 struct brcmf_cfg80211_ie *ie = &cfg_priv->ie;
4034 s32 err = 0;
4035
4036 if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
4037 WL_ERR("ei crosses buffer boundary\n");
4038 return -ENOSPC;
4039 }
4040 ie->buf[ie->offset] = t;
4041 ie->buf[ie->offset + 1] = l;
4042 memcpy(&ie->buf[ie->offset + 2], v, l);
4043 ie->offset += l + 2;
4044
4045 return err;
4046}
4047
4048static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv)
4049{
4050 struct net_device *dev = NULL;
4051 s32 err = 0;
4052
4053 WL_TRACE("Enter\n");
4054
4055 if (cfg_priv->link_up) {
4056 dev = cfg_to_ndev(cfg_priv);
4057 WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
4058 err = brcmf_dev_ioctl(dev, BRCMF_C_DISASSOC, NULL, 0);
4059 if (unlikely(err))
4060 WL_ERR("WLC_DISASSOC failed (%d)\n", err);
4061 cfg_priv->link_up = false;
4062 }
4063 WL_TRACE("Exit\n");
4064}
4065
4066static void brcmf_lock_eq(struct brcmf_cfg80211_priv *cfg_priv)
4067{
4068 spin_lock_irq(&cfg_priv->eq_lock);
4069}
4070
4071static void brcmf_unlock_eq(struct brcmf_cfg80211_priv *cfg_priv)
4072{
4073 spin_unlock_irq(&cfg_priv->eq_lock);
4074}
4075
4076static void brcmf_init_eq_lock(struct brcmf_cfg80211_priv *cfg_priv)
4077{
4078 spin_lock_init(&cfg_priv->eq_lock);
4079}
4080
4081static void brcmf_delay(u32 ms)
4082{
4083 if (ms < 1000 / HZ) {
4084 cond_resched();
4085 mdelay(ms);
4086 } else {
4087 msleep(ms);
4088 }
4089}
4090
4091static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data)
4092{
4093 dev->driver_data = data;
4094}
4095
4096static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev)
4097{
4098 void *data = NULL;
4099
4100 if (dev)
4101 data = dev->driver_data;
4102 return data;
4103}
4104
4105static void brcmf_set_mpc(struct net_device *ndev, int mpc)
4106{
4107 s32 err = 0;
4108 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
4109
4110 if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
4111 err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
4112 if (unlikely(err)) {
4113 WL_ERR("fail to set mpc\n");
4114 return;
4115 }
4116 WL_INFO("MPC : %d\n", mpc);
4117 }
4118}
4119
4120static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
4121{
4122 char buf[10+IFNAMSIZ];
4123 struct dentry *fd;
4124 s32 err = 0;
4125
4126 sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
4127 cfg_priv->debugfsdir = debugfs_create_dir(buf,
4128 cfg_to_wiphy(cfg_priv)->debugfsdir);
4129
4130 fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
4131 (u16 *)&cfg_priv->profile->beacon_interval);
4132 if (!fd) {
4133 err = -ENOMEM;
4134 goto err_out;
4135 }
4136
4137 fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
4138 (u8 *)&cfg_priv->profile->dtim_period);
4139 if (!fd) {
4140 err = -ENOMEM;
4141 goto err_out;
4142 }
4143
4144err_out:
4145 return err;
4146}
4147
4148static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
4149{
4150 debugfs_remove_recursive(cfg_priv->debugfsdir);
4151 cfg_priv->debugfsdir = NULL;
4152}
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
new file mode 100644
index 00000000000..f26d08793ca
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
@@ -0,0 +1,356 @@
1/*
2 * Copyright (c) 2010 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#ifndef _wl_cfg80211_h_
18#define _wl_cfg80211_h_
19
20struct brcmf_cfg80211_conf;
21struct brcmf_cfg80211_iface;
22struct brcmf_cfg80211_priv;
23struct brcmf_cfg80211_security;
24struct brcmf_cfg80211_ibss;
25
26#define WL_DBG_NONE 0
27#define WL_DBG_CONN (1 << 5)
28#define WL_DBG_SCAN (1 << 4)
29#define WL_DBG_TRACE (1 << 3)
30#define WL_DBG_INFO (1 << 1)
31#define WL_DBG_ERR (1 << 0)
32#define WL_DBG_MASK ((WL_DBG_INFO | WL_DBG_ERR | WL_DBG_TRACE) | \
33 (WL_DBG_SCAN) | (WL_DBG_CONN))
34
35#define WL_ERR(fmt, args...) \
36do { \
37 if (brcmf_dbg_level & WL_DBG_ERR) { \
38 if (net_ratelimit()) { \
39 printk(KERN_ERR "ERROR @%s : " fmt, \
40 __func__, ##args); \
41 } \
42 } \
43} while (0)
44
45#if (defined BCMDBG)
46#define WL_INFO(fmt, args...) \
47do { \
48 if (brcmf_dbg_level & WL_DBG_INFO) { \
49 if (net_ratelimit()) { \
50 printk(KERN_ERR "INFO @%s : " fmt, \
51 __func__, ##args); \
52 } \
53 } \
54} while (0)
55
56#define WL_TRACE(fmt, args...) \
57do { \
58 if (brcmf_dbg_level & WL_DBG_TRACE) { \
59 if (net_ratelimit()) { \
60 printk(KERN_ERR "TRACE @%s : " fmt, \
61 __func__, ##args); \
62 } \
63 } \
64} while (0)
65
66#define WL_SCAN(fmt, args...) \
67do { \
68 if (brcmf_dbg_level & WL_DBG_SCAN) { \
69 if (net_ratelimit()) { \
70 printk(KERN_ERR "SCAN @%s : " fmt, \
71 __func__, ##args); \
72 } \
73 } \
74} while (0)
75
76#define WL_CONN(fmt, args...) \
77do { \
78 if (brcmf_dbg_level & WL_DBG_CONN) { \
79 if (net_ratelimit()) { \
80 printk(KERN_ERR "CONN @%s : " fmt, \
81 __func__, ##args); \
82 } \
83 } \
84} while (0)
85
86#else /* (defined BCMDBG) */
87#define WL_INFO(fmt, args...)
88#define WL_TRACE(fmt, args...)
89#define WL_SCAN(fmt, args...)
90#define WL_CONN(fmt, args...)
91#endif /* (defined BCMDBG) */
92
93#define WL_NUM_SCAN_MAX 1
94#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used
95 * for 2.6.33 kernel
96 * or later
97 */
98#define WL_SCAN_BUF_MAX (1024 * 8)
99#define WL_TLV_INFO_MAX 1024
100#define WL_BSS_INFO_MAX 2048
101#define WL_ASSOC_INFO_MAX 512 /*
102 * needs to grab assoc info from dongle to
103 * report it to cfg80211 through "connect"
104 * event
105 */
106#define WL_IOCTL_LEN_MAX 1024
107#define WL_EXTRA_BUF_MAX 2048
108#define WL_ISCAN_BUF_MAX 2048 /*
109 * the buf length can be BRCMF_C_IOCTL_MAXLEN
110 * to reduce iteration
111 */
112#define WL_ISCAN_TIMER_INTERVAL_MS 3000
113#define WL_SCAN_ERSULTS_LAST (BRCMF_SCAN_RESULTS_NO_MEM+1)
114#define WL_AP_MAX 256 /* virtually unlimitted as long
115 * as kernel memory allows
116 */
117
118#define WL_ROAM_TRIGGER_LEVEL -75
119#define WL_ROAM_DELTA 20
120#define WL_BEACON_TIMEOUT 3
121
122#define WL_SCAN_CHANNEL_TIME 40
123#define WL_SCAN_UNASSOC_TIME 40
124#define WL_SCAN_PASSIVE_TIME 120
125
126/* dongle status */
127enum wl_status {
128 WL_STATUS_READY,
129 WL_STATUS_SCANNING,
130 WL_STATUS_SCAN_ABORTING,
131 WL_STATUS_CONNECTING,
132 WL_STATUS_CONNECTED
133};
134
135/* wi-fi mode */
136enum wl_mode {
137 WL_MODE_BSS,
138 WL_MODE_IBSS,
139 WL_MODE_AP
140};
141
142/* dongle profile list */
143enum wl_prof_list {
144 WL_PROF_MODE,
145 WL_PROF_SSID,
146 WL_PROF_SEC,
147 WL_PROF_IBSS,
148 WL_PROF_BAND,
149 WL_PROF_BSSID,
150 WL_PROF_ACT,
151 WL_PROF_BEACONINT,
152 WL_PROF_DTIMPERIOD
153};
154
155/* dongle iscan state */
156enum wl_iscan_state {
157 WL_ISCAN_STATE_IDLE,
158 WL_ISCAN_STATE_SCANING
159};
160
161/* dongle configuration */
162struct brcmf_cfg80211_conf {
163 u32 mode; /* adhoc , infrastructure or ap */
164 u32 frag_threshold;
165 u32 rts_threshold;
166 u32 retry_short;
167 u32 retry_long;
168 s32 tx_power;
169 struct ieee80211_channel channel;
170};
171
172/* cfg80211 main event loop */
173struct brcmf_cfg80211_event_loop {
174 s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_priv *cfg_priv,
175 struct net_device *ndev,
176 const struct brcmf_event_msg *e,
177 void *data);
178};
179
180/* representing interface of cfg80211 plane */
181struct brcmf_cfg80211_iface {
182 struct brcmf_cfg80211_priv *cfg_priv;
183};
184
185struct brcmf_cfg80211_dev {
186 void *driver_data; /* to store cfg80211 object information */
187};
188
189/* basic structure of scan request */
190struct brcmf_cfg80211_scan_req {
191 struct brcmf_ssid ssid;
192};
193
194/* basic structure of information element */
195struct brcmf_cfg80211_ie {
196 u16 offset;
197 u8 buf[WL_TLV_INFO_MAX];
198};
199
200/* event queue for cfg80211 main event */
201struct brcmf_cfg80211_event_q {
202 struct list_head eq_list;
203 u32 etype;
204 struct brcmf_event_msg emsg;
205 s8 edata[1];
206};
207
208/* security information with currently associated ap */
209struct brcmf_cfg80211_security {
210 u32 wpa_versions;
211 u32 auth_type;
212 u32 cipher_pairwise;
213 u32 cipher_group;
214 u32 wpa_auth;
215};
216
217/* ibss information for currently joined ibss network */
218struct brcmf_cfg80211_ibss {
219 u8 beacon_interval; /* in millisecond */
220 u8 atim; /* in millisecond */
221 s8 join_only;
222 u8 band;
223 u8 channel;
224};
225
226/* dongle profile */
227struct brcmf_cfg80211_profile {
228 u32 mode;
229 struct brcmf_ssid ssid;
230 u8 bssid[ETH_ALEN];
231 u16 beacon_interval;
232 u8 dtim_period;
233 struct brcmf_cfg80211_security sec;
234 struct brcmf_cfg80211_ibss ibss;
235 s32 band;
236};
237
238/* dongle iscan event loop */
239struct brcmf_cfg80211_iscan_eloop {
240 s32 (*handler[WL_SCAN_ERSULTS_LAST])
241 (struct brcmf_cfg80211_priv *cfg_priv);
242};
243
244/* dongle iscan controller */
245struct brcmf_cfg80211_iscan_ctrl {
246 struct net_device *dev;
247 struct timer_list timer;
248 u32 timer_ms;
249 u32 timer_on;
250 s32 state;
251 struct task_struct *tsk;
252 struct semaphore sync;
253 struct brcmf_cfg80211_iscan_eloop el;
254 void *data;
255 s8 ioctl_buf[BRCMF_C_IOCTL_SMLEN];
256 s8 scan_buf[WL_ISCAN_BUF_MAX];
257};
258
259/* association inform */
260struct brcmf_cfg80211_connect_info {
261 u8 *req_ie;
262 s32 req_ie_len;
263 u8 *resp_ie;
264 s32 resp_ie_len;
265};
266
267/* assoc ie length */
268struct brcmf_cfg80211_assoc_ielen {
269 u32 req_len;
270 u32 resp_len;
271};
272
273/* wpa2 pmk list */
274struct brcmf_cfg80211_pmk_list {
275 pmkid_list_t pmkids;
276 pmkid_t foo[MAXPMKID - 1];
277};
278
279/* dongle private data of cfg80211 interface */
280struct brcmf_cfg80211_priv {
281 struct wireless_dev *wdev; /* representing wl cfg80211 device */
282 struct brcmf_cfg80211_conf *conf; /* dongle configuration */
283 struct cfg80211_scan_request *scan_request; /* scan request
284 object */
285 struct brcmf_cfg80211_event_loop el; /* main event loop */
286 struct list_head eq_list; /* used for event queue */
287 spinlock_t eq_lock; /* for event queue synchronization */
288 struct mutex usr_sync; /* maily for dongle up/down synchronization */
289 struct brcmf_scan_results *bss_list; /* bss_list holding scanned
290 ap information */
291 struct brcmf_scan_results *scan_results;
292 struct brcmf_cfg80211_scan_req *scan_req_int; /* scan request object
293 for internal purpose */
294 struct wl_cfg80211_bss_info *bss_info; /* bss information for
295 cfg80211 layer */
296 struct brcmf_cfg80211_ie ie; /* information element object for
297 internal purpose */
298 struct semaphore event_sync; /* for synchronization of main event
299 thread */
300 struct brcmf_cfg80211_profile *profile; /* holding dongle profile */
301 struct brcmf_cfg80211_iscan_ctrl *iscan; /* iscan controller */
302 struct brcmf_cfg80211_connect_info conn_info; /* association info */
303 struct brcmf_cfg80211_pmk_list *pmk_list; /* wpa2 pmk list */
304 struct task_struct *event_tsk; /* task of main event handler thread */
305 unsigned long status; /* current dongle status */
306 void *pub;
307 u32 channel; /* current channel */
308 bool iscan_on; /* iscan on/off switch */
309 bool iscan_kickstart; /* indicate iscan already started */
310 bool active_scan; /* current scan mode */
311 bool ibss_starter; /* indicates this sta is ibss starter */
312 bool link_up; /* link/connection up flag */
313 bool pwr_save; /* indicate whether dongle to support
314 power save mode */
315 bool dongle_up; /* indicate whether dongle up or not */
316 bool roam_on; /* on/off switch for dongle self-roaming */
317 bool scan_tried; /* indicates if first scan attempted */
318 u8 *ioctl_buf; /* ioctl buffer */
319 u8 *extra_buf; /* maily to grab assoc information */
320 struct dentry *debugfsdir;
321 u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN)));
322};
323
324#define cfg_to_wiphy(w) (w->wdev->wiphy)
325#define wiphy_to_cfg(w) ((struct brcmf_cfg80211_priv *)(wiphy_priv(w)))
326#define cfg_to_wdev(w) (w->wdev)
327#define wdev_to_cfg(w) ((struct brcmf_cfg80211_priv *)(wdev_priv(w)))
328#define cfg_to_ndev(w) (w->wdev->netdev)
329#define ndev_to_cfg(n) (wdev_to_cfg(n->ieee80211_ptr))
330#define iscan_to_cfg(i) ((struct brcmf_cfg80211_priv *)(i->data))
331#define cfg_to_iscan(w) (w->iscan)
332#define cfg_to_conn(w) (&w->conn_info)
333
334static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list,
335 struct brcmf_bss_info *bss)
336{
337 return bss = bss ?
338 (struct brcmf_bss_info *)((unsigned long)bss +
339 le32_to_cpu(bss->length)) :
340 list->bss_info;
341}
342
343#define for_each_bss(list, bss, __i) \
344 for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss))
345
346extern s32 brcmf_cfg80211_attach(struct net_device *ndev, void *data);
347extern void brcmf_cfg80211_detach(void);
348/* event handler from dongle */
349extern void brcmf_cfg80211_event(struct net_device *ndev,
350 const struct brcmf_event_msg *e, void *data);
351extern void brcmf_cfg80211_sdio_func(void *func); /* set sdio function info */
352extern struct sdio_func *brcmf_cfg80211_get_sdio_func(void);
353extern s32 brcmf_cfg80211_up(void); /* dongle up */
354extern s32 brcmf_cfg80211_down(void); /* dongle down */
355
356#endif /* _wl_cfg80211_h_ */