x86/MSI: Support multiple MSIs in presense of IRQ remapping
The MSI specification has several constraints in comparison with MSI-X, most notable of them is the inability to configure MSIs independently. As a result, it is impossible to dispatch interrupts from different queues to different CPUs. This is largely devalues the support of multiple MSIs in SMP systems. Also, a necessity to allocate a contiguous block of vector numbers for devices capable of multiple MSIs might cause a considerable pressure on x86 interrupt vector allocator and could lead to fragmentation of the interrupt vectors space. This patch overcomes both drawbacks in presense of IRQ remapping and lets devices take advantage of multiple queues and per-IRQ affinity assignments. Signed-off-by: Alexander Gordeev <agordeev@redhat.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Suresh Siddha <suresh.b.siddha@intel.com> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Matthew Wilcox <willy@linux.intel.com> Cc: Jeff Garzik <jgarzik@pobox.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/c8bd86ff56b5fc118257436768aaa04489ac0a4c.1353324359.git.agordeev@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:

committed by
Ingo Molnar

parent
4cca6ea04d
commit
51906e779f
@@ -89,6 +89,29 @@ int irq_set_handler_data(unsigned int irq, void *data)
|
||||
}
|
||||
EXPORT_SYMBOL(irq_set_handler_data);
|
||||
|
||||
/**
|
||||
* irq_set_msi_desc_off - set MSI descriptor data for an irq at offset
|
||||
* @irq_base: Interrupt number base
|
||||
* @irq_offset: Interrupt number offset
|
||||
* @entry: Pointer to MSI descriptor data
|
||||
*
|
||||
* Set the MSI descriptor entry for an irq at offset
|
||||
*/
|
||||
int irq_set_msi_desc_off(unsigned int irq_base, unsigned int irq_offset,
|
||||
struct msi_desc *entry)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct irq_desc *desc = irq_get_desc_lock(irq_base + irq_offset, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
|
||||
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
desc->irq_data.msi_desc = entry;
|
||||
if (entry && !irq_offset)
|
||||
entry->irq = irq_base;
|
||||
irq_put_desc_unlock(desc, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* irq_set_msi_desc - set MSI descriptor data for an irq
|
||||
* @irq: Interrupt number
|
||||
@@ -98,16 +121,7 @@ EXPORT_SYMBOL(irq_set_handler_data);
|
||||
*/
|
||||
int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
|
||||
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
desc->irq_data.msi_desc = entry;
|
||||
if (entry)
|
||||
entry->irq = irq;
|
||||
irq_put_desc_unlock(desc, flags);
|
||||
return 0;
|
||||
return irq_set_msi_desc_off(irq, 0, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user