pass-through: fix unbinding of MSI interrupts Commit 568da4f8 ("pt-irq fixes and improvements") went a little too far in its cleaning up of pt_irq_destroy_bind(): While neither of the two lists need any maintenance, the actualunbinding still needs to be done. Fix this and at once enhance the final (optional) log message to make clear how much cleaning up was actually done. Reported-by: Sander Eikelenboom Signed-off-by: Jan Beulich --- a/xen/drivers/passthrough/io.c +++ b/xen/drivers/passthrough/io.c @@ -300,17 +300,15 @@ int pt_irq_destroy_bind( unsigned int intx = pt_irq_bind->u.pci.intx; unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx); unsigned int link = hvm_pci_intx_link(device, intx); - struct dev_intx_gsi_link *digl, *tmp; - struct hvm_girq_dpci_mapping *girq; struct pirq *pirq; + const char *what; switch ( pt_irq_bind->irq_type ) { case PT_IRQ_TYPE_PCI: + case PT_IRQ_TYPE_MSI: case PT_IRQ_TYPE_MSI_TRANSLATE: break; - case PT_IRQ_TYPE_MSI: - return 0; default: return -EOPNOTSUPP; } @@ -331,27 +329,32 @@ int pt_irq_destroy_bind( return -EINVAL; } - list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list ) + if ( pt_irq_bind->irq_type != PT_IRQ_TYPE_MSI ) { - if ( girq->bus == bus && - girq->device == device && - girq->intx == intx && - girq->machine_gsi == machine_gsi ) + struct hvm_girq_dpci_mapping *girq; + + list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list ) { - list_del(&girq->list); - xfree(girq); - girq = NULL; - break; + if ( girq->bus == bus && + girq->device == device && + girq->intx == intx && + girq->machine_gsi == machine_gsi ) + { + list_del(&girq->list); + xfree(girq); + girq = NULL; + break; + } } - } - if ( girq ) - { - spin_unlock(&d->event_lock); - return -EINVAL; - } + if ( girq ) + { + spin_unlock(&d->event_lock); + return -EINVAL; + } - hvm_irq_dpci->link_cnt[link]--; + hvm_irq_dpci->link_cnt[link]--; + } pirq = pirq_info(d, machine_gsi); pirq_dpci = pirq_dpci(pirq); @@ -359,14 +362,19 @@ int pt_irq_destroy_bind( /* clear the mirq info */ if ( pirq_dpci && (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) ) { - list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list ) + if ( pt_irq_bind->irq_type != PT_IRQ_TYPE_MSI ) { - if ( digl->bus == bus && - digl->device == device && - digl->intx == intx ) + struct dev_intx_gsi_link *digl, *tmp; + + list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list ) { - list_del(&digl->list); - xfree(digl); + if ( digl->bus == bus && + digl->device == device && + digl->intx == intx ) + { + list_del(&digl->list); + xfree(digl); + } } } @@ -379,14 +387,20 @@ int pt_irq_destroy_bind( pirq_dpci->dom = NULL; pirq_dpci->flags = 0; pirq_cleanup_check(pirq, d); + what = "final"; } + else + what = "partial"; } + else + what = "bogus"; + spin_unlock(&d->event_lock); if ( iommu_verbose ) dprintk(XENLOG_G_INFO, - "d%d unmap: m_irq=%u dev=%02x:%02x.%u intx=%u\n", - d->domain_id, machine_gsi, bus, + "d%d %s unmap: m_irq=%u dev=%02x:%02x.%u intx=%u\n", + d->domain_id, what, machine_gsi, bus, PCI_SLOT(device), PCI_FUNC(device), intx); return 0;