WIP FPC-III support
[linux/fpc-iii.git] / drivers / misc / ocxl / pasid.c
blobd14cb56e6920530e5c871c239d6e30a470f5e364
1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright 2017 IBM Corp.
3 #include "ocxl_internal.h"
6 struct id_range {
7 struct list_head list;
8 u32 start;
9 u32 end;
12 #ifdef DEBUG
13 static void dump_list(struct list_head *head, char *type_str)
15 struct id_range *cur;
17 pr_debug("%s ranges allocated:\n", type_str);
18 list_for_each_entry(cur, head, list) {
19 pr_debug("Range %d->%d\n", cur->start, cur->end);
22 #endif
24 static int range_alloc(struct list_head *head, u32 size, int max_id,
25 char *type_str)
27 struct list_head *pos;
28 struct id_range *cur, *new;
29 int rc, last_end;
31 new = kmalloc(sizeof(struct id_range), GFP_KERNEL);
32 if (!new)
33 return -ENOMEM;
35 pos = head;
36 last_end = -1;
37 list_for_each_entry(cur, head, list) {
38 if ((cur->start - last_end) > size)
39 break;
40 last_end = cur->end;
41 pos = &cur->list;
44 new->start = last_end + 1;
45 new->end = new->start + size - 1;
47 if (new->end > max_id) {
48 kfree(new);
49 rc = -ENOSPC;
50 } else {
51 list_add(&new->list, pos);
52 rc = new->start;
55 #ifdef DEBUG
56 dump_list(head, type_str);
57 #endif
58 return rc;
61 static void range_free(struct list_head *head, u32 start, u32 size,
62 char *type_str)
64 bool found = false;
65 struct id_range *cur, *tmp;
67 list_for_each_entry_safe(cur, tmp, head, list) {
68 if (cur->start == start && cur->end == (start + size - 1)) {
69 found = true;
70 list_del(&cur->list);
71 kfree(cur);
72 break;
75 WARN_ON(!found);
76 #ifdef DEBUG
77 dump_list(head, type_str);
78 #endif
81 int ocxl_pasid_afu_alloc(struct ocxl_fn *fn, u32 size)
83 int max_pasid;
85 if (fn->config.max_pasid_log < 0)
86 return -ENOSPC;
87 max_pasid = 1 << fn->config.max_pasid_log;
88 return range_alloc(&fn->pasid_list, size, max_pasid, "afu pasid");
91 void ocxl_pasid_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
93 return range_free(&fn->pasid_list, start, size, "afu pasid");
96 int ocxl_actag_afu_alloc(struct ocxl_fn *fn, u32 size)
98 int max_actag;
100 max_actag = fn->actag_enabled;
101 return range_alloc(&fn->actag_list, size, max_actag, "afu actag");
104 void ocxl_actag_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
106 return range_free(&fn->actag_list, start, size, "afu actag");