aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel
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/x86_64/kernel
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/x86_64/kernel')
-rw-r--r--arch/x86_64/kernel/io_apic.c89
1 files changed, 62 insertions, 27 deletions
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 31c270fee33..e55028fba94 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