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
7 * Maintained by Solarflare Communications
8 * <linux-xen-drivers@solarflare.com>
9 * <onload-dev@solarflare.com>
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.
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.
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 ****************************************************************************
27 /*! \cidoxg_include_ci_tools_platform */
29 #ifndef __CI_TOOLS_LINUX_KERNEL_H__
30 #define __CI_TOOLS_LINUX_KERNEL_H__
32 /**********************************************************************
33 * Need to know the kernel version.
36 #ifndef LINUX_VERSION_CODE
37 # include <linux/version.h>
39 /* 2.6.18 onwards defines UTS_RELEASE in a separate header */
40 # include <linux/utsrelease.h>
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"
50 #include <linux/slab.h> /* kmalloc / kfree */
51 #include <linux/vmalloc.h> /* vmalloc / vfree */
52 #include <linux/interrupt.h>/* in_interrupt() */
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>
64 #include <ci/tools/config.h>
66 #define ci_in_irq in_irq
67 #define ci_in_interrupt in_interrupt
68 #define ci_in_atomic in_atomic
71 /**********************************************************************
79 ci_inline void* __ci_alloc(size_t n)
80 { return kmalloc(n, (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)); }
82 ci_inline void* __ci_atomic_alloc(size_t n)
83 { return kmalloc(n, GFP_ATOMIC ); }
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); }
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
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
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
119 #define CI_LOG_FN_DEFAULT ci_log_syslog
122 /*--------------------------------------------------------------------
124 * irqs_disabled - needed for kmap helpers on some kernels
126 *--------------------------------------------------------------------*/
128 # define ci_irqs_disabled irqs_disabled
130 # if defined(__i386__) | defined(__x86_64__)
131 # define ci_irqs_disabled(x) \
133 unsigned long flags; \
134 local_save_flags(flags); \
138 # error "Need to implement irqs_disabled() for your architecture"
143 /**********************************************************************
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.
150 * NB in_interrupt != in_irq. If you don't know the difference then
151 * don't use kmap_in_atomic
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
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
161 ci_inline void* ci_kmap(struct page *page) {
162 CI_DEBUG(if( ci_in_atomic() | ci_in_interrupt() | ci_in_irq() ) BUG());
166 ci_inline void ci_kunmap(struct page *page) {
170 #define CI_KM_SLOT KM_SOFTIRQ0
173 typedef struct semaphore ci_semaphore_t;
176 ci_sem_init (ci_semaphore_t *sem, int val) {
177 sema_init (sem, val);
181 ci_sem_down (ci_semaphore_t *sem) {
186 ci_sem_trydown (ci_semaphore_t *sem) {
187 return down_trylock (sem);
191 ci_sem_up (ci_semaphore_t *sem) {
196 ci_sem_get_count(ci_semaphore_t *sem) {
197 return sem->count.counter;
200 ci_inline void* ci_kmap_in_atomic(struct page *page)
202 CI_DEBUG(if( ci_in_irq() ) BUG());
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
207 if(ci_in_interrupt() || ci_irqs_disabled())
208 return kmap_atomic(page, CI_KM_SLOT);
213 ci_inline void ci_kunmap_in_atomic(struct page *page, void* kaddr)
215 CI_DEBUG(if( ci_in_irq() ) BUG());
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
220 if(ci_in_interrupt() || ci_irqs_disabled())
221 kunmap_atomic(kaddr, CI_KM_SLOT);
226 /**********************************************************************
227 * spinlock implementation: used by <ci/tools/spinlock.h>
230 #define CI_HAVE_SPINLOCKS
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
236 typedef spinlock_t ci_lock_i;
237 typedef spinlock_t ci_irqlock_i;
238 typedef unsigned long ci_irqlock_state_t;
240 #define IRQLOCK_CYCLES 500000
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)
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))
254 /**********************************************************************
260 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
261 typedef volatile void __iomem* ioaddr_t;
263 typedef unsigned long ioaddr_t;
268 /**********************************************************************
269 * thread implementation -- kernel dependancies probably should be
270 * moved to driver/linux_kernel.h
273 #define ci_linux_daemonize(name) daemonize(name)
275 #include <linux/workqueue.h>
279 void* (*fn)(void* arg);
283 struct completion exit_event;
284 struct work_struct keventd_witem;
285 } ci_kernel_thread_t;
288 typedef ci_kernel_thread_t* cithread_t;
291 extern int cithread_create(cithread_t* tid, void* (*fn)(void*), void* arg,
293 extern int cithread_detach(cithread_t kt);
294 extern int cithread_join(cithread_t kt);
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;
307 /*--------------------------------------------------------------------
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.
314 *--------------------------------------------------------------------*/
322 ci_inline int ci_bigbuf_alloc(ci_bigbuf_t* bb, size_t bytes) {
323 if( bytes >= CI_PAGE_SIZE && ! ci_in_atomic() ) {
325 if( (bb->p = vmalloc(bytes)) ) return 0;
328 bb->p = kmalloc(bytes, ci_in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
329 return bb->p ? 0 : -ENOMEM;
332 ci_inline void ci_bigbuf_free(ci_bigbuf_t* bb) {
333 if( bb->is_vmalloc ) vfree(bb->p);
337 ci_inline char* ci_bigbuf_ptr(ci_bigbuf_t* bb)
340 /**********************************************************************
341 * struct iovec abstraction (for Windows port)
344 typedef struct iovec ci_iovec;
346 /* Accessors for buffer/length */
347 #define CI_IOVEC_BASE(i) ((i)->iov_base)
348 #define CI_IOVEC_LEN(i) ((i)->iov_len)
350 /**********************************************************************
355 ci_send_sig(int signum)
357 send_sig(signum, current, 0);
360 #endif /* __CI_TOOLS_LINUX_KERNEL_H__ */