summaryrefslogtreecommitdiff
path: root/drivers/staging/csr/os.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-26 18:14:49 (GMT)
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-26 18:14:49 (GMT)
commitb13bc8dda81c54a66a1c84e66f60b8feba659f28 (patch)
tree100a26eada424fa5d9b0e5eaaf4e23b8fa036fc8 /drivers/staging/csr/os.c
parent9fc377799bc9bfd8d5cb35d0d1ea2e2458cbdbb3 (diff)
parent419e9266884fa853179ab726c27a63a9d3ae46e3 (diff)
downloadlinux-fsl-qoriq-b13bc8dda81c54a66a1c84e66f60b8feba659f28.tar.xz
Merge tag 'staging-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging tree patches from Greg Kroah-Hartman: "Here's the big staging tree merge for the 3.6-rc1 merge window. There are some patches in here outside of drivers/staging/, notibly the iio code (which is still stradeling the staging / not staging boundry), the pstore code, and the tracing code. All of these have gotten acks from the various subsystem maintainers to be included in this tree. The pstore and tracing patches are related, and are coming here as they replace one of the android staging drivers. Otherwise, the normal staging mess. Lots of cleanups and a few new drivers (some iio drivers, and the large csr wireless driver abomination.) Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" Fixed up trivial conflicts in drivers/staging/comedi/drivers/s626.h and drivers/staging/gdm72xx/netlink_k.c * tag 'staging-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1108 commits) staging: csr: delete a bunch of unused library functions staging: csr: remove csr_utf16.c staging: csr: remove csr_pmem.h staging: csr: remove CsrPmemAlloc staging: csr: remove CsrPmemFree() staging: csr: remove CsrMemAllocDma() staging: csr: remove CsrMemCalloc() staging: csr: remove CsrMemAlloc() staging: csr: remove CsrMemFree() and CsrMemFreeDma() staging: csr: remove csr_util.h staging: csr: remove CsrOffSetOf() stating: csr: remove unneeded #includes in csr_util.c staging: csr: make CsrUInt16ToHex static staging: csr: remove CsrMemCpy() staging: csr: remove CsrStrLen() staging: csr: remove CsrVsnprintf() staging: csr: remove CsrStrDup staging: csr: remove CsrStrChr() staging: csr: remove CsrStrNCmp staging: csr: remove CsrStrCmp ...
Diffstat (limited to 'drivers/staging/csr/os.c')
-rw-r--r--drivers/staging/csr/os.c483
1 files changed, 483 insertions, 0 deletions
diff --git a/drivers/staging/csr/os.c b/drivers/staging/csr/os.c
new file mode 100644
index 0000000..35dc908
--- /dev/null
+++ b/drivers/staging/csr/os.c
@@ -0,0 +1,483 @@
+/*
+ * ---------------------------------------------------------------------------
+ * FILE: os.c
+ *
+ * PURPOSE:
+ * Routines to fulfil the OS-abstraction for the HIP lib.
+ * It is part of the porting exercise.
+ *
+ * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd.
+ *
+ * Refer to LICENSE.txt included with this source code for details on
+ * the license terms.
+ *
+ * ---------------------------------------------------------------------------
+ */
+
+/**
+ * The HIP lib OS abstraction consists of the implementation
+ * of the functions in this file. It is part of the porting exercise.
+ */
+
+#include "unifi_priv.h"
+
+
+/*
+ * ---------------------------------------------------------------------------
+ * unifi_net_data_malloc
+ *
+ * Allocate an OS specific net data buffer of "size" bytes.
+ * The bulk_data_slot.os_data_ptr must be initialised to point
+ * to the buffer allocated. The bulk_data_slot.length must be
+ * initialised to the requested size, zero otherwise.
+ * The bulk_data_slot.os_net_buf_ptr can be initialised to
+ * an OS specific pointer to be used in the unifi_net_data_free().
+ *
+ *
+ * Arguments:
+ * ospriv Pointer to device private context struct.
+ * bulk_data_slot Pointer to the bulk data structure to initialise.
+ * size Size of the buffer to be allocated.
+ *
+ * Returns:
+ * CSR_RESULT_SUCCESS on success, CSR_RESULT_FAILURE otherwise.
+ * ---------------------------------------------------------------------------
+ */
+CsrResult
+unifi_net_data_malloc(void *ospriv, bulk_data_desc_t *bulk_data_slot, unsigned int size)
+{
+ struct sk_buff *skb;
+ unifi_priv_t *priv = (unifi_priv_t*)ospriv;
+ int rounded_length;
+
+ if (priv->card_info.sdio_block_size == 0) {
+ unifi_error(priv, "unifi_net_data_malloc: Invalid SDIO block size\n");
+ return CSR_RESULT_FAILURE;
+ }
+
+ rounded_length = (size + priv->card_info.sdio_block_size - 1) & ~(priv->card_info.sdio_block_size - 1);
+
+ /*
+ * (ETH_HLEN + 2) bytes tailroom for header manipulation
+ * CSR_WIFI_ALIGN_BYTES bytes headroom for alignment manipulation
+ */
+ skb = dev_alloc_skb(rounded_length + 2 + ETH_HLEN + CSR_WIFI_ALIGN_BYTES);
+ if (! skb) {
+ unifi_error(ospriv, "alloc_skb failed.\n");
+ bulk_data_slot->os_net_buf_ptr = NULL;
+ bulk_data_slot->net_buf_length = 0;
+ bulk_data_slot->os_data_ptr = NULL;
+ bulk_data_slot->data_length = 0;
+ return CSR_RESULT_FAILURE;
+ }
+
+ bulk_data_slot->os_net_buf_ptr = (const unsigned char*)skb;
+ bulk_data_slot->net_buf_length = rounded_length + 2 + ETH_HLEN + CSR_WIFI_ALIGN_BYTES;
+ bulk_data_slot->os_data_ptr = (const void*)skb->data;
+ bulk_data_slot->data_length = size;
+
+ return CSR_RESULT_SUCCESS;
+} /* unifi_net_data_malloc() */
+
+/*
+ * ---------------------------------------------------------------------------
+ * unifi_net_data_free
+ *
+ * Free an OS specific net data buffer.
+ * The bulk_data_slot.length must be initialised to 0.
+ *
+ *
+ * Arguments:
+ * ospriv Pointer to device private context struct.
+ * bulk_data_slot Pointer to the bulk data structure that
+ * holds the data to be freed.
+ *
+ * Returns:
+ * None.
+ * ---------------------------------------------------------------------------
+ */
+void
+unifi_net_data_free(void *ospriv, bulk_data_desc_t *bulk_data_slot)
+{
+ struct sk_buff *skb;
+ CSR_UNUSED(ospriv);
+
+ skb = (struct sk_buff *)bulk_data_slot->os_net_buf_ptr;
+ dev_kfree_skb(skb);
+
+ bulk_data_slot->net_buf_length = 0;
+ bulk_data_slot->data_length = 0;
+ bulk_data_slot->os_data_ptr = bulk_data_slot->os_net_buf_ptr = NULL;
+
+} /* unifi_net_data_free() */
+
+
+/*
+* ---------------------------------------------------------------------------
+* unifi_net_dma_align
+*
+* DMA align an OS specific net data buffer.
+* The buffer must be empty.
+*
+*
+* Arguments:
+* ospriv Pointer to device private context struct.
+* bulk_data_slot Pointer to the bulk data structure that
+* holds the data to be aligned.
+*
+* Returns:
+* None.
+* ---------------------------------------------------------------------------
+*/
+CsrResult
+unifi_net_dma_align(void *ospriv, bulk_data_desc_t *bulk_data_slot)
+{
+ struct sk_buff *skb;
+ unsigned long buf_address;
+ int offset;
+ unifi_priv_t *priv = (unifi_priv_t*)ospriv;
+
+ if ((bulk_data_slot == NULL) || (CSR_WIFI_ALIGN_BYTES == 0)) {
+ return CSR_RESULT_SUCCESS;
+ }
+
+ if ((bulk_data_slot->os_data_ptr == NULL) || (bulk_data_slot->data_length == 0)) {
+ return CSR_RESULT_SUCCESS;
+ }
+
+ buf_address = (unsigned long)(bulk_data_slot->os_data_ptr) & (CSR_WIFI_ALIGN_BYTES - 1);
+
+ unifi_trace(priv, UDBG5,
+ "unifi_net_dma_align: Allign buffer (0x%p) by %d bytes\n",
+ bulk_data_slot->os_data_ptr, buf_address);
+
+ offset = CSR_WIFI_ALIGN_BYTES - buf_address;
+ if (offset < 0) {
+ unifi_error(priv, "unifi_net_dma_align: Failed (offset=%d)\n", offset);
+ return CSR_RESULT_FAILURE;
+ }
+
+ skb = (struct sk_buff*)(bulk_data_slot->os_net_buf_ptr);
+ skb_reserve(skb, offset);
+ bulk_data_slot->os_net_buf_ptr = (const unsigned char*)skb;
+ bulk_data_slot->os_data_ptr = (const void*)(skb->data);
+
+ return CSR_RESULT_SUCCESS;
+
+} /* unifi_net_dma_align() */
+
+#ifdef ANDROID_TIMESTAMP
+static volatile unsigned int printk_cpu = UINT_MAX;
+char tbuf[30];
+
+char* print_time(void )
+{
+ unsigned long long t;
+ unsigned long nanosec_rem;
+
+ t = cpu_clock(printk_cpu);
+ nanosec_rem = do_div(t, 1000000000);
+ sprintf(tbuf, "[%5lu.%06lu] ",
+ (unsigned long) t,
+ nanosec_rem / 1000);
+
+ return tbuf;
+}
+#endif
+
+
+/* Module parameters */
+extern int unifi_debug;
+
+#ifdef UNIFI_DEBUG
+#define DEBUG_BUFFER_SIZE 120
+
+#define FORMAT_TRACE(_s, _len, _args, _fmt) \
+ do { \
+ va_start(_args, _fmt); \
+ _len += vsnprintf(&(_s)[_len], \
+ (DEBUG_BUFFER_SIZE - _len), \
+ _fmt, _args); \
+ va_end(_args); \
+ if (_len >= DEBUG_BUFFER_SIZE) { \
+ (_s)[DEBUG_BUFFER_SIZE - 2] = '\n'; \
+ (_s)[DEBUG_BUFFER_SIZE - 1] = 0; \
+ } \
+ } while (0)
+
+void
+unifi_error(void* ospriv, const char *fmt, ...)
+{
+ unifi_priv_t *priv = (unifi_priv_t*) ospriv;
+ char s[DEBUG_BUFFER_SIZE];
+ va_list args;
+ unsigned int len;
+#ifdef ANDROID_TIMESTAMP
+ if (priv != NULL) {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi%d: ", print_time(), priv->instance);
+ } else {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi: ", print_time());
+ }
+#else
+ if (priv != NULL) {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi%d: ", priv->instance);
+ } else {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi: ");
+ }
+#endif /* ANDROID_TIMESTAMP */
+ FORMAT_TRACE(s, len, args, fmt);
+
+ printk("%s", s);
+}
+
+void
+unifi_warning(void* ospriv, const char *fmt, ...)
+{
+ unifi_priv_t *priv = (unifi_priv_t*) ospriv;
+ char s[DEBUG_BUFFER_SIZE];
+ va_list args;
+ unsigned int len;
+
+#ifdef ANDROID_TIMESTAMP
+ if (priv != NULL) {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "%s unifi%d: ", print_time(), priv->instance);
+ } else {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "%s unifi: ", print_time());
+ }
+#else
+ if (priv != NULL) {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "unifi%d: ", priv->instance);
+ } else {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "unifi: ");
+ }
+#endif /* ANDROID_TIMESTAMP */
+
+ FORMAT_TRACE(s, len, args, fmt);
+
+ printk("%s", s);
+}
+
+
+void
+unifi_notice(void* ospriv, const char *fmt, ...)
+{
+ unifi_priv_t *priv = (unifi_priv_t*) ospriv;
+ char s[DEBUG_BUFFER_SIZE];
+ va_list args;
+ unsigned int len;
+
+#ifdef ANDROID_TIMESTAMP
+ if (priv != NULL) {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "%s unifi%d: ", print_time(), priv->instance);
+ } else {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "%s unifi: ", print_time());
+ }
+#else
+ if (priv != NULL) {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "unifi%d: ", priv->instance);
+ } else {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "unifi: ");
+ }
+#endif /* ANDROID_TIMESTAMP */
+
+ FORMAT_TRACE(s, len, args, fmt);
+
+ printk("%s", s);
+}
+
+
+void
+unifi_info(void* ospriv, const char *fmt, ...)
+{
+ unifi_priv_t *priv = (unifi_priv_t*) ospriv;
+ char s[DEBUG_BUFFER_SIZE];
+ va_list args;
+ unsigned int len;
+
+#ifdef ANDROID_TIMESTAMP
+ if (priv != NULL) {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "%s unifi%d: ", print_time(), priv->instance);
+ } else {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "%s unifi: ", print_time());
+ }
+#else
+ if (priv != NULL) {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "unifi%d: ", priv->instance);
+ } else {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "unifi: ");
+ }
+#endif /* ANDROID_TIMESTAMP */
+
+ FORMAT_TRACE(s, len, args, fmt);
+
+ printk("%s", s);
+}
+
+/* debugging */
+void
+unifi_trace(void* ospriv, int level, const char *fmt, ...)
+{
+ unifi_priv_t *priv = (unifi_priv_t*) ospriv;
+ char s[DEBUG_BUFFER_SIZE];
+ va_list args;
+ unsigned int len;
+
+ if (unifi_debug >= level) {
+#ifdef ANDROID_TIMESTAMP
+ if (priv != NULL) {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi%d: ", print_time(), priv->instance);
+ } else {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi: ", print_time());
+ }
+#else
+ if (priv != NULL) {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi%d: ", priv->instance);
+ } else {
+ len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi: ");
+ }
+#endif /* ANDROID_TIMESTAMP */
+
+ FORMAT_TRACE(s, len, args, fmt);
+
+ printk("%s", s);
+ }
+}
+
+#else
+
+void
+unifi_error_nop(void* ospriv, const char *fmt, ...)
+{
+}
+
+void
+unifi_trace_nop(void* ospriv, int level, const char *fmt, ...)
+{
+}
+
+#endif /* UNIFI_DEBUG */
+
+
+/*
+ * ---------------------------------------------------------------------------
+ *
+ * Debugging support.
+ *
+ * ---------------------------------------------------------------------------
+ */
+
+#ifdef UNIFI_DEBUG
+
+/* Memory dump with level filter controlled by unifi_debug */
+void
+unifi_dump(void *ospriv, int level, const char *msg, void *mem, u16 len)
+{
+ unifi_priv_t *priv = (unifi_priv_t*) ospriv;
+
+ if (unifi_debug >= level) {
+#ifdef ANDROID_TIMESTAMP
+ if (priv != NULL) {
+ printk(KERN_ERR "%s unifi%d: --- dump: %s ---\n", print_time(), priv->instance, msg ? msg : "");
+ } else {
+ printk(KERN_ERR "%s unifi: --- dump: %s ---\n", print_time(), msg ? msg : "");
+ }
+#else
+ if (priv != NULL) {
+ printk(KERN_ERR "unifi%d: --- dump: %s ---\n", priv->instance, msg ? msg : "");
+ } else {
+ printk(KERN_ERR "unifi: --- dump: %s ---\n", msg ? msg : "");
+ }
+#endif /* ANDROID_TIMESTAMP */
+ dump(mem, len);
+
+ if (priv != NULL) {
+ printk(KERN_ERR "unifi%d: --- end of dump ---\n", priv->instance);
+ } else {
+ printk(KERN_ERR "unifi: --- end of dump ---\n");
+ }
+ }
+}
+
+/* Memory dump that appears all the time, use sparingly */
+void
+dump(void *mem, u16 len)
+{
+ int i, col = 0;
+ unsigned char *pdata = (unsigned char *)mem;
+#ifdef ANDROID_TIMESTAMP
+ printk("timestamp %s \n", print_time());
+#endif /* ANDROID_TIMESTAMP */
+ if (mem == NULL) {
+ printk("(null dump)\n");
+ return;
+ }
+ for (i = 0; i < len; i++) {
+ if (col == 0) {
+ printk("0x%02X: ", i);
+ }
+
+ printk(" %02X", pdata[i]);
+
+ if (++col == 16) {
+ printk("\n");
+ col = 0;
+ }
+ }
+ if (col) {
+ printk("\n");
+ }
+} /* dump() */
+
+
+void
+dump16(void *mem, u16 len)
+{
+ int i, col=0;
+ unsigned short *p = (unsigned short *)mem;
+#ifdef ANDROID_TIMESTAMP
+ printk("timestamp %s \n", print_time());
+#endif /* ANDROID_TIMESTAMP */
+ for (i = 0; i < len; i+=2) {
+ if (col == 0) {
+ printk("0x%02X: ", i);
+ }
+
+ printk(" %04X", *p++);
+
+ if (++col == 8) {
+ printk("\n");
+ col = 0;
+ }
+ }
+ if (col) {
+ printk("\n");
+ }
+}
+
+
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+void
+dump_str(void *mem, u16 len)
+{
+ int i, col = 0;
+ unsigned char *pdata = (unsigned char *)mem;
+#ifdef ANDROID_TIMESTAMP
+ printk("timestamp %s \n", print_time());
+#endif /* ANDROID_TIMESTAMP */
+ for (i = 0; i < len; i++) {
+ printk("%c", pdata[i]);
+ }
+ if (col) {
+ printk("\n");
+ }
+
+} /* dump_str() */
+#endif /* CSR_ONLY_NOTES */
+
+
+#endif /* UNIFI_DEBUG */
+
+
+/* ---------------------------------------------------------------------------
+ * - End -
+ * ------------------------------------------------------------------------- */