Root/drivers/staging/csr/os.c

1/*
2 * ---------------------------------------------------------------------------
3 * FILE: os.c
4 *
5 * PURPOSE:
6 * Routines to fulfil the OS-abstraction for the HIP lib.
7 * It is part of the porting exercise.
8 *
9 * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd.
10 *
11 * Refer to LICENSE.txt included with this source code for details on
12 * the license terms.
13 *
14 * ---------------------------------------------------------------------------
15 */
16
17/**
18 * The HIP lib OS abstraction consists of the implementation
19 * of the functions in this file. It is part of the porting exercise.
20 */
21
22#include "unifi_priv.h"
23
24
25/*
26 * ---------------------------------------------------------------------------
27 * unifi_net_data_malloc
28 *
29 * Allocate an OS specific net data buffer of "size" bytes.
30 * The bulk_data_slot.os_data_ptr must be initialised to point
31 * to the buffer allocated. The bulk_data_slot.length must be
32 * initialised to the requested size, zero otherwise.
33 * The bulk_data_slot.os_net_buf_ptr can be initialised to
34 * an OS specific pointer to be used in the unifi_net_data_free().
35 *
36 *
37 * Arguments:
38 * ospriv Pointer to device private context struct.
39 * bulk_data_slot Pointer to the bulk data structure to initialise.
40 * size Size of the buffer to be allocated.
41 *
42 * Returns:
43 * CSR_RESULT_SUCCESS on success, CSR_RESULT_FAILURE otherwise.
44 * ---------------------------------------------------------------------------
45 */
46CsrResult
47unifi_net_data_malloc(void *ospriv, bulk_data_desc_t *bulk_data_slot, unsigned int size)
48{
49    struct sk_buff *skb;
50    unifi_priv_t *priv = (unifi_priv_t*)ospriv;
51    int rounded_length;
52
53    if (priv->card_info.sdio_block_size == 0) {
54        unifi_error(priv, "unifi_net_data_malloc: Invalid SDIO block size\n");
55        return CSR_RESULT_FAILURE;
56    }
57
58    rounded_length = (size + priv->card_info.sdio_block_size - 1) & ~(priv->card_info.sdio_block_size - 1);
59
60    /*
61     * (ETH_HLEN + 2) bytes tailroom for header manipulation
62     * CSR_WIFI_ALIGN_BYTES bytes headroom for alignment manipulation
63     */
64    skb = dev_alloc_skb(rounded_length + 2 + ETH_HLEN + CSR_WIFI_ALIGN_BYTES);
65    if (! skb) {
66        unifi_error(ospriv, "alloc_skb failed.\n");
67        bulk_data_slot->os_net_buf_ptr = NULL;
68        bulk_data_slot->net_buf_length = 0;
69        bulk_data_slot->os_data_ptr = NULL;
70        bulk_data_slot->data_length = 0;
71        return CSR_RESULT_FAILURE;
72    }
73
74    bulk_data_slot->os_net_buf_ptr = (const unsigned char*)skb;
75    bulk_data_slot->net_buf_length = rounded_length + 2 + ETH_HLEN + CSR_WIFI_ALIGN_BYTES;
76    bulk_data_slot->os_data_ptr = (const void*)skb->data;
77    bulk_data_slot->data_length = size;
78
79    return CSR_RESULT_SUCCESS;
80} /* unifi_net_data_malloc() */
81
82/*
83 * ---------------------------------------------------------------------------
84 * unifi_net_data_free
85 *
86 * Free an OS specific net data buffer.
87 * The bulk_data_slot.length must be initialised to 0.
88 *
89 *
90 * Arguments:
91 * ospriv Pointer to device private context struct.
92 * bulk_data_slot Pointer to the bulk data structure that
93 * holds the data to be freed.
94 *
95 * Returns:
96 * None.
97 * ---------------------------------------------------------------------------
98 */
99void
100unifi_net_data_free(void *ospriv, bulk_data_desc_t *bulk_data_slot)
101{
102    struct sk_buff *skb;
103    CSR_UNUSED(ospriv);
104
105    skb = (struct sk_buff *)bulk_data_slot->os_net_buf_ptr;
106    dev_kfree_skb(skb);
107
108    bulk_data_slot->net_buf_length = 0;
109    bulk_data_slot->data_length = 0;
110    bulk_data_slot->os_data_ptr = bulk_data_slot->os_net_buf_ptr = NULL;
111
112} /* unifi_net_data_free() */
113
114
115/*
116* ---------------------------------------------------------------------------
117* unifi_net_dma_align
118*
119* DMA align an OS specific net data buffer.
120* The buffer must be empty.
121*
122*
123* Arguments:
124* ospriv Pointer to device private context struct.
125* bulk_data_slot Pointer to the bulk data structure that
126* holds the data to be aligned.
127*
128* Returns:
129* None.
130* ---------------------------------------------------------------------------
131*/
132CsrResult
133unifi_net_dma_align(void *ospriv, bulk_data_desc_t *bulk_data_slot)
134{
135    struct sk_buff *skb;
136    unsigned long buf_address;
137    int offset;
138    unifi_priv_t *priv = (unifi_priv_t*)ospriv;
139
140    if ((bulk_data_slot == NULL) || (CSR_WIFI_ALIGN_BYTES == 0)) {
141        return CSR_RESULT_SUCCESS;
142    }
143
144    if ((bulk_data_slot->os_data_ptr == NULL) || (bulk_data_slot->data_length == 0)) {
145        return CSR_RESULT_SUCCESS;
146    }
147
148    buf_address = (unsigned long)(bulk_data_slot->os_data_ptr) & (CSR_WIFI_ALIGN_BYTES - 1);
149
150    unifi_trace(priv, UDBG5,
151                "unifi_net_dma_align: Allign buffer (0x%p) by %d bytes\n",
152                bulk_data_slot->os_data_ptr, buf_address);
153
154    offset = CSR_WIFI_ALIGN_BYTES - buf_address;
155    if (offset < 0) {
156        unifi_error(priv, "unifi_net_dma_align: Failed (offset=%d)\n", offset);
157        return CSR_RESULT_FAILURE;
158    }
159
160    skb = (struct sk_buff*)(bulk_data_slot->os_net_buf_ptr);
161    skb_reserve(skb, offset);
162    bulk_data_slot->os_net_buf_ptr = (const unsigned char*)skb;
163    bulk_data_slot->os_data_ptr = (const void*)(skb->data);
164
165    return CSR_RESULT_SUCCESS;
166
167} /* unifi_net_dma_align() */
168
169#ifdef ANDROID_TIMESTAMP
170static volatile unsigned int printk_cpu = UINT_MAX;
171char tbuf[30];
172
173char* print_time(void )
174{
175    unsigned long long t;
176    unsigned long nanosec_rem;
177
178    t = cpu_clock(printk_cpu);
179    nanosec_rem = do_div(t, 1000000000);
180    sprintf(tbuf, "[%5lu.%06lu] ",
181                    (unsigned long) t,
182                    nanosec_rem / 1000);
183
184    return tbuf;
185}
186#endif
187
188
189/* Module parameters */
190extern int unifi_debug;
191
192#ifdef UNIFI_DEBUG
193#define DEBUG_BUFFER_SIZE 120
194
195#define FORMAT_TRACE(_s, _len, _args, _fmt) \
196    do { \
197        va_start(_args, _fmt); \
198        _len += vsnprintf(&(_s)[_len], \
199                         (DEBUG_BUFFER_SIZE - _len), \
200                         _fmt, _args); \
201        va_end(_args); \
202        if (_len >= DEBUG_BUFFER_SIZE) { \
203            (_s)[DEBUG_BUFFER_SIZE - 2] = '\n'; \
204            (_s)[DEBUG_BUFFER_SIZE - 1] = 0; \
205        } \
206    } while (0)
207
208void
209unifi_error(void* ospriv, const char *fmt, ...)
210{
211    unifi_priv_t *priv = (unifi_priv_t*) ospriv;
212    char s[DEBUG_BUFFER_SIZE];
213    va_list args;
214    unsigned int len;
215#ifdef ANDROID_TIMESTAMP
216    if (priv != NULL) {
217        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi%d: ", print_time(), priv->instance);
218    } else {
219        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi: ", print_time());
220    }
221#else
222    if (priv != NULL) {
223        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi%d: ", priv->instance);
224    } else {
225        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi: ");
226    }
227#endif /* ANDROID_TIMESTAMP */
228    FORMAT_TRACE(s, len, args, fmt);
229
230    printk("%s", s);
231}
232
233void
234unifi_warning(void* ospriv, const char *fmt, ...)
235{
236    unifi_priv_t *priv = (unifi_priv_t*) ospriv;
237    char s[DEBUG_BUFFER_SIZE];
238    va_list args;
239    unsigned int len;
240
241#ifdef ANDROID_TIMESTAMP
242    if (priv != NULL) {
243        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "%s unifi%d: ", print_time(), priv->instance);
244    } else {
245        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "%s unifi: ", print_time());
246    }
247#else
248    if (priv != NULL) {
249        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "unifi%d: ", priv->instance);
250    } else {
251        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "unifi: ");
252    }
253#endif /* ANDROID_TIMESTAMP */
254
255    FORMAT_TRACE(s, len, args, fmt);
256
257    printk("%s", s);
258}
259
260
261void
262unifi_notice(void* ospriv, const char *fmt, ...)
263{
264    unifi_priv_t *priv = (unifi_priv_t*) ospriv;
265    char s[DEBUG_BUFFER_SIZE];
266    va_list args;
267    unsigned int len;
268
269#ifdef ANDROID_TIMESTAMP
270    if (priv != NULL) {
271        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "%s unifi%d: ", print_time(), priv->instance);
272    } else {
273        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "%s unifi: ", print_time());
274    }
275#else
276    if (priv != NULL) {
277        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "unifi%d: ", priv->instance);
278    } else {
279        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "unifi: ");
280    }
281#endif /* ANDROID_TIMESTAMP */
282
283    FORMAT_TRACE(s, len, args, fmt);
284
285    printk("%s", s);
286}
287
288
289void
290unifi_info(void* ospriv, const char *fmt, ...)
291{
292    unifi_priv_t *priv = (unifi_priv_t*) ospriv;
293    char s[DEBUG_BUFFER_SIZE];
294    va_list args;
295    unsigned int len;
296
297#ifdef ANDROID_TIMESTAMP
298    if (priv != NULL) {
299        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "%s unifi%d: ", print_time(), priv->instance);
300    } else {
301        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "%s unifi: ", print_time());
302    }
303#else
304    if (priv != NULL) {
305        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "unifi%d: ", priv->instance);
306    } else {
307        len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "unifi: ");
308    }
309#endif /* ANDROID_TIMESTAMP */
310
311    FORMAT_TRACE(s, len, args, fmt);
312
313    printk("%s", s);
314}
315
316/* debugging */
317void
318unifi_trace(void* ospriv, int level, const char *fmt, ...)
319{
320    unifi_priv_t *priv = (unifi_priv_t*) ospriv;
321    char s[DEBUG_BUFFER_SIZE];
322    va_list args;
323    unsigned int len;
324
325    if (unifi_debug >= level) {
326#ifdef ANDROID_TIMESTAMP
327        if (priv != NULL) {
328            len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi%d: ", print_time(), priv->instance);
329        } else {
330            len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi: ", print_time());
331        }
332#else
333        if (priv != NULL) {
334            len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi%d: ", priv->instance);
335        } else {
336            len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi: ");
337        }
338#endif /* ANDROID_TIMESTAMP */
339
340        FORMAT_TRACE(s, len, args, fmt);
341
342        printk("%s", s);
343    }
344}
345
346#else
347
348void
349unifi_error_nop(void* ospriv, const char *fmt, ...)
350{
351}
352
353void
354unifi_trace_nop(void* ospriv, int level, const char *fmt, ...)
355{
356}
357
358#endif /* UNIFI_DEBUG */
359
360
361/*
362 * ---------------------------------------------------------------------------
363 *
364 * Debugging support.
365 *
366 * ---------------------------------------------------------------------------
367 */
368
369#ifdef UNIFI_DEBUG
370
371/* Memory dump with level filter controlled by unifi_debug */
372void
373unifi_dump(void *ospriv, int level, const char *msg, void *mem, u16 len)
374{
375    unifi_priv_t *priv = (unifi_priv_t*) ospriv;
376
377    if (unifi_debug >= level) {
378#ifdef ANDROID_TIMESTAMP
379        if (priv != NULL) {
380            printk(KERN_ERR "%s unifi%d: --- dump: %s ---\n", print_time(), priv->instance, msg ? msg : "");
381        } else {
382            printk(KERN_ERR "%s unifi: --- dump: %s ---\n", print_time(), msg ? msg : "");
383        }
384#else
385        if (priv != NULL) {
386            printk(KERN_ERR "unifi%d: --- dump: %s ---\n", priv->instance, msg ? msg : "");
387        } else {
388            printk(KERN_ERR "unifi: --- dump: %s ---\n", msg ? msg : "");
389        }
390#endif /* ANDROID_TIMESTAMP */
391        dump(mem, len);
392
393        if (priv != NULL) {
394            printk(KERN_ERR "unifi%d: --- end of dump ---\n", priv->instance);
395        } else {
396            printk(KERN_ERR "unifi: --- end of dump ---\n");
397        }
398    }
399}
400
401/* Memory dump that appears all the time, use sparingly */
402void
403dump(void *mem, u16 len)
404{
405    int i, col = 0;
406    unsigned char *pdata = (unsigned char *)mem;
407#ifdef ANDROID_TIMESTAMP
408    printk("timestamp %s \n", print_time());
409#endif /* ANDROID_TIMESTAMP */
410    if (mem == NULL) {
411        printk("(null dump)\n");
412        return;
413    }
414    for (i = 0; i < len; i++) {
415        if (col == 0) {
416            printk("0x%02X: ", i);
417        }
418
419        printk(" %02X", pdata[i]);
420
421        if (++col == 16) {
422            printk("\n");
423            col = 0;
424        }
425    }
426    if (col) {
427        printk("\n");
428    }
429} /* dump() */
430
431
432void
433dump16(void *mem, u16 len)
434{
435    int i, col=0;
436    unsigned short *p = (unsigned short *)mem;
437#ifdef ANDROID_TIMESTAMP
438    printk("timestamp %s \n", print_time());
439#endif /* ANDROID_TIMESTAMP */
440    for (i = 0; i < len; i+=2) {
441        if (col == 0) {
442            printk("0x%02X: ", i);
443        }
444
445        printk(" %04X", *p++);
446
447        if (++col == 8) {
448            printk("\n");
449            col = 0;
450        }
451    }
452    if (col) {
453        printk("\n");
454    }
455}
456
457
458#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
459void
460dump_str(void *mem, u16 len)
461{
462    int i, col = 0;
463    unsigned char *pdata = (unsigned char *)mem;
464#ifdef ANDROID_TIMESTAMP
465    printk("timestamp %s \n", print_time());
466#endif /* ANDROID_TIMESTAMP */
467    for (i = 0; i < len; i++) {
468        printk("%c", pdata[i]);
469    }
470    if (col) {
471        printk("\n");
472    }
473
474} /* dump_str() */
475#endif /* CSR_ONLY_NOTES */
476
477
478#endif /* UNIFI_DEBUG */
479
480
481/* ---------------------------------------------------------------------------
482 * - End -
483 * ------------------------------------------------------------------------- */
484

Archive Download this file



interactive