1 /****************************************************************************
2 * Driver for Solarflare network controllers -
3 * resource management for Xen backend, OpenOnload, etc
4 * (including support for SFE4001 10GBT NIC)
6 * This file provides efhw_page_t and efhw_iopage_t for Linux kernel.
8 * Copyright 2005-2007: Solarflare Communications Inc,
9 * 9501 Jeronimo Road, Suite 250,
10 * Irvine, CA 92618, USA
12 * Developed and maintained by Solarflare Communications:
13 * <linux-xen-drivers@solarflare.com>
14 * <onload-dev@solarflare.com>
16 * Certain parts of the driver were implemented by
17 * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
18 * OKTET Labs Ltd, Russia,
19 * http://oktetlabs.ru, <info@oktetlabs.ru>
20 * by request of Solarflare Communications
23 * This program is free software; you can redistribute it and/or modify it
24 * under the terms of the GNU General Public License version 2 as published
25 * by the Free Software Foundation, incorporated herein by reference.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 ****************************************************************************
38 #ifndef __CI_EFHW_IOPAGE_LINUX_H__
39 #define __CI_EFHW_IOPAGE_LINUX_H__
41 #include <linux/gfp.h>
42 #include <linux/hardirq.h>
43 #include <ci/efhw/debug.h>
45 /*--------------------------------------------------------------------
47 * efhw_page_t: A single page of memory. Directly mapped in the driver,
48 * and can be mapped to userlevel.
50 *--------------------------------------------------------------------*/
56 static inline int efhw_page_alloc(efhw_page_t *p)
58 p->kva = __get_free_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
59 return p->kva ? 0 : -ENOMEM;
62 static inline int efhw_page_alloc_zeroed(efhw_page_t *p)
64 p->kva = get_zeroed_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
65 return p->kva ? 0 : -ENOMEM;
68 static inline void efhw_page_free(efhw_page_t *p)
71 EFHW_DO_DEBUG(memset(p, 0, sizeof(*p)));
74 static inline char *efhw_page_ptr(efhw_page_t *p)
76 return (char *)p->kva;
79 static inline unsigned efhw_page_pfn(efhw_page_t *p)
81 return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
84 static inline void efhw_page_mark_invalid(efhw_page_t *p)
89 static inline int efhw_page_is_valid(efhw_page_t *p)
94 static inline void efhw_page_init_from_va(efhw_page_t *p, void *va)
96 p->kva = (unsigned long)va;
99 /*--------------------------------------------------------------------
101 * efhw_iopage_t: A single page of memory. Directly mapped in the driver,
102 * and can be mapped to userlevel. Can also be accessed by the NIC.
104 *--------------------------------------------------------------------*/
111 static inline dma_addr_t efhw_iopage_dma_addr(efhw_iopage_t *p)
116 #define efhw_iopage_ptr(iop) efhw_page_ptr(&(iop)->p)
117 #define efhw_iopage_pfn(iop) efhw_page_pfn(&(iop)->p)
118 #define efhw_iopage_mark_invalid(iop) efhw_page_mark_invalid(&(iop)->p)
119 #define efhw_iopage_is_valid(iop) efhw_page_is_valid(&(iop)->p)
121 /*--------------------------------------------------------------------
123 * efhw_iopages_t: A set of pages that are contiguous in physical memory.
124 * Directly mapped in the driver, and can be mapped to userlevel. Can also
125 * be accessed by the NIC.
127 * NB. The O/S may be unwilling to allocate many, or even any of these. So
128 * only use this type where the NIC really needs a physically contiguous
131 *--------------------------------------------------------------------*/
139 static inline caddr_t efhw_iopages_ptr(efhw_iopages_t *p)
144 static inline unsigned efhw_iopages_pfn(efhw_iopages_t *p)
146 return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
149 static inline dma_addr_t efhw_iopages_dma_addr(efhw_iopages_t *p)
154 static inline unsigned efhw_iopages_size(efhw_iopages_t *p)
156 return 1u << (p->order + PAGE_SHIFT);
159 /* efhw_iopage_t <-> efhw_iopages_t conversions for handling physically
160 * contiguous allocations in iobufsets for iSCSI. This allows the
161 * essential information about contiguous allocations from
162 * efhw_iopages_alloc() to be saved away in the efhw_iopage_t array in an
163 * iobufset. (Changing the iobufset resource to use a union type would
164 * involve a lot of code changes, and make the iobufset's metadata larger
165 * which could be bad as it's supposed to fit into a single page on some
169 efhw_iopage_init_from_iopages(efhw_iopage_t *iopage,
170 efhw_iopages_t *iopages, unsigned pageno)
172 iopage->p.kva = ((unsigned long)efhw_iopages_ptr(iopages))
173 + (pageno * PAGE_SIZE);
174 iopage->dma_addr = efhw_iopages_dma_addr(iopages) +
175 (pageno * PAGE_SIZE);
179 efhw_iopages_init_from_iopage(efhw_iopages_t *iopages,
180 efhw_iopage_t *iopage, unsigned order)
182 iopages->kva = (caddr_t) efhw_iopage_ptr(iopage);
183 EFHW_ASSERT(iopages->kva);
184 iopages->order = order;
185 iopages->dma_addr = efhw_iopage_dma_addr(iopage);
188 #endif /* __CI_EFHW_IOPAGE_LINUX_H__ */