gfp.h revision 293419
119304Speter/*-
219304Speter * Copyright (c) 2010 Isilon Systems, Inc.
319304Speter * Copyright (c) 2010 iX Systems, Inc.
419304Speter * Copyright (c) 2010 Panasas, Inc.
519304Speter * Copyright (c) 2013 Mellanox Technologies, Ltd.
619304Speter * All rights reserved.
719304Speter *
819304Speter * Redistribution and use in source and binary forms, with or without
919304Speter * modification, are permitted provided that the following conditions
1019304Speter * are met:
1119304Speter * 1. Redistributions of source code must retain the above copyright
1219304Speter *    notice unmodified, this list of conditions, and the following
13254225Speter *    disclaimer.
1419304Speter * 2. Redistributions in binary form must reproduce the above copyright
1519304Speter *    notice, this list of conditions and the following disclaimer in the
1619304Speter *    documentation and/or other materials provided with the distribution.
1719304Speter *
1819304Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1919304Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2019304Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2119304Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2219304Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2319304Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2419304Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2519304Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2619304Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2719304Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2819304Speter *
2919304Speter * $FreeBSD: head/sys/compat/linuxkpi/common/include/linux/gfp.h 293419 2016-01-08 10:04:19Z hselasky $
3019304Speter */
3119304Speter#ifndef	_LINUX_GFP_H_
3219304Speter#define	_LINUX_GFP_H_
3319304Speter
3419304Speter#include <sys/cdefs.h>
3519304Speter#include <sys/types.h>
3619304Speter#include <sys/systm.h>
37254225Speter#include <sys/malloc.h>
3819304Speter
3919304Speter#include <linux/page.h>
4019304Speter
4119304Speter#include <vm/vm_param.h>
4219304Speter#include <vm/vm_object.h>
4319304Speter#include <vm/vm_extern.h>
4419304Speter#include <vm/vm_kern.h>
4519304Speter
4619304Speter#define	__GFP_NOWARN	0
4719304Speter#define	__GFP_HIGHMEM	0
4819304Speter#define	__GFP_ZERO	M_ZERO
4919304Speter
5019304Speter#define	GFP_NOWAIT	M_NOWAIT
5119304Speter#define	GFP_ATOMIC	(M_NOWAIT | M_USE_RESERVE)
5219304Speter#define	GFP_KERNEL	M_WAITOK
5319304Speter#define	GFP_USER	M_WAITOK
5419304Speter#define	GFP_HIGHUSER	M_WAITOK
5519304Speter#define	GFP_HIGHUSER_MOVABLE	M_WAITOK
5619304Speter#define	GFP_IOFS	M_NOWAIT
5719304Speter
5819304Speterstatic inline void *
5919304Speterpage_address(struct page *page)
60254225Speter{
61254225Speter
62254225Speter	if (page->object != kmem_object && page->object != kernel_object)
63254225Speter		return (NULL);
64254225Speter	return ((void *)(uintptr_t)(VM_MIN_KERNEL_ADDRESS +
6519304Speter	    IDX_TO_OFF(page->pindex)));
6619304Speter}
6719304Speter
6819304Speterstatic inline unsigned long
6919304Speterlinux_get_page(gfp_t mask)
7019304Speter{
7119304Speter
7219304Speter	return kmem_malloc(kmem_arena, PAGE_SIZE, mask);
7319304Speter}
7419304Speter
7519304Speter#define	get_zeroed_page(mask)	linux_get_page((mask) | M_ZERO)
7619304Speter#define	alloc_page(mask)	virt_to_page(linux_get_page((mask)))
7719304Speter#define	__get_free_page(mask)	linux_get_page((mask))
7819304Speter
7919304Speterstatic inline void
8019304Speterfree_page(unsigned long page)
8119304Speter{
8219304Speter
8319304Speter	if (page == 0)
8419304Speter		return;
85254225Speter	kmem_free(kmem_arena, page, PAGE_SIZE);
8619304Speter}
8719304Speter
8819304Speterstatic inline void
8919304Speter__free_page(struct page *m)
9019304Speter{
9119304Speter
9219304Speter	if (m->object != kmem_object)
9319304Speter		panic("__free_page:  Freed page %p not allocated via wrappers.",
9419304Speter		    m);
95254225Speter	kmem_free(kmem_arena, (vm_offset_t)page_address(m), PAGE_SIZE);
96254225Speter}
9719304Speter
9819304Speterstatic inline void
9919304Speter__free_pages(struct page *m, unsigned int order)
10019304Speter{
10119304Speter	size_t size;
10219304Speter
10319304Speter	if (m == NULL)
10419304Speter		return;
10519304Speter	size = PAGE_SIZE << order;
10619304Speter	kmem_free(kmem_arena, (vm_offset_t)page_address(m), size);
10719304Speter}
10819304Speter
10919304Speterstatic inline void free_pages(uintptr_t addr, unsigned int order)
11019304Speter{
11119304Speter	if (addr == 0)
11219304Speter		return;
11319304Speter	__free_pages(virt_to_page((void *)addr), order);
11419304Speter}
11519304Speter
116254225Speter/*
11719304Speter * Alloc pages allocates directly from the buddy allocator on linux so
11819304Speter * order specifies a power of two bucket of pages and the results
119254225Speter * are expected to be aligned on the size as well.
120254225Speter */
12119304Speterstatic inline struct page *
12219304Speteralloc_pages(gfp_t gfp_mask, unsigned int order)
12319304Speter{
12419304Speter	unsigned long page;
12519304Speter	size_t size;
12619304Speter
12719304Speter	size = PAGE_SIZE << order;
12819304Speter	page = kmem_alloc_contig(kmem_arena, size, gfp_mask, 0, -1,
12919304Speter	    size, 0, VM_MEMATTR_DEFAULT);
130	if (page == 0)
131		return (NULL);
132        return (virt_to_page(page));
133}
134
135static inline uintptr_t __get_free_pages(gfp_t gfp_mask, unsigned int order)
136{
137	struct page *page;
138
139	page = alloc_pages(gfp_mask, order);
140	if (page == NULL)
141		return (0);
142	return ((uintptr_t)page_address(page));
143}
144
145#define alloc_pages_node(node, mask, order)     alloc_pages(mask, order)
146
147#define kmalloc_node(chunk, mask, node)         kmalloc(chunk, mask)
148
149#endif	/* _LINUX_GFP_H_ */
150