aboutsummaryrefslogtreecommitdiffstats
path: root/arch
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
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')
-rw-r--r--arch/i386/kernel/io_apic.c81
-rw-r--r--arch/x86_64/kernel/io_apic.c89
2 files changed, 120 insertions, 50 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/*
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 31c270fee337..e55028fba942 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -30,6 +30,7 @@
30#include <linux/mc146818rtc.h> 30#include <linux/mc146818rtc.h>
31#include <linux/acpi.h> 31#include <linux/acpi.h>
32#include <linux/sysdev.h> 32#include <linux/sysdev.h>
33#include <linux/msi.h>
33#ifdef CONFIG_ACPI 34#ifdef CONFIG_ACPI
34#include <acpi/acpi_bus.h> 35#include <acpi/acpi_bus.h>
35#endif 36#endif
@@ -1701,11 +1702,8 @@ void destroy_irq(unsigned int irq)
1701 * MSI mesage composition 1702 * MSI mesage composition
1702 */ 1703 */
1703#ifdef CONFIG_PCI_MSI 1704#ifdef CONFIG_PCI_MSI
1704static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) 1705static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
1705{ 1706{
1706 /* For now always this code always uses physical delivery
1707 * mode.
1708 */
1709 int vector; 1707 int vector;
1710 unsigned dest; 1708 unsigned dest;
1711 1709
@@ -1739,39 +1737,76 @@ static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg
1739 return vector; 1737 return vector;
1740} 1738}
1741 1739
1742static void msi_msg_teardown(unsigned int irq) 1740#ifdef CONFIG_SMP
1743{ 1741static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
1744 return;
1745}
1746
1747static void msi_msg_set_affinity(unsigned int irq, cpumask_t mask, struct msi_msg *msg)
1748{ 1742{
1743 struct msi_msg msg;
1744 unsigned int dest;
1745 cpumask_t tmp;
1749 int vector; 1746 int vector;
1750 unsigned dest; 1747
1748 cpus_and(tmp, mask, cpu_online_map);
1749 if (cpus_empty(tmp))
1750 tmp = TARGET_CPUS;
1751
1752 cpus_and(mask, tmp, CPU_MASK_ALL);
1751 1753
1752 vector = assign_irq_vector(irq, mask); 1754 vector = assign_irq_vector(irq, mask);
1753 if (vector > 0) { 1755 if (vector < 0)
1754 cpumask_t tmp; 1756 return;
1755 1757
1756 cpus_clear(tmp); 1758 cpus_clear(tmp);
1757 cpu_set(vector >> 8, tmp); 1759 cpu_set(vector >> 8, tmp);
1758 dest = cpu_mask_to_apicid(tmp); 1760 dest = cpu_mask_to_apicid(tmp);
1759 1761
1760 msg->data &= ~MSI_DATA_VECTOR_MASK; 1762 read_msi_msg(irq, &msg);
1761 msg->data |= MSI_DATA_VECTOR(vector); 1763
1762 msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK; 1764 msg.data &= ~MSI_DATA_VECTOR_MASK;
1763 msg->address_lo |= MSI_ADDR_DEST_ID(dest); 1765 msg.data |= MSI_DATA_VECTOR(vector);
1764 } 1766 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
1767 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
1768
1769 write_msi_msg(irq, &msg);
1770 set_native_irq_info(irq, mask);
1765} 1771}
1772#endif /* CONFIG_SMP */
1766 1773
1767struct msi_ops arch_msi_ops = { 1774/*
1768 .needs_64bit_address = 0, 1775 * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
1769 .setup = msi_msg_setup, 1776 * which implement the MSI or MSI-X Capability Structure.
1770 .teardown = msi_msg_teardown, 1777 */
1771 .target = msi_msg_set_affinity, 1778static struct irq_chip msi_chip = {
1779 .name = "PCI-MSI",
1780 .unmask = unmask_msi_irq,
1781 .mask = mask_msi_irq,
1782 .ack = ack_apic_edge,
1783#ifdef CONFIG_SMP
1784 .set_affinity = set_msi_irq_affinity,
1785#endif
1786 .retrigger = ioapic_retrigger_irq,
1772}; 1787};
1773 1788
1774#endif 1789int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
1790{
1791 struct msi_msg msg;
1792 int ret;
1793 ret = msi_compose_msg(dev, irq, &msg);
1794 if (ret < 0)
1795 return ret;
1796
1797 write_msi_msg(irq, &msg);
1798
1799 set_irq_chip_and_handler(irq, &msi_chip, handle_edge_irq);
1800
1801 return 0;
1802}
1803
1804void arch_teardown_msi_irq(unsigned int irq)
1805{
1806 return;
1807}
1808
1809#endif /* CONFIG_PCI_MSI */
1775 1810
1776/* 1811/*
1777 * Hypertransport interrupt support 1812 * Hypertransport interrupt support