]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/compat-wireless-3.5-libertas_uap.patch
asterisk addon: update to 11.13.1
[people/pmueller/ipfire-2.x.git] / src / patches / compat-wireless-3.5-libertas_uap.patch
CommitLineData
e9544fbe
AF
1diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/Makefile compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/Makefile
2--- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/Makefile 1970-01-01 01:00:00.000000000 +0100
3+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/Makefile 2012-07-31 14:23:04.000000000 +0200
9f44350f
AF
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
e9544fbe
AF
11diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_debug.c compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_debug.c
12--- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_debug.c 1970-01-01 01:00:00.000000000 +0100
13+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_debug.c 2012-07-31 14:23:04.000000000 +0200
9f44350f
AF
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
e9544fbe
AF
276diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_drv.h compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_drv.h
277--- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_drv.h 1970-01-01 01:00:00.000000000 +0100
278+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_drv.h 2012-07-31 14:23:04.000000000 +0200
9f44350f
AF
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 */
e9544fbe
AF
947diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_fw.h compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_fw.h
948--- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_fw.h 1970-01-01 01:00:00.000000000 +0100
949+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_fw.h 2012-07-31 14:23:04.000000000 +0200
9f44350f
AF
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 */
e9544fbe
AF
1310diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_headers.h compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_headers.h
1311--- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_headers.h 1970-01-01 01:00:00.000000000 +0100
1312+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_headers.h 2012-07-31 14:23:04.000000000 +0200
9f44350f
AF
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 */
e9544fbe
AF
1378diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_main.c compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_main.c
1379--- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_main.c 1970-01-01 01:00:00.000000000 +0100
1380+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_main.c 2012-07-31 14:25:28.473230753 +0200
1381@@ -0,0 +1,1815 @@
9f44350f
AF
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+/**
9f44350f
AF
2706+ * @brief This function handles the timeout of packet
2707+ * transmission
2708+ *
2709+ * @param dev A pointer to net_device structure
2710+ * @return n/a
2711+ */
2712+static void
2713+uap_tx_timeout(struct net_device *dev)
2714+{
2715+ uap_private *priv = (uap_private *) netdev_priv(dev);
2716+
2717+ ENTER();
2718+
2719+ PRINTM(DATA, "Tx timeout\n");
2720+ UpdateTransStart(dev);
2721+ priv->num_tx_timeout++;
2722+ priv->adapter->IntCounter++;
2723+ wake_up_interruptible(&priv->MainThread.waitQ);
2724+
2725+ LEAVE();
2726+}
2727+
2728+/**
2729+ * @brief This function handles packet transmission
2730+ *
2731+ * @param skb A pointer to sk_buff structure
2732+ * @param dev A pointer to net_device structure
2733+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
2734+ */
2735+static int
2736+uap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
2737+{
2738+ uap_private *priv = (uap_private *) netdev_priv(dev);
2739+ int ret = UAP_STATUS_SUCCESS;
2740+
2741+ ENTER();
2742+ PRINTM(DATA, "Data <= kernel\n");
2743+ DBG_HEXDUMP(DAT_D, "Tx", skb->data, MIN(skb->len, DATA_DUMP_LEN));
2744+ /* skb sanity check */
2745+ if (!skb->len || (skb->len > MRVDRV_MAXIMUM_ETH_PACKET_SIZE)) {
2746+ PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
2747+ MRVDRV_MAXIMUM_ETH_PACKET_SIZE);
2748+ priv->stats.tx_dropped++;
2749+ kfree(skb);
2750+ goto done;
2751+ }
2752+ skb_queue_tail(&priv->adapter->tx_queue, skb);
2753+ wake_up_interruptible(&priv->MainThread.waitQ);
2754+ if (skb_queue_len(&priv->adapter->tx_queue) > TX_HIGH_WATERMARK) {
2755+ UpdateTransStart(dev);
2756+ os_stop_queue(priv);
2757+ }
2758+ done:
2759+ LEAVE();
2760+ return ret;
2761+}
2762+
2763+/**
2764+ * @brief ioctl function - entry point
2765+ *
2766+ * @param dev A pointer to net_device structure
2767+ * @param req A pointer to ifreq structure
2768+ * @param cmd command
2769+ * @return UAP_STATUS_SUCCESS--success, otherwise fail
2770+ */
2771+static int
2772+uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
2773+{
2774+ int ret = UAP_STATUS_SUCCESS;
2775+
2776+ ENTER();
2777+
2778+ PRINTM(CMND, "uap_do_ioctl: ioctl cmd = 0x%x\n", cmd);
2779+
2780+ switch (cmd) {
2781+ case UAPHOSTCMD:
2782+ ret = uap_hostcmd_ioctl(dev, req);
2783+ break;
2784+ case UAP_POWER_MODE:
2785+ ret = uap_power_mode_ioctl(dev, req);
2786+ break;
2787+ default:
2788+ ret = -EINVAL;
2789+ break;
2790+ }
2791+
2792+ LEAVE();
2793+ return ret;
2794+}
2795+
2796+/**
2797+ * @brief This function handles events generated by firmware
2798+ *
2799+ * @param priv A pointer to uap_private structure
2800+ * @param payload A pointer to payload buffer
2801+ * @param len Length of the payload
2802+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
2803+ */
2804+int
2805+uap_process_event(uap_private * priv, u8 * payload, uint len)
2806+{
2807+ int ret = UAP_STATUS_SUCCESS;
2808+ uap_adapter *Adapter = priv->adapter;
2809+ struct sk_buff *skb = NULL;
2810+ struct nlmsghdr *nlh = NULL;
2811+ struct sock *sk = Adapter->nl_sk;
2812+ AP_Event *pEvent;
2813+
2814+ ENTER();
2815+ Adapter->ps_state = PS_STATE_AWAKE;
2816+ if (len > NL_MAX_PAYLOAD) {
2817+ PRINTM(ERROR, "event size is too big!!! len=%d\n", len);
2818+ ret = UAP_STATUS_FAILURE;
2819+ goto done;
2820+ }
2821+ pEvent = (AP_Event *) payload;
2822+ PRINTM(CMND, "Event: %d\n", pEvent->EventId);
2823+ switch (pEvent->EventId) {
2824+ case MICRO_AP_EV_ID_BSS_START:
2825+ memcpy(priv->uap_dev.netdev->dev_addr, pEvent->MacAddr, ETH_ALEN);
2826+ DBG_HEXDUMP(CMD_D, "BSS MAC addr", priv->uap_dev.netdev->dev_addr,
2827+ ETH_ALEN);
2828+ break;
2829+ case MICRO_AP_EV_BSS_ACTIVE:
2830+ // carrier on
2831+ priv->MediaConnected = TRUE;
2832+ os_carrier_on(priv);
2833+ os_start_queue(priv);
2834+ break;
2835+ case MICRO_AP_EV_BSS_IDLE:
2836+ os_stop_queue(priv);
2837+ os_carrier_off(priv);
2838+ priv->MediaConnected = FALSE;
2839+ break;
2840+ case EVENT_PS_AWAKE:
2841+ PRINTM(CMND, "UAP: PS_AWAKE\n");
2842+ Adapter->ps_state = PS_STATE_AWAKE;
2843+ Adapter->WakeupTries = 0;
2844+ break;
2845+ case EVENT_PS_SLEEP:
2846+ PRINTM(CMND, "UAP: PS_SLEEP\n");
2847+ Adapter->ps_state = PS_STATE_PRE_SLEEP;
2848+ break;
2849+ default:
2850+ break;
2851+ }
2852+ if ((pEvent->EventId == EVENT_PS_AWAKE) ||
2853+ (pEvent->EventId == EVENT_PS_SLEEP))
2854+ goto done;
2855+ if (sk) {
2856+ /* Allocate skb */
2857+ if (!(skb = alloc_skb(NLMSG_SPACE(NL_MAX_PAYLOAD), GFP_ATOMIC))) {
2858+ PRINTM(ERROR, "Could not allocate skb for netlink.\n");
2859+ ret = UAP_STATUS_FAILURE;
2860+ goto done;
2861+ }
2862+ nlh = (struct nlmsghdr *) skb->data;
2863+ nlh->nlmsg_len = NLMSG_SPACE(len);
2864+
2865+ /* From kernel */
2866+ nlh->nlmsg_pid = 0;
2867+ nlh->nlmsg_flags = 0;
2868+
2869+ /* Data */
2870+ skb_put(skb, nlh->nlmsg_len);
2871+ memcpy(NLMSG_DATA(nlh), payload, len);
2872+
2873+ /* From Kernel */
2874+ NETLINK_CB(skb).pid = 0;
2875+
2876+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
2877+ /* Multicast message */
2878+ NETLINK_CB(skb).dst_pid = 0;
2879+#endif
2880+
2881+ /* Multicast group number */
2882+ NETLINK_CB(skb).dst_group = NL_MULTICAST_GROUP;
2883+
2884+ /* Send message */
2885+ netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP, GFP_KERNEL);
2886+
2887+ ret = UAP_STATUS_SUCCESS;
2888+ } else {
2889+ PRINTM(ERROR, "Could not send event through NETLINK. Link down.\n");
2890+ ret = UAP_STATUS_FAILURE;
2891+ }
2892+ done:
2893+ LEAVE();
2894+ return ret;
2895+}
2896+
2897+/**
2898+ * @brief This function handles the interrupt. it will change PS
2899+ * state if applicable. it will wake up main_thread to handle
2900+ * the interrupt event as well.
2901+ *
2902+ * @param priv A pointer to uap_private structure
2903+ * @return n/a
2904+ */
2905+void
2906+uap_interrupt(uap_private * priv)
2907+{
2908+ ENTER();
2909+ priv->adapter->IntCounter++;
2910+ priv->adapter->WakeupTries = 0;
2911+ PRINTM(INFO, "*\n");
2912+ wake_up_interruptible(&priv->MainThread.waitQ);
2913+
2914+ LEAVE();
2915+
2916+}
2917+
2918+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
2919+/** Network device handlers */
2920+static const struct net_device_ops uap_netdev_ops = {
2921+ .ndo_open = uap_open,
2922+ .ndo_start_xmit = uap_hard_start_xmit,
2923+ .ndo_stop = uap_close,
2924+ .ndo_do_ioctl = uap_do_ioctl,
2925+ .ndo_set_mac_address = uap_set_mac_address,
2926+ .ndo_tx_timeout = uap_tx_timeout,
2927+ .ndo_get_stats = uap_get_stats,
9f44350f
AF
2928+};
2929+#endif
2930+
2931+/**
2932+ * @brief This function adds the card. it will probe the
2933+ * card, allocate the uap_priv and initialize the device.
2934+ *
2935+ * @param card A pointer to card
2936+ * @return A pointer to uap_private structure
2937+ */
2938+uap_private *
2939+uap_add_card(void *card)
2940+{
2941+ struct net_device *dev = NULL;
2942+ uap_private *priv = NULL;
2943+
2944+ ENTER();
2945+
2946+ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
2947+ goto exit_sem_err;
2948+
2949+ /* Allocate an Ethernet device */
2950+ if (!(dev = alloc_etherdev(sizeof(uap_private)))) {
2951+ PRINTM(FATAL, "Init ethernet device failed!\n");
2952+ goto error;
2953+ }
2954+ priv = (uap_private *) netdev_priv(dev);
2955+
2956+ /* Allocate name */
2957+ if (dev_alloc_name(dev, "uap%d") < 0) {
2958+ PRINTM(ERROR, "Could not allocate device name!\n");
2959+ goto error;
2960+ }
2961+
2962+ /* Allocate buffer for uap_adapter */
2963+ if (!(priv->adapter = kmalloc(sizeof(uap_adapter), GFP_KERNEL))) {
2964+ PRINTM(FATAL, "Allocate buffer for uap_adapter failed!\n");
2965+ goto error;
2966+ }
2967+ memset(priv->adapter, 0, sizeof(uap_adapter));
2968+
2969+ priv->uap_dev.netdev = dev;
2970+ priv->uap_dev.card = card;
2971+ priv->MediaConnected = FALSE;
2972+ uappriv = priv;
2973+ ((struct sdio_mmc_card *) card)->priv = priv;
2974+
2975+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
2976+ SET_MODULE_OWNER(dev);
2977+#endif
2978+
2979+ /* Setup the OS Interface to our functions */
2980+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
2981+ dev->open = uap_open;
2982+ dev->stop = uap_close;
2983+ dev->hard_start_xmit = uap_hard_start_xmit;
2984+ dev->tx_timeout = uap_tx_timeout;
2985+ dev->get_stats = uap_get_stats;
2986+ dev->do_ioctl = uap_do_ioctl;
2987+ dev->set_mac_address = uap_set_mac_address;
2988+ dev->set_multicast_list = uap_set_multicast_list;
2989+#else
2990+ dev->netdev_ops = &uap_netdev_ops;
2991+#endif
2992+ dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;
2993+ dev->hard_header_len += sizeof(TxPD) + INTF_HEADER_LEN;
2994+ dev->hard_header_len += HEADER_ALIGNMENT;
2995+#define NETIF_F_DYNALLOC 16
2996+ dev->features |= NETIF_F_DYNALLOC;
2997+ dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
2998+
2999+ /* Init SW */
3000+ if (uap_init_sw(priv)) {
3001+ PRINTM(FATAL, "Software Init Failed\n");
3002+ goto error;
3003+ }
3004+
3005+ PRINTM(INFO, "Starting kthread...\n");
3006+ priv->MainThread.priv = priv;
3007+ spin_lock_init(&priv->driver_lock);
3008+ uap_create_thread(uap_service_main_thread, &priv->MainThread,
3009+ "uap_main_service");
3010+ while (priv->MainThread.pid == 0) {
3011+ os_sched_timeout(2);
3012+ }
3013+
3014+ /* Register the device */
3015+ if (sbi_register_dev(priv) < 0) {
3016+ PRINTM(FATAL, "Failed to register uap device!\n");
3017+ goto err_registerdev;
3018+ }
3019+#ifdef FW_DNLD_NEEDED
3020+ SET_NETDEV_DEV(dev, priv->hotplug_device);
3021+#endif
3022+
3023+ /* Init FW and HW */
3024+ if (uap_init_fw(priv)) {
3025+ PRINTM(FATAL, "Firmware Init Failed\n");
3026+ goto err_init_fw;
3027+ }
3028+
3029+ priv->uap_dev.cmd_sent = FALSE;
3030+ priv->uap_dev.data_sent = FALSE;
3031+
3032+ /* Get mac address from firmware */
3033+ if (uap_get_mac_address(priv)) {
3034+ PRINTM(FATAL, "Fail to get mac address\n");
3035+ goto err_init_fw;
3036+ }
3037+ /* Register network device */
3038+ if (register_netdev(dev)) {
3039+ printk(KERN_ERR "Cannot register network device!\n");
3040+ goto err_init_fw;
3041+ }
3042+#ifdef CONFIG_PROC_FS
3043+ uap_proc_entry(priv, dev);
3044+ uap_debug_entry(priv, dev);
3045+#endif /* CPNFIG_PROC_FS */
3046+ OS_REL_SEMAPHORE(&AddRemoveCardSem);
3047+
3048+ LEAVE();
3049+ return priv;
3050+ err_init_fw:
3051+ sbi_unregister_dev(priv);
3052+ err_registerdev:
3053+ ((struct sdio_mmc_card *) card)->priv = NULL;
3054+ /* Stop the thread servicing the interrupts */
3055+ priv->adapter->SurpriseRemoved = TRUE;
3056+ wake_up_interruptible(&priv->MainThread.waitQ);
3057+ while (priv->MainThread.pid) {
3058+ os_sched_timeout(1);
3059+ }
3060+ error:
3061+ if (dev) {
3062+ if (dev->reg_state == NETREG_REGISTERED)
3063+ unregister_netdev(dev);
3064+ if (priv->adapter)
3065+ uap_free_adapter(priv);
3066+ free_netdev(dev);
3067+ uappriv = NULL;
3068+ }
3069+ OS_REL_SEMAPHORE(&AddRemoveCardSem);
3070+ exit_sem_err:
3071+ LEAVE();
3072+ return NULL;
3073+}
3074+
3075+/**
3076+ * @brief This function removes the card.
3077+ *
3078+ * @param card A pointer to card
3079+ * @return UAP_STATUS_SUCCESS
3080+ */
3081+int
3082+uap_remove_card(void *card)
3083+{
3084+ uap_private *priv = uappriv;
3085+ uap_adapter *Adapter;
3086+ struct net_device *dev;
3087+
3088+ ENTER();
3089+
3090+ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
3091+ goto exit_sem_err;
3092+
3093+ if (!priv || !(Adapter = priv->adapter)) {
3094+ goto exit_remove;
3095+ }
3096+ Adapter->SurpriseRemoved = TRUE;
3097+ if (Adapter->cmd_pending == TRUE) {
3098+ /* Wake up cmd Q */
3099+ Adapter->CmdWaitQWoken = TRUE;
3100+ wake_up_interruptible(&Adapter->cmdwait_q);
3101+ }
3102+ dev = priv->uap_dev.netdev;
3103+ if (priv->MediaConnected == TRUE) {
3104+ os_stop_queue(priv);
3105+ os_carrier_off(priv);
3106+ priv->MediaConnected = FALSE;
3107+ }
3108+ Adapter->CmdSize = 0;
3109+ Adapter->CmdWaitQWoken = TRUE;
3110+ wake_up_interruptible(&Adapter->cmdwait_q);
3111+ skb_queue_purge(&priv->adapter->tx_queue);
3112+ skb_queue_purge(&priv->adapter->cmd_queue);
3113+
3114+ /* Disable interrupts on the card */
3115+ sbi_disable_host_int(priv);
3116+ PRINTM(INFO, "netdev_finish_unregister: %s%s.\n", dev->name,
3117+ (dev->features & NETIF_F_DYNALLOC) ? "" : ", old style");
3118+ unregister_netdev(dev);
3119+ PRINTM(INFO, "Unregister finish\n");
3120+ wake_up_interruptible(&priv->MainThread.waitQ);
3121+ while (priv->MainThread.pid) {
3122+ os_sched_timeout(1);
3123+ }
3124+
3125+ if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) {
3126+ sock_release((Adapter->nl_sk)->sk_socket);
3127+ Adapter->nl_sk = NULL;
3128+ }
3129+#ifdef CONFIG_PROC_FS
3130+ uap_debug_remove(priv);
3131+ uap_proc_remove(priv);
3132+#endif
3133+ sbi_unregister_dev(priv);
3134+ PRINTM(INFO, "Free Adapter\n");
3135+ uap_free_adapter(priv);
3136+ priv->uap_dev.netdev = NULL;
3137+ free_netdev(dev);
3138+ uappriv = NULL;
3139+
3140+ exit_remove:
3141+ OS_REL_SEMAPHORE(&AddRemoveCardSem);
3142+ exit_sem_err:
3143+ LEAVE();
3144+ return UAP_STATUS_SUCCESS;
3145+}
3146+
3147+/**
3148+ * @brief This function initializes module.
3149+ *
3150+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3151+ */
3152+static int __init
3153+uap_init_module(void)
3154+{
3155+ int ret = UAP_STATUS_SUCCESS;
3156+ ENTER();
3157+
3158+ OS_INIT_SEMAPHORE(&AddRemoveCardSem);
3159+ ret = sbi_register();
3160+ LEAVE();
3161+ return ret;
3162+}
3163+
3164+/**
3165+ * @brief This function cleans module
3166+ *
3167+ * @return n/a
3168+ */
3169+static void __exit
3170+uap_cleanup_module(void)
3171+{
3172+ ENTER();
3173+
3174+ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
3175+ goto exit_sem_err;
3176+
3177+ if ((uappriv) && (uappriv->adapter)) {
3178+ uap_func_shutdown(uappriv);
3179+ }
3180+ OS_REL_SEMAPHORE(&AddRemoveCardSem);
3181+ exit_sem_err:
3182+ sbi_unregister();
3183+ LEAVE();
3184+}
3185+
3186+module_init(uap_init_module);
3187+module_exit(uap_cleanup_module);
3188+module_param(helper_name, charp, 0);
3189+MODULE_PARM_DESC(helper_name, "Helper name");
3190+module_param(fw_name, charp, 0);
3191+MODULE_PARM_DESC(fw_name, "Firmware name");
3192+
3193+MODULE_DESCRIPTION("M-UAP Driver");
3194+MODULE_AUTHOR("Marvell International Ltd.");
3195+MODULE_VERSION(DRIVER_VERSION);
3196+MODULE_LICENSE("GPL");
e9544fbe
AF
3197diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_proc.c compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_proc.c
3198--- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_proc.c 1970-01-01 01:00:00.000000000 +0100
3199+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_proc.c 2012-07-31 14:23:04.000000000 +0200
3200@@ -0,0 +1,296 @@
9f44350f
AF
3201+/** @file uap_proc.c
3202+ * @brief This file contains functions for proc file.
3203+ *
3204+ * Copyright (C) 2008-2009, Marvell International Ltd.
3205+ *
3206+ * This software file (the "File") is distributed by Marvell International
3207+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
3208+ * (the "License"). You may use, redistribute and/or modify this File in
3209+ * accordance with the terms and conditions of the License, a copy of which
3210+ * is available along with the File in the gpl.txt file or by writing to
3211+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
3212+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
3213+ *
3214+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
3215+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
3216+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
3217+ * this warranty disclaimer.
3218+ *
3219+ */
3220+#ifdef CONFIG_PROC_FS
3221+#include "uap_headers.h"
3222+
3223+/** /proc directory root */
3224+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
3225+#define PROC_DIR NULL
3226+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
3227+#define PROC_DIR &proc_root
3228+#else
3229+#define PROC_DIR proc_net
3230+#endif
3231+
3232+/********************************************************
3233+ Local Variables
3234+********************************************************/
3235+
3236+/********************************************************
3237+ Global Variables
3238+********************************************************/
3239+
3240+/********************************************************
3241+ Local Functions
3242+********************************************************/
3243+
3244+/**
3245+ * @brief proc read function
3246+ *
3247+ * @param page pointer to buffer
3248+ * @param start read data starting position
3249+ * @param offset offset
3250+ * @param count counter
3251+ * @param eof end of file flag
3252+ * @param data data to output
3253+ * @return number of output data
3254+ */
3255+static int
3256+uap_proc_read(char *page, char **start, off_t offset,
3257+ int count, int *eof, void *data)
3258+{
3259+ int i;
3260+ char *p = page;
3261+ struct net_device *netdev = data;
3262+ struct netdev_hw_addr *ha;
3263+ char fmt[64];
3264+ uap_private *priv = (uap_private *) netdev_priv(netdev);
3265+
3266+ if (offset != 0) {
3267+ *eof = 1;
3268+ goto exit;
3269+ }
3270+
3271+ strcpy(fmt, DRIVER_VERSION);
3272+
3273+ p += sprintf(p, "driver_name = " "\"uap\"\n");
3274+ p += sprintf(p, "driver_version = %s-(FP%s)", fmt, FPNUM);
3275+ p += sprintf(p, "\nInterfaceName=\"%s\"\n", netdev->name);
3276+ p += sprintf(p, "State=\"%s\"\n",
3277+ ((priv->MediaConnected ==
3278+ FALSE) ? "Disconnected" : "Connected"));
3279+ p += sprintf(p, "MACAddress=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
3280+ netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
3281+ netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
3282+ i = 0;
3283+ netdev_for_each_mc_addr(ha, netdev) {
3284+ ++i;
3285+ }
3286+ p += sprintf(p, "MCCount=\"%d\"\n", i);
3287+
3288+ /*
3289+ * Put out the multicast list
3290+ */
3291+ i = 0;
3292+ netdev_for_each_mc_addr(ha, netdev) {
3293+ p += sprintf(p,
3294+ "MCAddr[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
3295+ i++,
9f44350f
AF
3296+ ha->addr[0], ha->addr[1],
3297+ ha->addr[2], ha->addr[3],
3298+ ha->addr[4], ha->addr[5]);
9f44350f
AF
3299+ }
3300+
3301+ p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
3302+ p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
3303+ p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
3304+ p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
3305+ p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
3306+ p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
3307+ p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
3308+ p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
3309+ p += sprintf(p, "num_tx_timeout = %u\n", priv->num_tx_timeout);
3310+ p += sprintf(p, "carrier %s\n",
3311+ ((netif_carrier_ok(priv->uap_dev.netdev)) ? "on" : "off"));
3312+ p += sprintf(p, "tx queue %s\n",
3313+ ((netif_queue_stopped(priv->uap_dev.netdev)) ? "stopped" :
3314+ "started"));
3315+
3316+ exit:
3317+ return (p - page);
3318+}
3319+
3320+/**
3321+ * @brief hwstatus proc write function
3322+ *
3323+ * @param f file pointer
3324+ * @param buf pointer to data buffer
3325+ * @param cnt data number to write
3326+ * @param data data to write
3327+ * @return number of data
3328+ */
3329+static int
3330+uap_hwstatus_write(struct file *f, const char *buf, unsigned long cnt,
3331+ void *data)
3332+{
3333+ struct net_device *netdev = data;
3334+ uap_private *priv = (uap_private *) netdev_priv(netdev);
3335+ char databuf[10];
3336+ int hwstatus;
3337+ MODULE_GET;
3338+ if (cnt > 10) {
3339+ MODULE_PUT;
3340+ return cnt;
3341+ }
3342+ if (copy_from_user(databuf, buf, cnt)) {
3343+ MODULE_PUT;
3344+ return 0;
3345+ }
3346+ hwstatus = string_to_number(databuf);
3347+ switch (hwstatus) {
3348+ case HWReset:
3349+ PRINTM(MSG, "reset hw\n");
3350+ uap_soft_reset(priv);
3351+ priv->adapter->HardwareStatus = HWReset;
3352+ break;
3353+ default:
3354+ break;
3355+ }
3356+ MODULE_PUT;
3357+ return cnt;
3358+}
3359+
3360+/**
3361+ * @brief hwstatus proc read function
3362+ *
3363+ * @param page pointer to buffer
3364+ * @param s read data starting position
3365+ * @param off offset
3366+ * @param cnt counter
3367+ * @param eof end of file flag
3368+ * @param data data to output
3369+ * @return number of output data
3370+ */
3371+static int
3372+uap_hwstatus_read(char *page, char **s, off_t off, int cnt, int *eof,
3373+ void *data)
3374+{
3375+ char *p = page;
3376+ struct net_device *netdev = data;
3377+ uap_private *priv = (uap_private *) netdev_priv(netdev);
3378+ MODULE_GET;
3379+ p += sprintf(p, "%d\n", priv->adapter->HardwareStatus);
3380+ MODULE_PUT;
3381+ return p - page;
3382+}
3383+
3384+/********************************************************
3385+ Global Functions
3386+********************************************************/
3387+/**
3388+ * @brief create uap proc file
3389+ *
3390+ * @param priv pointer uap_private
3391+ * @param dev pointer net_device
3392+ * @return N/A
3393+ */
3394+void
3395+uap_proc_entry(uap_private * priv, struct net_device *dev)
3396+{
3397+ struct proc_dir_entry *r = PROC_DIR;
3398+
3399+ PRINTM(INFO, "Creating Proc Interface\n");
3400+ /* Check if uap directory already exists */
3401+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
3402+ for (r = r->subdir; r; r = r->next) {
3403+ if (r->namelen && !strcmp("uap", r->name)) {
3404+ /* Directory exists */
3405+ PRINTM(WARN, "proc directory already exists!\n");
3406+ priv->proc_uap = r;
3407+ break;
3408+ }
3409+ }
3410+#endif
3411+ if (!priv->proc_uap) {
3412+ priv->proc_uap = proc_mkdir("uap", PROC_DIR);
3413+ if (!priv->proc_uap)
3414+ return;
3415+ else
3416+ atomic_set(&priv->proc_uap->count, 1);
3417+ } else {
3418+ atomic_inc(&priv->proc_uap->count);
3419+ }
3420+ priv->proc_entry = proc_mkdir(dev->name, priv->proc_uap);
3421+
3422+ if (priv->proc_entry) {
3423+ r = create_proc_read_entry("info", 0, priv->proc_entry, uap_proc_read,
3424+ dev);
3425+ r = create_proc_entry("hwstatus", 0644, priv->proc_entry);
3426+ if (r) {
3427+ r->data = dev;
3428+ r->read_proc = uap_hwstatus_read;
3429+ r->write_proc = uap_hwstatus_write;
3430+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
3431+ r->owner = THIS_MODULE;
3432+#endif
3433+ } else
3434+ PRINTM(MSG, "Fail to create proc hwstatus\n");
3435+ }
3436+}
3437+
3438+/**
3439+ * @brief remove proc file
3440+ *
3441+ * @param priv pointer uap_private
3442+ * @return N/A
3443+ */
3444+void
3445+uap_proc_remove(uap_private * priv)
3446+{
3447+ if (priv->proc_uap) {
3448+ if (priv->proc_entry) {
3449+ remove_proc_entry("info", priv->proc_entry);
3450+ remove_proc_entry("hwstatus", priv->proc_entry);
3451+ }
3452+ remove_proc_entry(priv->uap_dev.netdev->name, priv->proc_uap);
3453+ atomic_dec(&priv->proc_uap->count);
3454+ if (atomic_read(&(priv->proc_uap->count)) == 0)
3455+ remove_proc_entry("uap", PROC_DIR);
3456+ }
3457+}
3458+
3459+/**
3460+ * @brief convert string to number
3461+ *
3462+ * @param s pointer to numbered string
3463+ * @return converted number from string s
3464+ */
3465+int
3466+string_to_number(char *s)
3467+{
3468+ int r = 0;
3469+ int base = 0;
3470+ int pn = 1;
3471+
3472+ if (strncmp(s, "-", 1) == 0) {
3473+ pn = -1;
3474+ s++;
3475+ }
3476+ if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) {
3477+ base = 16;
3478+ s += 2;
3479+ } else
3480+ base = 10;
3481+
3482+ for (s = s; *s != 0; s++) {
3483+ if ((*s >= '0') && (*s <= '9'))
3484+ r = (r * base) + (*s - '0');
3485+ else if ((*s >= 'A') && (*s <= 'F'))
3486+ r = (r * base) + (*s - 'A' + 10);
3487+ else if ((*s >= 'a') && (*s <= 'f'))
3488+ r = (r * base) + (*s - 'a' + 10);
3489+ else
3490+ break;
3491+ }
3492+
3493+ return (r * pn);
3494+}
3495+
3496+#endif
e9544fbe
AF
3497diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c
3498--- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c 1970-01-01 01:00:00.000000000 +0100
3499+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c 2012-07-31 14:23:04.000000000 +0200
9f44350f
AF
3500@@ -0,0 +1,1428 @@
3501+/** @file uap_sdio_mmc.c
3502+ * @brief This file contains SDIO IF (interface) module
3503+ * related functions.
3504+ *
3505+ * Copyright (C) 2007-2009, Marvell International Ltd.
3506+ *
3507+ * This software file (the "File") is distributed by Marvell International
3508+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
3509+ * (the "License"). You may use, redistribute and/or modify this File in
3510+ * accordance with the terms and conditions of the License, a copy of which
3511+ * is available along with the File in the gpl.txt file or by writing to
3512+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
3513+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
3514+ *
3515+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
3516+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
3517+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
3518+ * this warranty disclaimer.
3519+ *
3520+ */
3521+/****************************************************
3522+Change log:
3523+****************************************************/
3524+
3525+#include "uap_sdio_mmc.h"
3526+
3527+#include <linux/firmware.h>
3528+
3529+/** define SDIO block size */
3530+/* We support up to 480-byte block size due to FW buffer limitation. */
3531+#define SD_BLOCK_SIZE 256
3532+
3533+/** define allocated buffer size */
3534+#define ALLOC_BUF_SIZE (((MAX(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, \
3535+ MRVDRV_SIZE_OF_CMD_BUFFER) + INTF_HEADER_LEN \
3536+ + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE)
3537+
3538+/** Max retry number of CMD53 write */
3539+#define MAX_WRITE_IOMEM_RETRY 2
3540+
3541+/********************************************************
3542+ Local Variables
3543+********************************************************/
3544+
3545+/** SDIO Rx unit */
3546+static u8 sdio_rx_unit = 0;
3547+
3548+/**Interrupt status */
3549+static u8 sd_ireg = 0;
3550+/********************************************************
3551+ Global Variables
3552+********************************************************/
3553+extern u8 *helper_name;
3554+extern u8 *fw_name;
3555+/** Default helper name */
3556+#define DEFAULT_HELPER_NAME "mrvl/helper_sd.bin"
3557+/** Default firmware name */
3558+#define DEFAULT_FW_NAME "mrvl/sd8688_ap.bin"
3559+
3560+/********************************************************
3561+ Local Functions
3562+********************************************************/
3563+/**
3564+ * @brief This function reads the IO register.
3565+ *
3566+ * @param priv A pointer to uap_private structure
3567+ * @param reg register to be read
3568+ * @param dat A pointer to variable that keeps returned value
3569+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3570+ */
3571+static int
3572+sbi_read_ioreg(uap_private * priv, u32 reg, u8 * dat)
3573+{
3574+ struct sdio_mmc_card *card;
3575+ int ret = UAP_STATUS_FAILURE;
3576+
3577+ ENTER();
3578+
3579+ card = priv->uap_dev.card;
3580+ if (!card || !card->func) {
3581+ PRINTM(ERROR, "sbi_read_ioreg(): card or function is NULL!\n");
3582+ goto done;
3583+ }
3584+
3585+ *dat = sdio_readb(card->func, reg, &ret);
3586+ if (ret) {
3587+ PRINTM(ERROR, "sbi_read_ioreg(): sdio_readb failed! ret=%d\n", ret);
3588+ goto done;
3589+ }
3590+
3591+ PRINTM(INFO, "sbi_read_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv,
3592+ card->func->num, reg, *dat);
3593+
3594+ done:
3595+ LEAVE();
3596+ return ret;
3597+}
3598+
3599+/**
3600+ * @brief This function writes the IO register.
3601+ *
3602+ * @param priv A pointer to uap_private structure
3603+ * @param reg register to be written
3604+ * @param dat the value to be written
3605+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3606+ */
3607+static int
3608+sbi_write_ioreg(uap_private * priv, u32 reg, u8 dat)
3609+{
3610+ struct sdio_mmc_card *card;
3611+ int ret = UAP_STATUS_FAILURE;
3612+
3613+ ENTER();
3614+
3615+ card = priv->uap_dev.card;
3616+ if (!card || !card->func) {
3617+ PRINTM(ERROR, "sbi_write_ioreg(): card or function is NULL!\n");
3618+ goto done;
3619+ }
3620+
3621+ PRINTM(INFO, "sbi_write_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv,
3622+ card->func->num, reg, dat);
3623+
3624+ sdio_writeb(card->func, dat, reg, &ret);
3625+ if (ret) {
3626+ PRINTM(ERROR, "sbi_write_ioreg(): sdio_readb failed! ret=%d\n", ret);
3627+ goto done;
3628+ }
3629+
3630+ done:
3631+ LEAVE();
3632+ return ret;
3633+}
3634+
3635+/**
3636+ * @brief This function get rx_unit value
3637+ *
3638+ * @param priv A pointer to uap_private structure
3639+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3640+ */
3641+static int
3642+sd_get_rx_unit(uap_private * priv)
3643+{
3644+ int ret = UAP_STATUS_SUCCESS;
3645+ u8 reg;
3646+
3647+ ENTER();
3648+
3649+ ret = sbi_read_ioreg(priv, CARD_RX_UNIT_REG, &reg);
3650+ if (ret == UAP_STATUS_SUCCESS)
3651+ sdio_rx_unit = reg;
3652+
3653+ LEAVE();
3654+ return ret;
3655+}
3656+
3657+/**
3658+ * @brief This function reads rx length
3659+ *
3660+ * @param priv A pointer to uap_private structure
3661+ * @param dat A pointer to keep returned data
3662+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3663+ */
3664+static int
3665+sd_read_rx_len(uap_private * priv, u16 * dat)
3666+{
3667+ int ret = UAP_STATUS_SUCCESS;
3668+ u8 reg;
3669+
3670+ ENTER();
3671+
3672+ ret = sbi_read_ioreg(priv, CARD_RX_LEN_REG, &reg);
3673+ if (ret == UAP_STATUS_SUCCESS)
3674+ *dat = (u16) reg << sdio_rx_unit;
3675+
3676+ LEAVE();
3677+ return ret;
3678+}
3679+
3680+/**
3681+ * @brief This function reads fw status registers
3682+ *
3683+ * @param priv A pointer to uap_private structure
3684+ * @param dat A pointer to keep returned data
3685+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3686+ */
3687+static int
3688+sd_read_firmware_status(uap_private * priv, u16 * dat)
3689+{
3690+ int ret = UAP_STATUS_SUCCESS;
3691+ u8 fws0;
3692+ u8 fws1;
3693+
3694+ ENTER();
3695+
3696+ ret = sbi_read_ioreg(priv, CARD_FW_STATUS0_REG, &fws0);
3697+ if (ret < 0) {
3698+ LEAVE();
3699+ return UAP_STATUS_FAILURE;
3700+ }
3701+
3702+ ret = sbi_read_ioreg(priv, CARD_FW_STATUS1_REG, &fws1);
3703+ if (ret < 0) {
3704+ LEAVE();
3705+ return UAP_STATUS_FAILURE;
3706+ }
3707+
3708+ *dat = (((u16) fws1) << 8) | fws0;
3709+
3710+ LEAVE();
3711+ return UAP_STATUS_SUCCESS;
3712+}
3713+
3714+/**
3715+ * @brief This function polls the card status register.
3716+ *
3717+ * @param priv A pointer to uap_private structure
3718+ * @param bits the bit mask
3719+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3720+ */
3721+static int
3722+mv_sdio_poll_card_status(uap_private * priv, u8 bits)
3723+{
3724+ int tries;
3725+ u8 cs;
3726+
3727+ ENTER();
3728+
3729+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
3730+ if (sbi_read_ioreg(priv, CARD_STATUS_REG, &cs) < 0)
3731+ break;
3732+ else if ((cs & bits) == bits) {
3733+ LEAVE();
3734+ return UAP_STATUS_SUCCESS;
3735+ }
3736+ udelay(10);
3737+ }
3738+
3739+ PRINTM(WARN, "mv_sdio_poll_card_status failed, tries = %d\n", tries);
3740+
3741+ LEAVE();
3742+ return UAP_STATUS_FAILURE;
3743+}
3744+
3745+/**
3746+ * @brief This function set the sdio bus width.
3747+ *
3748+ * @param priv A pointer to uap_private structure
3749+ * @param mode 1--1 bit mode, 4--4 bit mode
3750+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3751+ */
3752+#if 0
3753+static int
3754+sdio_set_bus_width(uap_private * priv, u8 mode)
3755+{
3756+ ENTER();
3757+ LEAVE();
3758+ return UAP_STATUS_SUCCESS;
3759+}
3760+#endif
3761+
3762+/**
3763+ * @brief This function reads data from the card.
3764+ *
3765+ * @param priv A pointer to uap_private structure
3766+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3767+ */
3768+static int
3769+sd_card_to_host(uap_private * priv)
3770+{
3771+ int ret = UAP_STATUS_SUCCESS;
3772+ u16 buf_len = 0;
3773+ int buf_block_len;
3774+ int blksz;
3775+ struct sk_buff *skb = NULL;
3776+ u16 type;
3777+ u8 *payload = NULL;
3778+ struct sdio_mmc_card *card = priv->uap_dev.card;
3779+
3780+ ENTER();
3781+
3782+ if (!card || !card->func) {
3783+ PRINTM(ERROR, "card or function is NULL!\n");
3784+ ret = UAP_STATUS_FAILURE;
3785+ goto exit;
3786+ }
3787+
3788+ /* Read the length of data to be transferred */
3789+ ret = sd_read_rx_len(priv, &buf_len);
3790+ if (ret < 0) {
3791+ PRINTM(ERROR, "card_to_host, read scratch reg failed\n");
3792+ ret = UAP_STATUS_FAILURE;
3793+ goto exit;
3794+ }
3795+
3796+ /* Allocate buffer */
3797+ blksz = SD_BLOCK_SIZE;
3798+ buf_block_len = (buf_len + blksz - 1) / blksz;
3799+ if (buf_len <= INTF_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
3800+ PRINTM(ERROR, "card_to_host, invalid packet length: %d\n", buf_len);
3801+ ret = UAP_STATUS_FAILURE;
3802+ goto exit;
3803+ }
3804+#ifdef PXA3XX_DMA_ALIGN
3805+ skb = dev_alloc_skb(buf_block_len * blksz + PXA3XX_DMA_ALIGNMENT);
3806+#else
3807+ skb = dev_alloc_skb(buf_block_len * blksz);
3808+#endif
3809+ if (skb == NULL) {
3810+ PRINTM(WARN, "No free skb\n");
3811+ goto exit;
3812+ }
3813+#ifdef PXA3XX_DMA_ALIGN
3814+ if ((u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)) {
3815+ skb_put(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
3816+ skb_pull(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
3817+ }
3818+#endif /* PXA3XX_DMA_ALIGN */
3819+
3820+ payload = skb->tail;
3821+ ret = sdio_readsb(card->func, payload, priv->uap_dev.ioport,
3822+ buf_block_len * blksz);
3823+ if (ret < 0) {
3824+ PRINTM(ERROR, "card_to_host, read iomem failed: %d\n", ret);
3825+ ret = UAP_STATUS_FAILURE;
3826+ goto exit;
3827+ }
3828+ HEXDUMP("SDIO Blk Rd", payload, blksz * buf_block_len);
3829+ /*
3830+ * This is SDIO specific header
3831+ * u16 length,
3832+ * u16 type (MV_TYPE_DAT = 0, MV_TYPE_CMD = 1, MV_TYPE_EVENT = 3)
3833+ */
3834+ buf_len = uap_le16_to_cpu(*(u16 *) & payload[0]);
3835+ type = uap_le16_to_cpu(*(u16 *) & payload[2]);
3836+ switch (type) {
3837+ case MV_TYPE_EVENT:
3838+ skb_put(skb, buf_len);
3839+ skb_pull(skb, INTF_HEADER_LEN);
3840+ uap_process_event(priv, skb->data, skb->len);
3841+ kfree_skb(skb);
3842+ skb = NULL;
3843+ break;
3844+ case MV_TYPE_CMD:
3845+ skb_put(skb, buf_len);
3846+ skb_pull(skb, INTF_HEADER_LEN);
3847+ priv->adapter->cmd_pending = FALSE;
3848+ if (priv->adapter->cmd_wait_option ==
3849+ HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM) {
3850+ priv->adapter->cmd_wait_option = FALSE;
3851+ uap_process_sleep_confirm_resp(priv, skb->data, skb->len);
3852+ } else if (priv->adapter->cmd_wait_option) {
3853+ memcpy(priv->adapter->CmdBuf, skb->data, skb->len);
3854+ priv->adapter->CmdSize = skb->len;
3855+ priv->adapter->cmd_wait_option = FALSE;
3856+ priv->adapter->CmdWaitQWoken = TRUE;
3857+ wake_up_interruptible(&priv->adapter->cmdwait_q);
3858+ }
3859+ kfree_skb(skb);
3860+ skb = NULL;
3861+ break;
3862+ case MV_TYPE_DAT:
3863+ skb_put(skb, buf_len);
3864+ skb_pull(skb, INTF_HEADER_LEN);
3865+ uap_process_rx_packet(priv, skb);
3866+ break;
3867+ default:
3868+ priv->stats.rx_errors++;
3869+ priv->stats.rx_dropped++;
3870+ /* Driver specified event and command resp should be handle here */
3871+ PRINTM(INFO, "Unknown PKT type:%d\n", type);
3872+ kfree_skb(skb);
3873+ skb = NULL;
3874+ break;
3875+ }
3876+ exit:
3877+ if (ret) {
3878+ if (skb)
3879+ kfree_skb(skb);
3880+ }
3881+
3882+ LEAVE();
3883+ return ret;
3884+}
3885+
3886+/**
3887+ * @brief This function enables the host interrupts mask
3888+ *
3889+ * @param priv A pointer to uap_private structure
3890+ * @param mask the interrupt mask
3891+ * @return UAP_STATUS_SUCCESS
3892+ */
3893+static int
3894+enable_host_int_mask(uap_private * priv, u8 mask)
3895+{
3896+ int ret = UAP_STATUS_SUCCESS;
3897+
3898+ ENTER();
3899+
3900+ /* Simply write the mask to the register */
3901+ ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, mask);
3902+
3903+ if (ret) {
3904+ PRINTM(WARN, "Unable to enable the host interrupt!\n");
3905+ ret = UAP_STATUS_FAILURE;
3906+ }
3907+
3908+ LEAVE();
3909+ return ret;
3910+}
3911+
3912+/** @brief This function disables the host interrupts mask.
3913+ *
3914+ * @param priv A pointer to uap_private structure
3915+ * @param mask the interrupt mask
3916+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
3917+ */
3918+static int
3919+disable_host_int_mask(uap_private * priv, u8 mask)
3920+{
3921+ int ret = UAP_STATUS_SUCCESS;
3922+ u8 host_int_mask;
3923+
3924+ ENTER();
3925+
3926+ /* Read back the host_int_mask register */
3927+ ret = sbi_read_ioreg(priv, HOST_INT_MASK_REG, &host_int_mask);
3928+ if (ret) {
3929+ ret = UAP_STATUS_FAILURE;
3930+ goto done;
3931+ }
3932+
3933+ /* Update with the mask and write back to the register */
3934+ host_int_mask &= ~mask;
3935+ ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, host_int_mask);
3936+ if (ret < 0) {
3937+ PRINTM(WARN, "Unable to diable the host interrupt!\n");
3938+ ret = UAP_STATUS_FAILURE;
3939+ goto done;
3940+ }
3941+
3942+ done:
3943+ LEAVE();
3944+ return ret;
3945+}
3946+
3947+/********************************************************
3948+ Global Functions
3949+********************************************************/
3950+
3951+/**
3952+ * @brief This function handles the interrupt.
3953+ *
3954+ * @param func A pointer to sdio_func structure.
3955+ * @return n/a
3956+ */
3957+static void
3958+sbi_interrupt(struct sdio_func *func)
3959+{
3960+ struct sdio_mmc_card *card;
3961+ uap_private *priv;
3962+ u8 ireg = 0;
3963+ int ret = UAP_STATUS_SUCCESS;
3964+
3965+ ENTER();
3966+
3967+ card = sdio_get_drvdata(func);
3968+ if (!card || !card->priv) {
3969+ PRINTM(MSG, "%s: sbi_interrupt(%p) card or priv is NULL, card=%p\n",
3970+ __FUNCTION__, func, card);
3971+ LEAVE();
3972+ return;
3973+ }
3974+ priv = card->priv;
3975+#ifdef FW_WAKEUP_TIME
3976+ if ((priv->adapter->wt_pwrup_sending != 0L) &&
3977+ (priv->adapter->wt_int == 0L))
3978+ priv->adapter->wt_int = get_utimeofday();
3979+#endif
3980+
3981+ ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
3982+ if (ret) {
3983+ PRINTM(WARN, "sdio_read_ioreg: read int status register failed\n");
3984+ goto done;
3985+ }
3986+ if (ireg != 0) {
3987+ /*
3988+ * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
3989+ * Clear the interrupt status register and re-enable the interrupt
3990+ */
3991+ PRINTM(INFO, "sdio_ireg = 0x%x\n", ireg);
3992+ sdio_writeb(card->func,
3993+ ~(ireg) & (DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS),
3994+ HOST_INTSTATUS_REG, &ret);
3995+ if (ret) {
3996+ PRINTM(WARN,
3997+ "sdio_write_ioreg: clear int status register failed\n");
3998+ goto done;
3999+ }
4000+ }
4001+ OS_INT_DISABLE;
4002+ sd_ireg |= ireg;
4003+ OS_INT_RESTORE;
4004+
4005+ uap_interrupt(priv);
4006+ done:
4007+ LEAVE();
4008+}
4009+
4010+/**
4011+ * @brief This function probe the card
4012+ *
4013+ * @param func A pointer to sdio_func structure
4014+ * @param id A pointer to structure sd_device_id
4015+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4016+ */
4017+static int
4018+uap_probe(struct sdio_func *func, const struct sdio_device_id *id)
4019+{
4020+ int ret = UAP_STATUS_FAILURE;
4021+ struct sdio_mmc_card *card = NULL;
4022+
4023+ ENTER();
4024+
4025+ PRINTM(MSG, "%s: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
4026+ __FUNCTION__, func->vendor, func->device, func->class, func->num);
4027+
4028+ card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
4029+ if (!card) {
4030+ ret = -ENOMEM;
4031+ goto done;
4032+ }
4033+
4034+ card->func = func;
4035+
4036+ if (!uap_add_card(card)) {
4037+ PRINTM(ERROR, "%s: uap_add_callback failed\n", __FUNCTION__);
4038+ kfree(card);
4039+ ret = UAP_STATUS_FAILURE;
4040+ goto done;
4041+ }
4042+
4043+ ret = UAP_STATUS_SUCCESS;
4044+
4045+ done:
4046+ LEAVE();
4047+ return ret;
4048+}
4049+
4050+/**
4051+ * @brief This function removes the card
4052+ *
4053+ * @param func A pointer to sdio_func structure
4054+ * @return N/A
4055+ */
4056+static void
4057+uap_remove(struct sdio_func *func)
4058+{
4059+ struct sdio_mmc_card *card;
4060+
4061+ ENTER();
4062+
4063+ if (func) {
4064+ card = sdio_get_drvdata(func);
4065+ if (card) {
4066+ uap_remove_card(card);
4067+ kfree(card);
4068+ }
4069+ }
4070+
4071+ LEAVE();
4072+}
4073+
4074+#ifdef CONFIG_PM
4075+/**
4076+ * @brief This function handles client driver suspend
4077+ *
4078+ * @param func A pointer to sdio_func structure
4079+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4080+ */
4081+int
4082+uap_suspend(struct sdio_func *func)
4083+{
4084+ ENTER();
4085+ LEAVE();
4086+ return 0;
4087+}
4088+
4089+/**
4090+ * @brief This function handles client driver resume
4091+ *
4092+ * @param func A pointer to sdio_func structure
4093+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4094+ */
4095+int
4096+uap_resume(struct sdio_func *func)
4097+{
4098+ ENTER();
4099+ LEAVE();
4100+ return 0;
4101+}
4102+#endif
4103+
4104+/** Device ID for SD8688 */
4105+#define SD_DEVICE_ID_8688_UAP 0x9104
4106+/** UAP IDs */
4107+static const struct sdio_device_id uap_ids[] = {
4108+ {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SD_DEVICE_ID_8688_UAP)},
4109+ {},
4110+};
4111+
4112+MODULE_DEVICE_TABLE(sdio, uap_ids);
4113+
4114+static struct sdio_driver uap_sdio = {
4115+ .name = "uap_sdio",
4116+ .id_table = uap_ids,
4117+ .probe = uap_probe,
4118+ .remove = uap_remove,
4119+#ifdef CONFIG_PM
4120+/* .suspend = uap_suspend, */
4121+/* .resume = uap_resume, */
4122+#endif
4123+
4124+};
4125+
4126+/**
4127+ * @brief This function registers the IF module in bus driver.
4128+ *
4129+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4130+ */
4131+int __init
4132+sbi_register()
4133+{
4134+ int ret = UAP_STATUS_SUCCESS;
4135+
4136+ ENTER();
4137+
4138+ /* SDIO Driver Registration */
4139+ if (sdio_register_driver(&uap_sdio) != 0) {
4140+ PRINTM(FATAL, "SDIO Driver Registration Failed \n");
4141+ ret = UAP_STATUS_FAILURE;
4142+ }
4143+
4144+ LEAVE();
4145+ return ret;
4146+}
4147+
4148+/**
4149+ * @brief This function de-registers the IF module in bus driver.
4150+ *
4151+ * @return n/a
4152+ */
4153+void __exit
4154+sbi_unregister(void)
4155+{
4156+ ENTER();
4157+
4158+ /* SDIO Driver Unregistration */
4159+ sdio_unregister_driver(&uap_sdio);
4160+
4161+ LEAVE();
4162+}
4163+
4164+/**
4165+ * @brief This function checks the interrupt status and handle it accordingly.
4166+ *
4167+ * @param priv A pointer to uap_private structure
4168+ * @param ireg A pointer to variable that keeps returned value
4169+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4170+ */
4171+int
4172+sbi_get_int_status(uap_private * priv, u8 * ireg)
4173+{
4174+ int ret = UAP_STATUS_SUCCESS;
4175+ u8 sdio_ireg = 0;
4176+ struct sdio_mmc_card *card = priv->uap_dev.card;
4177+
4178+ ENTER();
4179+
4180+ *ireg = 0;
4181+ OS_INT_DISABLE;
4182+ sdio_ireg = sd_ireg;
4183+ sd_ireg = 0;
4184+ OS_INT_RESTORE;
4185+
4186+ sdio_claim_host(card->func);
4187+
4188+ if (sdio_ireg & DN_LD_HOST_INT_STATUS) { /* tx_done INT */
4189+ if (!priv->uap_dev.cmd_sent) { /* tx_done already received */
4190+ PRINTM(INFO,
4191+ "warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n",
4192+ priv->uap_dev.cmd_sent, sdio_ireg);
4193+ } else {
4194+ priv->uap_dev.cmd_sent = FALSE;
4195+ priv->uap_dev.data_sent = FALSE;
4196+ if ( (priv->uap_dev.netdev->reg_state == NETREG_REGISTERED) && (skb_queue_len(&priv->adapter->tx_queue) < TX_LOW_WATERMARK)) {
4197+ os_start_queue(priv);
4198+ }
4199+ }
4200+ }
4201+ if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
4202+ sd_card_to_host(priv);
4203+ }
4204+
4205+ *ireg = sdio_ireg;
4206+ ret = UAP_STATUS_SUCCESS;
4207+ sdio_release_host(card->func);
4208+
4209+ LEAVE();
4210+ return ret;
4211+}
4212+
4213+/**
4214+ * @brief This function disables the host interrupts.
4215+ *
4216+ * @param priv A pointer to uap_private structure
4217+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4218+ */
4219+int
4220+sbi_disable_host_int(uap_private * priv)
4221+{
4222+ struct sdio_mmc_card *card = priv->uap_dev.card;
4223+ int ret;
4224+
4225+ ENTER();
4226+
4227+ sdio_claim_host(card->func);
4228+ ret = disable_host_int_mask(priv, HIM_DISABLE);
4229+ sdio_release_host(card->func);
4230+
4231+ LEAVE();
4232+ return ret;
4233+}
4234+
4235+/**
4236+ * @brief This function enables the host interrupts.
4237+ *
4238+ * @param priv A pointer to uap_private structure
4239+ * @return UAP_STATUS_SUCCESS
4240+ */
4241+int
4242+sbi_enable_host_int(uap_private * priv)
4243+{
4244+ struct sdio_mmc_card *card = priv->uap_dev.card;
4245+ int ret;
4246+
4247+ ENTER();
4248+
4249+ sdio_claim_host(card->func);
4250+ ret = enable_host_int_mask(priv, HIM_ENABLE);
4251+ sdio_release_host(card->func);
4252+
4253+ LEAVE();
4254+ return ret;
4255+}
4256+
4257+/**
4258+ * @brief This function de-registers the device.
4259+ *
4260+ * @param priv A pointer to uap_private structure
4261+ * @return UAP_STATUS_SUCCESS
4262+ */
4263+int
4264+sbi_unregister_dev(uap_private * priv)
4265+{
4266+ struct sdio_mmc_card *card = priv->uap_dev.card;
4267+
4268+ ENTER();
4269+
4270+ if (!card || !card->func) {
4271+ PRINTM(ERROR, "Error: card or function is NULL!\n");
4272+ goto done;
4273+ }
4274+
4275+ sdio_claim_host(card->func);
4276+ sdio_release_irq(card->func);
4277+ sdio_disable_func(card->func);
4278+ sdio_release_host(card->func);
4279+
4280+ sdio_set_drvdata(card->func, NULL);
4281+
4282+ done:
4283+ LEAVE();
4284+ return UAP_STATUS_SUCCESS;
4285+}
4286+
4287+/**
4288+ * @brief This function registers the device.
4289+ *
4290+ * @param priv A pointer to uap_private structure
4291+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4292+ */
4293+int
4294+sbi_register_dev(uap_private * priv)
4295+{
4296+ int ret = UAP_STATUS_FAILURE;
4297+ u8 reg;
4298+ struct sdio_mmc_card *card = priv->uap_dev.card;
4299+ struct sdio_func *func;
4300+
4301+ ENTER();
4302+
4303+ if (!card || !card->func) {
4304+ PRINTM(ERROR, "Error: card or function is NULL!\n");
4305+ goto done;
4306+ }
4307+
4308+ func = card->func;
4309+
4310+ /* Initialize the private structure */
4311+ priv->uap_dev.ioport = 0;
4312+
4313+ sdio_claim_host(func);
4314+
4315+ ret = sdio_enable_func(func);
4316+ if (ret) {
4317+ PRINTM(FATAL, "sdio_enable_func() failed: ret=%d\n", ret);
4318+ goto release_host;
4319+ }
4320+
4321+ ret = sdio_claim_irq(func, sbi_interrupt);
4322+ if (ret) {
4323+ PRINTM(FATAL, "sdio_claim_irq failed: ret=%d\n", ret);
4324+ goto disable_func;
4325+ }
4326+
4327+ /* Read the IO port */
4328+ ret = sbi_read_ioreg(priv, IO_PORT_0_REG, &reg);
4329+ if (ret)
4330+ goto release_irq;
4331+ else
4332+ priv->uap_dev.ioport |= reg;
4333+
4334+ ret = sbi_read_ioreg(priv, IO_PORT_1_REG, &reg);
4335+ if (ret)
4336+ goto release_irq;
4337+ else
4338+ priv->uap_dev.ioport |= (reg << 8);
4339+
4340+ ret = sbi_read_ioreg(priv, IO_PORT_2_REG, &reg);
4341+ if (ret)
4342+ goto release_irq;
4343+ else
4344+ priv->uap_dev.ioport |= (reg << 16);
4345+
4346+ PRINTM(INFO, "SDIO FUNC #%d IO port: 0x%x\n", func->num,
4347+ priv->uap_dev.ioport);
4348+
4349+ ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
4350+ if (ret) {
4351+ PRINTM(ERROR, "%s: cannot set SDIO block size\n", __FUNCTION__);
4352+ ret = UAP_STATUS_FAILURE;
4353+ goto release_irq;
4354+ }
4355+ priv->hotplug_device = &func->dev;
4356+
4357+ if (helper_name == NULL) {
4358+ helper_name = DEFAULT_HELPER_NAME;
4359+ }
4360+ if (fw_name == NULL) {
4361+ fw_name = DEFAULT_FW_NAME;
4362+ }
4363+ sdio_release_host(func);
4364+
4365+ sdio_set_drvdata(func, card);
4366+
4367+ ret = UAP_STATUS_SUCCESS;
4368+ goto done;
4369+
4370+ release_irq:
4371+ sdio_release_irq(func);
4372+ disable_func:
4373+ sdio_disable_func(func);
4374+ release_host:
4375+ sdio_release_host(func);
4376+
4377+ done:
4378+ LEAVE();
4379+ return ret;
4380+}
4381+
4382+/**
4383+ * @brief This function sends data to the card.
4384+ *
4385+ * @param priv A pointer to uap_private structure
4386+ * @param payload A pointer to the data/cmd buffer
4387+ * @param nb the length of data/cmd
4388+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4389+ */
4390+int
4391+sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb)
4392+{
4393+ struct sdio_mmc_card *card = priv->uap_dev.card;
4394+ int ret = UAP_STATUS_SUCCESS;
4395+ int buf_block_len;
4396+ int blksz;
4397+ int i = 0;
4398+ u8 *buf = NULL;
4399+#ifdef PXA3XX_DMA_ALIGN
4400+ void *tmpbuf = NULL;
4401+ int tmpbufsz;
4402+#endif
4403+
4404+ ENTER();
4405+
4406+ if (!card || !card->func) {
4407+ PRINTM(ERROR, "card or function is NULL!\n");
4408+ LEAVE();
4409+ return UAP_STATUS_FAILURE;
4410+ }
4411+ buf = payload;
4412+#ifdef PXA3XX_DMA_ALIGN
4413+ if ((u32) payload & (PXA3XX_DMA_ALIGNMENT - 1)) {
4414+ tmpbufsz = ALIGN_SZ(nb, PXA3XX_DMA_ALIGNMENT);
4415+ tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL);
4416+ memset(tmpbuf, 0, tmpbufsz);
4417+ /* Ensure 8-byte aligned CMD buffer */
4418+ buf = (u8 *) ALIGN_ADDR(tmpbuf, PXA3XX_DMA_ALIGNMENT);
4419+ memcpy(buf, payload, nb);
4420+ }
4421+#endif
4422+ /* Allocate buffer and copy payload */
4423+ blksz = SD_BLOCK_SIZE;
4424+ buf_block_len = (nb + blksz - 1) / blksz;
4425+ sdio_claim_host(card->func);
4426+#define MAX_WRITE_IOMEM_RETRY 2
4427+ priv->uap_dev.cmd_sent = TRUE;
4428+ priv->uap_dev.data_sent = TRUE;
4429+ do {
4430+ /* Transfer data to card */
4431+ ret = sdio_writesb(card->func, priv->uap_dev.ioport, buf,
4432+ buf_block_len * blksz);
4433+ if (ret < 0) {
4434+ i++;
4435+ PRINTM(ERROR, "host_to_card, write iomem (%d) failed: %d\n", i,
4436+ ret);
4437+ ret = UAP_STATUS_FAILURE;
4438+ if (i > MAX_WRITE_IOMEM_RETRY)
4439+ goto exit;
4440+ } else {
4441+ HEXDUMP("SDIO Blk Wr", payload, nb);
4442+ }
4443+ } while (ret == UAP_STATUS_FAILURE);
4444+ exit:
4445+ sdio_release_host(card->func);
4446+#ifdef PXA3XX_DMA_ALIGN
4447+ if (tmpbuf)
4448+ kfree(tmpbuf);
4449+#endif
4450+ if (ret == UAP_STATUS_FAILURE) {
4451+ priv->uap_dev.cmd_sent = FALSE;
4452+ priv->uap_dev.data_sent = FALSE;
4453+ }
4454+ LEAVE();
4455+ return ret;
4456+}
4457+
4458+/**
4459+ * @brief This function reads CIS information.
4460+ *
4461+ * @param priv A pointer to uap_private structure
4462+ * @param cisinfo A pointer to CIS information output buffer
4463+ * @param cislen A pointer to length of CIS info output buffer
4464+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4465+ */
4466+#if 0
4467+static int
4468+sbi_get_cis_info(uap_private * priv, void *cisinfo, int *cislen)
4469+{
4470+#define CIS_PTR (0x8000)
4471+ struct sdio_mmc_card *card = priv->uap_dev.card;
4472+ unsigned int i, cis_ptr = CIS_PTR;
4473+ int ret = UAP_STATUS_FAILURE;
4474+
4475+ ENTER();
4476+
4477+ if (!card || !card->func) {
4478+ PRINTM(ERROR, "sbi_get_cis_info(): card or function is NULL!\n");
4479+ goto exit;
4480+ }
4481+#define MAX_SDIO_CIS_INFO_LEN (256)
4482+ if (!cisinfo || (*cislen < MAX_SDIO_CIS_INFO_LEN)) {
4483+ PRINTM(WARN, "ERROR! get_cis_info: insufficient buffer passed\n");
4484+ goto exit;
4485+ }
4486+
4487+ *cislen = MAX_SDIO_CIS_INFO_LEN;
4488+
4489+ sdio_claim_host(card->func);
4490+
4491+ PRINTM(INFO, "cis_ptr=%#x\n", cis_ptr);
4492+
4493+ /* Read the Tuple Data */
4494+ for (i = 0; i < *cislen; i++) {
4495+ ((unsigned char *) cisinfo)[i] =
4496+ sdio_readb(card->func, cis_ptr + i, &ret);
4497+ if (ret) {
4498+ PRINTM(WARN, "get_cis_info error: ret=%d\n", ret);
4499+ ret = UAP_STATUS_FAILURE;
4500+ goto done;
4501+ }
4502+ PRINTM(INFO, "cisinfo[%d]=%#x\n", i, ((unsigned char *) cisinfo)[i]);
4503+ }
4504+
4505+ done:
4506+ sdio_release_host(card->func);
4507+ exit:
4508+ LEAVE();
4509+ return ret;
4510+}
4511+#endif
4512+/**
4513+ * @brief This function downloads helper image to the card.
4514+ *
4515+ * @param priv A pointer to uap_private structure
4516+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4517+ */
4518+int
4519+sbi_prog_helper(uap_private * priv)
4520+{
4521+ struct sdio_mmc_card *card = priv->uap_dev.card;
4522+ u8 *helper = NULL;
4523+ int helperlen;
4524+ int ret = UAP_STATUS_SUCCESS;
4525+ void *tmphlprbuf = NULL;
4526+ int tmphlprbufsz;
4527+ u8 *hlprbuf;
4528+ int hlprblknow;
4529+ u32 tx_len;
4530+#ifdef FW_DOWNLOAD_SPEED
4531+ u32 tv1, tv2;
4532+#endif
4533+
4534+ ENTER();
4535+
4536+ if (!card || !card->func) {
4537+ PRINTM(ERROR, "sbi_prog_helper(): card or function is NULL!\n");
4538+ goto done;
4539+ }
4540+
4541+ if (priv->fw_helper) {
4542+ helper = (u8 *) priv->fw_helper->data;
4543+ helperlen = priv->fw_helper->size;
4544+ } else {
4545+ PRINTM(MSG, "No helper image found! Terminating download.\n");
4546+ LEAVE();
4547+ return UAP_STATUS_FAILURE;
4548+ }
4549+
4550+ PRINTM(INFO, "Downloading helper image (%d bytes), block size %d bytes\n",
4551+ helperlen, SD_BLOCK_SIZE);
4552+
4553+#ifdef FW_DOWNLOAD_SPEED
4554+ tv1 = get_utimeofday();
4555+#endif
4556+
4557+#ifdef PXA3XX_DMA_ALIGN
4558+ tmphlprbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT);
4559+#else /* !PXA3XX_DMA_ALIGN */
4560+ tmphlprbufsz = UAP_UPLD_SIZE;
4561+#endif /* !PXA3XX_DMA_ALIGN */
4562+ tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL);
4563+ if (!tmphlprbuf) {
4564+ PRINTM(ERROR,
4565+ "Unable to allocate buffer for helper. Terminating download\n");
4566+ ret = UAP_STATUS_FAILURE;
4567+ goto done;
4568+ }
4569+ memset(tmphlprbuf, 0, tmphlprbufsz);
4570+#ifdef PXA3XX_DMA_ALIGN
4571+ hlprbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, PXA3XX_DMA_ALIGNMENT);
4572+#else /* !PXA3XX_DMA_ALIGN */
4573+ hlprbuf = (u8 *) tmphlprbuf;
4574+#endif /* !PXA3XX_DMA_ALIGN */
4575+
4576+ sdio_claim_host(card->func);
4577+
4578+ /* Perform helper data transfer */
4579+ tx_len = (FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE) - INTF_HEADER_LEN;
4580+ hlprblknow = 0;
4581+ do {
4582+ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */
4583+ ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
4584+ if (ret < 0) {
4585+ PRINTM(FATAL, "Helper download poll status timeout @ %d\n",
4586+ hlprblknow);
4587+ goto done;
4588+ }
4589+
4590+ /* More data? */
4591+ if (hlprblknow >= helperlen)
4592+ break;
4593+
4594+ /* Set blocksize to transfer - checking for last block */
4595+ if (helperlen - hlprblknow < tx_len)
4596+ tx_len = helperlen - hlprblknow;
4597+
4598+ /* Set length to the 4-byte header */
4599+ *(u32 *) hlprbuf = uap_cpu_to_le32(tx_len);
4600+
4601+ /* Copy payload to buffer */
4602+ memcpy(&hlprbuf[INTF_HEADER_LEN], &helper[hlprblknow], tx_len);
4603+
4604+ PRINTM(INFO, ".");
4605+
4606+ /* Send data */
4607+ ret = sdio_writesb(card->func, priv->uap_dev.ioport,
4608+ hlprbuf, FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE);
4609+
4610+ if (ret < 0) {
4611+ PRINTM(FATAL, "IO error during helper download @ %d\n", hlprblknow);
4612+ goto done;
4613+ }
4614+
4615+ hlprblknow += tx_len;
4616+ } while (TRUE);
4617+
4618+#ifdef FW_DOWNLOAD_SPEED
4619+ tv2 = get_utimeofday();
4620+ PRINTM(INFO, "helper: %ld.%03ld.%03ld ", tv1 / 1000000,
4621+ (tv1 % 1000000) / 1000, tv1 % 1000);
4622+ PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, (tv2 % 1000000) / 1000,
4623+ tv2 % 1000);
4624+ tv2 -= tv1;
4625+ PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, (tv2 % 1000000) / 1000,
4626+ tv2 % 1000);
4627+#endif
4628+
4629+ /* Write last EOF data */
4630+ PRINTM(INFO, "\nTransferring helper image EOF block\n");
4631+ memset(hlprbuf, 0x0, SD_BLOCK_SIZE);
4632+ ret = sdio_writesb(card->func, priv->uap_dev.ioport,
4633+ hlprbuf, SD_BLOCK_SIZE);
4634+
4635+ if (ret < 0) {
4636+ PRINTM(FATAL, "IO error in writing helper image EOF block\n");
4637+ goto done;
4638+ }
4639+
4640+ ret = UAP_STATUS_SUCCESS;
4641+
4642+ done:
4643+ sdio_release_host(card->func);
4644+ if (tmphlprbuf)
4645+ kfree(tmphlprbuf);
4646+
4647+ LEAVE();
4648+ return ret;
4649+}
4650+
4651+/**
4652+ * @brief This function downloads firmware image to the card.
4653+ *
4654+ * @param priv A pointer to uap_private structure
4655+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4656+ */
4657+int
4658+sbi_prog_fw_w_helper(uap_private * priv)
4659+{
4660+ struct sdio_mmc_card *card = priv->uap_dev.card;
4661+ u8 *firmware = NULL;
4662+ int firmwarelen;
4663+ u8 base0;
4664+ u8 base1;
4665+ int ret = UAP_STATUS_SUCCESS;
4666+ int offset;
4667+ void *tmpfwbuf = NULL;
4668+ int tmpfwbufsz;
4669+ u8 *fwbuf;
4670+ u16 len;
4671+ int txlen = 0;
4672+ int tx_blocks = 0;
4673+ int i = 0;
4674+ int tries = 0;
4675+#ifdef FW_DOWNLOAD_SPEED
4676+ u32 tv1, tv2;
4677+#endif
4678+
4679+ ENTER();
4680+
4681+ if (!card || !card->func) {
4682+ PRINTM(ERROR, "sbi_prog_fw_w_helper(): card or function is NULL!\n");
4683+ goto done;
4684+ }
4685+
4686+ if (priv->firmware) {
4687+ firmware = (u8 *) priv->firmware->data;
4688+ firmwarelen = priv->firmware->size;
4689+ } else {
4690+ PRINTM(MSG, "No firmware image found! Terminating download.\n");
4691+ LEAVE();
4692+ return UAP_STATUS_FAILURE;
4693+ }
4694+
4695+ PRINTM(INFO, "Downloading FW image (%d bytes)\n", firmwarelen);
4696+
4697+#ifdef FW_DOWNLOAD_SPEED
4698+ tv1 = get_utimeofday();
4699+#endif
4700+
4701+#ifdef PXA3XX_DMA_ALIGN
4702+ tmpfwbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT);
4703+#else /* PXA3XX_DMA_ALIGN */
4704+ tmpfwbufsz = UAP_UPLD_SIZE;
4705+#endif /* PXA3XX_DMA_ALIGN */
4706+ tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL);
4707+ if (!tmpfwbuf) {
4708+ PRINTM(ERROR,
4709+ "Unable to allocate buffer for firmware. Terminating download.\n");
4710+ ret = UAP_STATUS_FAILURE;
4711+ goto done;
4712+ }
4713+ memset(tmpfwbuf, 0, tmpfwbufsz);
4714+#ifdef PXA3XX_DMA_ALIGN
4715+ /* Ensure 8-byte aligned firmware buffer */
4716+ fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, PXA3XX_DMA_ALIGNMENT);
4717+#else /* PXA3XX_DMA_ALIGN */
4718+ fwbuf = (u8 *) tmpfwbuf;
4719+#endif /* PXA3XX_DMA_ALIGN */
4720+
4721+ sdio_claim_host(card->func);
4722+
4723+ /* Perform firmware data transfer */
4724+ offset = 0;
4725+ do {
4726+ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */
4727+ ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
4728+ if (ret < 0) {
4729+ PRINTM(FATAL, "FW download with helper poll status timeout @ %d\n",
4730+ offset);
4731+ goto done;
4732+ }
4733+
4734+ /* More data? */
4735+ if (offset >= firmwarelen)
4736+ break;
4737+
4738+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
4739+ if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_0, &base0)) < 0) {
4740+ PRINTM(WARN, "Dev BASE0 register read failed:"
4741+ " base0=0x%04X(%d). Terminating download.\n", base0,
4742+ base0);
4743+ ret = UAP_STATUS_FAILURE;
4744+ goto done;
4745+ }
4746+ if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_1, &base1)) < 0) {
4747+ PRINTM(WARN, "Dev BASE1 register read failed:"
4748+ " base1=0x%04X(%d). Terminating download.\n", base1,
4749+ base1);
4750+ ret = UAP_STATUS_FAILURE;
4751+ goto done;
4752+ }
4753+ len = (((u16) base1) << 8) | base0;
4754+
4755+ /* For SD8688 wait until the length is not 0, 1 or 2 before
4756+ downloading the first FW block, since BOOT code writes the
4757+ register to indicate the helper/FW download winner, the value
4758+ could be 1 or 2 (Func1 or Func2). */
4759+ if ((len && offset) || (len > 2))
4760+ break;
4761+ udelay(10);
4762+ }
4763+
4764+ if (len == 0)
4765+ break;
4766+ else if (len > UAP_UPLD_SIZE) {
4767+ PRINTM(FATAL, "FW download failure @ %d, invalid length %d\n",
4768+ offset, len);
4769+ ret = UAP_STATUS_FAILURE;
4770+ goto done;
4771+ }
4772+
4773+ txlen = len;
4774+
4775+ if (len & BIT(0)) {
4776+ i++;
4777+ if (i > MAX_WRITE_IOMEM_RETRY) {
4778+ PRINTM(FATAL,
4779+ "FW download failure @ %d, over max retry count\n",
4780+ offset);
4781+ ret = UAP_STATUS_FAILURE;
4782+ goto done;
4783+ }
4784+ PRINTM(ERROR, "FW CRC error indicated by the helper:"
4785+ " len = 0x%04X, txlen = %d\n", len, txlen);
4786+ len &= ~BIT(0);
4787+ /* Setting this to 0 to resend from same offset */
4788+ txlen = 0;
4789+ } else {
4790+ i = 0;
4791+
4792+ /* Set blocksize to transfer - checking for last block */
4793+ if (firmwarelen - offset < txlen) {
4794+ txlen = firmwarelen - offset;
4795+ }
4796+ PRINTM(INFO, ".");
4797+
4798+ tx_blocks = (txlen + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE;
4799+
4800+ /* Copy payload to buffer */
4801+ memcpy(fwbuf, &firmware[offset], txlen);
4802+ }
4803+
4804+ /* Send data */
4805+ ret = sdio_writesb(card->func, priv->uap_dev.ioport,
4806+ fwbuf, tx_blocks * SD_BLOCK_SIZE);
4807+
4808+ if (ret < 0) {
4809+ PRINTM(ERROR, "FW download, write iomem (%d) failed @ %d\n", i,
4810+ offset);
4811+ if (sbi_write_ioreg(priv, CONFIGURATION_REG, 0x04) < 0) {
4812+ PRINTM(ERROR, "write ioreg failed (CFG)\n");
4813+ }
4814+ }
4815+
4816+ offset += txlen;
4817+ } while (TRUE);
4818+
4819+ PRINTM(INFO, "\nFW download over, size %d bytes\n", offset);
4820+
4821+ ret = UAP_STATUS_SUCCESS;
4822+ done:
4823+#ifdef FW_DOWNLOAD_SPEED
4824+ tv2 = get_utimeofday();
4825+ PRINTM(INFO, "FW: %ld.%03ld.%03ld ", tv1 / 1000000,
4826+ (tv1 % 1000000) / 1000, tv1 % 1000);
4827+ PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000,
4828+ (tv2 % 1000000) / 1000, tv2 % 1000);
4829+ tv2 -= tv1;
4830+ PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000,
4831+ (tv2 % 1000000) / 1000, tv2 % 1000);
4832+#endif
4833+ sdio_release_host(card->func);
4834+ if (tmpfwbuf)
4835+ kfree(tmpfwbuf);
4836+
4837+ LEAVE();
4838+ return ret;
4839+}
4840+
4841+/**
4842+ * @brief This function checks if the firmware is ready to accept
4843+ * command or not.
4844+ *
4845+ * @param priv A pointer to uap_private structure
4846+ * @param pollnum Poll number
4847+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4848+ */
4849+int
4850+sbi_check_fw_status(uap_private * priv, int pollnum)
4851+{
4852+ struct sdio_mmc_card *card = priv->uap_dev.card;
4853+ int ret = UAP_STATUS_SUCCESS;
4854+ u16 firmwarestat;
4855+ int tries;
4856+
4857+ ENTER();
4858+
4859+ sdio_claim_host(card->func);
4860+
4861+ /* Wait for firmware initialization event */
4862+ for (tries = 0; tries < pollnum; tries++) {
4863+ if ((ret = sd_read_firmware_status(priv, &firmwarestat)) < 0)
4864+ continue;
4865+ if (firmwarestat == FIRMWARE_READY) {
4866+ ret = UAP_STATUS_SUCCESS;
4867+ break;
4868+ } else {
4869+ mdelay(10);
4870+ ret = UAP_STATUS_FAILURE;
4871+ }
4872+ }
4873+
4874+ if (ret < 0)
4875+ goto done;
4876+
4877+ ret = UAP_STATUS_SUCCESS;
4878+ sd_get_rx_unit(priv);
4879+
4880+ done:
4881+ sdio_release_host(card->func);
4882+
4883+ LEAVE();
4884+ return ret;
4885+}
4886+
4887+/**
4888+ * @brief This function set bus clock on/off
4889+ *
4890+ * @param priv A pointer to uap_private structure
4891+ * @param option TRUE--on , FALSE--off
4892+ * @return UAP_STATUS_SUCCESS
4893+ */
4894+#if 0
4895+static int
4896+sbi_set_bus_clock(uap_private * priv, u8 option)
4897+{
4898+ ENTER();
4899+ LEAVE();
4900+ return UAP_STATUS_SUCCESS;
4901+}
4902+#endif
4903+
4904+/**
4905+ * @brief This function wakeup firmware
4906+ *
4907+ * @param priv A pointer to uap_private structure
4908+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
4909+ */
4910+int
4911+sbi_wakeup_firmware(uap_private * priv)
4912+{
4913+ struct sdio_mmc_card *card = priv->uap_dev.card;
4914+ int ret = UAP_STATUS_SUCCESS;
4915+
4916+ ENTER();
4917+
4918+ if (!card || !card->func) {
4919+ PRINTM(ERROR, "card or function is NULL!\n");
4920+ LEAVE();
4921+ return UAP_STATUS_FAILURE;
4922+ }
4923+ sdio_claim_host(card->func);
4924+ sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
4925+ sdio_release_host(card->func);
4926+ LEAVE();
4927+ return ret;
4928+}
e9544fbe
AF
4929diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h
4930--- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h 1970-01-01 01:00:00.000000000 +0100
4931+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h 2012-07-31 14:23:04.000000000 +0200
9f44350f
AF
4932@@ -0,0 +1,136 @@
4933+/** @file uap_sdio_mmc.h
4934+ * @brief This file contains SDIO IF (interface) module
4935+ * related macros, enum, and structure.
4936+ *
4937+ * Copyright (C) 2007-2009, Marvell International Ltd.
4938+ *
4939+ * This software file (the "File") is distributed by Marvell International
4940+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
4941+ * (the "License"). You may use, redistribute and/or modify this File in
4942+ * accordance with the terms and conditions of the License, a copy of which
4943+ * is available along with the File in the gpl.txt file or by writing to
4944+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
4945+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
4946+ *
4947+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
4948+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
4949+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
4950+ * this warranty disclaimer.
4951+ *
4952+ */
4953+/****************************************************
4954+Change log:
4955+ 10/10/07: initial version
4956+****************************************************/
4957+
4958+#ifndef _UAP_SDIO_MMC_H
4959+#define _UAP_SDIO_MMC_H
4960+
4961+#include <linux/mmc/sdio.h>
4962+#include <linux/mmc/sdio_ids.h>
4963+#include <linux/mmc/sdio_func.h>
4964+#include <linux/mmc/card.h>
4965+
4966+#include "uap_headers.h"
4967+
4968+/** The number of times to try when waiting for downloaded firmware to
4969+ become active. (polling the scratch register). */
4970+#define MAX_FIRMWARE_POLL_TRIES 100
4971+
4972+/** Firmware ready */
4973+#define FIRMWARE_READY 0xfedc
4974+
4975+/** Number of firmware blocks to transfer */
4976+#define FIRMWARE_TRANSFER_NBLOCK 2
4977+
4978+/* Host Control Registers */
4979+/** Host Control Registers : I/O port 0 */
4980+#define IO_PORT_0_REG 0x00
4981+/** Host Control Registers : I/O port 1 */
4982+#define IO_PORT_1_REG 0x01
4983+/** Host Control Registers : I/O port 2 */
4984+#define IO_PORT_2_REG 0x02
4985+
4986+/** Host Control Registers : Configuration */
4987+#define CONFIGURATION_REG 0x03
4988+/** Host Control Registers : Host without Command 53 finish host */
4989+#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2)
4990+/** Host Control Registers : Host power up */
4991+#define HOST_POWER_UP (0x1U << 1)
4992+/** Host Control Registers : Host power down */
4993+#define HOST_POWER_DOWN (0x1U << 0)
4994+
4995+/** Host Control Registers : Host interrupt mask */
4996+#define HOST_INT_MASK_REG 0x04
4997+/** Host Control Registers : Upload host interrupt mask */
4998+#define UP_LD_HOST_INT_MASK (0x1U)
4999+/** Host Control Registers : Download host interrupt mask */
5000+#define DN_LD_HOST_INT_MASK (0x2U)
5001+/** Enable Host interrupt mask */
5002+#define HIM_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK)
5003+/** Disable Host interrupt mask */
5004+#define HIM_DISABLE 0xff
5005+
5006+/** Host Control Registers : Host interrupt status */
5007+#define HOST_INTSTATUS_REG 0x05
5008+/** Host Control Registers : Upload host interrupt status */
5009+#define UP_LD_HOST_INT_STATUS (0x1U)
5010+/** Host Control Registers : Download host interrupt status */
5011+#define DN_LD_HOST_INT_STATUS (0x2U)
5012+
5013+/** Host F1 read base 0 */
5014+#define HOST_F1_RD_BASE_0 0x10
5015+/** Host F1 read base 1 */
5016+#define HOST_F1_RD_BASE_1 0x11
5017+
5018+/** Card Control Registers : Card status register */
5019+#define CARD_STATUS_REG 0x20
5020+/** Card Control Registers : Card I/O ready */
5021+#define CARD_IO_READY (0x1U << 3)
5022+/** Card Control Registers : CIS card ready */
5023+#define CIS_CARD_RDY (0x1U << 2)
5024+/** Card Control Registers : Upload card ready */
5025+#define UP_LD_CARD_RDY (0x1U << 1)
5026+/** Card Control Registers : Download card ready */
5027+#define DN_LD_CARD_RDY (0x1U << 0)
5028+
5029+/** Card Control Registers : Card OCR 0 register */
5030+#define CARD_OCR_0_REG 0x34
5031+/** Card Control Registers : Card OCR 1 register */
5032+#define CARD_OCR_1_REG 0x35
5033+
5034+/** Firmware status 0 register */
5035+#define CARD_FW_STATUS0_REG 0x40
5036+/** Firmware status 1 register */
5037+#define CARD_FW_STATUS1_REG 0x41
5038+/** Rx length register */
5039+#define CARD_RX_LEN_REG 0x42
5040+/** Rx unit register */
5041+#define CARD_RX_UNIT_REG 0x43
5042+
5043+/** Chip Id Register 0 */
5044+#define CARD_CHIP_ID_0_REG 0x801c
5045+/** Chip Id Register 1 */
5046+#define CARD_CHIP_ID_1_REG 0x801d
5047+
5048+#ifdef PXA3XX_DMA_ALIGN
5049+/** DMA alignment value for PXA3XX platforms */
5050+#define PXA3XX_DMA_ALIGNMENT 8
5051+/** Macros for Data Alignment : size */
5052+#define ALIGN_SZ(p, a) \
5053+ (((p) + ((a) - 1)) & ~((a) - 1))
5054+
5055+/** Macros for Data Alignment : address */
5056+#define ALIGN_ADDR(p, a) \
5057+ ((((u32)(p)) + (((u32)(a)) - 1)) & ~(((u32)(a)) - 1))
5058+#endif /* PXA3XX_DMA_ALIGN */
5059+
5060+struct sdio_mmc_card
5061+{
5062+ /** sdio_func structure pointer */
5063+ struct sdio_func *func;
5064+ /** uap_private structure pointer */
5065+ uap_private *priv;
5066+};
5067+
5068+#endif /* _UAP_SDIO_MMC_H */
e9544fbe
AF
5069diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/Makefile compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/Makefile
5070--- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/Makefile 2012-07-05 03:48:01.000000000 +0200
5071+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/Makefile 2012-07-31 14:20:01.343608619 +0200
9f44350f
AF
5072@@ -22,6 +22,8 @@
5073
5074 obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/
5075
5076+obj-$(CONFIG_LIBERTAS_UAP) += libertas_uap/
5077+
5078 obj-$(CONFIG_ADM8211) += adm8211.o
5079
5080 obj-$(CONFIG_MWL8K) += mwl8k.o