aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/msi-apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/msi-apic.c')
-rw-r--r--drivers/pci/msi-apic.c86
1 files changed, 64 insertions, 22 deletions
diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c
index afc0ed13aa89..822e59a1b822 100644
--- a/drivers/pci/msi-apic.c
+++ b/drivers/pci/msi-apic.c
@@ -4,10 +4,9 @@
4 4
5#include <linux/pci.h> 5#include <linux/pci.h>
6#include <linux/irq.h> 6#include <linux/irq.h>
7#include <linux/msi.h>
7#include <asm/smp.h> 8#include <asm/smp.h>
8 9
9#include "msi.h"
10
11/* 10/*
12 * Shifts for APIC-based data 11 * Shifts for APIC-based data
13 */ 12 */
@@ -31,6 +30,7 @@
31 * Shift/mask fields for APIC-based bus address 30 * Shift/mask fields for APIC-based bus address
32 */ 31 */
33 32
33#define MSI_TARGET_CPU_SHIFT 4
34#define MSI_ADDR_HEADER 0xfee00000 34#define MSI_ADDR_HEADER 0xfee00000
35 35
36#define MSI_ADDR_DESTID_MASK 0xfff0000f 36#define MSI_ADDR_DESTID_MASK 0xfff0000f
@@ -44,58 +44,100 @@
44#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) 44#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
45#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) 45#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
46 46
47static struct irq_chip ia64_msi_chip;
47 48
48static void 49#ifdef CONFIG_SMP
49msi_target_apic(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg) 50static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
50{ 51{
51 u32 addr = msg->address_lo; 52 struct msi_msg msg;
53 u32 addr;
54
55 read_msi_msg(irq, &msg);
52 56
57 addr = msg.address_lo;
53 addr &= MSI_ADDR_DESTID_MASK; 58 addr &= MSI_ADDR_DESTID_MASK;
54 addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask))); 59 addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask)));
60 msg.address_lo = addr;
55 61
56 msg->address_lo = addr; 62 write_msi_msg(irq, &msg);
63 set_native_irq_info(irq, cpu_mask);
57} 64}
65#endif /* CONFIG_SMP */
58 66
59static int 67int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
60msi_setup_apic(struct pci_dev *pdev, /* unused in generic */
61 unsigned int irq,
62 struct msi_msg *msg)
63{ 68{
69 struct msi_msg msg;
64 unsigned long dest_phys_id; 70 unsigned long dest_phys_id;
65 unsigned int vector; 71 unsigned int vector;
66 72
67 dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); 73 dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
68 vector = irq; 74 vector = irq;
69 75
70 msg->address_hi = 0; 76 msg.address_hi = 0;
71 msg->address_lo = 77 msg.address_lo =
72 MSI_ADDR_HEADER | 78 MSI_ADDR_HEADER |
73 MSI_ADDR_DESTMODE_PHYS | 79 MSI_ADDR_DESTMODE_PHYS |
74 MSI_ADDR_REDIRECTION_CPU | 80 MSI_ADDR_REDIRECTION_CPU |
75 MSI_ADDR_DESTID_CPU(dest_phys_id); 81 MSI_ADDR_DESTID_CPU(dest_phys_id);
76 82
77 msg->data = 83 msg.data =
78 MSI_DATA_TRIGGER_EDGE | 84 MSI_DATA_TRIGGER_EDGE |
79 MSI_DATA_LEVEL_ASSERT | 85 MSI_DATA_LEVEL_ASSERT |
80 MSI_DATA_DELIVERY_FIXED | 86 MSI_DATA_DELIVERY_FIXED |
81 MSI_DATA_VECTOR(vector); 87 MSI_DATA_VECTOR(vector);
82 88
89 write_msi_msg(irq, &msg);
90 set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
91
83 return 0; 92 return 0;
84} 93}
85 94
86static void 95void ia64_teardown_msi_irq(unsigned int irq)
87msi_teardown_apic(unsigned int irq)
88{ 96{
89 return; /* no-op */ 97 return; /* no-op */
90} 98}
91 99
100static void ia64_ack_msi_irq(unsigned int irq)
101{
102 move_native_irq(irq);
103 ia64_eoi();
104}
105
106static int ia64_msi_retrigger_irq(unsigned int irq)
107{
108 unsigned int vector = irq;
109 ia64_resend_irq(vector);
110
111 return 1;
112}
113
92/* 114/*
93 * Generic ops used on most IA archs/platforms. Set with msi_register() 115 * Generic ops used on most IA64 platforms.
94 */ 116 */
95 117static struct irq_chip ia64_msi_chip = {
96struct msi_ops msi_apic_ops = { 118 .name = "PCI-MSI",
97 .needs_64bit_address = 0, 119 .mask = mask_msi_irq,
98 .setup = msi_setup_apic, 120 .unmask = unmask_msi_irq,
99 .teardown = msi_teardown_apic, 121 .ack = ia64_ack_msi_irq,
100 .target = msi_target_apic, 122#ifdef CONFIG_SMP
123 .set_affinity = ia64_set_msi_irq_affinity,
124#endif
125 .retrigger = ia64_msi_retrigger_irq,
101}; 126};
127
128
129int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
130{
131 if (platform_setup_msi_irq)
132 return platform_setup_msi_irq(irq, pdev);
133
134 return ia64_setup_msi_irq(irq, pdev);
135}
136
137void arch_teardown_msi_irq(unsigned int irq)
138{
139 if (platform_teardown_msi_irq)
140 return platform_teardown_msi_irq(irq);
141
142 return ia64_teardown_msi_irq(irq);
143}