if ( radix_tree_delete(&d->pirq_tree, pirq->pirq) != pirq )
BUG();
+ free_pirq_struct(pirq);
}
/* Flush all ready EOIs from the top of this CPU's pending-EOI stack. */
if ( !is_hvm_domain(d1) )
pirq_guest_unbind(d1, pirq);
pirq->evtchn = 0;
- pirq_cleanup_check(pirq, d1);
- if ( is_hvm_domain(d1) && domain_pirq_to_irq(d1, pirq->pirq) > 0 )
- unmap_domain_pirq_emuirq(d1, pirq->pirq);
+ if ( !is_hvm_domain(d1) ||
+ domain_pirq_to_irq(d1, pirq->pirq) <= 0 ||
+ unmap_domain_pirq_emuirq(d1, pirq->pirq) < 0 )
+ /*
+ * The successful path of unmap_domain_pirq_emuirq() will have
+ * called pirq_cleanup_check() already.
+ */
+ pirq_cleanup_check(pirq, d1);
}
unlink_pirq_port(chn1, d1->vcpu[chn1->notify_vcpu_id]);
break;
void pirq_cleanup_check(struct pirq *pirq, struct domain *d);
#define pirq_cleanup_check(pirq, d) \
- ((pirq)->evtchn ? pirq_cleanup_check(pirq, d) : (void)0)
+ (!(pirq)->evtchn ? pirq_cleanup_check(pirq, d) : (void)0)
extern void pirq_guest_eoi(struct pirq *pirq);
extern void desc_guest_eoi(struct irq_desc *desc, struct pirq *pirq);