1d96e5996SHans Petter Selasky /*- 2d96e5996SHans Petter Selasky * Copyright (c) 2020 Mellanox Technologies, Ltd. 3d96e5996SHans Petter Selasky * All rights reserved. 4d96e5996SHans Petter Selasky * 5d96e5996SHans Petter Selasky * Redistribution and use in source and binary forms, with or without 6d96e5996SHans Petter Selasky * modification, are permitted provided that the following conditions 7d96e5996SHans Petter Selasky * are met: 8d96e5996SHans Petter Selasky * 1. Redistributions of source code must retain the above copyright 9d96e5996SHans Petter Selasky * notice unmodified, this list of conditions, and the following 10d96e5996SHans Petter Selasky * disclaimer. 11d96e5996SHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright 12d96e5996SHans Petter Selasky * notice, this list of conditions and the following disclaimer in the 13d96e5996SHans Petter Selasky * documentation and/or other materials provided with the distribution. 14d96e5996SHans Petter Selasky * 15d96e5996SHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16d96e5996SHans Petter Selasky * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17d96e5996SHans Petter Selasky * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18d96e5996SHans Petter Selasky * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19d96e5996SHans Petter Selasky * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20d96e5996SHans Petter Selasky * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21d96e5996SHans Petter Selasky * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22d96e5996SHans Petter Selasky * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23d96e5996SHans Petter Selasky * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24d96e5996SHans Petter Selasky * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25d96e5996SHans Petter Selasky * 26d96e5996SHans Petter Selasky * $FreeBSD$ 27d96e5996SHans Petter Selasky */ 28d96e5996SHans Petter Selasky #ifndef _LINUX_XARRAY_H_ 29d96e5996SHans Petter Selasky #define _LINUX_XARRAY_H_ 30d96e5996SHans Petter Selasky 31d96e5996SHans Petter Selasky #include <linux/gfp.h> 32d96e5996SHans Petter Selasky #include <linux/radix-tree.h> 33d96e5996SHans Petter Selasky #include <linux/err.h> 34d96e5996SHans Petter Selasky 35d96e5996SHans Petter Selasky #include <sys/lock.h> 36d96e5996SHans Petter Selasky #include <sys/mutex.h> 37d96e5996SHans Petter Selasky 38d96e5996SHans Petter Selasky #define XA_LIMIT(min, max) \ 39d96e5996SHans Petter Selasky ({ CTASSERT((min) == 0); (uint32_t)(max); }) 40d96e5996SHans Petter Selasky 41d96e5996SHans Petter Selasky #define XA_FLAGS_ALLOC (1U << 0) 42d96e5996SHans Petter Selasky #define XA_FLAGS_LOCK_IRQ (1U << 1) 43d96e5996SHans Petter Selasky 44d96e5996SHans Petter Selasky #define XA_ERROR(x) \ 45d96e5996SHans Petter Selasky ERR_PTR(x) 46d96e5996SHans Petter Selasky 47d96e5996SHans Petter Selasky #define xa_limit_32b XA_LIMIT(0, 0xFFFFFFFF) 48d96e5996SHans Petter Selasky 49d96e5996SHans Petter Selasky #define XA_ASSERT_LOCKED(xa) mtx_assert(&(xa)->mtx, MA_OWNED) 50d96e5996SHans Petter Selasky #define xa_lock(xa) mtx_lock(&(xa)->mtx) 51d96e5996SHans Petter Selasky #define xa_unlock(xa) mtx_unlock(&(xa)->mtx) 52d96e5996SHans Petter Selasky 53d96e5996SHans Petter Selasky struct xarray { 54d96e5996SHans Petter Selasky struct radix_tree_root root; 55d96e5996SHans Petter Selasky struct mtx mtx; /* internal mutex */ 56d96e5996SHans Petter Selasky }; 57d96e5996SHans Petter Selasky 58d96e5996SHans Petter Selasky /* 59d96e5996SHans Petter Selasky * Extensible arrays API implemented as a wrapper 60d96e5996SHans Petter Selasky * around the radix tree implementation. 61d96e5996SHans Petter Selasky */ 62d96e5996SHans Petter Selasky void *xa_erase(struct xarray *, uint32_t); 63d96e5996SHans Petter Selasky void *xa_load(struct xarray *, uint32_t); 64d96e5996SHans Petter Selasky int xa_alloc(struct xarray *, uint32_t *, void *, uint32_t, gfp_t); 65d96e5996SHans Petter Selasky int xa_alloc_cyclic(struct xarray *, uint32_t *, void *, uint32_t, uint32_t *, gfp_t); 66d96e5996SHans Petter Selasky int xa_insert(struct xarray *, uint32_t, void *, gfp_t); 67d96e5996SHans Petter Selasky void *xa_store(struct xarray *, uint32_t, void *, gfp_t); 68d96e5996SHans Petter Selasky void xa_init_flags(struct xarray *, uint32_t); 69d96e5996SHans Petter Selasky bool xa_empty(struct xarray *); 70d96e5996SHans Petter Selasky void xa_destroy(struct xarray *); 71d96e5996SHans Petter Selasky void *xa_next(struct xarray *, unsigned long *, bool); 72d96e5996SHans Petter Selasky 73d96e5996SHans Petter Selasky #define xa_for_each(xa, index, entry) \ 74d96e5996SHans Petter Selasky for ((entry) = NULL, (index) = 0; \ 75d96e5996SHans Petter Selasky ((entry) = xa_next(xa, &index, (entry) != NULL)) != NULL; ) 76d96e5996SHans Petter Selasky 77d96e5996SHans Petter Selasky /* 78d96e5996SHans Petter Selasky * Unlocked version of functions above. 79d96e5996SHans Petter Selasky */ 80d96e5996SHans Petter Selasky void *__xa_erase(struct xarray *, uint32_t); 81d96e5996SHans Petter Selasky int __xa_alloc(struct xarray *, uint32_t *, void *, uint32_t, gfp_t); 82d96e5996SHans Petter Selasky int __xa_alloc_cyclic(struct xarray *, uint32_t *, void *, uint32_t, uint32_t *, gfp_t); 83d96e5996SHans Petter Selasky int __xa_insert(struct xarray *, uint32_t, void *, gfp_t); 84d96e5996SHans Petter Selasky void *__xa_store(struct xarray *, uint32_t, void *, gfp_t); 85d96e5996SHans Petter Selasky bool __xa_empty(struct xarray *); 86d96e5996SHans Petter Selasky void *__xa_next(struct xarray *, unsigned long *, bool); 87d96e5996SHans Petter Selasky 88d96e5996SHans Petter Selasky static inline int 89d96e5996SHans Petter Selasky xa_err(void *ptr) 90d96e5996SHans Petter Selasky { 91d96e5996SHans Petter Selasky return (PTR_ERR_OR_ZERO(ptr)); 92d96e5996SHans Petter Selasky } 93d96e5996SHans Petter Selasky 94ab79c906SHans Petter Selasky static inline void 95ab79c906SHans Petter Selasky xa_init(struct xarray *xa) 96ab79c906SHans Petter Selasky { 97ab79c906SHans Petter Selasky xa_init_flags(xa, 0); 98ab79c906SHans Petter Selasky } 99ab79c906SHans Petter Selasky 100*b59ffedaSVladimir Kondratyev static inline void * 101*b59ffedaSVladimir Kondratyev xa_mk_value(unsigned long v) 102*b59ffedaSVladimir Kondratyev { 103*b59ffedaSVladimir Kondratyev unsigned long r = (v << 1) | 1; 104*b59ffedaSVladimir Kondratyev 105*b59ffedaSVladimir Kondratyev return ((void *)r); 106*b59ffedaSVladimir Kondratyev } 107*b59ffedaSVladimir Kondratyev 108*b59ffedaSVladimir Kondratyev static inline bool 109*b59ffedaSVladimir Kondratyev xa_is_value(const void *e) 110*b59ffedaSVladimir Kondratyev { 111*b59ffedaSVladimir Kondratyev unsigned long v = (unsigned long)e; 112*b59ffedaSVladimir Kondratyev 113*b59ffedaSVladimir Kondratyev return (v & 1); 114*b59ffedaSVladimir Kondratyev } 115*b59ffedaSVladimir Kondratyev 116*b59ffedaSVladimir Kondratyev static inline unsigned long 117*b59ffedaSVladimir Kondratyev xa_to_value(const void *e) 118*b59ffedaSVladimir Kondratyev { 119*b59ffedaSVladimir Kondratyev unsigned long v = (unsigned long)e; 120*b59ffedaSVladimir Kondratyev 121*b59ffedaSVladimir Kondratyev return (v >> 1); 122*b59ffedaSVladimir Kondratyev } 123d96e5996SHans Petter Selasky #endif /* _LINUX_XARRAY_H_ */ 124