[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v6 30/31] xen/arm: ITS: Generate ITS node for Dom0
From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> Parse host dt and generate ITS node for Dom0. ITS node resides inside GIC node so when GIC node is encountered look for ITS node. Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> --- v6: - Introduced get_its_phandle in gic_hw_ops - Removed make_hwdom_its_dt_node callback in gic_hw_ops - Renamed gic_get_msi_handle() as gic_update_msi_phandle() - Renamed its_get_phandle to its_update_phandle() - ITS node generation is wrapped inside GICv3 - Update msi-parent phandle only if msi-parent is ITS and find its phandle on demand v5: - Moved ITS dt node generation to ITS driver v4: - Generate only one ITS node for Dom0 - Replace msi-parent references to single its phandle --- xen/arch/arm/domain_build.c | 11 ++++ xen/arch/arm/gic-v3-its.c | 120 +++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/gic-v3.c | 14 ++++- xen/arch/arm/gic.c | 6 +++ xen/include/asm-arm/gic-its.h | 2 + xen/include/asm-arm/gic.h | 3 ++ 6 files changed, 155 insertions(+), 1 deletion(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index a059de6..19cd40d 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -469,6 +469,17 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo, continue; } + /* + * Replace all msi-parent phandle references to single ITS node + * generated for Dom0 + */ + if ( dt_property_name_is_equal(prop, "msi-parent") ) + { + DPRINT(" Set msi-parent with ITS phandle (if ITS available)\n"); + gic_update_msi_phandle(kinfo->fdt, prop); + continue; + } + res = fdt_property(kinfo->fdt, prop->name, prop_data, prop_len); xfree(new_data); diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c index e825d1e..9787f81 100644 --- a/xen/arch/arm/gic-v3-its.c +++ b/xen/arch/arm/gic-v3-its.c @@ -27,6 +27,8 @@ #include <xen/sched.h> #include <xen/errno.h> #include <xen/delay.h> +#include <xen/device_tree.h> +#include <xen/libfdt/libfdt.h> #include <xen/list.h> #include <xen/sizes.h> #include <xen/vmap.h> @@ -1244,6 +1246,124 @@ static void its_cpu_init_collection(void) spin_unlock(&its_lock); } +int its_make_dt_node(const struct domain *d, void *fdt) +{ + struct its_node *its; + const struct dt_device_node *node; + const void *compatible = NULL; + u32 len; + __be32 *new_cells, *tmp; + int res = 0; + + /* Will pass only first ITS node info */ + its = list_first_entry(&its_nodes, struct its_node, entry); + if ( !its ) + { + dprintk(XENLOG_ERR, "ITS node not found\n"); + return -FDT_ERR_XEN(ENOENT); + } + + node = its->dt_node; + + compatible = dt_get_property(node, "compatible", &len); + if ( !compatible ) + { + dprintk(XENLOG_ERR, "Can't find compatible property for the its node\n"); + return -FDT_ERR_XEN(ENOENT); + } + + res = fdt_begin_node(fdt, "gic-its"); + if ( res ) + return res; + + res = fdt_property(fdt, "compatible", compatible, len); + if ( res ) + return res; + + res = fdt_property(fdt, "msi-controller", NULL, 0); + if ( res ) + return res; + + len = dt_cells_to_size(dt_n_addr_cells(node) + dt_n_size_cells(node)); + + new_cells = xzalloc_bytes(len); + if ( new_cells == NULL ) + return -FDT_ERR_XEN(ENOMEM); + tmp = new_cells; + + dt_set_range(&tmp, node, its->phys_base, its->phys_size); + + res = fdt_property(fdt, "reg", new_cells, len); + xfree(new_cells); + if ( res ) + return res; + + if ( node->phandle ) + { + res = fdt_property_cell(fdt, "phandle", node->phandle); + if ( res ) + return res; + } + + res = fdt_end_node(fdt); + + return res; +} + +static int its_find_compatible_phandle(fdt32_t msi_parent_phandle) +{ + struct its_node *its; + const struct dt_device_node *node; + fdt32_t phandle; + + list_for_each_entry(its, &its_nodes, entry) + { + node = its->dt_node; + + if ( node->phandle ) + { + phandle = cpu_to_fdt32(node->phandle); + if ( phandle == msi_parent_phandle ) + return 0; + } + } + + return -FDT_ERR_XEN(ENOENT); +} + +int its_update_phandle(void *fdt, const struct dt_property *prop) +{ + struct its_node *its; + const struct dt_device_node *node; + fdt32_t phandle, msi_parent_phandle; + + memcpy(&msi_parent_phandle, prop->value, sizeof(msi_parent_phandle)); + + /* chech if msi-parent phandle is ITS */ + if ( its_find_compatible_phandle(msi_parent_phandle) ) + return -FDT_ERR_XEN(ENOENT); + + /* Only first ITS node phandle is considered */ + its = list_first_entry(&its_nodes, struct its_node, entry); + if ( !its ) + { + dprintk(XENLOG_ERR, "ITS node not found\n"); + return -FDT_ERR_XEN(ENOENT); + } + + node = its->dt_node; + + if ( node->phandle ) + { + phandle = cpu_to_fdt32(node->phandle); + fdt_property(fdt, prop->name, (void *)&phandle, sizeof(phandle)); + + return 0; + } + + return -FDT_ERR_XEN(ENOENT); +} + static int its_force_quiescent(void __iomem *base) { u32 count = 1000000; /* 1s */ diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c index 9260c6d..4389c6a 100644 --- a/xen/arch/arm/gic-v3.c +++ b/xen/arch/arm/gic-v3.c @@ -1080,6 +1080,11 @@ static void gicv3_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask) spin_unlock(&gicv3.lock); } +static int gicv3_update_its_phandle(void *fdt, const struct dt_property *prop) +{ + return its_update_phandle(fdt, prop); +} + static int gicv3_make_hwdom_dt_node(const struct domain *d, const struct dt_device_node *node, void *fdt) @@ -1101,6 +1106,10 @@ static int gicv3_make_hwdom_dt_node(const struct domain *d, if ( res ) return res; + res = fdt_property(fdt, "ranges", NULL, 0); + if ( res ) + return res; + res = fdt_property_cell(fdt, "redistributor-stride", d->arch.vgic.rdist_stride); if ( res ) @@ -1132,8 +1141,10 @@ static int gicv3_make_hwdom_dt_node(const struct domain *d, res = fdt_property(fdt, "reg", new_cells, len); xfree(new_cells); + if ( res ) + return res; - return res; + return its_make_dt_node(d, fdt); } static const hw_irq_controller gicv3_host_irq_type = { @@ -1366,6 +1377,7 @@ static const struct gic_hw_operations gicv3_ops = { .read_vmcr_priority = gicv3_read_vmcr_priority, .read_apr = gicv3_read_apr, .secondary_init = gicv3_secondary_cpu_init, + .update_its_phandle = gicv3_update_its_phandle, .make_hwdom_dt_node = gicv3_make_hwdom_dt_node, }; diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index d91623a..2b5842e 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -758,6 +758,12 @@ void __cpuinit init_maintenance_interrupt(void) "irq-maintenance", NULL); } +void gic_update_msi_phandle(void *fdt, const struct dt_property *prop) +{ + if ( gic_lpi_supported() ) + gic_hw_ops->update_its_phandle(fdt, prop); +} + int gic_make_hwdom_dt_node(const struct domain *d, const struct dt_device_node *node, void *fdt) diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h index 75a9c95..c620b17 100644 --- a/xen/include/asm-arm/gic-its.h +++ b/xen/include/asm-arm/gic-its.h @@ -356,6 +356,7 @@ struct its_device *irqdesc_get_its_device(struct irq_desc *desc); void irqdesc_set_its_device(struct irq_desc *desc, struct its_device *dev); bool_t is_valid_collection(struct domain *d, uint32_t col); unsigned int its_get_nr_event_ids(void); +int its_make_dt_node(const struct domain *d, void *fdt); int its_init(struct rdist_prop *rdists); int its_cpu_init(void); int its_add_device(u32 devid, u32 nr_ites, struct dt_device_node *dt_its); @@ -363,6 +364,7 @@ int its_assign_device(struct domain *d, u32 vdevid, u32 pdevid); void its_set_lpi_properties(struct irq_desc *desc, const cpumask_t *cpu_mask, unsigned int priority); +int its_update_phandle(void *fdt, const struct dt_property *prop); int vits_access_guest_table(struct domain *d, paddr_t entry, void *addr, uint32_t size, bool_t set); int vits_domain_init(struct domain *d); diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index abb8616..f620aff 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -151,6 +151,7 @@ #ifndef __ASSEMBLY__ #include <xen/device_tree.h> +#include <xen/libfdt/libfdt.h> #include <xen/irq.h> #include <asm-arm/vgic.h> @@ -369,6 +370,7 @@ struct gic_hw_operations { int (*secondary_init)(void); int (*make_hwdom_dt_node)(const struct domain *d, const struct dt_device_node *node, void *fdt); + int (*update_its_phandle)(void *fdt, const struct dt_property *prop); }; void register_gic_ops(const struct gic_hw_operations *ops); @@ -376,6 +378,7 @@ int gic_make_hwdom_dt_node(const struct domain *d, const struct dt_device_node *node, void *fdt); bool_t gic_is_lpi(unsigned int irq); +void gic_update_msi_phandle(void *fdt, const struct dt_property *prop); #endif /* __ASSEMBLY__ */ #endif -- 1.7.9.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |