diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2009-11-25 12:24:14 +0200 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2009-12-01 18:00:14 +0200 |
commit | 98304c846d8866dae6322ef400ce6595b23cfc41 (patch) | |
tree | 7526a2fb68d30d9f82143c35eab444770f835083 /hw/msix.c | |
parent | 1f944c661a821774e7b8cfbf5560a238795f2a60 (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.c | 27 |
1 files changed, 17 insertions, 10 deletions
@@ -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) |