aboutsummaryrefslogtreecommitdiffstats
diff options
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-24 09:50:16 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-24 09:50:16 -0700
commit4b54b72c5d696dae9276cdc16550a49cd1926067 (patch)
tree2fc9f1bdc34d1b048f6e8b4c0a795a43705fe93b
parent8a77a893e321c1fff214a542840be4f9ac03627b (diff)
downloadpatches-4b54b72c5d696dae9276cdc16550a49cd1926067.tar.gz
csr helper module
-rw-r--r--series1
-rw-r--r--staging-add-csr-wifi-os-helper-module.patch1651
2 files changed, 1652 insertions, 0 deletions
diff --git a/series b/series
index 01e0d098f5f137..94b385bfee5dfb 100644
--- a/series
+++ b/series
@@ -1,4 +1,5 @@
# My specific stuff, at the top to make it easier to work stuff below.
+staging-add-csr-wifi-os-helper-module.patch
time-don-t-inline-export_symbol-functions.patch
perf-turn-off-compiler-warnings-for-flex-and-bison-generated-files.patch
hfsplus-bugfixes.patch
diff --git a/staging-add-csr-wifi-os-helper-module.patch b/staging-add-csr-wifi-os-helper-module.patch
new file mode 100644
index 00000000000000..fe6cb7b2176008
--- /dev/null
+++ b/staging-add-csr-wifi-os-helper-module.patch
@@ -0,0 +1,1651 @@
+From 7d8f03379459cef5dd852503cecfff935d005abd Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Thu, 24 May 2012 09:47:38 -0700
+Subject: [PATCH] Staging: add CSR Wifi "os helper" module
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This module is used by the CSR wifi driver to "abstract" away the
+OS-specific parts of core functions. It will be eventually deleted, but
+for now is needed as the CSR driver relies on it.
+
+Cc: Mikko Virkkilä <mikko.virkkila@bluegiga.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
+index 97d412d..3cf7223 100644
+--- a/drivers/staging/Kconfig
++++ b/drivers/staging/Kconfig
+@@ -132,4 +132,6 @@ source "drivers/staging/ramster/Kconfig"
+
+ source "drivers/staging/ozwpan/Kconfig"
+
++source "drivers/staging/csr/Kconfig"
++
+ endif # STAGING
+diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
+index ffe7d44..845ee64 100644
+--- a/drivers/staging/Makefile
++++ b/drivers/staging/Makefile
+@@ -57,3 +57,4 @@ obj-$(CONFIG_ANDROID) += android/
+ obj-$(CONFIG_PHONE) += telephony/
+ obj-$(CONFIG_RAMSTER) += ramster/
+ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/
++obj-$(CONFIG_CSR_WIFI) += csr/
+diff --git a/drivers/staging/csr/Kconfig b/drivers/staging/csr/Kconfig
+new file mode 100644
+index 0000000..5d7b800
+--- /dev/null
++++ b/drivers/staging/csr/Kconfig
+@@ -0,0 +1,7 @@
++config CSR_WIFI
++ tristate "CSR wireless driver"
++ depends on PCI
++ help
++ Driver for the CSR wireless SDIO device.
++
++ If unsure, select N.
+diff --git a/drivers/staging/csr/Makefile b/drivers/staging/csr/Makefile
+new file mode 100644
+index 0000000..b9ba3b3
+--- /dev/null
++++ b/drivers/staging/csr/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_CSR_WIFI) += oska/
+diff --git a/drivers/staging/csr/oska/Makefile b/drivers/staging/csr/oska/Makefile
+new file mode 100644
+index 0000000..3a0b648
+--- /dev/null
++++ b/drivers/staging/csr/oska/Makefile
+@@ -0,0 +1,12 @@
++obj-$(CONFIG_CSR_WIFI) := csr_oska.o
++
++csr_oska-y := \
++ list.o \
++ refcount.o \
++ compat.o \
++ event.o \
++ oska_module.o \
++ print.o \
++ thread.o \
++ timer.o
++
+diff --git a/drivers/staging/csr/oska/all.h b/drivers/staging/csr/oska/all.h
+new file mode 100644
+index 0000000..5fe8583
+--- /dev/null
++++ b/drivers/staging/csr/oska/all.h
+@@ -0,0 +1,61 @@
++/*
++ * Operating system kernel abstraction -- all functions
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_ALL_H
++#define __OSKA_ALL_H
++
++/**
++ * @mainpage Operating System Kernel Abstraction
++ *
++ * @section intro Introduction
++ *
++ * The Operating System Kernel Abstraction (oska) is a software
++ * package providing an abstraction for various operating system
++ * kernel facilities for use by device drivers and other OS kernel
++ * software (e.g., SDIO stacks). Oska is modularized and intended to
++ * be a lightweight wrapper around an OSes interfaces.
++ *
++ * @section modules Modules
++ *
++ * Oska is organized into the modules, each of which has it's own
++ * header file providing the interface.
++ *
++ * - \ref alloc "Memory allocation" <oska/alloc.h>
++ * - \ref event "Events" <oska/event.h>
++ * - \ref mutex "Mutexes" <oska/mutex.h>
++ * - \ref print "Console output" <oska/print.h>
++ * - \ref spinlock "Spinlocks" <oska/spinlock.h>
++ * - \ref thread "Threading" <oska/thread.h>
++ * - \ref time "Timing and delays" <oska/time.h>
++ * - \ref timer "Timers" <oska/timer.h>
++ * - \ref types "Standard Types" <oska/types.h>
++ * - \ref util "Miscellaneous utilities" <oska/util.h>
++ *
++ * An <oska/all.h> header is provided which includes all the above
++ * modules.
++ *
++ * There are additional modules that are not included in <oska/all.h>.
++ *
++ * - \ref io "Memory mapped I/O" <oska/io.h>
++ * - \ref refcount "Reference Counting" <oska/refcount.h>
++ * - \ref list "Linked lists" <oska/list.h>
++ * - \ref trace "Tracing messages" <oska/trace.h>
++ */
++
++#include "alloc.h"
++#include "event.h"
++#include "mutex.h"
++#include "print.h"
++#include "spinlock.h"
++#include "thread.h"
++#include "time.h"
++#include "timer.h"
++#include "types.h"
++#include "util.h"
++
++#endif /* __OSKA_ALL_H */
+diff --git a/drivers/staging/csr/oska/alloc.h b/drivers/staging/csr/oska/alloc.h
+new file mode 100644
+index 0000000..0f10601
+--- /dev/null
++++ b/drivers/staging/csr/oska/alloc.h
+@@ -0,0 +1,41 @@
++/*
++ * OSKA Linux implementation -- memory allocation
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_ALLOC_H
++#define __OSKA_LINUX_ALLOC_H
++
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++
++static inline void *os_alloc(size_t size)
++{
++ return kzalloc(size, GFP_ATOMIC);
++}
++
++static inline void *os_alloc_nonzeroed(size_t size)
++{
++ return kmalloc(size, GFP_KERNEL);
++}
++
++static inline void os_free(void *ptr)
++{
++ kfree(ptr);
++}
++
++static inline void *os_alloc_big(size_t size)
++{
++ return vmalloc(size);
++}
++
++static inline void os_free_big(void *ptr)
++{
++ vfree(ptr);
++}
++
++#endif /* #ifndef __OSKA_LINUX_ALLOC_H */
+diff --git a/drivers/staging/csr/oska/compat.c b/drivers/staging/csr/oska/compat.c
+new file mode 100644
+index 0000000..790b97a
+--- /dev/null
++++ b/drivers/staging/csr/oska/compat.c
+@@ -0,0 +1,54 @@
++/*
++ * Linux version compatibility functions.
++ *
++ * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version
++ * 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#include "kernel-compat.h"
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
++
++int dev_set_name(struct device *dev, const char *fmt, ...)
++{
++ va_list vargs;
++
++ va_start(vargs, fmt);
++ vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs);
++ va_end(vargs);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(dev_set_name);
++
++#endif /* Linux kernel < 2.6.26 */
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
++
++struct device *class_find_device(struct class *class, struct device *start,
++ void *data, int (*match)(struct device *, void *))
++{
++ struct device *dev;
++
++ list_for_each_entry(dev, &class->devices, node) {
++ if (match(dev, data)) {
++ get_device(dev);
++ return dev;
++ }
++ }
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(class_find_device);
++
++#endif /* Linux kernel < 2.6.25 */
+diff --git a/drivers/staging/csr/oska/event.c b/drivers/staging/csr/oska/event.c
+new file mode 100644
+index 0000000..36bfcd9
+--- /dev/null
++++ b/drivers/staging/csr/oska/event.c
+@@ -0,0 +1,82 @@
++/*
++ * Linux event functions.
++ *
++ * Copyright (C) 2009 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#include <linux/module.h>
++#include <linux/sched.h>
++
++#include "event.h"
++
++void os_event_init(os_event_t *evt)
++{
++ init_waitqueue_head(&evt->wq);
++ spin_lock_init(&evt->lock);
++ evt->events = 0;
++}
++EXPORT_SYMBOL(os_event_init);
++
++uint16_t os_event_wait(os_event_t *evt)
++{
++ uint16_t e;
++ unsigned long flags;
++
++ wait_event(evt->wq, evt->events != 0);
++
++ spin_lock_irqsave(&evt->lock, flags);
++ e = evt->events;
++ evt->events &= ~e;
++ spin_unlock_irqrestore(&evt->lock, flags);
++
++ return e;
++}
++EXPORT_SYMBOL(os_event_wait);
++
++uint16_t os_event_wait_interruptible(os_event_t *evt)
++{
++ uint16_t e;
++ unsigned long flags;
++
++ wait_event_interruptible(evt->wq, evt->events != 0);
++
++ spin_lock_irqsave(&evt->lock, flags);
++ e = evt->events;
++ evt->events &= ~e;
++ spin_unlock_irqrestore(&evt->lock, flags);
++
++ return e;
++}
++EXPORT_SYMBOL(os_event_wait_interruptible);
++
++uint16_t os_event_wait_timed(os_event_t *evt, unsigned timeout_ms)
++{
++ uint16_t e;
++ unsigned long flags;
++
++ wait_event_interruptible_timeout(evt->wq,
++ evt->events != 0,
++ msecs_to_jiffies(timeout_ms));
++
++ spin_lock_irqsave(&evt->lock, flags);
++ e = evt->events;
++ evt->events &= ~e;
++ spin_unlock_irqrestore(&evt->lock, flags);
++
++ return e;
++}
++EXPORT_SYMBOL(os_event_wait_timed);
++
++void os_event_raise(os_event_t *evt, uint16_t events)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&evt->lock, flags);
++ evt->events |= events;
++ spin_unlock_irqrestore(&evt->lock, flags);
++
++ wake_up(&evt->wq);
++}
++EXPORT_SYMBOL(os_event_raise);
+diff --git a/drivers/staging/csr/oska/event.h b/drivers/staging/csr/oska/event.h
+new file mode 100644
+index 0000000..be52e42
+--- /dev/null
++++ b/drivers/staging/csr/oska/event.h
+@@ -0,0 +1,33 @@
++/*
++ * OSKA Linux implementation -- events
++ *
++ * Copyright (C) 2009 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_EVENT_H
++#define __OSKA_LINUX_EVENT_H
++
++#include <linux/kernel.h>
++#include <linux/wait.h>
++#include <linux/spinlock.h>
++
++typedef struct {
++ wait_queue_head_t wq;
++ spinlock_t lock;
++ uint16_t events;
++} os_event_t;
++
++void os_event_init(os_event_t *evt);
++
++static inline void os_event_destroy(os_event_t *evt)
++{
++}
++
++uint16_t os_event_wait(os_event_t *evt);
++uint16_t os_event_wait_interruptible(os_event_t *evt);
++uint16_t os_event_wait_timed(os_event_t *evt, unsigned timeout_ms);
++void os_event_raise(os_event_t *evt, uint16_t events);
++
++#endif /* #ifndef __OSKA_LINUX_EVENT_H */
+diff --git a/drivers/staging/csr/oska/io.h b/drivers/staging/csr/oska/io.h
+new file mode 100644
+index 0000000..c6c406c
+--- /dev/null
++++ b/drivers/staging/csr/oska/io.h
+@@ -0,0 +1,63 @@
++/*
++ * OSKA Linux implementation -- memory mapped I/O.
++ *
++ * Copyright (C) 2009 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_IO_H
++#define __OSKA_LINUX_IO_H
++
++#include <linux/kernel.h>
++#include <linux/io.h>
++#include <linux/kernel-compat.h>
++
++typedef void __iomem *os_io_mem_t;
++
++static inline uint8_t os_io_read8(os_io_mem_t base, unsigned offset)
++{
++ return readb(base + offset);
++}
++
++static inline uint16_t os_io_read16(os_io_mem_t base, unsigned offset)
++{
++ return readw(base + offset);
++}
++
++static inline uint32_t os_io_read32(os_io_mem_t base, unsigned offset)
++{
++ return readl(base + offset);
++}
++
++static inline uint64_t os_io_read64(os_io_mem_t base, unsigned offset)
++{
++ return readq(base + offset);
++}
++
++static inline void os_io_write8(os_io_mem_t base, unsigned offset, uint8_t val)
++{
++ writeb(val, base + offset);
++}
++
++static inline void os_io_write16(os_io_mem_t base, unsigned offset, uint16_t val)
++{
++ writew(val, base + offset);
++}
++
++static inline void os_io_write32(os_io_mem_t base, unsigned offset, uint32_t val)
++{
++ writel(val, base + offset);
++}
++
++static inline void os_io_write64(os_io_mem_t base, unsigned offset, uint64_t val)
++{
++ writeq(val, base + offset);
++}
++
++static inline void os_io_memory_barrier(void)
++{
++ mb();
++}
++
++#endif /* #ifndef __OSKA_LINUX_IO_H */
+diff --git a/drivers/staging/csr/oska/kernel-compat.h b/drivers/staging/csr/oska/kernel-compat.h
+new file mode 100644
+index 0000000..b6d27d3
+--- /dev/null
++++ b/drivers/staging/csr/oska/kernel-compat.h
+@@ -0,0 +1,199 @@
++/*
++ * Kernel version compatibility.
++ *
++ * Copyright (C) 2007-2008 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ *
++ * Wherever possible compatible implementations of newer APIs are
++ * provided for older kernel versions.
++ */
++#ifndef __LINUX_KERNEL_COMPAT_H
++#define __LINUX_KERNEL_COMPAT_H
++
++#include <linux/version.h>
++#include <linux/device.h>
++#include <linux/workqueue.h>
++
++#include <asm/io.h>
++
++/*
++ * linux/semaphore.h replaces asm/semaphore.h in 2.6.27.
++ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
++# include <asm/semaphore.h>
++#else
++# include <linux/semaphore.h>
++#endif
++
++/*
++ * Workqueue API changes in 2.6.20
++ *
++ * See http://lwn.net/Articles/211279/ for details.
++ *
++ * We deliberately don't provide the non-automatic release (NAR)
++ * variants as a simple compatible implementation is not possible.
++ * This shouldn't be a problem as all usage so far is to embed the
++ * struct work_struct into another struct and the NAR variants aren't
++ * useful in this case (see http://lwn.net/Articles/213149/).
++ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
++
++#include <linux/workqueue.h>
++
++#undef INIT_WORK
++#define INIT_WORK(_work, _func) \
++ do { \
++ INIT_LIST_HEAD(&(_work)->entry); \
++ (_work)->pending = 0; \
++ PREPARE_WORK((_work), (_func), (_work)); \
++ init_timer(&(_work)->timer); \
++ } while(0)
++
++#undef DECLARE_WORK
++#define DECLARE_WORK(n, f) \
++ struct work_struct n = __WORK_INITIALIZER((n), (f), &(n))
++
++struct delayed_work {
++ struct work_struct work;
++};
++
++#define INIT_DELAYED_WORK(dw, fn) \
++ INIT_WORK(&(dw)->work, (fn))
++
++#define queue_delayed_work(wq, dw, delay) \
++ queue_delayed_work((wq), &(dw)->work, (delay))
++
++#define schedule_delayed_work(dw, delay) \
++ schedule_delayed_work(&(dw)->work, (delay))
++
++#define cancel_delayed_work(dw) \
++ cancel_delayed_work(&(dw)->work)
++
++#endif /* Linux kernel < 2.6.20 */
++
++/*
++ * device_create()/class_device_create()
++ *
++ * device_create() gains a drvdata parameter in 2.6.27. Since all
++ * users of device_create() in CSR code don't use drvdata just ignore
++ * it.
++ *
++ * device_create() replaces class_device_create() in 2.6.21.
++ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
++
++#define device_create(class, parent, devt, drvdata, fmt, args...) \
++ class_device_create((class), (parent), (devt), NULL, (fmt), ## args)
++#define device_destroy(class, devt) \
++ class_device_destroy(class, devt)
++
++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
++
++#define device_create(class, parent, devt, drvdata, fmt, args...) \
++ device_create((class), (parent), (devt), (fmt), ## args)
++
++#endif /* Linux kernel < 2.6.26 */
++
++/*
++ * dev_name() and dev_set_name() added in 2.6.26.
++ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
++
++static inline char *dev_name(struct device *dev)
++{
++ return dev->bus_id;
++}
++
++int dev_set_name(struct device *dev, const char *fmt, ...);
++
++#endif /* Linux kernel < 2.6.26 */
++
++/*
++ * class_find_device() in 2.6.25
++ */
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
++
++struct device *class_find_device(struct class *class, struct device *start,
++ void *data, int (*match)(struct device *, void *));
++
++#endif /* Linux kernel < 2.6.25 */
++
++/*
++ * list_first_entry in 2.6.22.
++ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
++
++#define list_first_entry(ptr, type, member) \
++ list_entry((ptr)->next, type, member)
++
++#endif /* Linux kernel < 2.6.22 */
++
++/*
++ * 2.6.19 adds a bool type.
++ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
++
++typedef _Bool bool;
++enum {
++ false = 0,
++ true = 1
++};
++
++#endif /* Linux kernel < 2.6.19 */
++
++/*
++ * Provide readq() and writeq() if unavailable.
++ */
++#ifndef readq
++static inline __u64 readq(const volatile void __iomem *addr)
++{
++ const volatile u32 __iomem *p = addr;
++ u32 low, high;
++
++ low = readl(p);
++ high = readl(p + 1);
++
++ return low + ((u64)high << 32);
++}
++#endif
++
++#ifndef writeq
++static inline void writeq(__u64 val, volatile void __iomem *addr)
++{
++ writel(val, addr);
++ writel(val >> 32, addr+4);
++}
++#endif
++
++/*
++ * get_unaligned_le16() and friends added in 2.6.26.
++ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
++#include <asm/unaligned.h>
++
++static inline __u16 get_unaligned_le16(const void *p)
++{
++ return le16_to_cpu(get_unaligned((__le16 *)p));
++}
++
++static inline void put_unaligned_le16(__u16 val, const void *p)
++{
++ put_unaligned(cpu_to_le16(val), (__le16 *)p);
++}
++#endif /* Linux kernel < 2.6.26 */
++
++/*
++ * Various device or vendor IDs may not exist.
++ */
++#ifndef PCI_VENDOR_ID_CSR
++# define PCI_VENDOR_ID_CSR 0x18e5
++#endif
++
++#ifndef PCI_DEVICE_ID_JMICRON_JMB38X_SD
++# define PCI_DEVICE_ID_JMICRON_JMB38X_SD 0x2381
++#endif
++
++#endif /* #ifndef __LINUX_KERNEL_COMPAT_H */
+diff --git a/drivers/staging/csr/oska/list.c b/drivers/staging/csr/oska/list.c
+new file mode 100644
+index 0000000..b5e884e
+--- /dev/null
++++ b/drivers/staging/csr/oska/list.c
+@@ -0,0 +1,103 @@
++/*
++ * Operating system kernel abstraction -- linked lists.
++ *
++ * Copyright (C) 2009-2010 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++
++#include <stddef.h>
++
++#include "list.h"
++#include "util.h"
++
++/**
++ * Initialize an empty list.
++ *
++ * @ingroup list
++ */
++void os_list_init(struct os_list *list)
++{
++ list->head.next = list->head.prev = &list->head;
++}
++
++/**
++ * Is the list empty?
++ *
++ * @return true iff the list contains no nodes.
++ *
++ * @ingroup list
++ */
++int os_list_empty(struct os_list *list)
++{
++ return list->head.next == &list->head;
++}
++
++static void os_list_add(struct os_list_node *prev, struct os_list_node *new,
++ struct os_list_node *next)
++{
++ OS_ASSERT(new->next == NULL && new->prev == NULL);
++
++ next->prev = new;
++ new->next = next;
++ new->prev = prev;
++ prev->next = new;
++}
++
++/**
++ * Add a node to the tail of the list.
++ *
++ * @param list the list.
++ * @param node the list node to add.
++ *
++ * @ingroup list
++ */
++void os_list_add_tail(struct os_list *list, struct os_list_node *node)
++{
++ os_list_add(list->head.prev, node, &list->head);
++}
++
++/**
++ * Remove a node from a list.
++ *
++ * @param node the node to remove.
++ *
++ * @ingroup list
++ */
++void os_list_del(struct os_list_node *node)
++{
++ node->prev->next = node->next;
++ node->next->prev = node->prev;
++
++ node->prev = node->next = NULL;
++}
++
++/**
++ * The node at the head of the list.
++ *
++ * @param list the list.
++ *
++ * @return the node at the head of the list; or os_list_end() if the
++ * list is empty.
++ *
++ * @ingroup list
++ */
++struct os_list_node *os_list_head(struct os_list *list)
++{
++ return list->head.next;
++}
++
++/**
++ * The node marking the end of a list.
++ *
++ * @param list the list.
++ *
++ * @return the node that marks the end of the list.
++ *
++ * @ingroup list
++ */
++struct os_list_node *os_list_end(struct os_list *list)
++{
++ return &list->head;
++}
+diff --git a/drivers/staging/csr/oska/list.h b/drivers/staging/csr/oska/list.h
+new file mode 100644
+index 0000000..a69b3b7
+--- /dev/null
++++ b/drivers/staging/csr/oska/list.h
+@@ -0,0 +1,115 @@
++/*
++ * Operating system kernel abstraction -- linked lists.
++ *
++ * Copyright (C) 2009-2010 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LIST_H
++#define __OSKA_LIST_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * @defgroup list Linked Lists
++ *
++ * Generic linked list implementations suitable for all platforms.
++ *
++ * - Circular, doubly-linked list (struct os_list).
++ */
++
++/**
++ * A list node.
++ *
++ * This list node structure should be the first field within any
++ * structure that is to be stored in a list.
++ *
++ * @see struct os_list
++ * @ingroup list
++ */
++struct os_list_node {
++ /**
++ * The pointer to the previous node in the list, or os_list_end()
++ * if the end of the list has been reached.
++ */
++ struct os_list_node *prev;
++ /**
++ * The pointer to the next node in the list, or os_list_end() if
++ * the end of the list has been reached.
++ */
++ struct os_list_node *next;
++};
++
++/**
++ * A circular, doubly-linked list of nodes.
++ *
++ * Structures to be stored in a list should contains a struct
++ * os_list_node as the \e first field.
++ * \code
++ * struct foo {
++ * struct os_list_node node;
++ * int bar;
++ * ...
++ * };
++ * \endcode
++ * Going to/from a struct foo to a list node is then simple.
++ * \code
++ * struct os_list_node *node;
++ * struct foo *foo;
++ * [...]
++ * node = &foo->node;
++ * foo = (struct foo *)node
++ * \endcode
++ * Lists must be initialized with os_list_init() before adding nodes
++ * with os_list_add_tail(). The node at the head of the list is
++ * obtained with os_list_head(). Nodes are removed from the list with
++ * os_list_del().
++ *
++ * A list can be interated from the head to the tail using:
++ * \code
++ * struct os_list_node *node;
++ * for (node = os_list_head(list); node != os_list_end(list); node = node->next) {
++ * struct foo *foo = (struct foo *)node;
++ * ...
++ * }
++ * \endcode
++ *
++ * In the above loop, the current list node cannot be removed (with
++ * os_list_del()). If this is required use this form of loop:
++ * \code
++ * struct os_list_node *node, *next;
++ * for (node = os_list_head(list), next = node->next;
++ * node != os_list_end(list);
++ * node = next, next = node->next) {
++ * struct foo *foo = (struct foo *)node;
++ * ...
++ * os_list_del(node);
++ * ...
++ * }
++ * \endcode
++ *
++ * @ingroup list
++ */
++struct os_list {
++ /**
++ * @internal
++ * The dummy node marking the end of the list.
++ */
++ struct os_list_node head;
++};
++
++void os_list_init(struct os_list *list);
++int os_list_empty(struct os_list *list);
++void os_list_add_tail(struct os_list *list, struct os_list_node *node);
++void os_list_del(struct os_list_node *node);
++struct os_list_node *os_list_head(struct os_list *list);
++struct os_list_node *os_list_end(struct os_list *list);
++
++#ifdef __cplusplus
++} /* extern "C" */
++#endif
++
++#endif /* #ifndef __OSKA_LIST_H */
+diff --git a/drivers/staging/csr/oska/mutex.h b/drivers/staging/csr/oska/mutex.h
+new file mode 100644
+index 0000000..9138b28
+--- /dev/null
++++ b/drivers/staging/csr/oska/mutex.h
+@@ -0,0 +1,42 @@
++/*
++ * OSKA Linux implementation -- mutexes
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_MUTEX_H
++#define __OSKA_LINUX_MUTEX_H
++
++#include <linux/kernel.h>
++#include <linux/mutex.h>
++
++#include "kernel-compat.h"
++
++/* Real mutexes were only added to 2.6.16 so use semaphores
++ instead. */
++typedef struct semaphore os_mutex_t;
++
++static inline void os_mutex_init(os_mutex_t *mutex)
++{
++ //init_MUTEX(mutex);
++ sema_init(mutex, 1);
++}
++
++static inline void os_mutex_destroy(os_mutex_t *mutex)
++{
++ /* no op */
++}
++
++static inline void os_mutex_lock(os_mutex_t *mutex)
++{
++ down(mutex);
++}
++
++static inline void os_mutex_unlock(os_mutex_t *mutex)
++{
++ up(mutex);
++}
++
++#endif /* __OSKA_LINUX_MUTEX_H */
+diff --git a/drivers/staging/csr/oska/oska_module.c b/drivers/staging/csr/oska/oska_module.c
+new file mode 100644
+index 0000000..da12564
+--- /dev/null
++++ b/drivers/staging/csr/oska/oska_module.c
+@@ -0,0 +1,21 @@
++/*
++ * Linux kernel module support.
++ *
++ * Copyright (C) 2010 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#include <linux/module.h>
++
++#include "all.h"
++#include "refcount.h"
++
++EXPORT_SYMBOL(os_refcount_init);
++EXPORT_SYMBOL(os_refcount_destroy);
++EXPORT_SYMBOL(os_refcount_get);
++EXPORT_SYMBOL(os_refcount_put);
++
++MODULE_DESCRIPTION("Operating System Kernel Abstraction");
++MODULE_AUTHOR("Cambridge Silicon Radio Ltd.");
++MODULE_LICENSE("GPL and additional rights");
+diff --git a/drivers/staging/csr/oska/print.c b/drivers/staging/csr/oska/print.c
+new file mode 100644
+index 0000000..5f5b263
+--- /dev/null
++++ b/drivers/staging/csr/oska/print.c
+@@ -0,0 +1,44 @@
++/*
++ * Linux console printing functions.
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#include <linux/module.h>
++
++#include "print.h"
++
++void os_print(enum os_print_level level, const char *prefix, const char *name,
++ const char *format, ...)
++{
++ va_list va_args;
++
++ va_start(va_args, format);
++ os_vprint(level, prefix, name, format, va_args);
++ va_end(va_args);
++}
++EXPORT_SYMBOL(os_print);
++
++void os_vprint(enum os_print_level level, const char *prefix, const char *name,
++ const char *format, va_list args)
++{
++ const char *level_str[] = {
++ [OS_PRINT_ERROR] = KERN_ERR,
++ [OS_PRINT_WARNING] = KERN_WARNING,
++ [OS_PRINT_INFO] = KERN_INFO,
++ [OS_PRINT_DEBUG] = KERN_DEBUG,
++ };
++ char buf[80];
++ int w = 0;
++
++ if (name) {
++ w += snprintf(buf + w, sizeof(buf) - w, "%s%s%s: ", level_str[level], prefix, name);
++ } else {
++ w += snprintf(buf + w, sizeof(buf) - w, "%s%s", level_str[level], prefix);
++ }
++ w += vsnprintf(buf + w, sizeof(buf) - w, format, args);
++ printk("%s\n", buf);
++}
++EXPORT_SYMBOL(os_vprint);
+diff --git a/drivers/staging/csr/oska/print.h b/drivers/staging/csr/oska/print.h
+new file mode 100644
+index 0000000..f48bb83
+--- /dev/null
++++ b/drivers/staging/csr/oska/print.h
+@@ -0,0 +1,32 @@
++/*
++ * OSKA Linux implementation -- console printing
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_PRINT_H
++#define __OSKA_LINUX_PRINT_H
++
++#include <linux/kernel.h>
++
++/**
++ * Severity of a console or log message.
++ *
++ * @ingroup print
++ */
++enum os_print_level {
++ OS_PRINT_ERROR,
++ OS_PRINT_WARNING,
++ OS_PRINT_INFO,
++ OS_PRINT_DEBUG,
++};
++
++void os_print(enum os_print_level level, const char *prefix, const char *name,
++ const char *format, ...);
++void os_vprint(enum os_print_level level, const char *prefix, const char *name,
++ const char *format, va_list args);
++
++
++#endif /* #ifndef __OSKA_LINUX_PRINT_H */
+diff --git a/drivers/staging/csr/oska/refcount.c b/drivers/staging/csr/oska/refcount.c
+new file mode 100644
+index 0000000..28abb64
+--- /dev/null
++++ b/drivers/staging/csr/oska/refcount.c
+@@ -0,0 +1,47 @@
++/*
++ * OSKA generic implementation -- reference counting.
++ *
++ * Copyright (C) 2010 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#include "refcount.h"
++#include "types.h"
++
++void os_refcount_init(os_refcount_t *refcount, os_refcount_callback_f func, void *arg)
++{
++ os_spinlock_init(&refcount->lock);
++ refcount->count = 1;
++ refcount->func = func;
++ refcount->arg = arg;
++}
++
++void os_refcount_destroy(os_refcount_t *refcount)
++{
++ os_spinlock_destroy(&refcount->lock);
++}
++
++void os_refcount_get(os_refcount_t *refcount)
++{
++ os_int_status_t istate;
++
++ os_spinlock_lock_intsave(&refcount->lock, &istate);
++ refcount->count++;
++ os_spinlock_unlock_intrestore(&refcount->lock, &istate);
++}
++
++void os_refcount_put(os_refcount_t *refcount)
++{
++ bool is_zero;
++ os_int_status_t istate;
++
++ os_spinlock_lock_intsave(&refcount->lock, &istate);
++ refcount->count--;
++ is_zero = refcount->count == 0;
++ os_spinlock_unlock_intrestore(&refcount->lock, &istate);
++
++ if (is_zero) {
++ refcount->func(refcount->arg);
++ }
++}
+diff --git a/drivers/staging/csr/oska/refcount.h b/drivers/staging/csr/oska/refcount.h
+new file mode 100644
+index 0000000..741b00a
+--- /dev/null
++++ b/drivers/staging/csr/oska/refcount.h
+@@ -0,0 +1,86 @@
++/*
++ * Operating system kernel abstraction -- reference counting.
++ *
++ * Copyright (C) 2010 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_REFCOUNT_H
++#define __OSKA_REFCOUNT_H
++
++#include "spinlock.h"
++
++/**
++ * @defgroup refcount Reference Counting
++ *
++ * A reference count is an atomic counter. A callback function is
++ * called whenever the count reaches zero.
++ *
++ * A generic implementation is provided that is suitable for all
++ * platforms that support the spinlock API in <oska/spinlock.h> (see
++ * \ref spinlock).
++ */
++
++typedef void (*os_refcount_callback_f)(void *arg);
++
++struct __os_refcount_impl {
++ unsigned count;
++ os_spinlock_t lock;
++ os_refcount_callback_f func;
++ void *arg;
++};
++
++/**
++ * A reference count object.
++ *
++ * @ingroup refcount
++ */
++typedef struct __os_refcount_impl os_refcount_t;
++
++/**
++ * Initialize a reference count to 1.
++ *
++ * Initialized reference counts must be destroyed by calling
++ * os_refcount_destroy().
++ *
++ * @param refcount the reference count.
++ * @param func the function which will be called when the
++ * reference count reaches 0.
++ * @param arg an argument to pass to func.
++ *
++ * @ingroup refcount
++ */
++void os_refcount_init(os_refcount_t *refcount, os_refcount_callback_f func, void *arg);
++
++/**
++ * Destroy a reference count object.
++ *
++ * @param refcount the reference count.
++ *
++ * @ingroup refcount
++ */
++void os_refcount_destroy(os_refcount_t *refcount);
++
++/**
++ * Atomically increase the reference count by 1.
++ *
++ * @param refcount the reference count.
++ *
++ * @ingroup refcount
++ */
++void os_refcount_get(os_refcount_t *refcount);
++
++/**
++ * Atomically decrease the reference count by 1.
++ *
++ * The callback function passed to the call to os_refcount_init() is
++ * called if the count was decreased to zero.
++ *
++ * @param refcount the reference count.
++ *
++ * @ingroup refcount
++ */
++void os_refcount_put(os_refcount_t *refcount);
++
++#endif /* #ifndef __OSKA_REFCOUNT_H */
+diff --git a/drivers/staging/csr/oska/semaphore.h b/drivers/staging/csr/oska/semaphore.h
+new file mode 100644
+index 0000000..965bfe8
+--- /dev/null
++++ b/drivers/staging/csr/oska/semaphore.h
+@@ -0,0 +1,70 @@
++/*
++ * OSKA Linux implementation -- semaphores
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_SEMAPHORE_H
++#define __OSKA_LINUX_SEMAPHORE_H
++
++#include <linux/kernel.h>
++
++#include <linux/kernel-compat.h>
++
++typedef struct semaphore os_semaphore_t;
++
++static inline void os_semaphore_init(os_semaphore_t *sem)
++{
++ sema_init(sem, 0);
++}
++
++static inline void os_semaphore_destroy(os_semaphore_t *sem)
++{
++}
++
++static inline void os_semaphore_wait(os_semaphore_t *sem)
++{
++ down(sem);
++}
++
++/*
++ * down_timeout() was added in 2.6.26 with the generic semaphore
++ * implementation. For now, only support it on recent kernels as
++ * semaphores may be replaced by an event API that would be
++ * implemented with wait_event(), and wait_event_timeout().
++ */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
++
++static inline int os_semaphore_wait_timed(os_semaphore_t *sem,
++ int time_ms)
++{
++ if (down_timeout(sem, msecs_to_jiffies(time_ms)) < 0) {
++ return -ETIMEDOUT;
++ }
++ return 0;
++}
++
++#else
++
++static inline int os_semaphore_wait_timed(os_semaphore_t *sem, int time_ms)
++{
++ unsigned long now = jiffies;
++ do{
++ if(!down_trylock(sem))
++ return 0;
++ msleep(1);
++ } while(time_before(jiffies, now + msecs_to_jiffies(time_ms)));
++
++ return -ETIMEDOUT;
++}
++
++#endif
++
++static inline void os_semaphore_post(os_semaphore_t *sem)
++{
++ up(sem);
++}
++
++#endif /* __OSKA_LINUX_SEMAPHORE_H */
+diff --git a/drivers/staging/csr/oska/spinlock.h b/drivers/staging/csr/oska/spinlock.h
+new file mode 100644
+index 0000000..157b350
+--- /dev/null
++++ b/drivers/staging/csr/oska/spinlock.h
+@@ -0,0 +1,43 @@
++/*
++ * OSKA Linux implementation -- spinlocks
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_SPINLOCK_H
++#define __OSKA_LINUX_SPINLOCK_H
++
++#include <linux/kernel.h>
++#include <linux/spinlock.h>
++
++typedef spinlock_t os_spinlock_t;
++typedef unsigned long os_int_status_t;
++
++static inline void os_spinlock_init(os_spinlock_t *lock)
++{
++ spinlock_t *l = (spinlock_t *)lock;
++ spin_lock_init(l);
++}
++
++static inline void os_spinlock_destroy(os_spinlock_t *lock)
++{
++ /* no op */
++}
++
++static inline void os_spinlock_lock_intsave(os_spinlock_t *lock,
++ os_int_status_t *int_state)
++{
++ spinlock_t *l = (spinlock_t *)lock;
++ spin_lock_irqsave(l, *int_state);
++}
++
++static inline void os_spinlock_unlock_intrestore(os_spinlock_t *lock,
++ os_int_status_t *int_state)
++{
++ spinlock_t *l = (spinlock_t *)lock;
++ spin_unlock_irqrestore(l, *int_state);
++}
++
++#endif /* #ifndef __OSKA_LINUX_SPINLOCK_H */
+diff --git a/drivers/staging/csr/oska/thread.c b/drivers/staging/csr/oska/thread.c
+new file mode 100644
+index 0000000..f680cef
+--- /dev/null
++++ b/drivers/staging/csr/oska/thread.c
+@@ -0,0 +1,66 @@
++/*
++ * Linux thread functions.
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#include <linux/module.h>
++
++#include "thread.h"
++
++static int thread_func(void *data)
++{
++ os_thread_t *thread = data;
++
++ thread->func(thread->arg);
++
++ /*
++ * kthread_stop() cannot handle the thread exiting while
++ * kthread_should_stop() is false, so sleep until kthread_stop()
++ * wakes us up.
++ */
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (!kthread_should_stop())
++ schedule();
++
++ return 0;
++}
++
++int os_thread_create(os_thread_t *thread, const char *name, void (*func)(void *), void *arg)
++{
++ thread->func = func;
++ thread->arg = arg;
++
++ thread->stop = 0;
++
++ thread->task = kthread_run(thread_func, thread, name);
++ if (IS_ERR(thread->task)) {
++ return PTR_ERR(thread->task);
++ }
++ return 0;
++}
++EXPORT_SYMBOL(os_thread_create);
++
++void os_thread_stop(os_thread_t *thread, os_event_t *evt)
++{
++ /*
++ * Stop flag must be set before the event is raised so
++ * kthread_should_stop() cannot be used.
++ */
++ thread->stop = 1;
++
++ if (evt) {
++ os_event_raise(evt, ~0);
++ }
++
++ kthread_stop(thread->task);
++}
++EXPORT_SYMBOL(os_thread_stop);
++
++int os_thread_should_stop(os_thread_t *thread)
++{
++ return thread->stop;
++}
++EXPORT_SYMBOL(os_thread_should_stop);
+diff --git a/drivers/staging/csr/oska/thread.h b/drivers/staging/csr/oska/thread.h
+new file mode 100644
+index 0000000..8816dc8
+--- /dev/null
++++ b/drivers/staging/csr/oska/thread.h
+@@ -0,0 +1,39 @@
++/*
++ * OSKA Linux implementation -- threading
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_THREAD_H
++#define __OSKA_LINUX_THREAD_H
++
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/kthread.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
++#include <linux/freezer.h>
++#endif
++#include "event.h"
++
++struct os_thread_lx {
++ void (*func)(void *);
++ void *arg;
++ struct task_struct *task;
++ int stop;
++};
++
++typedef struct os_thread_lx os_thread_t;
++
++int os_thread_create(os_thread_t *thread, const char *name,
++ void (*func)(void *), void *arg);
++void os_thread_stop(os_thread_t *thread, os_event_t *evt);
++int os_thread_should_stop(os_thread_t *thread);
++
++static inline void os_try_suspend_thread(os_thread_t *thread)
++{
++ try_to_freeze();
++}
++
++#endif /* __OSKA_LINUX_THREAD_H */
+diff --git a/drivers/staging/csr/oska/time.h b/drivers/staging/csr/oska/time.h
+new file mode 100644
+index 0000000..d246ce9
+--- /dev/null
++++ b/drivers/staging/csr/oska/time.h
+@@ -0,0 +1,34 @@
++/*
++ * OSKA Linux implementation -- timing
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_TIME_H
++#define __OSKA_LINUX_TIME_H
++
++#include <linux/kernel.h>
++#include <linux/time.h>
++#include <linux/delay.h>
++#include <linux/jiffies.h>
++
++static inline unsigned long os_current_time_ms(void)
++{
++ return jiffies_to_msecs(jiffies);
++}
++
++static inline void os_sleep_ms(unsigned ms)
++{
++ msleep_interruptible(ms);
++}
++
++static inline void os_delay_us(unsigned us)
++{
++ udelay(us);
++}
++
++#define os_time_after(a, b) time_after((a), (b))
++
++#endif /* __OSKA_LINUX_TIME_H */
+diff --git a/drivers/staging/csr/oska/timer.c b/drivers/staging/csr/oska/timer.c
+new file mode 100644
+index 0000000..67d3423
+--- /dev/null
++++ b/drivers/staging/csr/oska/timer.c
+@@ -0,0 +1,28 @@
++/*
++ * OSKA Linux implementation -- timers.
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#include <linux/module.h>
++
++#include "timer.h"
++
++static void timer_func(unsigned long data)
++{
++ os_timer_t *timer = (os_timer_t *)data;
++
++ timer->func(timer->arg);
++}
++
++void os_timer_init(os_timer_t *timer, os_timer_func_t func, void *arg)
++{
++ timer->func = func;
++ timer->arg = arg;
++ timer->timer.function = timer_func;
++ timer->timer.data = (unsigned long)timer;
++ init_timer(&timer->timer);
++}
++EXPORT_SYMBOL(os_timer_init);
+diff --git a/drivers/staging/csr/oska/timer.h b/drivers/staging/csr/oska/timer.h
+new file mode 100644
+index 0000000..3045fc3
+--- /dev/null
++++ b/drivers/staging/csr/oska/timer.h
+@@ -0,0 +1,40 @@
++/*
++ * OSKA Linux implementation -- timers.
++ *
++ * Copyright (C) 2009 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_TIMER_H
++#define __OSKA_LINUX_TIMER_H
++
++#include <linux/kernel.h>
++#include <linux/timer.h>
++
++typedef void (*os_timer_func_t)(void *arg);
++
++typedef struct {
++ os_timer_func_t func;
++ void *arg;
++ struct timer_list timer;
++} os_timer_t;
++
++void os_timer_init(os_timer_t *timer, os_timer_func_t func, void *arg);
++
++static inline void os_timer_destroy(os_timer_t *timer)
++{
++ del_timer_sync(&timer->timer);
++}
++
++static inline void os_timer_set(os_timer_t *timer, unsigned long expires_ms)
++{
++ mod_timer(&timer->timer, jiffies + msecs_to_jiffies(expires_ms));
++}
++
++static inline void os_timer_cancel(os_timer_t *timer)
++{
++ del_timer(&timer->timer);
++}
++
++#endif /* #ifndef __OSKA_LINUX_TIMER_H */
+diff --git a/drivers/staging/csr/oska/trace.h b/drivers/staging/csr/oska/trace.h
+new file mode 100644
+index 0000000..b28f37d
+--- /dev/null
++++ b/drivers/staging/csr/oska/trace.h
+@@ -0,0 +1,23 @@
++/*
++ * OSKA Linux implementation -- tracing messages.
++ *
++ * Copyright (C) 2009 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_TRACE_H
++#define __OSKA_LINUX_TRACE_H
++
++#include <linux/kernel.h>
++
++#ifndef OS_TRACE_PREFIX
++# define OS_TRACE_PREFIX ""
++#endif
++
++#define os_trace_err(format, ...) printk(KERN_ERR OS_TRACE_PREFIX format "\n", ## __VA_ARGS__)
++#define os_trace_warn(format, ...) printk(KERN_WARNING OS_TRACE_PREFIX format "\n", ## __VA_ARGS__)
++#define os_trace_info(format, ...) printk(KERN_INFO OS_TRACE_PREFIX format "\n", ## __VA_ARGS__)
++#define os_trace_dbg(format, ...) printk(KERN_DEBUG OS_TRACE_PREFIX format "\n", ## __VA_ARGS__)
++
++#endif /* #ifndef __OSKA_LINUX_TRACE_H */
+diff --git a/drivers/staging/csr/oska/types.h b/drivers/staging/csr/oska/types.h
+new file mode 100644
+index 0000000..18d7c11
+--- /dev/null
++++ b/drivers/staging/csr/oska/types.h
+@@ -0,0 +1,14 @@
++/*
++ * OSKA Linux implementation -- types
++ *
++ * Copyright (C) 2009 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_TYPES_H
++#define __OSKA_LINUX_TYPES_H
++
++#include <linux/types.h>
++
++#endif /* #ifndef __OSKA_LINUX_TYPES_H */
+diff --git a/drivers/staging/csr/oska/util.h b/drivers/staging/csr/oska/util.h
+new file mode 100644
+index 0000000..bf29e2d
+--- /dev/null
++++ b/drivers/staging/csr/oska/util.h
+@@ -0,0 +1,48 @@
++/*
++ * OSKA Linux implementation -- misc. utility functions
++ *
++ * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
++ *
++ * Refer to LICENSE.txt included with this source code for details on
++ * the license terms.
++ */
++#ifndef __OSKA_LINUX_UTILS_H
++#define __OSKA_LINUX_UTILS_H
++
++#include <linux/kernel.h>
++#include <linux/bug.h>
++#include <asm/byteorder.h>
++
++#define OS_ASSERT(expr) BUG_ON(!(expr))
++
++static inline uint16_t os_le16_to_cpu(uint16_t x)
++{
++ return le16_to_cpu(x);
++}
++
++static inline uint16_t os_cpu_to_le16(uint16_t x)
++{
++ return cpu_to_le16(x);
++}
++
++static inline uint32_t os_le32_to_cpu(uint32_t x)
++{
++ return le32_to_cpu(x);
++}
++
++static inline uint32_t os_cpu_to_le32(uint32_t x)
++{
++ return cpu_to_le32(x);
++}
++
++static inline uint64_t os_le64_to_cpu(uint64_t x)
++{
++ return le64_to_cpu(x);
++}
++
++static inline uint64_t os_cpu_to_le64(uint64_t x)
++{
++ return cpu_to_le64(x);
++}
++
++#endif /* __OSKA_LINUX_UTILS_H */