aboutsummaryrefslogtreecommitdiff
path: root/hw/msix.c
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2009-11-25 12:24:14 +0200
committerMichael S. Tsirkin <mst@redhat.com>2009-12-01 18:00:14 +0200
commit98304c846d8866dae6322ef400ce6595b23cfc41 (patch)
tree7526a2fb68d30d9f82143c35eab444770f835083 /hw/msix.c
parent1f944c661a821774e7b8cfbf5560a238795f2a60 (diff)
msix: clear pending bit of an unused vector
PCI spec states: if a masked vector has its Pending bit set, and the associated underlying interrupt events are somehow satisfied (usually by software though the exact manner is function-specific), the function must clear the Pending bit, to avoid sending a spurious interrupt message later when software unmasks the vector. In our case this happens if vector becomes unused. Clear pending bit in this case. Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/msix.c')
-rw-r--r--hw/msix.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/hw/msix.c b/hw/msix.c
index 785e097d80..4bc6147234 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -105,14 +105,6 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
return 0;
}
-static void msix_free_irq_entries(PCIDevice *dev)
-{
- int vector;
-
- for (vector = 0; vector < dev->msix_entries_nr; ++vector)
- dev->msix_entry_used[vector] = 0;
-}
-
/* Handle MSI-X capability config write. */
void msix_write_config(PCIDevice *dev, uint32_t addr,
uint32_t val, int len)
@@ -271,6 +263,16 @@ err_index:
return ret;
}
+static void msix_free_irq_entries(PCIDevice *dev)
+{
+ int vector;
+
+ for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
+ dev->msix_entry_used[vector] = 0;
+ msix_clr_pending(dev, vector);
+ }
+}
+
/* Clean up resources for the device. */
int msix_uninit(PCIDevice *dev)
{
@@ -387,8 +389,13 @@ int msix_vector_use(PCIDevice *dev, unsigned vector)
/* Mark vector as unused. */
void msix_vector_unuse(PCIDevice *dev, unsigned vector)
{
- if (vector < dev->msix_entries_nr && dev->msix_entry_used[vector])
- --dev->msix_entry_used[vector];
+ if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector]) {
+ return;
+ }
+ if (--dev->msix_entry_used[vector]) {
+ return;
+ }
+ msix_clr_pending(dev, vector);
}
void msix_unuse_all_vectors(PCIDevice *dev)