From nobody Mon Feb 9 09:34:16 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1559111930; cv=none; d=zoho.com; s=zohoarc; b=C+vP3Vd2JzmBy5/ik8JGTOAZigzdo/233+Za2aNJ8cPAKKo0wEw4kvFWALjbYf30DzEtt8pfifuZcu4+4qjdqScrk1G5pqqZREzkMvNVwipY/dCKdaCP/s3qc+OVY7enDzvRLWGXLUdGtgfmgW63KoJuP64wzf9JWOyB/F4A+Y8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559111930; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=w002kDnb6IhIq2RlLAORj0k6Ck0En8tS6KWIuMYYS90=; b=QP0rF2Du/YZHwhIs1THamg3gav1nV28sPGut2DvmUJ3XaMuKChUBTKyswyXq6+oLOn1+YAoAN45DQcWkYftAk8ur5IRiFZ/7/5hxG9eQiv42sTYTBWZealQgd10uttSUgs6Agh+6cr6KiKoF/Flwc59xWmRf7zZMZppPOccscI8= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1559111930296143.68861289430356; Tue, 28 May 2019 23:38:50 -0700 (PDT) Received: from localhost ([127.0.0.1]:48150 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hVsEb-0007Tx-AI for importer@patchew.org; Wed, 29 May 2019 02:38:49 -0400 Received: from eggs.gnu.org ([209.51.188.92]:42075) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hVs4q-0000cg-HU for qemu-devel@nongnu.org; Wed, 29 May 2019 02:28:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hVs4o-0004gm-H9 for qemu-devel@nongnu.org; Wed, 29 May 2019 02:28:44 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60338) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hVs4o-0004ft-AS for qemu-devel@nongnu.org; Wed, 29 May 2019 02:28:42 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 09D425857F; Wed, 29 May 2019 06:28:41 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by smtp.corp.redhat.com (Postfix) with ESMTP id D8DB561B65; Wed, 29 May 2019 06:28:37 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 294591752B; Wed, 29 May 2019 08:28:33 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Wed, 29 May 2019 08:28:28 +0200 Message-Id: <20190529062832.26483-6-kraxel@redhat.com> In-Reply-To: <20190529062832.26483-1-kraxel@redhat.com> References: <20190529062832.26483-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Wed, 29 May 2019 06:28:41 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 5/9] usb-hub: make number of ports runtime-configurable X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add num_ports property which allows configure the number of downstream ports. Valid range is 1-8, default is 8. Signed-off-by: Gerd Hoffmann Message-id: 20190524070310.4952-3-kraxel@redhat.com --- hw/usb/dev-hub.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 9b04b6a6ec2d..4f700c8f92b5 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -29,7 +29,7 @@ #include "desc.h" #include "qemu/error-report.h" =20 -#define NUM_PORTS 8 +#define MAX_PORTS 8 =20 typedef struct USBHubPort { USBPort port; @@ -40,7 +40,8 @@ typedef struct USBHubPort { typedef struct USBHubState { USBDevice dev; USBEndpoint *intr; - USBHubPort ports[NUM_PORTS]; + uint32_t num_ports; + USBHubPort ports[MAX_PORTS]; } USBHubState; =20 #define TYPE_USB_HUB "usb-hub" @@ -109,7 +110,7 @@ static const USBDescIface desc_iface_hub =3D { { .bEndpointAddress =3D USB_DIR_IN | 0x01, .bmAttributes =3D USB_ENDPOINT_XFER_INT, - .wMaxPacketSize =3D 1 + DIV_ROUND_UP(NUM_PORTS, 8), + .wMaxPacketSize =3D 1 + DIV_ROUND_UP(MAX_PORTS, 8), .bInterval =3D 0xff, }, } @@ -242,7 +243,7 @@ static USBDevice *usb_hub_find_device(USBDevice *dev, u= int8_t addr) USBDevice *downstream; int i; =20 - for (i =3D 0; i < NUM_PORTS; i++) { + for (i =3D 0; i < s->num_ports; i++) { port =3D &s->ports[i]; if (!(port->wPortStatus & PORT_STAT_ENABLE)) { continue; @@ -262,7 +263,7 @@ static void usb_hub_handle_reset(USBDevice *dev) int i; =20 trace_usb_hub_reset(s->dev.addr); - for (i =3D 0; i < NUM_PORTS; i++) { + for (i =3D 0; i < s->num_ports; i++) { port =3D s->ports + i; port->wPortStatus =3D PORT_STAT_POWER; port->wPortChange =3D 0; @@ -332,7 +333,7 @@ static void usb_hub_handle_control(USBDevice *dev, USBP= acket *p, { unsigned int n =3D index - 1; USBHubPort *port; - if (n >=3D NUM_PORTS) { + if (n >=3D s->num_ports) { goto fail; } port =3D &s->ports[n]; @@ -361,7 +362,7 @@ static void usb_hub_handle_control(USBDevice *dev, USBP= acket *p, trace_usb_hub_set_port_feature(s->dev.addr, index, feature_name(value)); =20 - if (n >=3D NUM_PORTS) { + if (n >=3D s->num_ports) { goto fail; } port =3D &s->ports[n]; @@ -394,7 +395,7 @@ static void usb_hub_handle_control(USBDevice *dev, USBP= acket *p, trace_usb_hub_clear_port_feature(s->dev.addr, index, feature_name(value)); =20 - if (n >=3D NUM_PORTS) { + if (n >=3D s->num_ports) { goto fail; } port =3D &s->ports[n]; @@ -443,17 +444,17 @@ static void usb_hub_handle_control(USBDevice *dev, US= BPacket *p, unsigned int n, limit, var_hub_size =3D 0; memcpy(data, qemu_hub_hub_descriptor, sizeof(qemu_hub_hub_descriptor)); - data[2] =3D NUM_PORTS; + data[2] =3D s->num_ports; =20 /* fill DeviceRemovable bits */ - limit =3D DIV_ROUND_UP(NUM_PORTS + 1, 8) + 7; + limit =3D DIV_ROUND_UP(s->num_ports + 1, 8) + 7; for (n =3D 7; n < limit; n++) { data[n] =3D 0x00; var_hub_size++; } =20 /* fill PortPwrCtrlMask bits */ - limit =3D limit + DIV_ROUND_UP(NUM_PORTS, 8); + limit =3D limit + DIV_ROUND_UP(s->num_ports, 8); for (;n < limit; n++) { data[n] =3D 0xff; var_hub_size++; @@ -481,7 +482,7 @@ static void usb_hub_handle_data(USBDevice *dev, USBPack= et *p) unsigned int status; uint8_t buf[4]; int i, n; - n =3D DIV_ROUND_UP(NUM_PORTS + 1, 8); + n =3D DIV_ROUND_UP(s->num_ports + 1, 8); if (p->iov.size =3D=3D 1) { /* FreeBSD workaround */ n =3D 1; } else if (n > p->iov.size) { @@ -489,7 +490,7 @@ static void usb_hub_handle_data(USBDevice *dev, USBPack= et *p) return; } status =3D 0; - for(i =3D 0; i < NUM_PORTS; i++) { + for (i =3D 0; i < s->num_ports; i++) { port =3D &s->ports[i]; if (port->wPortChange) status |=3D (1 << (i + 1)); @@ -520,7 +521,7 @@ static void usb_hub_unrealize(USBDevice *dev, Error **e= rrp) USBHubState *s =3D (USBHubState *)dev; int i; =20 - for (i =3D 0; i < NUM_PORTS; i++) { + for (i =3D 0; i < s->num_ports; i++) { usb_unregister_port(usb_bus_from_device(dev), &s->ports[i].port); } @@ -540,6 +541,12 @@ static void usb_hub_realize(USBDevice *dev, Error **er= rp) USBHubPort *port; int i; =20 + if (s->num_ports < 1 || s->num_ports > MAX_PORTS) { + error_setg(errp, "num_ports (%d) out of range (1..%d)", + s->num_ports, MAX_PORTS); + return; + } + if (dev->port->hubcount =3D=3D 5) { error_setg(errp, "usb hub chain too deep"); return; @@ -548,7 +555,7 @@ static void usb_hub_realize(USBDevice *dev, Error **err= p) usb_desc_create_serial(dev); usb_desc_init(dev); s->intr =3D usb_ep_get(dev, USB_TOKEN_IN, 1); - for (i =3D 0; i < NUM_PORTS; i++) { + for (i =3D 0; i < s->num_ports; i++) { port =3D &s->ports[i]; usb_register_port(usb_bus_from_device(dev), &port->port, s, i, &usb_hub_port_ops, @@ -575,12 +582,17 @@ static const VMStateDescription vmstate_usb_hub =3D { .minimum_version_id =3D 1, .fields =3D (VMStateField[]) { VMSTATE_USB_DEVICE(dev, USBHubState), - VMSTATE_STRUCT_ARRAY(ports, USBHubState, NUM_PORTS, 0, + VMSTATE_STRUCT_ARRAY(ports, USBHubState, MAX_PORTS, 0, vmstate_usb_hub_port, USBHubPort), VMSTATE_END_OF_LIST() } }; =20 +static Property usb_hub_properties[] =3D { + DEFINE_PROP_UINT32("ports", USBHubState, num_ports, 8), + DEFINE_PROP_END_OF_LIST(), +}; + static void usb_hub_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); @@ -597,6 +609,7 @@ static void usb_hub_class_initfn(ObjectClass *klass, vo= id *data) set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->fw_name =3D "hub"; dc->vmsd =3D &vmstate_usb_hub; + dc->props =3D usb_hub_properties; } =20 static const TypeInfo hub_info =3D { --=20 2.18.1