@@ -1088,7 +1088,7 @@ int arch_early_irq_init(void)
return 0;
}
-int arch_init_chip_data(struct irq_desc *desc, int node)
+int arch_init_irq_desc(struct irq_desc *desc, int node, init_chip_data_fn fn)
{
desc->status |= IRQ_NOREQUEST;
return 0;
@@ -20,9 +20,9 @@
#include <linux/percpu.h>
#include <linux/profile.h>
#include <linux/smp.h>
+#include <linux/irq.h>
#include <asm/atomic.h>
-#include <asm/irq.h>
#include <asm/sections.h>
/* Interrupt handlers registered during init_IRQ */
@@ -61,6 +61,11 @@ extern void init_VISWS_APIC_irqs(void);
extern void setup_IO_APIC(void);
extern void disable_IO_APIC(void);
+extern void x86_copy_chip_data(struct irq_desc *old_desc,
+ struct irq_desc *desc, int node);
+extern void x86_free_chip_data(struct irq_desc *old_desc,
+ struct irq_desc *desc);
+
struct io_apic_irq_attr {
int ioapic;
int ioapic_pin;
@@ -211,7 +211,7 @@ static struct irq_cfg *get_one_free_irq_cfg(int node)
return cfg;
}
-int arch_init_chip_data(struct irq_desc *desc, int node)
+static int x86_init_chip_data(struct irq_desc *desc, int node)
{
struct irq_cfg *cfg;
@@ -287,8 +287,8 @@ static void free_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg)
old_cfg->irq_2_pin = NULL;
}
-void arch_init_copy_chip_data(struct irq_desc *old_desc,
- struct irq_desc *desc, int node)
+void x86_copy_chip_data(struct irq_desc *old_desc,
+ struct irq_desc *desc, int node)
{
struct irq_cfg *cfg;
struct irq_cfg *old_cfg;
@@ -312,7 +312,7 @@ static void free_irq_cfg(struct irq_cfg *old_cfg)
kfree(old_cfg);
}
-void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
+void x86_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
{
struct irq_cfg *old_cfg, *cfg;
@@ -329,6 +329,14 @@ void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
}
}
/* end for move_irq_desc */
+int arch_init_irq_desc(struct irq_desc *desc, int node,
+ init_chip_data_fn init_chip_data)
+{
+ if (!init_chip_data)
+ return x86_init_chip_data(desc, node);
+
+ return init_chip_data(desc, node);
+}
#else
struct irq_cfg *irq_cfg(unsigned int irq)
@@ -336,6 +344,15 @@ struct irq_cfg *irq_cfg(unsigned int irq)
return irq < nr_irqs ? irq_cfgx + irq : NULL;
}
+void x86_copy_chip_data(struct irq_desc *old_desc,
+ struct irq_desc *desc, int node)
+{
+}
+
+void x86_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
+{
+}
+
#endif
struct io_apic {
@@ -2747,6 +2764,9 @@ static struct irq_chip ioapic_chip __read_mostly = {
.set_affinity = set_ioapic_affinity_irq,
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
static struct irq_chip ir_ioapic_chip __read_mostly = {
@@ -2762,6 +2782,9 @@ static struct irq_chip ir_ioapic_chip __read_mostly = {
#endif
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
static inline void init_IO_APIC_traps(void)
@@ -3474,6 +3497,9 @@ static struct irq_chip msi_chip = {
.set_affinity = set_msi_irq_affinity,
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
static struct irq_chip msi_ir_chip = {
@@ -3487,6 +3513,9 @@ static struct irq_chip msi_ir_chip = {
#endif
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
/*
@@ -3646,6 +3675,9 @@ static struct irq_chip dmar_msi_type = {
.set_affinity = dmar_msi_set_affinity,
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
int arch_setup_dmar_msi(unsigned int irq)
@@ -3703,6 +3735,9 @@ static struct irq_chip ir_hpet_msi_type = {
#endif
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
static struct irq_chip hpet_msi_type = {
@@ -3714,6 +3749,9 @@ static struct irq_chip hpet_msi_type = {
.set_affinity = hpet_msi_set_affinity,
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
@@ -3800,6 +3838,9 @@ static struct irq_chip ht_irq_chip = {
.set_affinity = set_ht_irq_affinity,
#endif
.retrigger = ioapic_retrigger_irq,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
@@ -55,6 +55,9 @@ struct irq_chip uv_irq_chip = {
.eoi = uv_ack_apic,
.end = uv_noop,
.set_affinity = uv_set_irq_affinity,
+
+ .copy_chip_data = x86_copy_chip_data,
+ .free_chip_data = x86_free_chip_data,
};
/*
@@ -329,6 +329,11 @@ static void unmask_evtchn(int port)
put_cpu();
}
+static int xen_init_chip_data(struct irq_desc *desc, int node)
+{
+ return 0;
+}
+
static int find_unbound_irq(void)
{
int irq;
@@ -341,7 +346,7 @@ static int find_unbound_irq(void)
if (irq == nr_irqs)
panic("No available IRQ to bind to: increase nr_irqs!\n");
- desc = irq_to_desc_alloc_node(irq, 0);
+ desc = irq_to_desc_alloc_node_x(irq, 0, xen_init_chip_data);
if (WARN_ON(desc == NULL))
return -1;
@@ -611,6 +611,5 @@ struct irq_desc;
extern int early_irq_init(void);
extern int arch_probe_nr_irqs(void);
extern int arch_early_irq_init(void);
-extern int arch_init_chip_data(struct irq_desc *desc, int node);
#endif
@@ -140,6 +140,13 @@ struct irq_chip {
* Will disappear.
*/
const char *typename;
+
+ /* for move_irq_desc */
+ void (*copy_chip_data)(struct irq_desc *old_desc,
+ struct irq_desc *desc, int node);
+ void (*free_chip_data)(struct irq_desc *old_desc,
+ struct irq_desc *desc);
+
};
struct timer_rand_state;
@@ -208,10 +215,6 @@ struct irq_desc {
const char *name;
} ____cacheline_internodealigned_in_smp;
-extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
- struct irq_desc *desc, int node);
-extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
-
#ifndef CONFIG_SPARSE_IRQ
extern struct irq_desc irq_desc[NR_IRQS];
#endif
@@ -225,7 +228,15 @@ static inline struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
}
#endif
-extern struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node);
+typedef int (*init_chip_data_fn)(struct irq_desc *, int node);
+int arch_init_irq_desc(struct irq_desc *desc, int node, init_chip_data_fn fn);
+struct irq_desc *irq_to_desc_alloc_node_x(unsigned int irq, int node,
+ init_chip_data_fn fn);
+static inline struct irq_desc *irq_to_desc_alloc_node(unsigned int irq,
+ int node)
+{
+ return irq_to_desc_alloc_node_x(irq, node, NULL);
+}
/*
* Pick up the arch-dependent methods:
@@ -758,3 +758,10 @@ void __init set_irq_probe(unsigned int irq)
desc->status &= ~IRQ_NOPROBE;
raw_spin_unlock_irqrestore(&desc->lock, flags);
}
+
+int __weak arch_init_irq_desc(struct irq_desc *desc, int node,
+ init_chip_data_fn init_chip_data)
+{
+ return 0;
+}
+
@@ -100,7 +100,8 @@ void __ref init_kstat_irqs(struct irq_desc *desc, int node, int nr)
}
}
-static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)
+static void init_one_irq_desc(int irq, struct irq_desc *desc, int node,
+ init_chip_data_fn init_chip_data)
{
memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
@@ -120,7 +121,7 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)
BUG_ON(1);
}
init_desc_masks(desc);
- arch_init_chip_data(desc, node);
+ arch_init_irq_desc(desc, node, init_chip_data);
}
/*
@@ -198,7 +199,8 @@ int __init early_irq_init(void)
return arch_early_irq_init();
}
-struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
+struct irq_desc * __ref irq_to_desc_alloc_node_x(unsigned int irq, int node,
+ init_chip_data_fn init_chip_data)
{
struct irq_desc *desc;
unsigned long flags;
@@ -227,7 +229,7 @@ struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
printk(KERN_ERR "can not alloc irq_desc\n");
BUG_ON(1);
}
- init_one_irq_desc(irq, desc, node);
+ init_one_irq_desc(irq, desc, node, init_chip_data);
set_irq_desc(irq, desc);
@@ -277,7 +279,8 @@ struct irq_desc *irq_to_desc(unsigned int irq)
return (irq < NR_IRQS) ? irq_desc + irq : NULL;
}
-struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
+struct irq_desc *irq_to_desc_alloc_node_x(unsigned int irq, int node,
+ init_chip_data_fn init_chip_data)
{
return irq_to_desc(irq);
}
@@ -47,7 +47,8 @@ static bool init_copy_one_irq_desc(int irq, struct irq_desc *old_desc,
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
init_copy_kstat_irqs(old_desc, desc, node, nr_cpu_ids);
init_copy_desc_masks(old_desc, desc);
- arch_init_copy_chip_data(old_desc, desc, node);
+ if (desc->chip->copy_chip_data)
+ desc->chip->copy_chip_data(old_desc, desc, node);
return true;
}
@@ -55,7 +56,8 @@ static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc)
{
free_kstat_irqs(old_desc, desc);
free_desc_masks(old_desc, desc);
- arch_free_chip_data(old_desc, desc);
+ if (desc->chip->free_chip_data)
+ desc->chip->free_chip_data(old_desc, desc);
}
static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
@@ -107,9 +109,15 @@ out_unlock:
struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
{
+
/* those static or target node is -1, do not move them */
if (desc->irq < NR_IRQS_LEGACY || node == -1)
return desc;
+ /* IRQ chip does not support movement */
+ if (desc->chip_data &&
+ (desc->chip->copy_chip_data == NULL ||
+ desc->chip->free_chip_data == NULL))
+ return desc;
if (desc->node != node)
desc = __real_move_irq_desc(desc, node);
@@ -895,8 +895,3 @@ int __init __weak arch_early_irq_init(void)
{
return 0;
}
-
-int __weak arch_init_chip_data(struct irq_desc *desc, int node)
-{
- return 0;
-}