/* SPDX-License-Identifier: GPL-2.0-only */ #ifndef _ASM_POWERPC_RTAS_WORK_AREA_H #define _ASM_POWERPC_RTAS_WORK_AREA_H #include <linux/build_bug.h> #include <linux/sizes.h> #include <linux/types.h> #include <asm/page.h> /** * struct rtas_work_area - RTAS work area descriptor. * * Descriptor for a "work area" in PAPR terminology that satisfies * RTAS addressing requirements. */ struct rtas_work_area { /* private: Use the APIs provided below. */ char *buf; size_t size; }; enum { /* Maximum allocation size, enforced at build time. */ RTAS_WORK_AREA_MAX_ALLOC_SZ = SZ_128K, }; /** * rtas_work_area_alloc() - Acquire a work area of the requested size. * @size_: Allocation size. Must be compile-time constant and not more * than %RTAS_WORK_AREA_MAX_ALLOC_SZ. * * Allocate a buffer suitable for passing to RTAS functions that have * a memory address parameter, often (but not always) referred to as a * "work area" in PAPR. Although callers are allowed to block while * holding a work area, the amount of memory reserved for this purpose * is limited, and allocations should be short-lived. A good guideline * is to release any allocated work area before returning from a * system call. * * This function does not fail. It blocks until the allocation * succeeds. To prevent deadlocks, callers are discouraged from * allocating more than one work area simultaneously in a single task * context. * * Context: This function may sleep. * Return: A &struct rtas_work_area descriptor for the allocated work area. */ #define rtas_work_area_alloc(size_) ({ \ static_assert(__builtin_constant_p(size_)); \ static_assert((size_) > 0); \ static_assert((size_) <= RTAS_WORK_AREA_MAX_ALLOC_SZ); \ __rtas_work_area_alloc(size_); \ }) /* * Do not call __rtas_work_area_alloc() directly. Use * rtas_work_area_alloc(). */ struct rtas_work_area *__rtas_work_area_alloc(size_t size); /** * rtas_work_area_free() - Release a work area. * @area: Work area descriptor as returned from rtas_work_area_alloc(). * * Return a work area buffer to the pool. */ void rtas_work_area_free(struct rtas_work_area *area); static inline char *rtas_work_area_raw_buf(const struct rtas_work_area *area) { return area->buf; } static inline size_t rtas_work_area_size(const struct rtas_work_area *area) { return area->size; } static inline phys_addr_t rtas_work_area_phys(const struct rtas_work_area *area) { return __pa(area->buf); } /* * Early setup for the work area allocator. Call from * rtas_initialize() only. */ #ifdef CONFIG_PPC_PSERIES void rtas_work_area_reserve_arena(phys_addr_t limit); #else /* CONFIG_PPC_PSERIES */ static inline void rtas_work_area_reserve_arena(phys_addr_t limit) {} #endif /* CONFIG_PPC_PSERIES */ #endif /* _ASM_POWERPC_RTAS_WORK_AREA_H */