- supported.conf: Added sparse_keymap (eeepc_laptop depends on it)
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / sfc_netback / ci / tools / platform / linux_kernel.h
1 /****************************************************************************
2  * Copyright 2002-2005: Level 5 Networks Inc.
3  * Copyright 2005-2008: Solarflare Communications Inc,
4  *                      9501 Jeronimo Road, Suite 250,
5  *                      Irvine, CA 92618, USA
6  *
7  * Maintained by Solarflare Communications
8  *  <linux-xen-drivers@solarflare.com>
9  *  <onload-dev@solarflare.com>
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License version 2 as published
13  * by the Free Software Foundation, incorporated herein by reference.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23  ****************************************************************************
24  */
25
26
27 /*! \cidoxg_include_ci_tools_platform  */
28
29 #ifndef __CI_TOOLS_LINUX_KERNEL_H__
30 #define __CI_TOOLS_LINUX_KERNEL_H__
31
32 /**********************************************************************
33  * Need to know the kernel version.
34  */
35
36 #ifndef LINUX_VERSION_CODE
37 # include <linux/version.h>
38 # ifndef UTS_RELEASE
39    /* 2.6.18 onwards defines UTS_RELEASE in a separate header */
40 #  include <linux/utsrelease.h>
41 # endif
42 #endif
43
44 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) || \
45     LINUX_VERSION_CODE >= KERNEL_VERSION(2,7,0)
46 # error "Linux 2.6 required"
47 #endif
48
49
50 #include <linux/slab.h>     /* kmalloc / kfree */
51 #include <linux/vmalloc.h>  /* vmalloc / vfree */
52 #include <linux/interrupt.h>/* in_interrupt()  */
53 #include <linux/in.h>
54 #include <linux/in6.h>
55 #include <linux/spinlock.h>
56 #include <linux/highmem.h>
57 #include <linux/smp_lock.h>
58 #include <linux/ctype.h>
59 #include <linux/uio.h>
60 #include <asm/current.h>
61 #include <asm/errno.h>
62 #include <asm/kmap_types.h>
63 #include <asm/semaphore.h>
64
65 #include <ci/tools/config.h>
66
67 #define ci_in_irq        in_irq
68 #define ci_in_interrupt  in_interrupt
69 #define ci_in_atomic     in_atomic
70
71
72 /**********************************************************************
73  * Misc stuff.
74  */
75
76 #ifdef BUG
77 # define  CI_BOMB     BUG
78 #endif
79
80 ci_inline void* __ci_alloc(size_t n)
81 { return kmalloc(n, (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)); }
82
83 ci_inline void* __ci_atomic_alloc(size_t n)
84 { return kmalloc(n, GFP_ATOMIC ); }
85
86 ci_inline void  __ci_free(void* p)     { return kfree(p);   }
87 ci_inline void* __ci_vmalloc(size_t n) { return vmalloc(n); }
88 ci_inline void  __ci_vfree(void* p)    { return vfree(p);   }
89
90
91 #if CI_MEMLEAK_DEBUG_ALLOC_TABLE
92   #define ci_alloc(s)     ci_alloc_memleak_debug (s, __FILE__, __LINE__)
93   #define ci_atomic_alloc(s)  ci_atomic_alloc_memleak_debug(s, __FILE__, __LINE__)
94   #define ci_free         ci_free_memleak_debug
95   #define ci_vmalloc(s)   ci_vmalloc_memleak_debug (s, __FILE__,__LINE__)
96   #define ci_vfree        ci_vfree_memleak_debug
97   #define ci_alloc_fn     ci_alloc_fn_memleak_debug
98   #define ci_vmalloc_fn   ci_vmalloc_fn_memleak_debug
99 #else /* !CI_MEMLEAK_DEBUG_ALLOC_TABLE */
100   #define ci_alloc_fn     __ci_alloc
101   #define ci_vmalloc_fn   __ci_vmalloc
102 #endif 
103
104 #ifndef ci_alloc
105   #define ci_atomic_alloc __ci_atomic_alloc
106   #define ci_alloc        __ci_alloc
107   #define ci_free         __ci_free
108   #define ci_vmalloc      __ci_vmalloc
109   #define ci_vmalloc_fn   __ci_vmalloc
110   #define ci_vfree        __ci_vfree
111 #endif
112
113 #define ci_sprintf        sprintf
114 #define ci_vsprintf       vsprintf
115 #define ci_snprintf       snprintf
116 #define ci_vsnprintf      vsnprintf
117 #define ci_sscanf         sscanf
118
119
120 #define CI_LOG_FN_DEFAULT  ci_log_syslog
121
122
123 /*--------------------------------------------------------------------
124  *
125  * irqs_disabled - needed for kmap helpers on some kernels 
126  *
127  *--------------------------------------------------------------------*/
128 #ifdef irqs_disabled
129 # define ci_irqs_disabled irqs_disabled
130 #else
131 # if defined(__i386__) | defined(__x86_64__)
132 #   define ci_irqs_disabled(x)                  \
133   ({                                            \
134     unsigned long flags;                        \
135     local_save_flags(flags);                    \
136     !(flags & (1<<9));                          \
137   })
138 # else
139 #  error "Need to implement irqs_disabled() for your architecture"
140 # endif
141 #endif
142
143
144 /**********************************************************************
145  * kmap helpers. 
146  *
147  * Use ci_k(un)map for code paths which are not in an atomic context.
148  * For atomic code you need to use ci_k(un)map_in_atomic. This will grab
149  * one of the per-CPU kmap slots.
150  *
151  * NB in_interrupt != in_irq. If you don't know the difference then
152  * don't use kmap_in_atomic
153  *
154  * 2.4 allocates kmap slots by function. We are going to re-use the
155  * skb module's slot - we also use the same interlock
156  * 
157  * 2.6 allocates kmap slots by type as well as by function. We are
158  * going to use the currently (2.6.10) unsused SOFTIRQ slot 
159  *
160  */
161
162 ci_inline void* ci_kmap(struct page *page) {
163   CI_DEBUG(if( ci_in_atomic() | ci_in_interrupt() | ci_in_irq() )  BUG());
164   return kmap(page);
165 }
166
167 ci_inline void ci_kunmap(struct page *page) {
168   kunmap(page);
169 }
170
171 #define CI_KM_SLOT KM_SOFTIRQ0
172
173
174 typedef struct semaphore ci_semaphore_t;
175
176 ci_inline void
177 ci_sem_init (ci_semaphore_t *sem, int val) {
178   sema_init (sem, val);
179 }
180
181 ci_inline void
182 ci_sem_down (ci_semaphore_t *sem) {
183   down (sem);
184 }
185
186 ci_inline int
187 ci_sem_trydown (ci_semaphore_t *sem) {
188   return down_trylock (sem);
189 }
190
191 ci_inline void
192 ci_sem_up (ci_semaphore_t *sem) {
193   up (sem);
194 }
195
196 ci_inline int
197 ci_sem_get_count(ci_semaphore_t *sem) {
198   return sem->count.counter;
199 }
200
201 ci_inline void* ci_kmap_in_atomic(struct page *page) 
202 {
203   CI_DEBUG(if( ci_in_irq() )  BUG());
204
205   /* iSCSI can call without in_interrupt() but with irqs_disabled()
206      and in a context that can't sleep, so we need to check that
207      too */
208   if(ci_in_interrupt() || ci_irqs_disabled())
209     return kmap_atomic(page, CI_KM_SLOT);
210   else
211     return kmap(page);
212 }
213
214 ci_inline void ci_kunmap_in_atomic(struct page *page, void* kaddr) 
215 {
216   CI_DEBUG(if( ci_in_irq() )  BUG());
217
218   /* iSCSI can call without in_interrupt() but with irqs_disabled()
219      and in a context that can't sleep, so we need to check that
220      too */
221   if(ci_in_interrupt() || ci_irqs_disabled())
222     kunmap_atomic(kaddr, CI_KM_SLOT);
223   else
224     kunmap(page);
225 }
226
227 /**********************************************************************
228  * spinlock implementation: used by <ci/tools/spinlock.h>
229  */
230
231 #define CI_HAVE_SPINLOCKS
232
233 typedef ci_uintptr_t                            ci_lock_holder_t;
234 #define ci_lock_thisthread              (ci_lock_holder_t)current                       
235 #define ci_lock_no_holder     (ci_lock_holder_t)NULL
236
237 typedef spinlock_t                      ci_lock_i;
238 typedef spinlock_t                      ci_irqlock_i;
239 typedef unsigned long                   ci_irqlock_state_t;
240
241 #define IRQLOCK_CYCLES  500000
242
243 #define ci_lock_ctor_i(l)               spin_lock_init(l)
244 #define ci_lock_dtor_i(l)               do{}while(0)
245 #define ci_lock_lock_i(l)               spin_lock(l)
246 #define ci_lock_trylock_i(l)            spin_trylock(l)
247 #define ci_lock_unlock_i(l)             spin_unlock(l)
248
249 #define ci_irqlock_ctor_i(l)            spin_lock_init(l)
250 #define ci_irqlock_dtor_i(l)            do{}while(0)
251 #define ci_irqlock_lock_i(l,s)          spin_lock_irqsave(l,*(s))
252 #define ci_irqlock_unlock_i(l,s)        spin_unlock_irqrestore(l, *(s))
253
254
255 /**********************************************************************
256  * register access
257  */
258
259 #include <asm/io.h>
260
261 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
262 typedef volatile void __iomem*  ioaddr_t;
263 #else
264 typedef unsigned long ioaddr_t;
265 #endif
266
267
268
269 /**********************************************************************
270  * thread implementation -- kernel dependancies probably should be
271  * moved to driver/linux_kernel.h
272  */
273
274 #define ci_linux_daemonize(name) daemonize(name)
275
276 #include <linux/workqueue.h>
277
278
279 typedef struct {
280   void*                 (*fn)(void* arg);
281   void*                 arg;
282   const char*           name;
283   int                   thrd_id;
284   struct completion     exit_event;
285   struct work_struct    keventd_witem;
286 } ci_kernel_thread_t;
287
288
289 typedef ci_kernel_thread_t* cithread_t;
290
291
292 extern int cithread_create(cithread_t* tid, void* (*fn)(void*), void* arg,
293                            const char* name);
294 extern int cithread_detach(cithread_t kt);
295 extern int cithread_join(cithread_t kt);
296
297
298 /* Kernel sysctl variables. */
299 extern int sysctl_tcp_wmem[3];
300 extern int sysctl_tcp_rmem[3];
301 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
302 #define LINUX_HAS_SYSCTL_MEM_MAX
303 extern ci_uint32 sysctl_wmem_max;
304 extern ci_uint32 sysctl_rmem_max;
305 #endif
306
307
308 /*--------------------------------------------------------------------
309  *
310  * ci_bigbuf_t: An abstraction of a large buffer.  Needed because in the
311  * Linux kernel, large buffers need to be allocated with vmalloc(), whereas
312  * smaller buffers should use kmalloc().  This abstraction chooses the
313  * appropriate mechansim.
314  *
315  *--------------------------------------------------------------------*/
316
317 typedef struct {
318   char*         p;
319   int           is_vmalloc;
320 } ci_bigbuf_t;
321
322
323 ci_inline int ci_bigbuf_alloc(ci_bigbuf_t* bb, size_t bytes) {
324   if( bytes >= CI_PAGE_SIZE && ! ci_in_atomic() ) {
325     bb->is_vmalloc = 1;
326     if( (bb->p = vmalloc(bytes)) )  return 0;
327   }
328   bb->is_vmalloc = 0;
329   bb->p = kmalloc(bytes, ci_in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
330   return bb->p ? 0 : -ENOMEM;
331 }
332
333 ci_inline void ci_bigbuf_free(ci_bigbuf_t* bb) {
334   if( bb->is_vmalloc )  vfree(bb->p);
335   else                  kfree(bb->p);
336 }
337
338 ci_inline char* ci_bigbuf_ptr(ci_bigbuf_t* bb)
339 { return bb->p; }
340
341 /**********************************************************************
342  * struct iovec abstraction (for Windows port)
343  */
344
345 typedef struct iovec ci_iovec;
346
347 /* Accessors for buffer/length */
348 #define CI_IOVEC_BASE(i) ((i)->iov_base)
349 #define CI_IOVEC_LEN(i)  ((i)->iov_len)
350
351 /**********************************************************************
352  * Signals
353  */
354
355 ci_inline void
356 ci_send_sig(int signum)
357 {
358   send_sig(signum, current, 0);
359 }
360
361 #endif  /* __CI_TOOLS_LINUX_KERNEL_H__ */
362 /*! \cidoxg_end */