Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 // Copyright 2017 IBM Corp.
0003 #include "ocxl_internal.h"
0004 
0005 
0006 struct id_range {
0007     struct list_head list;
0008     u32 start;
0009     u32 end;
0010 };
0011 
0012 #ifdef DEBUG
0013 static void dump_list(struct list_head *head, char *type_str)
0014 {
0015     struct id_range *cur;
0016 
0017     pr_debug("%s ranges allocated:\n", type_str);
0018     list_for_each_entry(cur, head, list) {
0019         pr_debug("Range %d->%d\n", cur->start, cur->end);
0020     }
0021 }
0022 #endif
0023 
0024 static int range_alloc(struct list_head *head, u32 size, int max_id,
0025         char *type_str)
0026 {
0027     struct list_head *pos;
0028     struct id_range *cur, *new;
0029     int rc, last_end;
0030 
0031     new = kmalloc(sizeof(struct id_range), GFP_KERNEL);
0032     if (!new)
0033         return -ENOMEM;
0034 
0035     pos = head;
0036     last_end = -1;
0037     list_for_each_entry(cur, head, list) {
0038         if ((cur->start - last_end) > size)
0039             break;
0040         last_end = cur->end;
0041         pos = &cur->list;
0042     }
0043 
0044     new->start = last_end + 1;
0045     new->end = new->start + size - 1;
0046 
0047     if (new->end > max_id) {
0048         kfree(new);
0049         rc = -ENOSPC;
0050     } else {
0051         list_add(&new->list, pos);
0052         rc = new->start;
0053     }
0054 
0055 #ifdef DEBUG
0056     dump_list(head, type_str);
0057 #endif
0058     return rc;
0059 }
0060 
0061 static void range_free(struct list_head *head, u32 start, u32 size,
0062         char *type_str)
0063 {
0064     bool found = false;
0065     struct id_range *cur, *tmp;
0066 
0067     list_for_each_entry_safe(cur, tmp, head, list) {
0068         if (cur->start == start && cur->end == (start + size - 1)) {
0069             found = true;
0070             list_del(&cur->list);
0071             kfree(cur);
0072             break;
0073         }
0074     }
0075     WARN_ON(!found);
0076 #ifdef DEBUG
0077     dump_list(head, type_str);
0078 #endif
0079 }
0080 
0081 int ocxl_pasid_afu_alloc(struct ocxl_fn *fn, u32 size)
0082 {
0083     int max_pasid;
0084 
0085     if (fn->config.max_pasid_log < 0)
0086         return -ENOSPC;
0087     max_pasid = 1 << fn->config.max_pasid_log;
0088     return range_alloc(&fn->pasid_list, size, max_pasid, "afu pasid");
0089 }
0090 
0091 void ocxl_pasid_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
0092 {
0093     return range_free(&fn->pasid_list, start, size, "afu pasid");
0094 }
0095 
0096 int ocxl_actag_afu_alloc(struct ocxl_fn *fn, u32 size)
0097 {
0098     int max_actag;
0099 
0100     max_actag = fn->actag_enabled;
0101     return range_alloc(&fn->actag_list, size, max_actag, "afu actag");
0102 }
0103 
0104 void ocxl_actag_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
0105 {
0106     return range_free(&fn->actag_list, start, size, "afu actag");
0107 }