memcpy(cfg, &irq_cfg_init, sizeof(struct irq_cfg));
}
+static struct irq_cfg *irq_cfgx;
+static struct irq_cfg *irq_cfgx_free;
static void __init init_work(void *data)
{
struct dyn_array *da = data;
struct irq_cfg *cfg;
+ int legacy_count;
int i;
cfg = *da->name;
memcpy(cfg, irq_cfg_legacy, sizeof(irq_cfg_legacy));
- i = sizeof(irq_cfg_legacy)/sizeof(irq_cfg_legacy[0]);
- for (; i < *da->nr; i++)
+ legacy_count = sizeof(irq_cfg_legacy)/sizeof(irq_cfg_legacy[0]);
+ for (i = legacy_count; i < *da->nr; i++)
init_one_irq_cfg(&cfg[i]);
for (i = 1; i < *da->nr; i++)
cfg[i-1].next = &cfg[i];
+
+ irq_cfgx_free = &irq_cfgx[legacy_count];
+ irq_cfgx[legacy_count - 1].next = NULL;
}
#define for_each_irq_cfg(cfg) \
- for (cfg = irq_cfgx; cfg && cfg->irq != -1U; cfg = cfg->next)
+ for (cfg = irq_cfgx; cfg; cfg = cfg->next)
-static struct irq_cfg *irq_cfgx;
DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irq_cfg, PAGE_SIZE, init_work);
static struct irq_cfg *irq_cfg(unsigned int irq)
{
struct irq_cfg *cfg;
- BUG_ON(irq == -1U);
-
- cfg = &irq_cfgx[0];
+ cfg = irq_cfgx;
while (cfg) {
if (cfg->irq == irq)
return cfg;
- if (cfg->irq == -1U)
- return NULL;
-
cfg = cfg->next;
}
int i;
int count = 0;
- BUG_ON(irq == -1U);
-
- cfg_pri = cfg = &irq_cfgx[0];
+ cfg_pri = cfg = irq_cfgx;
while (cfg) {
if (cfg->irq == irq)
return cfg;
- if (cfg->irq == -1U) {
- cfg->irq = irq;
- return cfg;
- }
cfg_pri = cfg;
cfg = cfg->next;
count++;
}
- /*
- * we run out of pre-allocate ones, allocate more
- */
- printk(KERN_DEBUG "try to get more irq_cfg %d\n", nr_irq_cfg);
+ if (!irq_cfgx_free) {
+ unsigned long phys;
+ unsigned long total_bytes;
+ /*
+ * we run out of pre-allocate ones, allocate more
+ */
+ printk(KERN_DEBUG "try to get more irq_cfg %d\n", nr_irq_cfg);
- if (after_bootmem)
- cfg = kzalloc(sizeof(struct irq_cfg)*nr_irq_cfg, GFP_ATOMIC);
- else
- cfg = __alloc_bootmem_nopanic(sizeof(struct irq_cfg)*nr_irq_cfg, PAGE_SIZE, 0);
+ total_bytes = sizeof(struct irq_cfg) * nr_irq_cfg;
+ if (after_bootmem)
+ cfg = kzalloc(total_bytes, GFP_ATOMIC);
+ else
+ cfg = __alloc_bootmem_nopanic(total_bytes, PAGE_SIZE, 0);
- if (!cfg)
- panic("please boot with nr_irq_cfg= %d\n", count * 2);
+ if (!cfg)
+ panic("please boot with nr_irq_cfg= %d\n", count * 2);
- for (i = 0; i < nr_irq_cfg; i++)
- init_one_irq_cfg(&cfg[i]);
+ phys = __pa(cfg);
+ printk(KERN_DEBUG "irq_irq ==> [%#lx - %#lx]\n", phys, phys + total_bytes);
- for (i = 1; i < nr_irq_cfg; i++)
- cfg[i-1].next = &cfg[i];
+ for (i = 0; i < nr_irq_cfg; i++)
+ init_one_irq_cfg(&cfg[i]);
- cfg->irq = irq;
- cfg_pri->next = cfg;
+ for (i = 1; i < nr_irq_cfg; i++)
+ cfg[i-1].next = &cfg[i];
+
+ irq_cfgx_free = cfg;
+ }
+ cfg = irq_cfgx_free;
+ irq_cfgx_free = irq_cfgx_free->next;
+ cfg->next = NULL;
+ if (cfg_pri)
+ cfg_pri->next = cfg;
+ else
+ irq_cfgx = cfg;
+ cfg->irq = irq;
+ printk(KERN_DEBUG "found new irq_cfg for irq %d\n", cfg->irq);
+#ifdef CONFIG_HAVE_SPARSE_IRQ_DEBUG
+ {
+ /* dump the results */
+ struct irq_cfg *cfg;
+ unsigned long phys;
+ unsigned long bytes = sizeof(struct irq_cfg);
+
+ printk(KERN_DEBUG "=========================== %d\n", irq);
+ printk(KERN_DEBUG "irq_cfg dump after get that for %d\n", irq);
+ for_each_irq_cfg(cfg) {
+ phys = __pa(cfg);
+ printk(KERN_DEBUG "irq_cfg %d ==> [%#lx - %#lx]\n", cfg->irq, phys, phys + bytes);
+ }
+ printk(KERN_DEBUG "===========================\n");
+ }
+#endif
return cfg;
}
struct irq_cfg *cfg; \
struct irq_pin_list *entry; \
\
- BUG_ON(irq >= nr_irqs); \
cfg = irq_cfg(irq); \
entry = cfg->irq_2_pin; \
for (;;) { \
struct irq_cfg *cfg;
struct irq_pin_list *entry;
- BUG_ON(irq >= nr_irqs);
cfg = irq_cfg(irq);
entry = cfg->irq_2_pin;
for (;;) {
struct irq_cfg *cfg;
struct irq_pin_list *entry;
- BUG_ON(irq >= nr_irqs);
/* first time to refer irq_cfg, so with new */
cfg = irq_cfg_alloc(irq);
entry = cfg->irq_2_pin;
best_guess = irq;
}
}
- BUG_ON(best_guess >= nr_irqs);
return best_guess;
}
irq += nr_ioapic_registers[i++];
irq += pin;
}
- BUG_ON(irq >= nr_irqs);
return irq;
}
int cpu;
struct irq_cfg *cfg;
- BUG_ON((unsigned)irq >= nr_irqs);
cfg = irq_cfg(irq);
/* Only try and allocate irqs on cpus that are present */
cpumask_t mask;
int cpu, vector;
- BUG_ON((unsigned)irq >= nr_irqs);
cfg = irq_cfg(irq);
BUG_ON(!cfg->vector);
{
struct irq_desc *desc;
- desc = irq_to_desc(irq);
+ /* first time to use this irq_desc */
+ if (irq < 16)
+ desc = irq_to_desc(irq);
+ else
+ desc = irq_to_desc_alloc(irq);
+
if (trigger)
desc->status |= IRQ_LEVEL;
else
printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID);
+ printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type);
+ printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.bits.LTS);
printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)®_01);
printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.bits.entries);
struct irq_desc *desc;
struct irq_cfg *cfg;
irq = __get_cpu_var(vector_irq)[vector];
- if (irq >= nr_irqs)
- continue;
desc = irq_to_desc(irq);
+ if (!desc)
+ continue;
+
cfg = irq_cfg(irq);
spin_lock(&desc->lock);
if (!cfg->move_cleanup_count)
/*
* Dynamic irq allocate and deallocation
*/
-int create_irq(void)
+unsigned int create_irq_nr(unsigned int irq_want)
{
/* Allocate an unused irq */
- int irq;
- int new;
+ unsigned int irq;
+ unsigned int new;
unsigned long flags;
struct irq_cfg *cfg_new;
- irq = -ENOSPC;
+#ifndef CONFIG_HAVE_SPARSE_IRQ
+ irq_want = nr_irqs - 1;
+#endif
+
+ irq = 0;
spin_lock_irqsave(&vector_lock, flags);
- for (new = (nr_irqs - 1); new >= 0; new--) {
+ for (new = irq_want; new > 0; new--) {
if (platform_legacy_irq(new))
continue;
cfg_new = irq_cfg(new);
}
spin_unlock_irqrestore(&vector_lock, flags);
- if (irq >= 0) {
+ if (irq > 0) {
dynamic_irq_init(irq);
}
return irq;
}
+int create_irq(void)
+{
+ int irq;
+
+ irq = create_irq_nr(nr_irqs - 1);
+
+ if (irq == 0)
+ irq = -1;
+
+ return irq;
+}
+
void destroy_irq(unsigned int irq)
{
unsigned long flags;
return 0;
}
+static unsigned int build_irq_for_pci_dev(struct pci_dev *dev)
+{
+ unsigned int irq;
+
+ irq = dev->bus->number;
+ irq <<= 8;
+ irq |= dev->devfn;
+ irq <<= 12;
+
+ return irq;
+}
+
int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
{
- int irq, ret;
+ unsigned int irq;
+ int ret;
+ unsigned int irq_want;
+
+ irq_want = build_irq_for_pci_dev(dev) + 0x100;
- irq = create_irq();
- if (irq < 0)
- return irq;
+ irq = create_irq_nr(irq_want);
+ if (irq == 0)
+ return -1;
#ifdef CONFIG_INTR_REMAP
if (!intr_remapping_enabled)
int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
- int irq, ret, sub_handle;
+ unsigned int irq;
+ int ret, sub_handle;
struct msi_desc *desc;
+ unsigned int irq_want;
+
#ifdef CONFIG_INTR_REMAP
struct intel_iommu *iommu = 0;
int index = 0;
#endif
+ irq_want = build_irq_for_pci_dev(dev) + 0x100;
sub_handle = 0;
list_for_each_entry(desc, &dev->msi_list, list) {
- irq = create_irq();
- if (irq < 0)
- return irq;
+ irq = create_irq_nr(irq_want--);
+ if (irq == 0)
+ return -1;
#ifdef CONFIG_INTR_REMAP
if (!intr_remapping_enabled)
goto no_ir;