diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c index 63ef112..ace5bad 100644 --- a/arch/arm/mach-iop13xx/msi.c +++ b/arch/arm/mach-iop13xx/msi.c @@ -125,7 +125,7 @@ void __init iop13xx_msi_init(void) /* * Dynamic irq allocate and deallocation */ -int create_irq(void) +unsigned int create_irq(unsigned not_used) { int irq, pos; @@ -173,7 +173,7 @@ static struct irq_chip iop13xx_msi_chip = { int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) { - int id, irq = create_irq(); + int id, irq = create_irq(0); struct msi_msg msg; if (irq < 0) diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index d373290..9554513 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -532,7 +532,7 @@ iosapic_reassign_vector (int irq) int new_irq; if (iosapic_intr_info[irq].count) { - new_irq = create_irq(); + new_irq = create_irq(0); if (new_irq < 0) panic("%s: out of interrupt vectors!\n", __func__); printk(KERN_INFO "Reassigning vector %d to %d\n", @@ -784,7 +784,7 @@ iosapic_register_intr (unsigned int gsi, goto unlock_iosapic_lock; } } else - irq = create_irq(); + irq = create_irq(0); /* If vector is running out, we try to find a sharable vector */ if (irq < 0) { @@ -925,7 +925,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, delivery = IOSAPIC_PMI; break; case ACPI_INTERRUPT_INIT: - irq = create_irq(); + irq = create_irq(0); if (irq < 0) panic("%s: out of interrupt vectors!\n", __func__); vector = irq_to_vector(irq); diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index fa28483..123f8c1 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -403,7 +403,7 @@ void destroy_and_reserve_irq(unsigned int irq) /* * Dynamic irq allocate and deallocation for MSI */ -int create_irq(void) +unsigned int create_irq(unsigned int not_used) { unsigned long flags; int irq, vector, cpu; diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index 8199eb2..2774792 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c @@ -84,7 +84,7 @@ int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) int irq, vector; cpumask_t mask; - irq = create_irq(); + irq = create_irq(0); if (irq < 0) return irq; diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c index 51f66d8..004e0bb 100644 --- a/arch/ia64/sn/kernel/msi_sn.c +++ b/arch/ia64/sn/kernel/msi_sn.c @@ -83,7 +83,7 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) if (provider == NULL || provider->dma_map_consistent == NULL) return -EINVAL; - irq = create_irq(); + irq = create_irq(0); if (irq < 0) return irq; diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index 238e2dc..bcc1dd7 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -2499,15 +2499,15 @@ device_initcall(ioapic_init_sysfs); /* * Dynamic irq allocate and deallocation */ -int create_irq(void) +unsigned int create_irq(unsigned int not_used) { /* Allocate an unused irq */ - int irq, new, vector = 0; + unsigned int irq, new, vector = 0; unsigned long flags; - irq = -ENOSPC; + irq = 0; spin_lock_irqsave(&vector_lock, flags); - for (new = (nr_irqs - 1); new >= 0; new--) { + for (new = (nr_irqs - 1); new > 0; new--) { if (platform_legacy_irq(new)) continue; if (irq_vector[new] != 0) @@ -2519,7 +2519,7 @@ int create_irq(void) } spin_unlock_irqrestore(&vector_lock, flags); - if (irq >= 0) { + if (irq > 0) { set_intr_gate(vector, interrupt[irq]); dynamic_irq_init(irq); } @@ -2624,7 +2624,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) { struct msi_msg msg; int irq, ret; - irq = create_irq(); + irq = create_irq(0); if (irq < 0) return irq; diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 17a6914..2276be7 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -2508,17 +2508,21 @@ device_initcall(ioapic_init_sysfs); /* * Dynamic irq allocate and deallocation */ -int create_irq(void) +unsigned int create_irq(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); @@ -2533,7 +2537,7 @@ int create_irq(void) } spin_unlock_irqrestore(&vector_lock, flags); - if (irq >= 0) { + if (irq > 0) { dynamic_irq_init(irq); } return irq; @@ -2787,13 +2791,29 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq) 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 irq_want; - irq = create_irq(); - if (irq < 0) - return irq; + irq_want = build_irq_for_pci_dev(dev) + 0x100; + + irq = create_irq(irq_want); + if (irq == 0) + return -1; #ifdef CONFIG_INTR_REMAP if (!intr_remapping_enabled) @@ -2820,18 +2840,22 @@ error: 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(irq_want--); + if (irq == 0) + return -1; #ifdef CONFIG_INTR_REMAP if (!intr_remapping_enabled) goto no_ir; diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c index 279c940..6c82eab 100644 --- a/drivers/pci/htirq.c +++ b/drivers/pci/htirq.c @@ -82,6 +82,18 @@ void unmask_ht_irq(unsigned int irq) write_ht_irq_msg(irq, &msg); } +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; +} + /** * __ht_create_irq - create an irq and attach it to a device. * @dev: The hypertransport device to find the irq capability on. @@ -97,7 +109,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) u32 data; int max_irq; int pos; - int irq; + unsigned int irq; + unsigned int irq_want; pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ); if (!pos) @@ -125,8 +138,9 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) cfg->msg.address_lo = 0xffffffff; cfg->msg.address_hi = 0xffffffff; - irq = create_irq(); - if (irq < 0) { + irq_want= build_irq_for_pci_dev(dev); + irq = create_irq(irq_want + idx); + if (irq == 0) { kfree(cfg); return -EBUSY; } diff --git a/include/linux/irq.h b/include/linux/irq.h index 0fb3ae0..b179ccd 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -404,7 +404,7 @@ extern void set_irq_noprobe(unsigned int irq); extern void set_irq_probe(unsigned int irq); /* Handle dynamic irq creation and destruction */ -extern int create_irq(void); +extern unsigned int create_irq(unsigned int irq_want); extern void destroy_irq(unsigned int irq); /* Test to see if a driver has successfully requested an irq */