diff options
Diffstat (limited to 'arch/x86_64/kernel/io_apic.c')
-rw-r--r-- | arch/x86_64/kernel/io_apic.c | 89 |
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 |
1704 | static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) | 1705 | static 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 | ||
1742 | static void msi_msg_teardown(unsigned int irq) | 1740 | #ifdef CONFIG_SMP |
1743 | { | 1741 | static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask) |
1744 | return; | ||
1745 | } | ||
1746 | |||
1747 | static 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 | ||
1767 | struct 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, | 1778 | static 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 | 1789 | int 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 | |||
1804 | void 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 |