]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/backports-3.18.1-1_add_libertas_uap.patch
reiserfsprogs: Update to 3.6.27
[ipfire-2.x.git] / src / patches / backports-3.18.1-1_add_libertas_uap.patch
CommitLineData
91e56a59
AF
1diff -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"
19diff -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
29diff -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
293diff -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 */
964diff -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 */
1327diff -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 */
1395diff -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");
3216diff -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
3478diff -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+}
4910diff -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 */
5050diff -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/