irq: change ->set_affinity() to return status
[deliverable/linux.git] / arch / ia64 / kernel / msi_ia64.c
CommitLineData
fd58e55f
MM
1/*
2 * MSI hooks for standard x86 apic
3 */
4
5#include <linux/pci.h>
6#include <linux/irq.h>
3b7d1921 7#include <linux/msi.h>
62fdd767 8#include <linux/dmar.h>
a4cffb64 9#include <asm/smp.h>
2fa8937f 10#include <asm/msidef.h>
fd58e55f 11
3b7d1921 12static struct irq_chip ia64_msi_chip;
fd58e55f 13
3b7d1921 14#ifdef CONFIG_SMP
d5dedd45 15static int ia64_set_msi_irq_affinity(unsigned int irq,
0de26520 16 const cpumask_t *cpu_mask)
fd58e55f 17{
3b7d1921 18 struct msi_msg msg;
cd378f18 19 u32 addr, data;
0de26520 20 int cpu = first_cpu(*cpu_mask);
3b7d1921 21
cd378f18 22 if (!cpu_online(cpu))
d5dedd45 23 return -1;
cd378f18 24
a6cd6322 25 if (irq_prepare_move(irq, cpu))
d5dedd45 26 return -1;
4994be1b 27
3b7d1921 28 read_msi_msg(irq, &msg);
fd58e55f 29
3b7d1921 30 addr = msg.address_lo;
2fa8937f
XZ
31 addr &= MSI_ADDR_DEST_ID_MASK;
32 addr |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
3b7d1921 33 msg.address_lo = addr;
fd58e55f 34
cd378f18
YI
35 data = msg.data;
36 data &= MSI_DATA_VECTOR_MASK;
37 data |= MSI_DATA_VECTOR(irq_to_vector(irq));
38 msg.data = data;
39
3b7d1921 40 write_msi_msg(irq, &msg);
e65e49d0 41 cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
d5dedd45
YL
42
43 return 0;
fd58e55f 44}
3b7d1921 45#endif /* CONFIG_SMP */
fd58e55f 46
f7feaca7 47int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
fd58e55f 48{
3b7d1921 49 struct msi_msg msg;
fd58e55f 50 unsigned long dest_phys_id;
8a3a0ee7 51 int irq, vector;
4994be1b 52 cpumask_t mask;
fd58e55f 53
f7feaca7
EB
54 irq = create_irq();
55 if (irq < 0)
56 return irq;
57
58 set_irq_msi(irq, desc);
4994be1b
YI
59 cpus_and(mask, irq_to_domain(irq), cpu_online_map);
60 dest_phys_id = cpu_physical_id(first_cpu(mask));
9438a121 61 vector = irq_to_vector(irq);
fd58e55f 62
3b7d1921
EB
63 msg.address_hi = 0;
64 msg.address_lo =
38bc0361 65 MSI_ADDR_HEADER |
2fa8937f 66 MSI_ADDR_DEST_MODE_PHYS |
38bc0361 67 MSI_ADDR_REDIRECTION_CPU |
2fa8937f 68 MSI_ADDR_DEST_ID_CPU(dest_phys_id);
fd58e55f 69
3b7d1921 70 msg.data =
38bc0361 71 MSI_DATA_TRIGGER_EDGE |
fd58e55f
MM
72 MSI_DATA_LEVEL_ASSERT |
73 MSI_DATA_DELIVERY_FIXED |
74 MSI_DATA_VECTOR(vector);
75
3b7d1921
EB
76 write_msi_msg(irq, &msg);
77 set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
78
3aff0373 79 return 0;
fd58e55f
MM
80}
81
3b7d1921 82void ia64_teardown_msi_irq(unsigned int irq)
fd58e55f 83{
f7feaca7 84 destroy_irq(irq);
fd58e55f
MM
85}
86
3b7d1921
EB
87static void ia64_ack_msi_irq(unsigned int irq)
88{
a6cd6322 89 irq_complete_move(irq);
3b7d1921
EB
90 move_native_irq(irq);
91 ia64_eoi();
92}
93
94static int ia64_msi_retrigger_irq(unsigned int irq)
95{
9438a121 96 unsigned int vector = irq_to_vector(irq);
3b7d1921
EB
97 ia64_resend_irq(vector);
98
99 return 1;
100}
101
fd58e55f 102/*
3b7d1921 103 * Generic ops used on most IA64 platforms.
fd58e55f 104 */
3b7d1921
EB
105static struct irq_chip ia64_msi_chip = {
106 .name = "PCI-MSI",
107 .mask = mask_msi_irq,
108 .unmask = unmask_msi_irq,
109 .ack = ia64_ack_msi_irq,
110#ifdef CONFIG_SMP
111 .set_affinity = ia64_set_msi_irq_affinity,
112#endif
113 .retrigger = ia64_msi_retrigger_irq,
fd58e55f 114};
3b7d1921
EB
115
116
f7feaca7 117int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
3b7d1921
EB
118{
119 if (platform_setup_msi_irq)
f7feaca7 120 return platform_setup_msi_irq(pdev, desc);
3b7d1921 121
f7feaca7 122 return ia64_setup_msi_irq(pdev, desc);
3b7d1921
EB
123}
124
125void arch_teardown_msi_irq(unsigned int irq)
126{
127 if (platform_teardown_msi_irq)
128 return platform_teardown_msi_irq(irq);
129
130 return ia64_teardown_msi_irq(irq);
131}
62fdd767
FY
132
133#ifdef CONFIG_DMAR
134#ifdef CONFIG_SMP
d5dedd45 135static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
62fdd767
FY
136{
137 struct irq_cfg *cfg = irq_cfg + irq;
138 struct msi_msg msg;
0de26520 139 int cpu = cpumask_first(mask);
62fdd767
FY
140
141 if (!cpu_online(cpu))
d5dedd45 142 return -1;
62fdd767
FY
143
144 if (irq_prepare_move(irq, cpu))
d5dedd45 145 return -1;
62fdd767
FY
146
147 dmar_msi_read(irq, &msg);
148
149 msg.data &= ~MSI_DATA_VECTOR_MASK;
150 msg.data |= MSI_DATA_VECTOR(cfg->vector);
2fa8937f
XZ
151 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
152 msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
62fdd767
FY
153
154 dmar_msi_write(irq, &msg);
e65e49d0 155 cpumask_copy(irq_desc[irq].affinity, mask);
d5dedd45
YL
156
157 return 0;
62fdd767
FY
158}
159#endif /* CONFIG_SMP */
160
161struct irq_chip dmar_msi_type = {
162 .name = "DMAR_MSI",
163 .unmask = dmar_msi_unmask,
164 .mask = dmar_msi_mask,
165 .ack = ia64_ack_msi_irq,
166#ifdef CONFIG_SMP
167 .set_affinity = dmar_msi_set_affinity,
168#endif
169 .retrigger = ia64_msi_retrigger_irq,
170};
171
172static int
173msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
174{
175 struct irq_cfg *cfg = irq_cfg + irq;
176 unsigned dest;
177 cpumask_t mask;
178
179 cpus_and(mask, irq_to_domain(irq), cpu_online_map);
180 dest = cpu_physical_id(first_cpu(mask));
181
182 msg->address_hi = 0;
183 msg->address_lo =
184 MSI_ADDR_HEADER |
2fa8937f 185 MSI_ADDR_DEST_MODE_PHYS |
62fdd767 186 MSI_ADDR_REDIRECTION_CPU |
2fa8937f 187 MSI_ADDR_DEST_ID_CPU(dest);
62fdd767
FY
188
189 msg->data =
190 MSI_DATA_TRIGGER_EDGE |
191 MSI_DATA_LEVEL_ASSERT |
192 MSI_DATA_DELIVERY_FIXED |
193 MSI_DATA_VECTOR(cfg->vector);
194 return 0;
195}
196
197int arch_setup_dmar_msi(unsigned int irq)
198{
199 int ret;
200 struct msi_msg msg;
201
202 ret = msi_compose_msg(NULL, irq, &msg);
203 if (ret < 0)
204 return ret;
205 dmar_msi_write(irq, &msg);
206 set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
207 "edge");
208 return 0;
209}
210#endif /* CONFIG_DMAR */
211
This page took 0.282721 seconds and 5 git commands to generate.