Commit 20729dbd authored by Cao jin's avatar Cao jin Committed by Michael S. Tsirkin
Browse files

hcd-xhci: check & correct param before using it



usb_xhci_realize() corrects invalid values of property "intrs"
automatically, but the uncorrected value is passed to msi_init(),
which chokes on invalid values.  Delay that until after the
correction.

Resources allocated by usb_xhci_init() are leaked when msi_init()
fails.  Fix by calling it after msi_init().

CC: Gerd Hoffmann <kraxel@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Marcel Apfelbaum <marcel@redhat.com>
CC: Michael S. Tsirkin <mst@redhat.com>

Reviewed-by: default avatarMarkus Armbruster <armbru@redhat.com>
Acked-by: default avatarMarcel Apfelbaum <marcel@redhat.com>
Signed-off-by: default avatarCao jin <caoj.fnst@cn.fujitsu.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 93482436
Loading
Loading
Loading
Loading
+18 −19
Original line number Diff line number Diff line
@@ -3627,25 +3627,6 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
    dev->config[PCI_CACHE_LINE_SIZE] = 0x10;
    dev->config[0x60] = 0x30; /* release number */

    usb_xhci_init(xhci);

    if (xhci->msi != ON_OFF_AUTO_OFF) {
        ret = msi_init(dev, 0x70, xhci->numintrs, true, false, &err);
        /* Any error other than -ENOTSUP(board's MSI support is broken)
         * is a programming error */
        assert(!ret || ret == -ENOTSUP);
        if (ret && xhci->msi == ON_OFF_AUTO_ON) {
            /* Can't satisfy user's explicit msi=on request, fail */
            error_append_hint(&err, "You have to use msi=auto (default) or "
                    "msi=off with this machine type.\n");
            error_propagate(errp, err);
            return;
        }
        assert(!err || xhci->msi == ON_OFF_AUTO_AUTO);
        /* With msi=auto, we fall back to MSI off silently */
        error_free(err);
    }

    if (xhci->numintrs > MAXINTRS) {
        xhci->numintrs = MAXINTRS;
    }
@@ -3667,6 +3648,24 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
        xhci->max_pstreams_mask = 0;
    }

    if (xhci->msi != ON_OFF_AUTO_OFF) {
        ret = msi_init(dev, 0x70, xhci->numintrs, true, false, &err);
        /* Any error other than -ENOTSUP(board's MSI support is broken)
         * is a programming error */
        assert(!ret || ret == -ENOTSUP);
        if (ret && xhci->msi == ON_OFF_AUTO_ON) {
            /* Can't satisfy user's explicit msi=on request, fail */
            error_append_hint(&err, "You have to use msi=auto (default) or "
                    "msi=off with this machine type.\n");
            error_propagate(errp, err);
            return;
        }
        assert(!err || xhci->msi == ON_OFF_AUTO_AUTO);
        /* With msi=auto, we fall back to MSI off silently */
        error_free(err);
    }

    usb_xhci_init(xhci);
    xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci);

    memory_region_init(&xhci->mem, OBJECT(xhci), "xhci", LEN_REGS);