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