* [PATCH 0/5] Message signaled irq handling cleanups
@ 2006-09-27 19:55 Eric W. Biederman
2006-09-27 19:58 ` [PATCH 1/5] msi: Simplify msi sanity checks by adding with generic irq code Eric W. Biederman
` (6 more replies)
0 siblings, 7 replies; 13+ messages in thread
From: Eric W. Biederman @ 2006-09-27 19:55 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, Ingo Molnar, Luck, Tony, Andi Kleen,
Benjamin Herrenschmidt
The following patch set should be enough to clear up the
outstanding issues with genirq on i386 and x86_64. This actually
takes things a step farther and moves all of architecture
dependencies I could find into the appropriate architecture.
So hopefully we are finally close enough that other architectures
will be able implement msi support, without too much trouble.
msi: Simplify msi sanity checks by adding with generic irq code.
msi: Only use a single irq_chip for msi interrupts
msi: Refactor and move the msi irq_chip into the arch code.
msi: Move the ia64 code into arch/ia64
htirq: Tidy up the htirq code
Eric
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/5] msi: Simplify msi sanity checks by adding with generic irq code.
2006-09-27 19:55 [PATCH 0/5] Message signaled irq handling cleanups Eric W. Biederman
@ 2006-09-27 19:58 ` Eric W. Biederman
2006-09-27 19:58 ` [PATCH 2/5] msi: Only use a single irq_chip for msi interrupts Eric W. Biederman
` (5 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Eric W. Biederman @ 2006-09-27 19:58 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, Ingo Molnar, Tony Luck, Andi Kleen, Eric W. Biederman
Currently msi.c is doing sanity checks that make certain before
an irq is destroyed it has no more users.
By adding irq_has_action I can perform the test is a generic way, instead
of relying on a msi specific data structure.
By performing the core check in dynamic_irq_cleanup I ensure every user
of dynamic irqs has a test present and we don't free resources that are
in use.
In msi.c this allows me to kill the attrib.state member of msi_desc and
all of the assciated code to maintain it.
To keep from freeing data structures when irq cleanup code is called to
soon changing dyanamic_irq_cleanup is insufficient because there are
msi specific data structures that are also not safe to free.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
drivers/pci/msi.c | 43 ++++++++-----------------------------------
drivers/pci/msi.h | 2 +-
include/linux/irq.h | 7 +++++++
kernel/irq/chip.c | 7 +++++++
4 files changed, 23 insertions(+), 36 deletions(-)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index da2c6c2..e3ba396 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -188,18 +188,6 @@ static void unmask_MSI_irq(unsigned int
static unsigned int startup_msi_irq_wo_maskbit(unsigned int irq)
{
- struct msi_desc *entry;
- unsigned long flags;
-
- spin_lock_irqsave(&msi_lock, flags);
- entry = msi_desc[irq];
- if (!entry || !entry->dev) {
- spin_unlock_irqrestore(&msi_lock, flags);
- return 0;
- }
- entry->msi_attrib.state = 1; /* Mark it active */
- spin_unlock_irqrestore(&msi_lock, flags);
-
return 0; /* never anything pending */
}
@@ -212,14 +200,6 @@ static unsigned int startup_msi_irq_w_ma
static void shutdown_msi_irq(unsigned int irq)
{
- struct msi_desc *entry;
- unsigned long flags;
-
- spin_lock_irqsave(&msi_lock, flags);
- entry = msi_desc[irq];
- if (entry && entry->dev)
- entry->msi_attrib.state = 0; /* Mark it not active */
- spin_unlock_irqrestore(&msi_lock, flags);
}
static void end_msi_irq_wo_maskbit(unsigned int irq)
@@ -671,7 +651,6 @@ static int msi_capability_init(struct pc
entry->link.head = irq;
entry->link.tail = irq;
entry->msi_attrib.type = PCI_CAP_ID_MSI;
- entry->msi_attrib.state = 0; /* Mark it not active */
entry->msi_attrib.is_64 = is_64bit_address(control);
entry->msi_attrib.entry_nr = 0;
entry->msi_attrib.maskbit = is_mask_bit_support(control);
@@ -744,7 +723,6 @@ static int msix_capability_init(struct p
j = entries[i].entry;
entries[i].vector = irq;
entry->msi_attrib.type = PCI_CAP_ID_MSIX;
- entry->msi_attrib.state = 0; /* Mark it not active */
entry->msi_attrib.is_64 = 1;
entry->msi_attrib.entry_nr = j;
entry->msi_attrib.maskbit = 1;
@@ -897,12 +875,12 @@ void pci_disable_msi(struct pci_dev* dev
spin_unlock_irqrestore(&msi_lock, flags);
return;
}
- if (entry->msi_attrib.state) {
+ if (irq_has_action(dev->irq)) {
spin_unlock_irqrestore(&msi_lock, flags);
printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without "
"free_irq() on MSI irq %d\n",
pci_name(dev), dev->irq);
- BUG_ON(entry->msi_attrib.state > 0);
+ BUG_ON(irq_has_action(dev->irq));
} else {
default_irq = entry->msi_attrib.default_irq;
spin_unlock_irqrestore(&msi_lock, flags);
@@ -1035,17 +1013,16 @@ void pci_disable_msix(struct pci_dev* de
temp = dev->irq;
if (!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) {
- int state, irq, head, tail = 0, warning = 0;
+ int irq, head, tail = 0, warning = 0;
unsigned long flags;
irq = head = dev->irq;
dev->irq = temp; /* Restore pin IRQ */
while (head != tail) {
spin_lock_irqsave(&msi_lock, flags);
- state = msi_desc[irq]->msi_attrib.state;
tail = msi_desc[irq]->link.tail;
spin_unlock_irqrestore(&msi_lock, flags);
- if (state)
+ if (irq_has_action(irq))
warning = 1;
else if (irq != head) /* Release MSI-X irq */
msi_free_irq(dev, irq);
@@ -1072,7 +1049,7 @@ void pci_disable_msix(struct pci_dev* de
**/
void msi_remove_pci_irq_vectors(struct pci_dev* dev)
{
- int state, pos, temp;
+ int pos, temp;
unsigned long flags;
if (!pci_msi_enable || !dev)
@@ -1081,14 +1058,11 @@ void msi_remove_pci_irq_vectors(struct p
temp = dev->irq; /* Save IOAPIC IRQ */
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSI)) {
- spin_lock_irqsave(&msi_lock, flags);
- state = msi_desc[dev->irq]->msi_attrib.state;
- spin_unlock_irqrestore(&msi_lock, flags);
- if (state) {
+ if (irq_has_action(dev->irq)) {
printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
"called without free_irq() on MSI irq %d\n",
pci_name(dev), dev->irq);
- BUG_ON(state > 0);
+ BUG_ON(irq_has_action(dev->irq));
} else /* Release MSI irq assigned to this device */
msi_free_irq(dev, dev->irq);
dev->irq = temp; /* Restore IOAPIC IRQ */
@@ -1101,11 +1075,10 @@ void msi_remove_pci_irq_vectors(struct p
irq = head = dev->irq;
while (head != tail) {
spin_lock_irqsave(&msi_lock, flags);
- state = msi_desc[irq]->msi_attrib.state;
tail = msi_desc[irq]->link.tail;
base = msi_desc[irq]->mask_base;
spin_unlock_irqrestore(&msi_lock, flags);
- if (state)
+ if (irq_has_action(irq))
warning = 1;
else if (irq != head) /* Release MSI-X irq */
msi_free_irq(dev, irq);
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 435d05a..77823bf 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -53,7 +53,7 @@ struct msi_desc {
struct {
__u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
__u8 maskbit : 1; /* mask-pending bit supported ? */
- __u8 state : 1; /* {0: free, 1: busy} */
+ __u8 unused : 1;
__u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
__u8 pos; /* Location of the msi capability */
__u16 entry_nr; /* specific enabled entry */
diff --git a/include/linux/irq.h b/include/linux/irq.h
index ee8a5ea..86b65ed 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -373,6 +373,13 @@ set_irq_chained_handler(unsigned int irq
extern int create_irq(void);
extern void destroy_irq(unsigned int irq);
+/* Test to see if a driver has successfully requested an irq */
+static inline int irq_has_action(unsigned int irq)
+{
+ struct irq_desc *desc = irq_desc + irq;
+ return desc->action != NULL;
+}
+
/* Dynamic irq helper functions */
extern void dynamic_irq_init(unsigned int irq);
extern void dynamic_irq_cleanup(unsigned int irq);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index e128b7d..2253898 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -151,6 +151,13 @@ void dynamic_irq_cleanup(unsigned int ir
desc = irq_desc + irq;
spin_lock_irqsave(&desc->lock, flags);
+ if (desc->action) {
+ spin_unlock_irqrestore(&desc->lock, flags);
+ printk(KERN_ERR "Destroying IRQ%d without calling free_irq\n",
+ irq);
+ WARN_ON(1);
+ return;
+ }
desc->handle_irq = handle_bad_irq;
desc->chip = &no_irq_chip;
spin_unlock_irqrestore(&desc->lock, flags);
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/5] msi: Only use a single irq_chip for msi interrupts
2006-09-27 19:55 [PATCH 0/5] Message signaled irq handling cleanups Eric W. Biederman
2006-09-27 19:58 ` [PATCH 1/5] msi: Simplify msi sanity checks by adding with generic irq code Eric W. Biederman
@ 2006-09-27 19:58 ` Eric W. Biederman
2006-09-27 19:58 ` [PATCH 3/5] msi: Refactor and move the msi irq_chip into the arch code Eric W. Biederman
` (4 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Eric W. Biederman @ 2006-09-27 19:58 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, Ingo Molnar, Tony Luck, Andi Kleen, Eric W. Biederman
The logic works like this.
Since we no longer track the state logic by hand in msi.c startup
and shutdown are no longer needed.
By updating msi_set_mask_bit to work on msi devices that do not
implement a mask bit we can always call the mask/unmask functions.
What we really have are mask and unmask so we use them to
implement the .mask and .unmask functions instead of .enable
and .disable.
By switching to the handle_edge_irq handler we only need an ack
function that moves the irq if necessary. Which removes the
old end and ack functions and their peculiar logic of sometimes
disabling an irq.
This removes the reliance on pre genirq irq handling methods.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
drivers/pci/msi.c | 115 +++++++++++------------------------------------------
1 files changed, 24 insertions(+), 91 deletions(-)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index e3ba396..fc7dd2a 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -53,21 +53,20 @@ static void msi_set_mask_bit(unsigned in
struct msi_desc *entry;
entry = msi_desc[irq];
- if (!entry || !entry->dev || !entry->mask_base)
- return;
+ BUG_ON(!entry || !entry->dev);
switch (entry->msi_attrib.type) {
case PCI_CAP_ID_MSI:
- {
- int pos;
- u32 mask_bits;
-
- pos = (long)entry->mask_base;
- pci_read_config_dword(entry->dev, pos, &mask_bits);
- mask_bits &= ~(1);
- mask_bits |= flag;
- pci_write_config_dword(entry->dev, pos, mask_bits);
+ if (entry->msi_attrib.maskbit) {
+ int pos;
+ u32 mask_bits;
+
+ pos = (long)entry->mask_base;
+ pci_read_config_dword(entry->dev, pos, &mask_bits);
+ mask_bits &= ~(1);
+ mask_bits |= flag;
+ pci_write_config_dword(entry->dev, pos, mask_bits);
+ }
break;
- }
case PCI_CAP_ID_MSIX:
{
int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
@@ -76,6 +75,7 @@ static void msi_set_mask_bit(unsigned in
break;
}
default:
+ BUG();
break;
}
}
@@ -186,83 +186,21 @@ static void unmask_MSI_irq(unsigned int
msi_set_mask_bit(irq, 0);
}
-static unsigned int startup_msi_irq_wo_maskbit(unsigned int irq)
-{
- return 0; /* never anything pending */
-}
-
-static unsigned int startup_msi_irq_w_maskbit(unsigned int irq)
-{
- startup_msi_irq_wo_maskbit(irq);
- unmask_MSI_irq(irq);
- return 0; /* never anything pending */
-}
-
-static void shutdown_msi_irq(unsigned int irq)
-{
-}
-
-static void end_msi_irq_wo_maskbit(unsigned int irq)
+static void ack_msi_irq(unsigned int irq)
{
move_native_irq(irq);
ack_APIC_irq();
}
-static void end_msi_irq_w_maskbit(unsigned int irq)
-{
- move_native_irq(irq);
- unmask_MSI_irq(irq);
- ack_APIC_irq();
-}
-
-static void do_nothing(unsigned int irq)
-{
-}
-
-/*
- * Interrupt Type for MSI-X PCI/PCI-X/PCI-Express Devices,
- * which implement the MSI-X Capability Structure.
- */
-static struct hw_interrupt_type msix_irq_type = {
- .typename = "PCI-MSI-X",
- .startup = startup_msi_irq_w_maskbit,
- .shutdown = shutdown_msi_irq,
- .enable = unmask_MSI_irq,
- .disable = mask_MSI_irq,
- .ack = mask_MSI_irq,
- .end = end_msi_irq_w_maskbit,
- .set_affinity = set_msi_affinity
-};
-
-/*
- * Interrupt Type for MSI PCI/PCI-X/PCI-Express Devices,
- * which implement the MSI Capability Structure with
- * Mask-and-Pending Bits.
- */
-static struct hw_interrupt_type msi_irq_w_maskbit_type = {
- .typename = "PCI-MSI",
- .startup = startup_msi_irq_w_maskbit,
- .shutdown = shutdown_msi_irq,
- .enable = unmask_MSI_irq,
- .disable = mask_MSI_irq,
- .ack = mask_MSI_irq,
- .end = end_msi_irq_w_maskbit,
- .set_affinity = set_msi_affinity
-};
-
/*
- * Interrupt Type for MSI PCI/PCI-X/PCI-Express Devices,
- * which implement the MSI Capability Structure without
- * Mask-and-Pending Bits.
+ * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
+ * which implement the MSI or MSI-X Capability Structure.
*/
-static struct hw_interrupt_type msi_irq_wo_maskbit_type = {
- .typename = "PCI-MSI",
- .startup = startup_msi_irq_wo_maskbit,
- .shutdown = shutdown_msi_irq,
- .enable = do_nothing,
- .disable = do_nothing,
- .ack = do_nothing,
- .end = end_msi_irq_wo_maskbit,
+static struct irq_chip msi_chip = {
+ .name = "PCI-MSI",
+ .unmask = unmask_MSI_irq,
+ .mask = mask_MSI_irq,
+ .ack = ack_msi_irq,
.set_affinity = set_msi_affinity
};
@@ -330,7 +268,7 @@ static void attach_msi_entry(struct msi_
spin_unlock_irqrestore(&msi_lock, flags);
}
-static int create_msi_irq(struct hw_interrupt_type *handler)
+static int create_msi_irq(struct irq_chip *chip)
{
struct msi_desc *entry;
int irq;
@@ -345,7 +283,7 @@ static int create_msi_irq(struct hw_inte
return -EBUSY;
}
- set_irq_chip(irq, handler);
+ set_irq_chip_and_handler(irq, chip, handle_edge_irq);
set_irq_data(irq, entry);
return irq;
@@ -634,16 +572,11 @@ static int msi_capability_init(struct pc
struct msi_desc *entry;
int pos, irq;
u16 control;
- struct hw_interrupt_type *handler;
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
pci_read_config_word(dev, msi_control_reg(pos), &control);
/* MSI Entry Initialization */
- handler = &msi_irq_wo_maskbit_type;
- if (is_mask_bit_support(control))
- handler = &msi_irq_w_maskbit_type;
-
- irq = create_msi_irq(handler);
+ irq = create_msi_irq(&msi_chip);
if (irq < 0)
return irq;
@@ -715,7 +648,7 @@ static int msix_capability_init(struct p
/* MSI-X Table Initialization */
for (i = 0; i < nvec; i++) {
- irq = create_msi_irq(&msix_irq_type);
+ irq = create_msi_irq(&msi_chip);
if (irq < 0)
break;
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/5] msi: Refactor and move the msi irq_chip into the arch code.
2006-09-27 19:55 [PATCH 0/5] Message signaled irq handling cleanups Eric W. Biederman
2006-09-27 19:58 ` [PATCH 1/5] msi: Simplify msi sanity checks by adding with generic irq code Eric W. Biederman
2006-09-27 19:58 ` [PATCH 2/5] msi: Only use a single irq_chip for msi interrupts Eric W. Biederman
@ 2006-09-27 19:58 ` Eric W. Biederman
2006-09-27 19:58 ` [PATCH 4/5] msi: Move the ia64 code into arch/ia64 Eric W. Biederman
` (3 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Eric W. Biederman @ 2006-09-27 19:58 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, Ingo Molnar, Tony Luck, Andi Kleen, Eric W. Biederman
It turns out msi_ops was simply not enough to abstract the
architecture specific details of msi. So I have moved
the resposibility of constructing the struct irq_chip
to the architectures, and have two architecture specific
functions arch_setup_msi_irq, and arch_teardown_msi_irq.
For simple architectures those functions can do all of the work.
For architectures with platform dependencies they can call into
the appropriate platform code.
With this msi.c is finally free of assuming you have an apic,
and this actually takes less code.
The helpers for the architecture specific code are
declared in the linux/msi.h to keep them separate from
the msi functions used by drivers in linux/pci.h
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
arch/i386/kernel/io_apic.c | 81 +++++++++++++++-------
arch/x86_64/kernel/io_apic.c | 89 +++++++++++++++++-------
drivers/pci/msi-altix.c | 78 +++++++++++++--------
drivers/pci/msi-apic.c | 86 +++++++++++++++++------
drivers/pci/msi.c | 150 ++++++++--------------------------------
drivers/pci/msi.h | 27 -------
include/asm-i386/msi.h | 20 -----
include/asm-ia64/machvec.h | 21 ++++--
include/asm-ia64/machvec_sn2.h | 9 ++
include/asm-ia64/msi.h | 29 --------
include/asm-x86_64/msi.h | 21 ------
include/linux/msi.h | 49 +++++++++++++
include/linux/pci.h | 67 ------------------
13 files changed, 333 insertions(+), 394 deletions(-)
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 100406b..5a12527 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -32,6 +32,7 @@ #include <linux/acpi.h>
#include <linux/module.h>
#include <linux/sysdev.h>
#include <linux/pci.h>
+#include <linux/msi.h>
#include <asm/io.h>
#include <asm/smp.h>
@@ -2455,11 +2456,8 @@ #endif /* CONFIG_PCI_MSI */
* MSI mesage composition
*/
#ifdef CONFIG_PCI_MSI
-static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
{
- /* For now always this code always uses physical delivery
- * mode.
- */
int vector;
unsigned dest;
@@ -2489,34 +2487,71 @@ static int msi_msg_setup(struct pci_dev
return vector;
}
-static void msi_msg_teardown(unsigned int irq)
-{
- return;
-}
-
-static void msi_msg_set_affinity(unsigned int irq, cpumask_t mask, struct msi_msg *msg)
+#ifdef CONFIG_SMP
+static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
{
+ struct msi_msg msg;
+ unsigned int dest;
+ cpumask_t tmp;
int vector;
- unsigned dest;
+
+ cpus_and(tmp, mask, cpu_online_map);
+ if (cpus_empty(tmp))
+ tmp = TARGET_CPUS;
vector = assign_irq_vector(irq);
- if (vector > 0) {
- dest = cpu_mask_to_apicid(mask);
+ if (vector < 0)
+ return;
- msg->data &= ~MSI_DATA_VECTOR_MASK;
- msg->data |= MSI_DATA_VECTOR(vector);
- msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK;
- msg->address_lo |= MSI_ADDR_DEST_ID(dest);
- }
+ dest = cpu_mask_to_apicid(mask);
+
+ read_msi_msg(irq, &msg);
+
+ msg.data &= ~MSI_DATA_VECTOR_MASK;
+ msg.data |= MSI_DATA_VECTOR(vector);
+ msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+ msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+
+ write_msi_msg(irq, &msg);
+ set_native_irq_info(irq, mask);
}
+#endif /* CONFIG_SMP */
-struct msi_ops arch_msi_ops = {
- .needs_64bit_address = 0,
- .setup = msi_msg_setup,
- .teardown = msi_msg_teardown,
- .target = msi_msg_set_affinity,
+/*
+ * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
+ * which implement the MSI or MSI-X Capability Structure.
+ */
+static struct irq_chip msi_chip = {
+ .name = "PCI-MSI",
+ .unmask = unmask_msi_irq,
+ .mask = mask_msi_irq,
+ .ack = ack_ioapic_irq,
+#ifdef CONFIG_SMP
+ .set_affinity = set_msi_irq_affinity,
+#endif
+ .retrigger = ioapic_retrigger_irq,
};
+int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
+{
+ struct msi_msg msg;
+ int ret;
+ ret = msi_compose_msg(dev, irq, &msg);
+ if (ret < 0)
+ return ret;
+
+ write_msi_msg(irq, &msg);
+
+ set_irq_chip_and_handler(irq, &msi_chip, handle_edge_irq);
+
+ return 0;
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+ return;
+}
+
#endif /* CONFIG_PCI_MSI */
/*
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 31c270f..e55028f 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -30,6 +30,7 @@ #include <linux/pci.h>
#include <linux/mc146818rtc.h>
#include <linux/acpi.h>
#include <linux/sysdev.h>
+#include <linux/msi.h>
#ifdef CONFIG_ACPI
#include <acpi/acpi_bus.h>
#endif
@@ -1701,11 +1702,8 @@ void destroy_irq(unsigned int irq)
* MSI mesage composition
*/
#ifdef CONFIG_PCI_MSI
-static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
{
- /* For now always this code always uses physical delivery
- * mode.
- */
int vector;
unsigned dest;
@@ -1739,39 +1737,76 @@ static int msi_msg_setup(struct pci_dev
return vector;
}
-static void msi_msg_teardown(unsigned int irq)
-{
- return;
-}
-
-static void msi_msg_set_affinity(unsigned int irq, cpumask_t mask, struct msi_msg *msg)
+#ifdef CONFIG_SMP
+static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
{
+ struct msi_msg msg;
+ unsigned int dest;
+ cpumask_t tmp;
int vector;
- unsigned dest;
+
+ cpus_and(tmp, mask, cpu_online_map);
+ if (cpus_empty(tmp))
+ tmp = TARGET_CPUS;
+
+ cpus_and(mask, tmp, CPU_MASK_ALL);
vector = assign_irq_vector(irq, mask);
- if (vector > 0) {
- cpumask_t tmp;
+ if (vector < 0)
+ return;
- cpus_clear(tmp);
- cpu_set(vector >> 8, tmp);
- dest = cpu_mask_to_apicid(tmp);
+ cpus_clear(tmp);
+ cpu_set(vector >> 8, tmp);
+ dest = cpu_mask_to_apicid(tmp);
- msg->data &= ~MSI_DATA_VECTOR_MASK;
- msg->data |= MSI_DATA_VECTOR(vector);
- msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK;
- msg->address_lo |= MSI_ADDR_DEST_ID(dest);
- }
+ read_msi_msg(irq, &msg);
+
+ msg.data &= ~MSI_DATA_VECTOR_MASK;
+ msg.data |= MSI_DATA_VECTOR(vector);
+ msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+ msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+
+ write_msi_msg(irq, &msg);
+ set_native_irq_info(irq, mask);
}
+#endif /* CONFIG_SMP */
-struct msi_ops arch_msi_ops = {
- .needs_64bit_address = 0,
- .setup = msi_msg_setup,
- .teardown = msi_msg_teardown,
- .target = msi_msg_set_affinity,
+/*
+ * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
+ * which implement the MSI or MSI-X Capability Structure.
+ */
+static struct irq_chip msi_chip = {
+ .name = "PCI-MSI",
+ .unmask = unmask_msi_irq,
+ .mask = mask_msi_irq,
+ .ack = ack_apic_edge,
+#ifdef CONFIG_SMP
+ .set_affinity = set_msi_irq_affinity,
+#endif
+ .retrigger = ioapic_retrigger_irq,
};
-#endif
+int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
+{
+ struct msi_msg msg;
+ int ret;
+ ret = msi_compose_msg(dev, irq, &msg);
+ if (ret < 0)
+ return ret;
+
+ write_msi_msg(irq, &msg);
+
+ set_irq_chip_and_handler(irq, &msi_chip, handle_edge_irq);
+
+ return 0;
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+ return;
+}
+
+#endif /* CONFIG_PCI_MSI */
/*
* Hypertransport interrupt support
diff --git a/drivers/pci/msi-altix.c b/drivers/pci/msi-altix.c
index 7aedc2a..2b44128 100644
--- a/drivers/pci/msi-altix.c
+++ b/drivers/pci/msi-altix.c
@@ -9,6 +9,7 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/cpumask.h>
+#include <linux/msi.h>
#include <asm/sn/addrs.h>
#include <asm/sn/intr.h>
@@ -16,17 +17,16 @@ #include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/pcidev.h>
#include <asm/sn/nodepda.h>
-#include "msi.h"
-
struct sn_msi_info {
u64 pci_addr;
struct sn_irq_info *sn_irq_info;
};
-static struct sn_msi_info *sn_msi_info;
+static struct sn_msi_info sn_msi_info[NR_IRQS];
+
+static struct irq_chip sn_msi_chip;
-static void
-sn_msi_teardown(unsigned int irq)
+void sn_teardown_msi_irq(unsigned int irq)
{
nasid_t nasid;
int widget;
@@ -61,9 +61,10 @@ sn_msi_teardown(unsigned int irq)
return;
}
-int
-sn_msi_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
{
+ struct msi_msg msg;
+ struct msi_desc *entry;
int widget;
int status;
nasid_t nasid;
@@ -72,6 +73,10 @@ sn_msi_setup(struct pci_dev *pdev, unsig
struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+ entry = get_irq_data(irq);
+ if (!entry->msi_attrib.is_64bit)
+ return -EINVAL;
+
if (bussoft == NULL)
return -EINVAL;
@@ -121,25 +126,29 @@ sn_msi_setup(struct pci_dev *pdev, unsig
sn_msi_info[irq].sn_irq_info = sn_irq_info;
sn_msi_info[irq].pci_addr = bus_addr;
- msg->address_hi = (u32)(bus_addr >> 32);
- msg->address_lo = (u32)(bus_addr & 0x00000000ffffffff);
+ msg.address_hi = (u32)(bus_addr >> 32);
+ msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
/*
* In the SN platform, bit 16 is a "send vector" bit which
* must be present in order to move the vector through the system.
*/
- msg->data = 0x100 + irq;
+ msg.data = 0x100 + irq;
#ifdef CONFIG_SMP
set_irq_affinity_info(irq, sn_irq_info->irq_cpuid, 0);
#endif
+ write_msi_msg(irq, &msg);
+ set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
+
return 0;
}
-static void
-sn_msi_target(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg)
+#ifdef CONFIG_SMP
+static void sn_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
{
+ struct msi_msg msg;
int slice;
nasid_t nasid;
u64 bus_addr;
@@ -159,6 +168,7 @@ sn_msi_target(unsigned int irq, cpumask_
* Release XIO resources for the old MSI PCI address
*/
+ read_msi_msg(irq, &msg);
sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
pdev = sn_pdev->pdi_linux_pcidev;
provider = SN_PCIDEV_BUSPROVIDER(pdev);
@@ -185,27 +195,35 @@ sn_msi_target(unsigned int irq, cpumask_
SN_DMA_MSI|SN_DMA_ADDR_XIO);
sn_msi_info[irq].pci_addr = bus_addr;
- msg->address_hi = (u32)(bus_addr >> 32);
- msg->address_lo = (u32)(bus_addr & 0x00000000ffffffff);
+ msg.address_hi = (u32)(bus_addr >> 32);
+ msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
+
+ write_msi_msg(irq, &msg);
+ set_native_irq_info(irq, cpu_mask);
}
+#endif /* CONFIG_SMP */
-struct msi_ops sn_msi_ops = {
- .needs_64bit_address = 1,
- .setup = sn_msi_setup,
- .teardown = sn_msi_teardown,
-#ifdef CONFIG_SMP
- .target = sn_msi_target,
-#endif
-};
+static void sn_ack_msi_irq(unsigned int irq)
+{
+ move_native_irq(irq);
+ ia64_eoi();
+}
-int
-sn_msi_init(void)
+static int sn_msi_retrigger_irq(unsigned int irq)
{
- sn_msi_info =
- kzalloc(sizeof(struct sn_msi_info) * NR_IRQS, GFP_KERNEL);
- if (! sn_msi_info)
- return -ENOMEM;
+ unsigned int vector = irq;
+ ia64_resend_irq(vector);
- msi_register(&sn_msi_ops);
- return 0;
+ return 1;
}
+
+static struct irq_chip sn_msi_chip = {
+ .name = "PCI-MSI",
+ .mask = mask_msi_irq,
+ .unmask = unmask_msi_irq,
+ .ack = sn_ack_msi_irq,
+#ifdef CONFIG_SMP
+ .set_affinity = sn_set_msi_irq_affinity,
+#endif
+ .retrigger = sn_msi_retrigger_irq,
+};
diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c
index afc0ed1..0b083f6 100644
--- a/drivers/pci/msi-apic.c
+++ b/drivers/pci/msi-apic.c
@@ -4,10 +4,9 @@
#include <linux/pci.h>
#include <linux/irq.h>
+#include <linux/msi.h>
#include <asm/smp.h>
-#include "msi.h"
-
/*
* Shifts for APIC-based data
*/
@@ -31,6 +30,7 @@ #define MSI_DATA_TRIGGER_LEVEL (1 <<
* Shift/mask fields for APIC-based bus address
*/
+#define MSI_TARGET_CPU_SHIFT 4
#define MSI_ADDR_HEADER 0xfee00000
#define MSI_ADDR_DESTID_MASK 0xfff0000f
@@ -44,58 +44,100 @@ #define MSI_ADDR_REDIRECTION_SHIFT 3
#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
+static struct irq_chip ia64_msi_chip;
-static void
-msi_target_apic(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg)
+#ifdef CONFIG_SMP
+static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
{
- u32 addr = msg->address_lo;
+ struct msi_msg msg;
+ u32 addr;
+
+ read_msi_msg(irq, &msg);
+ addr = msg.address_lo;
addr &= MSI_ADDR_DESTID_MASK;
addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask)));
+ msg.address_lo = addr;
- msg->address_lo = addr;
+ write_msi_msg(irq, &msg);
+ set_native_irq_info(irq, cpu_mask);
}
+#endif /* CONFIG_SMP */
-static int
-msi_setup_apic(struct pci_dev *pdev, /* unused in generic */
- unsigned int irq,
- struct msi_msg *msg)
+int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
{
+ struct msi_msg msg;
unsigned long dest_phys_id;
unsigned int vector;
dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
vector = irq;
- msg->address_hi = 0;
- msg->address_lo =
+ msg.address_hi = 0;
+ msg.address_lo =
MSI_ADDR_HEADER |
MSI_ADDR_DESTMODE_PHYS |
MSI_ADDR_REDIRECTION_CPU |
MSI_ADDR_DESTID_CPU(dest_phys_id);
- msg->data =
+ msg.data =
MSI_DATA_TRIGGER_EDGE |
MSI_DATA_LEVEL_ASSERT |
MSI_DATA_DELIVERY_FIXED |
MSI_DATA_VECTOR(vector);
+ write_msi_msg(irq, &msg);
+ set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
+
return 0;
}
-static void
-msi_teardown_apic(unsigned int irq)
+void ia64_teardown_msi_irq(unsigned int irq)
{
return; /* no-op */
}
+static void ia64_ack_msi_irq(unsigned int irq)
+{
+ move_native_irq(irq);
+ ia64_eoi();
+}
+
+static int ia64_msi_retrigger_irq(unsigned int irq)
+{
+ unsigned int vector = irq;
+ ia64_resend_irq(vector);
+
+ return 1;
+}
+
/*
- * Generic ops used on most IA archs/platforms. Set with msi_register()
+ * Generic ops used on most IA64 platforms.
*/
-
-struct msi_ops msi_apic_ops = {
- .needs_64bit_address = 0,
- .setup = msi_setup_apic,
- .teardown = msi_teardown_apic,
- .target = msi_target_apic,
+static struct irq_chip ia64_msi_chip = {
+ .name = "PCI-MSI",
+ .mask = mask_msi_irq,
+ .unmask = unmask_msi_irq,
+ .ack = ia64_ack_msi_irq,
+#ifdef CONFIG_SMP
+ .set_affinity = ia64_set_msi_irq_affinity,
+#endif
+ .retrigger = ia64_msi_retrigger_irq,
};
+
+
+int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
+{
+ if (platform_setup_msi_irq)
+ return platform_setup_msi_irq(irq, pdev);
+
+ return ia64_setup_msi_irq(irq, pdev);
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+ if (platform_teardown_msi_irq)
+ return platform_teardown_msi_irq(irq);
+
+ return ia64_teardown_msi_irq(irq);
+}
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index fc7dd2a..f9fdc54 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -15,6 +15,7 @@ #include <linux/ioport.h>
#include <linux/smp_lock.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
+#include <linux/msi.h>
#include <asm/errno.h>
#include <asm/io.h>
@@ -29,15 +30,6 @@ static kmem_cache_t* msi_cachep;
static int pci_msi_enable = 1;
-static struct msi_ops *msi_ops;
-
-int
-msi_register(struct msi_ops *ops)
-{
- msi_ops = ops;
- return 0;
-}
-
static int msi_cache_init(void)
{
msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc),
@@ -80,8 +72,9 @@ static void msi_set_mask_bit(unsigned in
}
}
-static void read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
+void read_msi_msg(unsigned int irq, struct msi_msg *msg)
{
+ struct msi_desc *entry = get_irq_data(irq);
switch(entry->msi_attrib.type) {
case PCI_CAP_ID_MSI:
{
@@ -118,8 +111,9 @@ static void read_msi_msg(struct msi_desc
}
}
-static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
+void write_msi_msg(unsigned int irq, struct msi_msg *msg)
{
+ struct msi_desc *entry = get_irq_data(irq);
switch (entry->msi_attrib.type) {
case PCI_CAP_ID_MSI:
{
@@ -157,53 +151,16 @@ static void write_msi_msg(struct msi_des
}
}
-#ifdef CONFIG_SMP
-static void set_msi_affinity(unsigned int irq, cpumask_t cpu_mask)
-{
- struct msi_desc *entry;
- struct msi_msg msg;
-
- entry = msi_desc[irq];
- if (!entry || !entry->dev)
- return;
-
- read_msi_msg(entry, &msg);
- msi_ops->target(irq, cpu_mask, &msg);
- write_msi_msg(entry, &msg);
- set_native_irq_info(irq, cpu_mask);
-}
-#else
-#define set_msi_affinity NULL
-#endif /* CONFIG_SMP */
-
-static void mask_MSI_irq(unsigned int irq)
+void mask_msi_irq(unsigned int irq)
{
msi_set_mask_bit(irq, 1);
}
-static void unmask_MSI_irq(unsigned int irq)
+void unmask_msi_irq(unsigned int irq)
{
msi_set_mask_bit(irq, 0);
}
-static void ack_msi_irq(unsigned int irq)
-{
- move_native_irq(irq);
- ack_APIC_irq();
-}
-
-/*
- * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
- * which implement the MSI or MSI-X Capability Structure.
- */
-static struct irq_chip msi_chip = {
- .name = "PCI-MSI",
- .unmask = unmask_MSI_irq,
- .mask = mask_MSI_irq,
- .ack = ack_msi_irq,
- .set_affinity = set_msi_affinity
-};
-
static int msi_free_irq(struct pci_dev* dev, int irq);
static int msi_init(void)
{
@@ -219,22 +176,6 @@ static int msi_init(void)
return status;
}
- status = msi_arch_init();
- if (status < 0) {
- pci_msi_enable = 0;
- printk(KERN_WARNING
- "PCI: MSI arch init failed. MSI disabled.\n");
- return status;
- }
-
- if (! msi_ops) {
- pci_msi_enable = 0;
- printk(KERN_WARNING
- "PCI: MSI ops not registered. MSI disabled.\n");
- status = -EINVAL;
- return status;
- }
-
status = msi_cache_init();
if (status < 0) {
pci_msi_enable = 0;
@@ -268,7 +209,7 @@ static void attach_msi_entry(struct msi_
spin_unlock_irqrestore(&msi_lock, flags);
}
-static int create_msi_irq(struct irq_chip *chip)
+static int create_msi_irq(void)
{
struct msi_desc *entry;
int irq;
@@ -283,7 +224,6 @@ static int create_msi_irq(struct irq_chi
return -EBUSY;
}
- set_irq_chip_and_handler(irq, chip, handle_edge_irq);
set_irq_data(irq, entry);
return irq;
@@ -473,7 +413,7 @@ int pci_save_msix_state(struct pci_dev *
struct msi_desc *entry;
entry = msi_desc[irq];
- read_msi_msg(entry, &entry->msg_save);
+ read_msi_msg(irq, &entry->msg_save);
tail = msi_desc[irq]->link.tail;
irq = tail;
@@ -512,7 +452,7 @@ void pci_restore_msix_state(struct pci_d
irq = head = dev->irq;
while (head != tail) {
entry = msi_desc[irq];
- write_msi_msg(entry, &entry->msg_save);
+ write_msi_msg(irq, &entry->msg_save);
tail = msi_desc[irq]->link.tail;
irq = tail;
@@ -524,39 +464,6 @@ void pci_restore_msix_state(struct pci_d
}
#endif
-static int msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
-{
- int status;
- struct msi_msg msg;
- 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, dev->irq, &msg);
- if (status < 0)
- return status;
-
- write_msi_msg(entry, &msg);
- if (entry->msi_attrib.maskbit) {
- unsigned int maskbits, temp;
- /* All MSIs are unmasked by default, Mask them all */
- pci_read_config_dword(dev,
- msi_mask_bits_reg(pos, is_64bit_address(control)),
- &maskbits);
- temp = (1 << multi_msi_capable(control));
- temp = ((temp - 1) & ~temp);
- maskbits |= temp;
- pci_write_config_dword(dev,
- msi_mask_bits_reg(pos, is_64bit_address(control)),
- maskbits);
- }
-
- return 0;
-}
-
/**
* msi_capability_init - configure device's MSI capability structure
* @dev: pointer to the pci_dev data structure of MSI device function
@@ -576,7 +483,7 @@ static int msi_capability_init(struct pc
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
pci_read_config_word(dev, msi_control_reg(pos), &control);
/* MSI Entry Initialization */
- irq = create_msi_irq(&msi_chip);
+ irq = create_msi_irq();
if (irq < 0)
return irq;
@@ -589,16 +496,27 @@ static int msi_capability_init(struct pc
entry->msi_attrib.maskbit = is_mask_bit_support(control);
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
entry->msi_attrib.pos = pos;
- dev->irq = irq;
- entry->dev = dev;
if (is_mask_bit_support(control)) {
entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
is_64bit_address(control));
}
+ entry->dev = dev;
+ if (entry->msi_attrib.maskbit) {
+ unsigned int maskbits, temp;
+ /* All MSIs are unmasked by default, Mask them all */
+ pci_read_config_dword(dev,
+ msi_mask_bits_reg(pos, is_64bit_address(control)),
+ &maskbits);
+ temp = (1 << multi_msi_capable(control));
+ temp = ((temp - 1) & ~temp);
+ maskbits |= temp;
+ pci_write_config_dword(dev,
+ msi_mask_bits_reg(pos, is_64bit_address(control)),
+ maskbits);
+ }
/* Configure MSI capability structure */
- status = msi_register_init(dev, entry);
- if (status != 0) {
- dev->irq = entry->msi_attrib.default_irq;
+ status = arch_setup_msi_irq(irq, dev);
+ if (status < 0) {
destroy_msi_irq(irq);
return status;
}
@@ -607,6 +525,7 @@ static int msi_capability_init(struct pc
/* Set MSI enabled bits */
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+ dev->irq = irq;
return 0;
}
@@ -624,7 +543,6 @@ static int msix_capability_init(struct p
struct msix_entry *entries, int nvec)
{
struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
- struct msi_msg msg;
int status;
int irq, pos, i, j, nr_entries, temp = 0;
unsigned long phys_addr;
@@ -648,7 +566,7 @@ static int msix_capability_init(struct p
/* MSI-X Table Initialization */
for (i = 0; i < nvec; i++) {
- irq = create_msi_irq(&msi_chip);
+ irq = create_msi_irq();
if (irq < 0)
break;
@@ -676,13 +594,12 @@ static int msix_capability_init(struct p
temp = irq;
tail = entry;
/* Configure MSI-X capability structure */
- status = msi_ops->setup(dev, irq, &msg);
+ status = arch_setup_msi_irq(irq, dev);
if (status < 0) {
destroy_msi_irq(irq);
break;
}
- write_msi_msg(entry, &msg);
attach_msi_entry(entry, irq);
}
if (i != nvec) {
@@ -746,7 +663,6 @@ int pci_msi_supported(struct pci_dev * d
int pci_enable_msi(struct pci_dev* dev)
{
int pos, temp, status;
- u16 control;
if (pci_msi_supported(dev) < 0)
return -EINVAL;
@@ -761,10 +677,6 @@ 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_irq(dev, PCI_CAP_ID_MSI));
/* Check whether driver already requested for MSI-X irqs */
@@ -831,7 +743,7 @@ static int msi_free_irq(struct pci_dev*
void __iomem *base;
unsigned long flags;
- msi_ops->teardown(irq);
+ arch_teardown_msi_irq(irq);
spin_lock_irqsave(&msi_lock, flags);
entry = msi_desc[irq];
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 77823bf..f0cca17 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -6,8 +6,6 @@
#ifndef MSI_H
#define MSI_H
-#include <asm/msi.h>
-
/*
* MSI-X Address Register
*/
@@ -49,29 +47,4 @@ #define msix_unmask(address) (address
#define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK)
#define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK)
-struct msi_desc {
- struct {
- __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
- __u8 maskbit : 1; /* mask-pending bit supported ? */
- __u8 unused : 1;
- __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
- __u8 pos; /* Location of the msi capability */
- __u16 entry_nr; /* specific enabled entry */
- unsigned default_irq; /* default pre-assigned irq */
- }msi_attrib;
-
- struct {
- __u16 head;
- __u16 tail;
- }link;
-
- void __iomem *mask_base;
- struct pci_dev *dev;
-
-#ifdef CONFIG_PM
- /* PM save area for MSIX address/data */
- struct msi_msg msg_save;
-#endif
-};
-
#endif /* MSI_H */
diff --git a/include/asm-i386/msi.h b/include/asm-i386/msi.h
deleted file mode 100644
index 7368a89..0000000
--- a/include/asm-i386/msi.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2003-2004 Intel
- * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
- */
-
-#ifndef ASM_MSI_H
-#define ASM_MSI_H
-
-#include <asm/desc.h>
-#include <mach_apic.h>
-
-extern struct msi_ops arch_msi_ops;
-
-static inline int msi_arch_init(void)
-{
- msi_register(&arch_msi_ops);
- return 0;
-}
-
-#endif /* ASM_MSI_H */
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
index 15b545a..90cba96 100644
--- a/include/asm-ia64/machvec.h
+++ b/include/asm-ia64/machvec.h
@@ -20,6 +20,7 @@ struct page;
struct mm_struct;
struct pci_bus;
struct task_struct;
+struct pci_dev;
typedef void ia64_mv_setup_t (char **);
typedef void ia64_mv_cpu_init_t (void);
@@ -75,7 +76,9 @@ typedef unsigned char ia64_mv_readb_rela
typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *);
typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *);
typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *);
-typedef int ia64_mv_msi_init_t (void);
+
+typedef int ia64_mv_setup_msi_irq_t (unsigned int irq, struct pci_dev *pdev);
+typedef void ia64_mv_teardown_msi_irq_t (unsigned int irq);
static inline void
machvec_noop (void)
@@ -154,7 +157,8 @@ # define platform_readw_relaxed
# define platform_readl_relaxed ia64_mv.readl_relaxed
# define platform_readq_relaxed ia64_mv.readq_relaxed
# define platform_migrate ia64_mv.migrate
-# define platform_msi_init ia64_mv.msi_init
+# define platform_setup_msi_irq ia64_mv.setup_msi_irq
+# define platform_teardown_msi_irq ia64_mv.teardown_msi_irq
# endif
/* __attribute__((__aligned__(16))) is required to make size of the
@@ -204,7 +208,8 @@ struct ia64_machine_vector {
ia64_mv_readl_relaxed_t *readl_relaxed;
ia64_mv_readq_relaxed_t *readq_relaxed;
ia64_mv_migrate_t *migrate;
- ia64_mv_msi_init_t *msi_init;
+ ia64_mv_setup_msi_irq_t *setup_msi_irq;
+ ia64_mv_teardown_msi_irq_t *teardown_msi_irq;
} __attribute__((__aligned__(16))); /* align attrib? see above comment */
#define MACHVEC_INIT(name) \
@@ -250,7 +255,8 @@ #define MACHVEC_INIT(name) \
platform_readl_relaxed, \
platform_readq_relaxed, \
platform_migrate, \
- platform_msi_init, \
+ platform_setup_msi_irq, \
+ platform_teardown_msi_irq, \
}
extern struct ia64_machine_vector ia64_mv;
@@ -404,8 +410,11 @@ #endif
#ifndef platform_migrate
# define platform_migrate machvec_noop_task
#endif
-#ifndef platform_msi_init
-# define platform_msi_init ((ia64_mv_msi_init_t*)NULL)
+#ifndef platform_setup_msi_irq
+# define platform_setup_msi_irq ((ia64_mv_setup_msi_irq_t*)NULL)
+#endif
+#ifndef platform_teardown_msi_irq
+# define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL)
#endif
#endif /* _ASM_IA64_MACHVEC_H */
diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h
index cf724dc..c54b165 100644
--- a/include/asm-ia64/machvec_sn2.h
+++ b/include/asm-ia64/machvec_sn2.h
@@ -67,7 +67,8 @@ extern ia64_mv_dma_sync_sg_for_device sn
extern ia64_mv_dma_mapping_error sn_dma_mapping_error;
extern ia64_mv_dma_supported sn_dma_supported;
extern ia64_mv_migrate_t sn_migrate;
-extern ia64_mv_msi_init_t sn_msi_init;
+extern ia64_mv_setup_msi_irq_t sn_setup_msi_irq;
+extern ia64_mv_teardown_msi_irq_t sn_teardown_msi_irq;
/*
@@ -120,9 +121,11 @@ #define platform_dma_mapping_error sn_d
#define platform_dma_supported sn_dma_supported
#define platform_migrate sn_migrate
#ifdef CONFIG_PCI_MSI
-#define platform_msi_init sn_msi_init
+#define platform_setup_msi_irq sn_setup_msi_irq
+#define platform_teardown_msi_irq sn_teardown_msi_irq
#else
-#define platform_msi_init ((ia64_mv_msi_init_t*)NULL)
+#define platform_setup_msi_irq ((ia64_mv_setup_msi_irq_t*)NULL)
+#define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL)
#endif
#include <asm/sn/io.h>
diff --git a/include/asm-ia64/msi.h b/include/asm-ia64/msi.h
deleted file mode 100644
index bb92b0d..0000000
--- a/include/asm-ia64/msi.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2003-2004 Intel
- * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
- */
-
-#ifndef ASM_MSI_H
-#define ASM_MSI_H
-
-#define NR_VECTORS NR_IRQS
-#define FIRST_DEVICE_VECTOR IA64_FIRST_DEVICE_VECTOR
-#define LAST_DEVICE_VECTOR IA64_LAST_DEVICE_VECTOR
-static inline void set_intr_gate (int nr, void *func) {}
-#define IO_APIC_VECTOR(irq) (irq)
-#define ack_APIC_irq ia64_eoi
-#define MSI_TARGET_CPU_SHIFT 4
-
-extern struct msi_ops msi_apic_ops;
-
-static inline int msi_arch_init(void)
-{
- if (platform_msi_init)
- return platform_msi_init();
-
- /* default ops for most ia64 platforms */
- msi_register(&msi_apic_ops);
- return 0;
-}
-
-#endif /* ASM_MSI_H */
diff --git a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h
deleted file mode 100644
index 1876fda..0000000
--- a/include/asm-x86_64/msi.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2003-2004 Intel
- * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
- */
-
-#ifndef ASM_MSI_H
-#define ASM_MSI_H
-
-#include <asm/desc.h>
-#include <asm/mach_apic.h>
-#include <asm/smp.h>
-
-extern struct msi_ops arch_msi_ops;
-
-static inline int msi_arch_init(void)
-{
- msi_register(&arch_msi_ops);
- return 0;
-}
-
-#endif /* ASM_MSI_H */
diff --git a/include/linux/msi.h b/include/linux/msi.h
new file mode 100644
index 0000000..c7ef943
--- /dev/null
+++ b/include/linux/msi.h
@@ -0,0 +1,49 @@
+#ifndef LINUX_MSI_H
+#define LINUX_MSI_H
+
+struct msi_msg {
+ u32 address_lo; /* low 32 bits of msi message address */
+ u32 address_hi; /* high 32 bits of msi message address */
+ u32 data; /* 16 bits of msi message data */
+};
+
+/* Heper functions */
+extern void mask_msi_irq(unsigned int irq);
+extern void unmask_msi_irq(unsigned int irq);
+extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
+
+extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
+
+struct msi_desc {
+ struct {
+ __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
+ __u8 maskbit : 1; /* mask-pending bit supported ? */
+ __u8 unused : 1;
+ __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
+ __u8 pos; /* Location of the msi capability */
+ __u16 entry_nr; /* specific enabled entry */
+ unsigned default_irq; /* default pre-assigned irq */
+ }msi_attrib;
+
+ struct {
+ __u16 head;
+ __u16 tail;
+ }link;
+
+ void __iomem *mask_base;
+ struct pci_dev *dev;
+
+#ifdef CONFIG_PM
+ /* PM save area for MSIX address/data */
+ struct msi_msg msg_save;
+#endif
+};
+
+/*
+ * The arch hook for setup up msi irqs
+ */
+int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev);
+void arch_teardown_msi_irq(unsigned int irq);
+
+
+#endif /* LINUX_MSI_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 64cae66..9fa0740 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -599,11 +599,6 @@ struct msix_entry {
u16 entry; /* driver uses to specify entry, OS writes */
};
-struct msi_msg {
- u32 address_lo; /* low 32 bits of msi message address */
- u32 address_hi; /* high 32 bits of msi message address */
- u32 data; /* 16 bits of msi message data */
-};
#ifndef CONFIG_PCI_MSI
static inline void pci_scan_msi_device(struct pci_dev *dev) {}
@@ -621,68 +616,6 @@ extern int pci_enable_msix(struct pci_de
struct msix_entry *entries, int nvec);
extern void pci_disable_msix(struct pci_dev *dev);
extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
-
-/*
- * MSI operation vector. Used by the msi core code (drivers/pci/msi.c)
- * to abstract platform-specific tasks relating to MSI address generation
- * and resource management.
- */
-struct msi_ops {
- int needs_64bit_address;
- /**
- * setup - generate an MSI bus address and data for a given vector
- * @pdev: PCI device context (in)
- * @irq: irq allocated by the msi core (in)
- * @msg: PCI bus address and data for msi message (out)
- *
- * Description: The setup op is used to generate a PCI bus addres and
- * data which the msi core will program into the card MSI capability
- * registers. The setup routine is responsible for picking an initial
- * cpu to target the MSI at. The setup routine is responsible for
- * examining pdev to determine the MSI capabilities of the card and
- * generating a suitable address/data. The setup routine is
- * responsible for allocating and tracking any system resources it
- * needs to route the MSI to the cpu it picks, and for associating
- * those resources with the passed in vector.
- *
- * Returns 0 if the MSI address/data was successfully setup.
- **/
-
- int (*setup) (struct pci_dev *pdev, unsigned int irq,
- struct msi_msg *msg);
-
- /**
- * teardown - release resources allocated by setup
- * @vector: vector context for resources (in)
- *
- * Description: The teardown op is used to release any resources
- * that were allocated in the setup routine associated with the passed
- * in vector.
- **/
-
- void (*teardown) (unsigned int irq);
-
- /**
- * target - retarget an MSI at a different cpu
- * @vector: vector context for resources (in)
- * @cpu: new cpu to direct vector at (in)
- * @addr_hi: new value of PCI bus upper 32 bits (in/out)
- * @addr_lo: new value of PCI bus lower 32 bits (in/out)
- *
- * Description: The target op is used to redirect an MSI vector
- * at a different cpu. addr_hi/addr_lo coming in are the existing
- * values that the MSI core has programmed into the card. The
- * target code is responsible for freeing any resources (if any)
- * associated with the old address, and generating a new PCI bus
- * addr_hi/addr_lo that will redirect the vector at the indicated cpu.
- **/
-
- void (*target) (unsigned int irq, cpumask_t cpumask,
- struct msi_msg *msg);
-};
-
-extern int msi_register(struct msi_ops *ops);
-
#endif
#ifdef CONFIG_HT_IRQ
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 4/5] msi: Move the ia64 code into arch/ia64
2006-09-27 19:55 [PATCH 0/5] Message signaled irq handling cleanups Eric W. Biederman
` (2 preceding siblings ...)
2006-09-27 19:58 ` [PATCH 3/5] msi: Refactor and move the msi irq_chip into the arch code Eric W. Biederman
@ 2006-09-27 19:58 ` Eric W. Biederman
2006-09-27 19:58 ` [PATCH 5/5] htirq: Tidy up the htirq code Eric W. Biederman
` (2 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Eric W. Biederman @ 2006-09-27 19:58 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, Ingo Molnar, Tony Luck, Andi Kleen, Eric W. Biederman
This is just a few makefile tweaks and some file renames.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
arch/ia64/kernel/Makefile | 1
arch/ia64/kernel/msi_ia64.c | 143 ++++++++++++++++++++++++++
arch/ia64/sn/kernel/Makefile | 1
arch/ia64/sn/kernel/msi_sn.c | 229 ++++++++++++++++++++++++++++++++++++++++++
drivers/pci/Makefile | 9 +-
drivers/pci/msi-altix.c | 229 ------------------------------------------
drivers/pci/msi-apic.c | 143 --------------------------
7 files changed, 377 insertions(+), 378 deletions(-)
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 96686f8..8ae384e 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o jpro
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
obj-$(CONFIG_AUDIT) += audit.o
+obj-$(CONFIG_PCI_MSI) += msi_ia64.o
mca_recovery-y += mca_drv.o mca_drv_asm.o
obj-$(CONFIG_IA64_ESI) += esi.o
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
new file mode 100644
index 0000000..0b083f6
--- /dev/null
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -0,0 +1,143 @@
+/*
+ * MSI hooks for standard x86 apic
+ */
+
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/msi.h>
+#include <asm/smp.h>
+
+/*
+ * Shifts for APIC-based data
+ */
+
+#define MSI_DATA_VECTOR_SHIFT 0
+#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT)
+
+#define MSI_DATA_DELIVERY_SHIFT 8
+#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT)
+#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT)
+
+#define MSI_DATA_LEVEL_SHIFT 14
+#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT)
+#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT)
+
+#define MSI_DATA_TRIGGER_SHIFT 15
+#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT)
+#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT)
+
+/*
+ * Shift/mask fields for APIC-based bus address
+ */
+
+#define MSI_TARGET_CPU_SHIFT 4
+#define MSI_ADDR_HEADER 0xfee00000
+
+#define MSI_ADDR_DESTID_MASK 0xfff0000f
+#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT)
+
+#define MSI_ADDR_DESTMODE_SHIFT 2
+#define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT)
+#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT)
+
+#define MSI_ADDR_REDIRECTION_SHIFT 3
+#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
+#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
+
+static struct irq_chip ia64_msi_chip;
+
+#ifdef CONFIG_SMP
+static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
+{
+ struct msi_msg msg;
+ u32 addr;
+
+ read_msi_msg(irq, &msg);
+
+ addr = msg.address_lo;
+ addr &= MSI_ADDR_DESTID_MASK;
+ addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask)));
+ msg.address_lo = addr;
+
+ write_msi_msg(irq, &msg);
+ set_native_irq_info(irq, cpu_mask);
+}
+#endif /* CONFIG_SMP */
+
+int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
+{
+ struct msi_msg msg;
+ unsigned long dest_phys_id;
+ unsigned int vector;
+
+ dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
+ vector = irq;
+
+ msg.address_hi = 0;
+ msg.address_lo =
+ MSI_ADDR_HEADER |
+ MSI_ADDR_DESTMODE_PHYS |
+ MSI_ADDR_REDIRECTION_CPU |
+ MSI_ADDR_DESTID_CPU(dest_phys_id);
+
+ msg.data =
+ MSI_DATA_TRIGGER_EDGE |
+ MSI_DATA_LEVEL_ASSERT |
+ MSI_DATA_DELIVERY_FIXED |
+ MSI_DATA_VECTOR(vector);
+
+ write_msi_msg(irq, &msg);
+ set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
+
+ return 0;
+}
+
+void ia64_teardown_msi_irq(unsigned int irq)
+{
+ return; /* no-op */
+}
+
+static void ia64_ack_msi_irq(unsigned int irq)
+{
+ move_native_irq(irq);
+ ia64_eoi();
+}
+
+static int ia64_msi_retrigger_irq(unsigned int irq)
+{
+ unsigned int vector = irq;
+ ia64_resend_irq(vector);
+
+ return 1;
+}
+
+/*
+ * Generic ops used on most IA64 platforms.
+ */
+static struct irq_chip ia64_msi_chip = {
+ .name = "PCI-MSI",
+ .mask = mask_msi_irq,
+ .unmask = unmask_msi_irq,
+ .ack = ia64_ack_msi_irq,
+#ifdef CONFIG_SMP
+ .set_affinity = ia64_set_msi_irq_affinity,
+#endif
+ .retrigger = ia64_msi_retrigger_irq,
+};
+
+
+int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
+{
+ if (platform_setup_msi_irq)
+ return platform_setup_msi_irq(irq, pdev);
+
+ return ia64_setup_msi_irq(irq, pdev);
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+ if (platform_teardown_msi_irq)
+ return platform_teardown_msi_irq(irq);
+
+ return ia64_teardown_msi_irq(irq);
+}
diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
index ab9c48c..2d78f34 100644
--- a/arch/ia64/sn/kernel/Makefile
+++ b/arch/ia64/sn/kernel/Makefile
@@ -19,3 +19,4 @@ xp-y := xp_main.o xp_nofault.o
obj-$(CONFIG_IA64_SGI_SN_XP) += xpc.o
xpc-y := xpc_main.o xpc_channel.o xpc_partition.o
obj-$(CONFIG_IA64_SGI_SN_XP) += xpnet.o
+obj-$(CONFIG_PCI_MSI) += msi_sn.o
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c
new file mode 100644
index 0000000..2b44128
--- /dev/null
+++ b/arch/ia64/sn/kernel/msi_sn.c
@@ -0,0 +1,229 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/cpumask.h>
+#include <linux/msi.h>
+
+#include <asm/sn/addrs.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/nodepda.h>
+
+struct sn_msi_info {
+ u64 pci_addr;
+ struct sn_irq_info *sn_irq_info;
+};
+
+static struct sn_msi_info sn_msi_info[NR_IRQS];
+
+static struct irq_chip sn_msi_chip;
+
+void sn_teardown_msi_irq(unsigned int irq)
+{
+ nasid_t nasid;
+ int widget;
+ struct pci_dev *pdev;
+ struct pcidev_info *sn_pdev;
+ struct sn_irq_info *sn_irq_info;
+ struct pcibus_bussoft *bussoft;
+ struct sn_pcibus_provider *provider;
+
+ sn_irq_info = sn_msi_info[irq].sn_irq_info;
+ if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
+ return;
+
+ sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+ pdev = sn_pdev->pdi_linux_pcidev;
+ provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+ (*provider->dma_unmap)(pdev,
+ sn_msi_info[irq].pci_addr,
+ PCI_DMA_FROMDEVICE);
+ sn_msi_info[irq].pci_addr = 0;
+
+ bussoft = SN_PCIDEV_BUSSOFT(pdev);
+ nasid = NASID_GET(bussoft->bs_base);
+ widget = (nasid & 1) ?
+ TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
+ SWIN_WIDGETNUM(bussoft->bs_base);
+
+ sn_intr_free(nasid, widget, sn_irq_info);
+ sn_msi_info[irq].sn_irq_info = NULL;
+
+ return;
+}
+
+int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
+{
+ struct msi_msg msg;
+ struct msi_desc *entry;
+ int widget;
+ int status;
+ nasid_t nasid;
+ u64 bus_addr;
+ struct sn_irq_info *sn_irq_info;
+ struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
+ struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+ entry = get_irq_data(irq);
+ if (!entry->msi_attrib.is_64bit)
+ return -EINVAL;
+
+ if (bussoft == NULL)
+ return -EINVAL;
+
+ if (provider == NULL || provider->dma_map_consistent == NULL)
+ return -EINVAL;
+
+ /*
+ * Set up the vector plumbing. Let the prom (via sn_intr_alloc)
+ * decide which cpu to direct this msi at by default.
+ */
+
+ nasid = NASID_GET(bussoft->bs_base);
+ widget = (nasid & 1) ?
+ TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
+ SWIN_WIDGETNUM(bussoft->bs_base);
+
+ sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
+ if (! sn_irq_info)
+ return -ENOMEM;
+
+ status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1);
+ if (status) {
+ kfree(sn_irq_info);
+ return -ENOMEM;
+ }
+
+ sn_irq_info->irq_int_bit = -1; /* mark this as an MSI irq */
+ sn_irq_fixup(pdev, sn_irq_info);
+
+ /* Prom probably should fill these in, but doesn't ... */
+ sn_irq_info->irq_bridge_type = bussoft->bs_asic_type;
+ sn_irq_info->irq_bridge = (void *)bussoft->bs_base;
+
+ /*
+ * Map the xio address into bus space
+ */
+ bus_addr = (*provider->dma_map_consistent)(pdev,
+ sn_irq_info->irq_xtalkaddr,
+ sizeof(sn_irq_info->irq_xtalkaddr),
+ SN_DMA_MSI|SN_DMA_ADDR_XIO);
+ if (! bus_addr) {
+ sn_intr_free(nasid, widget, sn_irq_info);
+ kfree(sn_irq_info);
+ return -ENOMEM;
+ }
+
+ sn_msi_info[irq].sn_irq_info = sn_irq_info;
+ sn_msi_info[irq].pci_addr = bus_addr;
+
+ msg.address_hi = (u32)(bus_addr >> 32);
+ msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
+
+ /*
+ * In the SN platform, bit 16 is a "send vector" bit which
+ * must be present in order to move the vector through the system.
+ */
+ msg.data = 0x100 + irq;
+
+#ifdef CONFIG_SMP
+ set_irq_affinity_info(irq, sn_irq_info->irq_cpuid, 0);
+#endif
+
+ write_msi_msg(irq, &msg);
+ set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
+
+ return 0;
+}
+
+#ifdef CONFIG_SMP
+static void sn_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
+{
+ struct msi_msg msg;
+ int slice;
+ nasid_t nasid;
+ u64 bus_addr;
+ struct pci_dev *pdev;
+ struct pcidev_info *sn_pdev;
+ struct sn_irq_info *sn_irq_info;
+ struct sn_irq_info *new_irq_info;
+ struct sn_pcibus_provider *provider;
+ unsigned int cpu;
+
+ cpu = first_cpu(cpu_mask);
+ sn_irq_info = sn_msi_info[irq].sn_irq_info;
+ if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
+ return;
+
+ /*
+ * Release XIO resources for the old MSI PCI address
+ */
+
+ read_msi_msg(irq, &msg);
+ sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+ pdev = sn_pdev->pdi_linux_pcidev;
+ provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+ bus_addr = (u64)(msg->address_hi) << 32 | (u64)(msg->address_lo);
+ (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE);
+ sn_msi_info[irq].pci_addr = 0;
+
+ nasid = cpuid_to_nasid(cpu);
+ slice = cpuid_to_slice(cpu);
+
+ new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
+ sn_msi_info[irq].sn_irq_info = new_irq_info;
+ if (new_irq_info == NULL)
+ return;
+
+ /*
+ * Map the xio address into bus space
+ */
+
+ bus_addr = (*provider->dma_map_consistent)(pdev,
+ new_irq_info->irq_xtalkaddr,
+ sizeof(new_irq_info->irq_xtalkaddr),
+ SN_DMA_MSI|SN_DMA_ADDR_XIO);
+
+ sn_msi_info[irq].pci_addr = bus_addr;
+ msg.address_hi = (u32)(bus_addr >> 32);
+ msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
+
+ write_msi_msg(irq, &msg);
+ set_native_irq_info(irq, cpu_mask);
+}
+#endif /* CONFIG_SMP */
+
+static void sn_ack_msi_irq(unsigned int irq)
+{
+ move_native_irq(irq);
+ ia64_eoi();
+}
+
+static int sn_msi_retrigger_irq(unsigned int irq)
+{
+ unsigned int vector = irq;
+ ia64_resend_irq(vector);
+
+ return 1;
+}
+
+static struct irq_chip sn_msi_chip = {
+ .name = "PCI-MSI",
+ .mask = mask_msi_irq,
+ .unmask = unmask_msi_irq,
+ .ack = sn_ack_msi_irq,
+#ifdef CONFIG_SMP
+ .set_affinity = sn_set_msi_irq_affinity,
+#endif
+ .retrigger = sn_msi_retrigger_irq,
+};
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 2752c57..04694ec 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -14,6 +14,9 @@ obj-$(CONFIG_HOTPLUG) += hotplug.o
# Build the PCI Hotplug drivers if we were asked to
obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
+# Build the PCI MSI interrupt support
+obj-$(CONFIG_PCI_MSI) += msi.o
+
#
# Some architectures use the generic PCI setup functions
#
@@ -28,12 +31,6 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-
obj-$(CONFIG_X86_VISWS) += setup-irq.o
obj-$(CONFIG_HT_IRQ) += htirq.o
-msiobj-y := msi.o
-msiobj-$(CONFIG_IA64) += msi-apic.o
-msiobj-$(CONFIG_IA64_GENERIC) += msi-altix.o
-msiobj-$(CONFIG_IA64_SGI_SN2) += msi-altix.o
-obj-$(CONFIG_PCI_MSI) += $(msiobj-y)
-
#
# ACPI Related PCI FW Functions
#
diff --git a/drivers/pci/msi-altix.c b/drivers/pci/msi-altix.c
deleted file mode 100644
index 2b44128..0000000
--- a/drivers/pci/msi-altix.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/cpumask.h>
-#include <linux/msi.h>
-
-#include <asm/sn/addrs.h>
-#include <asm/sn/intr.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-#include <asm/sn/nodepda.h>
-
-struct sn_msi_info {
- u64 pci_addr;
- struct sn_irq_info *sn_irq_info;
-};
-
-static struct sn_msi_info sn_msi_info[NR_IRQS];
-
-static struct irq_chip sn_msi_chip;
-
-void sn_teardown_msi_irq(unsigned int irq)
-{
- nasid_t nasid;
- int widget;
- struct pci_dev *pdev;
- struct pcidev_info *sn_pdev;
- struct sn_irq_info *sn_irq_info;
- struct pcibus_bussoft *bussoft;
- struct sn_pcibus_provider *provider;
-
- sn_irq_info = sn_msi_info[irq].sn_irq_info;
- if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
- return;
-
- sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
- pdev = sn_pdev->pdi_linux_pcidev;
- provider = SN_PCIDEV_BUSPROVIDER(pdev);
-
- (*provider->dma_unmap)(pdev,
- sn_msi_info[irq].pci_addr,
- PCI_DMA_FROMDEVICE);
- sn_msi_info[irq].pci_addr = 0;
-
- bussoft = SN_PCIDEV_BUSSOFT(pdev);
- nasid = NASID_GET(bussoft->bs_base);
- widget = (nasid & 1) ?
- TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
- SWIN_WIDGETNUM(bussoft->bs_base);
-
- sn_intr_free(nasid, widget, sn_irq_info);
- sn_msi_info[irq].sn_irq_info = NULL;
-
- return;
-}
-
-int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
-{
- struct msi_msg msg;
- struct msi_desc *entry;
- int widget;
- int status;
- nasid_t nasid;
- u64 bus_addr;
- struct sn_irq_info *sn_irq_info;
- struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
- struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
-
- entry = get_irq_data(irq);
- if (!entry->msi_attrib.is_64bit)
- return -EINVAL;
-
- if (bussoft == NULL)
- return -EINVAL;
-
- if (provider == NULL || provider->dma_map_consistent == NULL)
- return -EINVAL;
-
- /*
- * Set up the vector plumbing. Let the prom (via sn_intr_alloc)
- * decide which cpu to direct this msi at by default.
- */
-
- nasid = NASID_GET(bussoft->bs_base);
- widget = (nasid & 1) ?
- TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
- SWIN_WIDGETNUM(bussoft->bs_base);
-
- sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
- if (! sn_irq_info)
- return -ENOMEM;
-
- status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1);
- if (status) {
- kfree(sn_irq_info);
- return -ENOMEM;
- }
-
- sn_irq_info->irq_int_bit = -1; /* mark this as an MSI irq */
- sn_irq_fixup(pdev, sn_irq_info);
-
- /* Prom probably should fill these in, but doesn't ... */
- sn_irq_info->irq_bridge_type = bussoft->bs_asic_type;
- sn_irq_info->irq_bridge = (void *)bussoft->bs_base;
-
- /*
- * Map the xio address into bus space
- */
- bus_addr = (*provider->dma_map_consistent)(pdev,
- sn_irq_info->irq_xtalkaddr,
- sizeof(sn_irq_info->irq_xtalkaddr),
- SN_DMA_MSI|SN_DMA_ADDR_XIO);
- if (! bus_addr) {
- sn_intr_free(nasid, widget, sn_irq_info);
- kfree(sn_irq_info);
- return -ENOMEM;
- }
-
- sn_msi_info[irq].sn_irq_info = sn_irq_info;
- sn_msi_info[irq].pci_addr = bus_addr;
-
- msg.address_hi = (u32)(bus_addr >> 32);
- msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
-
- /*
- * In the SN platform, bit 16 is a "send vector" bit which
- * must be present in order to move the vector through the system.
- */
- msg.data = 0x100 + irq;
-
-#ifdef CONFIG_SMP
- set_irq_affinity_info(irq, sn_irq_info->irq_cpuid, 0);
-#endif
-
- write_msi_msg(irq, &msg);
- set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
-
- return 0;
-}
-
-#ifdef CONFIG_SMP
-static void sn_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
-{
- struct msi_msg msg;
- int slice;
- nasid_t nasid;
- u64 bus_addr;
- struct pci_dev *pdev;
- struct pcidev_info *sn_pdev;
- struct sn_irq_info *sn_irq_info;
- struct sn_irq_info *new_irq_info;
- struct sn_pcibus_provider *provider;
- unsigned int cpu;
-
- cpu = first_cpu(cpu_mask);
- sn_irq_info = sn_msi_info[irq].sn_irq_info;
- if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
- return;
-
- /*
- * Release XIO resources for the old MSI PCI address
- */
-
- read_msi_msg(irq, &msg);
- sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
- pdev = sn_pdev->pdi_linux_pcidev;
- provider = SN_PCIDEV_BUSPROVIDER(pdev);
-
- bus_addr = (u64)(msg->address_hi) << 32 | (u64)(msg->address_lo);
- (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE);
- sn_msi_info[irq].pci_addr = 0;
-
- nasid = cpuid_to_nasid(cpu);
- slice = cpuid_to_slice(cpu);
-
- new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
- sn_msi_info[irq].sn_irq_info = new_irq_info;
- if (new_irq_info == NULL)
- return;
-
- /*
- * Map the xio address into bus space
- */
-
- bus_addr = (*provider->dma_map_consistent)(pdev,
- new_irq_info->irq_xtalkaddr,
- sizeof(new_irq_info->irq_xtalkaddr),
- SN_DMA_MSI|SN_DMA_ADDR_XIO);
-
- sn_msi_info[irq].pci_addr = bus_addr;
- msg.address_hi = (u32)(bus_addr >> 32);
- msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
-
- write_msi_msg(irq, &msg);
- set_native_irq_info(irq, cpu_mask);
-}
-#endif /* CONFIG_SMP */
-
-static void sn_ack_msi_irq(unsigned int irq)
-{
- move_native_irq(irq);
- ia64_eoi();
-}
-
-static int sn_msi_retrigger_irq(unsigned int irq)
-{
- unsigned int vector = irq;
- ia64_resend_irq(vector);
-
- return 1;
-}
-
-static struct irq_chip sn_msi_chip = {
- .name = "PCI-MSI",
- .mask = mask_msi_irq,
- .unmask = unmask_msi_irq,
- .ack = sn_ack_msi_irq,
-#ifdef CONFIG_SMP
- .set_affinity = sn_set_msi_irq_affinity,
-#endif
- .retrigger = sn_msi_retrigger_irq,
-};
diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c
deleted file mode 100644
index 0b083f6..0000000
--- a/drivers/pci/msi-apic.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * MSI hooks for standard x86 apic
- */
-
-#include <linux/pci.h>
-#include <linux/irq.h>
-#include <linux/msi.h>
-#include <asm/smp.h>
-
-/*
- * Shifts for APIC-based data
- */
-
-#define MSI_DATA_VECTOR_SHIFT 0
-#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT)
-
-#define MSI_DATA_DELIVERY_SHIFT 8
-#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT)
-#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT)
-
-#define MSI_DATA_LEVEL_SHIFT 14
-#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT)
-#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT)
-
-#define MSI_DATA_TRIGGER_SHIFT 15
-#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT)
-#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT)
-
-/*
- * Shift/mask fields for APIC-based bus address
- */
-
-#define MSI_TARGET_CPU_SHIFT 4
-#define MSI_ADDR_HEADER 0xfee00000
-
-#define MSI_ADDR_DESTID_MASK 0xfff0000f
-#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT)
-
-#define MSI_ADDR_DESTMODE_SHIFT 2
-#define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT)
-#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT)
-
-#define MSI_ADDR_REDIRECTION_SHIFT 3
-#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
-#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
-
-static struct irq_chip ia64_msi_chip;
-
-#ifdef CONFIG_SMP
-static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
-{
- struct msi_msg msg;
- u32 addr;
-
- read_msi_msg(irq, &msg);
-
- addr = msg.address_lo;
- addr &= MSI_ADDR_DESTID_MASK;
- addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask)));
- msg.address_lo = addr;
-
- write_msi_msg(irq, &msg);
- set_native_irq_info(irq, cpu_mask);
-}
-#endif /* CONFIG_SMP */
-
-int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
-{
- struct msi_msg msg;
- unsigned long dest_phys_id;
- unsigned int vector;
-
- dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
- vector = irq;
-
- msg.address_hi = 0;
- msg.address_lo =
- MSI_ADDR_HEADER |
- MSI_ADDR_DESTMODE_PHYS |
- MSI_ADDR_REDIRECTION_CPU |
- MSI_ADDR_DESTID_CPU(dest_phys_id);
-
- msg.data =
- MSI_DATA_TRIGGER_EDGE |
- MSI_DATA_LEVEL_ASSERT |
- MSI_DATA_DELIVERY_FIXED |
- MSI_DATA_VECTOR(vector);
-
- write_msi_msg(irq, &msg);
- set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
-
- return 0;
-}
-
-void ia64_teardown_msi_irq(unsigned int irq)
-{
- return; /* no-op */
-}
-
-static void ia64_ack_msi_irq(unsigned int irq)
-{
- move_native_irq(irq);
- ia64_eoi();
-}
-
-static int ia64_msi_retrigger_irq(unsigned int irq)
-{
- unsigned int vector = irq;
- ia64_resend_irq(vector);
-
- return 1;
-}
-
-/*
- * Generic ops used on most IA64 platforms.
- */
-static struct irq_chip ia64_msi_chip = {
- .name = "PCI-MSI",
- .mask = mask_msi_irq,
- .unmask = unmask_msi_irq,
- .ack = ia64_ack_msi_irq,
-#ifdef CONFIG_SMP
- .set_affinity = ia64_set_msi_irq_affinity,
-#endif
- .retrigger = ia64_msi_retrigger_irq,
-};
-
-
-int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
-{
- if (platform_setup_msi_irq)
- return platform_setup_msi_irq(irq, pdev);
-
- return ia64_setup_msi_irq(irq, pdev);
-}
-
-void arch_teardown_msi_irq(unsigned int irq)
-{
- if (platform_teardown_msi_irq)
- return platform_teardown_msi_irq(irq);
-
- return ia64_teardown_msi_irq(irq);
-}
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 5/5] htirq: Tidy up the htirq code
2006-09-27 19:55 [PATCH 0/5] Message signaled irq handling cleanups Eric W. Biederman
` (3 preceding siblings ...)
2006-09-27 19:58 ` [PATCH 4/5] msi: Move the ia64 code into arch/ia64 Eric W. Biederman
@ 2006-09-27 19:58 ` Eric W. Biederman
2006-09-27 20:29 ` [PATCH 0/5] Message signaled irq handling cleanups Eric W. Biederman
2006-09-27 22:36 ` Benjamin Herrenschmidt
6 siblings, 0 replies; 13+ messages in thread
From: Eric W. Biederman @ 2006-09-27 19:58 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, Ingo Molnar, Tony Luck, Andi Kleen, Eric W. Biederman
This moves the declarations for the architecture helpers into
include/linux/htirq.h from the generic include/linux/pci.h.
Hopefully this will make this distinction clearer.
htirq.h is included where it is needed.
The dependency on the msi code is fixed and removed.
The Makefile is tidied up.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
arch/i386/kernel/io_apic.c | 5 ++---
arch/x86_64/kernel/io_apic.c | 1 +
drivers/pci/Kconfig | 1 -
drivers/pci/Makefile | 4 +++-
drivers/pci/htirq.c | 1 +
include/linux/htirq.h | 15 +++++++++++++++
include/linux/pci.h | 11 -----------
7 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 5a12527..b7287fb 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -33,6 +33,7 @@ #include <linux/module.h>
#include <linux/sysdev.h>
#include <linux/pci.h>
#include <linux/msi.h>
+#include <linux/htirq.h>
#include <asm/io.h>
#include <asm/smp.h>
@@ -2409,9 +2410,8 @@ static int __init ioapic_init_sysfs(void
device_initcall(ioapic_init_sysfs);
-#ifdef CONFIG_PCI_MSI
/*
- * Dynamic irq allocate and deallocation for MSI
+ * Dynamic irq allocate and deallocation
*/
int create_irq(void)
{
@@ -2450,7 +2450,6 @@ void destroy_irq(unsigned int irq)
irq_vector[irq] = 0;
spin_unlock_irqrestore(&vector_lock, flags);
}
-#endif /* CONFIG_PCI_MSI */
/*
* MSI mesage composition
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index e55028f..91728d9 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -31,6 +31,7 @@ #include <linux/mc146818rtc.h>
#include <linux/acpi.h>
#include <linux/sysdev.h>
#include <linux/msi.h>
+#include <linux/htirq.h>
#ifdef CONFIG_ACPI
#include <acpi/acpi_bus.h>
#endif
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 0af6d72..3029412 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -55,7 +55,6 @@ config PCI_DEBUG
config HT_IRQ
bool "Interrupts on hypertransport devices"
default y
- depends on PCI_MSI
depends on X86_LOCAL_APIC && X86_IO_APIC
help
This allows native hypertransport devices to use interrupts.
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 04694ec..e3beb78 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -17,6 +17,9 @@ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
# Build the PCI MSI interrupt support
obj-$(CONFIG_PCI_MSI) += msi.o
+# Build the Hypertransport interrupt support
+obj-$(CONFIG_HT_IRQ) += htirq.o
+
#
# Some architectures use the generic PCI setup functions
#
@@ -29,7 +32,6 @@ obj-$(CONFIG_PPC32) += setup-irq.o
obj-$(CONFIG_PPC64) += setup-bus.o
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
-obj-$(CONFIG_HT_IRQ) += htirq.o
#
# ACPI Related PCI FW Functions
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c
index 4ba4635..0e27f24 100644
--- a/drivers/pci/htirq.c
+++ b/drivers/pci/htirq.c
@@ -11,6 +11,7 @@ #include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/gfp.h>
+#include <linux/htirq.h>
/* Global ht irq lock.
*
diff --git a/include/linux/htirq.h b/include/linux/htirq.h
new file mode 100644
index 0000000..1f15ce2
--- /dev/null
+++ b/include/linux/htirq.h
@@ -0,0 +1,15 @@
+#ifndef LINUX_HTIRQ_H
+#define LINUX_HTIRQ_H
+
+/* Helper functions.. */
+void write_ht_irq_low(unsigned int irq, u32 data);
+void write_ht_irq_high(unsigned int irq, u32 data);
+u32 read_ht_irq_low(unsigned int irq);
+u32 read_ht_irq_high(unsigned int irq);
+void mask_ht_irq(unsigned int irq);
+void unmask_ht_irq(unsigned int irq);
+
+/* The arch hook for getting things started */
+int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev);
+
+#endif /* LINUX_HTIRQ_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9fa0740..5bc4659 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -619,20 +619,9 @@ extern void msi_remove_pci_irq_vectors(s
#endif
#ifdef CONFIG_HT_IRQ
-/* Helper functions.. */
-void write_ht_irq_low(unsigned int irq, u32 data);
-void write_ht_irq_high(unsigned int irq, u32 data);
-u32 read_ht_irq_low(unsigned int irq);
-u32 read_ht_irq_high(unsigned int irq);
-void mask_ht_irq(unsigned int irq);
-void unmask_ht_irq(unsigned int irq);
-
/* The functions a driver should call */
int ht_create_irq(struct pci_dev *dev, int idx);
void ht_destroy_irq(unsigned int irq);
-
-/* The arch hook for getting things started */
-int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev);
#endif /* CONFIG_HT_IRQ */
extern void pci_block_user_cfg_access(struct pci_dev *dev);
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 0/5] Message signaled irq handling cleanups
2006-09-27 19:55 [PATCH 0/5] Message signaled irq handling cleanups Eric W. Biederman
` (4 preceding siblings ...)
2006-09-27 19:58 ` [PATCH 5/5] htirq: Tidy up the htirq code Eric W. Biederman
@ 2006-09-27 20:29 ` Eric W. Biederman
2006-09-27 22:36 ` Benjamin Herrenschmidt
6 siblings, 0 replies; 13+ messages in thread
From: Eric W. Biederman @ 2006-09-27 20:29 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, Ingo Molnar, Luck, Tony, Andi Kleen,
Benjamin Herrenschmidt
ebiederm@xmission.com (Eric W. Biederman) writes:
> The following patch set should be enough to clear up the
> outstanding issues with genirq on i386 and x86_64. This actually
> takes things a step farther and moves all of architecture
> dependencies I could find into the appropriate architecture.
>
> So hopefully we are finally close enough that other architectures
> will be able implement msi support, without too much trouble.
>
> msi: Simplify msi sanity checks by adding with generic irq code.
> msi: Only use a single irq_chip for msi interrupts
> msi: Refactor and move the msi irq_chip into the arch code.
> msi: Move the ia64 code into arch/ia64
> htirq: Tidy up the htirq code
>
> Eric
Grr.. My ia64 compiler is way too slow. It just told me I had some
trivial bugs in the altix portion of what I posted. Sorry I forgot
to mention all I can do is compile test ia64.
So here comes a second time with code that actually compiles :)
Darn this code that is so ugly that you have to test the cleanup on
multiple architectures!
Eric
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 0/5] Message signaled irq handling cleanups
2006-09-27 19:55 [PATCH 0/5] Message signaled irq handling cleanups Eric W. Biederman
` (5 preceding siblings ...)
2006-09-27 20:29 ` [PATCH 0/5] Message signaled irq handling cleanups Eric W. Biederman
@ 2006-09-27 22:36 ` Benjamin Herrenschmidt
2006-09-27 22:51 ` Benjamin Herrenschmidt
6 siblings, 1 reply; 13+ messages in thread
From: Benjamin Herrenschmidt @ 2006-09-27 22:36 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Andrew Morton, linux-kernel, Ingo Molnar, Luck, Tony, Andi Kleen,
Michael Ellerman
> So hopefully we are finally close enough that other architectures
> will be able implement msi support, without too much trouble.
>
> msi: Simplify msi sanity checks by adding with generic irq code.
> msi: Only use a single irq_chip for msi interrupts
> msi: Refactor and move the msi irq_chip into the arch code.
> msi: Move the ia64 code into arch/ia64
> htirq: Tidy up the htirq code
Heh ! And Michael was just coming up with a rewritten MSI core for
PowerPC :) Oh well... I'll dig through your patches.
My main problem is that you have thus dynamic_irq stuff in the generic
code. I just can't see any way that code can apply to me in any shape or
form. PowerPC has a virtual IRQ layer that remaps linux IRQs to
controller/line pairs to handle multiple controllers etc... thus we have
some primitives for allocating virtual irqs and binding them to a
controller etc...
I have the feeling that this dynamic_irq_* thing you introduced will not
only not work properly for us but can't be made to work in our context,
not with the current API and not with any "generic" non platform
specific API.
Also we need to have different low level callbacks for different busses
in the system for the various bits, ranging from allocating & providing
up the irq_chip, to setting up the MSI. Unfortunately, even your
reworked code just don't fit our needs at the moment in that area. Also,
you hijack irq data which we can't do as it can/will be used by our PIC
code that actually gets the MSIs on some machines (they are just routed
to it as normal irqs) etc....
At this point, best is that we finish a working implementation based on
Michael reworked core for PowerPC (which is currently located in
arch/powerpc and doesn't exclude whatever sits in drivers/pci/ except
that we don't build the later on PowerPC) so you can see more what our
approach looks like and why we need to go that way.
Ben.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 0/5] Message signaled irq handling cleanups
2006-09-27 22:36 ` Benjamin Herrenschmidt
@ 2006-09-27 22:51 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 13+ messages in thread
From: Benjamin Herrenschmidt @ 2006-09-27 22:51 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Andrew Morton, linux-kernel, Ingo Molnar, Luck, Tony, Andi Kleen,
Michael Ellerman
> At this point, best is that we finish a working implementation based on
> Michael reworked core for PowerPC (which is currently located in
> arch/powerpc and doesn't exclude whatever sits in drivers/pci/ except
> that we don't build the later on PowerPC) so you can see more what our
> approach looks like and why we need to go that way.
Don't look for it in the tree btw, it's not beem merged, though Michael
posted some versions to linuxppc-dev.
Ben.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 0/5] Message signaled irq handling cleanups
2006-09-27 22:57 ` Andi Kleen
@ 2006-09-28 4:02 ` Eric W. Biederman
0 siblings, 0 replies; 13+ messages in thread
From: Eric W. Biederman @ 2006-09-28 4:02 UTC (permalink / raw)
To: Andi Kleen
Cc: Andrew Morton, linux-kernel, Ingo Molnar, Tony, Benjamin Herrenschmidt
Andi Kleen <ak@suse.de> writes:
> On Wednesday 27 September 2006 21:54, Eric W. Biederman wrote:
>>
>> The following patch set should be enough to clear up the
>> outstanding issues with genirq on i386 and x86_64. This actually
>> takes things a step farther and moves all of architecture
>> dependencies I could find into the appropriate architecture.
>>
>> So hopefully we are finally close enough that other architectures
>> will be able implement msi support, without too much trouble.
>>
>> msi: Simplify msi sanity checks by adding with generic irq code.
>> msi: Only use a single irq_chip for msi interrupts
>> msi: Refactor and move the msi irq_chip into the arch code.
>> msi: Move the ia64 code into arch/ia64
>> htirq: Tidy up the htirq code
>
>
> The (small) x86-64 parts are fine by me. Thanks.
Note this should allow the hack in -mm that disables stack switch
with 4K stacks on i386 to be dropped.
Eric
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 0/5] Message signaled irq handling cleanups
2006-09-27 19:54 Eric W. Biederman
@ 2006-09-27 22:57 ` Andi Kleen
2006-09-28 4:02 ` Eric W. Biederman
0 siblings, 1 reply; 13+ messages in thread
From: Andi Kleen @ 2006-09-27 22:57 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Andrew Morton, linux-kernel, Ingo Molnar, Tony, Benjamin Herrenschmidt
On Wednesday 27 September 2006 21:54, Eric W. Biederman wrote:
>
> The following patch set should be enough to clear up the
> outstanding issues with genirq on i386 and x86_64. This actually
> takes things a step farther and moves all of architecture
> dependencies I could find into the appropriate architecture.
>
> So hopefully we are finally close enough that other architectures
> will be able implement msi support, without too much trouble.
>
> msi: Simplify msi sanity checks by adding with generic irq code.
> msi: Only use a single irq_chip for msi interrupts
> msi: Refactor and move the msi irq_chip into the arch code.
> msi: Move the ia64 code into arch/ia64
> htirq: Tidy up the htirq code
The (small) x86-64 parts are fine by me. Thanks.
-Andi
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 0/5] Message signaled irq handling cleanups
@ 2006-09-27 19:54 Eric W. Biederman
0 siblings, 0 replies; 13+ messages in thread
From: Eric W. Biederman @ 2006-09-27 19:54 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, Ingo Molnar, Luck, Tony <tony.luck@intel.com>,
Andi Kleen, Benjamin Herrenschmidt
The following patch set should be enough to clear up the
outstanding issues with genirq on i386 and x86_64. This actually
takes things a step farther and moves all of architecture
dependencies I could find into the appropriate architecture.
So hopefully we are finally close enough that other architectures
will be able implement msi support, without too much trouble.
msi: Simplify msi sanity checks by adding with generic irq code.
msi: Only use a single irq_chip for msi interrupts
msi: Refactor and move the msi irq_chip into the arch code.
msi: Move the ia64 code into arch/ia64
htirq: Tidy up the htirq code
Eric
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 0/5] Message signaled irq handling cleanups
@ 2006-09-27 19:54 Eric W. Biederman
2006-09-27 22:57 ` Andi Kleen
0 siblings, 1 reply; 13+ messages in thread
From: Eric W. Biederman @ 2006-09-27 19:54 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, Ingo Molnar, Luck, Tony, Andi Kleen,
Benjamin Herrenschmidt
The following patch set should be enough to clear up the
outstanding issues with genirq on i386 and x86_64. This actually
takes things a step farther and moves all of architecture
dependencies I could find into the appropriate architecture.
So hopefully we are finally close enough that other architectures
will be able implement msi support, without too much trouble.
msi: Simplify msi sanity checks by adding with generic irq code.
msi: Only use a single irq_chip for msi interrupts
msi: Refactor and move the msi irq_chip into the arch code.
msi: Move the ia64 code into arch/ia64
htirq: Tidy up the htirq code
Eric
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2006-09-28 4:03 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-09-27 19:55 [PATCH 0/5] Message signaled irq handling cleanups Eric W. Biederman
2006-09-27 19:58 ` [PATCH 1/5] msi: Simplify msi sanity checks by adding with generic irq code Eric W. Biederman
2006-09-27 19:58 ` [PATCH 2/5] msi: Only use a single irq_chip for msi interrupts Eric W. Biederman
2006-09-27 19:58 ` [PATCH 3/5] msi: Refactor and move the msi irq_chip into the arch code Eric W. Biederman
2006-09-27 19:58 ` [PATCH 4/5] msi: Move the ia64 code into arch/ia64 Eric W. Biederman
2006-09-27 19:58 ` [PATCH 5/5] htirq: Tidy up the htirq code Eric W. Biederman
2006-09-27 20:29 ` [PATCH 0/5] Message signaled irq handling cleanups Eric W. Biederman
2006-09-27 22:36 ` Benjamin Herrenschmidt
2006-09-27 22:51 ` Benjamin Herrenschmidt
-- strict thread matches above, loose matches on Subject: below --
2006-09-27 19:54 Eric W. Biederman
2006-09-27 19:54 Eric W. Biederman
2006-09-27 22:57 ` Andi Kleen
2006-09-28 4:02 ` Eric W. Biederman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome