diff options
Diffstat (limited to 'target/linux/layerscape/patches-4.4/7147-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch')
-rw-r--r-- | target/linux/layerscape/patches-4.4/7147-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch | 326 |
1 files changed, 0 insertions, 326 deletions
diff --git a/target/linux/layerscape/patches-4.4/7147-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch b/target/linux/layerscape/patches-4.4/7147-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch deleted file mode 100644 index c02c892b21..0000000000 --- a/target/linux/layerscape/patches-4.4/7147-staging-fsl-mc-Extended-MC-bus-allocator-to-include-.patch +++ /dev/null @@ -1,326 +0,0 @@ -From 23b09c6b4162a8264b600f35d7048256a7afc0cd Mon Sep 17 00:00:00 2001 -From: "J. German Rivera" <German.Rivera@freescale.com> -Date: Wed, 6 Jan 2016 16:03:23 -0600 -Subject: [PATCH 147/226] staging: fsl-mc: Extended MC bus allocator to - include IRQs - -All the IRQs for DPAA2 objects in the same DPRC must use -the ICID of that DPRC, as their device Id in the GIC-ITS. -Thus, all these IRQs must share the same ITT table in the GIC. -As a result, a pool of IRQs with the same device Id must be -preallocated per DPRC (fsl-mc bus instance). So, the fsl-mc -bus object allocator is extended to also provide services -to allocate IRQs to DPAA2 devices, from their parent fsl-mc bus -IRQ pool. - -Signed-off-by: J. German Rivera <German.Rivera@freescale.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> ---- - drivers/staging/fsl-mc/bus/mc-allocator.c | 199 +++++++++++++++++++++++++++ - drivers/staging/fsl-mc/include/mc-private.h | 15 ++ - drivers/staging/fsl-mc/include/mc.h | 9 ++ - 3 files changed, 223 insertions(+) - ---- a/drivers/staging/fsl-mc/bus/mc-allocator.c -+++ b/drivers/staging/fsl-mc/bus/mc-allocator.c -@@ -15,6 +15,7 @@ - #include "../include/dpcon-cmd.h" - #include "dpmcp-cmd.h" - #include "dpmcp.h" -+#include <linux/msi.h> - - /** - * fsl_mc_resource_pool_add_device - add allocatable device to a resource -@@ -160,6 +161,7 @@ static const char *const fsl_mc_pool_typ - [FSL_MC_POOL_DPMCP] = "dpmcp", - [FSL_MC_POOL_DPBP] = "dpbp", - [FSL_MC_POOL_DPCON] = "dpcon", -+ [FSL_MC_POOL_IRQ] = "irq", - }; - - static int __must_check object_type_to_pool_type(const char *object_type, -@@ -465,6 +467,203 @@ void fsl_mc_object_free(struct fsl_mc_de - } - EXPORT_SYMBOL_GPL(fsl_mc_object_free); - -+/* -+ * Initialize the interrupt pool associated with a MC bus. -+ * It allocates a block of IRQs from the GIC-ITS -+ */ -+int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, -+ unsigned int irq_count) -+{ -+ unsigned int i; -+ struct msi_desc *msi_desc; -+ struct fsl_mc_device_irq *irq_resources; -+ struct fsl_mc_device_irq *mc_dev_irq; -+ int error; -+ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; -+ struct fsl_mc_resource_pool *res_pool = -+ &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; -+ -+ if (WARN_ON(irq_count == 0 || -+ irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) -+ return -EINVAL; -+ -+ error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); -+ if (error < 0) -+ return error; -+ -+ irq_resources = devm_kzalloc(&mc_bus_dev->dev, -+ sizeof(*irq_resources) * irq_count, -+ GFP_KERNEL); -+ if (!irq_resources) { -+ error = -ENOMEM; -+ goto cleanup_msi_irqs; -+ } -+ -+ for (i = 0; i < irq_count; i++) { -+ mc_dev_irq = &irq_resources[i]; -+ -+ /* -+ * NOTE: This mc_dev_irq's MSI addr/value pair will be set -+ * by the fsl_mc_msi_write_msg() callback -+ */ -+ mc_dev_irq->resource.type = res_pool->type; -+ mc_dev_irq->resource.data = mc_dev_irq; -+ mc_dev_irq->resource.parent_pool = res_pool; -+ INIT_LIST_HEAD(&mc_dev_irq->resource.node); -+ list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); -+ } -+ -+ for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { -+ mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; -+ mc_dev_irq->msi_desc = msi_desc; -+ mc_dev_irq->resource.id = msi_desc->irq; -+ } -+ -+ res_pool->max_count = irq_count; -+ res_pool->free_count = irq_count; -+ mc_bus->irq_resources = irq_resources; -+ return 0; -+ -+cleanup_msi_irqs: -+ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); -+ return error; -+} -+EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); -+ -+/** -+ * Teardown the interrupt pool associated with an MC bus. -+ * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. -+ */ -+void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) -+{ -+ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; -+ struct fsl_mc_resource_pool *res_pool = -+ &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; -+ -+ if (WARN_ON(!mc_bus->irq_resources)) -+ return; -+ -+ if (WARN_ON(res_pool->max_count == 0)) -+ return; -+ -+ if (WARN_ON(res_pool->free_count != res_pool->max_count)) -+ return; -+ -+ INIT_LIST_HEAD(&res_pool->free_list); -+ res_pool->max_count = 0; -+ res_pool->free_count = 0; -+ mc_bus->irq_resources = NULL; -+ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); -+} -+EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); -+ -+/** -+ * It allocates the IRQs required by a given MC object device. The -+ * IRQs are allocated from the interrupt pool associated with the -+ * MC bus that contains the device, if the device is not a DPRC device. -+ * Otherwise, the IRQs are allocated from the interrupt pool associated -+ * with the MC bus that represents the DPRC device itself. -+ */ -+int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) -+{ -+ int i; -+ int irq_count; -+ int res_allocated_count = 0; -+ int error = -EINVAL; -+ struct fsl_mc_device_irq **irqs = NULL; -+ struct fsl_mc_bus *mc_bus; -+ struct fsl_mc_resource_pool *res_pool; -+ -+ if (WARN_ON(mc_dev->irqs)) -+ return -EINVAL; -+ -+ irq_count = mc_dev->obj_desc.irq_count; -+ if (WARN_ON(irq_count == 0)) -+ return -EINVAL; -+ -+ if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) -+ mc_bus = to_fsl_mc_bus(mc_dev); -+ else -+ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); -+ -+ if (WARN_ON(!mc_bus->irq_resources)) -+ return -EINVAL; -+ -+ res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; -+ if (res_pool->free_count < irq_count) { -+ dev_err(&mc_dev->dev, -+ "Not able to allocate %u irqs for device\n", irq_count); -+ return -ENOSPC; -+ } -+ -+ irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), -+ GFP_KERNEL); -+ if (!irqs) -+ return -ENOMEM; -+ -+ for (i = 0; i < irq_count; i++) { -+ struct fsl_mc_resource *resource; -+ -+ error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, -+ &resource); -+ if (error < 0) -+ goto error_resource_alloc; -+ -+ irqs[i] = to_fsl_mc_irq(resource); -+ res_allocated_count++; -+ -+ WARN_ON(irqs[i]->mc_dev); -+ irqs[i]->mc_dev = mc_dev; -+ irqs[i]->dev_irq_index = i; -+ } -+ -+ mc_dev->irqs = irqs; -+ return 0; -+ -+error_resource_alloc: -+ for (i = 0; i < res_allocated_count; i++) { -+ irqs[i]->mc_dev = NULL; -+ fsl_mc_resource_free(&irqs[i]->resource); -+ } -+ -+ return error; -+} -+EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); -+ -+/* -+ * It frees the IRQs that were allocated for a MC object device, by -+ * returning them to the corresponding interrupt pool. -+ */ -+void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) -+{ -+ int i; -+ int irq_count; -+ struct fsl_mc_bus *mc_bus; -+ struct fsl_mc_device_irq **irqs = mc_dev->irqs; -+ -+ if (WARN_ON(!irqs)) -+ return; -+ -+ irq_count = mc_dev->obj_desc.irq_count; -+ -+ if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) -+ mc_bus = to_fsl_mc_bus(mc_dev); -+ else -+ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); -+ -+ if (WARN_ON(!mc_bus->irq_resources)) -+ return; -+ -+ for (i = 0; i < irq_count; i++) { -+ WARN_ON(!irqs[i]->mc_dev); -+ irqs[i]->mc_dev = NULL; -+ fsl_mc_resource_free(&irqs[i]->resource); -+ } -+ -+ mc_dev->irqs = NULL; -+} -+EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); -+ - /** - * fsl_mc_allocator_probe - callback invoked when an allocatable device is - * being added to the system ---- a/drivers/staging/fsl-mc/include/mc-private.h -+++ b/drivers/staging/fsl-mc/include/mc-private.h -@@ -30,6 +30,16 @@ struct irq_domain; - struct msi_domain_info; - - /** -+ * Maximum number of total IRQs that can be pre-allocated for an MC bus' -+ * IRQ pool -+ */ -+#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 -+ -+struct device_node; -+struct irq_domain; -+struct msi_domain_info; -+ -+/** - * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device - * @root_mc_bus_dev: MC object device representing the root DPRC - * @num_translation_ranges: number of entries in addr_translation_ranges -@@ -137,4 +147,9 @@ int __init its_fsl_mc_msi_init(void); - - void its_fsl_mc_msi_cleanup(void); - -+int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, -+ unsigned int irq_count); -+ -+void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); -+ - #endif /* _FSL_MC_PRIVATE_H_ */ ---- a/drivers/staging/fsl-mc/include/mc.h -+++ b/drivers/staging/fsl-mc/include/mc.h -@@ -14,12 +14,14 @@ - #include <linux/device.h> - #include <linux/mod_devicetable.h> - #include <linux/list.h> -+#include <linux/interrupt.h> - #include "../include/dprc.h" - - #define FSL_MC_VENDOR_FREESCALE 0x1957 - - struct fsl_mc_device; - struct fsl_mc_io; -+struct fsl_mc_bus; - - /** - * struct fsl_mc_driver - MC object device driver object -@@ -75,6 +77,7 @@ enum fsl_mc_pool_type { - FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */ - FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */ - FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */ -+ FSL_MC_POOL_IRQ, - - /* - * NOTE: New resource pool types must be added before this entry -@@ -141,6 +144,7 @@ struct fsl_mc_device_irq { - * NULL if none. - * @obj_desc: MC description of the DPAA device - * @regions: pointer to array of MMIO region entries -+ * @irqs: pointer to array of pointers to interrupts allocated to this device - * @resource: generic resource associated with this MC object device, if any. - * - * Generic device object for MC object devices that are "attached" to a -@@ -172,6 +176,7 @@ struct fsl_mc_device { - struct fsl_mc_io *mc_io; - struct dprc_obj_desc obj_desc; - struct resource *regions; -+ struct fsl_mc_device_irq **irqs; - struct fsl_mc_resource *resource; - }; - -@@ -215,6 +220,10 @@ int __must_check fsl_mc_object_allocate( - - void fsl_mc_object_free(struct fsl_mc_device *mc_adev); - -+int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev); -+ -+void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); -+ - extern struct bus_type fsl_mc_bus_type; - - #endif /* _FSL_MC_H_ */ |