Multiple MSI only requires the IRQ in msi_desc entry to be set as
the value of irq_base.

This patch implements the above mentioned technique.

Signed-off-by: Mike Qiu <qiud...@linux.vnet.ibm.com>
---
 include/linux/irq.h |    2 ++
 kernel/irq/chip.c   |   40 ++++++++++++++++++++++++++++++----------
 2 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index fdf2c4a..60ef45b 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -528,6 +528,8 @@ extern int irq_set_handler_data(unsigned int irq, void 
*data);
 extern int irq_set_chip_data(unsigned int irq, void *data);
 extern int irq_set_irq_type(unsigned int irq, unsigned int type);
 extern int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry);
+extern int irq_set_multiple_msi_desc(unsigned int irq_base, unsigned int nvec,
+                                       struct msi_desc *entry);
 extern struct irq_data *irq_get_irq_data(unsigned int irq);
 
 static inline struct irq_chip *irq_get_chip(unsigned int irq)
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 3aca9f2..c4c39d3 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -90,6 +90,35 @@ int irq_set_handler_data(unsigned int irq, void *data)
 EXPORT_SYMBOL(irq_set_handler_data);
 
 /**
+ *     irq_set_multiple_msi_desc - set Multiple MSI descriptor data
+ *     for multiple IRQs
+ *     @irq_base:      Interrupt number base
+ *     @nvec:  The number of interrupts
+ *     @entry: Pointer to MSI descriptor data
+ *
+ *     Set IRQ descriptors for multiple MSIs
+ */
+int irq_set_multiple_msi_desc(unsigned int irq_base, unsigned int nvec,
+                               struct msi_desc *entry)
+{
+       unsigned long flags, i;
+       struct irq_desc *desc;
+
+       for (i = 0; i < nvec; i++) {
+               desc = irq_get_desc_lock(irq_base + i, &flags,
+                                       IRQ_GET_DESC_CHECK_GLOBAL);
+               if (!desc)
+                       return -EINVAL;
+               desc->irq_data.msi_desc = entry;
+               if (i == 0 && entry)
+                       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
  *     @entry: Pointer to MSI descriptor data
@@ -98,16 +127,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_multiple_msi_desc(irq, 1, entry);
 }
 
 /**
-- 
1.7.7.6

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to