Home | History | Annotate | Line # | Download | only in i915
      1  1.1  riastrad /*	$NetBSD: i915_buddy.h,v 1.2 2021/12/18 23:45:28 riastradh Exp $	*/
      2  1.1  riastrad 
      3  1.1  riastrad /* SPDX-License-Identifier: MIT */
      4  1.1  riastrad /*
      5  1.1  riastrad  * Copyright  2019 Intel Corporation
      6  1.1  riastrad  */
      7  1.1  riastrad 
      8  1.1  riastrad #ifndef __I915_BUDDY_H__
      9  1.1  riastrad #define __I915_BUDDY_H__
     10  1.1  riastrad 
     11  1.1  riastrad #include <linux/bitops.h>
     12  1.1  riastrad #include <linux/list.h>
     13  1.1  riastrad 
     14  1.1  riastrad struct i915_buddy_block {
     15  1.1  riastrad #define I915_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)
     16  1.1  riastrad #define I915_BUDDY_HEADER_STATE  GENMASK_ULL(11, 10)
     17  1.1  riastrad #define   I915_BUDDY_ALLOCATED	   (1 << 10)
     18  1.1  riastrad #define   I915_BUDDY_FREE	   (2 << 10)
     19  1.1  riastrad #define   I915_BUDDY_SPLIT	   (3 << 10)
     20  1.1  riastrad #define I915_BUDDY_HEADER_ORDER  GENMASK_ULL(9, 0)
     21  1.1  riastrad 	u64 header;
     22  1.1  riastrad 
     23  1.1  riastrad 	struct i915_buddy_block *left;
     24  1.1  riastrad 	struct i915_buddy_block *right;
     25  1.1  riastrad 	struct i915_buddy_block *parent;
     26  1.1  riastrad 
     27  1.1  riastrad 	void *private; /* owned by creator */
     28  1.1  riastrad 
     29  1.1  riastrad 	/*
     30  1.1  riastrad 	 * While the block is allocated by the user through i915_buddy_alloc*,
     31  1.1  riastrad 	 * the user has ownership of the link, for example to maintain within
     32  1.1  riastrad 	 * a list, if so desired. As soon as the block is freed with
     33  1.1  riastrad 	 * i915_buddy_free* ownership is given back to the mm.
     34  1.1  riastrad 	 */
     35  1.1  riastrad 	struct list_head link;
     36  1.1  riastrad 	struct list_head tmp_link;
     37  1.1  riastrad };
     38  1.1  riastrad 
     39  1.1  riastrad #define I915_BUDDY_MAX_ORDER  I915_BUDDY_HEADER_ORDER
     40  1.1  riastrad 
     41  1.1  riastrad /*
     42  1.1  riastrad  * Binary Buddy System.
     43  1.1  riastrad  *
     44  1.1  riastrad  * Locking should be handled by the user, a simple mutex around
     45  1.1  riastrad  * i915_buddy_alloc* and i915_buddy_free* should suffice.
     46  1.1  riastrad  */
     47  1.1  riastrad struct i915_buddy_mm {
     48  1.1  riastrad 	/* Maintain a free list for each order. */
     49  1.1  riastrad 	struct list_head *free_list;
     50  1.1  riastrad 
     51  1.1  riastrad 	/*
     52  1.1  riastrad 	 * Maintain explicit binary tree(s) to track the allocation of the
     53  1.1  riastrad 	 * address space. This gives us a simple way of finding a buddy block
     54  1.1  riastrad 	 * and performing the potentially recursive merge step when freeing a
     55  1.1  riastrad 	 * block.  Nodes are either allocated or free, in which case they will
     56  1.1  riastrad 	 * also exist on the respective free list.
     57  1.1  riastrad 	 */
     58  1.1  riastrad 	struct i915_buddy_block **roots;
     59  1.1  riastrad 
     60  1.1  riastrad 	/*
     61  1.1  riastrad 	 * Anything from here is public, and remains static for the lifetime of
     62  1.1  riastrad 	 * the mm. Everything above is considered do-not-touch.
     63  1.1  riastrad 	 */
     64  1.1  riastrad 	unsigned int n_roots;
     65  1.1  riastrad 	unsigned int max_order;
     66  1.1  riastrad 
     67  1.1  riastrad 	/* Must be at least PAGE_SIZE */
     68  1.1  riastrad 	u64 chunk_size;
     69  1.1  riastrad 	u64 size;
     70  1.1  riastrad };
     71  1.1  riastrad 
     72  1.1  riastrad static inline u64
     73  1.1  riastrad i915_buddy_block_offset(struct i915_buddy_block *block)
     74  1.1  riastrad {
     75  1.1  riastrad 	return block->header & I915_BUDDY_HEADER_OFFSET;
     76  1.1  riastrad }
     77  1.1  riastrad 
     78  1.1  riastrad static inline unsigned int
     79  1.1  riastrad i915_buddy_block_order(struct i915_buddy_block *block)
     80  1.1  riastrad {
     81  1.1  riastrad 	return block->header & I915_BUDDY_HEADER_ORDER;
     82  1.1  riastrad }
     83  1.1  riastrad 
     84  1.1  riastrad static inline unsigned int
     85  1.1  riastrad i915_buddy_block_state(struct i915_buddy_block *block)
     86  1.1  riastrad {
     87  1.1  riastrad 	return block->header & I915_BUDDY_HEADER_STATE;
     88  1.1  riastrad }
     89  1.1  riastrad 
     90  1.1  riastrad static inline bool
     91  1.1  riastrad i915_buddy_block_is_allocated(struct i915_buddy_block *block)
     92  1.1  riastrad {
     93  1.1  riastrad 	return i915_buddy_block_state(block) == I915_BUDDY_ALLOCATED;
     94  1.1  riastrad }
     95  1.1  riastrad 
     96  1.1  riastrad static inline bool
     97  1.1  riastrad i915_buddy_block_is_free(struct i915_buddy_block *block)
     98  1.1  riastrad {
     99  1.1  riastrad 	return i915_buddy_block_state(block) == I915_BUDDY_FREE;
    100  1.1  riastrad }
    101  1.1  riastrad 
    102  1.1  riastrad static inline bool
    103  1.1  riastrad i915_buddy_block_is_split(struct i915_buddy_block *block)
    104  1.1  riastrad {
    105  1.1  riastrad 	return i915_buddy_block_state(block) == I915_BUDDY_SPLIT;
    106  1.1  riastrad }
    107  1.1  riastrad 
    108  1.1  riastrad static inline u64
    109  1.1  riastrad i915_buddy_block_size(struct i915_buddy_mm *mm,
    110  1.1  riastrad 		      struct i915_buddy_block *block)
    111  1.1  riastrad {
    112  1.1  riastrad 	return mm->chunk_size << i915_buddy_block_order(block);
    113  1.1  riastrad }
    114  1.1  riastrad 
    115  1.1  riastrad int i915_buddy_init(struct i915_buddy_mm *mm, u64 size, u64 chunk_size);
    116  1.1  riastrad 
    117  1.1  riastrad void i915_buddy_fini(struct i915_buddy_mm *mm);
    118  1.1  riastrad 
    119  1.1  riastrad struct i915_buddy_block *
    120  1.1  riastrad i915_buddy_alloc(struct i915_buddy_mm *mm, unsigned int order);
    121  1.1  riastrad 
    122  1.1  riastrad int i915_buddy_alloc_range(struct i915_buddy_mm *mm,
    123  1.1  riastrad 			   struct list_head *blocks,
    124  1.1  riastrad 			   u64 start, u64 size);
    125  1.1  riastrad 
    126  1.1  riastrad void i915_buddy_free(struct i915_buddy_mm *mm, struct i915_buddy_block *block);
    127  1.1  riastrad 
    128  1.1  riastrad void i915_buddy_free_list(struct i915_buddy_mm *mm, struct list_head *objects);
    129  1.1  riastrad 
    130  1.1  riastrad #endif
    131