void notify_remote_via_irq(int irq) { int evtchn = evtchn_from_irq(irq); if (VALID_EVTCHN(evtchn)) notify_remote_via_evtchn(evtchn); }
static void unbind_from_irq(int irq) { struct evtchn_close close; int evtchn = evtchn_from_irq(irq); int cpu; mtx_lock_spin(&irq_mapping_update_lock); if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) { close.port = evtchn; HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); switch (type_from_irq(irq)) { case IRQT_VIRQ: cpu = cpu_from_evtchn(evtchn); pcpu_find(cpu)->pc_virq_to_irq[index_from_irq(irq)] = -1; break; case IRQT_IPI: cpu = cpu_from_evtchn(evtchn); pcpu_find(cpu)->pc_ipi_to_irq[index_from_irq(irq)] = -1; break; default: break; } /* Closed ports are implicitly re-bound to VCPU0. */ bind_evtchn_to_cpu(evtchn, 0); evtchn_to_irq[evtchn] = -1; irq_info[irq] = IRQ_UNBOUND; } mtx_unlock_spin(&irq_mapping_update_lock); }
static void end_dynirq(unsigned int irq) { int evtchn = evtchn_from_irq(irq); if (VALID_EVTCHN(evtchn) && !(irq_desc[irq].status & IRQ_DISABLED)) unmask_evtchn(evtchn); }
static void unbind_from_irq(unsigned int irq) { struct evtchn_close close; int evtchn = evtchn_from_irq(irq); spin_lock(&irq_mapping_update_lock); if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) { close.port = evtchn; if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) BUG(); switch (type_from_irq(irq)) { case IRQT_VIRQ: per_cpu(virq_to_irq, cpu_from_evtchn(evtchn)) [index_from_irq(irq)] = -1; break; case IRQT_IPI: per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn)) [index_from_irq(irq)] = -1; break; default: break; } /* Closed ports are implicitly re-bound to VCPU0. */ bind_evtchn_to_cpu(evtchn, 0); evtchn_to_irq[evtchn] = -1; irq_info[irq] = IRQ_UNBOUND; } spin_unlock(&irq_mapping_update_lock); }
static void disable_dynirq(unsigned int irq) { int evtchn = evtchn_from_irq(irq); if (VALID_EVTCHN(evtchn)) mask_evtchn(evtchn); }
static unsigned int startup_pirq(unsigned int irq) { struct evtchn_bind_pirq bind_pirq; int evtchn = evtchn_from_irq(irq); if (VALID_EVTCHN(evtchn)) goto out; bind_pirq.pirq = irq; /* NB. We are happy to share unless we are probing. */ bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE; if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) { if (!probing_irq(irq)) printk(KERN_INFO "Failed to obtain physical IRQ %d\n", irq); return 0; } evtchn = bind_pirq.port; pirq_query_unmask(irq_to_pirq(irq)); evtchn_to_irq[evtchn] = irq; bind_evtchn_to_cpu(evtchn, 0); irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, evtchn); out: unmask_evtchn(evtchn); pirq_unmask_notify(irq_to_pirq(irq)); return 0; }
static void rebind_irq_to_cpu(unsigned int irq, unsigned int tcpu) { int evtchn = evtchn_from_irq(irq); if (VALID_EVTCHN(evtchn)) rebind_evtchn_to_cpu(evtchn, tcpu); }
static unsigned int startup_dynirq(unsigned int irq) { int evtchn = evtchn_from_irq(irq); if (VALID_EVTCHN(evtchn)) unmask_evtchn(evtchn); return 0; }
void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { int evtchn = evtchn_from_irq(i); shared_info_t *s = HYPERVISOR_shared_info; if (!VALID_EVTCHN(evtchn)) return; BUG_ON(!synch_test_bit(evtchn, &s->evtchn_mask[0])); synch_set_bit(evtchn, &s->evtchn_pending[0]); }
static void end_pirq(unsigned int irq) { int evtchn = evtchn_from_irq(irq); if (VALID_EVTCHN(evtchn) && !(irq_desc[irq].status & IRQ_DISABLED)) { unmask_evtchn(evtchn); pirq_unmask_notify(irq_to_pirq(irq)); } }
static void enable_pirq(unsigned int irq) { int evtchn = evtchn_from_irq(irq); if (VALID_EVTCHN(evtchn)) { unmask_evtchn(evtchn); pirq_unmask_notify(irq_to_pirq(irq)); } }
static int retrigger(unsigned int irq) { int evtchn = evtchn_from_irq(irq); shared_info_t *s = HYPERVISOR_shared_info; if (!VALID_EVTCHN(evtchn)) return 1; synch_set_bit(evtchn, &s->evtchn_pending[0]); return 1; }
static void ack_dynirq(unsigned int irq) { int evtchn = evtchn_from_irq(irq); move_native_irq(irq); if (VALID_EVTCHN(evtchn)) { mask_evtchn(evtchn); clear_evtchn(evtchn); } }
int resend_irq_on_evtchn(unsigned int irq) { int masked, evtchn = evtchn_from_irq(irq); shared_info_t *s = HYPERVISOR_shared_info; if (!VALID_EVTCHN(evtchn)) return 1; masked = test_and_set_evtchn_mask(evtchn); synch_set_bit(evtchn, s->evtchn_pending); if (!masked) unmask_evtchn(evtchn); return 1; }
static void shutdown_pirq(unsigned int irq) { struct evtchn_close close; int evtchn = evtchn_from_irq(irq); if (!VALID_EVTCHN(evtchn)) return; mask_evtchn(evtchn); close.port = evtchn; if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) BUG(); bind_evtchn_to_cpu(evtchn, 0); evtchn_to_irq[evtchn] = -1; irq_info[irq] = IRQ_UNBOUND; }
/* Rebind an evtchn so that it gets delivered to a specific cpu */ static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu) { struct evtchn_bind_vcpu bind_vcpu; int evtchn = evtchn_from_irq(irq); if (!VALID_EVTCHN(evtchn)) return; /* Send future instances of this interrupt to other vcpu. */ bind_vcpu.port = evtchn; bind_vcpu.vcpu = tcpu; /* * If this fails, it usually just indicates that we're dealing with a * virq or IPI channel, which don't actually need to be rebound. Ignore * it, but don't do the xenlinux-level rebind in that case. */ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0) bind_evtchn_to_cpu(evtchn, tcpu); }
static void unbind_from_irq(unsigned int irq) { struct evtchn_close close; unsigned int cpu; int evtchn = evtchn_from_irq(irq); spin_lock(&irq_mapping_update_lock); if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) { close.port = evtchn; if ((type_from_irq(irq) != IRQT_CALLER_PORT) && HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) BUG(); switch (type_from_irq(irq)) { case IRQT_VIRQ: per_cpu(virq_to_irq, cpu_from_evtchn(evtchn)) [index_from_irq(irq)] = -1; break; case IRQT_IPI: per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn)) [index_from_irq(irq)] = -1; break; default: break; } /* Closed ports are implicitly re-bound to VCPU0. */ bind_evtchn_to_cpu(evtchn, 0); evtchn_to_irq[evtchn] = -1; irq_info[irq] = IRQ_UNBOUND; /* Zap stats across IRQ changes of use. */ for_each_possible_cpu(cpu) kstat_cpu(cpu).irqs[irq] = 0; } spin_unlock(&irq_mapping_update_lock); }