summaryrefslogtreecommitdiffstats
path: root/linux/drivers/soc/fsl/qbman/dpaa_resource.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/soc/fsl/qbman/dpaa_resource.c')
-rw-r--r--linux/drivers/soc/fsl/qbman/dpaa_resource.c363
1 files changed, 0 insertions, 363 deletions
diff --git a/linux/drivers/soc/fsl/qbman/dpaa_resource.c b/linux/drivers/soc/fsl/qbman/dpaa_resource.c
deleted file mode 100644
index 3f7b74bf..00000000
--- a/linux/drivers/soc/fsl/qbman/dpaa_resource.c
+++ /dev/null
@@ -1,363 +0,0 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
-#include <rtems/bsd/local/opt_dpaa.h>
-
-/* Copyright 2009 - 2015 Freescale Semiconductor, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Freescale Semiconductor nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if defined(CONFIG_FSL_BMAN_PORTAL) || \
- defined(CONFIG_FSL_BMAN_PORTAL_MODULE) || \
- defined(CONFIG_FSL_QMAN_PORTAL) || \
- defined(CONFIG_FSL_QMAN_PORTAL_MODULE)
-#include "dpaa_sys.h"
-
-/* The allocator is a (possibly-empty) list of these */
-struct dpaa_resource_node {
- struct list_head list;
- u32 base;
- u32 num;
- /* refcount and is_alloced are only set
- when the node is in the used list */
- unsigned int refcount;
- int is_alloced;
-};
-
-#ifdef DPAA_RESOURCE_DEBUG
-#define DPRINT pr_info
-static void DUMP(struct dpaa_resource *alloc)
-{
- int off = 0;
- char buf[256];
- struct dpaa_resource_node *p;
-
- pr_info("Free Nodes\n");
- list_for_each_entry(p, &alloc->free, list) {
- if (off < 255)
- off += snprintf(buf + off, 255-off, "{%d,%d}",
- p->base, p->base + p->num - 1);
- }
- pr_info("%s\n", buf);
-
- off = 0;
- pr_info("Used Nodes\n");
- list_for_each_entry(p, &alloc->used, list) {
- if (off < 255)
- off += snprintf(buf + off, 255-off, "{%d,%d}",
- p->base, p->base + p->num - 1);
- }
- pr_info("%s\n", buf);
-}
-#else
-#define DPRINT(x...)
-#define DUMP(a)
-#endif
-
-int dpaa_resource_new(struct dpaa_resource *alloc, u32 *result,
- u32 count, u32 align, int partial)
-{
- struct dpaa_resource_node *i = NULL, *next_best = NULL,
- *used_node = NULL;
- u32 base, next_best_base = 0, num = 0, next_best_num = 0;
- struct dpaa_resource_node *margin_left, *margin_right;
-
- *result = (u32)-1;
- DPRINT("alloc_range(%d,%d,%d)\n", count, align, partial);
- DUMP(alloc);
- /* If 'align' is 0, it should behave as though it was 1 */
- if (!align)
- align = 1;
- margin_left = kmalloc(sizeof(*margin_left), GFP_KERNEL);
- if (!margin_left)
- goto err;
- margin_right = kmalloc(sizeof(*margin_right), GFP_KERNEL);
- if (!margin_right) {
- kfree(margin_left);
- goto err;
- }
- spin_lock_irq(&alloc->lock);
- list_for_each_entry(i, &alloc->free, list) {
- base = (i->base + align - 1) / align;
- base *= align;
- if ((base - i->base) >= i->num)
- /* alignment is impossible, regardless of count */
- continue;
- num = i->num - (base - i->base);
- if (num >= count) {
- /* this one will do nicely */
- num = count;
- goto done;
- }
- if (num > next_best_num) {
- next_best = i;
- next_best_base = base;
- next_best_num = num;
- }
- }
- if (partial && next_best) {
- i = next_best;
- base = next_best_base;
- num = next_best_num;
- } else
- i = NULL;
-done:
- if (i) {
- if (base != i->base) {
- margin_left->base = i->base;
- margin_left->num = base - i->base;
- list_add_tail(&margin_left->list, &i->list);
- } else
- kfree(margin_left);
- if ((base + num) < (i->base + i->num)) {
- margin_right->base = base + num;
- margin_right->num = (i->base + i->num) -
- (base + num);
- list_add(&margin_right->list, &i->list);
- } else
- kfree(margin_right);
- list_del(&i->list);
- kfree(i);
- *result = base;
- }
- spin_unlock_irq(&alloc->lock);
-err:
- DPRINT("returning %d\n", i ? num : -ENOMEM);
- DUMP(alloc);
- if (!i)
- return -ENOMEM;
-
- /* Add the allocation to the used list with a refcount of 1 */
- used_node = kmalloc(sizeof(*used_node), GFP_KERNEL);
- if (!used_node)
- return -ENOMEM;
- used_node->base = *result;
- used_node->num = num;
- used_node->refcount = 1;
- used_node->is_alloced = 1;
- list_add_tail(&used_node->list, &alloc->used);
- return (int)num;
-}
-EXPORT_SYMBOL(dpaa_resource_new);
-
-/* Allocate the list node using GFP_ATOMIC, because we *really* want to avoid
- * forcing error-handling on to users in the deallocation path. */
-static void _dpaa_resource_free(struct dpaa_resource *alloc, u32 base_id,
- u32 count)
-{
- struct dpaa_resource_node *i,
- *node = kmalloc(sizeof(*node), GFP_ATOMIC);
-
- BUG_ON(!node);
- DPRINT("release_range(%d,%d)\n", base_id, count);
- DUMP(alloc);
- BUG_ON(!count);
- spin_lock_irq(&alloc->lock);
-
- node->base = base_id;
- node->num = count;
- list_for_each_entry(i, &alloc->free, list) {
- if (i->base >= node->base) {
- /* BUG_ON(any overlapping) */
- BUG_ON(i->base < (node->base + node->num));
- list_add_tail(&node->list, &i->list);
- goto done;
- }
- }
- list_add_tail(&node->list, &alloc->free);
-done:
- /* Merge to the left */
- i = list_entry(node->list.prev, struct dpaa_resource_node, list);
- if (node->list.prev != &alloc->free) {
- BUG_ON((i->base + i->num) > node->base);
- if ((i->base + i->num) == node->base) {
- node->base = i->base;
- node->num += i->num;
- list_del(&i->list);
- kfree(i);
- }
- }
- /* Merge to the right */
- i = list_entry(node->list.next, struct dpaa_resource_node, list);
- if (node->list.next != &alloc->free) {
- BUG_ON((node->base + node->num) > i->base);
- if ((node->base + node->num) == i->base) {
- node->num += i->num;
- list_del(&i->list);
- kfree(i);
- }
- }
- spin_unlock_irq(&alloc->lock);
- DUMP(alloc);
-}
-
-static void dpaa_resource_free(struct dpaa_resource *alloc, u32 base_id,
- u32 count)
-{
- struct dpaa_resource_node *i = NULL;
-
- spin_lock_irq(&alloc->lock);
-
- /* First find the node in the used list and decrement its ref count */
- list_for_each_entry(i, &alloc->used, list) {
- if (i->base == base_id && i->num == count) {
- --i->refcount;
- if (i->refcount == 0) {
- list_del(&i->list);
- spin_unlock_irq(&alloc->lock);
- if (i->is_alloced)
- _dpaa_resource_free(alloc, base_id,
- count);
- kfree(i);
- return;
- }
- spin_unlock_irq(&alloc->lock);
- return;
- }
- }
- /* Couldn't find the allocation */
- pr_err("Attempt to free ID 0x%x COUNT %d that wasn't alloc'd or reserved\n",
- base_id, count);
- spin_unlock_irq(&alloc->lock);
-}
-
-/* Same as free but no previous allocation checking is needed */
-void dpaa_resource_seed(struct dpaa_resource *alloc, u32 base_id, u32 count)
-{
- _dpaa_resource_free(alloc, base_id, count);
-}
-EXPORT_SYMBOL(dpaa_resource_seed);
-
-/* Like 'new' but specifies the desired range, returns -ENOMEM if the entire
- * desired range is not available, or 0 for success
- */
-int dpaa_resource_reserve(struct dpaa_resource *alloc, u32 base, u32 num)
-{
- struct dpaa_resource_node *i = NULL, *used_node;
-
- DPRINT("alloc_reserve(%d,%d)\n", base, num);
- DUMP(alloc);
-
- spin_lock_irq(&alloc->lock);
-
- /* Check for the node in the used list.
- If found, increase it's refcount */
- list_for_each_entry(i, &alloc->used, list) {
- if ((i->base == base) && (i->num == num)) {
- ++i->refcount;
- spin_unlock_irq(&alloc->lock);
- return 0;
- }
- if ((base >= i->base) && (base < (i->base + i->num))) {
- /* This is an attempt to reserve a region that was
- already reserved or alloced with a different
- base or num */
- pr_err("Cannot reserve %d - %d, it overlaps with"
- " existing reservation from %d - %d\n",
- base, base + num - 1, i->base,
- i->base + i->num - 1);
- spin_unlock_irq(&alloc->lock);
- return -1;
- }
- }
- /* Check to make sure this ID isn't in the free list */
- list_for_each_entry(i, &alloc->free, list) {
- if ((base >= i->base) && (base < (i->base + i->num))) {
- /* yep, the reservation is within this node */
- pr_err("Cannot reserve %d - %d, it overlaps with"
- " free range %d - %d and must be alloced\n",
- base, base + num - 1,
- i->base, i->base + i->num - 1);
- spin_unlock_irq(&alloc->lock);
- return -1;
- }
- }
- /* Add the allocation to the used list with a refcount of 1 */
- used_node = kmalloc(sizeof(*used_node), GFP_KERNEL);
- if (!used_node) {
- spin_unlock_irq(&alloc->lock);
- return -ENOMEM;
-
- }
- used_node->base = base;
- used_node->num = num;
- used_node->refcount = 1;
- used_node->is_alloced = 0;
- list_add_tail(&used_node->list, &alloc->used);
- spin_unlock_irq(&alloc->lock);
- return 0;
-}
-EXPORT_SYMBOL(dpaa_resource_reserve);
-
-/* This is a sort-of-conditional dpaa_resource_free() routine. Eg. when
- * releasing FQIDs (probably from user-space), it can filter out those
- * that aren't in the OOS state (better to leak a h/w resource than to
- * crash). This function returns the number of invalid IDs that were not
- * released.
-*/
-u32 dpaa_resource_release(struct dpaa_resource *alloc,
- u32 id, u32 count, int (*is_valid)(u32 id))
-{
- int valid_mode = 0;
- u32 loop = id, total_invalid = 0;
-
- while (loop < (id + count)) {
- int isvalid = is_valid ? is_valid(loop) : 1;
-
- if (!valid_mode) {
- /* We're looking for a valid ID to terminate an invalid
- * range */
- if (isvalid) {
- /* We finished a range of invalid IDs, a valid
- * range is now underway */
- valid_mode = 1;
- count -= (loop - id);
- id = loop;
- } else
- total_invalid++;
- } else {
- /* We're looking for an invalid ID to terminate a
- * valid range */
- if (!isvalid) {
- /* Release the range of valid IDs, an unvalid
- * range is now underway */
- if (loop > id)
- dpaa_resource_free(alloc, id,
- loop - id);
- valid_mode = 0;
- }
- }
- loop++;
- }
- /* Release any unterminated range of valid IDs */
- if (valid_mode && count)
- dpaa_resource_free(alloc, id, count);
- return total_invalid;
-}
-EXPORT_SYMBOL(dpaa_resource_release);
-#endif /* CONFIG_FSL_*MAN_PORTAL* */