Commit 20443598 authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by Thomas Gleixner

x86: devicetree: Configure IOAPIC pin only once

We use io_apic_setup_irq_pin() in order to configure pin's interrupt
number polarity and type. This is done on every irq_create_of_mapping()
which happens for instance during pci enable calls. Level typed
interrupts are masked by default, edge are unmasked.

On the first ->xlate() call the level interrupt is configured and
masked. The driver calls request_irq() and the line is unmasked. Lets
assume the interrupt line is shared with another device and we call
pci_enable_device() for this device. The ->xlate() configures the pin
again and it is masked. request_irq() does not unmask the line because
it _is_ already unmasked according to its internal state. So the
interrupt will never be unmasked again.

This patch is based on an earlier work by Torben Hohn and solves the
problem by configuring the pin only once. Since all devices must agree
on the same type and polarity there is no point in configuring the pin
more than once.

[ tglx: Split out the ce4100 part into a separate patch ]

Cc: Torben Hohn <torbenh@linutronix.de>
Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: http://lkml.kernel.org/r/%3C20110427143052.GA15211%40linutronix.de%3ESigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 39b68976
...@@ -150,7 +150,7 @@ void setup_IO_APIC_irq_extra(u32 gsi); ...@@ -150,7 +150,7 @@ void setup_IO_APIC_irq_extra(u32 gsi);
extern void ioapic_and_gsi_init(void); extern void ioapic_and_gsi_init(void);
extern void ioapic_insert_resources(void); extern void ioapic_insert_resources(void);
int io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr); int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
extern struct IO_APIC_route_entry **alloc_ioapic_entries(void); extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries); extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
......
...@@ -128,8 +128,8 @@ static int __init parse_noapic(char *str) ...@@ -128,8 +128,8 @@ static int __init parse_noapic(char *str)
} }
early_param("noapic", parse_noapic); early_param("noapic", parse_noapic);
static int io_apic_setup_irq_pin_once(unsigned int irq, int node, static int io_apic_setup_irq_pin(unsigned int irq, int node,
struct io_apic_irq_attr *attr); struct io_apic_irq_attr *attr);
/* Will be called in mpparse/acpi/sfi codes for saving IRQ info */ /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
void mp_save_irq(struct mpc_intsrc *m) void mp_save_irq(struct mpc_intsrc *m)
...@@ -3570,7 +3570,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) ...@@ -3570,7 +3570,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
} }
#endif /* CONFIG_HT_IRQ */ #endif /* CONFIG_HT_IRQ */
int static int
io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
{ {
struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node); struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node);
...@@ -3585,8 +3585,8 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) ...@@ -3585,8 +3585,8 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
return ret; return ret;
} }
static int io_apic_setup_irq_pin_once(unsigned int irq, int node, int io_apic_setup_irq_pin_once(unsigned int irq, int node,
struct io_apic_irq_attr *attr) struct io_apic_irq_attr *attr)
{ {
unsigned int id = attr->ioapic, pin = attr->ioapic_pin; unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
int ret; int ret;
......
...@@ -391,7 +391,7 @@ static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize, ...@@ -391,7 +391,7 @@ static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity); set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr); return io_apic_setup_irq_pin_once(*out_hwirq, cpu_to_node(0), &attr);
} }
static void __init ioapic_add_ofnode(struct device_node *np) static void __init ioapic_add_ofnode(struct device_node *np)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment