aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/io_apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel/io_apic.c')
-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 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