aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/events.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/events.c')
-rw-r--r--drivers/xen/events.c114
1 files changed, 112 insertions, 2 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 76e5b7386af9..332dd63750a0 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -355,7 +355,7 @@ static void unbind_from_irq(unsigned int irq)
355 355
356 spin_lock(&irq_mapping_update_lock); 356 spin_lock(&irq_mapping_update_lock);
357 357
358 if (VALID_EVTCHN(evtchn) && (--irq_bindcount[irq] == 0)) { 358 if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) {
359 close.port = evtchn; 359 close.port = evtchn;
360 if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) 360 if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
361 BUG(); 361 BUG();
@@ -375,7 +375,7 @@ static void unbind_from_irq(unsigned int irq)
375 evtchn_to_irq[evtchn] = -1; 375 evtchn_to_irq[evtchn] = -1;
376 irq_info[irq] = IRQ_UNBOUND; 376 irq_info[irq] = IRQ_UNBOUND;
377 377
378 dynamic_irq_init(irq); 378 dynamic_irq_cleanup(irq);
379 } 379 }
380 380
381 spin_unlock(&irq_mapping_update_lock); 381 spin_unlock(&irq_mapping_update_lock);
@@ -557,6 +557,33 @@ out:
557 put_cpu(); 557 put_cpu();
558} 558}
559 559
560/* Rebind a new event channel to an existing irq. */
561void rebind_evtchn_irq(int evtchn, int irq)
562{
563 /* Make sure the irq is masked, since the new event channel
564 will also be masked. */
565 disable_irq(irq);
566
567 spin_lock(&irq_mapping_update_lock);
568
569 /* After resume the irq<->evtchn mappings are all cleared out */
570 BUG_ON(evtchn_to_irq[evtchn] != -1);
571 /* Expect irq to have been bound before,
572 so the bindcount should be non-0 */
573 BUG_ON(irq_bindcount[irq] == 0);
574
575 evtchn_to_irq[evtchn] = irq;
576 irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
577
578 spin_unlock(&irq_mapping_update_lock);
579
580 /* new event channels are always bound to cpu 0 */
581 irq_set_affinity(irq, cpumask_of_cpu(0));
582
583 /* Unmask the event channel. */
584 enable_irq(irq);
585}
586
560/* Rebind an evtchn so that it gets delivered to a specific cpu */ 587/* Rebind an evtchn so that it gets delivered to a specific cpu */
561static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu) 588static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
562{ 589{
@@ -647,6 +674,89 @@ static int retrigger_dynirq(unsigned int irq)
647 return ret; 674 return ret;
648} 675}
649 676
677static void restore_cpu_virqs(unsigned int cpu)
678{
679 struct evtchn_bind_virq bind_virq;
680 int virq, irq, evtchn;
681
682 for (virq = 0; virq < NR_VIRQS; virq++) {
683 if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1)
684 continue;
685
686 BUG_ON(irq_info[irq].type != IRQT_VIRQ);
687 BUG_ON(irq_info[irq].index != virq);
688
689 /* Get a new binding from Xen. */
690 bind_virq.virq = virq;
691 bind_virq.vcpu = cpu;
692 if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
693 &bind_virq) != 0)
694 BUG();
695 evtchn = bind_virq.port;
696
697 /* Record the new mapping. */
698 evtchn_to_irq[evtchn] = irq;
699 irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
700 bind_evtchn_to_cpu(evtchn, cpu);
701
702 /* Ready for use. */
703 unmask_evtchn(evtchn);
704 }
705}
706
707static void restore_cpu_ipis(unsigned int cpu)
708{
709 struct evtchn_bind_ipi bind_ipi;
710 int ipi, irq, evtchn;
711
712 for (ipi = 0; ipi < XEN_NR_IPIS; ipi++) {
713 if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1)
714 continue;
715
716 BUG_ON(irq_info[irq].type != IRQT_IPI);
717 BUG_ON(irq_info[irq].index != ipi);
718
719 /* Get a new binding from Xen. */
720 bind_ipi.vcpu = cpu;
721 if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
722 &bind_ipi) != 0)
723 BUG();
724 evtchn = bind_ipi.port;
725
726 /* Record the new mapping. */
727 evtchn_to_irq[evtchn] = irq;
728 irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
729 bind_evtchn_to_cpu(evtchn, cpu);
730
731 /* Ready for use. */
732 unmask_evtchn(evtchn);
733
734 }
735}
736
737void xen_irq_resume(void)
738{
739 unsigned int cpu, irq, evtchn;
740
741 init_evtchn_cpu_bindings();
742
743 /* New event-channel space is not 'live' yet. */
744 for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
745 mask_evtchn(evtchn);
746
747 /* No IRQ <-> event-channel mappings. */
748 for (irq = 0; irq < NR_IRQS; irq++)
749 irq_info[irq].evtchn = 0; /* zap event-channel binding */
750
751 for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
752 evtchn_to_irq[evtchn] = -1;
753
754 for_each_possible_cpu(cpu) {
755 restore_cpu_virqs(cpu);
756 restore_cpu_ipis(cpu);
757 }
758}
759
650static struct irq_chip xen_dynamic_chip __read_mostly = { 760static struct irq_chip xen_dynamic_chip __read_mostly = {
651 .name = "xen-dyn", 761 .name = "xen-dyn",
652 .mask = disable_dynirq, 762 .mask = disable_dynirq,