diff options
Diffstat (limited to 'arch/ia64/sn')
| -rw-r--r-- | arch/ia64/sn/kernel/irq.c | 97 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/msi_sn.c | 32 |
2 files changed, 44 insertions, 85 deletions
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 13c15d968098..7f399f9d99c7 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 | ||
| 26 | static void force_interrupt(int irq); | ||
| 27 | static void register_intr_pda(struct sn_irq_info *sn_irq_info); | 26 | static void register_intr_pda(struct sn_irq_info *sn_irq_info); |
| 28 | static void unregister_intr_pda(struct sn_irq_info *sn_irq_info); | 27 | static void unregister_intr_pda(struct sn_irq_info *sn_irq_info); |
| 29 | 28 | ||
| 30 | int sn_force_interrupt_flag = 1; | ||
| 31 | extern int sn_ioif_inited; | 29 | extern int sn_ioif_inited; |
| 32 | struct list_head **sn_irq_lh; | 30 | struct list_head **sn_irq_lh; |
| 33 | static DEFINE_SPINLOCK(sn_irq_info_lock); /* non-IRQ lock */ | 31 | static 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 | ||
| 81 | static unsigned int sn_startup_irq(unsigned int irq) | 79 | static unsigned int sn_startup_irq(struct irq_data *data) |
| 82 | { | 80 | { |
| 83 | return 0; | 81 | return 0; |
| 84 | } | 82 | } |
| 85 | 83 | ||
| 86 | static void sn_shutdown_irq(unsigned int irq) | 84 | static void sn_shutdown_irq(struct irq_data *data) |
| 87 | { | 85 | { |
| 88 | } | 86 | } |
| 89 | 87 | ||
| 90 | extern void ia64_mca_register_cpev(int); | 88 | extern void ia64_mca_register_cpev(int); |
| 91 | 89 | ||
| 92 | static void sn_disable_irq(unsigned int irq) | 90 | static 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 | ||
| 98 | static void sn_enable_irq(unsigned int irq) | 96 | static 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 | ||
| 104 | static void sn_ack_irq(unsigned int irq) | 102 | static 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 | |||
| 117 | static 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 | ||
| 139 | static void sn_irq_info_free(struct rcu_head *head); | 115 | static 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 | ||
| 231 | static int sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask) | 207 | static 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 | ||
| @@ -259,26 +237,25 @@ void sn_set_err_irq_affinity(unsigned int irq) { } | |||
| 259 | #endif | 237 | #endif |
| 260 | 238 | ||
| 261 | static void | 239 | static void |
| 262 | sn_mask_irq(unsigned int irq) | 240 | sn_mask_irq(struct irq_data *data) |
| 263 | { | 241 | { |
| 264 | } | 242 | } |
| 265 | 243 | ||
| 266 | static void | 244 | static void |
| 267 | sn_unmask_irq(unsigned int irq) | 245 | sn_unmask_irq(struct irq_data *data) |
| 268 | { | 246 | { |
| 269 | } | 247 | } |
| 270 | 248 | ||
| 271 | struct irq_chip irq_type_sn = { | 249 | struct 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 | ||
| 284 | ia64_vector sn_irq_to_vector(int irq) | 261 | ia64_vector sn_irq_to_vector(int irq) |
| @@ -296,15 +273,13 @@ unsigned int sn_local_vector_to_irq(u8 vector) | |||
| 296 | void sn_irq_init(void) | 273 | void 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(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 | ||
| 447 | static 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 |
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c index a5e500f02853..2b98b9e088de 100644 --- a/arch/ia64/sn/kernel/msi_sn.c +++ b/arch/ia64/sn/kernel/msi_sn.c | |||
| @@ -144,16 +144,16 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) | |||
| 144 | */ | 144 | */ |
| 145 | msg.data = 0x100 + irq; | 145 | msg.data = 0x100 + irq; |
| 146 | 146 | ||
| 147 | set_irq_msi(irq, entry); | 147 | irq_set_msi_desc(irq, entry); |
| 148 | write_msi_msg(irq, &msg); | 148 | write_msi_msg(irq, &msg); |
| 149 | set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq); | 149 | irq_set_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq); |
| 150 | 150 | ||
| 151 | return 0; | 151 | return 0; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | #ifdef CONFIG_SMP | 154 | #ifdef CONFIG_SMP |
| 155 | static int sn_set_msi_irq_affinity(unsigned int irq, | 155 | static int sn_set_msi_irq_affinity(struct irq_data *data, |
| 156 | const struct cpumask *cpu_mask) | 156 | const struct cpumask *cpu_mask, bool force) |
| 157 | { | 157 | { |
| 158 | struct msi_msg msg; | 158 | struct msi_msg msg; |
| 159 | int slice; | 159 | int slice; |
| @@ -164,7 +164,7 @@ static int sn_set_msi_irq_affinity(unsigned int irq, | |||
| 164 | struct sn_irq_info *sn_irq_info; | 164 | struct sn_irq_info *sn_irq_info; |
| 165 | struct sn_irq_info *new_irq_info; | 165 | struct sn_irq_info *new_irq_info; |
| 166 | struct sn_pcibus_provider *provider; | 166 | struct sn_pcibus_provider *provider; |
| 167 | unsigned int cpu; | 167 | unsigned int cpu, irq = data->irq; |
| 168 | 168 | ||
| 169 | cpu = cpumask_first(cpu_mask); | 169 | cpu = cpumask_first(cpu_mask); |
| 170 | sn_irq_info = sn_msi_info[irq].sn_irq_info; | 170 | sn_irq_info = sn_msi_info[irq].sn_irq_info; |
| @@ -206,33 +206,33 @@ static int sn_set_msi_irq_affinity(unsigned int irq, | |||
| 206 | msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff); | 206 | msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff); |
| 207 | 207 | ||
| 208 | write_msi_msg(irq, &msg); | 208 | write_msi_msg(irq, &msg); |
| 209 | cpumask_copy(irq_desc[irq].affinity, cpu_mask); | 209 | cpumask_copy(data->affinity, cpu_mask); |
| 210 | 210 | ||
| 211 | return 0; | 211 | return 0; |
| 212 | } | 212 | } |
| 213 | #endif /* CONFIG_SMP */ | 213 | #endif /* CONFIG_SMP */ |
| 214 | 214 | ||
| 215 | static void sn_ack_msi_irq(unsigned int irq) | 215 | static void sn_ack_msi_irq(struct irq_data *data) |
| 216 | { | 216 | { |
| 217 | move_native_irq(irq); | 217 | irq_move_irq(data); |
| 218 | ia64_eoi(); | 218 | ia64_eoi(); |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | static int sn_msi_retrigger_irq(unsigned int irq) | 221 | static int sn_msi_retrigger_irq(struct irq_data *data) |
| 222 | { | 222 | { |
| 223 | unsigned int vector = irq; | 223 | unsigned int vector = data->irq; |
| 224 | ia64_resend_irq(vector); | 224 | ia64_resend_irq(vector); |
| 225 | 225 | ||
| 226 | return 1; | 226 | return 1; |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | static struct irq_chip sn_msi_chip = { | 229 | static struct irq_chip sn_msi_chip = { |
| 230 | .name = "PCI-MSI", | 230 | .name = "PCI-MSI", |
| 231 | .irq_mask = mask_msi_irq, | 231 | .irq_mask = mask_msi_irq, |
| 232 | .irq_unmask = unmask_msi_irq, | 232 | .irq_unmask = unmask_msi_irq, |
| 233 | .ack = sn_ack_msi_irq, | 233 | .irq_ack = sn_ack_msi_irq, |
| 234 | #ifdef CONFIG_SMP | 234 | #ifdef CONFIG_SMP |
| 235 | .set_affinity = sn_set_msi_irq_affinity, | 235 | .irq_set_affinity = sn_set_msi_irq_affinity, |
| 236 | #endif | 236 | #endif |
| 237 | .retrigger = sn_msi_retrigger_irq, | 237 | .irq_retrigger = sn_msi_retrigger_irq, |
| 238 | }; | 238 | }; |
