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()
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()
113 mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); 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()
119 mutex_lock(&res_pool->mutex); in fsl_mc_resource_pool_remove_device()
121 if (res_pool->max_count <= 0) in fsl_mc_resource_pool_remove_device()
123 if (res_pool->free_count <= 0 || in fsl_mc_resource_pool_remove_device()
124 res_pool->free_count > res_pool->max_count) in fsl_mc_resource_pool_remove_device()
131 if (list_empty(&resource->node)) { in fsl_mc_resource_pool_remove_device()
132 error = -EBUSY; in fsl_mc_resource_pool_remove_device()
133 dev_err(&mc_bus_dev->dev, in fsl_mc_resource_pool_remove_device()
135 dev_name(&mc_dev->dev)); in fsl_mc_resource_pool_remove_device()
139 list_del_init(&resource->node); in fsl_mc_resource_pool_remove_device()
140 res_pool->free_count--; in fsl_mc_resource_pool_remove_device()
141 res_pool->max_count--; in fsl_mc_resource_pool_remove_device()
143 devm_kfree(&mc_bus_dev->dev, resource); in fsl_mc_resource_pool_remove_device()
144 mc_dev->resource = NULL; in fsl_mc_resource_pool_remove_device()
147 mutex_unlock(&res_pool->mutex); in fsl_mc_resource_pool_remove_device()
172 return -EINVAL; in object_type_to_pool_type()
181 struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; in fsl_mc_resource_allocate()
182 int error = -EINVAL; in fsl_mc_resource_allocate()
191 res_pool = &mc_bus->resource_pools[pool_type]; in fsl_mc_resource_allocate()
192 if (res_pool->mc_bus != mc_bus) in fsl_mc_resource_allocate()
195 mutex_lock(&res_pool->mutex); in fsl_mc_resource_allocate()
196 resource = list_first_entry_or_null(&res_pool->free_list, in fsl_mc_resource_allocate()
200 error = -ENXIO; in fsl_mc_resource_allocate()
201 dev_err(&mc_bus_dev->dev, in fsl_mc_resource_allocate()
207 if (resource->type != pool_type) in fsl_mc_resource_allocate()
209 if (resource->parent_pool != res_pool) in fsl_mc_resource_allocate()
211 if (res_pool->free_count <= 0 || in fsl_mc_resource_allocate()
212 res_pool->free_count > res_pool->max_count) in fsl_mc_resource_allocate()
215 list_del_init(&resource->node); in fsl_mc_resource_allocate()
217 res_pool->free_count--; in fsl_mc_resource_allocate()
220 mutex_unlock(&res_pool->mutex); in fsl_mc_resource_allocate()
231 res_pool = resource->parent_pool; in fsl_mc_resource_free()
232 if (resource->type != res_pool->type) in fsl_mc_resource_free()
235 mutex_lock(&res_pool->mutex); in fsl_mc_resource_free()
236 if (res_pool->free_count < 0 || in fsl_mc_resource_free()
237 res_pool->free_count >= res_pool->max_count) in fsl_mc_resource_free()
240 if (!list_empty(&resource->node)) in fsl_mc_resource_free()
243 list_add_tail(&resource->node, &res_pool->free_list); in fsl_mc_resource_free()
244 res_pool->free_count++; in fsl_mc_resource_free()
246 mutex_unlock(&res_pool->mutex); in fsl_mc_resource_free()
251 * fsl_mc_object_allocate - Allocates an fsl-mc object of the given
252 * pool type from a given fsl-mc bus instance
254 * @mc_dev: fsl-mc device which is used in conjunction with the
264 * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
275 int error = -EINVAL; in fsl_mc_object_allocate()
279 if (mc_dev->flags & FSL_MC_IS_DPRC) in fsl_mc_object_allocate()
282 if (!dev_is_fsl_mc(mc_dev->dev.parent)) in fsl_mc_object_allocate()
288 mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); in fsl_mc_object_allocate()
294 mc_adev = resource->data; in fsl_mc_object_allocate()
296 error = -EINVAL; in fsl_mc_object_allocate()
300 mc_adev->consumer_link = device_link_add(&mc_dev->dev, in fsl_mc_object_allocate()
301 &mc_adev->dev, in fsl_mc_object_allocate()
303 if (!mc_adev->consumer_link) { in fsl_mc_object_allocate()
304 error = -EINVAL; in fsl_mc_object_allocate()
319 * fsl_mc_object_free - Returns an fsl-mc object to the resource
321 * @mc_adev: Pointer to the fsl-mc device
327 resource = mc_adev->resource; in fsl_mc_object_free()
328 if (resource->type == FSL_MC_POOL_DPMCP) in fsl_mc_object_free()
330 if (resource->data != mc_adev) in fsl_mc_object_free()
335 mc_adev->consumer_link = NULL; in fsl_mc_object_free()
340 * A DPRC and the devices in the DPRC all share the same GIC-ITS device
341 * ID. A block of IRQs is pre-allocated and maintained in a pool
346 * Initialize the interrupt pool associated with an fsl-mc bus.
347 * It allocates a block of IRQs from the GIC-ITS.
359 &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; in fsl_mc_populate_irq_pool()
362 if (mc_bus->irq_resources) in fsl_mc_populate_irq_pool()
367 return -EINVAL; in fsl_mc_populate_irq_pool()
369 error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); in fsl_mc_populate_irq_pool()
373 irq_resources = devm_kcalloc(&mc_bus_dev->dev, in fsl_mc_populate_irq_pool()
377 error = -ENOMEM; in fsl_mc_populate_irq_pool()
388 mc_dev_irq->resource.type = res_pool->type; in fsl_mc_populate_irq_pool()
389 mc_dev_irq->resource.data = mc_dev_irq; in fsl_mc_populate_irq_pool()
390 mc_dev_irq->resource.parent_pool = res_pool; in fsl_mc_populate_irq_pool()
391 INIT_LIST_HEAD(&mc_dev_irq->resource.node); in fsl_mc_populate_irq_pool()
392 list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); in fsl_mc_populate_irq_pool()
395 for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { in fsl_mc_populate_irq_pool()
396 mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; in fsl_mc_populate_irq_pool()
397 mc_dev_irq->msi_desc = msi_desc; in fsl_mc_populate_irq_pool()
398 mc_dev_irq->resource.id = msi_desc->irq; in fsl_mc_populate_irq_pool()
401 res_pool->max_count = irq_count; in fsl_mc_populate_irq_pool()
402 res_pool->free_count = irq_count; in fsl_mc_populate_irq_pool()
403 mc_bus->irq_resources = irq_resources; in fsl_mc_populate_irq_pool()
407 fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); in fsl_mc_populate_irq_pool()
413 * Teardown the interrupt pool associated with an fsl-mc bus.
414 * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
420 &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; in fsl_mc_cleanup_irq_pool()
422 if (!mc_bus->irq_resources) in fsl_mc_cleanup_irq_pool()
425 if (res_pool->max_count == 0) in fsl_mc_cleanup_irq_pool()
428 if (res_pool->free_count != res_pool->max_count) in fsl_mc_cleanup_irq_pool()
431 INIT_LIST_HEAD(&res_pool->free_list); in fsl_mc_cleanup_irq_pool()
432 res_pool->max_count = 0; in fsl_mc_cleanup_irq_pool()
433 res_pool->free_count = 0; in fsl_mc_cleanup_irq_pool()
434 mc_bus->irq_resources = NULL; in fsl_mc_cleanup_irq_pool()
435 fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); in fsl_mc_cleanup_irq_pool()
440 * Allocate the IRQs required by a given fsl-mc device.
447 int error = -EINVAL; in fsl_mc_allocate_irqs()
452 if (mc_dev->irqs) in fsl_mc_allocate_irqs()
453 return -EINVAL; in fsl_mc_allocate_irqs()
455 irq_count = mc_dev->obj_desc.irq_count; in fsl_mc_allocate_irqs()
457 return -EINVAL; in fsl_mc_allocate_irqs()
462 mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); in fsl_mc_allocate_irqs()
464 if (!mc_bus->irq_resources) in fsl_mc_allocate_irqs()
465 return -EINVAL; in fsl_mc_allocate_irqs()
467 res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; in fsl_mc_allocate_irqs()
468 if (res_pool->free_count < irq_count) { in fsl_mc_allocate_irqs()
469 dev_err(&mc_dev->dev, in fsl_mc_allocate_irqs()
471 return -ENOSPC; in fsl_mc_allocate_irqs()
474 irqs = devm_kcalloc(&mc_dev->dev, irq_count, sizeof(irqs[0]), in fsl_mc_allocate_irqs()
477 return -ENOMEM; in fsl_mc_allocate_irqs()
490 irqs[i]->mc_dev = mc_dev; in fsl_mc_allocate_irqs()
491 irqs[i]->dev_irq_index = i; in fsl_mc_allocate_irqs()
494 mc_dev->irqs = irqs; in fsl_mc_allocate_irqs()
499 irqs[i]->mc_dev = NULL; in fsl_mc_allocate_irqs()
500 fsl_mc_resource_free(&irqs[i]->resource); in fsl_mc_allocate_irqs()
508 * Frees the IRQs that were allocated for an fsl-mc device.
515 struct fsl_mc_device_irq **irqs = mc_dev->irqs; in fsl_mc_free_irqs()
520 irq_count = mc_dev->obj_desc.irq_count; in fsl_mc_free_irqs()
525 mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); in fsl_mc_free_irqs()
527 if (!mc_bus->irq_resources) in fsl_mc_free_irqs()
531 irqs[i]->mc_dev = NULL; in fsl_mc_free_irqs()
532 fsl_mc_resource_free(&irqs[i]->resource); in fsl_mc_free_irqs()
535 mc_dev->irqs = NULL; in fsl_mc_free_irqs()
546 &mc_bus->resource_pools[pool_type]; in fsl_mc_init_all_resource_pools()
548 res_pool->type = pool_type; in fsl_mc_init_all_resource_pools()
549 res_pool->max_count = 0; in fsl_mc_init_all_resource_pools()
550 res_pool->free_count = 0; in fsl_mc_init_all_resource_pools()
551 res_pool->mc_bus = mc_bus; in fsl_mc_init_all_resource_pools()
552 INIT_LIST_HEAD(&res_pool->free_list); in fsl_mc_init_all_resource_pools()
553 mutex_init(&res_pool->mutex); in fsl_mc_init_all_resource_pools()
564 &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()
569 devm_kfree(&mc_bus_dev->dev, resource); in fsl_mc_cleanup_resource_pool()
582 * fsl_mc_allocator_probe - callback invoked when an allocatable device is
593 return -EINVAL; in fsl_mc_allocator_probe()
595 mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); in fsl_mc_allocator_probe()
596 if (!dev_is_fsl_mc(&mc_bus_dev->dev)) in fsl_mc_allocator_probe()
597 return -EINVAL; in fsl_mc_allocator_probe()
600 error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type); in fsl_mc_allocator_probe()
608 dev_dbg(&mc_dev->dev, in fsl_mc_allocator_probe()
609 "Allocatable fsl-mc device bound to fsl_mc_allocator driver"); in fsl_mc_allocator_probe()
614 * fsl_mc_allocator_remove - callback invoked when an allocatable device is
622 return -EINVAL; in fsl_mc_allocator_remove()
624 if (mc_dev->resource) { in fsl_mc_allocator_remove()
630 dev_dbg(&mc_dev->dev, in fsl_mc_allocator_remove()
631 "Allocatable fsl-mc device unbound from fsl_mc_allocator driver"); in fsl_mc_allocator_remove()