* [PATCH v7 0/6] xen/arm: Interrupt management reworking
@ 2014-05-16 14:40 Julien Grall
2014-05-16 14:40 ` [PATCH v7 1/6] xen/arm: IRQ: Store IRQ type in arch_irq_desc Julien Grall
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Julien Grall @ 2014-05-16 14:40 UTC (permalink / raw)
To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell
Hello,
This is the seventh verion of this serie to rework interrupt management for ARM.
Changes in v7:
- Renaming function in patch #1
Every patches are acked except patch #1
This series is a dependency for the ARM SMMU drivers [1]. This new version
of this serie doesn't affect the IOMMU series sent a couple of days ago.
A working tree can be found here:
git://xenbits.xen.org/people/julieng/xen-unstable.git branch interrupt-mgmt-v7
Sincerely yours,
[1] http://lists.xen.org/archives/html/xen-devel/2014-05/msg01983.html
Julien Grall (6):
xen/arm: IRQ: Store IRQ type in arch_irq_desc
xen/arm: IRQ: Replace {request,setup}_dt_irq by {request,setup}_irq
xen/arm: Replace route_guest_dt_irq by route_guest_irq
xen: IRQ: Add dev_id parameter to release_irq
xen/arm: IRQ: extend {request,setup}_irq to take an irqflags in
parameter
xen/arm: IRQ: Handle multiple action per IRQ
xen/arch/arm/domain_build.c | 16 +-
xen/arch/arm/gic.c | 38 +++--
xen/arch/arm/irq.c | 237 ++++++++++++++++++++++++------
xen/arch/arm/platforms/xgene-storm.c | 15 +-
xen/arch/arm/setup.c | 3 +-
xen/arch/arm/time.c | 30 ++--
xen/arch/x86/hpet.c | 2 +-
xen/arch/x86/i8259.c | 2 +-
xen/arch/x86/irq.c | 11 +-
xen/arch/x86/time.c | 2 +-
xen/drivers/char/exynos4210-uart.c | 15 +-
xen/drivers/char/ns16550.c | 20 +--
xen/drivers/char/omap-uart.c | 15 +-
xen/drivers/char/pl011.c | 18 ++-
xen/drivers/passthrough/amd/iommu_init.c | 2 +-
xen/drivers/passthrough/vtd/iommu.c | 2 +-
xen/include/asm-arm/config.h | 2 +
xen/include/asm-arm/gic.h | 5 +-
xen/include/asm-arm/irq.h | 13 +-
xen/include/xen/device_tree.h | 3 +
xen/include/xen/irq.h | 11 +-
21 files changed, 319 insertions(+), 143 deletions(-)
--
1.7.10.4
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v7 1/6] xen/arm: IRQ: Store IRQ type in arch_irq_desc
2014-05-16 14:40 [PATCH v7 0/6] xen/arm: Interrupt management reworking Julien Grall
@ 2014-05-16 14:40 ` Julien Grall
2014-05-21 12:27 ` Ian Campbell
2014-05-16 14:40 ` [PATCH v7 2/6] xen/arm: IRQ: Replace {request, setup}_dt_irq by {request, setup}_irq Julien Grall
` (4 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Julien Grall @ 2014-05-16 14:40 UTC (permalink / raw)
To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell
For now, ARM uses different IRQ functions to setup an interrupt handler. This
is a bit annoying for common driver because we have to add idefery when
an IRQ is setup (see ns16550_init_postirq for an example).
To avoid to completely fork the IRQ management code, we can introduce a field
to store the IRQ type (e.g level/edge ...).
This patch also adds platform_get_irq which will retrieve the IRQ from the
device tree and setup correctly the IRQ type.
In order to use this solution, we have to move init_IRQ earlier for the boot
CPU. It's fine because the code only depends on percpu.
Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
Changes in v7:
- Rename irq_check_type into irq_validate_new_type
- Rename irq_set_type into irq_set_spi_type
Changes in v6:
- Introduce DT_IRQ_TYPE_INVALID to initialize IRQ type
- Introduce local_irqs_type to avoid use boot CPU PPIs type
config. Will be usefull for hotplug
- Export irq_set_type and restrict for SPIs
- Split IRQ set type for PPIs in another function
Changes in v5:
- Update comment in init_local_irq_data
- Don't set desc.arch.type on boot cpu in init_local_irq_data
- Use new macro boot_cpu instead of percpu(myvar, 0)
Changes in v4:
- Add an ASSERT to check if irq_set_type hasn't failed for PPI
on other CPU than 0
- platform_get_irq return -1 in case of error.
Changes in v3:
- irqflags is unsigned long not unsigned int
- fix comment
- don't need to set IRQ type when NONE is used
(already set at startup).
Changes in v2:
- Patch added
---
xen/arch/arm/gic.c | 25 +++++----
xen/arch/arm/irq.c | 125 ++++++++++++++++++++++++++++++++++++++---
xen/arch/arm/setup.c | 3 +-
xen/include/asm-arm/gic.h | 5 +-
xen/include/asm-arm/irq.h | 6 ++
xen/include/xen/device_tree.h | 3 +
6 files changed, 146 insertions(+), 21 deletions(-)
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 577d85b..13eeb33 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -216,14 +216,21 @@ static hw_irq_controller gic_guest_irq_type = {
/*
* - needs to be called with a valid cpu_mask, ie each cpu in the mask has
* already called gic_cpu_init
+ * - desc.lock must be held
+ * - arch.type must be valid (i.e != DT_IRQ_TYPE_INVALID)
*/
-static void gic_set_irq_properties(unsigned int irq, bool_t level,
+static void gic_set_irq_properties(struct irq_desc *desc,
const cpumask_t *cpu_mask,
unsigned int priority)
{
volatile unsigned char *bytereg;
uint32_t cfg, edgebit;
unsigned int mask;
+ unsigned int irq = desc->irq;
+ unsigned int type = desc->arch.type;
+
+ ASSERT(type != DT_IRQ_TYPE_INVALID);
+ ASSERT(spin_is_locked(&desc->lock));
spin_lock(&gic.lock);
@@ -232,9 +239,9 @@ static void gic_set_irq_properties(unsigned int irq, bool_t level,
/* Set edge / level */
cfg = GICD[GICD_ICFGR + irq / 16];
edgebit = 2u << (2 * (irq % 16));
- if ( level )
+ if ( type & DT_IRQ_TYPE_LEVEL_MASK )
cfg &= ~edgebit;
- else
+ else if ( type & DT_IRQ_TYPE_EDGE_BOTH )
cfg |= edgebit;
GICD[GICD_ICFGR + irq / 16] = cfg;
@@ -252,8 +259,8 @@ static void gic_set_irq_properties(unsigned int irq, bool_t level,
/* Program the GIC to route an interrupt to the host (i.e. Xen)
* - needs to be called with desc.lock held
*/
-void gic_route_irq_to_xen(struct irq_desc *desc, bool_t level,
- const cpumask_t *cpu_mask, unsigned int priority)
+void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mask,
+ unsigned int priority)
{
ASSERT(priority <= 0xff); /* Only 8 bits of priority */
ASSERT(desc->irq < gic.lines);/* Can't route interrupts that don't exist */
@@ -262,15 +269,14 @@ void gic_route_irq_to_xen(struct irq_desc *desc, bool_t level,
desc->handler = &gic_host_irq_type;
- gic_set_irq_properties(desc->irq, level, cpu_mask, priority);
+ gic_set_irq_properties(desc, cpu_mask, priority);
}
/* Program the GIC to route an interrupt to a guest
* - desc.lock must be held
*/
void gic_route_irq_to_guest(struct domain *d, struct irq_desc *desc,
- bool_t level, const cpumask_t *cpu_mask,
- unsigned int priority)
+ const cpumask_t *cpu_mask, unsigned int priority)
{
struct pending_irq *p;
ASSERT(spin_is_locked(&desc->lock));
@@ -278,8 +284,7 @@ void gic_route_irq_to_guest(struct domain *d, struct irq_desc *desc,
desc->handler = &gic_guest_irq_type;
desc->status |= IRQ_GUEST;
- gic_set_irq_properties(desc->irq, level, cpumask_of(smp_processor_id()),
- GIC_PRI_IRQ);
+ gic_set_irq_properties(desc, cpumask_of(smp_processor_id()), GIC_PRI_IRQ);
/* TODO: do not assume delivery to vcpu0 */
p = irq_to_pending(d->vcpu[0], desc->irq);
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 44696e7..832ee90 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -27,6 +27,9 @@
#include <asm/gic.h>
+static unsigned int local_irqs_type[NR_LOCAL_IRQS];
+static DEFINE_SPINLOCK(local_irqs_type_lock);
+
static void ack_none(struct irq_desc *irq)
{
printk("unexpected IRQ trap at irq %02x\n", irq->irq);
@@ -55,6 +58,7 @@ irq_desc_t *__irq_to_desc(int irq)
int __init arch_init_one_irq_desc(struct irq_desc *desc)
{
+ desc->arch.type = DT_IRQ_TYPE_INVALID;
return 0;
}
@@ -77,18 +81,37 @@ static int __cpuinit init_local_irq_data(void)
{
int irq;
+ spin_lock(&local_irqs_type_lock);
+
for (irq = 0; irq < NR_LOCAL_IRQS; irq++) {
struct irq_desc *desc = irq_to_desc(irq);
init_one_irq_desc(desc);
desc->irq = irq;
desc->action = NULL;
+
+ /* PPIs are included in local_irqs, we copy the IRQ type from
+ * local_irqs_type when bringing up local IRQ for this CPU in
+ * order to pick up any configuration done before this CPU came
+ * up. For interrupts configured after this point this is done in
+ * irq_set_type.
+ */
+ desc->arch.type = local_irqs_type[irq];
}
+ spin_unlock(&local_irqs_type_lock);
+
return 0;
}
void __init init_IRQ(void)
{
+ int irq;
+
+ spin_lock(&local_irqs_type_lock);
+ for ( irq = 0; irq < NR_LOCAL_IRQS; irq++ )
+ local_irqs_type[irq] = DT_IRQ_TYPE_INVALID;
+ spin_unlock(&local_irqs_type_lock);
+
BUG_ON(init_local_irq_data() < 0);
BUG_ON(init_irq_data() < 0);
}
@@ -275,9 +298,6 @@ int setup_dt_irq(const struct dt_irq *irq, struct irqaction *new)
/* First time the IRQ is setup */
if ( disabled )
{
- bool_t level;
-
- level = dt_irq_is_level_triggered(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
@@ -285,7 +305,8 @@ int setup_dt_irq(const struct dt_irq *irq, struct irqaction *new)
* TODO: Handle case where SPI is setup on different CPU than
* the targeted CPU and the priority.
*/
- gic_route_irq_to_xen(desc, level, cpumask_of(smp_processor_id()),
+ desc->arch.type = irq->type;
+ gic_route_irq_to_xen(desc, cpumask_of(smp_processor_id()),
GIC_PRI_IRQ);
desc->handler->startup(desc);
}
@@ -303,7 +324,6 @@ int route_dt_irq_to_guest(struct domain *d, const struct dt_irq *irq,
struct irq_desc *desc = irq_to_desc(irq->irq);
unsigned long flags;
int retval = 0;
- bool_t level;
action = xmalloc(struct irqaction);
if (!action)
@@ -341,8 +361,8 @@ int route_dt_irq_to_guest(struct domain *d, const struct dt_irq *irq,
if ( retval )
goto out;
- level = dt_irq_is_level_triggered(irq);
- gic_route_irq_to_guest(d, desc, level, cpumask_of(smp_processor_id()),
+ desc->arch.type = irq->type;
+ gic_route_irq_to_guest(d, desc, cpumask_of(smp_processor_id()),
GIC_PRI_IRQ);
spin_unlock_irqrestore(&desc->lock, flags);
return 0;
@@ -383,6 +403,97 @@ void pirq_set_affinity(struct domain *d, int pirq, const cpumask_t *mask)
BUG();
}
+static bool_t irq_validate_new_type(unsigned int curr, unsigned new)
+{
+ return (curr == DT_IRQ_TYPE_INVALID || curr == new );
+}
+
+int irq_set_spi_type(unsigned int spi, unsigned int type)
+{
+ unsigned long flags;
+ struct irq_desc *desc = irq_to_desc(spi);
+ int ret = -EBUSY;
+
+ /* This function should not be used for other than SPIs */
+ if ( spi < NR_LOCAL_IRQS )
+ return -EINVAL;
+
+ spin_lock_irqsave(&desc->lock, flags);
+
+ if ( !irq_validate_new_type(desc->arch.type, type) )
+ goto err;
+
+ desc->arch.type = type;
+
+ ret = 0;
+
+err:
+ spin_unlock_irqrestore(&desc->lock, flags);
+ return ret;
+}
+
+static int irq_local_set_type(unsigned int irq, unsigned int type)
+{
+ unsigned int cpu;
+ unsigned int old_type;
+ unsigned long flags;
+ int ret = -EBUSY;
+ struct irq_desc *desc;
+
+ ASSERT(irq < NR_LOCAL_IRQS);
+
+ spin_lock(&local_irqs_type_lock);
+
+ old_type = local_irqs_type[irq];
+
+ if ( !irq_validate_new_type(old_type, type) )
+ goto unlock;
+
+ ret = 0;
+ /* We don't need to reconfigure if the type is correctly set */
+ if ( old_type == type )
+ goto unlock;
+
+ local_irqs_type[irq] = type;
+
+ for_each_cpu( cpu, &cpu_online_map )
+ {
+ desc = &per_cpu(local_irq_desc, cpu)[irq];
+ spin_lock_irqsave(&desc->lock, flags);
+ desc->arch.type = type;
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+
+unlock:
+ spin_unlock(&local_irqs_type_lock);
+ return ret;
+}
+
+int platform_get_irq(const struct dt_device_node *device, int index)
+{
+ struct dt_irq dt_irq;
+ unsigned int type, irq;
+ int res;
+
+ res = dt_device_get_irq(device, index, &dt_irq);
+ if ( res )
+ return -1;
+
+ irq = dt_irq.irq;
+ type = dt_irq.type;
+
+ /* Setup the IRQ type */
+ if ( irq < NR_LOCAL_IRQS )
+ res = irq_local_set_type(irq, type);
+ else
+ res = irq_set_spi_type(irq, type);
+
+ if ( res )
+ return -1;
+
+ return irq;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index c983d95..b9ce7a9 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -688,6 +688,8 @@ void __init start_xen(unsigned long boot_phys_offset,
dt_unflatten_host_device_tree();
dt_irq_xlate = gic_irq_xlate;
+ init_IRQ();
+
dt_uart_init();
console_init_preirq();
@@ -717,7 +719,6 @@ void __init start_xen(unsigned long boot_phys_offset,
tasklet_subsys_init();
- init_IRQ();
xsm_dt_init();
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index b750b17..80f8dd2 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -168,11 +168,10 @@ extern void vgic_clear_pending_irqs(struct vcpu *v);
extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
/* Program the GIC to route an interrupt */
-extern void gic_route_irq_to_xen(struct irq_desc *desc, bool_t level,
- const cpumask_t *cpu_mask,
+extern void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t *cpu_mask,
unsigned int priority);
extern void gic_route_irq_to_guest(struct domain *, struct irq_desc *desc,
- bool_t level, const cpumask_t *cpu_mask,
+ const cpumask_t *cpu_mask,
unsigned int priority);
extern void gic_inject(void);
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index b52c26f..a7a796d 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -16,6 +16,7 @@ struct arch_pirq
struct arch_irq_desc {
int eoi_cpu;
+ unsigned int type;
};
#define NR_LOCAL_IRQS 32
@@ -47,6 +48,11 @@ int setup_dt_irq(const struct dt_irq *irq, struct irqaction *new);
int route_dt_irq_to_guest(struct domain *d, const struct dt_irq *irq,
const char *devname);
+/* Set IRQ type for an SPI */
+int irq_set_spi_type(unsigned int spi, unsigned int type);
+
+int platform_get_irq(const struct dt_device_node *device, int index);
+
#endif /* _ASM_HW_IRQ_H */
/*
* Local variables:
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index a169f0d..25db076 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -135,6 +135,7 @@ struct dt_phandle_args {
* DT_IRQ_TYPE_LEVEL_LOW - low level triggered
* DT_IRQ_TYPE_LEVEL_MASK - Mask to filter out the level bits
* DT_IRQ_TYPE_SENSE_MASK - Mask for all the above bits
+ * DT_IRQ_TYPE_INVALID - Use to initialize the type
*/
#define DT_IRQ_TYPE_NONE 0x00000000
#define DT_IRQ_TYPE_EDGE_RISING 0x00000001
@@ -147,6 +148,8 @@ struct dt_phandle_args {
(DT_IRQ_TYPE_LEVEL_LOW | DT_IRQ_TYPE_LEVEL_HIGH)
#define DT_IRQ_TYPE_SENSE_MASK 0x0000000f
+#define DT_IRQ_TYPE_INVALID 0x00000010
+
/**
* dt_irq - describe an IRQ in the device tree
* @irq: IRQ number
--
1.7.10.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v7 2/6] xen/arm: IRQ: Replace {request, setup}_dt_irq by {request, setup}_irq
2014-05-16 14:40 [PATCH v7 0/6] xen/arm: Interrupt management reworking Julien Grall
2014-05-16 14:40 ` [PATCH v7 1/6] xen/arm: IRQ: Store IRQ type in arch_irq_desc Julien Grall
@ 2014-05-16 14:40 ` Julien Grall
2014-05-16 14:40 ` [PATCH v7 3/6] xen/arm: Replace route_guest_dt_irq by route_guest_irq Julien Grall
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Julien Grall @ 2014-05-16 14:40 UTC (permalink / raw)
To: xen-devel
Cc: stefano.stabellini, Keir Fraser, Julien Grall, tim, ian.campbell
Now that irq_desc stores the type of the IRQ (e.g level/edge,...), we don't
need to use specific IRQ function for ARM.
Also replace every call to dt_device_get_irq by platform_get_irq which is
a wrapper to this function and setup the IRQ type correctly.
Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Keir Fraser <keir@xen.org>
---
Changes in v5:
- exynos4210 was testing the wrong IRQ variable
Changes in v4:
- platform_get_irq now returns -1 in case of error.
Changes in v3:
- Fix typoes in commit message
Changes in v2:
- Patch added
---
xen/arch/arm/gic.c | 13 +++++++------
xen/arch/arm/irq.c | 23 +++++++++++------------
xen/arch/arm/time.c | 30 ++++++++++++++++--------------
xen/drivers/char/exynos4210-uart.c | 15 ++++++++-------
xen/drivers/char/ns16550.c | 18 ++++--------------
xen/drivers/char/omap-uart.c | 15 ++++++++-------
xen/drivers/char/pl011.c | 18 ++++++++++--------
xen/include/asm-arm/irq.h | 5 -----
8 files changed, 64 insertions(+), 73 deletions(-)
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 13eeb33..b9fa73d 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -47,7 +47,7 @@ static struct {
paddr_t hbase; /* Address of virtual interface registers */
paddr_t vbase; /* Address of virtual cpu interface registers */
unsigned int lines; /* Number of interrupts (SPIs + PPIs + SGIs) */
- struct dt_irq maintenance; /* IRQ maintenance */
+ unsigned int maintenance_irq; /* IRQ maintenance */
unsigned int cpus;
spinlock_t lock;
} gic;
@@ -433,9 +433,10 @@ void __init gic_init(void)
if ( res || !gic.vbase || (gic.vbase & ~PAGE_MASK) )
panic("GIC: Cannot find a valid address for the virtual CPU");
- res = dt_device_get_irq(node, 0, &gic.maintenance);
- if ( res )
+ res = platform_get_irq(node, 0);
+ if ( res < 0 )
panic("GIC: Cannot find the maintenance IRQ");
+ gic.maintenance_irq = res;
/* Set the GIC as the primary interrupt controller */
dt_interrupt_controller = node;
@@ -449,7 +450,7 @@ void __init gic_init(void)
" gic_vcpu_addr=%"PRIpaddr"\n"
" gic_maintenance_irq=%u\n",
gic.dbase, gic.cbase, gic.hbase, gic.vbase,
- gic.maintenance.irq);
+ gic.maintenance_irq);
if ( (gic.dbase & ~PAGE_MASK) || (gic.cbase & ~PAGE_MASK) ||
(gic.hbase & ~PAGE_MASK) || (gic.vbase & ~PAGE_MASK) )
@@ -886,8 +887,8 @@ void gic_dump_info(struct vcpu *v)
void __cpuinit init_maintenance_interrupt(void)
{
- request_dt_irq(&gic.maintenance, maintenance_interrupt,
- "irq-maintenance", NULL);
+ request_irq(gic.maintenance_irq, maintenance_interrupt,
+ "irq-maintenance", NULL);
}
/*
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 832ee90..0808e36 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -133,9 +133,9 @@ static inline struct domain *irq_get_domain(struct irq_desc *desc)
return desc->action->dev_id;
}
-int request_dt_irq(const struct dt_irq *irq,
- void (*handler)(int, void *, struct cpu_user_regs *),
- const char *devname, void *dev_id)
+int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct cpu_user_regs *),
+ const char *devname, void *dev_id)
{
struct irqaction *action;
int retval;
@@ -146,13 +146,13 @@ int request_dt_irq(const struct dt_irq *irq,
* which interrupt is which (messes up the interrupt freeing
* logic etc).
*/
- if (irq->irq >= nr_irqs)
+ if ( irq >= nr_irqs )
return -EINVAL;
- if (!handler)
+ if ( !handler )
return -EINVAL;
action = xmalloc(struct irqaction);
- if (!action)
+ if ( !action )
return -ENOMEM;
action->handler = handler;
@@ -160,8 +160,8 @@ int request_dt_irq(const struct dt_irq *irq,
action->dev_id = dev_id;
action->free_on_release = 1;
- retval = setup_dt_irq(irq, action);
- if (retval)
+ retval = setup_irq(irq, action);
+ if ( retval )
xfree(action);
return retval;
@@ -268,14 +268,14 @@ static int __setup_irq(struct irq_desc *desc, struct irqaction *new)
return 0;
}
-int setup_dt_irq(const struct dt_irq *irq, struct irqaction *new)
+int setup_irq(unsigned int irq, struct irqaction *new)
{
int rc;
unsigned long flags;
struct irq_desc *desc;
bool_t disabled;
- desc = irq_to_desc(irq->irq);
+ desc = irq_to_desc(irq);
spin_lock_irqsave(&desc->lock, flags);
@@ -285,7 +285,7 @@ int setup_dt_irq(const struct dt_irq *irq, struct irqaction *new)
spin_unlock_irqrestore(&desc->lock, flags);
printk(XENLOG_ERR "ERROR: IRQ %u is already in use by the domain %u\n",
- irq->irq, d->domain_id);
+ irq, d->domain_id);
return -EBUSY;
}
@@ -305,7 +305,6 @@ int setup_dt_irq(const struct dt_irq *irq, struct irqaction *new)
* TODO: Handle case where SPI is setup on different CPU than
* the targeted CPU and the priority.
*/
- desc->arch.type = irq->type;
gic_route_irq_to_xen(desc, cpumask_of(smp_processor_id()),
GIC_PRI_IRQ);
desc->handler->startup(desc);
diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index d04c97a..7eb480e 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -48,13 +48,13 @@ uint64_t __read_mostly boot_count;
* register-mapped time source in the SoC. */
unsigned long __read_mostly cpu_khz; /* CPU clock frequency in kHz. */
-static struct dt_irq timer_irq[MAX_TIMER_PPI];
+static unsigned int timer_irq[MAX_TIMER_PPI];
unsigned int timer_get_irq(enum timer_ppi ppi)
{
ASSERT(ppi >= TIMER_PHYS_SECURE_PPI && ppi < MAX_TIMER_PPI);
- return timer_irq[ppi].irq;
+ return timer_irq[ppi];
}
/*static inline*/ s_time_t ticks_to_ns(uint64_t ticks)
@@ -120,15 +120,17 @@ int __init init_xen_time(void)
/* Retrieve all IRQs for the timer */
for ( i = TIMER_PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++ )
{
- res = dt_device_get_irq(dev, i, &timer_irq[i]);
- if ( res )
+ res = platform_get_irq(dev, i);
+
+ if ( res < 0 )
panic("Timer: Unable to retrieve IRQ %u from the device tree", i);
+ timer_irq[i] = res;
}
printk("Generic Timer IRQ: phys=%u hyp=%u virt=%u\n",
- timer_irq[TIMER_PHYS_NONSECURE_PPI].irq,
- timer_irq[TIMER_HYP_PPI].irq,
- timer_irq[TIMER_VIRT_PPI].irq);
+ timer_irq[TIMER_PHYS_NONSECURE_PPI],
+ timer_irq[TIMER_HYP_PPI],
+ timer_irq[TIMER_VIRT_PPI]);
res = platform_init_time();
if ( res )
@@ -192,7 +194,7 @@ int reprogram_timer(s_time_t timeout)
/* Handle the firing timer */
static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
{
- if ( irq == (timer_irq[TIMER_HYP_PPI].irq) &&
+ if ( irq == (timer_irq[TIMER_HYP_PPI]) &&
READ_SYSREG32(CNTHP_CTL_EL2) & CNTx_CTL_PENDING )
{
/* Signal the generic timer code to do its work */
@@ -201,7 +203,7 @@ static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
WRITE_SYSREG32(0, CNTHP_CTL_EL2);
}
- if ( irq == (timer_irq[TIMER_PHYS_NONSECURE_PPI].irq) &&
+ if ( irq == (timer_irq[TIMER_PHYS_NONSECURE_PPI]) &&
READ_SYSREG32(CNTP_CTL_EL0) & CNTx_CTL_PENDING )
{
/* Signal the generic timer code to do its work */
@@ -234,12 +236,12 @@ void __cpuinit init_timer_interrupt(void)
WRITE_SYSREG32(0, CNTHP_CTL_EL2); /* Hypervisor's timer disabled */
isb();
- request_dt_irq(&timer_irq[TIMER_HYP_PPI], timer_interrupt,
- "hyptimer", NULL);
- request_dt_irq(&timer_irq[TIMER_VIRT_PPI], vtimer_interrupt,
+ request_irq(timer_irq[TIMER_HYP_PPI], timer_interrupt,
+ "hyptimer", NULL);
+ request_irq(timer_irq[TIMER_VIRT_PPI], vtimer_interrupt,
"virtimer", NULL);
- request_dt_irq(&timer_irq[TIMER_PHYS_NONSECURE_PPI], timer_interrupt,
- "phytimer", NULL);
+ request_irq(timer_irq[TIMER_PHYS_NONSECURE_PPI], timer_interrupt,
+ "phytimer", NULL);
}
/* Wait a set number of microseconds */
diff --git a/xen/drivers/char/exynos4210-uart.c b/xen/drivers/char/exynos4210-uart.c
index 370539c..404ce05 100644
--- a/xen/drivers/char/exynos4210-uart.c
+++ b/xen/drivers/char/exynos4210-uart.c
@@ -30,7 +30,7 @@
static struct exynos4210_uart {
unsigned int baud, clock_hz, data_bits, parity, stop_bits;
- struct dt_irq irq;
+ unsigned int irq;
void *regs;
struct irqaction irqaction;
struct vuart_info vuart;
@@ -197,9 +197,9 @@ static void __init exynos4210_uart_init_postirq(struct serial_port *port)
uart->irqaction.name = "exynos4210_uart";
uart->irqaction.dev_id = port;
- if ( (rc = setup_dt_irq(&uart->irq, &uart->irqaction)) != 0 )
+ if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
dprintk(XENLOG_ERR, "Failed to allocated exynos4210_uart IRQ %d\n",
- uart->irq.irq);
+ uart->irq);
/* Unmask interrupts */
exynos4210_write(uart, UINTM, ~UINTM_ALLI);
@@ -272,7 +272,7 @@ static int __init exynos4210_uart_irq(struct serial_port *port)
{
struct exynos4210_uart *uart = port->uart;
- return uart->irq.irq;
+ return uart->irq;
}
static const struct vuart_info *exynos4210_vuart_info(struct serial_port *port)
@@ -323,12 +323,13 @@ static int __init exynos4210_uart_init(struct dt_device_node *dev,
return res;
}
- res = dt_device_get_irq(dev, 0, &uart->irq);
- if ( res )
+ res = platform_get_irq(dev, 0);
+ if ( res < 0 )
{
printk("exynos4210: Unable to retrieve the IRQ\n");
- return res;
+ return -EINVAL;
}
+ uart->irq = res;
uart->regs = ioremap_nocache(addr, size);
if ( !uart->regs )
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c
index 21f086a..6691806 100644
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -76,9 +76,6 @@ static struct ns16550 {
u8 bar_idx;
bool_t enable_ro; /* Make MMIO devices read only to Dom0 */
#endif
-#ifdef HAS_DEVICE_TREE
- struct dt_irq dt_irq;
-#endif
} ns16550_com[2] = { { 0 } };
struct ns16550_config_mmio {
@@ -612,13 +609,8 @@ static void __init ns16550_init_postirq(struct serial_port *port)
uart->irqaction.handler = ns16550_interrupt;
uart->irqaction.name = "ns16550";
uart->irqaction.dev_id = port;
-#ifdef HAS_DEVICE_TREE
- if ( (rc = setup_dt_irq(&uart->dt_irq, &uart->irqaction)) != 0 )
- printk("ERROR: Failed to allocate ns16550 DT IRQ.\n");
-#else
if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
printk("ERROR: Failed to allocate ns16550 IRQ %d\n", uart->irq);
-#endif
}
ns16550_setup_postirq(uart);
@@ -1172,12 +1164,10 @@ static int __init ns16550_uart_dt_init(struct dt_device_node *dev,
if ( uart->reg_width != 1 && uart->reg_width != 4 )
return -EINVAL;
- res = dt_device_get_irq(dev, 0, &uart->dt_irq);
- if ( res )
- return res;
-
- /* The common bit of the driver mostly deals with irq not dt_irq. */
- uart->irq = uart->dt_irq.irq;
+ res = platform_get_irq(dev, 0);
+ if ( ! res )
+ return -EINVAL;
+ uart->irq = res;
uart->dw_usr_bsy = dt_device_is_compatible(dev, "snps,dw-apb-uart");
diff --git a/xen/drivers/char/omap-uart.c b/xen/drivers/char/omap-uart.c
index b8da509..e598785 100644
--- a/xen/drivers/char/omap-uart.c
+++ b/xen/drivers/char/omap-uart.c
@@ -30,7 +30,7 @@
static struct omap_uart {
u32 baud, clock_hz, data_bits, parity, stop_bits, fifo_size;
- struct dt_irq irq;
+ unsigned int irq;
char __iomem *regs;
struct irqaction irqaction;
struct vuart_info vuart;
@@ -205,10 +205,10 @@ static void __init omap_uart_init_postirq(struct serial_port *port)
uart->irqaction.name = "omap_uart";
uart->irqaction.dev_id = port;
- if ( setup_dt_irq(&uart->irq, &uart->irqaction) != 0 )
+ if ( setup_irq(uart->irq, &uart->irqaction) != 0 )
{
dprintk(XENLOG_ERR, "Failed to allocated omap_uart IRQ %d\n",
- uart->irq.irq);
+ uart->irq);
return;
}
@@ -259,7 +259,7 @@ static int __init omap_uart_irq(struct serial_port *port)
{
struct omap_uart *uart = port->uart;
- return ((uart->irq.irq > 0) ? uart->irq.irq : -1);
+ return ((uart->irq > 0) ? uart->irq : -1);
}
static const struct vuart_info *omap_vuart_info(struct serial_port *port)
@@ -317,12 +317,13 @@ static int __init omap_uart_init(struct dt_device_node *dev,
return res;
}
- res = dt_device_get_irq(dev, 0, &uart->irq);
- if ( res )
+ res = platform_get_irq(dev, 0);
+ if ( res < 0 )
{
printk("omap-uart: Unable to retrieve the IRQ\n");
- return res;
+ return -EINVAL;
}
+ uart->irq = res;
uart->regs = ioremap_nocache(addr, size);
if ( !uart->regs )
diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index 459e686..89bda94 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -32,7 +32,7 @@
static struct pl011 {
unsigned int baud, clock_hz, data_bits, parity, stop_bits;
- struct dt_irq irq;
+ unsigned int irq;
void __iomem *regs;
/* UART with IRQ line: interrupt-driven I/O. */
struct irqaction irqaction;
@@ -132,13 +132,13 @@ static void __init pl011_init_postirq(struct serial_port *port)
struct pl011 *uart = port->uart;
int rc;
- if ( uart->irq.irq > 0 )
+ if ( uart->irq > 0 )
{
uart->irqaction.handler = pl011_interrupt;
uart->irqaction.name = "pl011";
uart->irqaction.dev_id = port;
- if ( (rc = setup_dt_irq(&uart->irq, &uart->irqaction)) != 0 )
- printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq.irq);
+ if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
+ printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq);
}
/* Clear pending error interrupts */
@@ -186,7 +186,8 @@ static int pl011_getc(struct serial_port *port, char *pc)
static int __init pl011_irq(struct serial_port *port)
{
struct pl011 *uart = port->uart;
- return ((uart->irq.irq > 0) ? uart->irq.irq : -1);
+
+ return ((uart->irq > 0) ? uart->irq : -1);
}
static const struct vuart_info *pl011_vuart(struct serial_port *port)
@@ -239,12 +240,13 @@ static int __init pl011_uart_init(struct dt_device_node *dev,
return res;
}
- res = dt_device_get_irq(dev, 0, &uart->irq);
- if ( res )
+ res = platform_get_irq(dev, 0);
+ if ( res < 0 )
{
printk("pl011: Unable to retrieve the IRQ\n");
- return res;
+ return -EINVAL;
}
+ uart->irq = res;
uart->regs = ioremap_nocache(addr, size);
if ( !uart->regs )
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index a7a796d..bb55390 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -40,11 +40,6 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq);
void init_IRQ(void);
void init_secondary_IRQ(void);
-int request_dt_irq(const struct dt_irq *irq,
- void (*handler)(int, void *, struct cpu_user_regs *),
- const char *devname, void *dev_id);
-int setup_dt_irq(const struct dt_irq *irq, struct irqaction *new);
-
int route_dt_irq_to_guest(struct domain *d, const struct dt_irq *irq,
const char *devname);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v7 3/6] xen/arm: Replace route_guest_dt_irq by route_guest_irq
2014-05-16 14:40 [PATCH v7 0/6] xen/arm: Interrupt management reworking Julien Grall
2014-05-16 14:40 ` [PATCH v7 1/6] xen/arm: IRQ: Store IRQ type in arch_irq_desc Julien Grall
2014-05-16 14:40 ` [PATCH v7 2/6] xen/arm: IRQ: Replace {request, setup}_dt_irq by {request, setup}_irq Julien Grall
@ 2014-05-16 14:40 ` Julien Grall
2014-05-16 14:40 ` [PATCH v7 4/6] xen: IRQ: Add dev_id parameter to release_irq Julien Grall
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Julien Grall @ 2014-05-16 14:40 UTC (permalink / raw)
To: xen-devel; +Cc: stefano.stabellini, Julien Grall, tim, ian.campbell
We can use platform_get_irq to get the IRQ which will be route to the guest.
platform_get_irq will store the type of IRQ (e.g level/edge...) directly in
the irq_desc.
This will avoid to have device tree specific routing function.
Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
Changes in v7:
- irq_set_type has been renamed into irq_set_spi_type
Changes in v6:
- Patch added
---
xen/arch/arm/domain_build.c | 16 +++++++++-------
xen/arch/arm/irq.c | 12 +++++-------
xen/arch/arm/platforms/xgene-storm.c | 15 ++++++++++-----
xen/include/asm-arm/irq.h | 4 ++--
4 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index c424793..ddbb88d 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -686,7 +686,7 @@ static int map_device(struct domain *d, struct dt_device_node *dev)
unsigned int naddr;
unsigned int i;
int res;
- struct dt_irq irq;
+ unsigned int irq;
struct dt_raw_irq rirq;
u64 addr, size;
@@ -729,20 +729,22 @@ static int map_device(struct domain *d, struct dt_device_node *dev)
continue;
}
- res = dt_irq_translate(&rirq, &irq);
- if ( res )
+ res = platform_get_irq(dev, i);
+ if ( res < 0 )
{
- printk(XENLOG_ERR "Unable to translate irq %u for %s\n",
+ printk(XENLOG_ERR "Unable to get irq %u for %s\n",
i, dt_node_full_name(dev));
return res;
}
- DPRINT("irq %u = %u type = 0x%x\n", i, irq.irq, irq.type);
- res = route_dt_irq_to_guest(d, &irq, dt_node_name(dev));
+ irq = res;
+
+ DPRINT("irq %u = %u\n", i, irq);
+ res = route_irq_to_guest(d, irq, dt_node_name(dev));
if ( res )
{
printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n",
- irq.irq, d->domain_id);
+ irq, d->domain_id);
return res;
}
}
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 0808e36..fa35e0d 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -316,11 +316,11 @@ err:
return rc;
}
-int route_dt_irq_to_guest(struct domain *d, const struct dt_irq *irq,
- const char * devname)
+int route_irq_to_guest(struct domain *d, unsigned int irq,
+ const char * devname)
{
struct irqaction *action;
- struct irq_desc *desc = irq_to_desc(irq->irq);
+ struct irq_desc *desc = irq_to_desc(irq);
unsigned long flags;
int retval = 0;
@@ -348,10 +348,9 @@ int route_dt_irq_to_guest(struct domain *d, const struct dt_irq *irq,
if ( desc->status & IRQ_GUEST )
printk(XENLOG_ERR "ERROR: IRQ %u is already used by domain %u\n",
- irq->irq, ad->domain_id);
+ irq, ad->domain_id);
else
- printk(XENLOG_ERR "ERROR: IRQ %u is already used by Xen\n",
- irq->irq);
+ printk(XENLOG_ERR "ERROR: IRQ %u is already used by Xen\n", irq);
retval = -EBUSY;
goto out;
}
@@ -360,7 +359,6 @@ int route_dt_irq_to_guest(struct domain *d, const struct dt_irq *irq,
if ( retval )
goto out;
- desc->arch.type = irq->type;
gic_route_irq_to_guest(d, desc, cpumask_of(smp_processor_id()),
GIC_PRI_IRQ);
spin_unlock_irqrestore(&desc->lock, flags);
diff --git a/xen/arch/arm/platforms/xgene-storm.c b/xen/arch/arm/platforms/xgene-storm.c
index 70aab73..c9dd63c 100644
--- a/xen/arch/arm/platforms/xgene-storm.c
+++ b/xen/arch/arm/platforms/xgene-storm.c
@@ -57,16 +57,21 @@ static int map_one_mmio(struct domain *d, const char *what,
static int map_one_spi(struct domain *d, const char *what,
unsigned int spi, unsigned int type)
{
- struct dt_irq irq;
+ unsigned int irq;
int ret;
- irq.type = type;
+ irq = spi + 32; /* SPIs start at IRQ 32 */
- irq.irq = spi + 32; /* SPIs start at IRQ 32 */
+ ret = irq_set_spi_type(irq, type);
+ if ( ret )
+ {
+ printk("Failed to set the type for IRQ%u\n", irq);
+ return ret;
+ }
- printk("Additional IRQ %u (%s)\n", irq.irq, what);
+ printk("Additional IRQ %u (%s)\n", irq, what);
- ret = route_dt_irq_to_guest(d, &irq, what);
+ ret = route_irq_to_guest(d, irq, what);
if ( ret )
printk("Failed to route %s to dom%d\n", what, d->domain_id);
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index bb55390..e567f71 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -40,8 +40,8 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq);
void init_IRQ(void);
void init_secondary_IRQ(void);
-int route_dt_irq_to_guest(struct domain *d, const struct dt_irq *irq,
- const char *devname);
+int route_irq_to_guest(struct domain *d, unsigned int irq,
+ const char *devname);
/* Set IRQ type for an SPI */
int irq_set_spi_type(unsigned int spi, unsigned int type);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v7 4/6] xen: IRQ: Add dev_id parameter to release_irq
2014-05-16 14:40 [PATCH v7 0/6] xen/arm: Interrupt management reworking Julien Grall
` (2 preceding siblings ...)
2014-05-16 14:40 ` [PATCH v7 3/6] xen/arm: Replace route_guest_dt_irq by route_guest_irq Julien Grall
@ 2014-05-16 14:40 ` Julien Grall
2014-05-16 14:40 ` [PATCH v7 5/6] xen/arm: IRQ: extend {request, setup}_irq to take an irqflags in parameter Julien Grall
2014-05-16 14:40 ` [PATCH v7 6/6] xen/arm: IRQ: Handle multiple action per IRQ Julien Grall
5 siblings, 0 replies; 8+ messages in thread
From: Julien Grall @ 2014-05-16 14:40 UTC (permalink / raw)
To: xen-devel
Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Jan Beulich
The new parameter (dev_id) will be used in on ARM to release the right
action when support for multiple action is added.
Even if this function is declared in common code, no one is using it. So it's
safe to modify the prototype also for x86.
Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
Changes in v3:
- Fix typoes in commit message
- Don't remove __init on release_irq for x86
Changes in v2:
- Patch added
---
xen/arch/arm/irq.c | 2 +-
xen/arch/x86/irq.c | 2 +-
xen/include/xen/irq.h | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index fa35e0d..24eca0a 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -232,7 +232,7 @@ out_no_end:
irq_exit();
}
-void release_irq(unsigned int irq)
+void release_irq(unsigned int irq, const void *dev_id)
{
struct irq_desc *desc;
unsigned long flags;
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 5b5b169..727472d 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -983,7 +983,7 @@ int __init request_irq(unsigned int irq,
return retval;
}
-void __init release_irq(unsigned int irq)
+void __init release_irq(unsigned int irq, const void *dev_id)
{
struct irq_desc *desc;
unsigned long flags;
diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h
index f2e6215..1f8bdb3 100644
--- a/xen/include/xen/irq.h
+++ b/xen/include/xen/irq.h
@@ -90,7 +90,7 @@ int arch_init_one_irq_desc(struct irq_desc *);
#define irq_desc_initialized(desc) ((desc)->handler != NULL)
extern int setup_irq(unsigned int irq, struct irqaction *);
-extern void release_irq(unsigned int irq);
+extern void release_irq(unsigned int irq, const void *dev_id);
extern int request_irq(unsigned int irq,
void (*handler)(int, void *, struct cpu_user_regs *),
const char * devname, void *dev_id);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v7 5/6] xen/arm: IRQ: extend {request, setup}_irq to take an irqflags in parameter
2014-05-16 14:40 [PATCH v7 0/6] xen/arm: Interrupt management reworking Julien Grall
` (3 preceding siblings ...)
2014-05-16 14:40 ` [PATCH v7 4/6] xen: IRQ: Add dev_id parameter to release_irq Julien Grall
@ 2014-05-16 14:40 ` Julien Grall
2014-05-16 14:40 ` [PATCH v7 6/6] xen/arm: IRQ: Handle multiple action per IRQ Julien Grall
5 siblings, 0 replies; 8+ messages in thread
From: Julien Grall @ 2014-05-16 14:40 UTC (permalink / raw)
To: xen-devel
Cc: Keir Fraser, ian.campbell, Julien Grall, tim, stefano.stabellini,
Jan Beulich, Aravind Gopalakrishnan, Suravee Suthikulpanit,
Xiantao Zhang
The irqflags will be used later on ARM to know if we can shared the IRQ or not.
On x86, the irqflags should always be 0.
Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Cc: Aravind Gopalakrishnan <Aravind.Gopalakrishnan@amd.com>
Cc: Xiantao Zhang <xiantao.zhang@intel.com>
---
Changes in v4:
- request_irq should pass irqflags to setup irq on x86
Changes in v3:
- Patch added
---
xen/arch/arm/gic.c | 2 +-
xen/arch/arm/irq.c | 6 +++---
xen/arch/arm/time.c | 6 +++---
xen/arch/x86/hpet.c | 2 +-
xen/arch/x86/i8259.c | 2 +-
xen/arch/x86/irq.c | 9 ++++++---
xen/arch/x86/time.c | 2 +-
xen/drivers/char/exynos4210-uart.c | 2 +-
xen/drivers/char/ns16550.c | 2 +-
xen/drivers/char/omap-uart.c | 2 +-
xen/drivers/char/pl011.c | 2 +-
xen/drivers/passthrough/amd/iommu_init.c | 2 +-
xen/drivers/passthrough/vtd/iommu.c | 2 +-
xen/include/xen/irq.h | 5 +++--
14 files changed, 25 insertions(+), 21 deletions(-)
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index b9fa73d..ff1addc 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -887,7 +887,7 @@ void gic_dump_info(struct vcpu *v)
void __cpuinit init_maintenance_interrupt(void)
{
- request_irq(gic.maintenance_irq, maintenance_interrupt,
+ request_irq(gic.maintenance_irq, 0, maintenance_interrupt,
"irq-maintenance", NULL);
}
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 24eca0a..1b62d83 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -133,7 +133,7 @@ static inline struct domain *irq_get_domain(struct irq_desc *desc)
return desc->action->dev_id;
}
-int request_irq(unsigned int irq,
+int request_irq(unsigned int irq, unsigned int irqflags,
void (*handler)(int, void *, struct cpu_user_regs *),
const char *devname, void *dev_id)
{
@@ -160,7 +160,7 @@ int request_irq(unsigned int irq,
action->dev_id = dev_id;
action->free_on_release = 1;
- retval = setup_irq(irq, action);
+ retval = setup_irq(irq, irqflags, action);
if ( retval )
xfree(action);
@@ -268,7 +268,7 @@ static int __setup_irq(struct irq_desc *desc, struct irqaction *new)
return 0;
}
-int setup_irq(unsigned int irq, struct irqaction *new)
+int setup_irq(unsigned int irq, unsigned int irqflags, struct irqaction *new)
{
int rc;
unsigned long flags;
diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index 7eb480e..0395b7b 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -236,11 +236,11 @@ void __cpuinit init_timer_interrupt(void)
WRITE_SYSREG32(0, CNTHP_CTL_EL2); /* Hypervisor's timer disabled */
isb();
- request_irq(timer_irq[TIMER_HYP_PPI], timer_interrupt,
+ request_irq(timer_irq[TIMER_HYP_PPI], 0, timer_interrupt,
"hyptimer", NULL);
- request_irq(timer_irq[TIMER_VIRT_PPI], vtimer_interrupt,
+ request_irq(timer_irq[TIMER_VIRT_PPI], 0, vtimer_interrupt,
"virtimer", NULL);
- request_irq(timer_irq[TIMER_PHYS_NONSECURE_PPI], timer_interrupt,
+ request_irq(timer_irq[TIMER_PHYS_NONSECURE_PPI], 0, timer_interrupt,
"phytimer", NULL);
}
diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c
index 3a4f7e8..0b13f52 100644
--- a/xen/arch/x86/hpet.c
+++ b/xen/arch/x86/hpet.c
@@ -355,7 +355,7 @@ static int __init hpet_setup_msi_irq(struct hpet_event_channel *ch)
hpet_write32(cfg, HPET_Tn_CFG(ch->idx));
desc->handler = &hpet_msi_type;
- ret = request_irq(ch->msi.irq, hpet_interrupt_handler, "HPET", ch);
+ ret = request_irq(ch->msi.irq, 0, hpet_interrupt_handler, "HPET", ch);
if ( ret >= 0 )
ret = __hpet_setup_msi_irq(desc);
if ( ret < 0 )
diff --git a/xen/arch/x86/i8259.c b/xen/arch/x86/i8259.c
index 9fec490..a71f734 100644
--- a/xen/arch/x86/i8259.c
+++ b/xen/arch/x86/i8259.c
@@ -433,6 +433,6 @@ void __init init_IRQ(void)
outb_p(LATCH & 0xff, PIT_CH0); /* LSB */
outb(LATCH >> 8, PIT_CH0); /* MSB */
- setup_irq(2, &cascade);
+ setup_irq(2, 0, &cascade);
}
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 727472d..dafd338 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -949,7 +949,7 @@ static int __init irq_ratelimit_init(void)
}
__initcall(irq_ratelimit_init);
-int __init request_irq(unsigned int irq,
+int __init request_irq(unsigned int irq, unsigned int irqflags,
void (*handler)(int, void *, struct cpu_user_regs *),
const char * devname, void *dev_id)
{
@@ -976,7 +976,7 @@ int __init request_irq(unsigned int irq,
action->dev_id = dev_id;
action->free_on_release = 1;
- retval = setup_irq(irq, action);
+ retval = setup_irq(irq, irqflags, action);
if (retval)
xfree(action);
@@ -1005,11 +1005,14 @@ void __init release_irq(unsigned int irq, const void *dev_id)
xfree(action);
}
-int __init setup_irq(unsigned int irq, struct irqaction *new)
+int __init setup_irq(unsigned int irq, unsigned int irqflags,
+ struct irqaction *new)
{
struct irq_desc *desc;
unsigned long flags;
+ ASSERT(irqflags == 0);
+
desc = irq_to_desc(irq);
spin_lock_irqsave(&desc->lock,flags);
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index b2dbde7..a4e1656 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -1473,7 +1473,7 @@ void __init early_time_init(void)
printk("Detected %lu.%03lu MHz processor.\n",
cpu_khz / 1000, cpu_khz % 1000);
- setup_irq(0, &irq0);
+ setup_irq(0, 0, &irq0);
}
/* keep pit enabled for pit_broadcast working while cpuidle enabled */
diff --git a/xen/drivers/char/exynos4210-uart.c b/xen/drivers/char/exynos4210-uart.c
index 404ce05..cba8729 100644
--- a/xen/drivers/char/exynos4210-uart.c
+++ b/xen/drivers/char/exynos4210-uart.c
@@ -197,7 +197,7 @@ static void __init exynos4210_uart_init_postirq(struct serial_port *port)
uart->irqaction.name = "exynos4210_uart";
uart->irqaction.dev_id = port;
- if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
+ if ( (rc = setup_irq(uart->irq, 0, &uart->irqaction)) != 0 )
dprintk(XENLOG_ERR, "Failed to allocated exynos4210_uart IRQ %d\n",
uart->irq);
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c
index 6691806..161b251 100644
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -609,7 +609,7 @@ static void __init ns16550_init_postirq(struct serial_port *port)
uart->irqaction.handler = ns16550_interrupt;
uart->irqaction.name = "ns16550";
uart->irqaction.dev_id = port;
- if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
+ if ( (rc = setup_irq(uart->irq, 0, &uart->irqaction)) != 0 )
printk("ERROR: Failed to allocate ns16550 IRQ %d\n", uart->irq);
}
diff --git a/xen/drivers/char/omap-uart.c b/xen/drivers/char/omap-uart.c
index e598785..a798b8d 100644
--- a/xen/drivers/char/omap-uart.c
+++ b/xen/drivers/char/omap-uart.c
@@ -205,7 +205,7 @@ static void __init omap_uart_init_postirq(struct serial_port *port)
uart->irqaction.name = "omap_uart";
uart->irqaction.dev_id = port;
- if ( setup_irq(uart->irq, &uart->irqaction) != 0 )
+ if ( setup_irq(uart->irq, 0, &uart->irqaction) != 0 )
{
dprintk(XENLOG_ERR, "Failed to allocated omap_uart IRQ %d\n",
uart->irq);
diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index 89bda94..dd19ce8 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -137,7 +137,7 @@ static void __init pl011_init_postirq(struct serial_port *port)
uart->irqaction.handler = pl011_interrupt;
uart->irqaction.name = "pl011";
uart->irqaction.dev_id = port;
- if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
+ if ( (rc = setup_irq(uart->irq, 0, &uart->irqaction)) != 0 )
printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq);
}
diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c
index ee8851a..b2f74ef 100644
--- a/xen/drivers/passthrough/amd/iommu_init.c
+++ b/xen/drivers/passthrough/amd/iommu_init.c
@@ -815,7 +815,7 @@ static bool_t __init set_iommu_interrupt_handler(struct amd_iommu *iommu)
handler = &iommu_msi_type;
ret = __setup_msi_irq(irq_to_desc(irq), &iommu->msi, handler);
if ( !ret )
- ret = request_irq(irq, iommu_interrupt_handler, "amd_iommu", iommu);
+ ret = request_irq(irq, 0, iommu_interrupt_handler, "amd_iommu", iommu);
if ( ret )
{
destroy_irq(irq);
diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c
index 9a9c1b4..f1ab517 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -1082,7 +1082,7 @@ static int __init iommu_set_interrupt(struct acpi_drhd_unit *drhd)
desc = irq_to_desc(irq);
desc->handler = &dma_msi_type;
- ret = request_irq(irq, iommu_page_fault, "dmar", iommu);
+ ret = request_irq(irq, 0, iommu_page_fault, "dmar", iommu);
if ( ret )
{
desc->handler = &no_irq_type;
diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h
index 1f8bdb3..f9a18d8 100644
--- a/xen/include/xen/irq.h
+++ b/xen/include/xen/irq.h
@@ -89,9 +89,10 @@ int arch_init_one_irq_desc(struct irq_desc *);
#define irq_desc_initialized(desc) ((desc)->handler != NULL)
-extern int setup_irq(unsigned int irq, struct irqaction *);
+extern int setup_irq(unsigned int irq, unsigned int irqflags,
+ struct irqaction *);
extern void release_irq(unsigned int irq, const void *dev_id);
-extern int request_irq(unsigned int irq,
+extern int request_irq(unsigned int irq, unsigned int irqflags,
void (*handler)(int, void *, struct cpu_user_regs *),
const char * devname, void *dev_id);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v7 6/6] xen/arm: IRQ: Handle multiple action per IRQ
2014-05-16 14:40 [PATCH v7 0/6] xen/arm: Interrupt management reworking Julien Grall
` (4 preceding siblings ...)
2014-05-16 14:40 ` [PATCH v7 5/6] xen/arm: IRQ: extend {request, setup}_irq to take an irqflags in parameter Julien Grall
@ 2014-05-16 14:40 ` Julien Grall
5 siblings, 0 replies; 8+ messages in thread
From: Julien Grall @ 2014-05-16 14:40 UTC (permalink / raw)
To: xen-devel
Cc: stefano.stabellini, Julien Grall, tim, ian.campbell, Jan Beulich
On ARM, it may happen (eg ARM SMMU) to setup multiple handler for the same
interrupt.
To be able to use multiple action, the driver has to explicitly call
{setup,request}_irq with IRQF_SHARED as 2nd parameter.
The behavior stays the same on x86, e.g only one action is handled.
Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
Changes in v4:
- Go back to a single custom linked list. The double linked-list
doesn't fit the requirements (i.e browsing safely without look) and
the llist.h from Linux doesn't allow use to delete a node in the middle
of the list.
Changes in v3:
- Drop {setup,request}_irq_flags, the current function has been
extended on an earlier patch.
- Rename IRQ_SHARED into IRQF_SHARED
Changes in v2:
- Explain design choice
- Introduce CONFIG_IRQ_HAS_MULTIPLE_ACTION
- Use list instead of custom pointer
- release_irq should not shutdown the IRQ at the beginning
- Add IRQ_SHARED flags
- Introduce request_irq_flags and setup_irq_flags
- Fix compilation on x86. Some code are creating the irqaction
via = { ... } so the "next" field should be moved
toward the end
---
xen/arch/arm/irq.c | 79 +++++++++++++++++++++++++++++++++---------
xen/include/asm-arm/config.h | 2 ++
xen/include/xen/irq.h | 4 +++
3 files changed, 68 insertions(+), 17 deletions(-)
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 1b62d83..3a9a688 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -171,7 +171,6 @@ int request_irq(unsigned int irq, unsigned int irqflags,
void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq)
{
struct irq_desc *desc = irq_to_desc(irq);
- struct irqaction *action = desc->action;
/* TODO: perfc_incr(irqs); */
@@ -182,7 +181,7 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq)
spin_lock(&desc->lock);
desc->handler->ack(desc);
- if ( action == NULL )
+ if ( !desc->action )
{
printk("Unknown %s %#3.3x\n",
is_fiq ? "FIQ" : "IRQ", irq);
@@ -214,12 +213,21 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq)
desc->status |= IRQ_INPROGRESS;
- action = desc->action;
while ( desc->status & IRQ_PENDING )
{
+ struct irqaction *action;
+
desc->status &= ~IRQ_PENDING;
+ action = desc->action;
+
spin_unlock_irq(&desc->lock);
- action->handler(irq, action->dev_id, regs);
+
+ do
+ {
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ } while ( action );
+
spin_lock_irq(&desc->lock);
}
@@ -236,34 +244,71 @@ void release_irq(unsigned int irq, const void *dev_id)
{
struct irq_desc *desc;
unsigned long flags;
- struct irqaction *action;
+ struct irqaction *action, **action_ptr;
desc = irq_to_desc(irq);
spin_lock_irqsave(&desc->lock,flags);
- desc->handler->shutdown(desc);
+ action_ptr = &desc->action;
+ for ( ;; )
+ {
+ action = *action_ptr;
+ if ( !action )
+ {
+ printk(XENLOG_WARNING "Trying to free already-free IRQ %u\n", irq);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ return;
+ }
+
+ if ( action->dev_id == dev_id )
+ break;
+
+ action_ptr = &action->next;
+ }
+
+ /* Found it - remove it from the action list */
+ *action_ptr = action->next;
- action = desc->action;
- desc->action = NULL;
- desc->status &= ~IRQ_GUEST;
+ /* If this was the last action, shut down the IRQ */
+ if ( !desc->action )
+ {
+ desc->handler->shutdown(desc);
+ desc->status &= ~IRQ_GUEST;
+ }
spin_unlock_irqrestore(&desc->lock,flags);
/* Wait to make sure it's not being used on another CPU */
do { smp_mb(); } while ( desc->status & IRQ_INPROGRESS );
- if ( action && action->free_on_release )
+ if ( action->free_on_release )
xfree(action);
}
-static int __setup_irq(struct irq_desc *desc, struct irqaction *new)
+static int __setup_irq(struct irq_desc *desc, unsigned int irqflags,
+ struct irqaction *new)
{
- if ( desc->action != NULL )
- return -EBUSY;
+ bool_t shared = !!(irqflags & IRQF_SHARED);
+
+ ASSERT(new != NULL);
+
+ /* Sanity checks:
+ * - if the IRQ is marked as shared
+ * - dev_id is not NULL when IRQF_SHARED is set
+ */
+ if ( desc->action != NULL && (!(desc->status & IRQF_SHARED) || !shared) )
+ return -EINVAL;
+ if ( shared && new->dev_id == NULL )
+ return -EINVAL;
+
+ if ( shared )
+ desc->status |= IRQF_SHARED;
- desc->action = new;
- dsb(sy);
+ new->next = desc->action;
+ dsb(ish);
+ desc->action = new;
+ dsb(ish);
return 0;
}
@@ -291,7 +336,7 @@ int setup_irq(unsigned int irq, unsigned int irqflags, struct irqaction *new)
disabled = (desc->action == NULL);
- rc = __setup_irq(desc, new);
+ rc = __setup_irq(desc, irqflags, new);
if ( rc )
goto err;
@@ -355,7 +400,7 @@ int route_irq_to_guest(struct domain *d, unsigned int irq,
goto out;
}
- retval = __setup_irq(desc, action);
+ retval = __setup_irq(desc, 0, action);
if ( retval )
goto out;
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index ef291ff..1c3abcf 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -37,6 +37,8 @@
#define CONFIG_VIDEO 1
+#define CONFIG_IRQ_HAS_MULTIPLE_ACTION 1
+
#define OPT_CONSOLE_STR "dtuart"
#ifdef MAX_PHYS_CPUS
diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h
index f9a18d8..40c0f3f 100644
--- a/xen/include/xen/irq.h
+++ b/xen/include/xen/irq.h
@@ -14,6 +14,9 @@ struct irqaction {
const char *name;
void *dev_id;
bool_t free_on_release;
+#ifdef CONFIG_IRQ_HAS_MULTIPLE_ACTION
+ struct irqaction *next;
+#endif
};
/*
@@ -27,6 +30,7 @@ struct irqaction {
#define IRQ_MOVE_PENDING (1u<<5) /* IRQ is migrating to another CPUs */
#define IRQ_PER_CPU (1u<<6) /* IRQ is per CPU */
#define IRQ_GUEST_EOI_PENDING (1u<<7) /* IRQ was disabled, pending a guest EOI */
+#define IRQF_SHARED (1<<8) /* IRQ is shared */
/* Special IRQ numbers. */
#define AUTO_ASSIGN_IRQ (-1)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v7 1/6] xen/arm: IRQ: Store IRQ type in arch_irq_desc
2014-05-16 14:40 ` [PATCH v7 1/6] xen/arm: IRQ: Store IRQ type in arch_irq_desc Julien Grall
@ 2014-05-21 12:27 ` Ian Campbell
0 siblings, 0 replies; 8+ messages in thread
From: Ian Campbell @ 2014-05-21 12:27 UTC (permalink / raw)
To: Julien Grall; +Cc: xen-devel, tim, stefano.stabellini
On Fri, 2014-05-16 at 15:40 +0100, Julien Grall wrote:
> For now, ARM uses different IRQ functions to setup an interrupt handler. This
> is a bit annoying for common driver because we have to add idefery when
> an IRQ is setup (see ns16550_init_postirq for an example).
>
> To avoid to completely fork the IRQ management code, we can introduce a field
> to store the IRQ type (e.g level/edge ...).
>
> This patch also adds platform_get_irq which will retrieve the IRQ from the
> device tree and setup correctly the IRQ type.
>
> In order to use this solution, we have to move init_IRQ earlier for the boot
> CPU. It's fine because the code only depends on percpu.
>
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
and with that I have shovelled the whole lot in. Thanks!
Ian.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2014-05-21 12:27 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-16 14:40 [PATCH v7 0/6] xen/arm: Interrupt management reworking Julien Grall
2014-05-16 14:40 ` [PATCH v7 1/6] xen/arm: IRQ: Store IRQ type in arch_irq_desc Julien Grall
2014-05-21 12:27 ` Ian Campbell
2014-05-16 14:40 ` [PATCH v7 2/6] xen/arm: IRQ: Replace {request, setup}_dt_irq by {request, setup}_irq Julien Grall
2014-05-16 14:40 ` [PATCH v7 3/6] xen/arm: Replace route_guest_dt_irq by route_guest_irq Julien Grall
2014-05-16 14:40 ` [PATCH v7 4/6] xen: IRQ: Add dev_id parameter to release_irq Julien Grall
2014-05-16 14:40 ` [PATCH v7 5/6] xen/arm: IRQ: extend {request, setup}_irq to take an irqflags in parameter Julien Grall
2014-05-16 14:40 ` [PATCH v7 6/6] xen/arm: IRQ: Handle multiple action per IRQ Julien Grall
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).