- Update Xen patches to 3.3-rc5 and c/s 1157.
[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/ctype.h>
58 #include <linux/uio.h>
59 #include <asm/current.h>
60 #include <asm/errno.h>
61 #include <asm/kmap_types.h>
62 #include <asm/semaphore.h>
63
64 #include <ci/tools/config.h>
65
66 #define ci_in_irq        in_irq
67 #define ci_in_interrupt  in_interrupt
68 #define ci_in_atomic     in_atomic
69
70
71 /**********************************************************************
72  * Misc stuff.
73  */
74
75 #ifdef BUG
76 # define  CI_BOMB     BUG
77 #endif
78
79 ci_inline void* __ci_alloc(size_t n)
80 { return kmalloc(n, (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)); }
81
82 ci_inline void* __ci_atomic_alloc(size_t n)
83 { return kmalloc(n, GFP_ATOMIC ); }
84
85 ci_inline void  __ci_free(void* p)     { return kfree(p);   }
86 ci_inline void* __ci_vmalloc(size_t n) { return vmalloc(n); }
87 ci_inline void  __ci_vfree(void* p)    { return vfree(p);   }
88
89
90 #if CI_MEMLEAK_DEBUG_ALLOC_TABLE
91   #define ci_alloc(s)     ci_alloc_memleak_debug (s, __FILE__, __LINE__)
92   #define ci_atomic_alloc(s)  ci_atomic_alloc_memleak_debug(s, __FILE__, __LINE__)
93   #define ci_free         ci_free_memleak_debug
94   #define ci_vmalloc(s)   ci_vmalloc_memleak_debug (s, __FILE__,__LINE__)
95   #define ci_vfree        ci_vfree_memleak_debug
96   #define ci_alloc_fn     ci_alloc_fn_memleak_debug
97   #define ci_vmalloc_fn   ci_vmalloc_fn_memleak_debug
98 #else /* !CI_MEMLEAK_DEBUG_ALLOC_TABLE */
99   #define ci_alloc_fn     __ci_alloc
100   #define ci_vmalloc_fn   __ci_vmalloc
101 #endif 
102
103 #ifndef ci_alloc
104   #define ci_atomic_alloc __ci_atomic_alloc
105   #define ci_alloc        __ci_alloc
106   #define ci_free         __ci_free
107   #define ci_vmalloc      __ci_vmalloc
108   #define ci_vmalloc_fn   __ci_vmalloc
109   #define ci_vfree        __ci_vfree
110 #endif
111
112 #define ci_sprintf        sprintf
113 #define ci_vsprintf       vsprintf
114 #define ci_snprintf       snprintf
115 #define ci_vsnprintf      vsnprintf
116 #define ci_sscanf         sscanf
117
118
119 #define CI_LOG_FN_DEFAULT  ci_log_syslog
120
121
122 /*--------------------------------------------------------------------
123  *
124  * irqs_disabled - needed for kmap helpers on some kernels 
125  *
126  *--------------------------------------------------------------------*/
127 #ifdef irqs_disabled
128 # define ci_irqs_disabled irqs_disabled
129 #else
130 # if defined(__i386__) | defined(__x86_64__)
131 #   define ci_irqs_disabled(x)                  \
132   ({                                            \
133     unsigned long flags;                        \
134     local_save_flags(flags);                    \
135     !(flags & (1<<9));                          \
136   })
137 # else
138 #  error "Need to implement irqs_disabled() for your architecture"
139 # endif
140 #endif
141
142
143 /**********************************************************************
144  * kmap helpers. 
145  *
146  * Use ci_k(un)map for code paths which are not in an atomic context.
147  * For atomic code you need to use ci_k(un)map_in_atomic. This will grab
148  * one of the per-CPU kmap slots.
149  *
150  * NB in_interrupt != in_irq. If you don't know the difference then
151  * don't use kmap_in_atomic
152  *
153  * 2.4 allocates kmap slots by function. We are going to re-use the
154  * skb module's slot - we also use the same interlock
155  * 
156  * 2.6 allocates kmap slots by type as well as by function. We are
157  * going to use the currently (2.6.10) unsused SOFTIRQ slot 
158  *
159  */
160
161 ci_inline void* ci_kmap(struct page *page) {
162   CI_DEBUG(if( ci_in_atomic() | ci_in_interrupt() | ci_in_irq() )  BUG());
163   return kmap(page);
164 }
165
166 ci_inline void ci_kunmap(struct page *page) {
167   kunmap(page);
168 }
169
170 #define CI_KM_SLOT KM_SOFTIRQ0
171
172
173 typedef struct semaphore ci_semaphore_t;
174
175 ci_inline void
176 ci_sem_init (ci_semaphore_t *sem, int val) {
177   sema_init (sem, val);
178 }
179
180 ci_inline void
181 ci_sem_down (ci_semaphore_t *sem) {
182   down (sem);
183 }
184
185 ci_inline int
186 ci_sem_trydown (ci_semaphore_t *sem) {
187   return down_trylock (sem);
188 }
189
190 ci_inline void
191 ci_sem_up (ci_semaphore_t *sem) {
192   up (sem);
193 }
194
195 ci_inline int
196 ci_sem_get_count(ci_semaphore_t *sem) {
197   return sem->count.counter;
198 }
199
200 ci_inline void* ci_kmap_in_atomic(struct page *page) 
201 {
202   CI_DEBUG(if( ci_in_irq() )  BUG());
203
204   /* iSCSI can call without in_interrupt() but with irqs_disabled()
205      and in a context that can't sleep, so we need to check that
206      too */
207   if(ci_in_interrupt() || ci_irqs_disabled())
208     return kmap_atomic(page, CI_KM_SLOT);
209   else
210     return kmap(page);
211 }
212
213 ci_inline void ci_kunmap_in_atomic(struct page *page, void* kaddr) 
214 {
215   CI_DEBUG(if( ci_in_irq() )  BUG());
216
217   /* iSCSI can call without in_interrupt() but with irqs_disabled()
218      and in a context that can't sleep, so we need to check that
219      too */
220   if(ci_in_interrupt() || ci_irqs_disabled())
221     kunmap_atomic(kaddr, CI_KM_SLOT);
222   else
223     kunmap(page);
224 }
225
226 /**********************************************************************
227  * spinlock implementation: used by <ci/tools/spinlock.h>
228  */
229
230 #define CI_HAVE_SPINLOCKS
231
232 typedef ci_uintptr_t                            ci_lock_holder_t;
233 #define ci_lock_thisthread              (ci_lock_holder_t)current                       
234 #define ci_lock_no_holder     (ci_lock_holder_t)NULL
235
236 typedef spinlock_t                      ci_lock_i;
237 typedef spinlock_t                      ci_irqlock_i;
238 typedef unsigned long                   ci_irqlock_state_t;
239
240 #define IRQLOCK_CYCLES  500000
241
242 #define ci_lock_ctor_i(l)               spin_lock_init(l)
243 #define ci_lock_dtor_i(l)               do{}while(0)
244 #define ci_lock_lock_i(l)               spin_lock(l)
245 #define ci_lock_trylock_i(l)            spin_trylock(l)
246 #define ci_lock_unlock_i(l)             spin_unlock(l)
247
248 #define ci_irqlock_ctor_i(l)            spin_lock_init(l)
249 #define ci_irqlock_dtor_i(l)            do{}while(0)
250 #define ci_irqlock_lock_i(l,s)          spin_lock_irqsave(l,*(s))
251 #define ci_irqlock_unlock_i(l,s)        spin_unlock_irqrestore(l, *(s))
252
253
254 /**********************************************************************
255  * register access
256  */
257
258 #include <asm/io.h>
259
260 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
261 typedef volatile void __iomem*  ioaddr_t;
262 #else
263 typedef unsigned long ioaddr_t;
264 #endif
265
266
267
268 /**********************************************************************
269  * thread implementation -- kernel dependancies probably should be
270  * moved to driver/linux_kernel.h
271  */
272
273 #define ci_linux_daemonize(name) daemonize(name)
274
275 #include <linux/workqueue.h>
276
277
278 typedef struct {
279   void*                 (*fn)(void* arg);
280   void*                 arg;
281   const char*           name;
282   int                   thrd_id;
283   struct completion     exit_event;
284   struct work_struct    keventd_witem;
285 } ci_kernel_thread_t;
286
287
288 typedef ci_kernel_thread_t* cithread_t;
289
290
291 extern int cithread_create(cithread_t* tid, void* (*fn)(void*), void* arg,
292                            const char* name);
293 extern int cithread_detach(cithread_t kt);
294 extern int cithread_join(cithread_t kt);
295
296
297 /* Kernel sysctl variables. */
298 extern int sysctl_tcp_wmem[3];
299 extern int sysctl_tcp_rmem[3];
300 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
301 #define LINUX_HAS_SYSCTL_MEM_MAX
302 extern ci_uint32 sysctl_wmem_max;
303 extern ci_uint32 sysctl_rmem_max;
304 #endif
305
306
307 /*--------------------------------------------------------------------
308  *
309  * ci_bigbuf_t: An abstraction of a large buffer.  Needed because in the
310  * Linux kernel, large buffers need to be allocated with vmalloc(), whereas
311  * smaller buffers should use kmalloc().  This abstraction chooses the
312  * appropriate mechansim.
313  *
314  *--------------------------------------------------------------------*/
315
316 typedef struct {
317   char*         p;
318   int           is_vmalloc;
319 } ci_bigbuf_t;
320
321
322 ci_inline int ci_bigbuf_alloc(ci_bigbuf_t* bb, size_t bytes) {
323   if( bytes >= CI_PAGE_SIZE && ! ci_in_atomic() ) {
324     bb->is_vmalloc = 1;
325     if( (bb->p = vmalloc(bytes)) )  return 0;
326   }
327   bb->is_vmalloc = 0;
328   bb->p = kmalloc(bytes, ci_in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
329   return bb->p ? 0 : -ENOMEM;
330 }
331
332 ci_inline void ci_bigbuf_free(ci_bigbuf_t* bb) {
333   if( bb->is_vmalloc )  vfree(bb->p);
334   else                  kfree(bb->p);
335 }
336
337 ci_inline char* ci_bigbuf_ptr(ci_bigbuf_t* bb)
338 { return bb->p; }
339
340 /**********************************************************************
341  * struct iovec abstraction (for Windows port)
342  */
343
344 typedef struct iovec ci_iovec;
345
346 /* Accessors for buffer/length */
347 #define CI_IOVEC_BASE(i) ((i)->iov_base)
348 #define CI_IOVEC_LEN(i)  ((i)->iov_len)
349
350 /**********************************************************************
351  * Signals
352  */
353
354 ci_inline void
355 ci_send_sig(int signum)
356 {
357   send_sig(signum, current, 0);
358 }
359
360 #endif  /* __CI_TOOLS_LINUX_KERNEL_H__ */
361 /*! \cidoxg_end */