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 struct efhw_page and struct efhw_iopage for Linux
9 * Copyright 2005-2007: Solarflare Communications Inc,
10 * 9501 Jeronimo Road, Suite 250,
11 * Irvine, CA 92618, USA
13 * Developed and maintained by Solarflare Communications:
14 * <linux-xen-drivers@solarflare.com>
15 * <onload-dev@solarflare.com>
17 * Certain parts of the driver were implemented by
18 * Alexandra Kossovsky <Alexandra.Kossovsky@oktetlabs.ru>
19 * OKTET Labs Ltd, Russia,
20 * http://oktetlabs.ru, <info@oktetlabs.ru>
21 * by request of Solarflare Communications
24 * This program is free software; you can redistribute it and/or modify it
25 * under the terms of the GNU General Public License version 2 as published
26 * by the Free Software Foundation, incorporated herein by reference.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 ****************************************************************************
39 #ifndef __CI_EFHW_IOPAGE_LINUX_H__
40 #define __CI_EFHW_IOPAGE_LINUX_H__
42 #include <linux/gfp.h>
43 #include <linux/hardirq.h>
44 #include <linux/errno.h>
45 #include <ci/efhw/debug.h>
47 /*--------------------------------------------------------------------
49 * struct efhw_page: A single page of memory. Directly mapped in the
50 * driver, and can be mapped to userlevel.
52 *--------------------------------------------------------------------*/
58 static inline int efhw_page_alloc(struct efhw_page *p)
60 p->kva = __get_free_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
61 return p->kva ? 0 : -ENOMEM;
64 static inline int efhw_page_alloc_zeroed(struct efhw_page *p)
66 p->kva = get_zeroed_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
67 return p->kva ? 0 : -ENOMEM;
70 static inline void efhw_page_free(struct efhw_page *p)
73 EFHW_DO_DEBUG(memset(p, 0, sizeof(*p)));
76 static inline char *efhw_page_ptr(struct efhw_page *p)
78 return (char *)p->kva;
81 static inline unsigned efhw_page_pfn(struct efhw_page *p)
83 return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
86 static inline void efhw_page_mark_invalid(struct efhw_page *p)
91 static inline int efhw_page_is_valid(struct efhw_page *p)
96 static inline void efhw_page_init_from_va(struct efhw_page *p, void *va)
98 p->kva = (unsigned long)va;
101 /*--------------------------------------------------------------------
103 * struct efhw_iopage: A single page of memory. Directly mapped in the driver,
104 * and can be mapped to userlevel. Can also be accessed by the NIC.
106 *--------------------------------------------------------------------*/
113 static inline dma_addr_t efhw_iopage_dma_addr(struct efhw_iopage *p)
118 #define efhw_iopage_ptr(iop) efhw_page_ptr(&(iop)->p)
119 #define efhw_iopage_pfn(iop) efhw_page_pfn(&(iop)->p)
120 #define efhw_iopage_mark_invalid(iop) efhw_page_mark_invalid(&(iop)->p)
121 #define efhw_iopage_is_valid(iop) efhw_page_is_valid(&(iop)->p)
123 /*--------------------------------------------------------------------
125 * struct efhw_iopages: A set of pages that are contiguous in physical
126 * memory. Directly mapped in the driver, and can be mapped to userlevel.
127 * Can also be accessed by the NIC.
129 * NB. The O/S may be unwilling to allocate many, or even any of these. So
130 * only use this type where the NIC really needs a physically contiguous
133 *--------------------------------------------------------------------*/
135 struct efhw_iopages {
141 static inline caddr_t efhw_iopages_ptr(struct efhw_iopages *p)
146 static inline unsigned efhw_iopages_pfn(struct efhw_iopages *p)
148 return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
151 static inline dma_addr_t efhw_iopages_dma_addr(struct efhw_iopages *p)
156 static inline unsigned efhw_iopages_size(struct efhw_iopages *p)
158 return 1u << (p->order + PAGE_SHIFT);
161 /* struct efhw_iopage <-> struct efhw_iopages conversions for handling
162 * physically contiguous allocations in iobufsets for iSCSI. This allows
163 * the essential information about contiguous allocations from
164 * efhw_iopages_alloc() to be saved away in the struct efhw_iopage array in
165 * an iobufset. (Changing the iobufset resource to use a union type would
166 * involve a lot of code changes, and make the iobufset's metadata larger
167 * which could be bad as it's supposed to fit into a single page on some
171 efhw_iopage_init_from_iopages(struct efhw_iopage *iopage,
172 struct efhw_iopages *iopages, unsigned pageno)
174 iopage->p.kva = ((unsigned long)efhw_iopages_ptr(iopages))
175 + (pageno * PAGE_SIZE);
176 iopage->dma_addr = efhw_iopages_dma_addr(iopages) +
177 (pageno * PAGE_SIZE);
181 efhw_iopages_init_from_iopage(struct efhw_iopages *iopages,
182 struct efhw_iopage *iopage, unsigned order)
184 iopages->kva = (caddr_t) efhw_iopage_ptr(iopage);
185 EFHW_ASSERT(iopages->kva);
186 iopages->order = order;
187 iopages->dma_addr = efhw_iopage_dma_addr(iopage);
190 #endif /* __CI_EFHW_IOPAGE_LINUX_H__ */