Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0+
  2// Copyright 2017 IBM Corp.
  3#include "ocxl_internal.h"
  4
  5
  6struct id_range {
  7	struct list_head list;
  8	u32 start;
  9	u32 end;
 10};
 11
 12#ifdef DEBUG
 13static void dump_list(struct list_head *head, char *type_str)
 14{
 15	struct id_range *cur;
 16
 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);
 20	}
 21}
 22#endif
 23
 24static int range_alloc(struct list_head *head, u32 size, int max_id,
 25		char *type_str)
 26{
 27	struct list_head *pos;
 28	struct id_range *cur, *new;
 29	int rc, last_end;
 30
 31	new = kmalloc(sizeof(struct id_range), GFP_KERNEL);
 32	if (!new)
 33		return -ENOMEM;
 34
 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;
 42	}
 43
 44	new->start = last_end + 1;
 45	new->end = new->start + size - 1;
 46
 47	if (new->end > max_id) {
 48		kfree(new);
 49		rc = -ENOSPC;
 50	} else {
 51		list_add(&new->list, pos);
 52		rc = new->start;
 53	}
 54
 55#ifdef DEBUG
 56	dump_list(head, type_str);
 57#endif
 58	return rc;
 59}
 60
 61static void range_free(struct list_head *head, u32 start, u32 size,
 62		char *type_str)
 63{
 64	bool found = false;
 65	struct id_range *cur, *tmp;
 66
 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;
 73		}
 74	}
 75	WARN_ON(!found);
 76#ifdef DEBUG
 77	dump_list(head, type_str);
 78#endif
 79}
 80
 81int ocxl_pasid_afu_alloc(struct ocxl_fn *fn, u32 size)
 82{
 83	int max_pasid;
 84
 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");
 89}
 90
 91void ocxl_pasid_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
 92{
 93	return range_free(&fn->pasid_list, start, size, "afu pasid");
 94}
 95
 96int ocxl_actag_afu_alloc(struct ocxl_fn *fn, u32 size)
 97{
 98	int max_actag;
 99
100	max_actag = fn->actag_enabled;
101	return range_alloc(&fn->actag_list, size, max_actag, "afu actag");
102}
103
104void ocxl_actag_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
105{
106	return range_free(&fn->actag_list, start, size, "afu actag");
107}