Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
os.c
Go to the documentation of this file.
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 
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  */
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 
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 
432 void
433 dump16(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
459 void
460 dump_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  * ------------------------------------------------------------------------- */