aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/irq.c')
-rw-r--r--arch/sparc64/kernel/irq.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 6b6165d36fd8..8cb3358674f5 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -293,6 +293,11 @@ static void sun4u_irq_enable(unsigned int virt_irq)
293 } 293 }
294} 294}
295 295
296static void sun4u_set_affinity(unsigned int virt_irq, cpumask_t mask)
297{
298 sun4u_irq_enable(virt_irq);
299}
300
296static void sun4u_irq_disable(unsigned int virt_irq) 301static void sun4u_irq_disable(unsigned int virt_irq)
297{ 302{
298 struct irq_handler_data *data = get_irq_chip_data(virt_irq); 303 struct irq_handler_data *data = get_irq_chip_data(virt_irq);
@@ -309,6 +314,10 @@ static void sun4u_irq_disable(unsigned int virt_irq)
309static void sun4u_irq_end(unsigned int virt_irq) 314static void sun4u_irq_end(unsigned int virt_irq)
310{ 315{
311 struct irq_handler_data *data = get_irq_chip_data(virt_irq); 316 struct irq_handler_data *data = get_irq_chip_data(virt_irq);
317 struct irq_desc *desc = irq_desc + virt_irq;
318
319 if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
320 return;
312 321
313 if (likely(data)) 322 if (likely(data))
314 upa_writeq(ICLR_IDLE, data->iclr); 323 upa_writeq(ICLR_IDLE, data->iclr);
@@ -340,6 +349,24 @@ static void sun4v_irq_enable(unsigned int virt_irq)
340 } 349 }
341} 350}
342 351
352static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask)
353{
354 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
355 unsigned int ino = bucket - &ivector_table[0];
356
357 if (likely(bucket)) {
358 unsigned long cpuid;
359 int err;
360
361 cpuid = irq_choose_cpu(virt_irq);
362
363 err = sun4v_intr_settarget(ino, cpuid);
364 if (err != HV_EOK)
365 printk("sun4v_intr_settarget(%x,%lu): err(%d)\n",
366 ino, cpuid, err);
367 }
368}
369
343static void sun4v_irq_disable(unsigned int virt_irq) 370static void sun4v_irq_disable(unsigned int virt_irq)
344{ 371{
345 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); 372 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
@@ -373,6 +400,10 @@ static void sun4v_irq_end(unsigned int virt_irq)
373{ 400{
374 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); 401 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
375 unsigned int ino = bucket - &ivector_table[0]; 402 unsigned int ino = bucket - &ivector_table[0];
403 struct irq_desc *desc = irq_desc + virt_irq;
404
405 if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
406 return;
376 407
377 if (likely(bucket)) { 408 if (likely(bucket)) {
378 int err; 409 int err;
@@ -418,6 +449,28 @@ static void sun4v_virq_enable(unsigned int virt_irq)
418 } 449 }
419} 450}
420 451
452static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
453{
454 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
455 unsigned int ino = bucket - &ivector_table[0];
456
457 if (likely(bucket)) {
458 unsigned long cpuid, dev_handle, dev_ino;
459 int err;
460
461 cpuid = irq_choose_cpu(virt_irq);
462
463 dev_handle = ino & IMAP_IGN;
464 dev_ino = ino & IMAP_INO;
465
466 err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
467 if (err != HV_EOK)
468 printk("sun4v_vintr_set_target(%lx,%lx,%lu): "
469 "err(%d)\n",
470 dev_handle, dev_ino, cpuid, err);
471 }
472}
473
421static void sun4v_virq_disable(unsigned int virt_irq) 474static void sun4v_virq_disable(unsigned int virt_irq)
422{ 475{
423 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); 476 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
@@ -443,6 +496,10 @@ static void sun4v_virq_end(unsigned int virt_irq)
443{ 496{
444 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); 497 struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
445 unsigned int ino = bucket - &ivector_table[0]; 498 unsigned int ino = bucket - &ivector_table[0];
499 struct irq_desc *desc = irq_desc + virt_irq;
500
501 if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
502 return;
446 503
447 if (likely(bucket)) { 504 if (likely(bucket)) {
448 unsigned long dev_handle, dev_ino; 505 unsigned long dev_handle, dev_ino;
@@ -477,6 +534,7 @@ static struct irq_chip sun4u_irq = {
477 .enable = sun4u_irq_enable, 534 .enable = sun4u_irq_enable,
478 .disable = sun4u_irq_disable, 535 .disable = sun4u_irq_disable,
479 .end = sun4u_irq_end, 536 .end = sun4u_irq_end,
537 .set_affinity = sun4u_set_affinity,
480}; 538};
481 539
482static struct irq_chip sun4u_irq_ack = { 540static struct irq_chip sun4u_irq_ack = {
@@ -485,6 +543,7 @@ static struct irq_chip sun4u_irq_ack = {
485 .disable = sun4u_irq_disable, 543 .disable = sun4u_irq_disable,
486 .ack = run_pre_handler, 544 .ack = run_pre_handler,
487 .end = sun4u_irq_end, 545 .end = sun4u_irq_end,
546 .set_affinity = sun4u_set_affinity,
488}; 547};
489 548
490static struct irq_chip sun4v_irq = { 549static struct irq_chip sun4v_irq = {
@@ -492,6 +551,7 @@ static struct irq_chip sun4v_irq = {
492 .enable = sun4v_irq_enable, 551 .enable = sun4v_irq_enable,
493 .disable = sun4v_irq_disable, 552 .disable = sun4v_irq_disable,
494 .end = sun4v_irq_end, 553 .end = sun4v_irq_end,
554 .set_affinity = sun4v_set_affinity,
495}; 555};
496 556
497static struct irq_chip sun4v_irq_ack = { 557static struct irq_chip sun4v_irq_ack = {
@@ -500,6 +560,7 @@ static struct irq_chip sun4v_irq_ack = {
500 .disable = sun4v_irq_disable, 560 .disable = sun4v_irq_disable,
501 .ack = run_pre_handler, 561 .ack = run_pre_handler,
502 .end = sun4v_irq_end, 562 .end = sun4v_irq_end,
563 .set_affinity = sun4v_set_affinity,
503}; 564};
504 565
505#ifdef CONFIG_PCI_MSI 566#ifdef CONFIG_PCI_MSI
@@ -511,6 +572,7 @@ static struct irq_chip sun4v_msi = {
511 .disable = sun4v_msi_disable, 572 .disable = sun4v_msi_disable,
512 .ack = run_pre_handler, 573 .ack = run_pre_handler,
513 .end = sun4v_irq_end, 574 .end = sun4v_irq_end,
575 .set_affinity = sun4v_set_affinity,
514}; 576};
515#endif 577#endif
516 578
@@ -519,6 +581,7 @@ static struct irq_chip sun4v_virq = {
519 .enable = sun4v_virq_enable, 581 .enable = sun4v_virq_enable,
520 .disable = sun4v_virq_disable, 582 .disable = sun4v_virq_disable,
521 .end = sun4v_virq_end, 583 .end = sun4v_virq_end,
584 .set_affinity = sun4v_virt_set_affinity,
522}; 585};
523 586
524static struct irq_chip sun4v_virq_ack = { 587static struct irq_chip sun4v_virq_ack = {
@@ -527,6 +590,7 @@ static struct irq_chip sun4v_virq_ack = {
527 .disable = sun4v_virq_disable, 590 .disable = sun4v_virq_disable,
528 .ack = run_pre_handler, 591 .ack = run_pre_handler,
529 .end = sun4v_virq_end, 592 .end = sun4v_virq_end,
593 .set_affinity = sun4v_virt_set_affinity,
530}; 594};
531 595
532void irq_install_pre_handler(int virt_irq, 596void irq_install_pre_handler(int virt_irq,
@@ -739,6 +803,26 @@ void handler_irq(int irq, struct pt_regs *regs)
739 set_irq_regs(old_regs); 803 set_irq_regs(old_regs);
740} 804}
741 805
806#ifdef CONFIG_HOTPLUG_CPU
807void fixup_irqs(void)
808{
809 unsigned int irq;
810
811 for (irq = 0; irq < NR_IRQS; irq++) {
812 unsigned long flags;
813
814 spin_lock_irqsave(&irq_desc[irq].lock, flags);
815 if (irq_desc[irq].action &&
816 !(irq_desc[irq].status & IRQ_PER_CPU)) {
817 if (irq_desc[irq].chip->set_affinity)
818 irq_desc[irq].chip->set_affinity(irq,
819 irq_desc[irq].affinity);
820 }
821 spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
822 }
823}
824#endif
825
742struct sun5_timer { 826struct sun5_timer {
743 u64 count0; 827 u64 count0;
744 u64 limit0; 828 u64 limit0;