aboutsummaryrefslogtreecommitdiff
path: root/hw/pci/msix.c
diff options
context:
space:
mode:
authorCao jin <caoj.fnst@cn.fujitsu.com>2017-01-17 14:18:48 +0800
committerMichael S. Tsirkin <mst@redhat.com>2017-02-01 03:37:18 +0200
commitee640c625e190a0c0e6b8966adc0e4720fb75200 (patch)
tree1514d71db96b8db6da3029471a100fb16f2f4a00 /hw/pci/msix.c
parent20729dbd0109b9d9065447dba354f10bcf78d0d6 (diff)
downloadqemu-ee640c625e190a0c0e6b8966adc0e4720fb75200.zip
qemu-ee640c625e190a0c0e6b8966adc0e4720fb75200.tar.gz
qemu-ee640c625e190a0c0e6b8966adc0e4720fb75200.tar.bz2
pci: Convert msix_init() to Error and fix callers
msix_init() reports errors with error_report(), which is wrong when it's used in realize(). The same issue was fixed for msi_init() in commit 1108b2f. In order to make the API change as small as possible, leave the return value check to later patch. For some devices(like e1000e, vmxnet3, nvme) who won't fail because of msix_init's failure, suppress the error report by passing NULL error object. Bonus: add comment for msix_init. CC: Jiri Pirko <jiri@resnulli.us> CC: Gerd Hoffmann <kraxel@redhat.com> CC: Dmitry Fleytman <dmitry@daynix.com> CC: Jason Wang <jasowang@redhat.com> CC: Michael S. Tsirkin <mst@redhat.com> CC: Hannes Reinecke <hare@suse.de> CC: Paolo Bonzini <pbonzini@redhat.com> CC: Alex Williamson <alex.williamson@redhat.com> CC: Markus Armbruster <armbru@redhat.com> CC: Marcel Apfelbaum <marcel@redhat.com> Signed-off-by: Cao jin <caoj.fnst@cn.fujitsu.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/pci/msix.c')
-rw-r--r--hw/pci/msix.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index c938a9b..bb54e8b 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -21,6 +21,7 @@
#include "hw/pci/pci.h"
#include "hw/xen/xen.h"
#include "qemu/range.h"
+#include "qapi/error.h"
#define MSIX_CAP_LENGTH 12
@@ -238,11 +239,31 @@ static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
}
}
-/* Initialize the MSI-X structures */
+/*
+ * Make PCI device @dev MSI-X capable
+ * @nentries is the max number of MSI-X vectors that the device support.
+ * @table_bar is the MemoryRegion that MSI-X table structure resides.
+ * @table_bar_nr is number of base address register corresponding to @table_bar.
+ * @table_offset indicates the offset that the MSI-X table structure starts with
+ * in @table_bar.
+ * @pba_bar is the MemoryRegion that the Pending Bit Array structure resides.
+ * @pba_bar_nr is number of base address register corresponding to @pba_bar.
+ * @pba_offset indicates the offset that the Pending Bit Array structure
+ * starts with in @pba_bar.
+ * Non-zero @cap_pos puts capability MSI-X at that offset in PCI config space.
+ * @errp is for returning errors.
+ *
+ * Return 0 on success; set @errp and return -errno on error:
+ * -ENOTSUP means lacking msi support for a msi-capable platform.
+ * -EINVAL means capability overlap, happens when @cap_pos is non-zero,
+ * also means a programming error, except device assignment, which can check
+ * if a real HW is broken.
+ */
int msix_init(struct PCIDevice *dev, unsigned short nentries,
MemoryRegion *table_bar, uint8_t table_bar_nr,
unsigned table_offset, MemoryRegion *pba_bar,
- uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos)
+ uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos,
+ Error **errp)
{
int cap;
unsigned table_size, pba_size;
@@ -250,10 +271,12 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
/* Nothing to do if MSI is not supported by interrupt controller */
if (!msi_nonbroken) {
+ error_setg(errp, "MSI-X is not supported by interrupt controller");
return -ENOTSUP;
}
if (nentries < 1 || nentries > PCI_MSIX_FLAGS_QSIZE + 1) {
+ error_setg(errp, "The number of MSI-X vectors is invalid");
return -EINVAL;
}
@@ -266,10 +289,13 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
table_offset + table_size > memory_region_size(table_bar) ||
pba_offset + pba_size > memory_region_size(pba_bar) ||
(table_offset | pba_offset) & PCI_MSIX_FLAGS_BIRMASK) {
+ error_setg(errp, "table & pba overlap, or they don't fit in BARs,"
+ " or don't align");
return -EINVAL;
}
- cap = pci_add_capability(dev, PCI_CAP_ID_MSIX, cap_pos, MSIX_CAP_LENGTH);
+ cap = pci_add_capability2(dev, PCI_CAP_ID_MSIX,
+ cap_pos, MSIX_CAP_LENGTH, errp);
if (cap < 0) {
return cap;
}
@@ -306,7 +332,7 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
}
int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
- uint8_t bar_nr)
+ uint8_t bar_nr, Error **errp)
{
int ret;
char *name;
@@ -338,7 +364,7 @@ int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr,
0, &dev->msix_exclusive_bar,
bar_nr, bar_pba_offset,
- 0);
+ 0, errp);
if (ret) {
return ret;
}