libqos: Solve bug in interrupt checking when using MSIX in virtio-pci.c

The MSIX interrupt was always acked without checking its value, which caused a
race condition. If the ISR was raised between the read and the acking, the ISR
was never detected and it timed out.

Signed-off-by: Marc Marí <marc.mari.barcelo@gmail.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Tested-by: John Snow <jsnow@redhat.com>
Message-id: 1424795655-16952-1-git-send-email-marc.mari.barcelo@gmail.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Marc Marí 2015-02-24 17:34:14 +01:00 committed by Kevin Wolf
parent 833a7cc36e
commit 1e34cf9681
1 changed files with 12 additions and 4 deletions

View File

@ -142,8 +142,12 @@ static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
return qpci_msix_pending(dev->pdev, vqpci->msix_entry);
} else {
data = readl(vqpci->msix_addr);
writel(vqpci->msix_addr, 0);
return data == vqpci->msix_data;
if (data == vqpci->msix_data) {
writel(vqpci->msix_addr, 0);
return true;
} else {
return false;
}
}
} else {
return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_ISR_STATUS) & 1;
@ -162,8 +166,12 @@ static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d)
return qpci_msix_pending(dev->pdev, dev->config_msix_entry);
} else {
data = readl(dev->config_msix_addr);
writel(dev->config_msix_addr, 0);
return data == dev->config_msix_data;
if (data == dev->config_msix_data) {
writel(dev->config_msix_addr, 0);
return true;
} else {
return false;
}
}
} else {
return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_ISR_STATUS) & 2;