From: Julien Grall <julien.grall@linaro.org>
To: xen-devel@lists.xenproject.org
Cc: stefano.stabellini@citrix.com,
Julien Grall <julien.grall@linaro.org>,
tim@xen.org, ian.campbell@citrix.com
Subject: [PATCH v4 14/18] xen/arm: IRQ: Store IRQ type in arch_irq_desc
Date: Tue, 22 Apr 2014 13:58:46 +0100 [thread overview]
Message-ID: <1398171530-27391-15-git-send-email-julien.grall@linaro.org> (raw)
In-Reply-To: <1398171530-27391-1-git-send-email-julien.grall@linaro.org>
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 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 | 23 ++++++------
xen/arch/arm/irq.c | 85 +++++++++++++++++++++++++++++++++++++++++----
xen/arch/arm/setup.c | 3 +-
xen/include/asm-arm/gic.h | 5 ++-
xen/include/asm-arm/irq.h | 3 ++
5 files changed, 98 insertions(+), 21 deletions(-)
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 577d85b..4a6ed35 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -216,14 +216,19 @@ 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
*/
-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(spin_is_locked(&desc->lock));
spin_lock(&gic.lock);
@@ -232,9 +237,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 +257,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 +267,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 +282,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..f1d6398 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -55,6 +55,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_NONE;
return 0;
}
@@ -82,6 +83,12 @@ static int __cpuinit init_local_irq_data(void)
init_one_irq_desc(desc);
desc->irq = irq;
desc->action = NULL;
+
+ /* PPIs are include in local_irqs, we have to copy the IRQ type from
+ * CPU0 otherwise we may miss the type if the IRQ type has been
+ * set early.
+ */
+ desc->arch.type = per_cpu(local_irq_desc, 0)[irq].arch.type;
}
return 0;
@@ -275,9 +282,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 +289,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 +308,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 +345,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 +387,73 @@ void pirq_set_affinity(struct domain *d, int pirq, const cpumask_t *mask)
BUG();
}
+static inline int irq_set_type(struct irq_desc *desc, unsigned int type)
+{
+ unsigned long flags;
+ int ret = -EBUSY;
+
+ if ( type == DT_IRQ_TYPE_NONE )
+ return 0;
+
+ spin_lock_irqsave(&desc->lock, flags);
+
+ if ( desc->arch.type != DT_IRQ_TYPE_NONE && desc->arch.type != type )
+ goto err;
+
+ desc->arch.type = type;
+
+ ret = 0;
+
+err:
+ spin_unlock_irqrestore(&desc->lock, flags);
+ return ret;
+}
+
+int platform_get_irq(const struct dt_device_node *device,
+ int index)
+{
+ struct dt_irq dt_irq;
+ struct irq_desc *desc;
+ unsigned int type, irq;
+ int res;
+
+ res = dt_device_get_irq(device, index, &dt_irq);
+ if ( res )
+ return 0;
+
+ irq = dt_irq.irq;
+ type = dt_irq.type;
+
+ /* Setup the IRQ type */
+ if ( irq < NR_LOCAL_IRQS )
+ {
+ unsigned int cpu;
+ /* For PPIs, we need to set IRQ type on every online CPUs */
+ for_each_cpu( cpu, &cpu_online_map )
+ {
+ desc = &per_cpu(local_irq_desc, cpu)[irq];
+ res = irq_set_type(desc, type);
+ if ( res )
+ {
+ /*
+ * For PPIs the IRQ type is the same on every CPU. It
+ * should not fail to other CPU than CPU0
+ */
+ ASSERT(cpu == 0);
+ return -1;
+ }
+ }
+ }
+ else
+ {
+ res = irq_set_type(irq_to_desc(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 dec5950..40ba26e 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..93d2128 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
@@ -46,6 +47,8 @@ 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);
+int platform_get_irq(const struct dt_device_node *device,
+ int index);
#endif /* _ASM_HW_IRQ_H */
/*
--
1.7.10.4
next prev parent reply other threads:[~2014-04-22 12:59 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-22 12:58 [PATCH v4 00/18] xen/arm: Interrupt management reworking Julien Grall
2014-04-22 12:58 ` [PATCH v4 01/18] xen/arm: timer: replace timer_dt_irq by timer_get_irq Julien Grall
2014-04-22 12:58 ` [PATCH v4 02/18] xen/arm: IRQ: Use default irq callback from common code for no_irq_type Julien Grall
2014-04-22 12:58 ` [PATCH v4 03/18] xen/arm: IRQ: Rename irq_cfg into arch_irq_desc Julien Grall
2014-04-22 12:58 ` [PATCH v4 04/18] xen/arm: IRQ: move gic {, un}lock in gic_set_irq_properties Julien Grall
2014-04-22 12:58 ` [PATCH v4 05/18] xen/arm: IRQ: drop irq parameter in __setup_irq Julien Grall
2014-04-22 12:58 ` [PATCH v4 06/18] xen/arm: IRQ: remove __init from setup_dt_irq, request_dt_irq and release_irq Julien Grall
2014-04-22 12:58 ` [PATCH v4 07/18] xen/arm: IRQ: Rework gic_route_irq_to_guest function Julien Grall
2014-04-22 12:58 ` [PATCH v4 08/18] xen/arm: IRQ: Move IRQ management from gic.c to irq.c Julien Grall
2014-04-22 12:58 ` [PATCH v4 09/18] xen/arm: IRQ Introduce irq_get_domain Julien Grall
2014-04-22 12:58 ` [PATCH v4 10/18] xen/arm: IRQ: Require desc.lock be held by callers of hw_irq_controller callbacks Julien Grall
2014-04-22 12:58 ` [PATCH v4 11/18] xen/arm: IRQ: Defer routing IRQ to Xen until setup_irq() call Julien Grall
2014-04-22 12:58 ` [PATCH v4 12/18] xen/arm: IRQ: Do not allow IRQ to be shared between domains and XEN Julien Grall
2014-04-22 12:58 ` [PATCH v4 13/18] xen/serial: remove serial_dt_irq Julien Grall
2014-04-22 12:58 ` Julien Grall [this message]
2014-04-23 12:26 ` [PATCH v4 14/18] xen/arm: IRQ: Store IRQ type in arch_irq_desc Julien Grall
2014-04-23 14:04 ` Ian Campbell
2014-05-02 8:49 ` Julien Grall
2014-05-02 8:57 ` Ian Campbell
2014-05-02 9:00 ` Julien Grall
2014-04-22 12:58 ` [PATCH v4 15/18] xen/arm: IRQ: Replace {request, setup}_dt_irq by {request, setup}_irq Julien Grall
2014-04-22 13:26 ` Julien Grall
2014-04-22 12:58 ` [PATCH v4 16/18] xen: IRQ: Add dev_id parameter to release_irq Julien Grall
2014-04-22 12:58 ` [PATCH v4 17/18] xen/arm: IRQ: extend {request, setup}_irq to take an irqflags in parameter Julien Grall
2014-04-22 12:58 ` [PATCH v4 18/18] xen/arm: IRQ: Handle multiple action per IRQ Julien Grall
2014-04-22 13:36 ` Jan Beulich
2014-04-23 14:07 ` Ian Campbell
2014-04-23 14:56 ` Julien Grall
2014-04-23 15:16 ` Ian Campbell
2014-04-23 15:28 ` Julien Grall
2014-04-23 15:28 ` Julien Grall
2014-05-02 8:52 ` [PATCH v4 00/18] xen/arm: Interrupt management reworking Julien Grall
2014-05-02 12:51 ` Ian Campbell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1398171530-27391-15-git-send-email-julien.grall@linaro.org \
--to=julien.grall@linaro.org \
--cc=ian.campbell@citrix.com \
--cc=stefano.stabellini@citrix.com \
--cc=tim@xen.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).