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