aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn/kernel/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/sn/kernel/irq.c')
-rw-r--r--arch/ia64/sn/kernel/irq.c101
1 files changed, 30 insertions, 71 deletions
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 13c15d968098..81a1f4e6bcd8 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -23,11 +23,9 @@
23#include <asm/sn/sn_sal.h> 23#include <asm/sn/sn_sal.h>
24#include <asm/sn/sn_feature_sets.h> 24#include <asm/sn/sn_feature_sets.h>
25 25
26static void force_interrupt(int irq);
27static void register_intr_pda(struct sn_irq_info *sn_irq_info); 26static void register_intr_pda(struct sn_irq_info *sn_irq_info);
28static void unregister_intr_pda(struct sn_irq_info *sn_irq_info); 27static void unregister_intr_pda(struct sn_irq_info *sn_irq_info);
29 28
30int sn_force_interrupt_flag = 1;
31extern int sn_ioif_inited; 29extern int sn_ioif_inited;
32struct list_head **sn_irq_lh; 30struct list_head **sn_irq_lh;
33static DEFINE_SPINLOCK(sn_irq_info_lock); /* non-IRQ lock */ 31static DEFINE_SPINLOCK(sn_irq_info_lock); /* non-IRQ lock */
@@ -78,62 +76,40 @@ u64 sn_intr_redirect(nasid_t local_nasid, int local_widget,
78 return ret_stuff.status; 76 return ret_stuff.status;
79} 77}
80 78
81static unsigned int sn_startup_irq(unsigned int irq) 79static unsigned int sn_startup_irq(struct irq_data *data)
82{ 80{
83 return 0; 81 return 0;
84} 82}
85 83
86static void sn_shutdown_irq(unsigned int irq) 84static void sn_shutdown_irq(struct irq_data *data)
87{ 85{
88} 86}
89 87
90extern void ia64_mca_register_cpev(int); 88extern void ia64_mca_register_cpev(int);
91 89
92static void sn_disable_irq(unsigned int irq) 90static void sn_disable_irq(struct irq_data *data)
93{ 91{
94 if (irq == local_vector_to_irq(IA64_CPE_VECTOR)) 92 if (data->irq == local_vector_to_irq(IA64_CPE_VECTOR))
95 ia64_mca_register_cpev(0); 93 ia64_mca_register_cpev(0);
96} 94}
97 95
98static void sn_enable_irq(unsigned int irq) 96static void sn_enable_irq(struct irq_data *data)
99{ 97{
100 if (irq == local_vector_to_irq(IA64_CPE_VECTOR)) 98 if (data->irq == local_vector_to_irq(IA64_CPE_VECTOR))
101 ia64_mca_register_cpev(irq); 99 ia64_mca_register_cpev(data->irq);
102} 100}
103 101
104static void sn_ack_irq(unsigned int irq) 102static void sn_ack_irq(struct irq_data *data)
105{ 103{
106 u64 event_occurred, mask; 104 u64 event_occurred, mask;
105 unsigned int irq = data->irq & 0xff;
107 106
108 irq = irq & 0xff;
109 event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)); 107 event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED));
110 mask = event_occurred & SH_ALL_INT_MASK; 108 mask = event_occurred & SH_ALL_INT_MASK;
111 HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask); 109 HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask);
112 __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); 110 __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
113 111
114 move_native_irq(irq); 112 irq_move_irq(data);
115}
116
117static void sn_end_irq(unsigned int irq)
118{
119 int ivec;
120 u64 event_occurred;
121
122 ivec = irq & 0xff;
123 if (ivec == SGI_UART_VECTOR) {
124 event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR (SH_EVENT_OCCURRED));
125 /* If the UART bit is set here, we may have received an
126 * interrupt from the UART that the driver missed. To
127 * make sure, we IPI ourselves to force us to look again.
128 */
129 if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
130 platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR,
131 IA64_IPI_DM_INT, 0);
132 }
133 }
134 __clear_bit(ivec, (volatile void *)pda->sn_in_service_ivecs);
135 if (sn_force_interrupt_flag)
136 force_interrupt(irq);
137} 113}
138 114
139static void sn_irq_info_free(struct rcu_head *head); 115static void sn_irq_info_free(struct rcu_head *head);
@@ -228,9 +204,11 @@ finish_up:
228 return new_irq_info; 204 return new_irq_info;
229} 205}
230 206
231static int sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask) 207static int sn_set_affinity_irq(struct irq_data *data,
208 const struct cpumask *mask, bool force)
232{ 209{
233 struct sn_irq_info *sn_irq_info, *sn_irq_info_safe; 210 struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
211 unsigned int irq = data->irq;
234 nasid_t nasid; 212 nasid_t nasid;
235 int slice; 213 int slice;
236 214
@@ -249,7 +227,7 @@ void sn_set_err_irq_affinity(unsigned int irq)
249{ 227{
250 /* 228 /*
251 * On systems which support CPU disabling (SHub2), all error interrupts 229 * On systems which support CPU disabling (SHub2), all error interrupts
252 * are targetted at the boot CPU. 230 * are targeted at the boot CPU.
253 */ 231 */
254 if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT)) 232 if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT))
255 set_irq_affinity_info(irq, cpu_physical_id(0), 0); 233 set_irq_affinity_info(irq, cpu_physical_id(0), 0);
@@ -259,26 +237,25 @@ void sn_set_err_irq_affinity(unsigned int irq) { }
259#endif 237#endif
260 238
261static void 239static void
262sn_mask_irq(unsigned int irq) 240sn_mask_irq(struct irq_data *data)
263{ 241{
264} 242}
265 243
266static void 244static void
267sn_unmask_irq(unsigned int irq) 245sn_unmask_irq(struct irq_data *data)
268{ 246{
269} 247}
270 248
271struct irq_chip irq_type_sn = { 249struct irq_chip irq_type_sn = {
272 .name = "SN hub", 250 .name = "SN hub",
273 .startup = sn_startup_irq, 251 .irq_startup = sn_startup_irq,
274 .shutdown = sn_shutdown_irq, 252 .irq_shutdown = sn_shutdown_irq,
275 .enable = sn_enable_irq, 253 .irq_enable = sn_enable_irq,
276 .disable = sn_disable_irq, 254 .irq_disable = sn_disable_irq,
277 .ack = sn_ack_irq, 255 .irq_ack = sn_ack_irq,
278 .end = sn_end_irq, 256 .irq_mask = sn_mask_irq,
279 .mask = sn_mask_irq, 257 .irq_unmask = sn_unmask_irq,
280 .unmask = sn_unmask_irq, 258 .irq_set_affinity = sn_set_affinity_irq
281 .set_affinity = sn_set_affinity_irq
282}; 259};
283 260
284ia64_vector sn_irq_to_vector(int irq) 261ia64_vector sn_irq_to_vector(int irq)
@@ -296,15 +273,13 @@ unsigned int sn_local_vector_to_irq(u8 vector)
296void sn_irq_init(void) 273void sn_irq_init(void)
297{ 274{
298 int i; 275 int i;
299 struct irq_desc *base_desc = irq_desc;
300 276
301 ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR; 277 ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR;
302 ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR; 278 ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR;
303 279
304 for (i = 0; i < NR_IRQS; i++) { 280 for (i = 0; i < NR_IRQS; i++) {
305 if (base_desc[i].chip == &no_irq_chip) { 281 if (irq_get_chip(i) == &no_irq_chip)
306 base_desc[i].chip = &irq_type_sn; 282 irq_set_chip(i, &irq_type_sn);
307 }
308 } 283 }
309} 284}
310 285
@@ -378,7 +353,6 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
378 int cpu = nasid_slice_to_cpuid(nasid, slice); 353 int cpu = nasid_slice_to_cpuid(nasid, slice);
379#ifdef CONFIG_SMP 354#ifdef CONFIG_SMP
380 int cpuphys; 355 int cpuphys;
381 struct irq_desc *desc;
382#endif 356#endif
383 357
384 pci_dev_get(pci_dev); 358 pci_dev_get(pci_dev);
@@ -395,12 +369,11 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
395#ifdef CONFIG_SMP 369#ifdef CONFIG_SMP
396 cpuphys = cpu_physical_id(cpu); 370 cpuphys = cpu_physical_id(cpu);
397 set_irq_affinity_info(sn_irq_info->irq_irq, cpuphys, 0); 371 set_irq_affinity_info(sn_irq_info->irq_irq, cpuphys, 0);
398 desc = irq_to_desc(sn_irq_info->irq_irq);
399 /* 372 /*
400 * Affinity was set by the PROM, prevent it from 373 * Affinity was set by the PROM, prevent it from
401 * being reset by the request_irq() path. 374 * being reset by the request_irq() path.
402 */ 375 */
403 desc->status |= IRQ_AFFINITY_SET; 376 irqd_mark_affinity_was_set(irq_get_irq_data(sn_irq_info->irq_irq));
404#endif 377#endif
405} 378}
406 379
@@ -439,25 +412,11 @@ sn_call_force_intr_provider(struct sn_irq_info *sn_irq_info)
439 pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type]; 412 pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type];
440 413
441 /* Don't force an interrupt if the irq has been disabled */ 414 /* Don't force an interrupt if the irq has been disabled */
442 if (!(irq_desc[sn_irq_info->irq_irq].status & IRQ_DISABLED) && 415 if (!irqd_irq_disabled(irq_get_irq_data(sn_irq_info->irq_irq)) &&
443 pci_provider && pci_provider->force_interrupt) 416 pci_provider && pci_provider->force_interrupt)
444 (*pci_provider->force_interrupt)(sn_irq_info); 417 (*pci_provider->force_interrupt)(sn_irq_info);
445} 418}
446 419
447static void force_interrupt(int irq)
448{
449 struct sn_irq_info *sn_irq_info;
450
451 if (!sn_ioif_inited)
452 return;
453
454 rcu_read_lock();
455 list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list)
456 sn_call_force_intr_provider(sn_irq_info);
457
458 rcu_read_unlock();
459}
460
461/* 420/*
462 * Check for lost interrupts. If the PIC int_status reg. says that 421 * Check for lost interrupts. If the PIC int_status reg. says that
463 * an interrupt has been sent, but not handled, and the interrupt 422 * an interrupt has been sent, but not handled, and the interrupt
@@ -476,7 +435,7 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
476 /* 435 /*
477 * Bridge types attached to TIO (anything but PIC) do not need this WAR 436 * Bridge types attached to TIO (anything but PIC) do not need this WAR
478 * since they do not target Shub II interrupt registers. If that 437 * since they do not target Shub II interrupt registers. If that
479 * ever changes, this check needs to accomodate. 438 * ever changes, this check needs to accommodate.
480 */ 439 */
481 if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_PIC) 440 if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_PIC)
482 return; 441 return;