|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 3/6] xen/arm: Allow platforms to hook IRQ routing
On Thu, 6 Apr 2017, Chris Patterson wrote:
> From: "Chris Patterson" <pattersonc@xxxxxxxxxxxx>
>
> Some common platforms (e.g. Tegra) have non-traditional IRQ controllers
> that must be programmed in addition to their primary GICs-- and which
> can come in unusual topologies. Device trees for targets that feature
> these controllers often deviate from the conventions that Xen expects.
>
> This commit provides a foundation for support of these platforms, by
> allowing the platform to decide which IRQs can be routed by Xen, rather
> than assuming that only GIC-connected IRQs can be routed. This enables
> platform specific logic to routing the IRQ to Xen and Guest.
>
> As dt_irq_translate() is presently hard-coded to just support the
> primary interrupt controller, instead rely on the newly added
> platform_irq_is_routable() check instead. The default behaviour of this
> new function should be consistent with the previous checks for platforms
> that do not implement it.
>
> Authored-by: Kyle Temkin <temkink@xxxxxxxxxxxx>
> Signed-off-by: Kyle Temkin <temkink@xxxxxxxxxxxx>
> Signed-off-by: Chris Patterson <pattersonc@xxxxxxxxxxxx>
Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx>
> ---
>
> changes since rfc:
> - use bool instead of bool_t
> - formatting & code style cleanup
> - reuse dt_irq_translate() path and drop platform_irq_for_device() approach
> - use const qualifier for platform_irq_is_routable rirq argument
>
> ---
>
> xen/arch/arm/domain_build.c | 12 ++++++++----
> xen/arch/arm/irq.c | 5 +++--
> xen/arch/arm/platform.c | 30 ++++++++++++++++++++++++++++++
> xen/common/device_tree.c | 8 +++-----
> xen/include/asm-arm/platform.h | 12 ++++++++++++
> 5 files changed, 56 insertions(+), 11 deletions(-)
>
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index cb66304..92536dd 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1120,12 +1120,16 @@ static int handle_device(struct domain *d, struct
> dt_device_node *dev,
>
> /*
> * Don't map IRQ that have no physical meaning
> - * ie: IRQ whose controller is not the GIC
> + * ie: IRQ that does not wind up being controlled by the GIC
> + * (Note that we can't just check to see if an IRQ is owned by the
> GIC,
> + * as some platforms have a controller between the device irq and
> the GIC,
> + * such as the Tegra legacy interrupt controller.)
> */
> - if ( rirq.controller != dt_interrupt_controller )
> + if ( !platform_irq_is_routable(&rirq) )
> {
> - dt_dprintk("irq %u not connected to primary controller.
> Connected to %s\n",
> - i, dt_node_full_name(rirq.controller));
> + dt_dprintk("irq %u not (directly or indirectly) connected to
> primary"
> + "controller. Connected to %s\n", i,
> + dt_node_full_name(rirq.controller));
> continue;
> }
>
> diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
> index f3f20a6..0b4eaa9 100644
> --- a/xen/arch/arm/irq.c
> +++ b/xen/arch/arm/irq.c
> @@ -26,6 +26,7 @@
>
> #include <asm/gic.h>
> #include <asm/vgic.h>
> +#include <asm/platform.h>
>
> static unsigned int local_irqs_type[NR_LOCAL_IRQS];
> static DEFINE_SPINLOCK(local_irqs_type_lock);
> @@ -369,7 +370,7 @@ int setup_irq(unsigned int irq, unsigned int irqflags,
> struct irqaction *new)
> /* First time the IRQ is setup */
> if ( disabled )
> {
> - gic_route_irq_to_xen(desc, GIC_PRI_IRQ);
> + platform_route_irq_to_xen(desc, GIC_PRI_IRQ);
> /* It's fine to use smp_processor_id() because:
> * For PPI: irq_desc is banked
> * For SPI: we don't care for now which CPU will receive the
> @@ -506,7 +507,7 @@ int route_irq_to_guest(struct domain *d, unsigned int
> virq,
> if ( retval )
> goto out;
>
> - retval = gic_route_irq_to_guest(d, virq, desc, GIC_PRI_IRQ);
> + retval = platform_route_irq_to_guest(d, virq, desc, GIC_PRI_IRQ);
>
> spin_unlock_irqrestore(&desc->lock, flags);
>
> diff --git a/xen/arch/arm/platform.c b/xen/arch/arm/platform.c
> index 0af6d57..539ee3b 100644
> --- a/xen/arch/arm/platform.c
> +++ b/xen/arch/arm/platform.c
> @@ -147,6 +147,36 @@ bool_t platform_device_is_blacklisted(const struct
> dt_device_node *node)
> return (dt_match_node(blacklist, node) != NULL);
> }
>
> +int platform_route_irq_to_guest(struct domain *d, unsigned int virq,
> + struct irq_desc *desc, unsigned int priority)
> +{
> + if ( platform && platform->route_irq_to_guest )
> + return platform->route_irq_to_guest(d, virq, desc, priority);
> + else
> + return gic_route_irq_to_guest(d, virq, desc, priority);
> +}
> +
> +void platform_route_irq_to_xen(struct irq_desc *desc, unsigned int priority)
> +{
> + if ( platform && platform->route_irq_to_xen )
> + platform->route_irq_to_xen(desc, priority);
> + else
> + gic_route_irq_to_xen(desc, priority);
> +}
> +
> +bool platform_irq_is_routable(const struct dt_raw_irq * rirq)
> +{
> + /*
> + * If we have a platform-specific method to determine if an IRQ is
> routable,
> + * check that; otherwise fall back to checking to see if an IRQ belongs
> to
> + * the GIC.
> + */
> + if ( platform && platform->irq_is_routable )
> + return platform->irq_is_routable(rirq);
> + else
> + return (rirq->controller == dt_interrupt_controller);
> +}
> +
> /*
> * Local variables:
> * mode: C
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 7b009ea..061693b 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -22,6 +22,7 @@
> #include <xen/string.h>
> #include <xen/cpumask.h>
> #include <xen/ctype.h>
> +#include <asm/platform.h>
> #include <asm/setup.h>
> #include <xen/err.h>
>
> @@ -1467,11 +1468,8 @@ int dt_irq_translate(const struct dt_raw_irq *raw,
> ASSERT(dt_irq_xlate != NULL);
> ASSERT(dt_interrupt_controller != NULL);
>
> - /*
> - * TODO: Retrieve the right irq_xlate. This is only works for the primary
> - * interrupt controller.
> - */
> - if ( raw->controller != dt_interrupt_controller )
> + /* Only proceed with translation if the irq is routable on the platform.
> */
> + if ( !platform_irq_is_routable(raw) )
> return -EINVAL;
>
> return dt_irq_xlate(raw->specifier, raw->size,
> diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h
> index 08010ba..119ad2e 100644
> --- a/xen/include/asm-arm/platform.h
> +++ b/xen/include/asm-arm/platform.h
> @@ -26,6 +26,12 @@ struct platform_desc {
> void (*reset)(void);
> /* Platform power-off */
> void (*poweroff)(void);
> + /* Platform-specific IRQ routing */
> + int (*route_irq_to_guest)(struct domain *d, unsigned int virq,
> + struct irq_desc *desc, unsigned int priority);
> + void (*route_irq_to_xen)(struct irq_desc *desc, unsigned int priority);
> + bool (*irq_is_routable)(const struct dt_raw_irq * rirq);
> +
> /*
> * Platform quirks
> * Defined has a function because a platform can support multiple
> @@ -56,6 +62,12 @@ int platform_cpu_up(int cpu);
> void platform_reset(void);
> void platform_poweroff(void);
> bool_t platform_has_quirk(uint32_t quirk);
> +
> +int platform_route_irq_to_guest(struct domain *d, unsigned int virq,
> + struct irq_desc *desc, unsigned int
> priority);
> +void platform_route_irq_to_xen(struct irq_desc *desc, unsigned int priority);
> +bool platform_irq_is_routable(const struct dt_raw_irq *rirq);
> +
> bool_t platform_device_is_blacklisted(const struct dt_device_node *node);
>
> #define PLATFORM_START(_name, _namestr) \
> --
> 2.1.4
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |