aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/io_apic.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-04 05:16:59 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:29 -0400
commit3b7d1921f4cdd6d6ddb7899ae7a8d413991c5cf4 (patch)
tree5f809e0c4310f60dfa6f65d54fbaf9f01e2ebff9 /arch/i386/kernel/io_apic.c
parent277bc33bc2479707e88b0b2ae6fe56e8e4aabe81 (diff)
[PATCH] msi: refactor and move the msi irq_chip into the arch code
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> Cc: Ingo Molnar <mingo@elte.hu> Cc: Tony Luck <tony.luck@intel.com> Cc: Andi Kleen <ak@suse.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Greg KH <greg@kroah.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/io_apic.c')
-rw-r--r--arch/i386/kernel/io_apic.c81
1 files changed, 58 insertions, 23 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 100406b453b8..5a1252753dbb 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -32,6 +32,7 @@
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/sysdev.h> 33#include <linux/sysdev.h>
34#include <linux/pci.h> 34#include <linux/pci.h>
35#include <linux/msi.h>
35 36
36#include <asm/io.h> 37#include <asm/io.h>
37#include <asm/smp.h> 38#include <asm/smp.h>
@@ -2455,11 +2456,8 @@ void destroy_irq(unsigned int irq)
2455 * MSI mesage composition 2456 * MSI mesage composition
2456 */ 2457 */
2457#ifdef CONFIG_PCI_MSI 2458#ifdef CONFIG_PCI_MSI
2458static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) 2459static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
2459{ 2460{
2460 /* For now always this code always uses physical delivery
2461 * mode.
2462 */
2463 int vector; 2461 int vector;
2464 unsigned dest; 2462 unsigned dest;
2465 2463
@@ -2489,34 +2487,71 @@ static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg
2489 return vector; 2487 return vector;
2490} 2488}
2491 2489
2492static void msi_msg_teardown(unsigned int irq) 2490#ifdef CONFIG_SMP
2493{ 2491static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
2494 return;
2495}
2496
2497static void msi_msg_set_affinity(unsigned int irq, cpumask_t mask, struct msi_msg *msg)
2498{ 2492{
2493 struct msi_msg msg;
2494 unsigned int dest;
2495 cpumask_t tmp;
2499 int vector; 2496 int vector;
2500 unsigned dest; 2497
2498 cpus_and(tmp, mask, cpu_online_map);
2499 if (cpus_empty(tmp))
2500 tmp = TARGET_CPUS;
2501 2501
2502 vector = assign_irq_vector(irq); 2502 vector = assign_irq_vector(irq);
2503 if (vector > 0) { 2503 if (vector < 0)
2504 dest = cpu_mask_to_apicid(mask); 2504 return;
2505 2505
2506 msg->data &= ~MSI_DATA_VECTOR_MASK; 2506 dest = cpu_mask_to_apicid(mask);
2507 msg->data |= MSI_DATA_VECTOR(vector); 2507
2508 msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK; 2508 read_msi_msg(irq, &msg);
2509 msg->address_lo |= MSI_ADDR_DEST_ID(dest); 2509
2510 } 2510 msg.data &= ~MSI_DATA_VECTOR_MASK;
2511 msg.data |= MSI_DATA_VECTOR(vector);
2512 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
2513 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
2514
2515 write_msi_msg(irq, &msg);
2516 set_native_irq_info(irq, mask);
2511} 2517}
2518#endif /* CONFIG_SMP */
2512 2519
2513struct msi_ops arch_msi_ops = { 2520/*
2514 .needs_64bit_address = 0, 2521 * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
2515 .setup = msi_msg_setup, 2522 * which implement the MSI or MSI-X Capability Structure.
2516 .teardown = msi_msg_teardown, 2523 */
2517 .target = msi_msg_set_affinity, 2524static struct irq_chip msi_chip = {
2525 .name = "PCI-MSI",
2526 .unmask = unmask_msi_irq,
2527 .mask = mask_msi_irq,
2528 .ack = ack_ioapic_irq,
2529#ifdef CONFIG_SMP
2530 .set_affinity = set_msi_irq_affinity,
2531#endif
2532 .retrigger = ioapic_retrigger_irq,
2518}; 2533};
2519 2534
2535int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
2536{
2537 struct msi_msg msg;
2538 int ret;
2539 ret = msi_compose_msg(dev, irq, &msg);
2540 if (ret < 0)
2541 return ret;
2542
2543 write_msi_msg(irq, &msg);
2544
2545 set_irq_chip_and_handler(irq, &msi_chip, handle_edge_irq);
2546
2547 return 0;
2548}
2549
2550void arch_teardown_msi_irq(unsigned int irq)
2551{
2552 return;
2553}
2554
2520#endif /* CONFIG_PCI_MSI */ 2555#endif /* CONFIG_PCI_MSI */
2521 2556
2522/* 2557/*