Lines Matching +full:fsl +full:- +full:mc

1 // SPDX-License-Identifier: GPL-2.0
3 * fsl-mc object allocator driver
5 * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
11 #include <linux/fsl/mc.h>
13 #include "fsl-mc-private.h"
23 * fsl_mc_resource_pool_add_device - add allocatable object to a resource
24 * pool of a given fsl-mc bus
26 * @mc_bus: pointer to the fsl-mc bus
28 * @mc_dev: pointer to allocatable fsl-mc device
39 struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; in fsl_mc_resource_pool_add_device()
40 int error = -EINVAL; in fsl_mc_resource_pool_add_device()
46 if (mc_dev->resource) in fsl_mc_resource_pool_add_device()
49 res_pool = &mc_bus->resource_pools[pool_type]; in fsl_mc_resource_pool_add_device()
50 if (res_pool->type != pool_type) in fsl_mc_resource_pool_add_device()
52 if (res_pool->mc_bus != mc_bus) in fsl_mc_resource_pool_add_device()
55 mutex_lock(&res_pool->mutex); in fsl_mc_resource_pool_add_device()
57 if (res_pool->max_count < 0) in fsl_mc_resource_pool_add_device()
59 if (res_pool->free_count < 0 || in fsl_mc_resource_pool_add_device()
60 res_pool->free_count > res_pool->max_count) in fsl_mc_resource_pool_add_device()
63 resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource), in fsl_mc_resource_pool_add_device()
66 error = -ENOMEM; in fsl_mc_resource_pool_add_device()
67 dev_err(&mc_bus_dev->dev, in fsl_mc_resource_pool_add_device()
72 resource->type = pool_type; in fsl_mc_resource_pool_add_device()
73 resource->id = mc_dev->obj_desc.id; in fsl_mc_resource_pool_add_device()
74 resource->data = mc_dev; in fsl_mc_resource_pool_add_device()
75 resource->parent_pool = res_pool; in fsl_mc_resource_pool_add_device()
76 INIT_LIST_HEAD(&resource->node); in fsl_mc_resource_pool_add_device()
77 list_add_tail(&resource->node, &res_pool->free_list); in fsl_mc_resource_pool_add_device()
78 mc_dev->resource = resource; in fsl_mc_resource_pool_add_device()
79 res_pool->free_count++; in fsl_mc_resource_pool_add_device()
80 res_pool->max_count++; in fsl_mc_resource_pool_add_device()
83 mutex_unlock(&res_pool->mutex); in fsl_mc_resource_pool_add_device()
89 * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
92 * @mc_dev: pointer to allocatable fsl-mc device
94 * It permanently removes an allocatable fsl-mc device from the resource
104 int error = -EINVAL; in fsl_mc_resource_pool_remove_device()
106 mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); in fsl_mc_resource_pool_remove_device()
109 resource = mc_dev->resource; in fsl_mc_resource_pool_remove_device()
110 if (!resource || resource->data != mc_dev) { in fsl_mc_resource_pool_remove_device()
111 dev_err(&mc_bus_dev->dev, "resource mismatch\n"); in fsl_mc_resource_pool_remove_device()
115 res_pool = resource->parent_pool; in fsl_mc_resource_pool_remove_device()
116 if (res_pool != &mc_bus->resource_pools[resource->type]) { in fsl_mc_resource_pool_remove_device()
117 dev_err(&mc_bus_dev->dev, "pool mismatch\n"); in fsl_mc_resource_pool_remove_device()
121 mutex_lock(&res_pool->mutex); in fsl_mc_resource_pool_remove_device()
123 if (res_pool->max_count <= 0) { in fsl_mc_resource_pool_remove_device()
124 dev_err(&mc_bus_dev->dev, "max_count underflow\n"); in fsl_mc_resource_pool_remove_device()
127 if (res_pool->free_count <= 0 || in fsl_mc_resource_pool_remove_device()
128 res_pool->free_count > res_pool->max_count) { in fsl_mc_resource_pool_remove_device()
129 dev_err(&mc_bus_dev->dev, "free_count mismatch\n"); in fsl_mc_resource_pool_remove_device()
137 if (list_empty(&resource->node)) { in fsl_mc_resource_pool_remove_device()
138 error = -EBUSY; in fsl_mc_resource_pool_remove_device()
139 dev_err(&mc_bus_dev->dev, in fsl_mc_resource_pool_remove_device()
141 dev_name(&mc_dev->dev)); in fsl_mc_resource_pool_remove_device()
145 list_del_init(&resource->node); in fsl_mc_resource_pool_remove_device()
146 res_pool->free_count--; in fsl_mc_resource_pool_remove_device()
147 res_pool->max_count--; in fsl_mc_resource_pool_remove_device()
149 devm_kfree(&mc_bus_dev->dev, resource); in fsl_mc_resource_pool_remove_device()
150 mc_dev->resource = NULL; in fsl_mc_resource_pool_remove_device()
153 mutex_unlock(&res_pool->mutex); in fsl_mc_resource_pool_remove_device()
178 return -EINVAL; in object_type_to_pool_type()
187 struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; in fsl_mc_resource_allocate()
188 int error = -EINVAL; in fsl_mc_resource_allocate()
197 res_pool = &mc_bus->resource_pools[pool_type]; in fsl_mc_resource_allocate()
198 if (res_pool->mc_bus != mc_bus) in fsl_mc_resource_allocate()
201 mutex_lock(&res_pool->mutex); in fsl_mc_resource_allocate()
202 resource = list_first_entry_or_null(&res_pool->free_list, in fsl_mc_resource_allocate()
206 error = -ENXIO; in fsl_mc_resource_allocate()
207 dev_err(&mc_bus_dev->dev, in fsl_mc_resource_allocate()
213 if (resource->type != pool_type) in fsl_mc_resource_allocate()
215 if (resource->parent_pool != res_pool) in fsl_mc_resource_allocate()
217 if (res_pool->free_count <= 0 || in fsl_mc_resource_allocate()
218 res_pool->free_count > res_pool->max_count) in fsl_mc_resource_allocate()
221 list_del_init(&resource->node); in fsl_mc_resource_allocate()
223 res_pool->free_count--; in fsl_mc_resource_allocate()
226 mutex_unlock(&res_pool->mutex); in fsl_mc_resource_allocate()
237 res_pool = resource->parent_pool; in fsl_mc_resource_free()
238 if (resource->type != res_pool->type) in fsl_mc_resource_free()
241 mutex_lock(&res_pool->mutex); in fsl_mc_resource_free()
242 if (res_pool->free_count < 0 || in fsl_mc_resource_free()
243 res_pool->free_count >= res_pool->max_count) in fsl_mc_resource_free()
246 if (!list_empty(&resource->node)) in fsl_mc_resource_free()
249 list_add_tail(&resource->node, &res_pool->free_list); in fsl_mc_resource_free()
250 res_pool->free_count++; in fsl_mc_resource_free()
252 mutex_unlock(&res_pool->mutex); in fsl_mc_resource_free()
257 * fsl_mc_object_allocate - Allocates an fsl-mc object of the given
258 * pool type from a given fsl-mc bus instance
260 * @mc_dev: fsl-mc device which is used in conjunction with the
270 * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
281 int error = -EINVAL; in fsl_mc_object_allocate()
285 if (mc_dev->flags & FSL_MC_IS_DPRC) in fsl_mc_object_allocate()
288 if (!dev_is_fsl_mc(mc_dev->dev.parent)) in fsl_mc_object_allocate()
294 mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); in fsl_mc_object_allocate()
300 mc_adev = resource->data; in fsl_mc_object_allocate()
302 error = -EINVAL; in fsl_mc_object_allocate()
306 mc_adev->consumer_link = device_link_add(&mc_dev->dev, in fsl_mc_object_allocate()
307 &mc_adev->dev, in fsl_mc_object_allocate()
309 if (!mc_adev->consumer_link) { in fsl_mc_object_allocate()
310 error = -EINVAL; in fsl_mc_object_allocate()
325 * fsl_mc_object_free - Returns an fsl-mc object to the resource
327 * @mc_adev: Pointer to the fsl-mc device
333 resource = mc_adev->resource; in fsl_mc_object_free()
334 if (resource->type == FSL_MC_POOL_DPMCP) in fsl_mc_object_free()
336 if (resource->data != mc_adev) in fsl_mc_object_free()
341 mc_adev->consumer_link = NULL; in fsl_mc_object_free()
346 * A DPRC and the devices in the DPRC all share the same GIC-ITS device
347 * ID. A block of IRQs is pre-allocated and maintained in a pool
352 * Initialize the interrupt pool associated with an fsl-mc bus.
353 * It allocates a block of IRQs from the GIC-ITS.
364 &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; in fsl_mc_populate_irq_pool()
367 if (mc_bus->irq_resources) in fsl_mc_populate_irq_pool()
372 return -EINVAL; in fsl_mc_populate_irq_pool()
374 error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); in fsl_mc_populate_irq_pool()
378 irq_resources = devm_kcalloc(&mc_bus_dev->dev, in fsl_mc_populate_irq_pool()
382 error = -ENOMEM; in fsl_mc_populate_irq_pool()
393 mc_dev_irq->resource.type = res_pool->type; in fsl_mc_populate_irq_pool()
394 mc_dev_irq->resource.data = mc_dev_irq; in fsl_mc_populate_irq_pool()
395 mc_dev_irq->resource.parent_pool = res_pool; in fsl_mc_populate_irq_pool()
396 mc_dev_irq->virq = msi_get_virq(&mc_bus_dev->dev, i); in fsl_mc_populate_irq_pool()
397 mc_dev_irq->resource.id = mc_dev_irq->virq; in fsl_mc_populate_irq_pool()
398 INIT_LIST_HEAD(&mc_dev_irq->resource.node); in fsl_mc_populate_irq_pool()
399 list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); in fsl_mc_populate_irq_pool()
402 res_pool->max_count = irq_count; in fsl_mc_populate_irq_pool()
403 res_pool->free_count = irq_count; in fsl_mc_populate_irq_pool()
404 mc_bus->irq_resources = irq_resources; in fsl_mc_populate_irq_pool()
408 fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); in fsl_mc_populate_irq_pool()
414 * Teardown the interrupt pool associated with an fsl-mc bus.
415 * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
421 &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; in fsl_mc_cleanup_irq_pool()
423 if (!mc_bus->irq_resources) in fsl_mc_cleanup_irq_pool()
426 if (res_pool->max_count == 0) in fsl_mc_cleanup_irq_pool()
429 if (res_pool->free_count != res_pool->max_count) in fsl_mc_cleanup_irq_pool()
432 INIT_LIST_HEAD(&res_pool->free_list); in fsl_mc_cleanup_irq_pool()
433 res_pool->max_count = 0; in fsl_mc_cleanup_irq_pool()
434 res_pool->free_count = 0; in fsl_mc_cleanup_irq_pool()
435 mc_bus->irq_resources = NULL; in fsl_mc_cleanup_irq_pool()
436 fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); in fsl_mc_cleanup_irq_pool()
441 * Allocate the IRQs required by a given fsl-mc device.
448 int error = -EINVAL; in fsl_mc_allocate_irqs()
453 if (mc_dev->irqs) in fsl_mc_allocate_irqs()
454 return -EINVAL; in fsl_mc_allocate_irqs()
456 irq_count = mc_dev->obj_desc.irq_count; in fsl_mc_allocate_irqs()
458 return -EINVAL; in fsl_mc_allocate_irqs()
463 mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); in fsl_mc_allocate_irqs()
465 if (!mc_bus->irq_resources) in fsl_mc_allocate_irqs()
466 return -EINVAL; in fsl_mc_allocate_irqs()
468 res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; in fsl_mc_allocate_irqs()
469 if (res_pool->free_count < irq_count) { in fsl_mc_allocate_irqs()
470 dev_err(&mc_dev->dev, in fsl_mc_allocate_irqs()
472 return -ENOSPC; in fsl_mc_allocate_irqs()
475 irqs = devm_kcalloc(&mc_dev->dev, irq_count, sizeof(irqs[0]), in fsl_mc_allocate_irqs()
478 return -ENOMEM; in fsl_mc_allocate_irqs()
491 irqs[i]->mc_dev = mc_dev; in fsl_mc_allocate_irqs()
492 irqs[i]->dev_irq_index = i; in fsl_mc_allocate_irqs()
495 mc_dev->irqs = irqs; in fsl_mc_allocate_irqs()
500 irqs[i]->mc_dev = NULL; in fsl_mc_allocate_irqs()
501 fsl_mc_resource_free(&irqs[i]->resource); in fsl_mc_allocate_irqs()
509 * Frees the IRQs that were allocated for an fsl-mc device.
516 struct fsl_mc_device_irq **irqs = mc_dev->irqs; in fsl_mc_free_irqs()
521 irq_count = mc_dev->obj_desc.irq_count; in fsl_mc_free_irqs()
526 mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); in fsl_mc_free_irqs()
528 if (!mc_bus->irq_resources) in fsl_mc_free_irqs()
532 irqs[i]->mc_dev = NULL; in fsl_mc_free_irqs()
533 fsl_mc_resource_free(&irqs[i]->resource); in fsl_mc_free_irqs()
536 mc_dev->irqs = NULL; in fsl_mc_free_irqs()
547 &mc_bus->resource_pools[pool_type]; in fsl_mc_init_all_resource_pools()
549 res_pool->type = pool_type; in fsl_mc_init_all_resource_pools()
550 res_pool->max_count = 0; in fsl_mc_init_all_resource_pools()
551 res_pool->free_count = 0; in fsl_mc_init_all_resource_pools()
552 res_pool->mc_bus = mc_bus; in fsl_mc_init_all_resource_pools()
553 INIT_LIST_HEAD(&res_pool->free_list); in fsl_mc_init_all_resource_pools()
554 mutex_init(&res_pool->mutex); in fsl_mc_init_all_resource_pools()
565 &mc_bus->resource_pools[pool_type]; in fsl_mc_cleanup_resource_pool()
567 list_for_each_entry_safe(resource, next, &res_pool->free_list, node) in fsl_mc_cleanup_resource_pool()
568 devm_kfree(&mc_bus_dev->dev, resource); in fsl_mc_cleanup_resource_pool()
580 * fsl_mc_allocator_probe - callback invoked when an allocatable device is
591 return -EINVAL; in fsl_mc_allocator_probe()
593 mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); in fsl_mc_allocator_probe()
594 if (!dev_is_fsl_mc(&mc_bus_dev->dev)) in fsl_mc_allocator_probe()
595 return -EINVAL; in fsl_mc_allocator_probe()
598 error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type); in fsl_mc_allocator_probe()
606 dev_dbg(&mc_dev->dev, in fsl_mc_allocator_probe()
607 "Allocatable fsl-mc device bound to fsl_mc_allocator driver"); in fsl_mc_allocator_probe()
612 * fsl_mc_allocator_remove - callback invoked when an allocatable device is
619 if (mc_dev->resource) { in fsl_mc_allocator_remove()
625 dev_dbg(&mc_dev->dev, in fsl_mc_allocator_remove()
626 "Allocatable fsl-mc device unbound from fsl_mc_allocator driver"); in fsl_mc_allocator_remove()