]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/linux-3.10.39-add_libertas_uap.patch
firewall: add more pscan matches and filter INVALID conntrack packages.
[ipfire-2.x.git] / src / patches / linux-3.10.39-add_libertas_uap.patch
1 diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
2 index f8f0156..42a0702 100644
3 --- a/drivers/net/wireless/Kconfig
4 +++ b/drivers/net/wireless/Kconfig
5 @@ -51,6 +51,14 @@ config LIBERTAS_THINFIRM_USB
6 ---help---
7 A driver for Marvell Libertas 8388 USB devices using thinfirm.
8
9 +config LIBERTAS_UAP
10 + tristate "Marvell 8xxx Libertas UAP"
11 + depends on MAC80211
12 + depends on MMC
13 + select FW_LOADER
14 + ---help---
15 + Driver for Marvell Libertas 8xxx micro AP.
16 +
17 config AIRO
18 tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
19 depends on ISA_DMA_API && (PCI || BROKEN)
20 diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
21 index 67156ef..475a1b3 100644
22 --- a/drivers/net/wireless/Makefile
23 +++ b/drivers/net/wireless/Makefile
24 @@ -37,6 +37,8 @@ obj-$(CONFIG_LIBERTAS) += libertas/
25
26 obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/
27
28 +obj-$(CONFIG_LIBERTAS_UAP) += libertas_uap/
29 +
30 obj-$(CONFIG_ADM8211) += adm8211.o
31
32 obj-$(CONFIG_MWL8K) += mwl8k.o
33 diff --git a/drivers/net/wireless/libertas_uap/Makefile b/drivers/net/wireless/libertas_uap/Makefile
34 new file mode 100644
35 index 0000000..821f2a4
36 --- /dev/null
37 +++ b/drivers/net/wireless/libertas_uap/Makefile
38 @@ -0,0 +1,6 @@
39 +obj-$(CONFIG_LIBERTAS_UAP) += uap8xxx.o
40 +
41 +uap8xxx-y += uap_main.o uap_sdio_mmc.o
42 +uap8xxx-$(CONFIG_PROC_FS) += uap_proc.o uap_debug.o
43 +
44 +EXTRA_CFLAGS += -DFPNUM='"52"' -DPXA3XX_DMA_ALIGN -DDEBUG_LEVEL1
45 diff --git a/drivers/net/wireless/libertas_uap/uap_debug.c b/drivers/net/wireless/libertas_uap/uap_debug.c
46 new file mode 100644
47 index 0000000..a2f6dc9
48 --- /dev/null
49 +++ b/drivers/net/wireless/libertas_uap/uap_debug.c
50 @@ -0,0 +1,260 @@
51 +/** @file uap_debug.c
52 + * @brief This file contains functions for debug proc file.
53 + *
54 + * Copyright (C) 2008-2009, Marvell International Ltd.
55 + *
56 + * This software file (the "File") is distributed by Marvell International
57 + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
58 + * (the "License"). You may use, redistribute and/or modify this File in
59 + * accordance with the terms and conditions of the License, a copy of which
60 + * is available along with the File in the gpl.txt file or by writing to
61 + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
62 + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
63 + *
64 + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
65 + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
66 + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
67 + * this warranty disclaimer.
68 + *
69 + */
70 +#ifdef CONFIG_PROC_FS
71 +#include "uap_headers.h"
72 +
73 +/********************************************************
74 + Local Variables
75 +********************************************************/
76 +
77 +#define item_size(n) (sizeof ((uap_adapter *)0)->n)
78 +#define item_addr(n) ((u32) &((uap_adapter *)0)->n)
79 +
80 +#define item_dbg_size(n) (sizeof (((uap_adapter *)0)->dbg.n))
81 +#define item_dbg_addr(n) ((u32) &(((uap_adapter *)0)->dbg.n))
82 +
83 +#define item_dev_size(n) (sizeof ((uap_dev_t *)0)->n)
84 +#define item_dev_addr(n) ((u32) &((uap_dev_t *)0)->n)
85 +
86 +/** MicroAp device offset */
87 +#define OFFSET_UAP_DEV 0x01
88 +/** Bluetooth adapter offset */
89 +#define OFFSET_UAP_ADAPTER 0x02
90 +
91 +struct debug_data
92 +{
93 + /** Name */
94 + char name[32];
95 + /** Size */
96 + u32 size;
97 + /** Address */
98 + u32 addr;
99 + /** Offset */
100 + u32 offset;
101 + /** Flag */
102 + u32 flag;
103 +};
104 +
105 +/* To debug any member of uap_adapter, simply add one line here.
106 + */
107 +static struct debug_data items[] = {
108 + {"cmd_sent", item_dev_size(cmd_sent), 0, item_dev_addr(cmd_sent),
109 + OFFSET_UAP_DEV},
110 + {"data_sent", item_dev_size(data_sent), 0, item_dev_addr(data_sent),
111 + OFFSET_UAP_DEV},
112 + {"IntCounter", item_size(IntCounter), 0, item_addr(IntCounter),
113 + OFFSET_UAP_ADAPTER},
114 + {"cmd_pending", item_size(cmd_pending), 0, item_addr(cmd_pending),
115 + OFFSET_UAP_ADAPTER},
116 + {"num_cmd_h2c_fail", item_dbg_size(num_cmd_host_to_card_failure), 0,
117 + item_dbg_addr(num_cmd_host_to_card_failure), OFFSET_UAP_ADAPTER},
118 + {"num_tx_h2c_fail", item_dbg_size(num_tx_host_to_card_failure), 0,
119 + item_dbg_addr(num_tx_host_to_card_failure), OFFSET_UAP_ADAPTER},
120 + {"psmode", item_size(psmode), 0, item_addr(psmode), OFFSET_UAP_ADAPTER},
121 + {"ps_state", item_size(ps_state), 0, item_addr(ps_state),
122 + OFFSET_UAP_ADAPTER},
123 +#ifdef DEBUG_LEVEL1
124 + {"drvdbg", sizeof(drvdbg), (u32) & drvdbg, 0, 0}
125 +#endif
126 +};
127 +
128 +static int num_of_items = sizeof(items) / sizeof(items[0]);
129 +
130 +/********************************************************
131 + Global Variables
132 +********************************************************/
133 +
134 +/********************************************************
135 + Local Functions
136 +********************************************************/
137 +/**
138 + * @brief proc read function
139 + *
140 + * @param page pointer to buffer
141 + * @param s read data starting position
142 + * @param off offset
143 + * @param cnt counter
144 + * @param eof end of file flag
145 + * @param data data to output
146 + * @return number of output data
147 + */
148 +static int uap_debug_proc_show(struct seq_file *s, void *data) {
149 + int val = 0;
150 + int i;
151 +
152 + struct debug_data *d = (struct debug_data *)s->private;
153 +
154 + if (MODULE_GET == 0)
155 + return UAP_STATUS_FAILURE;
156 +
157 + for (i = 0; i < num_of_items; i++) {
158 + if (d[i].size == 1)
159 + val = *((u8 *) d[i].addr);
160 + else if (d[i].size == 2)
161 + val = *((u16 *) d[i].addr);
162 + else if (d[i].size == 4)
163 + val = *((u32 *) d[i].addr);
164 +
165 + seq_printf(s, "%s=%d\n", d[i].name, val);
166 + }
167 + MODULE_PUT;
168 + return 0;
169 +}
170 +
171 +static int uap_debug_proc_open(struct inode* inode, struct file* file) {
172 + return single_open(file, uap_debug_proc_show, PDE_DATA(inode));
173 +}
174 +
175 +/**
176 + * @brief proc write function
177 + *
178 + * @param f file pointer
179 + * @param buf pointer to data buffer
180 + * @param cnt data number to write
181 + * @param data data to write
182 + * @return number of data
183 + */
184 +static ssize_t uap_debug_proc_write(struct file *f, const char __user *buf, size_t cnt, loff_t *data) {
185 + int r, i;
186 + char *pdata;
187 + char *p;
188 + char *p0;
189 + char *p1;
190 + char *p2;
191 + struct debug_data *d = (struct debug_data *)PDE_DATA(file_inode(f));
192 +
193 + if (MODULE_GET == 0)
194 + return UAP_STATUS_FAILURE;
195 +
196 + pdata = (char *) kmalloc(cnt, GFP_KERNEL);
197 + if (pdata == NULL) {
198 + MODULE_PUT;
199 + return 0;
200 + }
201 +
202 + if (copy_from_user(pdata, buf, cnt)) {
203 + PRINTM(INFO, "Copy from user failed\n");
204 + kfree(pdata);
205 + MODULE_PUT;
206 + return 0;
207 + }
208 +
209 + p0 = pdata;
210 + for (i = 0; i < num_of_items; i++) {
211 + do {
212 + p = strstr(p0, d[i].name);
213 + if (p == NULL)
214 + break;
215 + p1 = strchr(p, '\n');
216 + if (p1 == NULL)
217 + break;
218 + p0 = p1++;
219 + p2 = strchr(p, '=');
220 + if (!p2)
221 + break;
222 + p2++;
223 + r = string_to_number(p2);
224 + if (d[i].size == 1)
225 + *((u8 *) d[i].addr) = (u8) r;
226 + else if (d[i].size == 2)
227 + *((u16 *) d[i].addr) = (u16) r;
228 + else if (d[i].size == 4)
229 + *((u32 *) d[i].addr) = (u32) r;
230 + break;
231 + } while (TRUE);
232 + }
233 + kfree(pdata);
234 +#ifdef DEBUG_LEVEL1
235 + printk(KERN_ALERT "drvdbg = 0x%x\n", drvdbg);
236 + printk(KERN_ALERT "INFO (%08lx) %s\n", DBG_INFO,
237 + (drvdbg & DBG_INFO) ? "X" : "");
238 + printk(KERN_ALERT "WARN (%08lx) %s\n", DBG_WARN,
239 + (drvdbg & DBG_WARN) ? "X" : "");
240 + printk(KERN_ALERT "ENTRY (%08lx) %s\n", DBG_ENTRY,
241 + (drvdbg & DBG_ENTRY) ? "X" : "");
242 + printk(KERN_ALERT "CMD_D (%08lx) %s\n", DBG_CMD_D,
243 + (drvdbg & DBG_CMD_D) ? "X" : "");
244 + printk(KERN_ALERT "DAT_D (%08lx) %s\n", DBG_DAT_D,
245 + (drvdbg & DBG_DAT_D) ? "X" : "");
246 + printk(KERN_ALERT "CMND (%08lx) %s\n", DBG_CMND,
247 + (drvdbg & DBG_CMND) ? "X" : "");
248 + printk(KERN_ALERT "DATA (%08lx) %s\n", DBG_DATA,
249 + (drvdbg & DBG_DATA) ? "X" : "");
250 + printk(KERN_ALERT "ERROR (%08lx) %s\n", DBG_ERROR,
251 + (drvdbg & DBG_ERROR) ? "X" : "");
252 + printk(KERN_ALERT "FATAL (%08lx) %s\n", DBG_FATAL,
253 + (drvdbg & DBG_FATAL) ? "X" : "");
254 + printk(KERN_ALERT "MSG (%08lx) %s\n", DBG_MSG,
255 + (drvdbg & DBG_MSG) ? "X" : "");
256 +#endif
257 + MODULE_PUT;
258 + return cnt;
259 +}
260 +
261 +static const struct file_operations uap_debug_proc_fops = {
262 + .owner = THIS_MODULE,
263 + .open = uap_debug_proc_open,
264 + .read = seq_read,
265 + .llseek = seq_lseek,
266 + .release = single_release,
267 + .write = uap_debug_proc_write,
268 +};
269 +
270 +/********************************************************
271 + Global Functions
272 +********************************************************/
273 +/**
274 + * @brief create debug proc file
275 + *
276 + * @param priv pointer uap_private
277 + * @param dev pointer net_device
278 + * @return N/A
279 + */
280 +void
281 +uap_debug_entry(uap_private * priv, struct net_device *dev)
282 +{
283 + int i;
284 +
285 + if (priv->proc_entry == NULL)
286 + return;
287 +
288 + for (i = 0; i < num_of_items; i++) {
289 + if (items[i].flag & OFFSET_UAP_ADAPTER)
290 + items[i].addr = items[i].offset + (u32) priv->adapter;
291 + if (items[i].flag & OFFSET_UAP_DEV)
292 + items[i].addr = items[i].offset + (u32) & priv->uap_dev;
293 + }
294 + proc_create_data("debug", 0644, priv->proc_entry, &uap_debug_proc_fops,
295 + &items[0]);
296 +}
297 +
298 +/**
299 + * @brief remove proc file
300 + *
301 + * @param priv pointer uap_private
302 + * @return N/A
303 + */
304 +void
305 +uap_debug_remove(uap_private * priv)
306 +{
307 + remove_proc_entry("debug", priv->proc_entry);
308 +}
309 +
310 +#endif
311 diff --git a/drivers/net/wireless/libertas_uap/uap_drv.h b/drivers/net/wireless/libertas_uap/uap_drv.h
312 new file mode 100644
313 index 0000000..5aa009f
314 --- /dev/null
315 +++ b/drivers/net/wireless/libertas_uap/uap_drv.h
316 @@ -0,0 +1,667 @@
317 +/** @file uap_drv.h
318 + * @brief This file contains Linux OS related definitions and
319 + * declarations, uAP driver
320 + *
321 + * Copyright (C) 2008-2009, Marvell International Ltd.
322 + *
323 + * This software file (the "File") is distributed by Marvell International
324 + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
325 + * (the "License"). You may use, redistribute and/or modify this File in
326 + * accordance with the terms and conditions of the License, a copy of which
327 + * is available along with the File in the gpl.txt file or by writing to
328 + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
329 + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
330 + *
331 + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
332 + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
333 + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
334 + * this warranty disclaimer.
335 + *
336 + */
337 +
338 +#ifndef _UAP_DRV_H
339 +#define _UAP_DRV_H
340 +
341 +/** Driver release version */
342 +#define DRIVER_VERSION "26146"
343 +
344 +/** True */
345 +#ifndef TRUE
346 +#define TRUE 1
347 +#endif
348 +/** False */
349 +#ifndef FALSE
350 +#define FALSE 0
351 +#endif
352 +
353 +/** Bit definitions */
354 +#ifndef BIT
355 +#define BIT(x) (1UL << (x))
356 +#endif
357 +
358 +/** Dma addresses are 32-bits wide. */
359 +#ifndef __ATTRIB_ALIGN__
360 +#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
361 +#endif
362 +
363 +/** attribute pack */
364 +#ifndef __ATTRIB_PACK__
365 +#define __ATTRIB_PACK__ __attribute__ ((packed))
366 +#endif
367 +
368 +/** Debug Macro definition*/
369 +#ifdef DEBUG_LEVEL1
370 +
371 +extern u32 drvdbg;
372 +
373 +/** Debug message control bit definition for drvdbg */
374 +/** Debug message */
375 +#define DBG_MSG BIT(0)
376 +/** Debug fatal message */
377 +#define DBG_FATAL BIT(1)
378 +/** Debug error message */
379 +#define DBG_ERROR BIT(2)
380 +/** Debug data message */
381 +#define DBG_DATA BIT(3)
382 +/** Debug command message */
383 +#define DBG_CMND BIT(4)
384 +
385 +/** Debug data */
386 +#define DBG_DAT_D BIT(16)
387 +/** Debug command */
388 +#define DBG_CMD_D BIT(17)
389 +
390 +/** Debug entry */
391 +#define DBG_ENTRY BIT(28)
392 +/** Debug warning */
393 +#define DBG_WARN BIT(29)
394 +/** Debug info */
395 +#define DBG_INFO BIT(30)
396 +
397 +/** Print info */
398 +#define PRINTM_INFO(msg...) {if (drvdbg & DBG_INFO) printk(KERN_DEBUG msg);}
399 +/** Print warn message */
400 +#define PRINTM_WARN(msg...) {if (drvdbg & DBG_WARN) printk(KERN_DEBUG msg);}
401 +/** Print entry */
402 +#define PRINTM_ENTRY(msg...) {if (drvdbg & DBG_ENTRY) printk(KERN_DEBUG msg);}
403 +/** Print cmd_d */
404 +#define PRINTM_CMD_D(msg...) {if (drvdbg & DBG_CMD_D) printk(KERN_DEBUG msg);}
405 +/** Print data_d */
406 +#define PRINTM_DAT_D(msg...) {if (drvdbg & DBG_DAT_D) printk(KERN_DEBUG msg);}
407 +/** Print command */
408 +#define PRINTM_CMND(msg...) {if (drvdbg & DBG_CMND) printk(KERN_DEBUG msg);}
409 +/** Print data */
410 +#define PRINTM_DATA(msg...) {if (drvdbg & DBG_DATA) printk(KERN_DEBUG msg);}
411 +/** Print error message */
412 +#define PRINTM_ERROR(msg...) {if (drvdbg & DBG_ERROR) printk(KERN_DEBUG msg);}
413 +/** Print fatal message */
414 +#define PRINTM_FATAL(msg...) {if (drvdbg & DBG_FATAL) printk(KERN_DEBUG msg);}
415 +/** Print message */
416 +#define PRINTM_MSG(msg...) {if (drvdbg & DBG_MSG) printk(KERN_ALERT msg);}
417 +/** Print level */
418 +#define PRINTM(level,msg...) PRINTM_##level(msg)
419 +
420 +#else
421 +
422 +#define PRINTM(level,msg...) do {} while (0)
423 +
424 +#endif /* DEBUG_LEVEL1 */
425 +
426 +/** Wait until a condition becomes true */
427 +#define ASSERT(cond) \
428 +do { \
429 + if (!(cond)) \
430 + PRINTM(INFO, "ASSERT: %s, %s:%i\n", \
431 + __FUNCTION__, __FILE__, __LINE__); \
432 +} while(0)
433 +
434 +/** Log enrty point for debugging */
435 +#define ENTER() PRINTM(ENTRY, "Enter: %s, %s:%i\n", __FUNCTION__, \
436 + __FILE__, __LINE__)
437 +/** Log exit point for debugging */
438 +#define LEAVE() PRINTM(ENTRY, "Leave: %s, %s:%i\n", __FUNCTION__, \
439 + __FILE__, __LINE__)
440 +
441 +#ifdef DEBUG_LEVEL1
442 +/** Dump buffer length */
443 +#define DBG_DUMP_BUF_LEN 64
444 +/** Maximum dump per line */
445 +#define MAX_DUMP_PER_LINE 16
446 +/** Data dump length */
447 +#define DATA_DUMP_LEN 32
448 +
449 +static inline void
450 +hexdump(char *prompt, u8 * buf, int len)
451 +{
452 + int i;
453 + char dbgdumpbuf[DBG_DUMP_BUF_LEN];
454 + char *ptr = dbgdumpbuf;
455 +
456 + printk(KERN_DEBUG "%s:\n", prompt);
457 + for (i = 1; i <= len; i++) {
458 + ptr += sprintf(ptr, "%02x ", *buf);
459 + buf++;
460 + if (i % MAX_DUMP_PER_LINE == 0) {
461 + *ptr = 0;
462 + printk(KERN_DEBUG "%s\n", dbgdumpbuf);
463 + ptr = dbgdumpbuf;
464 + }
465 + }
466 + if (len % MAX_DUMP_PER_LINE) {
467 + *ptr = 0;
468 + printk(KERN_DEBUG "%s\n", dbgdumpbuf);
469 + }
470 +}
471 +
472 +/** Debug command */
473 +#define DBG_HEXDUMP_CMD_D(x,y,z) {if (drvdbg & DBG_CMD_D) hexdump(x,y,z);}
474 +/** Debug data */
475 +#define DBG_HEXDUMP_DAT_D(x,y,z) {if (drvdbg & DBG_DAT_D) hexdump(x,y,z);}
476 +/** Debug hexdump */
477 +#define DBG_HEXDUMP(level,x,y,z) DBG_HEXDUMP_##level(x,y,z)
478 +/** hexdump */
479 +#define HEXDUMP(x,y,z) {if (drvdbg & DBG_INFO) hexdump(x,y,z);}
480 +#else
481 +/** Do nothing since debugging is not turned on */
482 +#define DBG_HEXDUMP(level,x,y,z) do {} while (0)
483 +/** Do nothing since debugging is not turned on */
484 +#define HEXDUMP(x,y,z) do {} while (0)
485 +#endif
486 +
487 +/**
488 + * Typedefs
489 + */
490 +/** Unsigned char */
491 +typedef u8 BOOLEAN;
492 +
493 +/*
494 + * OS macro definitions
495 + */
496 +/** OS macro to get time */
497 +#define os_time_get() jiffies
498 +
499 +/** OS macro to update transfer start time */
500 +#define UpdateTransStart(dev) { \
501 + dev->trans_start = jiffies; \
502 +}
503 +
504 +/** Try to get a reference to the module */
505 +#define MODULE_GET try_module_get(THIS_MODULE)
506 +/** Decrease module reference count */
507 +#define MODULE_PUT module_put(THIS_MODULE)
508 +
509 +/** OS macro to initialize semaphore */
510 +#define OS_INIT_SEMAPHORE(x) sema_init(x,1)
511 +/** OS macro to acquire blocking semaphore */
512 +#define OS_ACQ_SEMAPHORE_BLOCK(x) down_interruptible(x)
513 +/** OS macro to acquire non-blocking semaphore */
514 +#define OS_ACQ_SEMAPHORE_NOBLOCK(x) down_trylock(x)
515 +/** OS macro to release semaphore */
516 +#define OS_REL_SEMAPHORE(x) up(x)
517 +
518 +static inline void
519 +os_sched_timeout(u32 millisec)
520 +{
521 + set_current_state(TASK_INTERRUPTIBLE);
522 + schedule_timeout((millisec * HZ) / 1000);
523 +}
524 +
525 +/** Maximum size of ethernet packet */
526 +#define MRVDRV_MAXIMUM_ETH_PACKET_SIZE 1514
527 +
528 +/** Maximum size of multicast list */
529 +#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
530 +
531 +/** Find minimum */
532 +#ifndef MIN
533 +#define MIN(a,b) ((a) < (b) ? (a) : (b))
534 +#endif
535 +
536 +/** Find maximum */
537 +#ifndef MAX
538 +#define MAX(a,b) ((a) > (b) ? (a) : (b))
539 +#endif
540 +
541 +/** Find number of elements */
542 +#ifndef NELEMENTS
543 +#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
544 +#endif
545 +
546 +/** Buffer Constants */
547 +
548 +/** Size of command buffer */
549 +#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
550 +
551 +/** Length of device length */
552 +#define DEV_NAME_LEN 32
553 +
554 +/** Length of ethernet address */
555 +#ifndef ETH_ALEN
556 +#define ETH_ALEN 6
557 +#endif
558 +
559 +/** Default watchdog timeout */
560 +#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (2 * HZ)
561 +
562 +/** Success */
563 +#define UAP_STATUS_SUCCESS (0)
564 +/** Failure */
565 +#define UAP_STATUS_FAILURE (-1)
566 +/** Not accepted */
567 +#define UAP_STATUS_NOT_ACCEPTED (-2)
568 +
569 +/** Max loop count (* 100ms) for waiting device ready at init time */
570 +#define MAX_WAIT_DEVICE_READY_COUNT 50
571 +
572 +/** Tx high watermark. Stop Tx queue after this is crossed */
573 +#define TX_HIGH_WATERMARK 4
574 +/** Tx low watermark. Restart Tx queue after this is crossed */
575 +#define TX_LOW_WATERMARK 2
576 +
577 +/** Netlink protocol number */
578 +#define NETLINK_MARVELL (MAX_LINKS - 1)
579 +/** Netlink maximum payload size */
580 +#define NL_MAX_PAYLOAD 1024
581 +/** Netlink multicast group number */
582 +#define NL_MULTICAST_GROUP 1
583 +
584 +/** 20 seconds */
585 +#define MRVDRV_TIMER_20S 20000
586 +
587 +/** Host Command option for wait till Send */
588 +#define HostCmd_OPTION_WAITFORSEND 0x0001
589 +/** Host Command option for wait for RSP */
590 +#define HostCmd_OPTION_WAITFORRSP 0x0002
591 +/** Host Command option for wait for RSP or Timeout */
592 +#define HostCmd_OPTION_WAITFORRSP_TIMEOUT 0x0003
593 +/** Host Command option for wait for RSP of sleep confirm */
594 +#define HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM 0x0004
595 +
596 +/** Sleep until a condition gets true or a timeout elapses */
597 +#define os_wait_interruptible_timeout(waitq, cond, timeout) \
598 + wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000))
599 +
600 +/** Private command ID to Host command */
601 +#define UAPHOSTCMD (SIOCDEVPRIVATE + 1)
602 +
603 +/** Private command ID to Power Mode */
604 +#define UAP_POWER_MODE (SIOCDEVPRIVATE + 3)
605 +/** sleep_param */
606 +typedef struct _ps_sleep_param
607 +{
608 + /** control bitmap */
609 + u32 ctrl_bitmap;
610 + /** minimum sleep period (micro second) */
611 + u32 min_sleep;
612 + /** maximum sleep period (micro second) */
613 + u32 max_sleep;
614 +} ps_sleep_param;
615 +
616 +/** inactivity sleep_param */
617 +typedef struct _inact_sleep_param
618 +{
619 + /** inactivity timeout (micro second) */
620 + u32 inactivity_to;
621 + /** miniumu awake period (micro second) */
622 + u32 min_awake;
623 + /** maximum awake period (micro second) */
624 + u32 max_awake;
625 +} inact_sleep_param;
626 +
627 +/** flag for ps mode */
628 +#define PS_FLAG_PS_MODE 1
629 +/** flag for sleep param */
630 +#define PS_FLAG_SLEEP_PARAM 2
631 +/** flag for inactivity sleep param */
632 +#define PS_FLAG_INACT_SLEEP_PARAM 4
633 +
634 +/** Disable power mode */
635 +#define PS_MODE_DISABLE 0
636 +/** Enable periodic dtim ps */
637 +#define PS_MODE_PERIODIC_DTIM 1
638 +/** Enable inactivity ps */
639 +#define PS_MODE_INACTIVITY 2
640 +
641 +/** sleep parameter */
642 +#define SLEEP_PARAMETER 1
643 +/** inactivity sleep parameter */
644 +#define INACTIVITY_SLEEP_PARAMETER 2
645 +/** ps_mgmt */
646 +typedef struct _ps_mgmt
647 +{
648 + /** flags for valid field */
649 + u16 flags;
650 + /** power mode */
651 + u16 ps_mode;
652 + /** sleep param */
653 + ps_sleep_param sleep_param;
654 + /** inactivity sleep param */
655 + inact_sleep_param inact_param;
656 +} ps_mgmt;
657 +
658 +/** Semaphore structure */
659 +typedef struct semaphore SEMAPHORE;
660 +
661 +/** Global Varibale Declaration */
662 +/** Private data structure of the device */
663 +typedef struct _uap_private uap_private;
664 +/** Adapter data structure of the device */
665 +typedef struct _uap_adapter uap_adapter;
666 +/** private structure */
667 +extern uap_private *uappriv;
668 +
669 +/** ENUM definition*/
670 +
671 +/** Hardware status codes */
672 +typedef enum _HARDWARE_STATUS
673 +{
674 + HWReady,
675 + HWInitializing,
676 + HWReset,
677 + HWClosing,
678 + HWNotReady
679 +} HARDWARE_STATUS;
680 +
681 +/** info for debug purpose */
682 +typedef struct _uap_dbg
683 +{
684 + /** Number of host to card command failures */
685 + u32 num_cmd_host_to_card_failure;
686 + /** Number of host to card Tx failures */
687 + u32 num_tx_host_to_card_failure;
688 +} uap_dbg;
689 +
690 +/** Set thread state */
691 +#define OS_SET_THREAD_STATE(x) set_current_state(x)
692 +
693 +typedef struct
694 +{
695 + /** Task */
696 + struct task_struct *task;
697 + /** Queue */
698 + wait_queue_head_t waitQ;
699 + /** PID */
700 + pid_t pid;
701 + /** Private structure */
702 + void *priv;
703 +} uap_thread;
704 +
705 +static inline void
706 +uap_activate_thread(uap_thread * thr)
707 +{
708 + /** Record the thread pid */
709 + thr->pid = current->pid;
710 +
711 + /** Initialize the wait queue */
712 + init_waitqueue_head(&thr->waitQ);
713 +}
714 +
715 +static inline void
716 +uap_deactivate_thread(uap_thread * thr)
717 +{
718 + thr->pid = 0;
719 + return;
720 +}
721 +
722 +static inline void
723 +uap_create_thread(int (*uapfunc) (void *), uap_thread * thr, char *name)
724 +{
725 + thr->task = kthread_run(uapfunc, thr, "%s", name);
726 +}
727 +
728 +static inline int
729 +uap_terminate_thread(uap_thread * thr)
730 +{
731 + /* Check if the thread is active or not */
732 + if (!thr->pid)
733 + return -1;
734 + kthread_stop(thr->task);
735 + return 0;
736 +}
737 +
738 +/** Data structure for the Marvell uAP device */
739 +typedef struct _uap_dev
740 +{
741 + /** device name */
742 + char name[DEV_NAME_LEN];
743 + /** card pointer */
744 + void *card;
745 + /** IO port */
746 + u32 ioport;
747 + /** Rx unit */
748 + u8 rx_unit;
749 + /** Data sent:
750 + TRUE - Data is sent to fw, no Tx Done received
751 + FALSE - Tx done received for previous Tx */
752 + BOOLEAN data_sent;
753 + /** CMD sent:
754 + TRUE - CMD is sent to fw, no CMD Done received
755 + FALSE - CMD done received for previous CMD */
756 + BOOLEAN cmd_sent;
757 + /** netdev pointer */
758 + struct net_device *netdev;
759 +} uap_dev_t, *puap_dev_t;
760 +
761 +/** Private structure for the MV device */
762 +struct _uap_private
763 +{
764 + /** Device open */
765 + int open;
766 +
767 + /** Device adapter structure */
768 + uap_adapter *adapter;
769 + /** Device structure */
770 + uap_dev_t uap_dev;
771 +
772 + /** Net device statistics structure */
773 + struct net_device_stats stats;
774 +
775 + /** Number of Tx timeouts */
776 + u32 num_tx_timeout;
777 +
778 + /** Media connection status */
779 + BOOLEAN MediaConnected;
780 +
781 +#ifdef CONFIG_PROC_FS
782 + struct proc_dir_entry *proc_uap;
783 + struct proc_dir_entry *proc_entry;
784 +#endif /* CONFIG_PROC_FS */
785 +
786 + /** Firmware helper */
787 + const struct firmware *fw_helper;
788 + /** Firmware */
789 + const struct firmware *firmware;
790 + /** Hotplug device */
791 + struct device *hotplug_device;
792 + /** thread to service interrupts */
793 + uap_thread MainThread;
794 + /** Driver lock */
795 + spinlock_t driver_lock;
796 + /** Driver lock flags */
797 + ulong driver_flags;
798 +
799 +};
800 +
801 +/** PS_CMD_ConfirmSleep */
802 +typedef struct _PS_CMD_ConfirmSleep
803 +{
804 + /** SDIO Length */
805 + u16 SDLen;
806 + /** SDIO Type */
807 + u16 SDType;
808 + /** Command */
809 + u16 Command;
810 + /** Size */
811 + u16 Size;
812 + /** Sequence number */
813 + u16 SeqNum;
814 + /** Result */
815 + u16 Result;
816 +} __ATTRIB_PACK__ PS_CMD_ConfirmSleep, *PPS_CMD_ConfirmSleep;
817 +
818 +/** Wlan Adapter data structure*/
819 +struct _uap_adapter
820 +{
821 + /** Power save confirm sleep command */
822 + PS_CMD_ConfirmSleep PSConfirmSleep;
823 + /** Device status */
824 + HARDWARE_STATUS HardwareStatus;
825 + /** Interrupt counter */
826 + u32 IntCounter;
827 + /** Tx packet queue */
828 + struct sk_buff_head tx_queue;
829 + /** Cmd packet queue */
830 + struct sk_buff_head cmd_queue;
831 + /** Command sequence number */
832 + u16 SeqNum;
833 + /** Command buffer */
834 + u8 *CmdBuf;
835 + /** cmd pending flag */
836 + u8 cmd_pending;
837 + /** cmd wait option */
838 + u8 cmd_wait_option;
839 + /** Command buffer length */
840 + u32 CmdSize;
841 + /** Command wait queue */
842 + wait_queue_head_t cmdwait_q __ATTRIB_ALIGN__;
843 + /** Command wait queue state flag */
844 + u8 CmdWaitQWoken;
845 + /** PnP support */
846 + BOOLEAN SurpriseRemoved;
847 + /** Debug */
848 + uap_dbg dbg;
849 + /** Netlink kernel socket */
850 + struct sock *nl_sk;
851 + /** Semaphore for CMD */
852 + SEMAPHORE CmdSem;
853 + /** Power Save mode */
854 + u8 psmode;
855 + /** Power Save state */
856 + u8 ps_state;
857 + /** Number of wakeup tries */
858 + u32 WakeupTries;
859 +};
860 +
861 +static inline int
862 +os_upload_rx_packet(uap_private * priv, struct sk_buff *skb)
863 +{
864 + skb->dev = priv->uap_dev.netdev;
865 + skb->protocol = eth_type_trans(skb, priv->uap_dev.netdev);
866 + skb->ip_summed = CHECKSUM_UNNECESSARY;
867 + if (in_interrupt())
868 + netif_rx(skb);
869 + else
870 + netif_rx_ni(skb);
871 + return 0;
872 +}
873 +
874 +/*
875 + * netif carrier_on/off and start(wake)/stop_queue handling
876 + */
877 +static inline void
878 +os_carrier_on(uap_private * priv)
879 +{
880 + if (!netif_carrier_ok(priv->uap_dev.netdev) &&
881 + (priv->MediaConnected == TRUE)) {
882 + netif_carrier_on(priv->uap_dev.netdev);
883 + }
884 +}
885 +
886 +static inline void
887 +os_carrier_off(uap_private * priv)
888 +{
889 + if (netif_carrier_ok(priv->uap_dev.netdev)) {
890 + netif_carrier_off(priv->uap_dev.netdev);
891 + }
892 +}
893 +
894 +static inline void
895 +os_start_queue(uap_private * priv)
896 +{
897 + if (netif_queue_stopped(priv->uap_dev.netdev) &&
898 + (priv->MediaConnected == TRUE)) {
899 + netif_wake_queue(priv->uap_dev.netdev);
900 + }
901 +}
902 +
903 +static inline void
904 +os_stop_queue(uap_private * priv)
905 +{
906 + if (!netif_queue_stopped(priv->uap_dev.netdev)) {
907 + netif_stop_queue(priv->uap_dev.netdev);
908 + }
909 +}
910 +
911 +/** Interface specific header */
912 +#define INTF_HEADER_LEN 4
913 +
914 +/** headroom alignment for tx packet */
915 +#define HEADER_ALIGNMENT 8
916 +
917 +/** The number of times to try when polling for status bits */
918 +#define MAX_POLL_TRIES 100
919 +
920 +/** Length of SNAP header */
921 +#define MRVDRV_SNAP_HEADER_LEN 8
922 +
923 +/** Extra length of Tx packet buffer */
924 +#define EXTRA_LEN 36
925 +
926 +/** Buffer size for ethernet Tx packets */
927 +#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
928 + (ETH_FRAME_LEN + sizeof(TxPD) + EXTRA_LEN)
929 +
930 +/** Buffer size for ethernet Rx packets */
931 +#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
932 + (ETH_FRAME_LEN + sizeof(RxPD) \
933 + + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
934 +
935 +/** Packet type: data, command & event */
936 +typedef enum _mv_type
937 +{
938 + MV_TYPE_DAT = 0,
939 + MV_TYPE_CMD = 1,
940 + MV_TYPE_EVENT = 3
941 +} mv_type;
942 +
943 +/** Disable interrupt */
944 +#define OS_INT_DISABLE spin_lock_irqsave(&priv->driver_lock, priv->driver_flags)
945 +/** Enable interrupt */
946 +#define OS_INT_RESTORE spin_unlock_irqrestore(&priv->driver_lock, priv->driver_flags)
947 +
948 +int uap_process_rx_packet(uap_private * priv, struct sk_buff *skb);
949 +void uap_interrupt(uap_private * priv);
950 +uap_private *uap_add_card(void *card);
951 +int uap_remove_card(void *card);
952 +int uap_process_event(uap_private * priv, u8 * payload, uint len);
953 +int uap_soft_reset(uap_private * priv);
954 +int uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len);
955 +
956 +#ifdef CONFIG_PROC_FS
957 +/** The proc fs interface */
958 +void uap_proc_entry(uap_private * priv, struct net_device *dev);
959 +void uap_proc_remove(uap_private * priv);
960 +int string_to_number(char *s);
961 +void uap_debug_entry(uap_private * priv, struct net_device *dev);
962 +void uap_debug_remove(uap_private * priv);
963 +#endif /* CONFIG_PROC_FS */
964 +
965 +int sbi_register(void);
966 +
967 +void sbi_unregister(void);
968 +int sbi_register_dev(uap_private * priv);
969 +int sbi_unregister_dev(uap_private * priv);
970 +int sbi_prog_fw_w_helper(uap_private *);
971 +
972 +int sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb);
973 +int sbi_enable_host_int(uap_private * priv);
974 +int sbi_disable_host_int(uap_private * priv);
975 +
976 +int sbi_get_int_status(uap_private * priv, u8 * ireg);
977 +/** Check firmware status */
978 +int sbi_check_fw_status(uap_private *, int);
979 +int sbi_prog_helper(uap_private *);
980 +
981 +int sbi_wakeup_firmware(uap_private * priv);
982 +
983 +#endif /* _UAP_DRV_H */
984 diff --git a/drivers/net/wireless/libertas_uap/uap_fw.h b/drivers/net/wireless/libertas_uap/uap_fw.h
985 new file mode 100644
986 index 0000000..23a40d6
987 --- /dev/null
988 +++ b/drivers/net/wireless/libertas_uap/uap_fw.h
989 @@ -0,0 +1,359 @@
990 +/** @file uap_fw.h
991 + *
992 + * @brief This file contains firmware specific defines.
993 + *
994 + * Copyright (C) 2008-2009, Marvell International Ltd.
995 + *
996 + * This software file (the "File") is distributed by Marvell International
997 + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
998 + * (the "License"). You may use, redistribute and/or modify this File in
999 + * accordance with the terms and conditions of the License, a copy of which
1000 + * is available along with the File in the gpl.txt file or by writing to
1001 + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1002 + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
1003 + *
1004 + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
1005 + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
1006 + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
1007 + * this warranty disclaimer.
1008 + *
1009 + */
1010 +/********************************************************
1011 +Change log:
1012 + 02/26/08: Initial creation
1013 +********************************************************/
1014 +
1015 +#ifndef _UAP_FW_H
1016 +#define _UAP_FW_H
1017 +
1018 +/** uap upload size */
1019 +#define UAP_UPLD_SIZE 2312
1020 +/** Packet type Micro AP */
1021 +#define PKT_TYPE_MICROAP 1
1022 +/** Packet type client */
1023 +#define PKT_TYPE_CLIENT 0
1024 +
1025 +/** TxPD descriptor */
1026 +typedef struct _TxPD
1027 +{
1028 + /** Bss Type */
1029 + u8 BssType;
1030 + /** Bss num */
1031 + u8 BssNum;
1032 + /** Tx packet length */
1033 + u16 TxPktLength;
1034 + /** Tx packet offset */
1035 + u16 TxPktOffset;
1036 + /** Tx packet type */
1037 + u16 TxPktType;
1038 + /** Tx Control */
1039 + u32 TxControl;
1040 + /** reserved */
1041 + u32 reserved[2];
1042 +} __ATTRIB_PACK__ TxPD, *PTxPD;
1043 +
1044 +/** RxPD Descriptor */
1045 +typedef struct _RxPD
1046 +{
1047 + /** Bss Type */
1048 + u8 BssType;
1049 + /** Bss Num */
1050 + u8 BssNum;
1051 + /** Tx packet length */
1052 + u16 RxPktLength;
1053 + /** Tx packet offset */
1054 + u16 RxPktOffset;
1055 +} __ATTRIB_PACK__ RxPD, *PRxPD;
1056 +
1057 +#ifdef BIG_ENDIAN
1058 +/** Convert from 16 bit little endian format to CPU format */
1059 +#define uap_le16_to_cpu(x) le16_to_cpu(x)
1060 +/** Convert from 32 bit little endian format to CPU format */
1061 +#define uap_le32_to_cpu(x) le32_to_cpu(x)
1062 +/** Convert from 64 bit little endian format to CPU format */
1063 +#define uap_le64_to_cpu(x) le64_to_cpu(x)
1064 +/** Convert to 16 bit little endian format from CPU format */
1065 +#define uap_cpu_to_le16(x) cpu_to_le16(x)
1066 +/** Convert to 32 bit little endian format from CPU format */
1067 +#define uap_cpu_to_le32(x) cpu_to_le32(x)
1068 +/** Convert to 64 bit little endian format from CPU format */
1069 +#define uap_cpu_to_le64(x) cpu_to_le64(x)
1070 +
1071 +/** Convert TxPD to little endian format from CPU format */
1072 +#define endian_convert_TxPD(x); \
1073 + { \
1074 + (x)->TxPktLength = uap_cpu_to_le16((x)->TxPktLength); \
1075 + (x)->TxPktOffset = uap_cpu_to_le32((x)->TxPktOffset); \
1076 + (x)->TxControl = uap_cpu_to_le32((x)->TxControl); \
1077 + (x)->TxPktType = uap_cpu_to_le32((x)->TxPktType); \
1078 + }
1079 +
1080 +/** Convert RxPD from little endian format to CPU format */
1081 +#define endian_convert_RxPD(x); \
1082 + { \
1083 + (x)->RxPktLength = uap_le16_to_cpu((x)->RxPktLength); \
1084 + (x)->RxPktOffset = uap_le32_to_cpu((x)->RxPktOffset); \
1085 + }
1086 +#else /* BIG_ENDIAN */
1087 +/** Do nothing */
1088 +#define uap_le16_to_cpu(x) x
1089 +/** Do nothing */
1090 +#define uap_le32_to_cpu(x) x
1091 +/** Do nothing */
1092 +#define uap_le64_to_cpu(x) x
1093 +/** Do nothing */
1094 +#define uap_cpu_to_le16(x) x
1095 +/** Do nothing */
1096 +#define uap_cpu_to_le32(x) x
1097 +/** Do nothing */
1098 +#define uap_cpu_to_le64(x) x
1099 +
1100 +/** Do nothing */
1101 +#define endian_convert_TxPD(x)
1102 +/** Do nothing */
1103 +#define endian_convert_RxPD(x)
1104 +#endif /* BIG_ENDIAN */
1105 +
1106 +/** Host Command ID : Function initialization */
1107 +#define HostCmd_CMD_FUNC_INIT 0x00a9
1108 +/** Host Command ID : Function shutdown */
1109 +#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa
1110 +
1111 +/** Host Command id: SYS_INFO */
1112 +#define HOST_CMD_APCMD_SYS_INFO 0x00ae
1113 +/** Host Command id: SYS_RESET */
1114 +#define HOST_CMD_APCMD_SYS_RESET 0x00af
1115 +/** Host Command id: SYS_CONFIGURE */
1116 +#define HOST_CMD_APCMD_SYS_CONFIGURE 0x00b0
1117 +/** Host Command id: BSS_START */
1118 +#define HOST_CMD_APCMD_BSS_START 0x00b1
1119 +/** Host Command id: SYS_STOP */
1120 +#define HOST_CMD_APCMD_BSS_STOP 0x00b2
1121 +/** Host Command id: STA_LIST */
1122 +#define HOST_CMD_APCMD_STA_LIST 0x00b3
1123 +/** Host Command id: STA_FILTER_TABLE */
1124 +#define HOST_CMD_APCMD_STA_FILTER_TABLE 0x00b4
1125 +/** Host Command id: STA_DEAUTH */
1126 +#define HOST_CMD_APCMD_STA_DEAUTH 0x00b5
1127 +/** Host Command id: SOFT_RESET */
1128 +#define HOST_CMD_APCMD_SOFT_RESET 0x00d5
1129 +/** Host Command id: POWER_MGMT_EXT */
1130 +#define HOST_CMD_POWER_MGMT_EXT 0x00ef
1131 +/** Host Command id: SLEEP_CONFIRM*/
1132 +#define HOST_CMD_SLEEP_CONFIRM 0x00d8
1133 +
1134 +/** TLV type : SSID */
1135 +#define TLV_TYPE_SSID 0x0000
1136 +/** TLV type : Rates */
1137 +#define TLV_TYPE_RATES 0x0001
1138 +/** TLV type : PHY DS */
1139 +#define TLV_TYPE_PHY_DS 0x0003
1140 +
1141 +/** TLV Id : Base id */
1142 +#define PROPRIETARY_TLV_BASE_ID 0x0100
1143 +/** TLV Id : AP_MAC_ADDRESS */
1144 +#define MRVL_AP_MAC_ADDRESS_TLV_ID (PROPRIETARY_TLV_BASE_ID + 43)
1145 +/** TLV Id : Beacon period */
1146 +#define MRVL_BEACON_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 44)
1147 +/** TLV Id : Dtim period */
1148 +#define MRVL_DTIM_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 45)
1149 +/** TLV Id : Basic rates */
1150 +#define MRVL_BASIC_RATES_TLV_ID (PROPRIETARY_TLV_BASE_ID + 46)
1151 +/** TLV Id : Tx Power */
1152 +#define MRVL_TX_POWER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 47)
1153 +/** TLV Id : Broadcast SSID control */
1154 +#define MRVL_BCAST_SSID_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 48)
1155 +/** TLV Id : Preamble control */
1156 +#define MRVL_PREAMBLE_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 49)
1157 +/** TLV Id : Antenna control */
1158 +#define MRVL_ANTENNA_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 50)
1159 +/** TLV Id : RTS threshold */
1160 +#define MRVL_RTS_THRESHOLD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 51)
1161 +/** TLV Id : Radio control */
1162 +#define MRVL_RADIO_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 52)
1163 +/** TLV Id : TX data rate */
1164 +#define MRVL_TX_DATA_RATE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 53)
1165 +/** TLV Id : Packet forward control */
1166 +#define MRVL_PKT_FWD_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 54)
1167 +/** TLV Id : STA info */
1168 +#define MRVL_STA_INFO_TLV_ID (PROPRIETARY_TLV_BASE_ID + 55)
1169 +/** TLV Id : STA MAC address filter */
1170 +#define MRVL_STA_MAC_ADDR_FILTER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 56)
1171 +/** TLV Id : STA ageout timer */
1172 +#define MRVL_STA_AGEOUT_TIMER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 57)
1173 +/** TLV Id : Security config */
1174 +#define MRVL_SECURITY_CFG_TLV_ID (PROPRIETARY_TLV_BASE_ID + 58)
1175 +/** TLV Id : WEP KEY */
1176 +#define MRVL_WEP_KEY_TLV_ID (PROPRIETARY_TLV_BASE_ID + 59)
1177 +/** TLV Id : WPA Passphrase */
1178 +#define MRVL_WPA_PASSPHRASE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 60)
1179 +
1180 +/** Action get */
1181 +#define ACTION_GET 0
1182 +/** Action set */
1183 +#define ACTION_SET 1
1184 +/** Length of ethernet address */
1185 +#ifndef ETH_ALEN
1186 +#define ETH_ALEN 6
1187 +#endif
1188 +
1189 +/** HostCmd_DS_GEN */
1190 +typedef struct
1191 +{
1192 + /** Command */
1193 + u16 Command;
1194 + /** Size */
1195 + u16 Size;
1196 + /** Sequence number */
1197 + u16 SeqNum;
1198 + /** Result */
1199 + u16 Result;
1200 +} __ATTRIB_PACK__ HostCmd_DS_GEN;
1201 +
1202 +/** Size of HostCmd_DS_GEN */
1203 +#define S_DS_GEN sizeof(HostCmd_DS_GEN)
1204 +
1205 +/** _HostCmd_HEADER*/
1206 +typedef struct
1207 +{
1208 + /** Command Header : Command */
1209 + u16 Command;
1210 + /** Command Header : Size */
1211 + u16 Size;
1212 +} __ATTRIB_PACK__ HostCmd_HEADER;
1213 +
1214 +/** HostCmd_SYS_CONFIG */
1215 +typedef struct _HostCmd_SYS_CONFIG
1216 +{
1217 + /** CMD Action GET/SET*/
1218 + u16 Action;
1219 + /** Tlv buffer */
1220 + u8 TlvBuffer[0];
1221 +} __ATTRIB_PACK__ HostCmd_SYS_CONFIG;
1222 +
1223 +/** HostCmd_DS_POWER_MGMT_EXT */
1224 +typedef struct _HostCmd_DS_POWER_MGMT_EXT
1225 +{
1226 + /** CMD Action Get/Set*/
1227 + u16 action;
1228 + /** power mode */
1229 + u16 power_mode;
1230 +} __ATTRIB_PACK__ HostCmd_DS_POWER_MGMT_EXT;
1231 +
1232 +/** _HostCmd_DS_COMMAND*/
1233 +typedef struct _HostCmd_DS_COMMAND
1234 +{
1235 +
1236 + /** Command Header : Command */
1237 + u16 Command;
1238 + /** Command Header : Size */
1239 + u16 Size;
1240 + /** Command Header : Sequence number */
1241 + u16 SeqNum;
1242 + /** Command Header : Result */
1243 + u16 Result;
1244 + /** Command Body */
1245 + union
1246 + {
1247 + HostCmd_SYS_CONFIG sys_config;
1248 + HostCmd_DS_POWER_MGMT_EXT pm_cfg;
1249 +
1250 + } params;
1251 +} __ATTRIB_PACK__ HostCmd_DS_COMMAND;
1252 +
1253 +/** MrvlIEtypesHeader_*/
1254 +typedef struct _MrvlIEtypesHeader
1255 +{
1256 + /** Header type */
1257 + u16 Type;
1258 + /** Header length */
1259 + u16 Len;
1260 +} __ATTRIB_PACK__ MrvlIEtypesHeader_t;
1261 +
1262 +/** MrvlIEtypes_Data_t */
1263 +typedef struct _MrvlIEtypes_Data_t
1264 +{
1265 + /** Header */
1266 + MrvlIEtypesHeader_t Header;
1267 + /** Data */
1268 + u8 Data[1];
1269 +} __ATTRIB_PACK__ MrvlIEtypes_Data_t;
1270 +
1271 +/** MrvlIEtypes_ChanListParamSet_t */
1272 +typedef struct _MrvlIEtypes_MacAddr_t
1273 +{
1274 + /** Header */
1275 + MrvlIEtypesHeader_t Header;
1276 + /** AP MAC address */
1277 + u8 ApMacAddr[ETH_ALEN];
1278 +} __ATTRIB_PACK__ MrvlIEtypes_MacAddr_t;
1279 +
1280 +/** Event ID: BSS started */
1281 +#define MICRO_AP_EV_ID_BSS_START 46
1282 +
1283 +/** Event ID: BSS idle event */
1284 +#define MICRO_AP_EV_BSS_IDLE 67
1285 +
1286 +/** Event ID: BSS active event */
1287 +#define MICRO_AP_EV_BSS_ACTIVE 68
1288 +
1289 +/** Event ID: PS_AWAKE */
1290 +#define EVENT_PS_AWAKE 0x0a
1291 +
1292 +/** Event ID: PS_SLEEP */
1293 +#define EVENT_PS_SLEEP 0x0b
1294 +
1295 +/** PS_STATE */
1296 +typedef enum _PS_STATE
1297 +{
1298 + PS_STATE_AWAKE,
1299 + PS_STATE_PRE_SLEEP,
1300 + PS_STATE_SLEEP
1301 +} PS_STATE;
1302 +
1303 +/** TLV type: AP Sleep param */
1304 +#define TLV_TYPE_AP_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 106)
1305 +/** TLV type: AP Inactivity Sleep param */
1306 +#define TLV_TYPE_AP_INACT_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 107)
1307 +
1308 +/** MrvlIEtypes_sleep_param_t */
1309 +typedef struct _MrvlIEtypes_sleep_param_t
1310 +{
1311 + /** Header */
1312 + MrvlIEtypesHeader_t header;
1313 + /** control bitmap */
1314 + u32 ctrl_bitmap;
1315 + /** min_sleep */
1316 + u32 min_sleep;
1317 + /** max_sleep */
1318 + u32 max_sleep;
1319 +} __ATTRIB_PACK__ MrvlIEtypes_sleep_param_t;
1320 +
1321 +/** MrvlIEtypes_inact_sleep_param_t */
1322 +typedef struct _MrvlIEtypes_inact_sleep_param_t
1323 +{
1324 + /** Header */
1325 + MrvlIEtypesHeader_t header;
1326 + /** inactivity timeout */
1327 + u32 inactivity_to;
1328 + /** min_awake */
1329 + u32 min_awake;
1330 + /** max_awake */
1331 + u32 max_awake;
1332 +} __ATTRIB_PACK__ MrvlIEtypes_inact_sleep_param_t;
1333 +
1334 +/** AP_Event */
1335 +typedef struct _AP_Event
1336 +{
1337 + /** Event ID */
1338 + u32 EventId;
1339 + /*
1340 + * Reserved for STA_ASSOCIATED event and contains
1341 + * status information for the MIC_COUNTERMEASURES event.
1342 + */
1343 + /** Reserved/status */
1344 + u16 status;
1345 + /** AP MAC address */
1346 + u8 MacAddr[ETH_ALEN];
1347 +} __ATTRIB_PACK__ AP_Event;
1348 +#endif /* _UAP_FW_H */
1349 diff --git a/drivers/net/wireless/libertas_uap/uap_headers.h b/drivers/net/wireless/libertas_uap/uap_headers.h
1350 new file mode 100644
1351 index 0000000..fa09af4
1352 --- /dev/null
1353 +++ b/drivers/net/wireless/libertas_uap/uap_headers.h
1354 @@ -0,0 +1,64 @@
1355 +/** @file uap_headers.h
1356 + *
1357 + * @brief This file contains all the necessary include file.
1358 + *
1359 + * Copyright (C) 2008-2009, Marvell International Ltd.
1360 + *
1361 + * This software file (the "File") is distributed by Marvell International
1362 + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
1363 + * (the "License"). You may use, redistribute and/or modify this File in
1364 + * accordance with the terms and conditions of the License, a copy of which
1365 + * is available along with the File in the gpl.txt file or by writing to
1366 + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1367 + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
1368 + *
1369 + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
1370 + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
1371 + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
1372 + * this warranty disclaimer.
1373 + *
1374 + */
1375 +#ifndef _UAP_HEADERS_H
1376 +#define _UAP_HEADERS_H
1377 +
1378 +/* Linux header files */
1379 +#include <linux/kernel.h>
1380 +#include <linux/module.h>
1381 +#include <linux/init.h>
1382 +#include <linux/version.h>
1383 +#include <linux/param.h>
1384 +#include <linux/types.h>
1385 +#include <linux/interrupt.h>
1386 +#include <linux/proc_fs.h>
1387 +#include <linux/kthread.h>
1388 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
1389 +#include <linux/semaphore.h>
1390 +#else
1391 +#include <asm/semaphore.h>
1392 +#endif
1393 +
1394 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
1395 +#include <linux/config.h>
1396 +#endif
1397 +
1398 +/* Net header files */
1399 +#include <linux/netdevice.h>
1400 +#include <linux/net.h>
1401 +#include <linux/skbuff.h>
1402 +#include <linux/if_ether.h>
1403 +#include <linux/etherdevice.h>
1404 +#include <net/sock.h>
1405 +#include <linux/netlink.h>
1406 +#include <linux/firmware.h>
1407 +#include <linux/delay.h>
1408 +
1409 +#include "uap_drv.h"
1410 +#include "uap_fw.h"
1411 +
1412 +#include <linux/mmc/sdio.h>
1413 +#include <linux/mmc/sdio_ids.h>
1414 +#include <linux/mmc/sdio_func.h>
1415 +#include <linux/mmc/card.h>
1416 +#include "uap_sdio_mmc.h"
1417 +
1418 +#endif /* _UAP_HEADERS_H */
1419 diff --git a/drivers/net/wireless/libertas_uap/uap_main.c b/drivers/net/wireless/libertas_uap/uap_main.c
1420 new file mode 100644
1421 index 0000000..6ad8403
1422 --- /dev/null
1423 +++ b/drivers/net/wireless/libertas_uap/uap_main.c
1424 @@ -0,0 +1,1817 @@
1425 +/** @file uap_main.c
1426 + * @brief This file contains the major functions in uAP
1427 + * driver. It includes init, exit etc..
1428 + * This file also contains the initialization for SW,
1429 + * FW and HW
1430 + *
1431 + * Copyright (C) 2008-2009, Marvell International Ltd.
1432 + *
1433 + * This software file (the "File") is distributed by Marvell International
1434 + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
1435 + * (the "License"). You may use, redistribute and/or modify this File in
1436 + * accordance with the terms and conditions of the License, a copy of which
1437 + * is available along with the File in the gpl.txt file or by writing to
1438 + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1439 + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
1440 + *
1441 + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
1442 + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
1443 + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
1444 + * this warranty disclaimer.
1445 + *
1446 + */
1447 +/**
1448 + * @mainpage uAP Linux Driver
1449 + *
1450 + * @section overview_sec Overview
1451 + *
1452 + * This is Linux reference driver for Marvell uAP.
1453 + *
1454 + * @section copyright_sec Copyright
1455 + *
1456 + * Copyright (C) 2008, Marvell International Ltd.
1457 + *
1458 + */
1459 +
1460 +#include "uap_headers.h"
1461 +
1462 +/**
1463 + * the global variable of a pointer to uap_private
1464 + * structure variable
1465 + */
1466 +uap_private *uappriv = NULL;
1467 +#ifdef DEBUG_LEVEL1
1468 +#define DEFAULT_DEBUG_MASK (DBG_MSG | DBG_FATAL | DBG_ERROR)
1469 +u32 drvdbg = DEFAULT_DEBUG_MASK;
1470 +#endif
1471 +/** Helper name */
1472 +char *helper_name = NULL;
1473 +/** Firmware name */
1474 +char *fw_name = NULL;
1475 +
1476 +/** Semaphore for add/remove card */
1477 +SEMAPHORE AddRemoveCardSem;
1478 +
1479 +/********************************************************
1480 + Local Functions
1481 +********************************************************/
1482 +/**
1483 + * @brief This function send sleep confirm command to firmware
1484 + *
1485 + * @param priv A pointer to uap_private structure
1486 + * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
1487 + */
1488 +static int
1489 +uap_dnld_sleep_confirm_cmd(uap_private * priv)
1490 +{
1491 + uap_adapter *Adapter = priv->adapter;
1492 + int ret = UAP_STATUS_SUCCESS;
1493 + ENTER();
1494 + PRINTM(CMND, "Sleep confirm\n");
1495 + Adapter->cmd_pending = TRUE;
1496 + Adapter->cmd_wait_option = HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM;
1497 + ret =
1498 + sbi_host_to_card(priv, (u8 *) & Adapter->PSConfirmSleep,
1499 + sizeof(PS_CMD_ConfirmSleep));
1500 + if (ret != UAP_STATUS_SUCCESS) {
1501 + Adapter->ps_state = PS_STATE_AWAKE;
1502 + Adapter->cmd_pending = FALSE;
1503 + Adapter->cmd_wait_option = FALSE;
1504 + }
1505 + LEAVE();
1506 + return ret;
1507 +}
1508 +
1509 +/**
1510 + * @brief This function process sleep confirm resp from firmware
1511 + *
1512 + * @param priv A pointer to uap_private structure
1513 + * @param resp A pointer to resp buf
1514 + * @param resp_len resp buf len
1515 + * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
1516 + */
1517 +int
1518 +uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len)
1519 +{
1520 + int ret = UAP_STATUS_SUCCESS;
1521 + HostCmd_DS_COMMAND *cmd;
1522 + uap_adapter *Adapter = priv->adapter;
1523 + ENTER();
1524 + PRINTM(CMND, "Sleep confirm resp\n");
1525 + if (!resp_len) {
1526 + PRINTM(ERROR, "Cmd Size is 0\n");
1527 + ret = -EFAULT;
1528 + goto done;
1529 + }
1530 + cmd = (HostCmd_DS_COMMAND *) resp;
1531 + cmd->Result = uap_le16_to_cpu(cmd->Result);
1532 + if (cmd->Result != UAP_STATUS_SUCCESS) {
1533 + PRINTM(ERROR, "HOST_CMD_APCMD_PS_SLEEP_CONFIRM fail=%x\n", cmd->Result);
1534 + ret = -EFAULT;
1535 + }
1536 + done:
1537 + if (ret == UAP_STATUS_SUCCESS)
1538 + Adapter->ps_state = PS_STATE_SLEEP;
1539 + else
1540 + Adapter->ps_state = PS_STATE_AWAKE;
1541 + LEAVE();
1542 + return ret;
1543 +}
1544 +
1545 +/**
1546 + * @brief This function checks condition and prepares to
1547 + * send sleep confirm command to firmware if OK.
1548 + *
1549 + * @param priv A pointer to uap_private structure
1550 + * @return n/a
1551 + */
1552 +static void
1553 +uap_ps_cond_check(uap_private * priv)
1554 +{
1555 + uap_adapter *Adapter = priv->adapter;
1556 +
1557 + ENTER();
1558 + if (!priv->uap_dev.cmd_sent &&
1559 + !Adapter->cmd_pending && !Adapter->IntCounter) {
1560 + uap_dnld_sleep_confirm_cmd(priv);
1561 + } else {
1562 + PRINTM(INFO, "Delay Sleep Confirm (%s%s%s)\n",
1563 + (priv->uap_dev.cmd_sent) ? "D" : "",
1564 + (Adapter->cmd_pending) ? "C" : "",
1565 + (Adapter->IntCounter) ? "I" : "");
1566 + }
1567 + LEAVE();
1568 +}
1569 +
1570 +/**
1571 + * @brief This function add cmd to cmdQ and waiting for response
1572 + *
1573 + * @param priv A pointer to uap_private structure
1574 + * @param skb A pointer to the skb for process
1575 + * @param wait_option Wait option
1576 + * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
1577 + */
1578 +static int
1579 +uap_process_cmd(uap_private * priv, struct sk_buff *skb, u8 wait_option)
1580 +{
1581 + uap_adapter *Adapter = priv->adapter;
1582 + int ret = UAP_STATUS_SUCCESS;
1583 + HostCmd_DS_COMMAND *cmd;
1584 + u8 *headptr;
1585 + ENTER();
1586 + if (Adapter->HardwareStatus != HWReady) {
1587 + PRINTM(ERROR, "Hw not ready, uap_process_cmd\n");
1588 + kfree(skb);
1589 + LEAVE();
1590 + return -EFAULT;
1591 + }
1592 + skb->cb[0] = wait_option;
1593 + headptr = skb->data;
1594 + *(u16 *) & headptr[0] = uap_cpu_to_le16(skb->len);
1595 + *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_CMD);
1596 + cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
1597 + Adapter->SeqNum++;
1598 + cmd->SeqNum = uap_cpu_to_le16(Adapter->SeqNum);
1599 + PRINTM(CMND, "process_cmd: %x\n", cmd->Command);
1600 + DBG_HEXDUMP(CMD_D, "process_cmd", (u8 *) cmd, cmd->Size);
1601 + if (!wait_option) {
1602 + skb_queue_tail(&priv->adapter->cmd_queue, skb);
1603 + wake_up_interruptible(&priv->MainThread.waitQ);
1604 + LEAVE();
1605 + return ret;
1606 + }
1607 + if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->CmdSem)) {
1608 + PRINTM(ERROR, "Acquire semaphore error, uap_prepare_cmd\n");
1609 + kfree(skb);
1610 + LEAVE();
1611 + return -EBUSY;
1612 + }
1613 + skb_queue_tail(&priv->adapter->cmd_queue, skb);
1614 + Adapter->CmdWaitQWoken = FALSE;
1615 + wake_up_interruptible(&priv->MainThread.waitQ);
1616 + /* Sleep until response is generated by FW */
1617 + if (wait_option == HostCmd_OPTION_WAITFORRSP_TIMEOUT) {
1618 + if (!os_wait_interruptible_timeout
1619 + (Adapter->cmdwait_q, Adapter->CmdWaitQWoken, MRVDRV_TIMER_20S)) {
1620 + PRINTM(ERROR, "Cmd timeout\n");
1621 + Adapter->cmd_pending = FALSE;
1622 + ret = -EFAULT;
1623 + }
1624 + } else
1625 + wait_event_interruptible(Adapter->cmdwait_q, Adapter->CmdWaitQWoken);
1626 + OS_REL_SEMAPHORE(&Adapter->CmdSem);
1627 + LEAVE();
1628 + return ret;
1629 +}
1630 +
1631 +/**
1632 + * @brief Inspect the response buffer for pointers to expected TLVs
1633 + *
1634 + *
1635 + * @param pTlv Pointer to the start of the TLV buffer to parse
1636 + * @param tlvBufSize Size of the TLV buffer
1637 + * @param reqTlvType request tlv's tlvtype
1638 + * @param ppTlv Output parameter: Pointer to the request TLV if found
1639 + *
1640 + * @return void
1641 + */
1642 +static void
1643 +uap_get_tlv_ptrs(MrvlIEtypes_Data_t * pTlv, int tlvBufSize,
1644 + u16 reqTlvType, MrvlIEtypes_Data_t ** ppTlv)
1645 +{
1646 + MrvlIEtypes_Data_t *pCurrentTlv;
1647 + int tlvBufLeft;
1648 + u16 tlvType;
1649 + u16 tlvLen;
1650 +
1651 + ENTER();
1652 + pCurrentTlv = pTlv;
1653 + tlvBufLeft = tlvBufSize;
1654 + *ppTlv = NULL;
1655 + PRINTM(INFO, "uap_get_tlv: tlvBufSize = %d, reqTlvType=%x\n", tlvBufSize,
1656 + reqTlvType);
1657 + while (tlvBufLeft >= sizeof(MrvlIEtypesHeader_t)) {
1658 + tlvType = uap_le16_to_cpu(pCurrentTlv->Header.Type);
1659 + tlvLen = uap_le16_to_cpu(pCurrentTlv->Header.Len);
1660 + if (reqTlvType == tlvType)
1661 + *ppTlv = (MrvlIEtypes_Data_t *) pCurrentTlv;
1662 + if (*ppTlv) {
1663 + HEXDUMP("TLV Buf", (u8 *) * ppTlv, tlvLen);
1664 + break;
1665 + }
1666 + tlvBufLeft -= (sizeof(pTlv->Header) + tlvLen);
1667 + pCurrentTlv = (MrvlIEtypes_Data_t *) (pCurrentTlv->Data + tlvLen);
1668 + } /* while */
1669 + LEAVE();
1670 +}
1671 +
1672 +/**
1673 + * @brief This function get mac
1674 + *
1675 + * @param priv A pointer to uap_private structure
1676 + * @return UAP_STATUS_SUCCESS on success, otherwise failure code
1677 + */
1678 +static int
1679 +uap_get_mac_address(uap_private * priv)
1680 +{
1681 + int ret = UAP_STATUS_SUCCESS;
1682 + u32 CmdSize;
1683 + HostCmd_DS_COMMAND *cmd;
1684 + uap_adapter *Adapter = priv->adapter;
1685 + struct sk_buff *skb;
1686 + MrvlIEtypes_MacAddr_t *pMacAddrTlv;
1687 + MrvlIEtypes_Data_t *pTlv;
1688 + u16 tlvBufSize;
1689 + ENTER();
1690 + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
1691 + if (!skb) {
1692 + PRINTM(ERROR, "No free skb\n");
1693 + ret = -ENOMEM;
1694 + goto done;
1695 + }
1696 + CmdSize =
1697 + S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t);
1698 + cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
1699 + cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
1700 + cmd->Size = uap_cpu_to_le16(CmdSize);
1701 + cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_GET);
1702 + pMacAddrTlv =
1703 + (MrvlIEtypes_MacAddr_t *) (skb->data + INTF_HEADER_LEN + S_DS_GEN +
1704 + sizeof(HostCmd_SYS_CONFIG));
1705 + pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID);
1706 + pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN);
1707 + skb_put(skb, CmdSize + INTF_HEADER_LEN);
1708 + if (UAP_STATUS_SUCCESS !=
1709 + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
1710 + PRINTM(ERROR, "Fail to process cmd SYS_CONFIGURE Query\n");
1711 + ret = -EFAULT;
1712 + goto done;
1713 + }
1714 + if (!Adapter->CmdSize) {
1715 + PRINTM(ERROR, "Cmd Size is 0\n");
1716 + ret = -EFAULT;
1717 + goto done;
1718 + }
1719 + cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
1720 + cmd->Result = uap_le16_to_cpu(cmd->Result);
1721 + if (cmd->Result != UAP_STATUS_SUCCESS) {
1722 + PRINTM(ERROR, "uap_get_mac_address fail=%x\n", cmd->Result);
1723 + ret = -EFAULT;
1724 + goto done;
1725 + }
1726 + pTlv =
1727 + (MrvlIEtypes_Data_t *) (Adapter->CmdBuf + S_DS_GEN +
1728 + sizeof(HostCmd_SYS_CONFIG));
1729 + tlvBufSize = Adapter->CmdSize - S_DS_GEN - sizeof(HostCmd_SYS_CONFIG);
1730 + uap_get_tlv_ptrs(pTlv, tlvBufSize, MRVL_AP_MAC_ADDRESS_TLV_ID,
1731 + (MrvlIEtypes_Data_t **) & pMacAddrTlv);
1732 + if (pMacAddrTlv) {
1733 + memcpy(priv->uap_dev.netdev->dev_addr, pMacAddrTlv->ApMacAddr,
1734 + ETH_ALEN);
1735 + HEXDUMP("Original MAC addr", priv->uap_dev.netdev->dev_addr, ETH_ALEN);
1736 + }
1737 + done:
1738 + LEAVE();
1739 + return ret;
1740 +}
1741 +
1742 +/**
1743 + * @brief This function checks the conditions and sends packet to device
1744 + *
1745 + * @param priv A pointer to uap_private structure
1746 + * @param skb A pointer to the skb for process
1747 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
1748 + */
1749 +static int
1750 +uap_process_tx(uap_private * priv, struct sk_buff *skb)
1751 +{
1752 + uap_adapter *Adapter = priv->adapter;
1753 + int ret = UAP_STATUS_SUCCESS;
1754 + TxPD *pLocalTxPD;
1755 + u8 *headptr;
1756 + struct sk_buff *newskb;
1757 + int newheadlen;
1758 + ENTER();
1759 + ASSERT(skb);
1760 + if (!skb) {
1761 + LEAVE();
1762 + return UAP_STATUS_FAILURE;
1763 + }
1764 + if (skb_headroom(skb) < (sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT)) {
1765 + newheadlen = sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT;
1766 + PRINTM(WARN, "Tx: Insufficient skb headroom %d\n", skb_headroom(skb));
1767 + /* Insufficient skb headroom - allocate a new skb */
1768 + newskb = skb_realloc_headroom(skb, newheadlen);
1769 + if (unlikely(newskb == NULL)) {
1770 + PRINTM(ERROR, "Tx: Cannot allocate skb\n");
1771 + ret = UAP_STATUS_FAILURE;
1772 + goto done;
1773 + }
1774 + kfree_skb(skb);
1775 + skb = newskb;
1776 + PRINTM(INFO, "new skb headroom %d\n", skb_headroom(skb));
1777 + }
1778 + /* headptr should be aligned */
1779 + headptr = skb->data - sizeof(TxPD) - INTF_HEADER_LEN;
1780 + headptr = (u8 *) ((u32) headptr & ~((u32) (HEADER_ALIGNMENT - 1)));
1781 +
1782 + pLocalTxPD = (TxPD *) (headptr + INTF_HEADER_LEN);
1783 + memset(pLocalTxPD, 0, sizeof(TxPD));
1784 + pLocalTxPD->BssType = PKT_TYPE_MICROAP;
1785 + pLocalTxPD->TxPktLength = skb->len;
1786 + /* offset of actual data */
1787 + pLocalTxPD->TxPktOffset = (long) skb->data - (long) pLocalTxPD;
1788 + endian_convert_TxPD(pLocalTxPD);
1789 + *(u16 *) & headptr[0] =
1790 + uap_cpu_to_le16(skb->len + ((long) skb->data - (long) headptr));
1791 + *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_DAT);
1792 + ret =
1793 + sbi_host_to_card(priv, headptr,
1794 + skb->len + ((long) skb->data - (long) headptr));
1795 + if (ret) {
1796 + PRINTM(ERROR, "uap_process_tx Error: sbi_host_to_card failed: 0x%X\n",
1797 + ret);
1798 + Adapter->dbg.num_tx_host_to_card_failure++;
1799 + goto done;
1800 + }
1801 + PRINTM(DATA, "Data => FW\n");
1802 + DBG_HEXDUMP(DAT_D, "Tx", headptr,
1803 + MIN(skb->len + sizeof(TxPD), DATA_DUMP_LEN));
1804 + done:
1805 + /* Freed skb */
1806 + kfree_skb(skb);
1807 + LEAVE();
1808 + return ret;
1809 +}
1810 +
1811 +static struct netlink_kernel_cfg cfg = {
1812 + .groups = NL_MULTICAST_GROUP,
1813 +};
1814 +
1815 +/**
1816 + * @brief This function initializes the adapter structure
1817 + * and set default value to the member of adapter.
1818 + *
1819 + * @param priv A pointer to uap_private structure
1820 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
1821 + */
1822 +static int
1823 +uap_init_sw(uap_private * priv)
1824 +{
1825 + uap_adapter *Adapter = priv->adapter;
1826 +
1827 + ENTER();
1828 +
1829 + if (!(Adapter->CmdBuf = kmalloc(MRVDRV_SIZE_OF_CMD_BUFFER, GFP_KERNEL))) {
1830 + PRINTM(INFO, "Failed to allocate command buffer!\n");
1831 + LEAVE();
1832 + return UAP_STATUS_FAILURE;
1833 + }
1834 +
1835 + Adapter->cmd_pending = FALSE;
1836 + Adapter->CmdWaitQWoken = FALSE;
1837 + Adapter->ps_state = PS_STATE_AWAKE;
1838 + Adapter->WakeupTries = 0;
1839 +
1840 + memset(&Adapter->PSConfirmSleep, 0, sizeof(PS_CMD_ConfirmSleep));
1841 + /** SDIO header */
1842 + Adapter->PSConfirmSleep.SDLen =
1843 + uap_cpu_to_le16(sizeof(PS_CMD_ConfirmSleep));
1844 + Adapter->PSConfirmSleep.SDType = uap_cpu_to_le16(MV_TYPE_CMD);
1845 + Adapter->PSConfirmSleep.SeqNum = 0;
1846 + Adapter->PSConfirmSleep.Command = uap_cpu_to_le16(HOST_CMD_SLEEP_CONFIRM);
1847 + Adapter->PSConfirmSleep.Size = uap_cpu_to_le16(sizeof(HostCmd_DS_GEN));
1848 + Adapter->PSConfirmSleep.Result = 0;
1849 +
1850 + init_waitqueue_head(&Adapter->cmdwait_q);
1851 + OS_INIT_SEMAPHORE(&Adapter->CmdSem);
1852 +
1853 + skb_queue_head_init(&Adapter->tx_queue);
1854 + skb_queue_head_init(&Adapter->cmd_queue);
1855 +
1856 + /* Status variable */
1857 + Adapter->HardwareStatus = HWInitializing;
1858 +
1859 + /* PnP support */
1860 + Adapter->SurpriseRemoved = FALSE;
1861 +
1862 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
1863 + Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL,
1864 + NL_MULTICAST_GROUP, NULL,
1865 + THIS_MODULE);
1866 +#else
1867 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
1868 + Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL,
1869 + NL_MULTICAST_GROUP, NULL, NULL,
1870 + THIS_MODULE);
1871 +#else
1872 + Adapter->nl_sk = netlink_kernel_create(&init_net, NETLINK_MARVELL, &cfg);
1873 +#endif
1874 +#endif
1875 + if (!Adapter->nl_sk) {
1876 + PRINTM(ERROR,
1877 + "Could not initialize netlink event passing mechanism!\n");
1878 + }
1879 + LEAVE();
1880 + return UAP_STATUS_SUCCESS;
1881 +}
1882 +
1883 +/**
1884 + * @brief This function sends FUNC_INIT command to firmware
1885 + *
1886 + * @param priv A pointer to uap_private structure
1887 + * @return UAP_STATUS_SUCCESS on success, otherwise failure code
1888 + */
1889 +static int
1890 +uap_func_init(uap_private * priv)
1891 +{
1892 + int ret = UAP_STATUS_SUCCESS;
1893 + u32 CmdSize;
1894 + HostCmd_DS_GEN *cmd;
1895 + uap_adapter *Adapter = priv->adapter;
1896 + struct sk_buff *skb;
1897 + ENTER();
1898 + if (Adapter->HardwareStatus != HWReady) {
1899 + PRINTM(ERROR, "uap_func_init:Hardware is not ready!\n");
1900 + ret = -EFAULT;
1901 + goto done;
1902 + }
1903 + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
1904 + if (!skb) {
1905 + PRINTM(ERROR, "No free skb\n");
1906 + ret = -ENOMEM;
1907 + goto done;
1908 + }
1909 + CmdSize = sizeof(HostCmd_DS_GEN);
1910 + cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
1911 + cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_INIT);
1912 + cmd->Size = uap_cpu_to_le16(CmdSize);
1913 + skb_put(skb, CmdSize + INTF_HEADER_LEN);
1914 + PRINTM(CMND, "HostCmd_CMD_FUNC_INIT\n");
1915 + if (UAP_STATUS_SUCCESS !=
1916 + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
1917 + PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_INIT\n");
1918 + ret = -EFAULT;
1919 + goto done;
1920 + }
1921 + done:
1922 + LEAVE();
1923 + return ret;
1924 +}
1925 +
1926 +/**
1927 + * @brief This function sends FUNC_SHUTDOWN command to firmware
1928 + *
1929 + * @param priv A pointer to uap_private structure
1930 + * @return UAP_STATUS_SUCCESS on success, otherwise failure code
1931 + */
1932 +static int __exit
1933 +uap_func_shutdown(uap_private * priv)
1934 +{
1935 + int ret = UAP_STATUS_SUCCESS;
1936 + u32 CmdSize;
1937 + HostCmd_DS_GEN *cmd;
1938 + uap_adapter *Adapter = priv->adapter;
1939 + struct sk_buff *skb;
1940 + ENTER();
1941 + if (Adapter->HardwareStatus != HWReady) {
1942 + PRINTM(ERROR, "uap_func_shutdown:Hardware is not ready!\n");
1943 + ret = -EFAULT;
1944 + goto done;
1945 + }
1946 + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
1947 + if (!skb) {
1948 + PRINTM(ERROR, "No free skb\n");
1949 + ret = -ENOMEM;
1950 + goto done;
1951 + }
1952 + CmdSize = sizeof(HostCmd_DS_GEN);
1953 + cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
1954 + cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_SHUTDOWN);
1955 + cmd->Size = uap_cpu_to_le16(CmdSize);
1956 + skb_put(skb, CmdSize + INTF_HEADER_LEN);
1957 + PRINTM(CMND, "HostCmd_CMD_FUNC_SHUTDOWN\n");
1958 + if (UAP_STATUS_SUCCESS !=
1959 + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
1960 + PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_SHUTDOWN\n");
1961 + ret = -EFAULT;
1962 + goto done;
1963 + }
1964 + done:
1965 + LEAVE();
1966 + return ret;
1967 +}
1968 +
1969 +/**
1970 + * @brief This function initializes firmware
1971 + *
1972 + * @param priv A pointer to uap_private structure
1973 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
1974 + */
1975 +static int
1976 +uap_init_fw(uap_private * priv)
1977 +{
1978 + int ret = UAP_STATUS_SUCCESS;
1979 + ENTER();
1980 + sbi_disable_host_int(priv);
1981 + /* Check if firmware is already running */
1982 + if (sbi_check_fw_status(priv, 1) == UAP_STATUS_SUCCESS) {
1983 + PRINTM(MSG, "UAP FW already running! Skip FW download\n");
1984 + } else {
1985 + if ((ret = request_firmware(&priv->fw_helper, helper_name,
1986 + priv->hotplug_device)) < 0) {
1987 + PRINTM(FATAL,
1988 + "request_firmware() failed (helper), error code = %#x\n",
1989 + ret);
1990 + goto done;
1991 + }
1992 +
1993 + /* Download the helper */
1994 + ret = sbi_prog_helper(priv);
1995 +
1996 + if (ret) {
1997 + PRINTM(FATAL,
1998 + "Bootloader in invalid state! Helper download failed!\n");
1999 + ret = UAP_STATUS_FAILURE;
2000 + goto done;
2001 + }
2002 + if ((ret = request_firmware(&priv->firmware, fw_name,
2003 + priv->hotplug_device)) < 0) {
2004 + PRINTM(FATAL, "request_firmware() failed, error code = %#x\n", ret);
2005 + goto done;
2006 + }
2007 +
2008 + /* Download the main firmware via the helper firmware */
2009 + if (sbi_prog_fw_w_helper(priv)) {
2010 + PRINTM(FATAL, "UAP FW download failed!\n");
2011 + ret = UAP_STATUS_FAILURE;
2012 + goto done;
2013 + }
2014 + /* Check if the firmware is downloaded successfully or not */
2015 + if (sbi_check_fw_status(priv, MAX_FIRMWARE_POLL_TRIES) ==
2016 + UAP_STATUS_FAILURE) {
2017 + PRINTM(FATAL, "FW failed to be active in time!\n");
2018 + ret = UAP_STATUS_FAILURE;
2019 + goto done;
2020 + }
2021 + PRINTM(MSG, "UAP FW is active\n");
2022 + }
2023 + sbi_enable_host_int(priv);
2024 + priv->adapter->HardwareStatus = HWReady;
2025 + if (uap_func_init(priv) != UAP_STATUS_SUCCESS) {
2026 + ret = UAP_STATUS_FAILURE;
2027 + goto done;
2028 + }
2029 + done:
2030 + if (priv->fw_helper)
2031 + release_firmware(priv->fw_helper);
2032 + if (priv->firmware)
2033 + release_firmware(priv->firmware);
2034 + LEAVE();
2035 + return ret;
2036 +
2037 +}
2038 +
2039 +/**
2040 + * @brief This function frees the structure of adapter
2041 + *
2042 + * @param priv A pointer to uap_private structure
2043 + * @return n/a
2044 + */
2045 +static void
2046 +uap_free_adapter(uap_private * priv)
2047 +{
2048 + uap_adapter *Adapter = priv->adapter;
2049 +
2050 + ENTER();
2051 +
2052 + if (Adapter) {
2053 + if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) {
2054 + sock_release((Adapter->nl_sk)->sk_socket);
2055 + Adapter->nl_sk = NULL;
2056 + }
2057 + if (Adapter->CmdBuf)
2058 + kfree(Adapter->CmdBuf);
2059 + skb_queue_purge(&priv->adapter->tx_queue);
2060 + skb_queue_purge(&priv->adapter->cmd_queue);
2061 + /* Free the adapter object itself */
2062 + kfree(Adapter);
2063 + priv->adapter = NULL;
2064 + }
2065 +
2066 + LEAVE();
2067 +}
2068 +
2069 +/**
2070 + * @brief This function handles the major job in uap driver.
2071 + * it handles the event generated by firmware, rx data received
2072 + * from firmware and tx data sent from kernel.
2073 + *
2074 + * @param data A pointer to uap_thread structure
2075 + * @return BT_STATUS_SUCCESS
2076 + */
2077 +static int
2078 +uap_service_main_thread(void *data)
2079 +{
2080 + uap_thread *thread = data;
2081 + uap_private *priv = thread->priv;
2082 + uap_adapter *Adapter = priv->adapter;
2083 + wait_queue_t wait;
2084 + u8 ireg = 0;
2085 + struct sk_buff *skb;
2086 + ENTER();
2087 + uap_activate_thread(thread);
2088 + init_waitqueue_entry(&wait, current);
2089 + current->flags |= PF_NOFREEZE;
2090 +
2091 + for (;;) {
2092 + add_wait_queue(&thread->waitQ, &wait);
2093 + OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE);
2094 + if ((Adapter->WakeupTries) ||
2095 + (!Adapter->IntCounter && Adapter->ps_state == PS_STATE_PRE_SLEEP) ||
2096 + (!priv->adapter->IntCounter
2097 + && (priv->uap_dev.data_sent ||
2098 + skb_queue_empty(&priv->adapter->tx_queue))
2099 + && (priv->uap_dev.cmd_sent || Adapter->cmd_pending ||
2100 + skb_queue_empty(&priv->adapter->cmd_queue))
2101 + )) {
2102 + PRINTM(INFO, "Main: Thread sleeping...\n");
2103 + schedule();
2104 + }
2105 + OS_SET_THREAD_STATE(TASK_RUNNING);
2106 + remove_wait_queue(&thread->waitQ, &wait);
2107 + if (kthread_should_stop() || Adapter->SurpriseRemoved) {
2108 + PRINTM(INFO, "main-thread: break from main thread: "
2109 + "SurpriseRemoved=0x%x\n", Adapter->SurpriseRemoved);
2110 + /* Cancel pending command */
2111 + if (Adapter->cmd_pending == TRUE) {
2112 + /* Wake up cmd Q */
2113 + Adapter->CmdWaitQWoken = TRUE;
2114 + wake_up_interruptible(&Adapter->cmdwait_q);
2115 + }
2116 + break;
2117 + }
2118 +
2119 + PRINTM(INFO, "Main: Thread waking up...\n");
2120 + if (priv->adapter->IntCounter) {
2121 + OS_INT_DISABLE;
2122 + Adapter->IntCounter = 0;
2123 + OS_INT_RESTORE;
2124 + sbi_get_int_status(priv, &ireg);
2125 + } else if ((priv->adapter->ps_state == PS_STATE_SLEEP) &&
2126 + (!skb_queue_empty(&priv->adapter->cmd_queue) ||
2127 + !skb_queue_empty(&priv->adapter->tx_queue))) {
2128 + priv->adapter->WakeupTries++;
2129 + PRINTM(CMND, "%lu : Wakeup device...\n", os_time_get());
2130 + sbi_wakeup_firmware(priv);
2131 + continue;
2132 + }
2133 + if (Adapter->ps_state == PS_STATE_PRE_SLEEP)
2134 + uap_ps_cond_check(priv);
2135 +
2136 + /* The PS state is changed during processing of Sleep Request event
2137 + above */
2138 + if ((Adapter->ps_state == PS_STATE_SLEEP) ||
2139 + (Adapter->ps_state == PS_STATE_PRE_SLEEP))
2140 + continue;
2141 + /* Execute the next command */
2142 + if (!priv->uap_dev.cmd_sent && !Adapter->cmd_pending &&
2143 + (Adapter->HardwareStatus == HWReady)) {
2144 + if (!skb_queue_empty(&priv->adapter->cmd_queue)) {
2145 + skb = skb_dequeue(&priv->adapter->cmd_queue);
2146 + if (skb) {
2147 + Adapter->CmdSize = 0;
2148 + Adapter->cmd_pending = TRUE;
2149 + Adapter->cmd_wait_option = skb->cb[0];
2150 + if (sbi_host_to_card(priv, skb->data, skb->len)) {
2151 + PRINTM(ERROR, "Cmd:sbi_host_to_card failed!\n");
2152 + Adapter->cmd_pending = FALSE;
2153 + Adapter->dbg.num_cmd_host_to_card_failure++;
2154 + /* Wake up cmd Q */
2155 + Adapter->CmdWaitQWoken = TRUE;
2156 + wake_up_interruptible(&Adapter->cmdwait_q);
2157 + } else {
2158 + if (Adapter->cmd_wait_option ==
2159 + HostCmd_OPTION_WAITFORSEND) {
2160 + /* Wake up cmd Q */
2161 + Adapter->CmdWaitQWoken = TRUE;
2162 + wake_up_interruptible(&Adapter->cmdwait_q);
2163 + Adapter->cmd_wait_option = FALSE;
2164 + }
2165 + }
2166 + kfree_skb(skb);
2167 + }
2168 + }
2169 + }
2170 + if (!priv->uap_dev.data_sent && (Adapter->HardwareStatus == HWReady)) {
2171 + if (!skb_queue_empty(&priv->adapter->tx_queue)) {
2172 + skb = skb_dequeue(&priv->adapter->tx_queue);
2173 + if (skb) {
2174 + if (uap_process_tx(priv, skb)) {
2175 + priv->stats.tx_dropped++;
2176 + priv->stats.tx_errors++;
2177 + os_start_queue(priv);
2178 + } else {
2179 + priv->stats.tx_packets++;
2180 + priv->stats.tx_bytes += skb->len;
2181 + }
2182 +
2183 + }
2184 + }
2185 + }
2186 + }
2187 + uap_deactivate_thread(thread);
2188 + LEAVE();
2189 + return UAP_STATUS_SUCCESS;
2190 +}
2191 +
2192 +/**
2193 + * @brief uap hostcmd ioctl handler
2194 + *
2195 + * @param dev A pointer to net_device structure
2196 + * @param req A pointer to ifreq structure
2197 + * @return UAP_STATUS_SUCCESS --success, otherwise fail
2198 + */
2199 +/********* format of ifr_data *************/
2200 +/* buf_len + Hostcmd_body */
2201 +/* buf_len: 4 bytes */
2202 +/* the length of the buf which */
2203 +/* can be used to return data */
2204 +/* to application */
2205 +/* Hostcmd_body */
2206 +/*******************************************/
2207 +static int
2208 +uap_hostcmd_ioctl(struct net_device *dev, struct ifreq *req)
2209 +{
2210 + u32 buf_len;
2211 + HostCmd_HEADER head;
2212 + uap_private *priv = (uap_private *) netdev_priv(dev);
2213 + uap_adapter *Adapter = priv->adapter;
2214 + int ret = UAP_STATUS_SUCCESS;
2215 + struct sk_buff *skb;
2216 +
2217 + ENTER();
2218 +
2219 + /* Sanity check */
2220 + if (req->ifr_data == NULL) {
2221 + PRINTM(ERROR, "uap_hostcmd_ioctl() corrupt data\n");
2222 + LEAVE();
2223 + return -EFAULT;
2224 + }
2225 + if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) {
2226 + PRINTM(ERROR, "Copy from user failed\n");
2227 + LEAVE();
2228 + return -EFAULT;
2229 + }
2230 + memset(&head, 0, sizeof(HostCmd_HEADER));
2231 + /* Get the command size from user space */
2232 + if (copy_from_user
2233 + (&head, req->ifr_data + sizeof(buf_len), sizeof(HostCmd_HEADER))) {
2234 + PRINTM(ERROR, "Copy from user failed\n");
2235 + LEAVE();
2236 + return -EFAULT;
2237 + }
2238 + head.Size = uap_le16_to_cpu(head.Size);
2239 + if (head.Size > MRVDRV_SIZE_OF_CMD_BUFFER) {
2240 + PRINTM(ERROR, "CmdSize too big=%d\n", head.Size);
2241 + LEAVE();
2242 + return -EFAULT;
2243 + }
2244 + PRINTM(CMND, "ioctl: hostcmd=%x, size=%d,buf_len=%d\n", head.Command,
2245 + head.Size, buf_len);
2246 + skb = dev_alloc_skb(head.Size + INTF_HEADER_LEN);
2247 + if (!skb) {
2248 + PRINTM(ERROR, "No free skb\n");
2249 + LEAVE();
2250 + return -ENOMEM;
2251 + }
2252 +
2253 + /* Get the command from user space */
2254 + if (copy_from_user
2255 + (skb->data + INTF_HEADER_LEN, req->ifr_data + sizeof(buf_len),
2256 + head.Size)) {
2257 + PRINTM(ERROR, "Copy from user failed\n");
2258 + LEAVE();
2259 + return -EFAULT;
2260 + }
2261 + skb_put(skb, head.Size + INTF_HEADER_LEN);
2262 + if (UAP_STATUS_SUCCESS !=
2263 + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) {
2264 + PRINTM(ERROR, "Fail to process cmd\n");
2265 + LEAVE();
2266 + return -EFAULT;
2267 + }
2268 + if (!Adapter->CmdSize) {
2269 + PRINTM(ERROR, "Cmd Size is 0\n");
2270 + LEAVE();
2271 + return -EFAULT;
2272 + }
2273 + if (Adapter->CmdSize > buf_len) {
2274 + PRINTM(ERROR, "buf_len is too small\n");
2275 + LEAVE();
2276 + return -EFAULT;
2277 + }
2278 + /* Copy to user */
2279 + if (copy_to_user
2280 + (req->ifr_data + sizeof(buf_len), Adapter->CmdBuf, Adapter->CmdSize)) {
2281 + PRINTM(ERROR, "Copy to user failed!\n");
2282 + LEAVE();
2283 + return -EFAULT;
2284 + }
2285 + LEAVE();
2286 + return ret;
2287 +}
2288 +
2289 +/**
2290 + * @brief uap power mode ioctl handler
2291 + *
2292 + * @param dev A pointer to net_device structure
2293 + * @param req A pointer to ifreq structure
2294 + * @return UAP_STATUS_SUCCESS --success, otherwise fail
2295 + */
2296 +static int
2297 +uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req)
2298 +{
2299 + ps_mgmt pm_cfg;
2300 + int ret = UAP_STATUS_SUCCESS;
2301 + uap_private *priv = (uap_private *) netdev_priv(dev);
2302 + uap_adapter *Adapter = priv->adapter;
2303 + struct sk_buff *skb = NULL;
2304 + HostCmd_DS_COMMAND *cmd;
2305 + u32 CmdSize;
2306 + u8 *tlv = NULL;
2307 + MrvlIEtypes_sleep_param_t *sleep_tlv = NULL;
2308 + MrvlIEtypes_inact_sleep_param_t *inact_tlv = NULL;
2309 + u16 tlv_buf_left = 0;
2310 + MrvlIEtypesHeader_t *tlvbuf = NULL;
2311 + u16 tlv_type = 0;
2312 + u16 tlv_len = 0;
2313 +
2314 + ENTER();
2315 +
2316 + /* Sanity check */
2317 + if (req->ifr_data == NULL) {
2318 + PRINTM(ERROR, "uap_power_mode_ioctl() corrupt data\n");
2319 + LEAVE();
2320 + return -EFAULT;
2321 + }
2322 +
2323 + memset(&pm_cfg, 0, sizeof(ps_mgmt));
2324 + if (copy_from_user(&pm_cfg, req->ifr_data, sizeof(ps_mgmt))) {
2325 + PRINTM(ERROR, "Copy from user failed\n");
2326 + LEAVE();
2327 + return -EFAULT;
2328 + }
2329 + PRINTM(CMND,
2330 + "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d "
2331 + "inact_to=%d min_awake=%d max_awake=%d\n", pm_cfg.flags,
2332 + (int) pm_cfg.ps_mode, (int) pm_cfg.sleep_param.ctrl_bitmap,
2333 + (int) pm_cfg.sleep_param.min_sleep,
2334 + (int) pm_cfg.sleep_param.max_sleep,
2335 + (int) pm_cfg.inact_param.inactivity_to,
2336 + (int) pm_cfg.inact_param.min_awake,
2337 + (int) pm_cfg.inact_param.max_awake);
2338 +
2339 + if (pm_cfg.
2340 + flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM |
2341 + PS_FLAG_INACT_SLEEP_PARAM)) {
2342 + PRINTM(ERROR, "Invalid parameter: flags = 0x%x\n", pm_cfg.flags);
2343 + ret = -EINVAL;
2344 + goto done;
2345 + }
2346 + if (pm_cfg.ps_mode > PS_MODE_INACTIVITY) {
2347 + PRINTM(ERROR, "Invalid parameter: ps_mode = %d\n", (int) pm_cfg.flags);
2348 + ret = -EINVAL;
2349 + goto done;
2350 + }
2351 +
2352 + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
2353 + if (!skb) {
2354 + PRINTM(INFO, "No free skb\n");
2355 + ret = -ENOMEM;
2356 + goto done;
2357 + }
2358 +
2359 + CmdSize = S_DS_GEN + sizeof(HostCmd_DS_POWER_MGMT_EXT);
2360 +
2361 + cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
2362 + cmd->Command = uap_cpu_to_le16(HOST_CMD_POWER_MGMT_EXT);
2363 + if (!pm_cfg.flags) {
2364 + cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_GET);
2365 + } else {
2366 + cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_SET);
2367 + cmd->params.pm_cfg.power_mode = uap_cpu_to_le16(pm_cfg.ps_mode);
2368 + tlv = (u8 *) & cmd->params.pm_cfg + sizeof(HostCmd_DS_POWER_MGMT_EXT);
2369 +
2370 + if ((pm_cfg.ps_mode) && (pm_cfg.flags & PS_FLAG_SLEEP_PARAM)) {
2371 + sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlv;
2372 + sleep_tlv->header.Type = uap_cpu_to_le16(TLV_TYPE_AP_SLEEP_PARAM);
2373 + sleep_tlv->header.Len =
2374 + uap_cpu_to_le16(sizeof(MrvlIEtypes_sleep_param_t) -
2375 + sizeof(MrvlIEtypesHeader_t));
2376 + sleep_tlv->ctrl_bitmap =
2377 + uap_cpu_to_le32(pm_cfg.sleep_param.ctrl_bitmap);
2378 + sleep_tlv->min_sleep =
2379 + uap_cpu_to_le32(pm_cfg.sleep_param.min_sleep);
2380 + sleep_tlv->max_sleep =
2381 + uap_cpu_to_le32(pm_cfg.sleep_param.max_sleep);
2382 + CmdSize += sizeof(MrvlIEtypes_sleep_param_t);
2383 + tlv += sizeof(MrvlIEtypes_sleep_param_t);
2384 + }
2385 + if ((pm_cfg.ps_mode == PS_MODE_INACTIVITY) &&
2386 + (pm_cfg.flags & PS_FLAG_INACT_SLEEP_PARAM)) {
2387 + inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlv;
2388 + inact_tlv->header.Type =
2389 + uap_cpu_to_le16(TLV_TYPE_AP_INACT_SLEEP_PARAM);
2390 + inact_tlv->header.Len =
2391 + uap_cpu_to_le16(sizeof(MrvlIEtypes_inact_sleep_param_t) -
2392 + sizeof(MrvlIEtypesHeader_t));
2393 + inact_tlv->inactivity_to =
2394 + uap_cpu_to_le32(pm_cfg.inact_param.inactivity_to);
2395 + inact_tlv->min_awake =
2396 + uap_cpu_to_le32(pm_cfg.inact_param.min_awake);
2397 + inact_tlv->max_awake =
2398 + uap_cpu_to_le32(pm_cfg.inact_param.max_awake);
2399 + CmdSize += sizeof(MrvlIEtypes_inact_sleep_param_t);
2400 + tlv += sizeof(MrvlIEtypes_inact_sleep_param_t);
2401 + }
2402 + }
2403 + cmd->Size = uap_cpu_to_le16(CmdSize);
2404 + skb_put(skb, CmdSize + INTF_HEADER_LEN);
2405 + if (UAP_STATUS_SUCCESS !=
2406 + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) {
2407 + PRINTM(ERROR, "Fail to process cmd POWER_MODE\n");
2408 + ret = -EFAULT;
2409 + goto done;
2410 + }
2411 + if (!Adapter->CmdSize) {
2412 + PRINTM(ERROR, "Cmd Size is 0\n");
2413 + ret = -EFAULT;
2414 + goto done;
2415 + }
2416 + cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
2417 + cmd->Result = uap_le16_to_cpu(cmd->Result);
2418 + if (cmd->Result != UAP_STATUS_SUCCESS) {
2419 + PRINTM(ERROR, "HOST_CMD_APCMD_POWER_MODE fail=%x\n", cmd->Result);
2420 + ret = -EFAULT;
2421 + goto done;
2422 + }
2423 + if (pm_cfg.flags) {
2424 + Adapter->psmode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode);
2425 + } else {
2426 + pm_cfg.flags = PS_FLAG_PS_MODE;
2427 + pm_cfg.ps_mode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode);
2428 + tlv_buf_left =
2429 + cmd->Size - (sizeof(HostCmd_DS_POWER_MGMT_EXT) + S_DS_GEN);
2430 + tlvbuf =
2431 + (MrvlIEtypesHeader_t *) ((u8 *) & cmd->params.pm_cfg +
2432 + sizeof(HostCmd_DS_POWER_MGMT_EXT));
2433 + while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
2434 + tlv_type = uap_le16_to_cpu(tlvbuf->Type);
2435 + tlv_len = uap_le16_to_cpu(tlvbuf->Len);
2436 + switch (tlv_type) {
2437 + case TLV_TYPE_AP_SLEEP_PARAM:
2438 + sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlvbuf;
2439 + pm_cfg.flags |= PS_FLAG_SLEEP_PARAM;
2440 + pm_cfg.sleep_param.ctrl_bitmap =
2441 + uap_le32_to_cpu(sleep_tlv->ctrl_bitmap);
2442 + pm_cfg.sleep_param.min_sleep =
2443 + uap_le32_to_cpu(sleep_tlv->min_sleep);
2444 + pm_cfg.sleep_param.max_sleep =
2445 + uap_le32_to_cpu(sleep_tlv->max_sleep);
2446 + break;
2447 + case TLV_TYPE_AP_INACT_SLEEP_PARAM:
2448 + inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlvbuf;
2449 + pm_cfg.flags |= PS_FLAG_INACT_SLEEP_PARAM;
2450 + pm_cfg.inact_param.inactivity_to =
2451 + uap_le32_to_cpu(inact_tlv->inactivity_to);
2452 + pm_cfg.inact_param.min_awake =
2453 + uap_le32_to_cpu(inact_tlv->min_awake);
2454 + pm_cfg.inact_param.max_awake =
2455 + uap_le32_to_cpu(inact_tlv->max_awake);
2456 + break;
2457 + }
2458 + tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
2459 + tlvbuf =
2460 + (MrvlIEtypesHeader_t *) ((u8 *) tlvbuf + tlv_len +
2461 + sizeof(MrvlIEtypesHeader_t));
2462 + }
2463 + /* Copy to user */
2464 + if (copy_to_user(req->ifr_data, &pm_cfg, sizeof(ps_mgmt))) {
2465 + PRINTM(ERROR, "Copy to user failed!\n");
2466 + LEAVE();
2467 + return -EFAULT;
2468 + }
2469 + }
2470 + done:
2471 + LEAVE();
2472 + return ret;
2473 +}
2474 +
2475 +/**
2476 + * @brief This function send bss_stop command to firmware
2477 + *
2478 + * @param priv A pointer to uap_private structure
2479 + * @return UAP_STATUS_SUCCESS on success, otherwise failure code
2480 + */
2481 +static int
2482 +uap_bss_stop(uap_private * priv)
2483 +{
2484 + int ret = UAP_STATUS_SUCCESS;
2485 + u32 CmdSize;
2486 + HostCmd_DS_GEN *cmd;
2487 + uap_adapter *Adapter = priv->adapter;
2488 + struct sk_buff *skb;
2489 + ENTER();
2490 + if (Adapter->HardwareStatus != HWReady) {
2491 + PRINTM(ERROR, "uap_bss_stop:Hardware is not ready!\n");
2492 + ret = -EFAULT;
2493 + goto done;
2494 + }
2495 + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
2496 + if (!skb) {
2497 + PRINTM(ERROR, "No free skb\n");
2498 + ret = -ENOMEM;
2499 + goto done;
2500 + }
2501 + CmdSize = sizeof(HostCmd_DS_GEN);
2502 + cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
2503 + cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_BSS_STOP);
2504 + cmd->Size = uap_cpu_to_le16(CmdSize);
2505 + skb_put(skb, CmdSize + INTF_HEADER_LEN);
2506 + PRINTM(CMND, "APCMD_BSS_STOP\n");
2507 + if (UAP_STATUS_SUCCESS !=
2508 + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
2509 + PRINTM(ERROR, "Fail to process cmd BSS_STOP\n");
2510 + ret = -EFAULT;
2511 + goto done;
2512 + }
2513 + done:
2514 + LEAVE();
2515 + return ret;
2516 +}
2517 +
2518 +/********************************************************
2519 + Global Functions
2520 +********************************************************/
2521 +/**
2522 + * @brief This function send soft_reset command to firmware
2523 + *
2524 + * @param priv A pointer to uap_private structure
2525 + * @return UAP_STATUS_SUCCESS on success, otherwise failure code
2526 + */
2527 +int
2528 +uap_soft_reset(uap_private * priv)
2529 +{
2530 + int ret = UAP_STATUS_SUCCESS;
2531 + u32 CmdSize;
2532 + HostCmd_DS_GEN *cmd;
2533 + uap_adapter *Adapter = priv->adapter;
2534 + struct sk_buff *skb;
2535 + ENTER();
2536 + ret = uap_bss_stop(priv);
2537 + if (ret != UAP_STATUS_SUCCESS)
2538 + goto done;
2539 + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
2540 + if (!skb) {
2541 + PRINTM(ERROR, "No free skb\n");
2542 + ret = -ENOMEM;
2543 + goto done;
2544 + }
2545 + CmdSize = sizeof(HostCmd_DS_GEN);
2546 + cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
2547 + cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SOFT_RESET);
2548 + cmd->Size = uap_cpu_to_le16(CmdSize);
2549 + skb_put(skb, CmdSize + INTF_HEADER_LEN);
2550 + PRINTM(CMND, "APCMD_SOFT_RESET\n");
2551 + if (UAP_STATUS_SUCCESS !=
2552 + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORSEND)) {
2553 + PRINTM(ERROR, "Fail to process cmd SOFT_RESET\n");
2554 + ret = -EFAULT;
2555 + goto done;
2556 + }
2557 + Adapter->SurpriseRemoved = TRUE;
2558 + /* delay to allow hardware complete reset */
2559 + os_sched_timeout(5);
2560 + if (priv->MediaConnected == TRUE) {
2561 + os_stop_queue(priv);
2562 + os_carrier_off(priv);
2563 + priv->MediaConnected = FALSE;
2564 + }
2565 + Adapter->CmdSize = 0;
2566 + Adapter->CmdWaitQWoken = TRUE;
2567 + wake_up_interruptible(&Adapter->cmdwait_q);
2568 + skb_queue_purge(&priv->adapter->tx_queue);
2569 + skb_queue_purge(&priv->adapter->cmd_queue);
2570 + done:
2571 + LEAVE();
2572 + return ret;
2573 +}
2574 +
2575 +/**
2576 + * @brief This function processes received packet and forwards it
2577 + * to kernel/upper layer
2578 + *
2579 + * @param priv A pointer to uap_private
2580 + * @param skb A pointer to skb which includes the received packet
2581 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
2582 + */
2583 +int
2584 +uap_process_rx_packet(uap_private * priv, struct sk_buff *skb)
2585 +{
2586 + int ret = UAP_STATUS_SUCCESS;
2587 + RxPD *pRxPD;
2588 + ENTER();
2589 + priv->adapter->ps_state = PS_STATE_AWAKE;
2590 + pRxPD = (RxPD *) skb->data;
2591 + endian_convert_RxPD(pRxPD);
2592 + DBG_HEXDUMP(DAT_D, "Rx", skb->data, MIN(skb->len, DATA_DUMP_LEN));
2593 + skb_pull(skb, pRxPD->RxPktOffset);
2594 + priv->stats.rx_packets++;
2595 + priv->stats.rx_bytes += skb->len;
2596 + os_upload_rx_packet(priv, skb);
2597 + LEAVE();
2598 + return ret;
2599 +}
2600 +
2601 +/**
2602 + * @brief This function opens the network device
2603 + *
2604 + * @param dev A pointer to net_device structure
2605 + * @return UAP_STATUS_SUCCESS
2606 + */
2607 +static int
2608 +uap_open(struct net_device *dev)
2609 +{
2610 + uap_private *priv = (uap_private *) (uap_private *) netdev_priv(dev);
2611 + uap_adapter *Adapter = priv->adapter;
2612 + int i = 0;
2613 +
2614 + ENTER();
2615 +
2616 + /* On some systems the device open handler will be called before HW ready. */
2617 + /* Use the following flag check and wait function to work around the issue. */
2618 + while ((Adapter->HardwareStatus != HWReady) &&
2619 + (i < MAX_WAIT_DEVICE_READY_COUNT)) {
2620 + i++;
2621 + os_sched_timeout(100);
2622 + }
2623 + if (i >= MAX_WAIT_DEVICE_READY_COUNT) {
2624 + PRINTM(FATAL, "HW not ready, uap_open() return failure\n");
2625 + LEAVE();
2626 + return UAP_STATUS_FAILURE;
2627 + }
2628 +
2629 + if (MODULE_GET == 0)
2630 + return UAP_STATUS_FAILURE;
2631 +
2632 + priv->open = TRUE;
2633 + if (priv->MediaConnected == TRUE) {
2634 + os_carrier_on(priv);
2635 + os_start_queue(priv);
2636 + } else {
2637 + os_stop_queue(priv);
2638 + os_carrier_off(priv);
2639 + }
2640 + LEAVE();
2641 + return UAP_STATUS_SUCCESS;
2642 +}
2643 +
2644 +/**
2645 + * @brief This function closes the network device
2646 + *
2647 + * @param dev A pointer to net_device structure
2648 + * @return UAP_STATUS_SUCCESS
2649 + */
2650 +static int
2651 +uap_close(struct net_device *dev)
2652 +{
2653 + uap_private *priv = (uap_private *) netdev_priv(dev);
2654 +
2655 + ENTER();
2656 + skb_queue_purge(&priv->adapter->tx_queue);
2657 + os_stop_queue(priv);
2658 + os_carrier_off(priv);
2659 +
2660 + MODULE_PUT;
2661 + priv->open = FALSE;
2662 + LEAVE();
2663 + return UAP_STATUS_SUCCESS;
2664 +}
2665 +
2666 +/**
2667 + * @brief This function returns the network statistics
2668 + *
2669 + * @param dev A pointer to uap_private structure
2670 + * @return A pointer to net_device_stats structure
2671 + */
2672 +static struct net_device_stats *
2673 +uap_get_stats(struct net_device *dev)
2674 +{
2675 + uap_private *priv = (uap_private *) netdev_priv(dev);
2676 +
2677 + return &priv->stats;
2678 +}
2679 +
2680 +/**
2681 + * @brief This function sets the MAC address to firmware.
2682 + *
2683 + * @param dev A pointer to uap_private structure
2684 + * @param addr MAC address to set
2685 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
2686 + */
2687 +static int
2688 +uap_set_mac_address(struct net_device *dev, void *addr)
2689 +{
2690 + int ret = UAP_STATUS_SUCCESS;
2691 + uap_private *priv = (uap_private *) netdev_priv(dev);
2692 + struct sockaddr *pHwAddr = (struct sockaddr *) addr;
2693 + u32 CmdSize;
2694 + HostCmd_DS_COMMAND *cmd;
2695 + MrvlIEtypes_MacAddr_t *pMacAddrTlv;
2696 + uap_adapter *Adapter = priv->adapter;
2697 + struct sk_buff *skb;
2698 +
2699 + ENTER();
2700 +
2701 + /* Dump MAC address */
2702 + DBG_HEXDUMP(CMD_D, "Original MAC addr", dev->dev_addr, ETH_ALEN);
2703 + DBG_HEXDUMP(CMD_D, "New MAC addr", pHwAddr->sa_data, ETH_ALEN);
2704 + if (priv->open && (priv->MediaConnected == TRUE)) {
2705 + os_carrier_on(priv);
2706 + os_start_queue(priv);
2707 + }
2708 + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
2709 + if (!skb) {
2710 + PRINTM(ERROR, "No free skb\n");
2711 + LEAVE();
2712 + return -ENOMEM;
2713 + }
2714 + CmdSize =
2715 + S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t);
2716 + cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
2717 + cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
2718 + cmd->Size = uap_cpu_to_le16(CmdSize);
2719 + cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_SET);
2720 + pMacAddrTlv =
2721 + (MrvlIEtypes_MacAddr_t *) ((u8 *) cmd + S_DS_GEN +
2722 + sizeof(HostCmd_SYS_CONFIG));
2723 + pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID);
2724 + pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN);
2725 + memcpy(pMacAddrTlv->ApMacAddr, pHwAddr->sa_data, ETH_ALEN);
2726 + skb_put(skb, CmdSize + INTF_HEADER_LEN);
2727 + PRINTM(CMND, "set_mac_address\n");
2728 + if (UAP_STATUS_SUCCESS !=
2729 + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
2730 + PRINTM(ERROR, "Fail to set mac address\n");
2731 + LEAVE();
2732 + return -EFAULT;
2733 + }
2734 + if (!Adapter->CmdSize) {
2735 + PRINTM(ERROR, "Cmd Size is 0\n");
2736 + LEAVE();
2737 + return -EFAULT;
2738 + }
2739 + cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
2740 + cmd->Result = uap_cpu_to_le16(cmd->Result);
2741 + if (cmd->Result != UAP_STATUS_SUCCESS) {
2742 + PRINTM(ERROR, "set mac addrress fail,cmd result=%x\n", cmd->Result);
2743 + ret = -EFAULT;
2744 + } else
2745 + memcpy(dev->dev_addr, pHwAddr->sa_data, ETH_ALEN);
2746 + LEAVE();
2747 + return ret;
2748 +}
2749 +
2750 +/**
2751 + * @brief This function handles the timeout of packet
2752 + * transmission
2753 + *
2754 + * @param dev A pointer to net_device structure
2755 + * @return n/a
2756 + */
2757 +static void
2758 +uap_tx_timeout(struct net_device *dev)
2759 +{
2760 + uap_private *priv = (uap_private *) netdev_priv(dev);
2761 +
2762 + ENTER();
2763 +
2764 + PRINTM(DATA, "Tx timeout\n");
2765 + UpdateTransStart(dev);
2766 + priv->num_tx_timeout++;
2767 + priv->adapter->IntCounter++;
2768 + wake_up_interruptible(&priv->MainThread.waitQ);
2769 +
2770 + LEAVE();
2771 +}
2772 +
2773 +/**
2774 + * @brief This function handles packet transmission
2775 + *
2776 + * @param skb A pointer to sk_buff structure
2777 + * @param dev A pointer to net_device structure
2778 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
2779 + */
2780 +static int
2781 +uap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2782 +{
2783 + uap_private *priv = (uap_private *) netdev_priv(dev);
2784 + int ret = UAP_STATUS_SUCCESS;
2785 +
2786 + ENTER();
2787 + PRINTM(DATA, "Data <= kernel\n");
2788 + DBG_HEXDUMP(DAT_D, "Tx", skb->data, MIN(skb->len, DATA_DUMP_LEN));
2789 + /* skb sanity check */
2790 + if (!skb->len || (skb->len > MRVDRV_MAXIMUM_ETH_PACKET_SIZE)) {
2791 + PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
2792 + MRVDRV_MAXIMUM_ETH_PACKET_SIZE);
2793 + priv->stats.tx_dropped++;
2794 + kfree(skb);
2795 + goto done;
2796 + }
2797 + skb_queue_tail(&priv->adapter->tx_queue, skb);
2798 + wake_up_interruptible(&priv->MainThread.waitQ);
2799 + if (skb_queue_len(&priv->adapter->tx_queue) > TX_HIGH_WATERMARK) {
2800 + UpdateTransStart(dev);
2801 + os_stop_queue(priv);
2802 + }
2803 + done:
2804 + LEAVE();
2805 + return ret;
2806 +}
2807 +
2808 +/**
2809 + * @brief ioctl function - entry point
2810 + *
2811 + * @param dev A pointer to net_device structure
2812 + * @param req A pointer to ifreq structure
2813 + * @param cmd command
2814 + * @return UAP_STATUS_SUCCESS--success, otherwise fail
2815 + */
2816 +static int
2817 +uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
2818 +{
2819 + int ret = UAP_STATUS_SUCCESS;
2820 +
2821 + ENTER();
2822 +
2823 + PRINTM(CMND, "uap_do_ioctl: ioctl cmd = 0x%x\n", cmd);
2824 +
2825 + switch (cmd) {
2826 + case UAPHOSTCMD:
2827 + ret = uap_hostcmd_ioctl(dev, req);
2828 + break;
2829 + case UAP_POWER_MODE:
2830 + ret = uap_power_mode_ioctl(dev, req);
2831 + break;
2832 + default:
2833 + ret = -EINVAL;
2834 + break;
2835 + }
2836 +
2837 + LEAVE();
2838 + return ret;
2839 +}
2840 +
2841 +/**
2842 + * @brief This function handles events generated by firmware
2843 + *
2844 + * @param priv A pointer to uap_private structure
2845 + * @param payload A pointer to payload buffer
2846 + * @param len Length of the payload
2847 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
2848 + */
2849 +int
2850 +uap_process_event(uap_private * priv, u8 * payload, uint len)
2851 +{
2852 + int ret = UAP_STATUS_SUCCESS;
2853 + uap_adapter *Adapter = priv->adapter;
2854 + struct sk_buff *skb = NULL;
2855 + struct nlmsghdr *nlh = NULL;
2856 + struct sock *sk = Adapter->nl_sk;
2857 + AP_Event *pEvent;
2858 +
2859 + ENTER();
2860 + Adapter->ps_state = PS_STATE_AWAKE;
2861 + if (len > NL_MAX_PAYLOAD) {
2862 + PRINTM(ERROR, "event size is too big!!! len=%d\n", len);
2863 + ret = UAP_STATUS_FAILURE;
2864 + goto done;
2865 + }
2866 + pEvent = (AP_Event *) payload;
2867 + PRINTM(CMND, "Event: %d\n", pEvent->EventId);
2868 + switch (pEvent->EventId) {
2869 + case MICRO_AP_EV_ID_BSS_START:
2870 + memcpy(priv->uap_dev.netdev->dev_addr, pEvent->MacAddr, ETH_ALEN);
2871 + DBG_HEXDUMP(CMD_D, "BSS MAC addr", priv->uap_dev.netdev->dev_addr,
2872 + ETH_ALEN);
2873 + break;
2874 + case MICRO_AP_EV_BSS_ACTIVE:
2875 + // carrier on
2876 + priv->MediaConnected = TRUE;
2877 + os_carrier_on(priv);
2878 + os_start_queue(priv);
2879 + break;
2880 + case MICRO_AP_EV_BSS_IDLE:
2881 + os_stop_queue(priv);
2882 + os_carrier_off(priv);
2883 + priv->MediaConnected = FALSE;
2884 + break;
2885 + case EVENT_PS_AWAKE:
2886 + PRINTM(CMND, "UAP: PS_AWAKE\n");
2887 + Adapter->ps_state = PS_STATE_AWAKE;
2888 + Adapter->WakeupTries = 0;
2889 + break;
2890 + case EVENT_PS_SLEEP:
2891 + PRINTM(CMND, "UAP: PS_SLEEP\n");
2892 + Adapter->ps_state = PS_STATE_PRE_SLEEP;
2893 + break;
2894 + default:
2895 + break;
2896 + }
2897 + if ((pEvent->EventId == EVENT_PS_AWAKE) ||
2898 + (pEvent->EventId == EVENT_PS_SLEEP))
2899 + goto done;
2900 + if (sk) {
2901 + /* Allocate skb */
2902 + if (!(skb = alloc_skb(NLMSG_SPACE(NL_MAX_PAYLOAD), GFP_ATOMIC))) {
2903 + PRINTM(ERROR, "Could not allocate skb for netlink.\n");
2904 + ret = UAP_STATUS_FAILURE;
2905 + goto done;
2906 + }
2907 + nlh = (struct nlmsghdr *) skb->data;
2908 + nlh->nlmsg_len = NLMSG_SPACE(len);
2909 +
2910 + /* From kernel */
2911 + nlh->nlmsg_pid = 0;
2912 + nlh->nlmsg_flags = 0;
2913 +
2914 + /* Data */
2915 + skb_put(skb, nlh->nlmsg_len);
2916 + memcpy(NLMSG_DATA(nlh), payload, len);
2917 +
2918 + /* From Kernel */
2919 + NETLINK_CB(skb).portid = 0;
2920 +
2921 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
2922 + /* Multicast message */
2923 + NETLINK_CB(skb).dst_pid = 0;
2924 +#endif
2925 +
2926 + /* Multicast group number */
2927 + NETLINK_CB(skb).dst_group = NL_MULTICAST_GROUP;
2928 +
2929 + /* Send message */
2930 + netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP, GFP_KERNEL);
2931 +
2932 + ret = UAP_STATUS_SUCCESS;
2933 + } else {
2934 + PRINTM(ERROR, "Could not send event through NETLINK. Link down.\n");
2935 + ret = UAP_STATUS_FAILURE;
2936 + }
2937 + done:
2938 + LEAVE();
2939 + return ret;
2940 +}
2941 +
2942 +/**
2943 + * @brief This function handles the interrupt. it will change PS
2944 + * state if applicable. it will wake up main_thread to handle
2945 + * the interrupt event as well.
2946 + *
2947 + * @param priv A pointer to uap_private structure
2948 + * @return n/a
2949 + */
2950 +void
2951 +uap_interrupt(uap_private * priv)
2952 +{
2953 + ENTER();
2954 + priv->adapter->IntCounter++;
2955 + priv->adapter->WakeupTries = 0;
2956 + PRINTM(INFO, "*\n");
2957 + wake_up_interruptible(&priv->MainThread.waitQ);
2958 +
2959 + LEAVE();
2960 +
2961 +}
2962 +
2963 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
2964 +/** Network device handlers */
2965 +static const struct net_device_ops uap_netdev_ops = {
2966 + .ndo_open = uap_open,
2967 + .ndo_start_xmit = uap_hard_start_xmit,
2968 + .ndo_stop = uap_close,
2969 + .ndo_do_ioctl = uap_do_ioctl,
2970 + .ndo_set_mac_address = uap_set_mac_address,
2971 + .ndo_tx_timeout = uap_tx_timeout,
2972 + .ndo_get_stats = uap_get_stats,
2973 +};
2974 +#endif
2975 +
2976 +/**
2977 + * @brief This function adds the card. it will probe the
2978 + * card, allocate the uap_priv and initialize the device.
2979 + *
2980 + * @param card A pointer to card
2981 + * @return A pointer to uap_private structure
2982 + */
2983 +uap_private *
2984 +uap_add_card(void *card)
2985 +{
2986 + struct net_device *dev = NULL;
2987 + uap_private *priv = NULL;
2988 +
2989 + ENTER();
2990 +
2991 + if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
2992 + goto exit_sem_err;
2993 +
2994 + /* Allocate an Ethernet device */
2995 + if (!(dev = alloc_etherdev(sizeof(uap_private)))) {
2996 + PRINTM(FATAL, "Init ethernet device failed!\n");
2997 + goto error;
2998 + }
2999 + priv = (uap_private *) netdev_priv(dev);
3000 +
3001 + /* Allocate name */
3002 + if (dev_alloc_name(dev, "uap%d") < 0) {
3003 + PRINTM(ERROR, "Could not allocate device name!\n");
3004 + goto error;
3005 + }
3006 +
3007 + /* Allocate buffer for uap_adapter */
3008 + if (!(priv->adapter = kmalloc(sizeof(uap_adapter), GFP_KERNEL))) {
3009 + PRINTM(FATAL, "Allocate buffer for uap_adapter failed!\n");
3010 + goto error;
3011 + }
3012 + memset(priv->adapter, 0, sizeof(uap_adapter));
3013 +
3014 + priv->uap_dev.netdev = dev;
3015 + priv->uap_dev.card = card;
3016 + priv->MediaConnected = FALSE;
3017 + uappriv = priv;
3018 + ((struct sdio_mmc_card *) card)->priv = priv;
3019 +
3020 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
3021 + SET_MODULE_OWNER(dev);
3022 +#endif
3023 +
3024 + /* Setup the OS Interface to our functions */
3025 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
3026 + dev->open = uap_open;
3027 + dev->stop = uap_close;
3028 + dev->hard_start_xmit = uap_hard_start_xmit;
3029 + dev->tx_timeout = uap_tx_timeout;
3030 + dev->get_stats = uap_get_stats;
3031 + dev->do_ioctl = uap_do_ioctl;
3032 + dev->set_mac_address = uap_set_mac_address;
3033 + dev->set_multicast_list = uap_set_multicast_list;
3034 +#else
3035 + dev->netdev_ops = &uap_netdev_ops;
3036 +#endif
3037 + dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;
3038 + dev->hard_header_len += sizeof(TxPD) + INTF_HEADER_LEN;
3039 + dev->hard_header_len += HEADER_ALIGNMENT;
3040 +#define NETIF_F_DYNALLOC 16
3041 + dev->features |= NETIF_F_DYNALLOC;
3042 + dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
3043 +
3044 + /* Init SW */
3045 + if (uap_init_sw(priv)) {
3046 + PRINTM(FATAL, "Software Init Failed\n");
3047 + goto error;
3048 + }
3049 +
3050 + PRINTM(INFO, "Starting kthread...\n");
3051 + priv->MainThread.priv = priv;
3052 + spin_lock_init(&priv->driver_lock);
3053 + uap_create_thread(uap_service_main_thread, &priv->MainThread,
3054 + "uap_main_service");
3055 + while (priv->MainThread.pid == 0) {
3056 + os_sched_timeout(2);
3057 + }
3058 +
3059 + /* Register the device */
3060 + if (sbi_register_dev(priv) < 0) {
3061 + PRINTM(FATAL, "Failed to register uap device!\n");
3062 + goto err_registerdev;
3063 + }
3064 +#ifdef FW_DNLD_NEEDED
3065 + SET_NETDEV_DEV(dev, priv->hotplug_device);
3066 +#endif
3067 +
3068 + /* Init FW and HW */
3069 + if (uap_init_fw(priv)) {
3070 + PRINTM(FATAL, "Firmware Init Failed\n");
3071 + goto err_init_fw;
3072 + }
3073 +
3074 + priv->uap_dev.cmd_sent = FALSE;
3075 + priv->uap_dev.data_sent = FALSE;
3076 +
3077 + /* Get mac address from firmware */
3078 + if (uap_get_mac_address(priv)) {
3079 + PRINTM(FATAL, "Fail to get mac address\n");
3080 + goto err_init_fw;
3081 + }
3082 + /* Register network device */
3083 + if (register_netdev(dev)) {
3084 + printk(KERN_ERR "Cannot register network device!\n");
3085 + goto err_init_fw;
3086 + }
3087 +#ifdef CONFIG_PROC_FS
3088 + uap_proc_entry(priv, dev);
3089 + uap_debug_entry(priv, dev);
3090 +#endif /* CPNFIG_PROC_FS */
3091 + OS_REL_SEMAPHORE(&AddRemoveCardSem);
3092 +
3093 + LEAVE();
3094 + return priv;
3095 + err_init_fw:
3096 + sbi_unregister_dev(priv);
3097 + err_registerdev:
3098 + ((struct sdio_mmc_card *) card)->priv = NULL;
3099 + /* Stop the thread servicing the interrupts */
3100 + priv->adapter->SurpriseRemoved = TRUE;
3101 + wake_up_interruptible(&priv->MainThread.waitQ);
3102 + while (priv->MainThread.pid) {
3103 + os_sched_timeout(1);
3104 + }
3105 + error:
3106 + if (dev) {
3107 + if (dev->reg_state == NETREG_REGISTERED)
3108 + unregister_netdev(dev);
3109 + if (priv->adapter)
3110 + uap_free_adapter(priv);
3111 + free_netdev(dev);
3112 + uappriv = NULL;
3113 + }
3114 + OS_REL_SEMAPHORE(&AddRemoveCardSem);
3115 + exit_sem_err:
3116 + LEAVE();
3117 + return NULL;
3118 +}
3119 +
3120 +/**
3121 + * @brief This function removes the card.
3122 + *
3123 + * @param card A pointer to card
3124 + * @return UAP_STATUS_SUCCESS
3125 + */
3126 +int
3127 +uap_remove_card(void *card)
3128 +{
3129 + uap_private *priv = uappriv;
3130 + uap_adapter *Adapter;
3131 + struct net_device *dev;
3132 +
3133 + ENTER();
3134 +
3135 + if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
3136 + goto exit_sem_err;
3137 +
3138 + if (!priv || !(Adapter = priv->adapter)) {
3139 + goto exit_remove;
3140 + }
3141 + Adapter->SurpriseRemoved = TRUE;
3142 + if (Adapter->cmd_pending == TRUE) {
3143 + /* Wake up cmd Q */
3144 + Adapter->CmdWaitQWoken = TRUE;
3145 + wake_up_interruptible(&Adapter->cmdwait_q);
3146 + }
3147 + dev = priv->uap_dev.netdev;
3148 + if (priv->MediaConnected == TRUE) {
3149 + os_stop_queue(priv);
3150 + os_carrier_off(priv);
3151 + priv->MediaConnected = FALSE;
3152 + }
3153 + Adapter->CmdSize = 0;
3154 + Adapter->CmdWaitQWoken = TRUE;
3155 + wake_up_interruptible(&Adapter->cmdwait_q);
3156 + skb_queue_purge(&priv->adapter->tx_queue);
3157 + skb_queue_purge(&priv->adapter->cmd_queue);
3158 +
3159 + /* Disable interrupts on the card */
3160 + sbi_disable_host_int(priv);
3161 + PRINTM(INFO, "netdev_finish_unregister: %s%s.\n", dev->name,
3162 + (dev->features & NETIF_F_DYNALLOC) ? "" : ", old style");
3163 + unregister_netdev(dev);
3164 + PRINTM(INFO, "Unregister finish\n");
3165 + wake_up_interruptible(&priv->MainThread.waitQ);
3166 + while (priv->MainThread.pid) {
3167 + os_sched_timeout(1);
3168 + }
3169 +
3170 + if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) {
3171 + sock_release((Adapter->nl_sk)->sk_socket);
3172 + Adapter->nl_sk = NULL;
3173 + }
3174 +#ifdef CONFIG_PROC_FS
3175 + uap_debug_remove(priv);
3176 + uap_proc_remove(priv);
3177 +#endif
3178 + sbi_unregister_dev(priv);
3179 + PRINTM(INFO, "Free Adapter\n");
3180 + uap_free_adapter(priv);
3181 + priv->uap_dev.netdev = NULL;
3182 + free_netdev(dev);
3183 + uappriv = NULL;
3184 +
3185 + exit_remove:
3186 + OS_REL_SEMAPHORE(&AddRemoveCardSem);
3187 + exit_sem_err:
3188 + LEAVE();
3189 + return UAP_STATUS_SUCCESS;
3190 +}
3191 +
3192 +/**
3193 + * @brief This function initializes module.
3194 + *
3195 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3196 + */
3197 +static int __init
3198 +uap_init_module(void)
3199 +{
3200 + int ret = UAP_STATUS_SUCCESS;
3201 + ENTER();
3202 +
3203 + OS_INIT_SEMAPHORE(&AddRemoveCardSem);
3204 + ret = sbi_register();
3205 + LEAVE();
3206 + return ret;
3207 +}
3208 +
3209 +/**
3210 + * @brief This function cleans module
3211 + *
3212 + * @return n/a
3213 + */
3214 +static void __exit
3215 +uap_cleanup_module(void)
3216 +{
3217 + ENTER();
3218 +
3219 + if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
3220 + goto exit_sem_err;
3221 +
3222 + if ((uappriv) && (uappriv->adapter)) {
3223 + uap_func_shutdown(uappriv);
3224 + }
3225 + OS_REL_SEMAPHORE(&AddRemoveCardSem);
3226 + exit_sem_err:
3227 + sbi_unregister();
3228 + LEAVE();
3229 +}
3230 +
3231 +module_init(uap_init_module);
3232 +module_exit(uap_cleanup_module);
3233 +module_param(helper_name, charp, 0);
3234 +MODULE_PARM_DESC(helper_name, "Helper name");
3235 +module_param(fw_name, charp, 0);
3236 +MODULE_PARM_DESC(fw_name, "Firmware name");
3237 +
3238 +MODULE_DESCRIPTION("M-UAP Driver");
3239 +MODULE_AUTHOR("Marvell International Ltd.");
3240 +MODULE_VERSION(DRIVER_VERSION);
3241 +MODULE_LICENSE("GPL");
3242 diff --git a/drivers/net/wireless/libertas_uap/uap_proc.c b/drivers/net/wireless/libertas_uap/uap_proc.c
3243 new file mode 100644
3244 index 0000000..d673f56
3245 --- /dev/null
3246 +++ b/drivers/net/wireless/libertas_uap/uap_proc.c
3247 @@ -0,0 +1,258 @@
3248 +/** @file uap_proc.c
3249 + * @brief This file contains functions for proc file.
3250 + *
3251 + * Copyright (C) 2008-2009, Marvell International Ltd.
3252 + *
3253 + * This software file (the "File") is distributed by Marvell International
3254 + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
3255 + * (the "License"). You may use, redistribute and/or modify this File in
3256 + * accordance with the terms and conditions of the License, a copy of which
3257 + * is available along with the File in the gpl.txt file or by writing to
3258 + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
3259 + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
3260 + *
3261 + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
3262 + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
3263 + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
3264 + * this warranty disclaimer.
3265 + *
3266 + */
3267 +#ifdef CONFIG_PROC_FS
3268 +#include <linux/proc_fs.h>
3269 +#include <linux/seq_file.h>
3270 +#include "uap_headers.h"
3271 +
3272 +/** /proc directory root */
3273 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
3274 +#define PROC_DIR NULL
3275 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
3276 +#define PROC_DIR &proc_root
3277 +#else
3278 +#define PROC_DIR proc_net
3279 +#endif
3280 +
3281 +/********************************************************
3282 + Local Variables
3283 +********************************************************/
3284 +
3285 +/********************************************************
3286 + Global Variables
3287 +********************************************************/
3288 +
3289 +/********************************************************
3290 + Local Functions
3291 +********************************************************/
3292 +
3293 +static int uap_info_proc_show(struct seq_file *s, void *data) {
3294 + int i;
3295 + struct net_device *netdev = (struct net_device*)s->private;
3296 + struct netdev_hw_addr *ha;
3297 + uap_private *priv = (uap_private *) netdev_priv(netdev);
3298 +
3299 + seq_printf(s, "driver_name = " "\"uap\"\n");
3300 + seq_printf(s, "driver_version = %s-(FP%s)", DRIVER_VERSION, FPNUM);
3301 + seq_printf(s, "\nInterfaceName=\"%s\"\n", netdev->name);
3302 +
3303 + seq_printf(s, "State=\"%s\"\n",
3304 + ((priv->MediaConnected ==
3305 + FALSE) ? "Disconnected" : "Connected"));
3306 + seq_printf(s, "MACAddress=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
3307 + netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
3308 + netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
3309 + i = 0;
3310 + netdev_for_each_mc_addr(ha, netdev) {
3311 + ++i;
3312 + }
3313 + seq_printf(s, "MCCount=\"%d\"\n", i);
3314 +
3315 + /*
3316 + * Put out the multicast list
3317 + */
3318 + i = 0;
3319 + netdev_for_each_mc_addr(ha, netdev) {
3320 + seq_printf(s,
3321 + "MCAddr[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
3322 + i++,
3323 + ha->addr[0], ha->addr[1],
3324 + ha->addr[2], ha->addr[3],
3325 + ha->addr[4], ha->addr[5]);
3326 + }
3327 +
3328 + seq_printf(s, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
3329 + seq_printf(s, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
3330 + seq_printf(s, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
3331 + seq_printf(s, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
3332 + seq_printf(s, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
3333 + seq_printf(s, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
3334 + seq_printf(s, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
3335 + seq_printf(s, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
3336 + seq_printf(s, "num_tx_timeout = %u\n", priv->num_tx_timeout);
3337 + seq_printf(s, "carrier %s\n",
3338 + ((netif_carrier_ok(priv->uap_dev.netdev)) ? "on" : "off"));
3339 + seq_printf(s, "tx queue %s\n",
3340 + ((netif_queue_stopped(priv->uap_dev.netdev)) ? "stopped" :
3341 + "started"));
3342 +
3343 + return 0;
3344 +}
3345 +
3346 +static int uap_info_proc_open(struct inode *inode, struct file *file) {
3347 + return single_open(file, uap_info_proc_show, PDE_DATA(inode));
3348 +}
3349 +
3350 +static int uap_hwstatus_proc_show(struct seq_file *s, void *data) {
3351 + struct net_device *netdev = (struct net_device*)s->private;
3352 + uap_private *priv = (uap_private *) netdev_priv(netdev);
3353 +
3354 + MODULE_GET;
3355 + seq_printf(s, "%d\n", priv->adapter->HardwareStatus);
3356 + MODULE_PUT;
3357 +
3358 + return 0;
3359 +}
3360 +
3361 +static int uap_hwstatus_proc_open(struct inode *inode, struct file *file) {
3362 + return single_open(file, uap_hwstatus_proc_show, PDE_DATA(inode));
3363 +}
3364 +
3365 +static ssize_t uap_hwstatus_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *data) {
3366 + struct net_device *netdev = (struct net_device *)PDE_DATA(file_inode(file));
3367 + uap_private *priv = (uap_private *) netdev_priv(netdev);
3368 +
3369 + int hwstatus;
3370 + char value[10];
3371 +
3372 + if (count > sizeof(value))
3373 + return count;
3374 +
3375 + if (copy_from_user(&value, buffer, count))
3376 + return -EFAULT;
3377 +
3378 + hwstatus = string_to_number(value);
3379 + switch (hwstatus) {
3380 + case HWReset:
3381 + PRINTM(MSG, "reset hw\n");
3382 + uap_soft_reset(priv);
3383 + priv->adapter->HardwareStatus = HWReset;
3384 + break;
3385 + default:
3386 + break;
3387 + }
3388 +
3389 + MODULE_PUT;
3390 + return count;
3391 +}
3392 +
3393 +static const struct file_operations uap_info_proc_fops = {
3394 + .owner = THIS_MODULE,
3395 + .open = uap_info_proc_open,
3396 + .read = seq_read,
3397 + .llseek = seq_lseek,
3398 + .release = single_release,
3399 +};
3400 +
3401 +static const struct file_operations uap_hwstatus_proc_fops = {
3402 + .owner = THIS_MODULE,
3403 + .open = uap_hwstatus_proc_open,
3404 + .read = seq_read,
3405 + .llseek = seq_lseek,
3406 + .release = single_release,
3407 + .write = uap_hwstatus_proc_write,
3408 +};
3409 +
3410 +/********************************************************
3411 + Global Functions
3412 +********************************************************/
3413 +/**
3414 + * @brief create uap proc file
3415 + *
3416 + * @param priv pointer uap_private
3417 + * @param dev pointer net_device
3418 + * @return N/A
3419 + */
3420 +void
3421 +uap_proc_entry(uap_private * priv, struct net_device *dev)
3422 +{
3423 + PRINTM(INFO, "Creating Proc Interface\n");
3424 + /* Check if uap directory already exists */
3425 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
3426 + struct proc_dir_entry *r = PROC_DIR;
3427 +
3428 + for (r = r->subdir; r; r = r->next) {
3429 + if (r->namelen && !strcmp("uap", r->name)) {
3430 + /* Directory exists */
3431 + PRINTM(WARN, "proc directory already exists!\n");
3432 + priv->proc_uap = r;
3433 + break;
3434 + }
3435 + }
3436 +#endif
3437 + if (!priv->proc_uap) {
3438 + priv->proc_uap = proc_mkdir("uap", PROC_DIR);
3439 + if (!priv->proc_uap)
3440 + return;
3441 + }
3442 + priv->proc_entry = proc_mkdir(dev->name, priv->proc_uap);
3443 +
3444 + if (priv->proc_entry) {
3445 + proc_create_data("info", 0644, priv->proc_entry, &uap_info_proc_fops, dev);
3446 + proc_create_data("hwinfo", 0644, priv->proc_entry, &uap_hwstatus_proc_fops, dev);
3447 + }
3448 +}
3449 +
3450 +/**
3451 + * @brief remove proc file
3452 + *
3453 + * @param priv pointer uap_private
3454 + * @return N/A
3455 + */
3456 +void
3457 +uap_proc_remove(uap_private * priv)
3458 +{
3459 + if (priv->proc_uap) {
3460 + if (priv->proc_entry) {
3461 + remove_proc_entry("info", priv->proc_entry);
3462 + remove_proc_entry("hwstatus", priv->proc_entry);
3463 + }
3464 + remove_proc_entry(priv->uap_dev.netdev->name, priv->proc_uap);
3465 + }
3466 +}
3467 +
3468 +/**
3469 + * @brief convert string to number
3470 + *
3471 + * @param s pointer to numbered string
3472 + * @return converted number from string s
3473 + */
3474 +int
3475 +string_to_number(char *s)
3476 +{
3477 + int r = 0;
3478 + int base = 0;
3479 + int pn = 1;
3480 +
3481 + if (strncmp(s, "-", 1) == 0) {
3482 + pn = -1;
3483 + s++;
3484 + }
3485 + if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) {
3486 + base = 16;
3487 + s += 2;
3488 + } else
3489 + base = 10;
3490 +
3491 + for (s = s; *s != 0; s++) {
3492 + if ((*s >= '0') && (*s <= '9'))
3493 + r = (r * base) + (*s - '0');
3494 + else if ((*s >= 'A') && (*s <= 'F'))
3495 + r = (r * base) + (*s - 'A' + 10);
3496 + else if ((*s >= 'a') && (*s <= 'f'))
3497 + r = (r * base) + (*s - 'a' + 10);
3498 + else
3499 + break;
3500 + }
3501 +
3502 + return (r * pn);
3503 +}
3504 +
3505 +#endif
3506 diff --git a/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c b/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c
3507 new file mode 100644
3508 index 0000000..86f55b5
3509 --- /dev/null
3510 +++ b/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c
3511 @@ -0,0 +1,1428 @@
3512 +/** @file uap_sdio_mmc.c
3513 + * @brief This file contains SDIO IF (interface) module
3514 + * related functions.
3515 + *
3516 + * Copyright (C) 2007-2009, Marvell International Ltd.
3517 + *
3518 + * This software file (the "File") is distributed by Marvell International
3519 + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
3520 + * (the "License"). You may use, redistribute and/or modify this File in
3521 + * accordance with the terms and conditions of the License, a copy of which
3522 + * is available along with the File in the gpl.txt file or by writing to
3523 + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
3524 + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
3525 + *
3526 + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
3527 + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
3528 + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
3529 + * this warranty disclaimer.
3530 + *
3531 + */
3532 +/****************************************************
3533 +Change log:
3534 +****************************************************/
3535 +
3536 +#include "uap_sdio_mmc.h"
3537 +
3538 +#include <linux/firmware.h>
3539 +
3540 +/** define SDIO block size */
3541 +/* We support up to 480-byte block size due to FW buffer limitation. */
3542 +#define SD_BLOCK_SIZE 256
3543 +
3544 +/** define allocated buffer size */
3545 +#define ALLOC_BUF_SIZE (((MAX(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, \
3546 + MRVDRV_SIZE_OF_CMD_BUFFER) + INTF_HEADER_LEN \
3547 + + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE)
3548 +
3549 +/** Max retry number of CMD53 write */
3550 +#define MAX_WRITE_IOMEM_RETRY 2
3551 +
3552 +/********************************************************
3553 + Local Variables
3554 +********************************************************/
3555 +
3556 +/** SDIO Rx unit */
3557 +static u8 sdio_rx_unit = 0;
3558 +
3559 +/**Interrupt status */
3560 +static u8 sd_ireg = 0;
3561 +/********************************************************
3562 + Global Variables
3563 +********************************************************/
3564 +extern u8 *helper_name;
3565 +extern u8 *fw_name;
3566 +/** Default helper name */
3567 +#define DEFAULT_HELPER_NAME "mrvl/helper_sd.bin"
3568 +/** Default firmware name */
3569 +#define DEFAULT_FW_NAME "mrvl/sd8688_ap.bin"
3570 +
3571 +/********************************************************
3572 + Local Functions
3573 +********************************************************/
3574 +/**
3575 + * @brief This function reads the IO register.
3576 + *
3577 + * @param priv A pointer to uap_private structure
3578 + * @param reg register to be read
3579 + * @param dat A pointer to variable that keeps returned value
3580 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3581 + */
3582 +static int
3583 +sbi_read_ioreg(uap_private * priv, u32 reg, u8 * dat)
3584 +{
3585 + struct sdio_mmc_card *card;
3586 + int ret = UAP_STATUS_FAILURE;
3587 +
3588 + ENTER();
3589 +
3590 + card = priv->uap_dev.card;
3591 + if (!card || !card->func) {
3592 + PRINTM(ERROR, "sbi_read_ioreg(): card or function is NULL!\n");
3593 + goto done;
3594 + }
3595 +
3596 + *dat = sdio_readb(card->func, reg, &ret);
3597 + if (ret) {
3598 + PRINTM(ERROR, "sbi_read_ioreg(): sdio_readb failed! ret=%d\n", ret);
3599 + goto done;
3600 + }
3601 +
3602 + PRINTM(INFO, "sbi_read_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv,
3603 + card->func->num, reg, *dat);
3604 +
3605 + done:
3606 + LEAVE();
3607 + return ret;
3608 +}
3609 +
3610 +/**
3611 + * @brief This function writes the IO register.
3612 + *
3613 + * @param priv A pointer to uap_private structure
3614 + * @param reg register to be written
3615 + * @param dat the value to be written
3616 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3617 + */
3618 +static int
3619 +sbi_write_ioreg(uap_private * priv, u32 reg, u8 dat)
3620 +{
3621 + struct sdio_mmc_card *card;
3622 + int ret = UAP_STATUS_FAILURE;
3623 +
3624 + ENTER();
3625 +
3626 + card = priv->uap_dev.card;
3627 + if (!card || !card->func) {
3628 + PRINTM(ERROR, "sbi_write_ioreg(): card or function is NULL!\n");
3629 + goto done;
3630 + }
3631 +
3632 + PRINTM(INFO, "sbi_write_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv,
3633 + card->func->num, reg, dat);
3634 +
3635 + sdio_writeb(card->func, dat, reg, &ret);
3636 + if (ret) {
3637 + PRINTM(ERROR, "sbi_write_ioreg(): sdio_readb failed! ret=%d\n", ret);
3638 + goto done;
3639 + }
3640 +
3641 + done:
3642 + LEAVE();
3643 + return ret;
3644 +}
3645 +
3646 +/**
3647 + * @brief This function get rx_unit value
3648 + *
3649 + * @param priv A pointer to uap_private structure
3650 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3651 + */
3652 +static int
3653 +sd_get_rx_unit(uap_private * priv)
3654 +{
3655 + int ret = UAP_STATUS_SUCCESS;
3656 + u8 reg;
3657 +
3658 + ENTER();
3659 +
3660 + ret = sbi_read_ioreg(priv, CARD_RX_UNIT_REG, &reg);
3661 + if (ret == UAP_STATUS_SUCCESS)
3662 + sdio_rx_unit = reg;
3663 +
3664 + LEAVE();
3665 + return ret;
3666 +}
3667 +
3668 +/**
3669 + * @brief This function reads rx length
3670 + *
3671 + * @param priv A pointer to uap_private structure
3672 + * @param dat A pointer to keep returned data
3673 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3674 + */
3675 +static int
3676 +sd_read_rx_len(uap_private * priv, u16 * dat)
3677 +{
3678 + int ret = UAP_STATUS_SUCCESS;
3679 + u8 reg;
3680 +
3681 + ENTER();
3682 +
3683 + ret = sbi_read_ioreg(priv, CARD_RX_LEN_REG, &reg);
3684 + if (ret == UAP_STATUS_SUCCESS)
3685 + *dat = (u16) reg << sdio_rx_unit;
3686 +
3687 + LEAVE();
3688 + return ret;
3689 +}
3690 +
3691 +/**
3692 + * @brief This function reads fw status registers
3693 + *
3694 + * @param priv A pointer to uap_private structure
3695 + * @param dat A pointer to keep returned data
3696 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3697 + */
3698 +static int
3699 +sd_read_firmware_status(uap_private * priv, u16 * dat)
3700 +{
3701 + int ret = UAP_STATUS_SUCCESS;
3702 + u8 fws0;
3703 + u8 fws1;
3704 +
3705 + ENTER();
3706 +
3707 + ret = sbi_read_ioreg(priv, CARD_FW_STATUS0_REG, &fws0);
3708 + if (ret < 0) {
3709 + LEAVE();
3710 + return UAP_STATUS_FAILURE;
3711 + }
3712 +
3713 + ret = sbi_read_ioreg(priv, CARD_FW_STATUS1_REG, &fws1);
3714 + if (ret < 0) {
3715 + LEAVE();
3716 + return UAP_STATUS_FAILURE;
3717 + }
3718 +
3719 + *dat = (((u16) fws1) << 8) | fws0;
3720 +
3721 + LEAVE();
3722 + return UAP_STATUS_SUCCESS;
3723 +}
3724 +
3725 +/**
3726 + * @brief This function polls the card status register.
3727 + *
3728 + * @param priv A pointer to uap_private structure
3729 + * @param bits the bit mask
3730 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3731 + */
3732 +static int
3733 +mv_sdio_poll_card_status(uap_private * priv, u8 bits)
3734 +{
3735 + int tries;
3736 + u8 cs;
3737 +
3738 + ENTER();
3739 +
3740 + for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
3741 + if (sbi_read_ioreg(priv, CARD_STATUS_REG, &cs) < 0)
3742 + break;
3743 + else if ((cs & bits) == bits) {
3744 + LEAVE();
3745 + return UAP_STATUS_SUCCESS;
3746 + }
3747 + udelay(10);
3748 + }
3749 +
3750 + PRINTM(WARN, "mv_sdio_poll_card_status failed, tries = %d\n", tries);
3751 +
3752 + LEAVE();
3753 + return UAP_STATUS_FAILURE;
3754 +}
3755 +
3756 +/**
3757 + * @brief This function set the sdio bus width.
3758 + *
3759 + * @param priv A pointer to uap_private structure
3760 + * @param mode 1--1 bit mode, 4--4 bit mode
3761 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3762 + */
3763 +#if 0
3764 +static int
3765 +sdio_set_bus_width(uap_private * priv, u8 mode)
3766 +{
3767 + ENTER();
3768 + LEAVE();
3769 + return UAP_STATUS_SUCCESS;
3770 +}
3771 +#endif
3772 +
3773 +/**
3774 + * @brief This function reads data from the card.
3775 + *
3776 + * @param priv A pointer to uap_private structure
3777 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3778 + */
3779 +static int
3780 +sd_card_to_host(uap_private * priv)
3781 +{
3782 + int ret = UAP_STATUS_SUCCESS;
3783 + u16 buf_len = 0;
3784 + int buf_block_len;
3785 + int blksz;
3786 + struct sk_buff *skb = NULL;
3787 + u16 type;
3788 + u8 *payload = NULL;
3789 + struct sdio_mmc_card *card = priv->uap_dev.card;
3790 +
3791 + ENTER();
3792 +
3793 + if (!card || !card->func) {
3794 + PRINTM(ERROR, "card or function is NULL!\n");
3795 + ret = UAP_STATUS_FAILURE;
3796 + goto exit;
3797 + }
3798 +
3799 + /* Read the length of data to be transferred */
3800 + ret = sd_read_rx_len(priv, &buf_len);
3801 + if (ret < 0) {
3802 + PRINTM(ERROR, "card_to_host, read scratch reg failed\n");
3803 + ret = UAP_STATUS_FAILURE;
3804 + goto exit;
3805 + }
3806 +
3807 + /* Allocate buffer */
3808 + blksz = SD_BLOCK_SIZE;
3809 + buf_block_len = (buf_len + blksz - 1) / blksz;
3810 + if (buf_len <= INTF_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
3811 + PRINTM(ERROR, "card_to_host, invalid packet length: %d\n", buf_len);
3812 + ret = UAP_STATUS_FAILURE;
3813 + goto exit;
3814 + }
3815 +#ifdef PXA3XX_DMA_ALIGN
3816 + skb = dev_alloc_skb(buf_block_len * blksz + PXA3XX_DMA_ALIGNMENT);
3817 +#else
3818 + skb = dev_alloc_skb(buf_block_len * blksz);
3819 +#endif
3820 + if (skb == NULL) {
3821 + PRINTM(WARN, "No free skb\n");
3822 + goto exit;
3823 + }
3824 +#ifdef PXA3XX_DMA_ALIGN
3825 + if ((u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)) {
3826 + skb_put(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
3827 + skb_pull(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
3828 + }
3829 +#endif /* PXA3XX_DMA_ALIGN */
3830 +
3831 + payload = skb->tail;
3832 + ret = sdio_readsb(card->func, payload, priv->uap_dev.ioport,
3833 + buf_block_len * blksz);
3834 + if (ret < 0) {
3835 + PRINTM(ERROR, "card_to_host, read iomem failed: %d\n", ret);
3836 + ret = UAP_STATUS_FAILURE;
3837 + goto exit;
3838 + }
3839 + HEXDUMP("SDIO Blk Rd", payload, blksz * buf_block_len);
3840 + /*
3841 + * This is SDIO specific header
3842 + * u16 length,
3843 + * u16 type (MV_TYPE_DAT = 0, MV_TYPE_CMD = 1, MV_TYPE_EVENT = 3)
3844 + */
3845 + buf_len = uap_le16_to_cpu(*(u16 *) & payload[0]);
3846 + type = uap_le16_to_cpu(*(u16 *) & payload[2]);
3847 + switch (type) {
3848 + case MV_TYPE_EVENT:
3849 + skb_put(skb, buf_len);
3850 + skb_pull(skb, INTF_HEADER_LEN);
3851 + uap_process_event(priv, skb->data, skb->len);
3852 + kfree_skb(skb);
3853 + skb = NULL;
3854 + break;
3855 + case MV_TYPE_CMD:
3856 + skb_put(skb, buf_len);
3857 + skb_pull(skb, INTF_HEADER_LEN);
3858 + priv->adapter->cmd_pending = FALSE;
3859 + if (priv->adapter->cmd_wait_option ==
3860 + HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM) {
3861 + priv->adapter->cmd_wait_option = FALSE;
3862 + uap_process_sleep_confirm_resp(priv, skb->data, skb->len);
3863 + } else if (priv->adapter->cmd_wait_option) {
3864 + memcpy(priv->adapter->CmdBuf, skb->data, skb->len);
3865 + priv->adapter->CmdSize = skb->len;
3866 + priv->adapter->cmd_wait_option = FALSE;
3867 + priv->adapter->CmdWaitQWoken = TRUE;
3868 + wake_up_interruptible(&priv->adapter->cmdwait_q);
3869 + }
3870 + kfree_skb(skb);
3871 + skb = NULL;
3872 + break;
3873 + case MV_TYPE_DAT:
3874 + skb_put(skb, buf_len);
3875 + skb_pull(skb, INTF_HEADER_LEN);
3876 + uap_process_rx_packet(priv, skb);
3877 + break;
3878 + default:
3879 + priv->stats.rx_errors++;
3880 + priv->stats.rx_dropped++;
3881 + /* Driver specified event and command resp should be handle here */
3882 + PRINTM(INFO, "Unknown PKT type:%d\n", type);
3883 + kfree_skb(skb);
3884 + skb = NULL;
3885 + break;
3886 + }
3887 + exit:
3888 + if (ret) {
3889 + if (skb)
3890 + kfree_skb(skb);
3891 + }
3892 +
3893 + LEAVE();
3894 + return ret;
3895 +}
3896 +
3897 +/**
3898 + * @brief This function enables the host interrupts mask
3899 + *
3900 + * @param priv A pointer to uap_private structure
3901 + * @param mask the interrupt mask
3902 + * @return UAP_STATUS_SUCCESS
3903 + */
3904 +static int
3905 +enable_host_int_mask(uap_private * priv, u8 mask)
3906 +{
3907 + int ret = UAP_STATUS_SUCCESS;
3908 +
3909 + ENTER();
3910 +
3911 + /* Simply write the mask to the register */
3912 + ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, mask);
3913 +
3914 + if (ret) {
3915 + PRINTM(WARN, "Unable to enable the host interrupt!\n");
3916 + ret = UAP_STATUS_FAILURE;
3917 + }
3918 +
3919 + LEAVE();
3920 + return ret;
3921 +}
3922 +
3923 +/** @brief This function disables the host interrupts mask.
3924 + *
3925 + * @param priv A pointer to uap_private structure
3926 + * @param mask the interrupt mask
3927 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3928 + */
3929 +static int
3930 +disable_host_int_mask(uap_private * priv, u8 mask)
3931 +{
3932 + int ret = UAP_STATUS_SUCCESS;
3933 + u8 host_int_mask;
3934 +
3935 + ENTER();
3936 +
3937 + /* Read back the host_int_mask register */
3938 + ret = sbi_read_ioreg(priv, HOST_INT_MASK_REG, &host_int_mask);
3939 + if (ret) {
3940 + ret = UAP_STATUS_FAILURE;
3941 + goto done;
3942 + }
3943 +
3944 + /* Update with the mask and write back to the register */
3945 + host_int_mask &= ~mask;
3946 + ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, host_int_mask);
3947 + if (ret < 0) {
3948 + PRINTM(WARN, "Unable to diable the host interrupt!\n");
3949 + ret = UAP_STATUS_FAILURE;
3950 + goto done;
3951 + }
3952 +
3953 + done:
3954 + LEAVE();
3955 + return ret;
3956 +}
3957 +
3958 +/********************************************************
3959 + Global Functions
3960 +********************************************************/
3961 +
3962 +/**
3963 + * @brief This function handles the interrupt.
3964 + *
3965 + * @param func A pointer to sdio_func structure.
3966 + * @return n/a
3967 + */
3968 +static void
3969 +sbi_interrupt(struct sdio_func *func)
3970 +{
3971 + struct sdio_mmc_card *card;
3972 + uap_private *priv;
3973 + u8 ireg = 0;
3974 + int ret = UAP_STATUS_SUCCESS;
3975 +
3976 + ENTER();
3977 +
3978 + card = sdio_get_drvdata(func);
3979 + if (!card || !card->priv) {
3980 + PRINTM(MSG, "%s: sbi_interrupt(%p) card or priv is NULL, card=%p\n",
3981 + __FUNCTION__, func, card);
3982 + LEAVE();
3983 + return;
3984 + }
3985 + priv = card->priv;
3986 +#ifdef FW_WAKEUP_TIME
3987 + if ((priv->adapter->wt_pwrup_sending != 0L) &&
3988 + (priv->adapter->wt_int == 0L))
3989 + priv->adapter->wt_int = get_utimeofday();
3990 +#endif
3991 +
3992 + ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
3993 + if (ret) {
3994 + PRINTM(WARN, "sdio_read_ioreg: read int status register failed\n");
3995 + goto done;
3996 + }
3997 + if (ireg != 0) {
3998 + /*
3999 + * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
4000 + * Clear the interrupt status register and re-enable the interrupt
4001 + */
4002 + PRINTM(INFO, "sdio_ireg = 0x%x\n", ireg);
4003 + sdio_writeb(card->func,
4004 + ~(ireg) & (DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS),
4005 + HOST_INTSTATUS_REG, &ret);
4006 + if (ret) {
4007 + PRINTM(WARN,
4008 + "sdio_write_ioreg: clear int status register failed\n");
4009 + goto done;
4010 + }
4011 + }
4012 + OS_INT_DISABLE;
4013 + sd_ireg |= ireg;
4014 + OS_INT_RESTORE;
4015 +
4016 + uap_interrupt(priv);
4017 + done:
4018 + LEAVE();
4019 +}
4020 +
4021 +/**
4022 + * @brief This function probe the card
4023 + *
4024 + * @param func A pointer to sdio_func structure
4025 + * @param id A pointer to structure sd_device_id
4026 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4027 + */
4028 +static int
4029 +uap_probe(struct sdio_func *func, const struct sdio_device_id *id)
4030 +{
4031 + int ret = UAP_STATUS_FAILURE;
4032 + struct sdio_mmc_card *card = NULL;
4033 +
4034 + ENTER();
4035 +
4036 + PRINTM(MSG, "%s: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
4037 + __FUNCTION__, func->vendor, func->device, func->class, func->num);
4038 +
4039 + card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
4040 + if (!card) {
4041 + ret = -ENOMEM;
4042 + goto done;
4043 + }
4044 +
4045 + card->func = func;
4046 +
4047 + if (!uap_add_card(card)) {
4048 + PRINTM(ERROR, "%s: uap_add_callback failed\n", __FUNCTION__);
4049 + kfree(card);
4050 + ret = UAP_STATUS_FAILURE;
4051 + goto done;
4052 + }
4053 +
4054 + ret = UAP_STATUS_SUCCESS;
4055 +
4056 + done:
4057 + LEAVE();
4058 + return ret;
4059 +}
4060 +
4061 +/**
4062 + * @brief This function removes the card
4063 + *
4064 + * @param func A pointer to sdio_func structure
4065 + * @return N/A
4066 + */
4067 +static void
4068 +uap_remove(struct sdio_func *func)
4069 +{
4070 + struct sdio_mmc_card *card;
4071 +
4072 + ENTER();
4073 +
4074 + if (func) {
4075 + card = sdio_get_drvdata(func);
4076 + if (card) {
4077 + uap_remove_card(card);
4078 + kfree(card);
4079 + }
4080 + }
4081 +
4082 + LEAVE();
4083 +}
4084 +
4085 +#ifdef CONFIG_PM
4086 +/**
4087 + * @brief This function handles client driver suspend
4088 + *
4089 + * @param func A pointer to sdio_func structure
4090 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4091 + */
4092 +int
4093 +uap_suspend(struct sdio_func *func)
4094 +{
4095 + ENTER();
4096 + LEAVE();
4097 + return 0;
4098 +}
4099 +
4100 +/**
4101 + * @brief This function handles client driver resume
4102 + *
4103 + * @param func A pointer to sdio_func structure
4104 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4105 + */
4106 +int
4107 +uap_resume(struct sdio_func *func)
4108 +{
4109 + ENTER();
4110 + LEAVE();
4111 + return 0;
4112 +}
4113 +#endif
4114 +
4115 +/** Device ID for SD8688 */
4116 +#define SD_DEVICE_ID_8688_UAP 0x9104
4117 +/** UAP IDs */
4118 +static const struct sdio_device_id uap_ids[] = {
4119 + {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SD_DEVICE_ID_8688_UAP)},
4120 + {},
4121 +};
4122 +
4123 +MODULE_DEVICE_TABLE(sdio, uap_ids);
4124 +
4125 +static struct sdio_driver uap_sdio = {
4126 + .name = "uap_sdio",
4127 + .id_table = uap_ids,
4128 + .probe = uap_probe,
4129 + .remove = uap_remove,
4130 +#ifdef CONFIG_PM
4131 +/* .suspend = uap_suspend, */
4132 +/* .resume = uap_resume, */
4133 +#endif
4134 +
4135 +};
4136 +
4137 +/**
4138 + * @brief This function registers the IF module in bus driver.
4139 + *
4140 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4141 + */
4142 +int __init
4143 +sbi_register()
4144 +{
4145 + int ret = UAP_STATUS_SUCCESS;
4146 +
4147 + ENTER();
4148 +
4149 + /* SDIO Driver Registration */
4150 + if (sdio_register_driver(&uap_sdio) != 0) {
4151 + PRINTM(FATAL, "SDIO Driver Registration Failed \n");
4152 + ret = UAP_STATUS_FAILURE;
4153 + }
4154 +
4155 + LEAVE();
4156 + return ret;
4157 +}
4158 +
4159 +/**
4160 + * @brief This function de-registers the IF module in bus driver.
4161 + *
4162 + * @return n/a
4163 + */
4164 +void __exit
4165 +sbi_unregister(void)
4166 +{
4167 + ENTER();
4168 +
4169 + /* SDIO Driver Unregistration */
4170 + sdio_unregister_driver(&uap_sdio);
4171 +
4172 + LEAVE();
4173 +}
4174 +
4175 +/**
4176 + * @brief This function checks the interrupt status and handle it accordingly.
4177 + *
4178 + * @param priv A pointer to uap_private structure
4179 + * @param ireg A pointer to variable that keeps returned value
4180 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4181 + */
4182 +int
4183 +sbi_get_int_status(uap_private * priv, u8 * ireg)
4184 +{
4185 + int ret = UAP_STATUS_SUCCESS;
4186 + u8 sdio_ireg = 0;
4187 + struct sdio_mmc_card *card = priv->uap_dev.card;
4188 +
4189 + ENTER();
4190 +
4191 + *ireg = 0;
4192 + OS_INT_DISABLE;
4193 + sdio_ireg = sd_ireg;
4194 + sd_ireg = 0;
4195 + OS_INT_RESTORE;
4196 +
4197 + sdio_claim_host(card->func);
4198 +
4199 + if (sdio_ireg & DN_LD_HOST_INT_STATUS) { /* tx_done INT */
4200 + if (!priv->uap_dev.cmd_sent) { /* tx_done already received */
4201 + PRINTM(INFO,
4202 + "warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n",
4203 + priv->uap_dev.cmd_sent, sdio_ireg);
4204 + } else {
4205 + priv->uap_dev.cmd_sent = FALSE;
4206 + priv->uap_dev.data_sent = FALSE;
4207 + if ( (priv->uap_dev.netdev->reg_state == NETREG_REGISTERED) && (skb_queue_len(&priv->adapter->tx_queue) < TX_LOW_WATERMARK)) {
4208 + os_start_queue(priv);
4209 + }
4210 + }
4211 + }
4212 + if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
4213 + sd_card_to_host(priv);
4214 + }
4215 +
4216 + *ireg = sdio_ireg;
4217 + ret = UAP_STATUS_SUCCESS;
4218 + sdio_release_host(card->func);
4219 +
4220 + LEAVE();
4221 + return ret;
4222 +}
4223 +
4224 +/**
4225 + * @brief This function disables the host interrupts.
4226 + *
4227 + * @param priv A pointer to uap_private structure
4228 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4229 + */
4230 +int
4231 +sbi_disable_host_int(uap_private * priv)
4232 +{
4233 + struct sdio_mmc_card *card = priv->uap_dev.card;
4234 + int ret;
4235 +
4236 + ENTER();
4237 +
4238 + sdio_claim_host(card->func);
4239 + ret = disable_host_int_mask(priv, HIM_DISABLE);
4240 + sdio_release_host(card->func);
4241 +
4242 + LEAVE();
4243 + return ret;
4244 +}
4245 +
4246 +/**
4247 + * @brief This function enables the host interrupts.
4248 + *
4249 + * @param priv A pointer to uap_private structure
4250 + * @return UAP_STATUS_SUCCESS
4251 + */
4252 +int
4253 +sbi_enable_host_int(uap_private * priv)
4254 +{
4255 + struct sdio_mmc_card *card = priv->uap_dev.card;
4256 + int ret;
4257 +
4258 + ENTER();
4259 +
4260 + sdio_claim_host(card->func);
4261 + ret = enable_host_int_mask(priv, HIM_ENABLE);
4262 + sdio_release_host(card->func);
4263 +
4264 + LEAVE();
4265 + return ret;
4266 +}
4267 +
4268 +/**
4269 + * @brief This function de-registers the device.
4270 + *
4271 + * @param priv A pointer to uap_private structure
4272 + * @return UAP_STATUS_SUCCESS
4273 + */
4274 +int
4275 +sbi_unregister_dev(uap_private * priv)
4276 +{
4277 + struct sdio_mmc_card *card = priv->uap_dev.card;
4278 +
4279 + ENTER();
4280 +
4281 + if (!card || !card->func) {
4282 + PRINTM(ERROR, "Error: card or function is NULL!\n");
4283 + goto done;
4284 + }
4285 +
4286 + sdio_claim_host(card->func);
4287 + sdio_release_irq(card->func);
4288 + sdio_disable_func(card->func);
4289 + sdio_release_host(card->func);
4290 +
4291 + sdio_set_drvdata(card->func, NULL);
4292 +
4293 + done:
4294 + LEAVE();
4295 + return UAP_STATUS_SUCCESS;
4296 +}
4297 +
4298 +/**
4299 + * @brief This function registers the device.
4300 + *
4301 + * @param priv A pointer to uap_private structure
4302 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4303 + */
4304 +int
4305 +sbi_register_dev(uap_private * priv)
4306 +{
4307 + int ret = UAP_STATUS_FAILURE;
4308 + u8 reg;
4309 + struct sdio_mmc_card *card = priv->uap_dev.card;
4310 + struct sdio_func *func;
4311 +
4312 + ENTER();
4313 +
4314 + if (!card || !card->func) {
4315 + PRINTM(ERROR, "Error: card or function is NULL!\n");
4316 + goto done;
4317 + }
4318 +
4319 + func = card->func;
4320 +
4321 + /* Initialize the private structure */
4322 + priv->uap_dev.ioport = 0;
4323 +
4324 + sdio_claim_host(func);
4325 +
4326 + ret = sdio_enable_func(func);
4327 + if (ret) {
4328 + PRINTM(FATAL, "sdio_enable_func() failed: ret=%d\n", ret);
4329 + goto release_host;
4330 + }
4331 +
4332 + ret = sdio_claim_irq(func, sbi_interrupt);
4333 + if (ret) {
4334 + PRINTM(FATAL, "sdio_claim_irq failed: ret=%d\n", ret);
4335 + goto disable_func;
4336 + }
4337 +
4338 + /* Read the IO port */
4339 + ret = sbi_read_ioreg(priv, IO_PORT_0_REG, &reg);
4340 + if (ret)
4341 + goto release_irq;
4342 + else
4343 + priv->uap_dev.ioport |= reg;
4344 +
4345 + ret = sbi_read_ioreg(priv, IO_PORT_1_REG, &reg);
4346 + if (ret)
4347 + goto release_irq;
4348 + else
4349 + priv->uap_dev.ioport |= (reg << 8);
4350 +
4351 + ret = sbi_read_ioreg(priv, IO_PORT_2_REG, &reg);
4352 + if (ret)
4353 + goto release_irq;
4354 + else
4355 + priv->uap_dev.ioport |= (reg << 16);
4356 +
4357 + PRINTM(INFO, "SDIO FUNC #%d IO port: 0x%x\n", func->num,
4358 + priv->uap_dev.ioport);
4359 +
4360 + ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
4361 + if (ret) {
4362 + PRINTM(ERROR, "%s: cannot set SDIO block size\n", __FUNCTION__);
4363 + ret = UAP_STATUS_FAILURE;
4364 + goto release_irq;
4365 + }
4366 + priv->hotplug_device = &func->dev;
4367 +
4368 + if (helper_name == NULL) {
4369 + helper_name = DEFAULT_HELPER_NAME;
4370 + }
4371 + if (fw_name == NULL) {
4372 + fw_name = DEFAULT_FW_NAME;
4373 + }
4374 + sdio_release_host(func);
4375 +
4376 + sdio_set_drvdata(func, card);
4377 +
4378 + ret = UAP_STATUS_SUCCESS;
4379 + goto done;
4380 +
4381 + release_irq:
4382 + sdio_release_irq(func);
4383 + disable_func:
4384 + sdio_disable_func(func);
4385 + release_host:
4386 + sdio_release_host(func);
4387 +
4388 + done:
4389 + LEAVE();
4390 + return ret;
4391 +}
4392 +
4393 +/**
4394 + * @brief This function sends data to the card.
4395 + *
4396 + * @param priv A pointer to uap_private structure
4397 + * @param payload A pointer to the data/cmd buffer
4398 + * @param nb the length of data/cmd
4399 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4400 + */
4401 +int
4402 +sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb)
4403 +{
4404 + struct sdio_mmc_card *card = priv->uap_dev.card;
4405 + int ret = UAP_STATUS_SUCCESS;
4406 + int buf_block_len;
4407 + int blksz;
4408 + int i = 0;
4409 + u8 *buf = NULL;
4410 +#ifdef PXA3XX_DMA_ALIGN
4411 + void *tmpbuf = NULL;
4412 + int tmpbufsz;
4413 +#endif
4414 +
4415 + ENTER();
4416 +
4417 + if (!card || !card->func) {
4418 + PRINTM(ERROR, "card or function is NULL!\n");
4419 + LEAVE();
4420 + return UAP_STATUS_FAILURE;
4421 + }
4422 + buf = payload;
4423 +#ifdef PXA3XX_DMA_ALIGN
4424 + if ((u32) payload & (PXA3XX_DMA_ALIGNMENT - 1)) {
4425 + tmpbufsz = ALIGN_SZ(nb, PXA3XX_DMA_ALIGNMENT);
4426 + tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL);
4427 + memset(tmpbuf, 0, tmpbufsz);
4428 + /* Ensure 8-byte aligned CMD buffer */
4429 + buf = (u8 *) ALIGN_ADDR(tmpbuf, PXA3XX_DMA_ALIGNMENT);
4430 + memcpy(buf, payload, nb);
4431 + }
4432 +#endif
4433 + /* Allocate buffer and copy payload */
4434 + blksz = SD_BLOCK_SIZE;
4435 + buf_block_len = (nb + blksz - 1) / blksz;
4436 + sdio_claim_host(card->func);
4437 +#define MAX_WRITE_IOMEM_RETRY 2
4438 + priv->uap_dev.cmd_sent = TRUE;
4439 + priv->uap_dev.data_sent = TRUE;
4440 + do {
4441 + /* Transfer data to card */
4442 + ret = sdio_writesb(card->func, priv->uap_dev.ioport, buf,
4443 + buf_block_len * blksz);
4444 + if (ret < 0) {
4445 + i++;
4446 + PRINTM(ERROR, "host_to_card, write iomem (%d) failed: %d\n", i,
4447 + ret);
4448 + ret = UAP_STATUS_FAILURE;
4449 + if (i > MAX_WRITE_IOMEM_RETRY)
4450 + goto exit;
4451 + } else {
4452 + HEXDUMP("SDIO Blk Wr", payload, nb);
4453 + }
4454 + } while (ret == UAP_STATUS_FAILURE);
4455 + exit:
4456 + sdio_release_host(card->func);
4457 +#ifdef PXA3XX_DMA_ALIGN
4458 + if (tmpbuf)
4459 + kfree(tmpbuf);
4460 +#endif
4461 + if (ret == UAP_STATUS_FAILURE) {
4462 + priv->uap_dev.cmd_sent = FALSE;
4463 + priv->uap_dev.data_sent = FALSE;
4464 + }
4465 + LEAVE();
4466 + return ret;
4467 +}
4468 +
4469 +/**
4470 + * @brief This function reads CIS information.
4471 + *
4472 + * @param priv A pointer to uap_private structure
4473 + * @param cisinfo A pointer to CIS information output buffer
4474 + * @param cislen A pointer to length of CIS info output buffer
4475 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4476 + */
4477 +#if 0
4478 +static int
4479 +sbi_get_cis_info(uap_private * priv, void *cisinfo, int *cislen)
4480 +{
4481 +#define CIS_PTR (0x8000)
4482 + struct sdio_mmc_card *card = priv->uap_dev.card;
4483 + unsigned int i, cis_ptr = CIS_PTR;
4484 + int ret = UAP_STATUS_FAILURE;
4485 +
4486 + ENTER();
4487 +
4488 + if (!card || !card->func) {
4489 + PRINTM(ERROR, "sbi_get_cis_info(): card or function is NULL!\n");
4490 + goto exit;
4491 + }
4492 +#define MAX_SDIO_CIS_INFO_LEN (256)
4493 + if (!cisinfo || (*cislen < MAX_SDIO_CIS_INFO_LEN)) {
4494 + PRINTM(WARN, "ERROR! get_cis_info: insufficient buffer passed\n");
4495 + goto exit;
4496 + }
4497 +
4498 + *cislen = MAX_SDIO_CIS_INFO_LEN;
4499 +
4500 + sdio_claim_host(card->func);
4501 +
4502 + PRINTM(INFO, "cis_ptr=%#x\n", cis_ptr);
4503 +
4504 + /* Read the Tuple Data */
4505 + for (i = 0; i < *cislen; i++) {
4506 + ((unsigned char *) cisinfo)[i] =
4507 + sdio_readb(card->func, cis_ptr + i, &ret);
4508 + if (ret) {
4509 + PRINTM(WARN, "get_cis_info error: ret=%d\n", ret);
4510 + ret = UAP_STATUS_FAILURE;
4511 + goto done;
4512 + }
4513 + PRINTM(INFO, "cisinfo[%d]=%#x\n", i, ((unsigned char *) cisinfo)[i]);
4514 + }
4515 +
4516 + done:
4517 + sdio_release_host(card->func);
4518 + exit:
4519 + LEAVE();
4520 + return ret;
4521 +}
4522 +#endif
4523 +/**
4524 + * @brief This function downloads helper image to the card.
4525 + *
4526 + * @param priv A pointer to uap_private structure
4527 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4528 + */
4529 +int
4530 +sbi_prog_helper(uap_private * priv)
4531 +{
4532 + struct sdio_mmc_card *card = priv->uap_dev.card;
4533 + u8 *helper = NULL;
4534 + int helperlen;
4535 + int ret = UAP_STATUS_SUCCESS;
4536 + void *tmphlprbuf = NULL;
4537 + int tmphlprbufsz;
4538 + u8 *hlprbuf;
4539 + int hlprblknow;
4540 + u32 tx_len;
4541 +#ifdef FW_DOWNLOAD_SPEED
4542 + u32 tv1, tv2;
4543 +#endif
4544 +
4545 + ENTER();
4546 +
4547 + if (!card || !card->func) {
4548 + PRINTM(ERROR, "sbi_prog_helper(): card or function is NULL!\n");
4549 + goto done;
4550 + }
4551 +
4552 + if (priv->fw_helper) {
4553 + helper = (u8 *) priv->fw_helper->data;
4554 + helperlen = priv->fw_helper->size;
4555 + } else {
4556 + PRINTM(MSG, "No helper image found! Terminating download.\n");
4557 + LEAVE();
4558 + return UAP_STATUS_FAILURE;
4559 + }
4560 +
4561 + PRINTM(INFO, "Downloading helper image (%d bytes), block size %d bytes\n",
4562 + helperlen, SD_BLOCK_SIZE);
4563 +
4564 +#ifdef FW_DOWNLOAD_SPEED
4565 + tv1 = get_utimeofday();
4566 +#endif
4567 +
4568 +#ifdef PXA3XX_DMA_ALIGN
4569 + tmphlprbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT);
4570 +#else /* !PXA3XX_DMA_ALIGN */
4571 + tmphlprbufsz = UAP_UPLD_SIZE;
4572 +#endif /* !PXA3XX_DMA_ALIGN */
4573 + tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL);
4574 + if (!tmphlprbuf) {
4575 + PRINTM(ERROR,
4576 + "Unable to allocate buffer for helper. Terminating download\n");
4577 + ret = UAP_STATUS_FAILURE;
4578 + goto done;
4579 + }
4580 + memset(tmphlprbuf, 0, tmphlprbufsz);
4581 +#ifdef PXA3XX_DMA_ALIGN
4582 + hlprbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, PXA3XX_DMA_ALIGNMENT);
4583 +#else /* !PXA3XX_DMA_ALIGN */
4584 + hlprbuf = (u8 *) tmphlprbuf;
4585 +#endif /* !PXA3XX_DMA_ALIGN */
4586 +
4587 + sdio_claim_host(card->func);
4588 +
4589 + /* Perform helper data transfer */
4590 + tx_len = (FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE) - INTF_HEADER_LEN;
4591 + hlprblknow = 0;
4592 + do {
4593 + /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */
4594 + ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
4595 + if (ret < 0) {
4596 + PRINTM(FATAL, "Helper download poll status timeout @ %d\n",
4597 + hlprblknow);
4598 + goto done;
4599 + }
4600 +
4601 + /* More data? */
4602 + if (hlprblknow >= helperlen)
4603 + break;
4604 +
4605 + /* Set blocksize to transfer - checking for last block */
4606 + if (helperlen - hlprblknow < tx_len)
4607 + tx_len = helperlen - hlprblknow;
4608 +
4609 + /* Set length to the 4-byte header */
4610 + *(u32 *) hlprbuf = uap_cpu_to_le32(tx_len);
4611 +
4612 + /* Copy payload to buffer */
4613 + memcpy(&hlprbuf[INTF_HEADER_LEN], &helper[hlprblknow], tx_len);
4614 +
4615 + PRINTM(INFO, ".");
4616 +
4617 + /* Send data */
4618 + ret = sdio_writesb(card->func, priv->uap_dev.ioport,
4619 + hlprbuf, FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE);
4620 +
4621 + if (ret < 0) {
4622 + PRINTM(FATAL, "IO error during helper download @ %d\n", hlprblknow);
4623 + goto done;
4624 + }
4625 +
4626 + hlprblknow += tx_len;
4627 + } while (TRUE);
4628 +
4629 +#ifdef FW_DOWNLOAD_SPEED
4630 + tv2 = get_utimeofday();
4631 + PRINTM(INFO, "helper: %ld.%03ld.%03ld ", tv1 / 1000000,
4632 + (tv1 % 1000000) / 1000, tv1 % 1000);
4633 + PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, (tv2 % 1000000) / 1000,
4634 + tv2 % 1000);
4635 + tv2 -= tv1;
4636 + PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, (tv2 % 1000000) / 1000,
4637 + tv2 % 1000);
4638 +#endif
4639 +
4640 + /* Write last EOF data */
4641 + PRINTM(INFO, "\nTransferring helper image EOF block\n");
4642 + memset(hlprbuf, 0x0, SD_BLOCK_SIZE);
4643 + ret = sdio_writesb(card->func, priv->uap_dev.ioport,
4644 + hlprbuf, SD_BLOCK_SIZE);
4645 +
4646 + if (ret < 0) {
4647 + PRINTM(FATAL, "IO error in writing helper image EOF block\n");
4648 + goto done;
4649 + }
4650 +
4651 + ret = UAP_STATUS_SUCCESS;
4652 +
4653 + done:
4654 + sdio_release_host(card->func);
4655 + if (tmphlprbuf)
4656 + kfree(tmphlprbuf);
4657 +
4658 + LEAVE();
4659 + return ret;
4660 +}
4661 +
4662 +/**
4663 + * @brief This function downloads firmware image to the card.
4664 + *
4665 + * @param priv A pointer to uap_private structure
4666 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4667 + */
4668 +int
4669 +sbi_prog_fw_w_helper(uap_private * priv)
4670 +{
4671 + struct sdio_mmc_card *card = priv->uap_dev.card;
4672 + u8 *firmware = NULL;
4673 + int firmwarelen;
4674 + u8 base0;
4675 + u8 base1;
4676 + int ret = UAP_STATUS_SUCCESS;
4677 + int offset;
4678 + void *tmpfwbuf = NULL;
4679 + int tmpfwbufsz;
4680 + u8 *fwbuf;
4681 + u16 len;
4682 + int txlen = 0;
4683 + int tx_blocks = 0;
4684 + int i = 0;
4685 + int tries = 0;
4686 +#ifdef FW_DOWNLOAD_SPEED
4687 + u32 tv1, tv2;
4688 +#endif
4689 +
4690 + ENTER();
4691 +
4692 + if (!card || !card->func) {
4693 + PRINTM(ERROR, "sbi_prog_fw_w_helper(): card or function is NULL!\n");
4694 + goto done;
4695 + }
4696 +
4697 + if (priv->firmware) {
4698 + firmware = (u8 *) priv->firmware->data;
4699 + firmwarelen = priv->firmware->size;
4700 + } else {
4701 + PRINTM(MSG, "No firmware image found! Terminating download.\n");
4702 + LEAVE();
4703 + return UAP_STATUS_FAILURE;
4704 + }
4705 +
4706 + PRINTM(INFO, "Downloading FW image (%d bytes)\n", firmwarelen);
4707 +
4708 +#ifdef FW_DOWNLOAD_SPEED
4709 + tv1 = get_utimeofday();
4710 +#endif
4711 +
4712 +#ifdef PXA3XX_DMA_ALIGN
4713 + tmpfwbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT);
4714 +#else /* PXA3XX_DMA_ALIGN */
4715 + tmpfwbufsz = UAP_UPLD_SIZE;
4716 +#endif /* PXA3XX_DMA_ALIGN */
4717 + tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL);
4718 + if (!tmpfwbuf) {
4719 + PRINTM(ERROR,
4720 + "Unable to allocate buffer for firmware. Terminating download.\n");
4721 + ret = UAP_STATUS_FAILURE;
4722 + goto done;
4723 + }
4724 + memset(tmpfwbuf, 0, tmpfwbufsz);
4725 +#ifdef PXA3XX_DMA_ALIGN
4726 + /* Ensure 8-byte aligned firmware buffer */
4727 + fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, PXA3XX_DMA_ALIGNMENT);
4728 +#else /* PXA3XX_DMA_ALIGN */
4729 + fwbuf = (u8 *) tmpfwbuf;
4730 +#endif /* PXA3XX_DMA_ALIGN */
4731 +
4732 + sdio_claim_host(card->func);
4733 +
4734 + /* Perform firmware data transfer */
4735 + offset = 0;
4736 + do {
4737 + /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */
4738 + ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
4739 + if (ret < 0) {
4740 + PRINTM(FATAL, "FW download with helper poll status timeout @ %d\n",
4741 + offset);
4742 + goto done;
4743 + }
4744 +
4745 + /* More data? */
4746 + if (offset >= firmwarelen)
4747 + break;
4748 +
4749 + for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
4750 + if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_0, &base0)) < 0) {
4751 + PRINTM(WARN, "Dev BASE0 register read failed:"
4752 + " base0=0x%04X(%d). Terminating download.\n", base0,
4753 + base0);
4754 + ret = UAP_STATUS_FAILURE;
4755 + goto done;
4756 + }
4757 + if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_1, &base1)) < 0) {
4758 + PRINTM(WARN, "Dev BASE1 register read failed:"
4759 + " base1=0x%04X(%d). Terminating download.\n", base1,
4760 + base1);
4761 + ret = UAP_STATUS_FAILURE;
4762 + goto done;
4763 + }
4764 + len = (((u16) base1) << 8) | base0;
4765 +
4766 + /* For SD8688 wait until the length is not 0, 1 or 2 before
4767 + downloading the first FW block, since BOOT code writes the
4768 + register to indicate the helper/FW download winner, the value
4769 + could be 1 or 2 (Func1 or Func2). */
4770 + if ((len && offset) || (len > 2))
4771 + break;
4772 + udelay(10);
4773 + }
4774 +
4775 + if (len == 0)
4776 + break;
4777 + else if (len > UAP_UPLD_SIZE) {
4778 + PRINTM(FATAL, "FW download failure @ %d, invalid length %d\n",
4779 + offset, len);
4780 + ret = UAP_STATUS_FAILURE;
4781 + goto done;
4782 + }
4783 +
4784 + txlen = len;
4785 +
4786 + if (len & BIT(0)) {
4787 + i++;
4788 + if (i > MAX_WRITE_IOMEM_RETRY) {
4789 + PRINTM(FATAL,
4790 + "FW download failure @ %d, over max retry count\n",
4791 + offset);
4792 + ret = UAP_STATUS_FAILURE;
4793 + goto done;
4794 + }
4795 + PRINTM(ERROR, "FW CRC error indicated by the helper:"
4796 + " len = 0x%04X, txlen = %d\n", len, txlen);
4797 + len &= ~BIT(0);
4798 + /* Setting this to 0 to resend from same offset */
4799 + txlen = 0;
4800 + } else {
4801 + i = 0;
4802 +
4803 + /* Set blocksize to transfer - checking for last block */
4804 + if (firmwarelen - offset < txlen) {
4805 + txlen = firmwarelen - offset;
4806 + }
4807 + PRINTM(INFO, ".");
4808 +
4809 + tx_blocks = (txlen + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE;
4810 +
4811 + /* Copy payload to buffer */
4812 + memcpy(fwbuf, &firmware[offset], txlen);
4813 + }
4814 +
4815 + /* Send data */
4816 + ret = sdio_writesb(card->func, priv->uap_dev.ioport,
4817 + fwbuf, tx_blocks * SD_BLOCK_SIZE);
4818 +
4819 + if (ret < 0) {
4820 + PRINTM(ERROR, "FW download, write iomem (%d) failed @ %d\n", i,
4821 + offset);
4822 + if (sbi_write_ioreg(priv, CONFIGURATION_REG, 0x04) < 0) {
4823 + PRINTM(ERROR, "write ioreg failed (CFG)\n");
4824 + }
4825 + }
4826 +
4827 + offset += txlen;
4828 + } while (TRUE);
4829 +
4830 + PRINTM(INFO, "\nFW download over, size %d bytes\n", offset);
4831 +
4832 + ret = UAP_STATUS_SUCCESS;
4833 + done:
4834 +#ifdef FW_DOWNLOAD_SPEED
4835 + tv2 = get_utimeofday();
4836 + PRINTM(INFO, "FW: %ld.%03ld.%03ld ", tv1 / 1000000,
4837 + (tv1 % 1000000) / 1000, tv1 % 1000);
4838 + PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000,
4839 + (tv2 % 1000000) / 1000, tv2 % 1000);
4840 + tv2 -= tv1;
4841 + PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000,
4842 + (tv2 % 1000000) / 1000, tv2 % 1000);
4843 +#endif
4844 + sdio_release_host(card->func);
4845 + if (tmpfwbuf)
4846 + kfree(tmpfwbuf);
4847 +
4848 + LEAVE();
4849 + return ret;
4850 +}
4851 +
4852 +/**
4853 + * @brief This function checks if the firmware is ready to accept
4854 + * command or not.
4855 + *
4856 + * @param priv A pointer to uap_private structure
4857 + * @param pollnum Poll number
4858 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4859 + */
4860 +int
4861 +sbi_check_fw_status(uap_private * priv, int pollnum)
4862 +{
4863 + struct sdio_mmc_card *card = priv->uap_dev.card;
4864 + int ret = UAP_STATUS_SUCCESS;
4865 + u16 firmwarestat;
4866 + int tries;
4867 +
4868 + ENTER();
4869 +
4870 + sdio_claim_host(card->func);
4871 +
4872 + /* Wait for firmware initialization event */
4873 + for (tries = 0; tries < pollnum; tries++) {
4874 + if ((ret = sd_read_firmware_status(priv, &firmwarestat)) < 0)
4875 + continue;
4876 + if (firmwarestat == FIRMWARE_READY) {
4877 + ret = UAP_STATUS_SUCCESS;
4878 + break;
4879 + } else {
4880 + mdelay(10);
4881 + ret = UAP_STATUS_FAILURE;
4882 + }
4883 + }
4884 +
4885 + if (ret < 0)
4886 + goto done;
4887 +
4888 + ret = UAP_STATUS_SUCCESS;
4889 + sd_get_rx_unit(priv);
4890 +
4891 + done:
4892 + sdio_release_host(card->func);
4893 +
4894 + LEAVE();
4895 + return ret;
4896 +}
4897 +
4898 +/**
4899 + * @brief This function set bus clock on/off
4900 + *
4901 + * @param priv A pointer to uap_private structure
4902 + * @param option TRUE--on , FALSE--off
4903 + * @return UAP_STATUS_SUCCESS
4904 + */
4905 +#if 0
4906 +static int
4907 +sbi_set_bus_clock(uap_private * priv, u8 option)
4908 +{
4909 + ENTER();
4910 + LEAVE();
4911 + return UAP_STATUS_SUCCESS;
4912 +}
4913 +#endif
4914 +
4915 +/**
4916 + * @brief This function wakeup firmware
4917 + *
4918 + * @param priv A pointer to uap_private structure
4919 + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4920 + */
4921 +int
4922 +sbi_wakeup_firmware(uap_private * priv)
4923 +{
4924 + struct sdio_mmc_card *card = priv->uap_dev.card;
4925 + int ret = UAP_STATUS_SUCCESS;
4926 +
4927 + ENTER();
4928 +
4929 + if (!card || !card->func) {
4930 + PRINTM(ERROR, "card or function is NULL!\n");
4931 + LEAVE();
4932 + return UAP_STATUS_FAILURE;
4933 + }
4934 + sdio_claim_host(card->func);
4935 + sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
4936 + sdio_release_host(card->func);
4937 + LEAVE();
4938 + return ret;
4939 +}
4940 diff --git a/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h b/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h
4941 new file mode 100644
4942 index 0000000..191c67f
4943 --- /dev/null
4944 +++ b/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h
4945 @@ -0,0 +1,136 @@
4946 +/** @file uap_sdio_mmc.h
4947 + * @brief This file contains SDIO IF (interface) module
4948 + * related macros, enum, and structure.
4949 + *
4950 + * Copyright (C) 2007-2009, Marvell International Ltd.
4951 + *
4952 + * This software file (the "File") is distributed by Marvell International
4953 + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
4954 + * (the "License"). You may use, redistribute and/or modify this File in
4955 + * accordance with the terms and conditions of the License, a copy of which
4956 + * is available along with the File in the gpl.txt file or by writing to
4957 + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
4958 + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
4959 + *
4960 + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
4961 + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
4962 + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
4963 + * this warranty disclaimer.
4964 + *
4965 + */
4966 +/****************************************************
4967 +Change log:
4968 + 10/10/07: initial version
4969 +****************************************************/
4970 +
4971 +#ifndef _UAP_SDIO_MMC_H
4972 +#define _UAP_SDIO_MMC_H
4973 +
4974 +#include <linux/mmc/sdio.h>
4975 +#include <linux/mmc/sdio_ids.h>
4976 +#include <linux/mmc/sdio_func.h>
4977 +#include <linux/mmc/card.h>
4978 +
4979 +#include "uap_headers.h"
4980 +
4981 +/** The number of times to try when waiting for downloaded firmware to
4982 + become active. (polling the scratch register). */
4983 +#define MAX_FIRMWARE_POLL_TRIES 100
4984 +
4985 +/** Firmware ready */
4986 +#define FIRMWARE_READY 0xfedc
4987 +
4988 +/** Number of firmware blocks to transfer */
4989 +#define FIRMWARE_TRANSFER_NBLOCK 2
4990 +
4991 +/* Host Control Registers */
4992 +/** Host Control Registers : I/O port 0 */
4993 +#define IO_PORT_0_REG 0x00
4994 +/** Host Control Registers : I/O port 1 */
4995 +#define IO_PORT_1_REG 0x01
4996 +/** Host Control Registers : I/O port 2 */
4997 +#define IO_PORT_2_REG 0x02
4998 +
4999 +/** Host Control Registers : Configuration */
5000 +#define CONFIGURATION_REG 0x03
5001 +/** Host Control Registers : Host without Command 53 finish host */
5002 +#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2)
5003 +/** Host Control Registers : Host power up */
5004 +#define HOST_POWER_UP (0x1U << 1)
5005 +/** Host Control Registers : Host power down */
5006 +#define HOST_POWER_DOWN (0x1U << 0)
5007 +
5008 +/** Host Control Registers : Host interrupt mask */
5009 +#define HOST_INT_MASK_REG 0x04
5010 +/** Host Control Registers : Upload host interrupt mask */
5011 +#define UP_LD_HOST_INT_MASK (0x1U)
5012 +/** Host Control Registers : Download host interrupt mask */
5013 +#define DN_LD_HOST_INT_MASK (0x2U)
5014 +/** Enable Host interrupt mask */
5015 +#define HIM_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK)
5016 +/** Disable Host interrupt mask */
5017 +#define HIM_DISABLE 0xff
5018 +
5019 +/** Host Control Registers : Host interrupt status */
5020 +#define HOST_INTSTATUS_REG 0x05
5021 +/** Host Control Registers : Upload host interrupt status */
5022 +#define UP_LD_HOST_INT_STATUS (0x1U)
5023 +/** Host Control Registers : Download host interrupt status */
5024 +#define DN_LD_HOST_INT_STATUS (0x2U)
5025 +
5026 +/** Host F1 read base 0 */
5027 +#define HOST_F1_RD_BASE_0 0x10
5028 +/** Host F1 read base 1 */
5029 +#define HOST_F1_RD_BASE_1 0x11
5030 +
5031 +/** Card Control Registers : Card status register */
5032 +#define CARD_STATUS_REG 0x20
5033 +/** Card Control Registers : Card I/O ready */
5034 +#define CARD_IO_READY (0x1U << 3)
5035 +/** Card Control Registers : CIS card ready */
5036 +#define CIS_CARD_RDY (0x1U << 2)
5037 +/** Card Control Registers : Upload card ready */
5038 +#define UP_LD_CARD_RDY (0x1U << 1)
5039 +/** Card Control Registers : Download card ready */
5040 +#define DN_LD_CARD_RDY (0x1U << 0)
5041 +
5042 +/** Card Control Registers : Card OCR 0 register */
5043 +#define CARD_OCR_0_REG 0x34
5044 +/** Card Control Registers : Card OCR 1 register */
5045 +#define CARD_OCR_1_REG 0x35
5046 +
5047 +/** Firmware status 0 register */
5048 +#define CARD_FW_STATUS0_REG 0x40
5049 +/** Firmware status 1 register */
5050 +#define CARD_FW_STATUS1_REG 0x41
5051 +/** Rx length register */
5052 +#define CARD_RX_LEN_REG 0x42
5053 +/** Rx unit register */
5054 +#define CARD_RX_UNIT_REG 0x43
5055 +
5056 +/** Chip Id Register 0 */
5057 +#define CARD_CHIP_ID_0_REG 0x801c
5058 +/** Chip Id Register 1 */
5059 +#define CARD_CHIP_ID_1_REG 0x801d
5060 +
5061 +#ifdef PXA3XX_DMA_ALIGN
5062 +/** DMA alignment value for PXA3XX platforms */
5063 +#define PXA3XX_DMA_ALIGNMENT 8
5064 +/** Macros for Data Alignment : size */
5065 +#define ALIGN_SZ(p, a) \
5066 + (((p) + ((a) - 1)) & ~((a) - 1))
5067 +
5068 +/** Macros for Data Alignment : address */
5069 +#define ALIGN_ADDR(p, a) \
5070 + ((((u32)(p)) + (((u32)(a)) - 1)) & ~(((u32)(a)) - 1))
5071 +#endif /* PXA3XX_DMA_ALIGN */
5072 +
5073 +struct sdio_mmc_card
5074 +{
5075 + /** sdio_func structure pointer */
5076 + struct sdio_func *func;
5077 + /** uap_private structure pointer */
5078 + uap_private *priv;
5079 +};
5080 +
5081 +#endif /* _UAP_SDIO_MMC_H */