From 38bc0361303535c86f6b67b151a541728d7bdae6 Mon Sep 17 00:00:00 2001
From: "Eric W. Biederman" <ebiederm@xmission.com>
Date: Wed, 4 Oct 2006 02:16:34 -0700
Subject: [PATCH] genirq: msi: refactor the msi_ops

The current msi_ops are short sighted in a number of ways, this patch attempts
to fix the glaring deficiences.

- Report in msi_ops if a 64bit address is needed in the msi message, so we
  can fail 32bit only msi structures.

- Send and receive a full struct msi_msg in both setup and target.  This is
  a little cleaner and allows for architectures that need to modify the data
  to retarget the msi interrupt to a different cpu.

- In target pass in the full cpu mask instead of just the first cpu in case
  we can make use of the full cpu mask.

- Operate in terms of irqs and not vectors, currently there is still a 1-1
  relationship but on architectures other than ia64 I expect this will change.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rajesh Shah <rajesh.shah@intel.com>
Cc: Andi Kleen <ak@muc.de>
Cc: "Protasevich, Natalie" <Natalie.Protasevich@UNISYS.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 drivers/pci/msi.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

(limited to 'drivers/pci/msi.c')

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index cca6cb3ccdac..6d9de026e141 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -165,19 +165,17 @@ static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 }
 
 #ifdef CONFIG_SMP
-static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
+static void set_msi_affinity(unsigned int irq, cpumask_t cpu_mask)
 {
 	struct msi_desc *entry;
 	struct msi_msg msg;
-	unsigned int irq = vector;
-	unsigned int dest_cpu = first_cpu(cpu_mask);
 
-	entry = (struct msi_desc *)msi_desc[vector];
+	entry = msi_desc[irq];
 	if (!entry || !entry->dev)
 		return;
 
 	read_msi_msg(entry, &msg);
-	msi_ops->target(vector, dest_cpu, &msg.address_hi, &msg.address_lo);
+	msi_ops->target(irq, cpu_mask, &msg);
 	write_msi_msg(entry, &msg);
 	set_native_irq_info(irq, cpu_mask);
 }
@@ -701,14 +699,14 @@ static int msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
 {
 	int status;
 	struct msi_msg msg;
-	int pos, vector = dev->irq;
+	int pos;
 	u16 control;
 
 	pos = entry->msi_attrib.pos;
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
 
 	/* Configure MSI capability structure */
-	status = msi_ops->setup(dev, vector, &msg.address_hi, &msg.address_lo, &msg.data);
+	status = msi_ops->setup(dev, dev->irq, &msg);
 	if (status < 0)
 		return status;
 
@@ -863,10 +861,7 @@ static int msix_capability_init(struct pci_dev *dev,
 		/* Replace with MSI-X handler */
 		irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
 		/* Configure MSI-X capability structure */
-		status = msi_ops->setup(dev, vector,
-					&msg.address_hi,
-					&msg.address_lo,
-					&msg.data);
+		status = msi_ops->setup(dev, vector, &msg);
 		if (status < 0)
 			break;
 
@@ -928,6 +923,7 @@ int pci_msi_supported(struct pci_dev * dev)
 int pci_enable_msi(struct pci_dev* dev)
 {
 	int pos, temp, status;
+	u16 control;
 
 	if (pci_msi_supported(dev) < 0)
 		return -EINVAL;
@@ -942,6 +938,10 @@ int pci_enable_msi(struct pci_dev* dev)
 	if (!pos)
 		return -EINVAL;
 
+	pci_read_config_word(dev, msi_control_reg(pos), &control);
+	if (!is_64bit_address(control) && msi_ops->needs_64bit_address)
+		return -EINVAL;
+
 	WARN_ON(!msi_lookup_vector(dev, PCI_CAP_ID_MSI));
 
 	/* Check whether driver already requested for MSI-X vectors */
-- 
cgit v1.2.3