]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/staging/csr/os.c
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[karo-tx-linux.git] / 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  */
46 CsrResult
47 unifi_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  */
99 void
100 unifi_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 */
132 CsrResult
133 unifi_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
170 static volatile unsigned int printk_cpu = UINT_MAX;
171 char tbuf[30];
172
173 char* 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 */
190 extern 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
208 void
209 unifi_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
233 void
234 unifi_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
261 void
262 unifi_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
289 void
290 unifi_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 */
317 void
318 unifi_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
348 void
349 unifi_error_nop(void* ospriv, const char *fmt, ...)
350 {
351 }
352
353 void
354 unifi_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 */
372 void
373 unifi_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 */
402 void
403 dump(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         printk(" %02X", pdata[i]);
419
420         if (++col == 16) {
421             printk("\n");
422             col = 0;
423         }
424     }
425     if (col)
426         printk("\n");
427 } /* dump() */
428
429
430 void
431 dump16(void *mem, u16 len)
432 {
433     int i, col=0;
434     unsigned short *p = (unsigned short *)mem;
435 #ifdef ANDROID_TIMESTAMP
436     printk("timestamp %s \n", print_time());
437 #endif /* ANDROID_TIMESTAMP */
438     for (i = 0; i < len; i+=2) {
439         if (col == 0)
440             printk("0x%02X: ", i);
441
442         printk(" %04X", *p++);
443
444         if (++col == 8) {
445             printk("\n");
446             col = 0;
447         }
448     }
449     if (col)
450         printk("\n");
451 }
452
453
454 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
455 void
456 dump_str(void *mem, u16 len)
457 {
458     int i;
459     unsigned char *pdata = (unsigned char *)mem;
460 #ifdef ANDROID_TIMESTAMP
461     printk("timestamp %s \n", print_time());
462 #endif /* ANDROID_TIMESTAMP */
463     for (i = 0; i < len; i++) {
464         printk("%c", pdata[i]);
465     }
466         printk("\n");
467
468 } /* dump_str() */
469 #endif /* CSR_ONLY_NOTES */
470
471
472 #endif /* UNIFI_DEBUG */
473
474
475 /* ---------------------------------------------------------------------------
476  *                              - End -
477  * ------------------------------------------------------------------------- */