From patchwork Sat Jan 18 07:08:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 13944096 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A59AEC0218A for ; Sat, 18 Jan 2025 07:09:54 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tZ2xN-0003Ci-Qc; Sat, 18 Jan 2025 02:09:22 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tZ2xF-0003CH-7A for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:13 -0500 Received: from mail-pj1-x1035.google.com ([2607:f8b0:4864:20::1035]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tZ2xA-0007ng-Lf for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:11 -0500 Received: by mail-pj1-x1035.google.com with SMTP id 98e67ed59e1d1-2ee74291415so3939492a91.3 for ; Fri, 17 Jan 2025 23:09:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1737184147; x=1737788947; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vTuUXB2A9ro+1crlnXyI2/NaqcqQJSxv4wzppP8o+Cs=; b=K/9JeGnY+MExT6QNrg79L2R3bWxggEz/6zhq/OdMHc8myXe32Cjfi9xckb1hK7yz2P EnWh7ZlH/PciirLQQlmhGXspHxw3f1/tQNFEZfaPlaowtffstMLxYM7xjVSblSEfT7mq oMyjBm97j6bwbJGf1gjytsmhc/j6ujNMhK4DP5+ZSos72BjPjTsSlfhkZ0SiPN55/FQf oCmQdwE7M2MQC9YZw8hVClzvB5RyZUDozrmvhJTrzmyThL3EWylr6+f1Coub4EvPSIvx 5P2yJcc7CqXdq7fF2AMvGmNc4vZN7MMLtFJWUyb2tYk6MAMi2xIqkAxYxNUdLa3RSnp1 OxTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737184147; x=1737788947; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vTuUXB2A9ro+1crlnXyI2/NaqcqQJSxv4wzppP8o+Cs=; b=Tyi+gHEZigLrBapq2riUdm8YQMsqfMuicKlW44vVLQR91FzKPCGykRJBL0AqScwR5a OYJg0aGoj2Usz/sHmyM7oKzvM+kBGCD/LDf5rb7Njn7wrgCk7ODAKvI3704cR19EsmzA PQPVzZKCmDR+dusIhy74lvjt9a6JAMaqc71yMtrYQR0F56N3AKUV5WpuSoZm8+Jzrb62 MuLBCPmFVvxjcoUtRDd6ZlmZk0ggufEFpAXM5BOvJtzYnZA4sVN9kz2BJEclhxs+nvdq 7T5ermEsKPjntNYTM825OpnQTEde9HFR9GqwY72xae3yc+wkU4yAthop525IiWsUVeTR H8bw== X-Gm-Message-State: AOJu0YwR+Sdy4FflbPBJ8APgY0HBu8MVSzSMoGY3zjqW5MvsWeDVrfdd jTycY2/aEhif1vLSnjID4wsfsvvxxP1YGQ//NOs0QvpCcCtMfmQrAez1dA== X-Gm-Gg: ASbGnctPpP7FSsY8lD/8apQuP01fV4rgjh3ivXPbI22ggCKv6EivixcBKwUNDtpqC2U DPqU8wcVtYrDcKs7XEhzyxLtwpB7bAOQT+zOXa6EbAaACdcLK5va6CskKP/ow55CVhdJVDSV+Mv I5Z6XrVzl5M1FnpbBWU3kXJz5/rU4CDT7mZ2lFfU1ZCntNzuahKSJ26jTzv/KBvEMiC11vIEF3m /yqZsfx3b4BWq3bKsX2CFt/i0R/yY2tJ+RTfh0TG5+fy8ng/yoA1d/sSypsL2Pco/wX3P541Aau 3y8xcbuMA43tZzRT7yGgk3Wxhih9 X-Google-Smtp-Source: AGHT+IFggzqAGdfuVF2cT8EDYQ3bOrZMPTjASluy+JclmpFJuLmS4vbTVqpPmscL2PPIGUNj+dhXPg== X-Received: by 2002:a05:6a00:4c18:b0:725:c8ea:b320 with SMTP id d2e1a72fcca58-72daf99ec6dmr8461042b3a.14.1737184146526; Fri, 17 Jan 2025 23:09:06 -0800 (PST) Received: from wheely.local0.net (124-169-212-233.tpgi.com.au. [124.169.212.233]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72dab9c95adsm3192880b3a.107.2025.01.17.23.09.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jan 2025 23:09:05 -0800 (PST) From: Nicholas Piggin To: qemu-devel@nongnu.org Cc: Nicholas Piggin , Paolo Bonzini , "Michael S. Tsirkin" , Marcel Apfelbaum , Fabiano Rosas , Laurent Vivier , Phil Dennis-Jordan Subject: [PATCH v2 1/8] hw/usb/xhci: Move HCD constants to a header and add register constants Date: Sat, 18 Jan 2025 17:08:46 +1000 Message-ID: <20250118070853.653778-2-npiggin@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250118070853.653778-1-npiggin@gmail.com> References: <20250118070853.653778-1-npiggin@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1035; envelope-from=npiggin@gmail.com; helo=mail-pj1-x1035.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Prepare to use some of these constants in xhci qtest code. Signed-off-by: Nicholas Piggin --- hw/usb/hcd-xhci.h | 214 ++++++++++++++++++++++ hw/usb/hcd-xhci.c | 450 +++++++++++++++------------------------------- 2 files changed, 360 insertions(+), 304 deletions(-) diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h index 9609b835141..bd1d8e8e81a 100644 --- a/hw/usb/hcd-xhci.h +++ b/hw/usb/hcd-xhci.h @@ -115,6 +115,220 @@ typedef enum TRBCCode { CC_SPLIT_TRANSACTION_ERROR } TRBCCode; +/* Register definitions */ +#define XHCI_HCCAP_REG_CAPLENGTH 0x00 +#define XHCI_HCCAP_REG_HCIVERSION 0x02 +#define XHCI_HCCAP_REG_HCSPARAMS1 0x04 +#define XHCI_HCCAP_REG_HCSPARAMS2 0x08 +#define XHCI_HCCAP_REG_HCSPARAMS3 0x0C +#define XHCI_HCCAP_REG_HCCPARAMS1 0x10 +#define XHCI_HCCPARAMS1_AC64 0x00000001 +#define XHCI_HCCPARAMS1_XECP_SHIFT 16 +#define XHCI_HCCPARAMS1_MAXPSASIZE_SHIFT 12 +#define XHCI_HCCAP_REG_DBOFF 0x14 +#define XHCI_HCCAP_REG_RTSOFF 0x18 +#define XHCI_HCCAP_REG_HCCPARAMS2 0x1C +#define XHCI_HCCAP_EXTCAP_START 0x20 /* SW-defined */ + +#define XHCI_PORT_PR_SZ 0x10 +#define XHCI_PORT_REG_PORTSC 0x00 +#define XHCI_PORTSC_CCS (1 << 0) +#define XHCI_PORTSC_PED (1 << 1) +#define XHCI_PORTSC_OCA (1 << 3) +#define XHCI_PORTSC_PR (1 << 4) +#define XHCI_PORTSC_PLS_SHIFT 5 +#define XHCI_PORTSC_PLS_MASK 0xf +#define XHCI_PORTSC_PP (1 << 9) +#define XHCI_PORTSC_SPEED_SHIFT 10 +#define XHCI_PORTSC_SPEED_MASK 0xf +#define XHCI_PORTSC_SPEED_FULL (1 << 10) +#define XHCI_PORTSC_SPEED_LOW (2 << 10) +#define XHCI_PORTSC_SPEED_HIGH (3 << 10) +#define XHCI_PORTSC_SPEED_SUPER (4 << 10) +#define XHCI_PORTSC_PIC_SHIFT 14 +#define XHCI_PORTSC_PIC_MASK 0x3 +#define XHCI_PORTSC_LWS (1 << 16) +#define XHCI_PORTSC_CSC (1 << 17) +#define XHCI_PORTSC_PEC (1 << 18) +#define XHCI_PORTSC_WRC (1 << 19) +#define XHCI_PORTSC_OCC (1 << 20) +#define XHCI_PORTSC_PRC (1 << 21) +#define XHCI_PORTSC_PLC (1 << 22) +#define XHCI_PORTSC_CEC (1 << 23) +#define XHCI_PORTSC_CAS (1 << 24) +#define XHCI_PORTSC_WCE (1 << 25) +#define XHCI_PORTSC_WDE (1 << 26) +#define XHCI_PORTSC_WOE (1 << 27) +#define XHCI_PORTSC_DR (1 << 30) +#define XHCI_PORTSC_WPR (1 << 31) +/* read/write bits */ +#define XHCI_PORTSC_RW_MASK (XHCI_PORTSC_PP | \ + XHCI_PORTSC_WCE | \ + XHCI_PORTSC_WDE | \ + XHCI_PORTSC_WOE) +/* write-1-to-clear bits*/ +#define XHCI_PORTSC_W1C_MASK (XHCI_PORTSC_CSC | \ + XHCI_PORTSC_PEC | \ + XHCI_PORTSC_WRC | \ + XHCI_PORTSC_OCC | \ + XHCI_PORTSC_PRC | \ + XHCI_PORTSC_PLC | \ + XHCI_PORTSC_CEC) +#define XHCI_PORT_REG_PORTPMSC 0x04 +#define XHCI_PORT_REG_PORTLI 0x08 +#define XHCI_PORT_REG_PORTHLPMC 0x0C + +#define XHCI_OPER_REG_USBCMD 0x00 +#define XHCI_USBCMD_RS (1 << 0) +#define XHCI_USBCMD_HCRST (1 << 1) +#define XHCI_USBCMD_INTE (1 << 2) +#define XHCI_USBCMD_HSEE (1 << 3) +#define XHCI_USBCMD_LHCRST (1 << 7) +#define XHCI_USBCMD_CSS (1 << 8) +#define XHCI_USBCMD_CRS (1 << 9) +#define XHCI_USBCMD_EWE (1 << 10) +#define XHCI_USBCMD_EU3S (1 << 11) +#define XHCI_OPER_REG_USBSTS 0x04 +#define XHCI_USBSTS_HCH (1 << 0) +#define XHCI_USBSTS_HSE (1 << 2) +#define XHCI_USBSTS_EINT (1 << 3) +#define XHCI_USBSTS_PCD (1 << 4) +#define XHCI_USBSTS_SSS (1 << 8) +#define XHCI_USBSTS_RSS (1 << 9) +#define XHCI_USBSTS_SRE (1 << 10) +#define XHCI_USBSTS_CNR (1 << 11) +#define XHCI_USBSTS_HCE (1 << 12) +/* these bits are write-1-to-clear */ +#define XHCI_USBSTS_W1C_MASK (XHCI_USBSTS_HSE | \ + XHCI_USBSTS_EINT | \ + XHCI_USBSTS_PCD | \ + XHCI_USBSTS_SRE) +#define XHCI_OPER_REG_PAGESIZE 0x08 +#define XHCI_OPER_REG_DNCTRL 0x14 +#define XHCI_OPER_REG_CRCR_LO 0x18 +#define XHCI_CRCR_RCS (1 << 0) +#define XHCI_CRCR_CS (1 << 1) +#define XHCI_CRCR_CA (1 << 2) +#define XHCI_CRCR_CRR (1 << 3) +#define XHCI_OPER_REG_CRCR_HI 0x1C +#define XHCI_OPER_REG_DCBAAP_LO 0x30 +#define XHCI_OPER_REG_DCBAAP_HI 0x34 +#define XHCI_OPER_REG_CONFIG 0x38 + +#define XHCI_DBELL_DB_SZ 0x4 + +#define XHCI_INTR_REG_MFINDEX 0x00 +#define XHCI_INTR_REG_IR0 0x20 +#define XHCI_INTR_IR_SZ 0x20 + +#define XHCI_INTR_REG_IMAN 0x00 +#define XHCI_IMAN_IP (1 << 0) +#define XHCI_IMAN_IE (1 << 1) +#define XHCI_INTR_REG_IMOD 0x04 +#define XHCI_INTR_REG_ERSTSZ 0x08 +#define XHCI_INTR_REG_ERSTBA_LO 0x10 +#define XHCI_INTR_REG_ERSTBA_HI 0x14 +#define XHCI_INTR_REG_ERDP_LO 0x18 +#define XHCI_ERDP_EHB (1 << 3) +#define XHCI_INTR_REG_ERDP_HI 0x1C + +#define TRB_SIZE 16 +typedef struct XHCITRB { + uint64_t parameter; + uint32_t status; + uint32_t control; + dma_addr_t addr; + bool ccs; +} XHCITRB; + +enum { + PLS_U0 = 0, + PLS_U1 = 1, + PLS_U2 = 2, + PLS_U3 = 3, + PLS_DISABLED = 4, + PLS_RX_DETECT = 5, + PLS_INACTIVE = 6, + PLS_POLLING = 7, + PLS_RECOVERY = 8, + PLS_HOT_RESET = 9, + PLS_COMPILANCE_MODE = 10, + PLS_TEST_MODE = 11, + PLS_RESUME = 15, +}; + +#define CR_LINK TR_LINK + +#define TRB_C (1 << 0) +#define TRB_TYPE_SHIFT 10 +#define TRB_TYPE_MASK 0x3f +#define TRB_TYPE(t) (((t).control >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK) + +#define TRB_EV_ED (1 << 2) + +#define TRB_TR_ENT (1 << 1) +#define TRB_TR_ISP (1 << 2) +#define TRB_TR_NS (1 << 3) +#define TRB_TR_CH (1 << 4) +#define TRB_TR_IOC (1 << 5) +#define TRB_TR_IDT (1 << 6) +#define TRB_TR_TBC_SHIFT 7 +#define TRB_TR_TBC_MASK 0x3 +#define TRB_TR_BEI (1 << 9) +#define TRB_TR_TLBPC_SHIFT 16 +#define TRB_TR_TLBPC_MASK 0xf +#define TRB_TR_FRAMEID_SHIFT 20 +#define TRB_TR_FRAMEID_MASK 0x7ff +#define TRB_TR_SIA (1 << 31) + +#define TRB_TR_DIR (1 << 16) + +#define TRB_CR_SLOTID_SHIFT 24 +#define TRB_CR_SLOTID_MASK 0xff +#define TRB_CR_EPID_SHIFT 16 +#define TRB_CR_EPID_MASK 0x1f + +#define TRB_CR_BSR (1 << 9) +#define TRB_CR_DC (1 << 9) + +#define TRB_LK_TC (1 << 1) + +#define TRB_INTR_SHIFT 22 +#define TRB_INTR_MASK 0x3ff +#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK) + +#define EP_TYPE_MASK 0x7 +#define EP_TYPE_SHIFT 3 + +#define EP_STATE_MASK 0x7 +#define EP_DISABLED (0 << 0) +#define EP_RUNNING (1 << 0) +#define EP_HALTED (2 << 0) +#define EP_STOPPED (3 << 0) +#define EP_ERROR (4 << 0) + +#define SLOT_STATE_MASK 0x1f +#define SLOT_STATE_SHIFT 27 +#define SLOT_STATE(s) (((s) >> SLOT_STATE_SHIFT) & SLOT_STATE_MASK) +#define SLOT_ENABLED 0 +#define SLOT_DEFAULT 1 +#define SLOT_ADDRESSED 2 +#define SLOT_CONFIGURED 3 + +#define SLOT_CONTEXT_ENTRIES_MASK 0x1f +#define SLOT_CONTEXT_ENTRIES_SHIFT 27 + +typedef enum EPType { + ET_INVALID = 0, + ET_ISO_OUT, + ET_BULK_OUT, + ET_INTR_OUT, + ET_CONTROL, + ET_ISO_IN, + ET_BULK_IN, + ET_INTR_IN, +} EPType; + typedef struct XHCIRing { dma_addr_t dequeue; bool ccs; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 00d5bc37792..d21b0543957 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -47,8 +47,8 @@ #define TRANSFER_LIMIT 256 #define LEN_CAP 0x40 -#define LEN_OPER (0x400 + 0x10 * XHCI_MAXPORTS) -#define LEN_RUNTIME ((XHCI_MAXINTRS + 1) * 0x20) +#define LEN_OPER (0x400 + XHCI_PORT_PR_SZ * XHCI_MAXPORTS) +#define LEN_RUNTIME ((XHCI_MAXINTRS + 1) * XHCI_INTR_IR_SZ) #define LEN_DOORBELL ((XHCI_MAXSLOTS + 1) * 0x20) #define OFF_OPER LEN_CAP @@ -65,154 +65,6 @@ # error Increase XHCI_LEN_REGS #endif -/* bit definitions */ -#define USBCMD_RS (1<<0) -#define USBCMD_HCRST (1<<1) -#define USBCMD_INTE (1<<2) -#define USBCMD_HSEE (1<<3) -#define USBCMD_LHCRST (1<<7) -#define USBCMD_CSS (1<<8) -#define USBCMD_CRS (1<<9) -#define USBCMD_EWE (1<<10) -#define USBCMD_EU3S (1<<11) - -#define USBSTS_HCH (1<<0) -#define USBSTS_HSE (1<<2) -#define USBSTS_EINT (1<<3) -#define USBSTS_PCD (1<<4) -#define USBSTS_SSS (1<<8) -#define USBSTS_RSS (1<<9) -#define USBSTS_SRE (1<<10) -#define USBSTS_CNR (1<<11) -#define USBSTS_HCE (1<<12) - - -#define PORTSC_CCS (1<<0) -#define PORTSC_PED (1<<1) -#define PORTSC_OCA (1<<3) -#define PORTSC_PR (1<<4) -#define PORTSC_PLS_SHIFT 5 -#define PORTSC_PLS_MASK 0xf -#define PORTSC_PP (1<<9) -#define PORTSC_SPEED_SHIFT 10 -#define PORTSC_SPEED_MASK 0xf -#define PORTSC_SPEED_FULL (1<<10) -#define PORTSC_SPEED_LOW (2<<10) -#define PORTSC_SPEED_HIGH (3<<10) -#define PORTSC_SPEED_SUPER (4<<10) -#define PORTSC_PIC_SHIFT 14 -#define PORTSC_PIC_MASK 0x3 -#define PORTSC_LWS (1<<16) -#define PORTSC_CSC (1<<17) -#define PORTSC_PEC (1<<18) -#define PORTSC_WRC (1<<19) -#define PORTSC_OCC (1<<20) -#define PORTSC_PRC (1<<21) -#define PORTSC_PLC (1<<22) -#define PORTSC_CEC (1<<23) -#define PORTSC_CAS (1<<24) -#define PORTSC_WCE (1<<25) -#define PORTSC_WDE (1<<26) -#define PORTSC_WOE (1<<27) -#define PORTSC_DR (1<<30) -#define PORTSC_WPR (1<<31) - -#define CRCR_RCS (1<<0) -#define CRCR_CS (1<<1) -#define CRCR_CA (1<<2) -#define CRCR_CRR (1<<3) - -#define IMAN_IP (1<<0) -#define IMAN_IE (1<<1) - -#define ERDP_EHB (1<<3) - -#define TRB_SIZE 16 -typedef struct XHCITRB { - uint64_t parameter; - uint32_t status; - uint32_t control; - dma_addr_t addr; - bool ccs; -} XHCITRB; - -enum { - PLS_U0 = 0, - PLS_U1 = 1, - PLS_U2 = 2, - PLS_U3 = 3, - PLS_DISABLED = 4, - PLS_RX_DETECT = 5, - PLS_INACTIVE = 6, - PLS_POLLING = 7, - PLS_RECOVERY = 8, - PLS_HOT_RESET = 9, - PLS_COMPILANCE_MODE = 10, - PLS_TEST_MODE = 11, - PLS_RESUME = 15, -}; - -#define CR_LINK TR_LINK - -#define TRB_C (1<<0) -#define TRB_TYPE_SHIFT 10 -#define TRB_TYPE_MASK 0x3f -#define TRB_TYPE(t) (((t).control >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK) - -#define TRB_EV_ED (1<<2) - -#define TRB_TR_ENT (1<<1) -#define TRB_TR_ISP (1<<2) -#define TRB_TR_NS (1<<3) -#define TRB_TR_CH (1<<4) -#define TRB_TR_IOC (1<<5) -#define TRB_TR_IDT (1<<6) -#define TRB_TR_TBC_SHIFT 7 -#define TRB_TR_TBC_MASK 0x3 -#define TRB_TR_BEI (1<<9) -#define TRB_TR_TLBPC_SHIFT 16 -#define TRB_TR_TLBPC_MASK 0xf -#define TRB_TR_FRAMEID_SHIFT 20 -#define TRB_TR_FRAMEID_MASK 0x7ff -#define TRB_TR_SIA (1<<31) - -#define TRB_TR_DIR (1<<16) - -#define TRB_CR_SLOTID_SHIFT 24 -#define TRB_CR_SLOTID_MASK 0xff -#define TRB_CR_EPID_SHIFT 16 -#define TRB_CR_EPID_MASK 0x1f - -#define TRB_CR_BSR (1<<9) -#define TRB_CR_DC (1<<9) - -#define TRB_LK_TC (1<<1) - -#define TRB_INTR_SHIFT 22 -#define TRB_INTR_MASK 0x3ff -#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK) - -#define EP_TYPE_MASK 0x7 -#define EP_TYPE_SHIFT 3 - -#define EP_STATE_MASK 0x7 -#define EP_DISABLED (0<<0) -#define EP_RUNNING (1<<0) -#define EP_HALTED (2<<0) -#define EP_STOPPED (3<<0) -#define EP_ERROR (4<<0) - -#define SLOT_STATE_MASK 0x1f -#define SLOT_STATE_SHIFT 27 -#define SLOT_STATE(s) (((s)>>SLOT_STATE_SHIFT)&SLOT_STATE_MASK) -#define SLOT_ENABLED 0 -#define SLOT_DEFAULT 1 -#define SLOT_ADDRESSED 2 -#define SLOT_CONFIGURED 3 - -#define SLOT_CONTEXT_ENTRIES_MASK 0x1f -#define SLOT_CONTEXT_ENTRIES_SHIFT 27 - #define get_field(data, field) \ (((data) >> field##_SHIFT) & field##_MASK) @@ -223,17 +75,6 @@ enum { *data = val_; \ } while (0) -typedef enum EPType { - ET_INVALID = 0, - ET_ISO_OUT, - ET_BULK_OUT, - ET_INTR_OUT, - ET_CONTROL, - ET_ISO_IN, - ET_BULK_IN, - ET_INTR_IN, -} EPType; - typedef struct XHCITransfer { XHCIEPContext *epctx; USBPacket packet; @@ -440,7 +281,7 @@ static uint64_t xhci_mfindex_get(XHCIState *xhci) static void xhci_mfwrap_update(XHCIState *xhci) { - const uint32_t bits = USBCMD_RS | USBCMD_EWE; + const uint32_t bits = XHCI_USBCMD_RS | XHCI_USBCMD_EWE; uint32_t mfindex, left; int64_t now; @@ -465,7 +306,7 @@ static void xhci_mfwrap_timer(void *opaque) static void xhci_die(XHCIState *xhci) { - xhci->usbsts |= USBSTS_HCE; + xhci->usbsts |= XHCI_USBSTS_HCE; DPRINTF("xhci: asserted controller error\n"); } @@ -557,51 +398,51 @@ static void xhci_intr_update(XHCIState *xhci, int v) int level = 0; if (v == 0) { - if (xhci->intr[0].iman & IMAN_IP && - xhci->intr[0].iman & IMAN_IE && - xhci->usbcmd & USBCMD_INTE) { + if (xhci->intr[0].iman & XHCI_IMAN_IP && + xhci->intr[0].iman & XHCI_IMAN_IE && + xhci->usbcmd & XHCI_USBCMD_INTE) { level = 1; } if (xhci->intr_raise) { if (xhci->intr_raise(xhci, 0, level)) { - xhci->intr[0].iman &= ~IMAN_IP; + xhci->intr[0].iman &= ~XHCI_IMAN_IP; } } } if (xhci->intr_update) { xhci->intr_update(xhci, v, - xhci->intr[v].iman & IMAN_IE); + xhci->intr[v].iman & XHCI_IMAN_IE); } } static void xhci_intr_raise(XHCIState *xhci, int v) { - bool pending = (xhci->intr[v].erdp_low & ERDP_EHB); + bool pending = (xhci->intr[v].erdp_low & XHCI_ERDP_EHB); - xhci->intr[v].erdp_low |= ERDP_EHB; - xhci->intr[v].iman |= IMAN_IP; - xhci->usbsts |= USBSTS_EINT; + xhci->intr[v].erdp_low |= XHCI_ERDP_EHB; + xhci->intr[v].iman |= XHCI_IMAN_IP; + xhci->usbsts |= XHCI_USBSTS_EINT; if (pending) { return; } - if (!(xhci->intr[v].iman & IMAN_IE)) { + if (!(xhci->intr[v].iman & XHCI_IMAN_IE)) { return; } - if (!(xhci->usbcmd & USBCMD_INTE)) { + if (!(xhci->usbcmd & XHCI_USBCMD_INTE)) { return; } if (xhci->intr_raise) { if (xhci->intr_raise(xhci, v, true)) { - xhci->intr[v].iman &= ~IMAN_IP; + xhci->intr[v].iman &= ~XHCI_IMAN_IP; } } } static inline int xhci_running(XHCIState *xhci) { - return !(xhci->usbsts & USBSTS_HCH); + return !(xhci->usbsts & XHCI_USBSTS_HCH); } static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v) @@ -845,15 +686,15 @@ static void xhci_er_reset(XHCIState *xhci, int v) static void xhci_run(XHCIState *xhci) { trace_usb_xhci_run(); - xhci->usbsts &= ~USBSTS_HCH; + xhci->usbsts &= ~XHCI_USBSTS_HCH; xhci->mfindex_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); } static void xhci_stop(XHCIState *xhci) { trace_usb_xhci_stop(); - xhci->usbsts |= USBSTS_HCH; - xhci->crcr_low &= ~CRCR_CRR; + xhci->usbsts |= XHCI_USBSTS_HCH; + xhci->crcr_low &= ~XHCI_CRCR_CRR; } static XHCIStreamContext *xhci_alloc_stream_contexts(unsigned count, @@ -2479,7 +2320,7 @@ static void xhci_process_commands(XHCIState *xhci) return; } - xhci->crcr_low |= CRCR_CRR; + xhci->crcr_low |= XHCI_CRCR_CRR; while ((type = xhci_ring_fetch(xhci, &xhci->cmd_ring, &trb, &addr))) { event.ptr = addr; @@ -2631,32 +2472,32 @@ static void xhci_port_update(XHCIPort *port, int is_detach) uint32_t pls = PLS_RX_DETECT; assert(port); - port->portsc = PORTSC_PP; + port->portsc = XHCI_PORTSC_PP; if (!is_detach && xhci_port_have_device(port)) { - port->portsc |= PORTSC_CCS; + port->portsc |= XHCI_PORTSC_CCS; switch (port->uport->dev->speed) { case USB_SPEED_LOW: - port->portsc |= PORTSC_SPEED_LOW; + port->portsc |= XHCI_PORTSC_SPEED_LOW; pls = PLS_POLLING; break; case USB_SPEED_FULL: - port->portsc |= PORTSC_SPEED_FULL; + port->portsc |= XHCI_PORTSC_SPEED_FULL; pls = PLS_POLLING; break; case USB_SPEED_HIGH: - port->portsc |= PORTSC_SPEED_HIGH; + port->portsc |= XHCI_PORTSC_SPEED_HIGH; pls = PLS_POLLING; break; case USB_SPEED_SUPER: - port->portsc |= PORTSC_SPEED_SUPER; - port->portsc |= PORTSC_PED; + port->portsc |= XHCI_PORTSC_SPEED_SUPER; + port->portsc |= XHCI_PORTSC_PED; pls = PLS_U0; break; } } - set_field(&port->portsc, pls, PORTSC_PLS); + set_field(&port->portsc, pls, XHCI_PORTSC_PLS); trace_usb_xhci_port_link(port->portnr, pls); - xhci_port_notify(port, PORTSC_CSC); + xhci_port_notify(port, XHCI_PORTSC_CSC); } static void xhci_port_reset(XHCIPort *port, bool warm_reset) @@ -2672,20 +2513,20 @@ static void xhci_port_reset(XHCIPort *port, bool warm_reset) switch (port->uport->dev->speed) { case USB_SPEED_SUPER: if (warm_reset) { - port->portsc |= PORTSC_WRC; + port->portsc |= XHCI_PORTSC_WRC; } /* fall through */ case USB_SPEED_LOW: case USB_SPEED_FULL: case USB_SPEED_HIGH: - set_field(&port->portsc, PLS_U0, PORTSC_PLS); + set_field(&port->portsc, PLS_U0, XHCI_PORTSC_PLS); trace_usb_xhci_port_link(port->portnr, PLS_U0); - port->portsc |= PORTSC_PED; + port->portsc |= XHCI_PORTSC_PED; break; } - port->portsc &= ~PORTSC_PR; - xhci_port_notify(port, PORTSC_PRC); + port->portsc &= ~XHCI_PORTSC_PR; + xhci_port_notify(port, XHCI_PORTSC_PRC); } static void xhci_reset(DeviceState *dev) @@ -2694,12 +2535,12 @@ static void xhci_reset(DeviceState *dev) int i; trace_usb_xhci_reset(); - if (!(xhci->usbsts & USBSTS_HCH)) { + if (!(xhci->usbsts & XHCI_USBSTS_HCH)) { DPRINTF("xhci: reset while running!\n"); } xhci->usbcmd = 0; - xhci->usbsts = USBSTS_HCH; + xhci->usbsts = XHCI_USBSTS_HCH; xhci->dnctrl = 0; xhci->crcr_low = 0; xhci->crcr_high = 0; @@ -2740,56 +2581,56 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) uint32_t ret; switch (reg) { - case 0x00: /* HCIVERSION, CAPLENGTH */ + case XHCI_HCCAP_REG_CAPLENGTH: /* Covers HCIVERSION and CAPLENGTH */ ret = 0x01000000 | LEN_CAP; break; - case 0x04: /* HCSPARAMS 1 */ + case XHCI_HCCAP_REG_HCSPARAMS1: ret = ((xhci->numports_2+xhci->numports_3)<<24) | (xhci->numintrs<<8) | xhci->numslots; break; - case 0x08: /* HCSPARAMS 2 */ + case XHCI_HCCAP_REG_HCSPARAMS2: ret = 0x0000000f; break; - case 0x0c: /* HCSPARAMS 3 */ + case XHCI_HCCAP_REG_HCSPARAMS3: ret = 0x00000000; break; - case 0x10: /* HCCPARAMS */ - if (sizeof(dma_addr_t) == 4) { - ret = 0x00080000 | (xhci->max_pstreams_mask << 12); - } else { - ret = 0x00080001 | (xhci->max_pstreams_mask << 12); + case XHCI_HCCAP_REG_HCCPARAMS1: + ret = (XHCI_HCCAP_EXTCAP_START / 4) << XHCI_HCCPARAMS1_XECP_SHIFT; + ret |= xhci->max_pstreams_mask << XHCI_HCCPARAMS1_MAXPSASIZE_SHIFT; + if (sizeof(dma_addr_t) == 8) { + ret |= XHCI_HCCPARAMS1_AC64; } break; - case 0x14: /* DBOFF */ + case XHCI_HCCAP_REG_DBOFF: ret = OFF_DOORBELL; break; - case 0x18: /* RTSOFF */ + case XHCI_HCCAP_REG_RTSOFF: ret = OFF_RUNTIME; break; /* extended capabilities */ - case 0x20: /* Supported Protocol:00 */ + case XHCI_HCCAP_EXTCAP_START + 0x00: /* Supported Protocol:00 */ ret = 0x02000402; /* USB 2.0 */ break; - case 0x24: /* Supported Protocol:04 */ + case XHCI_HCCAP_EXTCAP_START + 0x04: /* Supported Protocol:04 */ ret = 0x20425355; /* "USB " */ break; - case 0x28: /* Supported Protocol:08 */ + case XHCI_HCCAP_EXTCAP_START + 0x08: /* Supported Protocol:08 */ ret = (xhci->numports_2 << 8) | (xhci->numports_3 + 1); break; - case 0x2c: /* Supported Protocol:0c */ + case XHCI_HCCAP_EXTCAP_START + 0x0c: /* Supported Protocol:0c */ ret = 0x00000000; /* reserved */ break; - case 0x30: /* Supported Protocol:00 */ + case XHCI_HCCAP_EXTCAP_START + 0x10: /* Supported Protocol:00 */ ret = 0x03000002; /* USB 3.0 */ break; - case 0x34: /* Supported Protocol:04 */ + case XHCI_HCCAP_EXTCAP_START + 0x14: /* Supported Protocol:04 */ ret = 0x20425355; /* "USB " */ break; - case 0x38: /* Supported Protocol:08 */ + case XHCI_HCCAP_EXTCAP_START + 0x18: /* Supported Protocol:08 */ ret = (xhci->numports_3 << 8) | 1; break; - case 0x3c: /* Supported Protocol:0c */ + case XHCI_HCCAP_EXTCAP_START + 0x1c: /* Supported Protocol:0c */ ret = 0x00000000; /* reserved */ break; default: @@ -2807,14 +2648,18 @@ static uint64_t xhci_port_read(void *ptr, hwaddr reg, unsigned size) uint32_t ret; switch (reg) { - case 0x00: /* PORTSC */ + case XHCI_PORT_REG_PORTSC: ret = port->portsc; break; - case 0x04: /* PORTPMSC */ - case 0x08: /* PORTLI */ + case XHCI_PORT_REG_PORTLI: ret = 0; break; - case 0x0c: /* PORTHLPMC */ + case XHCI_PORT_REG_PORTPMSC: + ret = 0; + qemu_log_mask(LOG_UNIMP, "%s: read from port register PORTHPMSC", + __func__); + break; + case XHCI_PORT_REG_PORTHLPMC: ret = 0; qemu_log_mask(LOG_UNIMP, "%s: read from port register PORTHLPMC", __func__); @@ -2839,37 +2684,35 @@ static void xhci_port_write(void *ptr, hwaddr reg, trace_usb_xhci_port_write(port->portnr, reg, val); switch (reg) { - case 0x00: /* PORTSC */ + case XHCI_PORT_REG_PORTSC: /* write-1-to-start bits */ - if (val & PORTSC_WPR) { + if (val & XHCI_PORTSC_WPR) { xhci_port_reset(port, true); break; } - if (val & PORTSC_PR) { + if (val & XHCI_PORTSC_PR) { xhci_port_reset(port, false); break; } portsc = port->portsc; notify = 0; - /* write-1-to-clear bits*/ - portsc &= ~(val & (PORTSC_CSC|PORTSC_PEC|PORTSC_WRC|PORTSC_OCC| - PORTSC_PRC|PORTSC_PLC|PORTSC_CEC)); - if (val & PORTSC_LWS) { + portsc &= ~(val & XHCI_PORTSC_W1C_MASK); + if (val & XHCI_PORTSC_LWS) { /* overwrite PLS only when LWS=1 */ - uint32_t old_pls = get_field(port->portsc, PORTSC_PLS); - uint32_t new_pls = get_field(val, PORTSC_PLS); + uint32_t old_pls = get_field(port->portsc, XHCI_PORTSC_PLS); + uint32_t new_pls = get_field(val, XHCI_PORTSC_PLS); switch (new_pls) { case PLS_U0: if (old_pls != PLS_U0) { - set_field(&portsc, new_pls, PORTSC_PLS); + set_field(&portsc, new_pls, XHCI_PORTSC_PLS); trace_usb_xhci_port_link(port->portnr, new_pls); - notify = PORTSC_PLC; + notify = XHCI_PORTSC_PLC; } break; case PLS_U3: if (old_pls < PLS_U3) { - set_field(&portsc, new_pls, PORTSC_PLS); + set_field(&portsc, new_pls, XHCI_PORTSC_PLS); trace_usb_xhci_port_link(port->portnr, new_pls); } break; @@ -2882,22 +2725,21 @@ static void xhci_port_write(void *ptr, hwaddr reg, break; } } - /* read/write bits */ - portsc &= ~(PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE); - portsc |= (val & (PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE)); + portsc &= ~XHCI_PORTSC_RW_MASK; + portsc |= val & XHCI_PORTSC_RW_MASK; port->portsc = portsc; if (notify) { xhci_port_notify(port, notify); } break; - case 0x04: /* PORTPMSC */ - case 0x0c: /* PORTHLPMC */ + case XHCI_PORT_REG_PORTPMSC: + case XHCI_PORT_REG_PORTHLPMC: qemu_log_mask(LOG_UNIMP, "%s: write 0x%" PRIx64 " (%u bytes) to port register at offset 0x%" HWADDR_PRIx, __func__, val, size, reg); break; - case 0x08: /* PORTLI */ + case XHCI_PORT_REG_PORTLI: qemu_log_mask(LOG_GUEST_ERROR, "%s: Write to read-only PORTLI register", __func__); break; @@ -2916,31 +2758,31 @@ static uint64_t xhci_oper_read(void *ptr, hwaddr reg, unsigned size) uint32_t ret; switch (reg) { - case 0x00: /* USBCMD */ + case XHCI_OPER_REG_USBCMD: ret = xhci->usbcmd; break; - case 0x04: /* USBSTS */ + case XHCI_OPER_REG_USBSTS: ret = xhci->usbsts; break; - case 0x08: /* PAGESIZE */ + case XHCI_OPER_REG_PAGESIZE: ret = 1; /* 4KiB */ break; - case 0x14: /* DNCTRL */ + case XHCI_OPER_REG_DNCTRL: ret = xhci->dnctrl; break; - case 0x18: /* CRCR low */ + case XHCI_OPER_REG_CRCR_LO: ret = xhci->crcr_low & ~0xe; break; - case 0x1c: /* CRCR high */ + case XHCI_OPER_REG_CRCR_HI: ret = xhci->crcr_high; break; - case 0x30: /* DCBAAP low */ + case XHCI_OPER_REG_DCBAAP_LO: ret = xhci->dcbaap_low; break; - case 0x34: /* DCBAAP high */ + case XHCI_OPER_REG_DCBAAP_HI: ret = xhci->dcbaap_high; break; - case 0x38: /* CONFIG */ + case XHCI_OPER_REG_CONFIG: ret = xhci->config; break; default: @@ -2960,60 +2802,60 @@ static void xhci_oper_write(void *ptr, hwaddr reg, trace_usb_xhci_oper_write(reg, val); switch (reg) { - case 0x00: /* USBCMD */ - if ((val & USBCMD_RS) && !(xhci->usbcmd & USBCMD_RS)) { + case XHCI_OPER_REG_USBCMD: + if ((val & XHCI_USBCMD_RS) && !(xhci->usbcmd & XHCI_USBCMD_RS)) { xhci_run(xhci); - } else if (!(val & USBCMD_RS) && (xhci->usbcmd & USBCMD_RS)) { + } else if (!(val & XHCI_USBCMD_RS) && (xhci->usbcmd & XHCI_USBCMD_RS)) { xhci_stop(xhci); } - if (val & USBCMD_CSS) { + if (val & XHCI_USBCMD_CSS) { /* save state */ - xhci->usbsts &= ~USBSTS_SRE; + xhci->usbsts &= ~XHCI_USBSTS_SRE; } - if (val & USBCMD_CRS) { + if (val & XHCI_USBCMD_CRS) { /* restore state */ - xhci->usbsts |= USBSTS_SRE; + xhci->usbsts |= XHCI_USBSTS_SRE; } xhci->usbcmd = val & 0xc0f; xhci_mfwrap_update(xhci); - if (val & USBCMD_HCRST) { + if (val & XHCI_USBCMD_HCRST) { xhci_reset(DEVICE(xhci)); } xhci_intr_update(xhci, 0); break; - case 0x04: /* USBSTS */ - /* these bits are write-1-to-clear */ - xhci->usbsts &= ~(val & (USBSTS_HSE|USBSTS_EINT|USBSTS_PCD|USBSTS_SRE)); + case XHCI_OPER_REG_USBSTS: + xhci->usbsts &= ~(val & XHCI_USBSTS_W1C_MASK); xhci_intr_update(xhci, 0); break; - case 0x14: /* DNCTRL */ + case XHCI_OPER_REG_DNCTRL: xhci->dnctrl = val & 0xffff; break; - case 0x18: /* CRCR low */ - xhci->crcr_low = (val & 0xffffffcf) | (xhci->crcr_low & CRCR_CRR); + case XHCI_OPER_REG_CRCR_LO: + xhci->crcr_low = (val & 0xffffffcf) | (xhci->crcr_low & XHCI_CRCR_CRR); break; - case 0x1c: /* CRCR high */ + case XHCI_OPER_REG_CRCR_HI: xhci->crcr_high = val; - if (xhci->crcr_low & (CRCR_CA|CRCR_CS) && (xhci->crcr_low & CRCR_CRR)) { + if (xhci->crcr_low & (XHCI_CRCR_CA | XHCI_CRCR_CS) && + (xhci->crcr_low & XHCI_CRCR_CRR)) { XHCIEvent event = {ER_COMMAND_COMPLETE, CC_COMMAND_RING_STOPPED}; - xhci->crcr_low &= ~CRCR_CRR; + xhci->crcr_low &= ~XHCI_CRCR_CRR; xhci_event(xhci, &event, 0); DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low); } else { dma_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val); xhci_ring_init(xhci, &xhci->cmd_ring, base); } - xhci->crcr_low &= ~(CRCR_CA | CRCR_CS); + xhci->crcr_low &= ~(XHCI_CRCR_CA | XHCI_CRCR_CS); break; - case 0x30: /* DCBAAP low */ + case XHCI_OPER_REG_DCBAAP_LO: xhci->dcbaap_low = val & 0xffffffc0; break; - case 0x34: /* DCBAAP high */ + case XHCI_OPER_REG_DCBAAP_HI: xhci->dcbaap_high = val; break; - case 0x38: /* CONFIG */ + case XHCI_OPER_REG_CONFIG: xhci->config = val & 0xff; break; default: @@ -3027,9 +2869,9 @@ static uint64_t xhci_runtime_read(void *ptr, hwaddr reg, XHCIState *xhci = ptr; uint32_t ret = 0; - if (reg < 0x20) { + if (reg < XHCI_INTR_REG_IR0) { switch (reg) { - case 0x00: /* MFINDEX */ + case XHCI_INTR_REG_MFINDEX: ret = xhci_mfindex_get(xhci) & 0x3fff; break; default: @@ -3037,28 +2879,28 @@ static uint64_t xhci_runtime_read(void *ptr, hwaddr reg, break; } } else { - int v = (reg - 0x20) / 0x20; + int v = (reg - XHCI_INTR_REG_IR0) / XHCI_INTR_IR_SZ; XHCIInterrupter *intr = &xhci->intr[v]; - switch (reg & 0x1f) { - case 0x00: /* IMAN */ + switch (reg & (XHCI_INTR_IR_SZ - 1)) { + case XHCI_INTR_REG_IMAN: ret = intr->iman; break; - case 0x04: /* IMOD */ + case XHCI_INTR_REG_IMOD: ret = intr->imod; break; - case 0x08: /* ERSTSZ */ + case XHCI_INTR_REG_ERSTSZ: ret = intr->erstsz; break; - case 0x10: /* ERSTBA low */ + case XHCI_INTR_REG_ERSTBA_LO: ret = intr->erstba_low; break; - case 0x14: /* ERSTBA high */ + case XHCI_INTR_REG_ERSTBA_HI: ret = intr->erstba_high; break; - case 0x18: /* ERDP low */ + case XHCI_INTR_REG_ERDP_LO: ret = intr->erdp_low; break; - case 0x1c: /* ERDP high */ + case XHCI_INTR_REG_ERDP_HI: ret = intr->erdp_high; break; } @@ -3077,29 +2919,29 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, trace_usb_xhci_runtime_write(reg, val); - if (reg < 0x20) { + if (reg < XHCI_INTR_REG_IR0) { trace_usb_xhci_unimplemented("runtime write", reg); return; } - v = (reg - 0x20) / 0x20; + v = (reg - XHCI_INTR_REG_IR0) / XHCI_INTR_IR_SZ; intr = &xhci->intr[v]; - switch (reg & 0x1f) { - case 0x00: /* IMAN */ - if (val & IMAN_IP) { - intr->iman &= ~IMAN_IP; + switch (reg & (XHCI_INTR_IR_SZ - 1)) { + case XHCI_INTR_REG_IMAN: + if (val & XHCI_IMAN_IP) { + intr->iman &= ~XHCI_IMAN_IP; } - intr->iman &= ~IMAN_IE; - intr->iman |= val & IMAN_IE; + intr->iman &= ~XHCI_IMAN_IE; + intr->iman |= val & XHCI_IMAN_IE; xhci_intr_update(xhci, v); break; - case 0x04: /* IMOD */ + case XHCI_INTR_REG_IMOD: intr->imod = val; break; - case 0x08: /* ERSTSZ */ + case XHCI_INTR_REG_ERSTSZ: intr->erstsz = val & 0xffff; break; - case 0x10: /* ERSTBA low */ + case XHCI_INTR_REG_ERSTBA_LO: if (xhci->nec_quirks) { /* NEC driver bug: it doesn't align this to 64 bytes */ intr->erstba_low = val & 0xfffffff0; @@ -3107,16 +2949,17 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, intr->erstba_low = val & 0xffffffc0; } break; - case 0x14: /* ERSTBA high */ + case XHCI_INTR_REG_ERSTBA_HI: intr->erstba_high = val; xhci_er_reset(xhci, v); break; - case 0x18: /* ERDP low */ - if (val & ERDP_EHB) { - intr->erdp_low &= ~ERDP_EHB; + case XHCI_INTR_REG_ERDP_LO: + if (val & XHCI_ERDP_EHB) { + intr->erdp_low &= ~XHCI_ERDP_EHB; } - intr->erdp_low = (val & ~ERDP_EHB) | (intr->erdp_low & ERDP_EHB); - if (val & ERDP_EHB) { + intr->erdp_low = (val & ~XHCI_ERDP_EHB) | + (intr->erdp_low & XHCI_ERDP_EHB); + if (val & XHCI_ERDP_EHB) { dma_addr_t erdp = xhci_addr64(intr->erdp_low, intr->erdp_high); unsigned int dp_idx = (erdp - intr->er_start) / TRB_SIZE; if (erdp >= intr->er_start && @@ -3126,7 +2969,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, } } break; - case 0x1c: /* ERDP high */ + case XHCI_INTR_REG_ERDP_HI: intr->erdp_high = val; break; default: @@ -3155,8 +2998,7 @@ static void xhci_doorbell_write(void *ptr, hwaddr reg, return; } - reg >>= 2; - + reg /= XHCI_DBELL_DB_SZ; if (reg == 0) { if (val == 0) { xhci_process_commands(xhci); @@ -3249,11 +3091,11 @@ static void xhci_wakeup(USBPort *usbport) XHCIPort *port = xhci_lookup_port(xhci, usbport); assert(port); - if (get_field(port->portsc, PORTSC_PLS) != PLS_U3) { + if (get_field(port->portsc, XHCI_PORTSC_PLS) != PLS_U3) { return; } - set_field(&port->portsc, PLS_RESUME, PORTSC_PLS); - xhci_port_notify(port, PORTSC_PLC); + set_field(&port->portsc, PLS_RESUME, XHCI_PORTSC_PLS); + xhci_port_notify(port, XHCI_PORTSC_PLC); } static void xhci_complete(USBPort *port, USBPacket *packet) @@ -3340,7 +3182,7 @@ static void usb_xhci_init(XHCIState *xhci) XHCIPort *port; unsigned int i, usbports, speedmask; - xhci->usbsts = USBSTS_HCH; + xhci->usbsts = XHCI_USBSTS_HCH; if (xhci->numports_2 > XHCI_MAXPORTS_2) { xhci->numports_2 = XHCI_MAXPORTS_2; @@ -3428,10 +3270,10 @@ static void usb_xhci_realize(DeviceState *dev, Error **errp) for (i = 0; i < xhci->numports; i++) { XHCIPort *port = &xhci->ports[i]; - uint32_t offset = OFF_OPER + 0x400 + 0x10 * i; + uint32_t offset = OFF_OPER + 0x400 + XHCI_PORT_PR_SZ * i; port->xhci = xhci; memory_region_init_io(&port->mem, OBJECT(dev), &xhci_port_ops, port, - port->name, 0x10); + port->name, XHCI_PORT_PR_SZ); memory_region_add_subregion(&xhci->mem, offset, &port->mem); } } From patchwork Sat Jan 18 07:08:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 13944095 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AD501C02187 for ; Sat, 18 Jan 2025 07:09:57 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tZ2xS-0003Dc-PZ; Sat, 18 Jan 2025 02:09:27 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tZ2xG-0003CP-Ru for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:17 -0500 Received: from mail-pl1-x630.google.com ([2607:f8b0:4864:20::630]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tZ2xE-0007oB-Qk for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:14 -0500 Received: by mail-pl1-x630.google.com with SMTP id d9443c01a7336-2161eb94cceso35890205ad.2 for ; Fri, 17 Jan 2025 23:09:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1737184150; x=1737788950; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/cx7Pxt/DNCLGhkMoyXvElc9TbIWqgkun0mAfcUqVZM=; b=kiuHL/xee5wlwkfNvZbPWQB1y0NuwP9nwuQ08yScfdB4JOYcuoSTGn+fhLgr+YFh4s uJBbvBz0XbIlJDLDZeVelO4/ltbuldcFTPORVZPSZ6/O3pbygzcZ7Nu2UVD17BqZRvoT o2z70pTShwVVyvcV6oWWPGcuU1tyh8yF9fX+XmFSv+ucJ6WrkrFNTqvbiWJN/kiJwrWa SljWqIByAUOEiMNqKTbB9hBIgHkHr27CWZ5ARdoVG+j+NCnQ792unndnduPTeONAEUn0 2zNQlEJR5MxT+UMex/a8YmthoWmANoKHMvJCOi2KJa3uWU9xfTiyULmEIkCvkp5CbdeN zlIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737184150; x=1737788950; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/cx7Pxt/DNCLGhkMoyXvElc9TbIWqgkun0mAfcUqVZM=; b=U04OkVQhmEjuxCVJOQUAzRHK65Iuzs6eNf0GH9jHa+cfyGOmVFfnhuCBEv8zDCRL4T 6zUxlAY7Ip38sotZ0FndItFN6t9Q3d7x7dbUb/QKu7KHNEWPFGETunI+OWnq1ZdmlbK9 tLrklmhIcVbLB4OaRqByRtxo+6CeFTbc5qe/kAuNpI5j9jHb72rrac+HJlbXwGS0PyiK W8CrL+01qG6ufBRiWwRyF2vmL+jKKXYsEmZQg6KUjdLI3sIOfTSgqWSZZX/pCivRA+7L npZI39CRE2dR2Kmybd5pSA3VahIEmULFMiicNKn6vFypxBe0+D24Dsam4auwqvhK5/kF 2uig== X-Gm-Message-State: AOJu0Yy35Nrd5/aX7ct2Ipyld7+UuhW9t+C8J+In7wprDm3e+QgS+qn0 pg9GrmtCua4wqTIoM3WYdLC3YskeXvk7nTPAgjQxSLXY6Km1+7PfYLIo9g== X-Gm-Gg: ASbGncsJCPMR9mHavsenpHjnjWHaMWLsWzzU8wa2YlYRoCZUC8w/BSP9+DqZnfBWDfr UElV52NLDs1hX26KOx7Ic6L9iE3cfeUKcAEWfeMnR8rE+bZKqGWNvOyJ33dd5n0Id6zbnlfFVYU /Bfa3LJ9hjtIvwC5crgdiYsYHTKcy7hqltRGMnPJ1WL4ZipiFKI1Oxfkufkn/r7yzwzHYFFGCdh p1LmqjG4umFFCo+JQV9aZkfamccPNYyrGuGBwKycAUpqIs/nFsk9S3v+cIe6OJwHdSqDPhdTQWW J3UOGdZxq3ORGa9gzMx2xgKO1czN X-Google-Smtp-Source: AGHT+IFqOuidF1n+qV3hPTMWqVK5wrAuoYBjE8s6o6zAgBZpsRzpqVXTrXXYo5T7/G3RNeoWw0rybw== X-Received: by 2002:a05:6a21:164e:b0:1e0:d1c3:97d1 with SMTP id adf61e73a8af0-1eb215685b5mr10475199637.29.1737184150547; Fri, 17 Jan 2025 23:09:10 -0800 (PST) Received: from wheely.local0.net (124-169-212-233.tpgi.com.au. [124.169.212.233]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72dab9c95adsm3192880b3a.107.2025.01.17.23.09.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jan 2025 23:09:10 -0800 (PST) From: Nicholas Piggin To: qemu-devel@nongnu.org Cc: Nicholas Piggin , Paolo Bonzini , "Michael S. Tsirkin" , Marcel Apfelbaum , Fabiano Rosas , Laurent Vivier , Phil Dennis-Jordan Subject: [PATCH v2 2/8] hw/usb/xhci: Rename and move HCD register region constants to header Date: Sat, 18 Jan 2025 17:08:47 +1000 Message-ID: <20250118070853.653778-3-npiggin@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250118070853.653778-1-npiggin@gmail.com> References: <20250118070853.653778-1-npiggin@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::630; envelope-from=npiggin@gmail.com; helo=mail-pl1-x630.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This also adds some missing constants rather than open-coding offsets and sizes. Signed-off-by: Nicholas Piggin --- hw/usb/hcd-xhci.h | 16 ++++++++++++++++ hw/usb/hcd-xhci.c | 48 ++++++++++++++++++++++------------------------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h index bd1d8e8e81a..8557f59dafe 100644 --- a/hw/usb/hcd-xhci.h +++ b/hw/usb/hcd-xhci.h @@ -115,6 +115,22 @@ typedef enum TRBCCode { CC_SPLIT_TRANSACTION_ERROR } TRBCCode; +/* Register regions */ +#define XHCI_REGS_LENGTH_CAP 0x40 +#define XHCI_REGS_LENGTH_OPER 0x400 +#define XHCI_REGS_LENGTH_PORT (XHCI_PORT_PR_SZ * XHCI_MAXPORTS) +#define XHCI_REGS_LENGTH_RUNTIME ((XHCI_MAXINTRS + 1) * XHCI_INTR_IR_SZ) +/* XXX: Should doorbell length be *4 rather than *32? */ +#define XHCI_REGS_LENGTH_DOORBELL ((XHCI_MAXSLOTS + 1) * 0x20) + +#define XHCI_REGS_OFFSET_CAP 0 +#define XHCI_REGS_OFFSET_OPER (XHCI_REGS_OFFSET_CAP + \ + XHCI_REGS_LENGTH_CAP) +#define XHCI_REGS_OFFSET_PORT (XHCI_REGS_OFFSET_OPER + \ + XHCI_REGS_LENGTH_OPER) +#define XHCI_REGS_OFFSET_RUNTIME 0x1000 +#define XHCI_REGS_OFFSET_DOORBELL 0x2000 + /* Register definitions */ #define XHCI_HCCAP_REG_CAPLENGTH 0x00 #define XHCI_HCCAP_REG_HCIVERSION 0x02 diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index d21b0543957..76eb473c150 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -46,22 +46,14 @@ #define COMMAND_LIMIT 256 #define TRANSFER_LIMIT 256 -#define LEN_CAP 0x40 -#define LEN_OPER (0x400 + XHCI_PORT_PR_SZ * XHCI_MAXPORTS) -#define LEN_RUNTIME ((XHCI_MAXINTRS + 1) * XHCI_INTR_IR_SZ) -#define LEN_DOORBELL ((XHCI_MAXSLOTS + 1) * 0x20) - -#define OFF_OPER LEN_CAP -#define OFF_RUNTIME 0x1000 -#define OFF_DOORBELL 0x2000 - -#if (OFF_OPER + LEN_OPER) > OFF_RUNTIME -#error Increase OFF_RUNTIME +#if (XHCI_REGS_OFFSET_PORT + XHCI_REGS_LENGTH_PORT) > XHCI_REGS_OFFSET_RUNTIME +#error Increase XHCI_REGS_OFFSET_RUNTIME #endif -#if (OFF_RUNTIME + LEN_RUNTIME) > OFF_DOORBELL -#error Increase OFF_DOORBELL +#if (XHCI_REGS_OFFSET_RUNTIME + XHCI_REGS_LENGTH_RUNTIME) > \ + XHCI_REGS_OFFSET_DOORBELL +#error Increase XHCI_REGS_OFFSET_DOORBELL #endif -#if (OFF_DOORBELL + LEN_DOORBELL) > XHCI_LEN_REGS +#if (XHCI_REGS_OFFSET_DOORBELL + XHCI_REGS_LENGTH_DOORBELL) > XHCI_LEN_REGS # error Increase XHCI_LEN_REGS #endif @@ -2582,7 +2574,7 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) switch (reg) { case XHCI_HCCAP_REG_CAPLENGTH: /* Covers HCIVERSION and CAPLENGTH */ - ret = 0x01000000 | LEN_CAP; + ret = 0x01000000 | XHCI_REGS_LENGTH_CAP; break; case XHCI_HCCAP_REG_HCSPARAMS1: ret = ((xhci->numports_2+xhci->numports_3)<<24) @@ -2602,10 +2594,10 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) } break; case XHCI_HCCAP_REG_DBOFF: - ret = OFF_DOORBELL; + ret = XHCI_REGS_OFFSET_DOORBELL; break; case XHCI_HCCAP_REG_RTSOFF: - ret = OFF_RUNTIME; + ret = XHCI_REGS_OFFSET_RUNTIME; break; /* extended capabilities */ @@ -3255,22 +3247,26 @@ static void usb_xhci_realize(DeviceState *dev, Error **errp) memory_region_init(&xhci->mem, OBJECT(dev), "xhci", XHCI_LEN_REGS); memory_region_init_io(&xhci->mem_cap, OBJECT(dev), &xhci_cap_ops, xhci, - "capabilities", LEN_CAP); + "capabilities", XHCI_REGS_LENGTH_CAP); memory_region_init_io(&xhci->mem_oper, OBJECT(dev), &xhci_oper_ops, xhci, - "operational", 0x400); + "operational", XHCI_REGS_LENGTH_OPER); memory_region_init_io(&xhci->mem_runtime, OBJECT(dev), &xhci_runtime_ops, - xhci, "runtime", LEN_RUNTIME); + xhci, "runtime", XHCI_REGS_LENGTH_RUNTIME); memory_region_init_io(&xhci->mem_doorbell, OBJECT(dev), &xhci_doorbell_ops, - xhci, "doorbell", LEN_DOORBELL); + xhci, "doorbell", XHCI_REGS_LENGTH_DOORBELL); - memory_region_add_subregion(&xhci->mem, 0, &xhci->mem_cap); - memory_region_add_subregion(&xhci->mem, OFF_OPER, &xhci->mem_oper); - memory_region_add_subregion(&xhci->mem, OFF_RUNTIME, &xhci->mem_runtime); - memory_region_add_subregion(&xhci->mem, OFF_DOORBELL, &xhci->mem_doorbell); + memory_region_add_subregion(&xhci->mem, XHCI_REGS_OFFSET_CAP, + &xhci->mem_cap); + memory_region_add_subregion(&xhci->mem, XHCI_REGS_OFFSET_OPER, + &xhci->mem_oper); + memory_region_add_subregion(&xhci->mem, XHCI_REGS_OFFSET_RUNTIME, + &xhci->mem_runtime); + memory_region_add_subregion(&xhci->mem, XHCI_REGS_OFFSET_DOORBELL, + &xhci->mem_doorbell); for (i = 0; i < xhci->numports; i++) { XHCIPort *port = &xhci->ports[i]; - uint32_t offset = OFF_OPER + 0x400 + XHCI_PORT_PR_SZ * i; + uint32_t offset = XHCI_REGS_OFFSET_PORT + XHCI_PORT_PR_SZ * i; port->xhci = xhci; memory_region_init_io(&port->mem, OBJECT(dev), &xhci_port_ops, port, port->name, XHCI_PORT_PR_SZ); From patchwork Sat Jan 18 07:08:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 13944099 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 40789C02185 for ; Sat, 18 Jan 2025 07:10:32 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tZ2xU-0003Ea-2L; Sat, 18 Jan 2025 02:09:28 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tZ2xO-0003DF-9I for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:22 -0500 Received: from mail-pj1-x1030.google.com ([2607:f8b0:4864:20::1030]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tZ2xJ-0007ov-NY for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:20 -0500 Received: by mail-pj1-x1030.google.com with SMTP id 98e67ed59e1d1-2ee50ffcf14so6419989a91.0 for ; Fri, 17 Jan 2025 23:09:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1737184155; x=1737788955; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FyfxFiQXudQSGc+5H8K041E8vPTe9Roj2xyajI/ltTw=; b=DTWY7uNxAOF/T+T8kA/lBd08NcLV+9nlZXTcGj8snMRV207/VtPu5uZJRZRksBRYLN Gx7w6n7pdQMZCB+7or/LD2U+JcqIGuzi1pP9dKhSEeN2skSps9hWgyTHH6hLi6yf+Ang WSNM0bBHfrJ8w0M3rccrIHmqEcXySm39AwdJ0whtWh3GxlnJyffuxjHbpm+Nz0fReUjy MigkFgaJtLlCVK7DgMN+UF96ILZckuo60uyA2YsaBFQHeHtBaT3AyxK77N0tKkkEe/rz MiZWfkxYqZ7ZyP/lntZg0e+xm3nUIYESdDAfsRtOVcaii5i6alNlXim5CYnhld2w1M+z DBVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737184155; x=1737788955; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FyfxFiQXudQSGc+5H8K041E8vPTe9Roj2xyajI/ltTw=; b=DlloC0hJHQPbKNBmQq6HxOrNpwF6osQJcZBgq8ibSWY0dw2sWk1ZZH1FnTMwnshAMW 7rOy1SX59LX6ypRIAnXqtcIVNXT4WzAFkZkYJ49fVutJeURbclMbo64j9Bm6LGkUsRR5 NAQDUI9aGjuLGObVKvmW0WiV5KgIvpMpKyZcOFYJi7cWNnKVm9c6ypl6cNQ/W/XBbquC S1sMNJGMx3lUwAiGJjfUA4RFIUMTSzCr1SnLH33MBWYisYx6BRq8tV/2jySYsxO0OBZm E8ZXnKeewOCsgfOfJRvbCmUxcTmg41Wu2ugvyy3eMbIo7KFxG1X1VA1y8Lfe0Mo+z8Dm egww== X-Gm-Message-State: AOJu0YyaFpsl57XKHrYS/Gqb7ru1+B7K+PKauZUGRRKwzMGsdb9gmAnf 81qDM8I2c19+zygxwoVvcXRasgQdcTSyZS1rDi2rbcJOxblwsg8wtvHAtQ== X-Gm-Gg: ASbGncsb177ZjiM4pxUvIc70z9EaIQoir5g3GIPhZEOoMTNXbRjbP8zeJLRBo88vPxi 96qTwliumL/kSoKjGnI4+uSq6G71ofgGswnu6DWMSxRw3onO/kLQgB1beUChX+RlnO+l3+nOK1a cs3kFFKNfZMQXNeCJVwbfTUVj1sdc9ufJGIZlUcqVzriubWrgTbhEWRHS48j+mB7XvUdyRejR73 O8/ropbRuoAIT8DIADe4itQ9VoM9fC45F7BUyvN8hdNaf6d2JhOhHDB4x5W/JBKFIyl3zeSgVBY pJqbo8tYwmweth098QWlr+aS6mRP X-Google-Smtp-Source: AGHT+IHJghDw7thYh/TE2Ye4+QtthoWfkyhfKoWqXDtneRn25939xEaJ2fFFaNaPvMpSDoUg9ZA9RQ== X-Received: by 2002:a05:6a00:1d12:b0:728:15fd:dabb with SMTP id d2e1a72fcca58-72db1c5d820mr8449779b3a.8.1737184154878; Fri, 17 Jan 2025 23:09:14 -0800 (PST) Received: from wheely.local0.net (124-169-212-233.tpgi.com.au. [124.169.212.233]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72dab9c95adsm3192880b3a.107.2025.01.17.23.09.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jan 2025 23:09:14 -0800 (PST) From: Nicholas Piggin To: qemu-devel@nongnu.org Cc: Nicholas Piggin , Paolo Bonzini , "Michael S. Tsirkin" , Marcel Apfelbaum , Fabiano Rosas , Laurent Vivier , Phil Dennis-Jordan Subject: [PATCH v2 3/8] tests/qtest/xhci: Add controller and device setup and ring tests Date: Sat, 18 Jan 2025 17:08:48 +1000 Message-ID: <20250118070853.653778-4-npiggin@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250118070853.653778-1-npiggin@gmail.com> References: <20250118070853.653778-1-npiggin@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1030; envelope-from=npiggin@gmail.com; helo=mail-pj1-x1030.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add tests which init the host controller registers to the point where command and event rings, irqs are operational. Enumerate ports and set up an attached device context that enables device transfer ring to be set up and tested. This test does a bunch of things at once and is not yet well librified, but it allows testing basic mechanisms and gives a starting point for further work. Signed-off-by: Nicholas Piggin --- hw/usb/hcd-xhci.h | 7 + hw/usb/hcd-xhci.c | 7 - tests/qtest/usb-hcd-xhci-test.c | 516 +++++++++++++++++++++++++++++++- 3 files changed, 517 insertions(+), 13 deletions(-) diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h index 8557f59dafe..d149ef59c11 100644 --- a/hw/usb/hcd-xhci.h +++ b/hw/usb/hcd-xhci.h @@ -350,6 +350,13 @@ typedef struct XHCIRing { bool ccs; } XHCIRing; +typedef struct XHCIEvRingSeg { + uint32_t addr_low; + uint32_t addr_high; + uint32_t size; + uint32_t rsvd; +} XHCIEvRingSeg; + typedef struct XHCIPort { XHCIState *xhci; uint32_t portsc; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 76eb473c150..c68cf268365 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -128,13 +128,6 @@ struct XHCIEPContext { QEMUTimer *kick_timer; }; -typedef struct XHCIEvRingSeg { - uint32_t addr_low; - uint32_t addr_high; - uint32_t size; - uint32_t rsvd; -} XHCIEvRingSeg; - static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid, unsigned int streamid); static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid); diff --git a/tests/qtest/usb-hcd-xhci-test.c b/tests/qtest/usb-hcd-xhci-test.c index 0cccfd85a64..b9fb2356d26 100644 --- a/tests/qtest/usb-hcd-xhci-test.c +++ b/tests/qtest/usb-hcd-xhci-test.c @@ -8,17 +8,174 @@ */ #include "qemu/osdep.h" +#include "qemu/bswap.h" +#include "libqtest.h" +#include "libqos/libqos-pc.h" #include "libqtest-single.h" #include "libqos/usb.h" +#include "hw/pci/pci_ids.h" +#include "hw/pci/pci_regs.h" +#include "hw/usb/hcd-xhci.h" + +/*** Test Setup & Teardown ***/ +typedef struct XHCIQSlotState { + /* In-memory arrays */ + uint64_t device_context; + uint64_t transfer_ring; + + uint32_t tr_trb_entries; + uint32_t tr_trb_idx; + uint32_t tr_trb_c; +} XHCIQSlotState; + +typedef struct XHCIQState { + /* QEMU PCI variables */ + QOSState *parent; + QPCIDevice *dev; + QPCIBar bar; + uint64_t barsize; + uint32_t fingerprint; + + /* In-memory arrays */ + uint64_t dc_base_array; + uint64_t command_ring; + uint64_t event_ring_seg; + uint64_t event_ring; + + uint32_t cr_trb_entries; + uint32_t cr_trb_idx; + uint32_t cr_trb_c; + uint32_t er_trb_entries; + uint32_t er_trb_idx; + uint32_t er_trb_c; + + /* Host controller properties */ + uint32_t rtoff, dboff; + uint32_t maxports, maxslots, maxintrs; + + XHCIQSlotState slots[32]; +} XHCIQState; + +#define XHCI_NEC_ID (PCI_DEVICE_ID_NEC_UPD720200 << 16 | \ + PCI_VENDOR_ID_NEC) + +/** + * Locate, verify, and return a handle to the XHCI device. + */ +static QPCIDevice *get_xhci_device(QTestState *qts, uint32_t *fingerprint) +{ + QPCIDevice *xhci; + uint32_t xhci_fingerprint; + QPCIBus *pcibus; + + pcibus = qpci_new_pc(qts, NULL); + + /* Find the XHCI PCI device and verify it's the right one. */ + xhci = qpci_device_find(pcibus, QPCI_DEVFN(0x1D, 0x0)); + g_assert(xhci != NULL); + + xhci_fingerprint = qpci_config_readl(xhci, PCI_VENDOR_ID); + switch (xhci_fingerprint) { + case XHCI_NEC_ID: + break; + default: + /* Unknown device. */ + g_assert_not_reached(); + } + + if (fingerprint) { + *fingerprint = xhci_fingerprint; + } + return xhci; +} + +static void free_xhci_device(QPCIDevice *dev) +{ + QPCIBus *pcibus = dev ? dev->bus : NULL; + + /* libqos doesn't have a function for this, so free it manually */ + g_free(dev); + qpci_free_pc(pcibus); +} + +/** + * Start a Q35 machine and bookmark a handle to the XHCI device. + */ +G_GNUC_PRINTF(1, 0) +static XHCIQState *xhci_vboot(const char *cli, va_list ap) +{ + XHCIQState *s; + + s = g_new0(XHCIQState, 1); + s->parent = qtest_pc_vboot(cli, ap); + alloc_set_flags(&s->parent->alloc, ALLOC_LEAK_ASSERT); + + /* Verify that we have an XHCI device present. */ + s->dev = get_xhci_device(s->parent->qts, &s->fingerprint); + s->bar = qpci_iomap(s->dev, 0, &s->barsize); + /* turns on pci.cmd.iose, pci.cmd.mse and pci.cmd.bme */ + qpci_device_enable(s->dev); + + return s; +} + +/** + * Start a Q35 machine and bookmark a handle to the XHCI device. + */ +G_GNUC_PRINTF(1, 2) +static XHCIQState *xhci_boot(const char *cli, ...) +{ + XHCIQState *s; + va_list ap; + + if (cli) { + va_start(ap, cli); + s = xhci_vboot(cli, ap); + va_end(ap); + } else { + s = xhci_boot("-M q35 " + "-device nec-usb-xhci,id=xhci,bus=pcie.0,addr=1d.0 " + "-drive id=drive0,if=none,file=null-co://," + "file.read-zeroes=on,format=raw"); + } + + return s; +} + +/** + * Clean up the PCI device, then terminate the QEMU instance. + */ +static void xhci_shutdown(XHCIQState *xhci) +{ + QOSState *qs = xhci->parent; + + free_xhci_device(xhci->dev); + g_free(xhci); + qtest_shutdown(qs); +} + +/*** tests ***/ static void test_xhci_hotplug(void) { - usb_test_hotplug(global_qtest, "xhci", "1", NULL); + XHCIQState *s; + QTestState *qts; + + s = xhci_boot(NULL); + qts = s->parent->qts; + + usb_test_hotplug(qts, "xhci", "1", NULL); + + xhci_shutdown(s); } static void test_usb_uas_hotplug(void) { - QTestState *qts = global_qtest; + XHCIQState *s; + QTestState *qts; + + s = xhci_boot(NULL); + qts = s->parent->qts; qtest_qmp_device_add(qts, "usb-uas", "uas", "{}"); qtest_qmp_device_add(qts, "scsi-hd", "scsihd", "{'drive': 'drive0'}"); @@ -30,25 +187,371 @@ static void test_usb_uas_hotplug(void) qtest_qmp_device_del(qts, "scsihd"); qtest_qmp_device_del(qts, "uas"); + + xhci_shutdown(s); } static void test_usb_ccid_hotplug(void) { - QTestState *qts = global_qtest; + XHCIQState *s; + QTestState *qts; + + s = xhci_boot(NULL); + qts = s->parent->qts; qtest_qmp_device_add(qts, "usb-ccid", "ccid", "{}"); qtest_qmp_device_del(qts, "ccid"); /* check the device can be added again */ qtest_qmp_device_add(qts, "usb-ccid", "ccid", "{}"); qtest_qmp_device_del(qts, "ccid"); + + xhci_shutdown(s); +} + +static uint64_t xhci_guest_zalloc(XHCIQState *s, uint64_t size) +{ + char mem[0x1000]; + uint64_t ret; + + g_assert(size <= 0x1000); + + memset(mem, 0, size); + + ret = guest_alloc(&s->parent->alloc, size); + qtest_memwrite(s->parent->qts, ret, mem, size); + + return ret; +} + +static uint32_t xhci_cap_readl(XHCIQState *s, uint64_t addr) +{ + return qpci_io_readl(s->dev, s->bar, XHCI_REGS_OFFSET_CAP + addr); } +static uint32_t xhci_op_readl(XHCIQState *s, uint64_t addr) +{ + return qpci_io_readl(s->dev, s->bar, XHCI_REGS_OFFSET_OPER + addr); +} + +static void xhci_op_writel(XHCIQState *s, uint64_t addr, uint32_t value) +{ + qpci_io_writel(s->dev, s->bar, XHCI_REGS_OFFSET_OPER + addr, value); +} + +static uint32_t xhci_port_readl(XHCIQState *s, uint32_t port, uint64_t addr) +{ + return qpci_io_readl(s->dev, s->bar, + XHCI_REGS_OFFSET_PORT + port * XHCI_PORT_PR_SZ + addr); +} + +static uint32_t xhci_rt_readl(XHCIQState *s, uint64_t addr) +{ + return qpci_io_readl(s->dev, s->bar, s->rtoff + addr); +} + +static void xhci_rt_writel(XHCIQState *s, uint64_t addr, uint32_t value) +{ + qpci_io_writel(s->dev, s->bar, s->rtoff + addr, value); +} + +static uint32_t xhci_intr_readl(XHCIQState *s, uint32_t intr, uint64_t addr) +{ + return xhci_rt_readl(s, XHCI_INTR_REG_IR0 + + intr * XHCI_INTR_IR_SZ + addr); +} + + +static void xhci_intr_writel(XHCIQState *s, uint32_t intr, uint64_t addr, + uint32_t value) +{ + xhci_rt_writel(s, XHCI_INTR_REG_IR0 + + intr * XHCI_INTR_IR_SZ + addr, value); +} + +static void xhci_db_writel(XHCIQState *s, uint32_t db, uint32_t value) +{ + qpci_io_writel(s->dev, s->bar, s->dboff + db * XHCI_DBELL_DB_SZ, value); +} + +static void wait_event_trb(XHCIQState *s, XHCITRB *trb) +{ + XHCITRB t; + uint64_t er_addr = s->event_ring + s->er_trb_idx * TRB_SIZE; + uint32_t value; + guint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; + + /* Wait for event interrupt */ + + do { + if (g_get_monotonic_time() >= end_time) { + g_error("Timeout expired"); + } + qtest_clock_step(s->parent->qts, 10000); + + value = xhci_op_readl(s, XHCI_OPER_REG_USBSTS); + } while (!(value & XHCI_USBSTS_EINT)); + + value = xhci_intr_readl(s, 0, XHCI_INTR_REG_IMAN); + + /* With MSI-X enabled, IMAN IP is cleared after raising the interrupt */ + g_assert(!(value & XHCI_IMAN_IP)); + + /* Ensure MSI-X interrupt is pending. */ + /* XXX: this is never cleared so it doesn't verify multiple interrupts. + * should enable the msix vector like e1000e */ + assert(qpci_msix_pending(s->dev, 0)); + + xhci_op_writel(s, XHCI_OPER_REG_USBSTS, XHCI_USBSTS_EINT); /* clear EINT */ + + qtest_memread(s->parent->qts, er_addr, &t, TRB_SIZE); + + trb->parameter = le64_to_cpu(t.parameter); + trb->status = le32_to_cpu(t.status); + trb->control = le32_to_cpu(t.control); + + g_assert((trb->status >> 24) == CC_SUCCESS); + g_assert((trb->control & TRB_C) == s->er_trb_c); /* C bit has been set */ + + s->er_trb_idx++; + if (s->er_trb_idx == s->er_trb_entries) { + s->er_trb_idx = 0; + s->er_trb_c ^= 1; + } + /* Update ERDP to processed TRB addr and EHB bit, which clears EHB */ + er_addr = s->event_ring + s->er_trb_idx * TRB_SIZE; + xhci_intr_writel(s, 0, XHCI_INTR_REG_ERDP_LO, + (er_addr & 0xffffffff) | XHCI_ERDP_EHB); +} + +static void set_link_trb(XHCIQState *s, uint64_t ring, uint32_t c, + uint32_t entries) +{ + XHCITRB trb; + + g_assert(entries > 1); + + memset(&trb, 0, TRB_SIZE); + trb.parameter = cpu_to_le64(ring); + trb.control = cpu_to_le32(c | /* C */ + (TR_LINK << TRB_TYPE_SHIFT) | + TRB_LK_TC); + qtest_memwrite(s->parent->qts, ring + TRB_SIZE * (entries - 1), + &trb, TRB_SIZE); +} + +static void submit_cr_trb(XHCIQState *s, XHCITRB *trb) +{ + uint64_t cr_addr = s->command_ring + s->cr_trb_idx * TRB_SIZE; + XHCITRB t; + + trb->control |= s->cr_trb_c; /* C */ + + t.parameter = cpu_to_le64(trb->parameter); + t.status = cpu_to_le32(trb->status); + t.control = cpu_to_le32(trb->control); + + qtest_memwrite(s->parent->qts, cr_addr, &t, TRB_SIZE); + s->cr_trb_idx++; + /* Last entry contains the link, so wrap back */ + if (s->cr_trb_idx == s->cr_trb_entries - 1) { + set_link_trb(s, s->command_ring, s->cr_trb_c, s->cr_trb_entries); + s->cr_trb_idx = 0; + s->cr_trb_c ^= 1; + } + xhci_db_writel(s, 0, 0); /* doorbell 0 */ +} + +/* + * This test brings up an endpoint and runs some noops through its command + * ring and gets responses back on the event ring. + * + * This could be librified in future (like AHCI0 to have a way to bring up + * an endpoint to test device protocols. + */ +static void pci_xhci_stress_rings(void) +{ + XHCIQState *s; + uint32_t value; + uint64_t input_context; + XHCIEvRingSeg ev_seg; + XHCITRB trb; + uint32_t hcsparams1; + uint32_t slotid; + g_autofree void *mem = g_malloc0(0x1000); /* buffer for writing to guest */ + int i; + + s = xhci_boot("-M q35 " + "-device nec-usb-xhci,id=xhci,bus=pcie.0,addr=1d.0 " + "-device usb-storage,bus=xhci.0,drive=drive0 " + "-drive id=drive0,if=none,file=null-co://," + "file.read-zeroes=on,format=raw " + ); + + hcsparams1 = xhci_cap_readl(s, XHCI_HCCAP_REG_HCSPARAMS1); + s->maxports = (hcsparams1 >> 24) & 0xff; + s->maxintrs = (hcsparams1 >> 8) & 0x3ff; + s->maxslots = hcsparams1 & 0xff; + + s->dboff = xhci_cap_readl(s, XHCI_HCCAP_REG_DBOFF); + s->rtoff = xhci_cap_readl(s, XHCI_HCCAP_REG_RTSOFF); + + s->dc_base_array = xhci_guest_zalloc(s, 0x800); + s->command_ring = xhci_guest_zalloc(s, 0x1000); + s->event_ring = xhci_guest_zalloc(s, 0x1000); + s->event_ring_seg = xhci_guest_zalloc(s, 0x100); + + /* Arbitrary small sizes so we can make them wrap */ + s->cr_trb_entries = 0x20; + s->cr_trb_c = 1; + s->er_trb_entries = 0x10; + s->er_trb_c = 1; + + ev_seg.addr_low = cpu_to_le32(s->event_ring & 0xffffffff); + ev_seg.addr_high = cpu_to_le32(s->event_ring >> 32); + ev_seg.size = cpu_to_le32(0x10); + ev_seg.rsvd = 0; + qtest_memwrite(s->parent->qts, s->event_ring_seg, &ev_seg, sizeof(ev_seg)); + + xhci_op_writel(s, XHCI_OPER_REG_USBCMD, XHCI_USBCMD_HCRST); + do { + value = xhci_op_readl(s, XHCI_OPER_REG_USBSTS); + } while (value & XHCI_USBSTS_CNR); + + xhci_op_writel(s, XHCI_OPER_REG_CONFIG, s->maxslots); + + xhci_op_writel(s, XHCI_OPER_REG_DCBAAP_LO, s->dc_base_array & 0xffffffff); + xhci_op_writel(s, XHCI_OPER_REG_DCBAAP_HI, s->dc_base_array >> 32); + + xhci_op_writel(s, XHCI_OPER_REG_CRCR_LO, + (s->command_ring & 0xffffffff) | s->cr_trb_c); + xhci_op_writel(s, XHCI_OPER_REG_CRCR_HI, s->command_ring >> 32); + + xhci_intr_writel(s, 0, XHCI_INTR_REG_ERSTSZ, 1); + + xhci_intr_writel(s, 0, XHCI_INTR_REG_ERSTBA_LO, + s->event_ring_seg & 0xffffffff); + xhci_intr_writel(s, 0, XHCI_INTR_REG_ERSTBA_HI, + s->event_ring_seg >> 32); + + /* ERDP */ + xhci_intr_writel(s, 0, XHCI_INTR_REG_ERDP_LO, s->event_ring & 0xffffffff); + xhci_intr_writel(s, 0, XHCI_INTR_REG_ERDP_HI, s->event_ring >> 32); + + qpci_msix_enable(s->dev); + xhci_op_writel(s, XHCI_OPER_REG_USBCMD, XHCI_USBCMD_RS | XHCI_USBCMD_INTE); + + /* Enable interrupts on ER IMAN */ + xhci_intr_writel(s, 0, XHCI_INTR_REG_IMAN, XHCI_IMAN_IE); + + assert(!qpci_msix_pending(s->dev, 0)); + + /* Wrap the command and event rings with no-ops a few times */ + for (i = 0; i < 100; i++) { + /* Issue a command ring no-op */ + memset(&trb, 0, TRB_SIZE); + trb.control |= CR_NOOP << TRB_TYPE_SHIFT; + trb.control |= TRB_TR_IOC; + submit_cr_trb(s, &trb); + wait_event_trb(s, &trb); + } + + /* Query ports */ + for (i = 0; i < s->maxports; i++) { + value = xhci_port_readl(s, i, 0); /* PORTSC */ + + /* Only first port should be attached and enabled */ + if (i == 0) { + g_assert(value & XHCI_PORTSC_CCS); + g_assert(value & XHCI_PORTSC_PED); + /* Port Speed must be identified (non-zero) */ + g_assert(((value >> XHCI_PORTSC_SPEED_SHIFT) & + XHCI_PORTSC_SPEED_MASK) != 0); + } else { + g_assert(!(value & XHCI_PORTSC_CCS)); + g_assert(!(value & XHCI_PORTSC_PED)); + g_assert(((value >> XHCI_PORTSC_PLS_SHIFT) & + XHCI_PORTSC_PLS_MASK) == 5); + } + } + + /* Issue a command ring enable slot */ + memset(&trb, 0, TRB_SIZE); + trb.control |= CR_ENABLE_SLOT << TRB_TYPE_SHIFT; + trb.control |= TRB_TR_IOC; + submit_cr_trb(s, &trb); + wait_event_trb(s, &trb); + slotid = (trb.control >> TRB_CR_SLOTID_SHIFT) & 0xff; + + s->slots[slotid].transfer_ring = xhci_guest_zalloc(s, 0x1000); + s->slots[slotid].tr_trb_entries = 0x10; + s->slots[slotid].tr_trb_c = 1; + + /* 32-byte input context size, should check HCCPARAMS1 for 64-byte size */ + input_context = xhci_guest_zalloc(s, 0x420); + + /* Set input control context */ + ((uint32_t *)mem)[1] = cpu_to_le32(0x3); /* Add device contexts 0 and 1 */ + ((uint32_t *)mem)[8] = cpu_to_le32(1 << 27); /* 1 context entry */ + ((uint32_t *)mem)[9] = cpu_to_le32(1 << 16); /* 1 port number */ + + /* Set endpoint 0 context */ + ((uint32_t *)mem)[16] = 0; + ((uint32_t *)mem)[17] = cpu_to_le32((ET_CONTROL << EP_TYPE_SHIFT) | + (0x200 << 16)); /* max packet sz XXX? */ + ((uint32_t *)mem)[18] = cpu_to_le32((s->slots[slotid].transfer_ring & + 0xffffffff) | 1); /* DCS=1 */ + ((uint32_t *)mem)[19] = cpu_to_le32(s->slots[slotid].transfer_ring >> 32); + ((uint32_t *)mem)[20] = cpu_to_le32(0x200); /* Average TRB length */ + qtest_memwrite(s->parent->qts, input_context, mem, 0x420); + + s->slots[slotid].device_context = xhci_guest_zalloc(s, 0x400); + + ((uint64_t *)mem)[0] = cpu_to_le64(s->slots[slotid].device_context); + qtest_memwrite(s->parent->qts, s->dc_base_array + 8 * slotid, mem, 8); + + /* Issue a command ring address device */ + memset(&trb, 0, TRB_SIZE); + trb.parameter = input_context; + trb.control |= CR_ADDRESS_DEVICE << TRB_TYPE_SHIFT; + trb.control |= slotid << TRB_CR_SLOTID_SHIFT; + submit_cr_trb(s, &trb); + wait_event_trb(s, &trb); + + /* XXX: Could check EP state is running */ + + /* Shut it down */ + qpci_msix_disable(s->dev); + + guest_free(&s->parent->alloc, s->slots[slotid].device_context); + guest_free(&s->parent->alloc, s->slots[slotid].transfer_ring); + guest_free(&s->parent->alloc, input_context); + guest_free(&s->parent->alloc, s->event_ring); + guest_free(&s->parent->alloc, s->event_ring_seg); + guest_free(&s->parent->alloc, s->command_ring); + guest_free(&s->parent->alloc, s->dc_base_array); + + xhci_shutdown(s); +} + +/* tests */ int main(int argc, char **argv) { int ret; + const char *arch; g_test_init(&argc, &argv, NULL); + /* Check architecture */ + arch = qtest_get_arch(); + if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) { + g_test_message("Skipping test for non-x86"); + return 0; + } + + if (!qtest_has_device("nec-usb-xhci")) { + return 0; + } + qtest_add_func("/xhci/pci/hotplug", test_xhci_hotplug); if (qtest_has_device("usb-uas")) { qtest_add_func("/xhci/pci/hotplug/usb-uas", test_usb_uas_hotplug); @@ -56,11 +559,12 @@ int main(int argc, char **argv) if (qtest_has_device("usb-ccid")) { qtest_add_func("/xhci/pci/hotplug/usb-ccid", test_usb_ccid_hotplug); } + if (qtest_has_device("usb-storage")) { + qtest_add_func("/xhci/pci/xhci-stress-rings", pci_xhci_stress_rings); + } - qtest_start("-device nec-usb-xhci,id=xhci" - " -drive id=drive0,if=none,file=null-co://," - "file.read-zeroes=on,format=raw"); ret = g_test_run(); + qtest_end(); return ret; From patchwork Sat Jan 18 07:08:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 13944101 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C15A5C02185 for ; Sat, 18 Jan 2025 07:11:10 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tZ2xW-0003FA-1W; Sat, 18 Jan 2025 02:09:30 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tZ2xP-0003DH-QP for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:24 -0500 Received: from mail-pl1-x629.google.com ([2607:f8b0:4864:20::629]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tZ2xO-0007pI-27 for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:23 -0500 Received: by mail-pl1-x629.google.com with SMTP id d9443c01a7336-2165448243fso66777965ad.1 for ; Fri, 17 Jan 2025 23:09:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1737184159; x=1737788959; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=v4VzgFnlAufaRydiep0qE8J1DEBNHc9FILqOQebNfGs=; b=ZWIxXcz7F3qoPpbg60iLJMJ5G8TFU9Tx4D7kSrQYNMH3i6Gmh/Qu37mjgXcUogeF+C vOzRPWVfKS6DKdUcrG3gEw9nnkcIqk+6gmXtEdFWGYX5PZEClreDFzXHav46O7Pss71E YHInsKUhaxuw5ueQMb6KBeqtlxDR5tpa1zrOxfiO4K+g0Dqpa06orSAQqaVjygCLFT8Z Jkl8ibafaYO95rrk1KTn4d2ZSCZZb4AX+nxm+rsEpsJJTWIZPORMRmL8ZShtDNpnHFw9 3qTIzdVsJOrC3peh18YrWq8gudM/f7KoCTxmK1rFngDv1Tr344rFFpKZQC+pdNUETEDn dtlw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737184159; x=1737788959; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=v4VzgFnlAufaRydiep0qE8J1DEBNHc9FILqOQebNfGs=; b=Cl5KpbDWTLEq69H6haZiqw2tby0VXY9tecCjUcii6gw5VNCNRg+SpYyOvYxLxckaOA H6L9p+OZYpOm/YCEaf/ACJ2zPTFY02qlt3sgYOBrZnItgHq5a3oSDOwQTvcP4M6CleDG OJ3hrqF6F2AVZgp+NjN7eukpmhGIZ2jhAq27WHdT72vyTIV/NKCwoY1Q2iaGn2YmMkxK gDvl1nJ5HYzb5IgMjlAPF4NOyUoA/jkCgZdMFuFUAXbDQAGEnyhR0l0fS6bHLuYIqp7U 8PQLuUxy/IrMA0TPN76sni9sXFXsuxz4DOxqs1yhsn34UcFIwPjLyHQbH8rmPwYmu72r /PVQ== X-Gm-Message-State: AOJu0Yy+3QNnDUaN9AGq3PMv8AMa6PJgpaAZrtdlsbfbe3vmmCUmBcFy khXtHMiq5OcjUDcUPxJAiyyMVUVKw69WDuUbTpKiQhirCvgCqvRR0Tvjaw== X-Gm-Gg: ASbGncvmjTSVIT5E7IjU4Z6JdlH7NN6Cbg2Lhln7DdemQuKtg9zunUq8QLZ02Ty3MRk 8M1970/jQT40vnXq6VQMRWAP/IoQLwWUhj+CPcUALtvgkukf5aFSyHo3+auLzxwBuRUF2bP+mSf D5jBo7lZwRqLh1X02XITzzMLdMBSQkWiF0VbjnNJFjA1AeNAjF4zuRkPbXSOvBdjZFi5Z/p7zi1 dXZRsvR8vK/YoIrTmjaBE3eiBM7vV3K57eqTk2CF0H8vkkfknQJtGYo1b3EhVFl6N62XU0On0dU 1K2ODRiLlMbtJ2JvBEuh1ZQoyTA8 X-Google-Smtp-Source: AGHT+IEVZGUaGonDWGU/ppEhKH/xlMbup3a7MCMdcv83t90xMoyDnFls1udIPHlS6YLD5grw53SUGA== X-Received: by 2002:a05:6a20:3942:b0:1e0:c6c0:1e08 with SMTP id adf61e73a8af0-1eb214afe1cmr7864173637.25.1737184158882; Fri, 17 Jan 2025 23:09:18 -0800 (PST) Received: from wheely.local0.net (124-169-212-233.tpgi.com.au. [124.169.212.233]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72dab9c95adsm3192880b3a.107.2025.01.17.23.09.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jan 2025 23:09:18 -0800 (PST) From: Nicholas Piggin To: qemu-devel@nongnu.org Cc: Nicholas Piggin , Paolo Bonzini , "Michael S. Tsirkin" , Marcel Apfelbaum , Fabiano Rosas , Laurent Vivier , Phil Dennis-Jordan Subject: [PATCH v2 4/8] hw/usb/xhci: Support TR NOOP commands Date: Sat, 18 Jan 2025 17:08:49 +1000 Message-ID: <20250118070853.653778-5-npiggin@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250118070853.653778-1-npiggin@gmail.com> References: <20250118070853.653778-1-npiggin@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::629; envelope-from=npiggin@gmail.com; helo=mail-pl1-x629.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Implement XHCI TR NOOP commands by setting up then immediately completing the packet. The IBM AIX XHCI HCD driver uses NOOP commands to check driver and hardware health, which works after this change. Signed-off-by: Nicholas Piggin --- hw/usb/hcd-xhci.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index c68cf268365..256bee6c72f 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1662,6 +1662,20 @@ static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext return xhci_submit(xhci, xfer, epctx); } +static int xhci_noop_transfer(XHCIState *xhci, XHCITransfer *xfer) +{ + /* + * TR NOOP conceptually probably better not call into USB subsystem + * (usb_packet_setup() via xhci_setup_packet()). In practice it + * works and avoids code duplication. + */ + if (xhci_setup_packet(xfer) < 0) { + return -1; + } + xhci_try_complete_packet(xfer); + return 0; +} + static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid, unsigned int streamid) { @@ -1784,6 +1798,8 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) epctx->kick_active++; while (1) { + bool noop = false; + length = xhci_ring_chain_length(xhci, ring); if (length <= 0) { if (epctx->type == ET_ISO_OUT || epctx->type == ET_ISO_IN) { @@ -1812,10 +1828,20 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) epctx->kick_active--; return; } + if (type == TR_NOOP) { + noop = true; + } } xfer->streamid = streamid; - if (epctx->epid == 1) { + if (noop) { + if (length != 1) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: NOOP TR TRB within TRB chain!\n", __func__); + /* Undefined behavior, we no-op the entire chain */ + } + xhci_noop_transfer(xhci, xfer); + } else if (epctx->epid == 1) { xhci_fire_ctl_transfer(xhci, xfer); } else { xhci_fire_transfer(xhci, xfer, epctx); From patchwork Sat Jan 18 07:08:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 13944100 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C52E8C02185 for ; Sat, 18 Jan 2025 07:10:54 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tZ2xX-0003Fn-1M; Sat, 18 Jan 2025 02:09:31 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tZ2xS-0003Dv-Oe for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:27 -0500 Received: from mail-pj1-x1035.google.com ([2607:f8b0:4864:20::1035]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tZ2xQ-0007ps-Rk for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:26 -0500 Received: by mail-pj1-x1035.google.com with SMTP id 98e67ed59e1d1-2ef70c7efa5so4109691a91.2 for ; Fri, 17 Jan 2025 23:09:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1737184163; x=1737788963; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Auj/lFHkLSk6o6v8/a4KxcoWT3RjhdCD5eZzJWt0p3Y=; b=GCsphVSMJNz+jR0/gX7CYWAZtOHe1fquDmVI3h6vOhufqqm1bjUTBFcGkgCRLSNRM3 hWMMw31474jl/uwAT98yFUm9kUqRlxLncLRJ6oLlJMxYqxDuFn48uejh0dcEVrQqmH0k nknXc0kpsQklX40sslj4hbV8IkpyCmI0QB/4mXL8/Gwwr4F10EX5/D+ZD22jbvXrFDRE 6y6h/ih2Bg+bPIhyN/Bd76LBgOkI+641zO7cuIfUDdGdKUfIBYbNf5af3BE9IxdfKFam YDao0gYG5xwjXgntZHuPcPeBlFnjUnWnnqpRz3fsIZ8ncF3z93mX5wRvU18lQZwtj8li LBfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737184163; x=1737788963; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Auj/lFHkLSk6o6v8/a4KxcoWT3RjhdCD5eZzJWt0p3Y=; b=bhTq0aMOIgmWBWP7qJOpNBXNf7y2dVZ/xHeBWl8lbEyKdhpA0YkfcOFvRvAe0h9vUc dLAzAf8MmP3NcHFldjeV7mvoMI5gtEhcseASgyvTbBIm4SxoqPBzjVWZafnl2+2X5AAN 4DAvmjloyB9yJLyRH+eWzO7UoTz3+uNSdmSgsFfU0duAnpCLCe4njyCtdcnNCRBfeWl4 qx2V0lmM0sNAogPlyXS9bkCJ0gAfIfJDMtDGSp0QtmXKdq+oy5y7QdY0zU1nx1dNwqI+ pnIR3USrsYQhgQk+B2lymUqcB5MjRwmjQSJqEJgOzYwuNG49+MBKWkTPe/YYAu4TYQFz HQuA== X-Gm-Message-State: AOJu0YymuRXZuPjXo8LONpRm3zlZUhqtON2I2XSdit/pk/MvS3B/TsX7 iR9ydojwzAxsI7VlNySA7+NuvwC37gQ9czMRXCJQUp88bO0jA63IjtrtKQ== X-Gm-Gg: ASbGnct7Ymn6TO0H7alu84HoU8DZTAZobJXhpffGfzG1DupM9ccwSqAjauWkOxMtt2N l1PxQhTg26T/4IJy/jg8KfGCDy/DaD0V6QJt5luxBLUkMboLKSXCyS0GkBkn7sptUjikbTfBW+D smKLj11JtdfeahypZ2AVJzbVApaK9WMFLAomh4cR/B9J1W+6gLdzCc28qaZ4gEw+4f9I19AxU0w dpQDq7IYo7V2bsl7RRyRtqg5D8Ly6WjwuKuSjvNg3r6Aoi4+Z6xc7GczxerHORS8REd2xI/RB6S a6LS2BTDNC81HL/U6feHNNfe/Vxj X-Google-Smtp-Source: AGHT+IH4Ln7YyDyAVGQur8xll+OxxFjkqlv83CnGLLq0I4r5KEJMBbg6taLXxuKnSG3WQPNSNmD/NA== X-Received: by 2002:a05:6a00:1a94:b0:725:ea30:aafc with SMTP id d2e1a72fcca58-72daf929f5cmr6365577b3a.5.1737184162848; Fri, 17 Jan 2025 23:09:22 -0800 (PST) Received: from wheely.local0.net (124-169-212-233.tpgi.com.au. [124.169.212.233]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72dab9c95adsm3192880b3a.107.2025.01.17.23.09.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jan 2025 23:09:22 -0800 (PST) From: Nicholas Piggin To: qemu-devel@nongnu.org Cc: Nicholas Piggin , Paolo Bonzini , "Michael S. Tsirkin" , Marcel Apfelbaum , Fabiano Rosas , Laurent Vivier , Phil Dennis-Jordan Subject: [PATCH v2 5/8] tests/qtest/xhci: add a test for TR NOOP commands Date: Sat, 18 Jan 2025 17:08:50 +1000 Message-ID: <20250118070853.653778-6-npiggin@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250118070853.653778-1-npiggin@gmail.com> References: <20250118070853.653778-1-npiggin@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1035; envelope-from=npiggin@gmail.com; helo=mail-pj1-x1035.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Run some TR NOOP commands through the transfer ring. Signed-off-by: Nicholas Piggin --- tests/qtest/usb-hcd-xhci-test.c | 36 ++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/tests/qtest/usb-hcd-xhci-test.c b/tests/qtest/usb-hcd-xhci-test.c index b9fb2356d26..63359fb70b9 100644 --- a/tests/qtest/usb-hcd-xhci-test.c +++ b/tests/qtest/usb-hcd-xhci-test.c @@ -361,9 +361,33 @@ static void submit_cr_trb(XHCIQState *s, XHCITRB *trb) xhci_db_writel(s, 0, 0); /* doorbell 0 */ } +static void submit_tr_trb(XHCIQState *s, int slot, XHCITRB *trb) +{ + XHCIQSlotState *sl = &s->slots[slot]; + uint64_t tr_addr = sl->transfer_ring + sl->tr_trb_idx * TRB_SIZE; + XHCITRB t; + + trb->control |= sl->tr_trb_c; /* C */ + + t.parameter = cpu_to_le64(trb->parameter); + t.status = cpu_to_le32(trb->status); + t.control = cpu_to_le32(trb->control); + + qtest_memwrite(s->parent->qts, tr_addr, &t, TRB_SIZE); + sl->tr_trb_idx++; + /* Last entry contains the link, so wrap back */ + if (sl->tr_trb_idx == sl->tr_trb_entries - 1) { + set_link_trb(s, sl->transfer_ring, sl->tr_trb_c, sl->tr_trb_entries); + sl->tr_trb_idx = 0; + sl->tr_trb_c ^= 1; + } + xhci_db_writel(s, slot, 1); /* doorbell slot, EP0 target */ +} + /* * This test brings up an endpoint and runs some noops through its command - * ring and gets responses back on the event ring. + * ring and gets responses back on the event ring, then brings up a device + * context and runs some noops through its transfer ring. * * This could be librified in future (like AHCI0 to have a way to bring up * an endpoint to test device protocols. @@ -519,6 +543,16 @@ static void pci_xhci_stress_rings(void) /* XXX: Could check EP state is running */ + /* Wrap the transfer ring a few times */ + for (i = 0; i < 100; i++) { + /* Issue a transfer ring slot 0 noop */ + memset(&trb, 0, TRB_SIZE); + trb.control |= TR_NOOP << TRB_TYPE_SHIFT; + trb.control |= TRB_TR_IOC; + submit_tr_trb(s, slotid, &trb); + wait_event_trb(s, &trb); + } + /* Shut it down */ qpci_msix_disable(s->dev); From patchwork Sat Jan 18 07:08:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 13944097 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id ADDE6C02187 for ; Sat, 18 Jan 2025 07:10:16 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tZ2xY-0003G9-Fp; Sat, 18 Jan 2025 02:09:32 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tZ2xW-0003FZ-CC for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:30 -0500 Received: from mail-pj1-x1030.google.com ([2607:f8b0:4864:20::1030]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tZ2xU-0007qS-IN for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:30 -0500 Received: by mail-pj1-x1030.google.com with SMTP id 98e67ed59e1d1-2ef72924e53so4953326a91.3 for ; Fri, 17 Jan 2025 23:09:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1737184167; x=1737788967; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NiA0OcT7kkutyeI3Mw8qH8TpIB7VaMZJNO6sZmBmX5c=; b=DSCSMx4uG08s9avsnqRxoWZxcY5jqQz4MFZYQTK0MzPX2Ga/dBNlFy/K1HZJzsJpe3 a8n1jL1PLbBvDQr3C+NB02rPYcAcFy/B4Hv3QM6OItM6RQiXMBnk5Q7Ei1Hc12mcaIGG 62WJnUm5G3bA7rTBFHTqDZlETmJuTyqvNGiXz/yN8Lt/1PsldS6S7BWx/ZAIO2ZRdWE/ ECxra8FLYDwORHErHqFkalCILdf2g/AxmaUZNfG/Z5oVvnE1mcQF2F7Aj19yYkhkCGbx Jju6mZDZL5XLCM1uPJfNfbmkz4rvxAoP8T8igeePYPJ/q87jrHa+GygqReOuPzXtaKvM STzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737184167; x=1737788967; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NiA0OcT7kkutyeI3Mw8qH8TpIB7VaMZJNO6sZmBmX5c=; b=dh0v0MjmeEYoCC3q40svw5uN6O0GqYqkmm2KijTi+Q01xa4im4HRPMXENTz4c53KoT p4RsHy6owlbtHBsk/otEaWLBcfxxC1KAoVHv7DmPHPQSa3NZYlZlWC1fnPmOO7v2crmU YQnWPmbWQZFuKroBdiybb45uWMyLczDoLyyRc+FQw2mZOAYiY5dzdYF52wYZpLxEQ2pS YbxL3bc3yjYSOwUW92v50T/JA62TLubGWIqIOIuc+xSqyUfayAUJVc3rdTQnM8dSZ8H6 0owr+7tqcFpbAGa0lKvp5cue7MrS9feVG7UG1BV9BopaLf4XHjzqSWWYetezAYroZorM T0TQ== X-Gm-Message-State: AOJu0YwToHLA6kKcj0aU+pFmHq+TsDnn3lSqAX5jc0ut+eA1LJTiqisi EXUEzlZJN8FgitjuhwK8KEPuGhCYIfv/sCVvByWyU/U1DPQ+y0x3afbgTA== X-Gm-Gg: ASbGncsIIsUoupWF4tZ894BEy+l7U9WNG+wSR65PJrfchKpO0y1vIIzKKueFpjsZGhT n38GfzNFYiZUsLsdrtszxjSj2p8KM/rkuFP6J77ZriPzqx4T0Q3Q+V6AYn/rRUTr/9ayPmFGs4s zvhtsQ8R9rCs/HIUcyZlJgrpptwtCBu6CNLAG5XfZwJAB8RehbAk8yEnu2DwCtHS9+qGW1SWdSz IGP98d1OakhzvcMA4Ma+s9TZXr+TUyvnOJSOHm92jdMpQGiqAIbQIjEArPzc5TjAp/mHcMYZJPG jT0hbIyzv/Nptdp3bY8NoWZ2UNjhZTV/JbTelUw= X-Google-Smtp-Source: AGHT+IHnQfPGkLhPVoHjlW8FXQKRT/P6TOBtzhBUJcvdILFAYZ/NAyMNY7iZ4B/pNEpdy5234x+g9A== X-Received: by 2002:a05:6a00:cc9:b0:729:1c0f:b94a with SMTP id d2e1a72fcca58-72dafbc0447mr8682310b3a.23.1737184167005; Fri, 17 Jan 2025 23:09:27 -0800 (PST) Received: from wheely.local0.net (124-169-212-233.tpgi.com.au. [124.169.212.233]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72dab9c95adsm3192880b3a.107.2025.01.17.23.09.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jan 2025 23:09:26 -0800 (PST) From: Nicholas Piggin To: qemu-devel@nongnu.org Cc: Nicholas Piggin , Paolo Bonzini , "Michael S. Tsirkin" , Marcel Apfelbaum , Fabiano Rosas , Laurent Vivier , Phil Dennis-Jordan Subject: [PATCH v2 6/8] tests/qtest/xhci: test the qemu-xhci device Date: Sat, 18 Jan 2025 17:08:51 +1000 Message-ID: <20250118070853.653778-7-npiggin@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250118070853.653778-1-npiggin@gmail.com> References: <20250118070853.653778-1-npiggin@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1030; envelope-from=npiggin@gmail.com; helo=mail-pj1-x1030.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add support in the test code for running multiple drivers, and add tests for the qemu-xhci device. Signed-off-by: Nicholas Piggin --- tests/qtest/usb-hcd-xhci-test.c | 96 +++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/tests/qtest/usb-hcd-xhci-test.c b/tests/qtest/usb-hcd-xhci-test.c index 63359fb70b9..4efe7b69d4f 100644 --- a/tests/qtest/usb-hcd-xhci-test.c +++ b/tests/qtest/usb-hcd-xhci-test.c @@ -13,10 +13,15 @@ #include "libqos/libqos-pc.h" #include "libqtest-single.h" #include "libqos/usb.h" +#include "hw/pci/pci.h" #include "hw/pci/pci_ids.h" #include "hw/pci/pci_regs.h" #include "hw/usb/hcd-xhci.h" +typedef struct TestData { + const char *device; +} TestData; + /*** Test Setup & Teardown ***/ typedef struct XHCIQSlotState { /* In-memory arrays */ @@ -56,6 +61,8 @@ typedef struct XHCIQState { XHCIQSlotState slots[32]; } XHCIQState; +#define XHCI_QEMU_ID (PCI_DEVICE_ID_REDHAT_XHCI << 16 | \ + PCI_VENDOR_ID_REDHAT) #define XHCI_NEC_ID (PCI_DEVICE_ID_NEC_UPD720200 << 16 | \ PCI_VENDOR_ID_NEC) @@ -76,6 +83,7 @@ static QPCIDevice *get_xhci_device(QTestState *qts, uint32_t *fingerprint) xhci_fingerprint = qpci_config_readl(xhci, PCI_VENDOR_ID); switch (xhci_fingerprint) { + case XHCI_QEMU_ID: case XHCI_NEC_ID: break; default: @@ -128,20 +136,21 @@ static XHCIQState *xhci_boot(const char *cli, ...) XHCIQState *s; va_list ap; - if (cli) { - va_start(ap, cli); - s = xhci_vboot(cli, ap); - va_end(ap); - } else { - s = xhci_boot("-M q35 " - "-device nec-usb-xhci,id=xhci,bus=pcie.0,addr=1d.0 " - "-drive id=drive0,if=none,file=null-co://," - "file.read-zeroes=on,format=raw"); - } + va_start(ap, cli); + s = xhci_vboot(cli, ap); + va_end(ap); return s; } +static XHCIQState *xhci_boot_dev(const char *device) +{ + return xhci_boot("-M q35 " + "-device %s,id=xhci,bus=pcie.0,addr=1d.0 " + "-drive id=drive0,if=none,file=null-co://," + "file.read-zeroes=on,format=raw", device); +} + /** * Clean up the PCI device, then terminate the QEMU instance. */ @@ -156,12 +165,13 @@ static void xhci_shutdown(XHCIQState *xhci) /*** tests ***/ -static void test_xhci_hotplug(void) +static void test_xhci_hotplug(const void *arg) { + const TestData *td = arg; XHCIQState *s; QTestState *qts; - s = xhci_boot(NULL); + s = xhci_boot_dev(td->device); qts = s->parent->qts; usb_test_hotplug(qts, "xhci", "1", NULL); @@ -169,12 +179,13 @@ static void test_xhci_hotplug(void) xhci_shutdown(s); } -static void test_usb_uas_hotplug(void) +static void test_usb_uas_hotplug(const void *arg) { + const TestData *td = arg; XHCIQState *s; QTestState *qts; - s = xhci_boot(NULL); + s = xhci_boot_dev(td->device); qts = s->parent->qts; qtest_qmp_device_add(qts, "usb-uas", "uas", "{}"); @@ -191,12 +202,13 @@ static void test_usb_uas_hotplug(void) xhci_shutdown(s); } -static void test_usb_ccid_hotplug(void) +static void test_usb_ccid_hotplug(const void *arg) { + const TestData *td = arg; XHCIQState *s; QTestState *qts; - s = xhci_boot(NULL); + s = xhci_boot_dev(td->device); qts = s->parent->qts; qtest_qmp_device_add(qts, "usb-ccid", "ccid", "{}"); @@ -392,8 +404,9 @@ static void submit_tr_trb(XHCIQState *s, int slot, XHCITRB *trb) * This could be librified in future (like AHCI0 to have a way to bring up * an endpoint to test device protocols. */ -static void pci_xhci_stress_rings(void) +static void test_xhci_stress_rings(const void *arg) { + const TestData *td = arg; XHCIQState *s; uint32_t value; uint64_t input_context; @@ -405,11 +418,11 @@ static void pci_xhci_stress_rings(void) int i; s = xhci_boot("-M q35 " - "-device nec-usb-xhci,id=xhci,bus=pcie.0,addr=1d.0 " + "-device %s,id=xhci,bus=pcie.0,addr=1d.0 " "-device usb-storage,bus=xhci.0,drive=drive0 " "-drive id=drive0,if=none,file=null-co://," - "file.read-zeroes=on,format=raw " - ); + "file.read-zeroes=on,format=raw ", + td->device); hcsparams1 = xhci_cap_readl(s, XHCI_HCCAP_REG_HCSPARAMS1); s->maxports = (hcsparams1 >> 24) & 0xff; @@ -567,11 +580,37 @@ static void pci_xhci_stress_rings(void) xhci_shutdown(s); } +static void add_test(const char *name, TestData *td, void (*fn)(const void *)) +{ + g_autofree char *full_name = g_strdup_printf( + "/xhci/pci/%s/%s", td->device, name); + qtest_add_data_func(full_name, td, fn); +} + +static void add_tests(TestData *td) +{ + add_test("hotplug", td, test_xhci_hotplug); + if (qtest_has_device("usb-uas")) { + add_test("usb-uas", td, test_usb_uas_hotplug); + } + if (qtest_has_device("usb-ccid")) { + add_test("usb-ccid", td, test_usb_ccid_hotplug); + } + if (qtest_has_device("usb-storage")) { + add_test("xhci-stress-rings", td, test_xhci_stress_rings); + } +} + /* tests */ int main(int argc, char **argv) { int ret; const char *arch; + int i; + TestData td[] = { + { .device = "qemu-xhci", }, + { .device = "nec-usb-xhci", }, + }; g_test_init(&argc, &argv, NULL); @@ -582,19 +621,10 @@ int main(int argc, char **argv) return 0; } - if (!qtest_has_device("nec-usb-xhci")) { - return 0; - } - - qtest_add_func("/xhci/pci/hotplug", test_xhci_hotplug); - if (qtest_has_device("usb-uas")) { - qtest_add_func("/xhci/pci/hotplug/usb-uas", test_usb_uas_hotplug); - } - if (qtest_has_device("usb-ccid")) { - qtest_add_func("/xhci/pci/hotplug/usb-ccid", test_usb_ccid_hotplug); - } - if (qtest_has_device("usb-storage")) { - qtest_add_func("/xhci/pci/xhci-stress-rings", pci_xhci_stress_rings); + for (i = 0; i < ARRAY_SIZE(td); i++) { + if (qtest_has_device(td[i].device)) { + add_tests(&td[i]); + } } ret = g_test_run(); From patchwork Sat Jan 18 07:08:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 13944094 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 79187C02187 for ; Sat, 18 Jan 2025 07:09:54 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tZ2xc-0003Gd-9H; Sat, 18 Jan 2025 02:09:36 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tZ2xa-0003GJ-Mo for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:34 -0500 Received: from mail-pl1-x62a.google.com ([2607:f8b0:4864:20::62a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tZ2xY-0007qy-Sn for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:34 -0500 Received: by mail-pl1-x62a.google.com with SMTP id d9443c01a7336-21a7ed0155cso45360905ad.3 for ; Fri, 17 Jan 2025 23:09:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1737184171; x=1737788971; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zNO5lCbo8e/XtcQXdeEOm1z3tzxTfEs5Ck6HtIwTvS8=; b=ASi6HtQxLUyjt4LBGnqEzwueVSlJ+WcBWk7vWwMG6pCvAVIxdWUa8LFBwiArYJdNoT AGzS0hi9Nr1q7hjtfMPZiFY9fWObIhVvzWKEKQc9bG+ssrNRGkOhwX8Wlcm0hiVqlcdZ YUucBcfDOAuLU6mtpcn+syS7HrrjTp2t3Zf/1fQcmZKoS2PY0gkq2xCsaZNGv/fpWwxW 8p1qDYYiy1deuTXOYwgcxl+/0Gt4m3K2ub6ntp2YN1RqmO8SviRDld8C0+2DjPVbp4IL RSSNSIviRbPYfjHWTWYs7pqK18Avgp2YEssKHigLvxgHGHXDVytcS7RP0BQqRvMFlng1 dU4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737184171; x=1737788971; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zNO5lCbo8e/XtcQXdeEOm1z3tzxTfEs5Ck6HtIwTvS8=; b=sHAoDC++ibafHdX1U++RZRXMQYQee0gzDyaP7im/6O6Lu5hh3qbmRYSF8PSEezeI82 vy/Iq8OyYzxRC1oGgl6kTyJ0Az6OrbhIr5lQQ/nV/6O738SCR4M2FAuHejedqd4E78CL LGceejkSGOlY0plrKXhgFNycW4BluVGR47qrPMXNXpgIbCsg1YES58cxeUvbBg+0P1Vb p0MNmM8H9JVkaOgrKE5ssu+DxNDOdGj+dI+hV/TjibsWhOvVG12LL+nSOOPdVj3LByY2 fxguxUbFevPHGQ+7yWnig25FiYRSenquJh1MeWfDy3unv2Kl9klSZLNHa1BhNQQY9K5G jSHA== X-Gm-Message-State: AOJu0YwgcIeD+nFRHnNeqR74vM20jjsZFkrS5nj/r6DJg4JwSL318zo0 DFcBPnb1HHXp6DIIYu1oZAhWLkvhsPNa5qPALwPPy/7qW9eelVaEQzoEtg== X-Gm-Gg: ASbGncuxlCif+WUEvdMq0ZFPx6xXoq9Vi3uZULm8e7cwbKJS2aQt1k/NBbU1FVBvxsk RccMVZ5ej3H9YUykkeEmoIduego+B9kt95EfCbgMGVu6uR/3+R/G4v2DhivIphouXHhqZSdOBCt YDrX+g5r6CikABbICAuMbt2KG1/Q/VS8VWHSxb6qcUzTCuyUGrCXMkHIqipW9U1ogtxPJPfgemB 3VULnWMRCiapilZ5vo7+P3QFp4+/YdhaHBQTqQ5t0R61mv+TWEDCIl9maBluDRJybN/nEg1Ylb7 KU6kDGxS2nuxfoWxV4BwXgUOP0XE X-Google-Smtp-Source: AGHT+IHTIyDz59+ao77xTX8w8z7Xcv6QgYRVD0mUOErdh75QSiXfyu86OuXYqFjDtKiPIGgnqlt0dg== X-Received: by 2002:a05:6a00:9082:b0:725:cfa3:bc6b with SMTP id d2e1a72fcca58-72daf931c0dmr9001992b3a.3.1737184171026; Fri, 17 Jan 2025 23:09:31 -0800 (PST) Received: from wheely.local0.net (124-169-212-233.tpgi.com.au. [124.169.212.233]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72dab9c95adsm3192880b3a.107.2025.01.17.23.09.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jan 2025 23:09:30 -0800 (PST) From: Nicholas Piggin To: qemu-devel@nongnu.org Cc: Nicholas Piggin , Paolo Bonzini , "Michael S. Tsirkin" , Marcel Apfelbaum , Fabiano Rosas , Laurent Vivier , Phil Dennis-Jordan Subject: [PATCH v2 7/8] hw/usb/hcd-xhci-pci: Make PCI device more configurable Date: Sat, 18 Jan 2025 17:08:52 +1000 Message-ID: <20250118070853.653778-8-npiggin@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250118070853.653778-1-npiggin@gmail.com> References: <20250118070853.653778-1-npiggin@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::62a; envelope-from=npiggin@gmail.com; helo=mail-pl1-x62a.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org To prepare to support another USB PCI Host Controller, make some PCI configuration dynamic. Signed-off-by: Nicholas Piggin --- hw/usb/hcd-xhci-pci.h | 9 +++++ hw/usb/hcd-xhci-pci.c | 87 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/hw/usb/hcd-xhci-pci.h b/hw/usb/hcd-xhci-pci.h index 08f70ce97cc..213076aabf6 100644 --- a/hw/usb/hcd-xhci-pci.h +++ b/hw/usb/hcd-xhci-pci.h @@ -40,6 +40,15 @@ typedef struct XHCIPciState { XHCIState xhci; OnOffAuto msi; OnOffAuto msix; + uint8_t cache_line_size; + uint8_t pm_cap_off; + uint8_t pcie_cap_off; + uint8_t msi_cap_off; + uint8_t msix_cap_off; + int msix_bar_nr; + uint64_t msix_bar_size; + uint32_t msix_table_off; + uint32_t msix_pba_off; } XHCIPciState; #endif diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c index 49642aab58e..525537c2b7e 100644 --- a/hw/usb/hcd-xhci-pci.c +++ b/hw/usb/hcd-xhci-pci.c @@ -32,9 +32,6 @@ #include "trace.h" #include "qapi/error.h" -#define OFF_MSIX_TABLE 0x3000 -#define OFF_MSIX_PBA 0x3800 - static void xhci_pci_intr_update(XHCIState *xhci, int n, bool enable) { XHCIPciState *s = container_of(xhci, XHCIPciState, xhci); @@ -105,6 +102,31 @@ static int xhci_pci_vmstate_post_load(void *opaque, int version_id) return 0; } +static int xhci_pci_add_pm_capability(PCIDevice *pci_dev, uint8_t offset, + Error **errp) +{ + int err; + + err = pci_add_capability(pci_dev, PCI_CAP_ID_PM, offset, + PCI_PM_SIZEOF, errp); + if (err < 0) { + return err; + } + + pci_set_word(pci_dev->config + offset + PCI_PM_PMC, + PCI_PM_CAP_VER_1_2 | + PCI_PM_CAP_D1 | PCI_PM_CAP_D2 | + PCI_PM_CAP_PME_D0 | PCI_PM_CAP_PME_D1 | + PCI_PM_CAP_PME_D2 | PCI_PM_CAP_PME_D3hot); + pci_set_word(pci_dev->wmask + offset + PCI_PM_PMC, 0); + pci_set_word(pci_dev->config + offset + PCI_PM_CTRL, + PCI_PM_CTRL_NO_SOFT_RESET); + pci_set_word(pci_dev->wmask + offset + PCI_PM_CTRL, + PCI_PM_CTRL_STATE_MASK); + + return 0; +} + static void usb_xhci_pci_realize(struct PCIDevice *dev, Error **errp) { int ret; @@ -113,7 +135,7 @@ static void usb_xhci_pci_realize(struct PCIDevice *dev, Error **errp) dev->config[PCI_CLASS_PROG] = 0x30; /* xHCI */ dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */ - dev->config[PCI_CACHE_LINE_SIZE] = 0x10; + dev->config[PCI_CACHE_LINE_SIZE] = s->cache_line_size; dev->config[0x60] = 0x30; /* release number */ object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL); @@ -126,8 +148,16 @@ static void usb_xhci_pci_realize(struct PCIDevice *dev, Error **errp) s->xhci.nec_quirks = true; } + if (s->pm_cap_off) { + if (xhci_pci_add_pm_capability(dev, s->pm_cap_off, &err)) { + error_propagate(errp, err); + return; + } + } + if (s->msi != ON_OFF_AUTO_OFF) { - ret = msi_init(dev, 0x70, s->xhci.numintrs, true, false, &err); + ret = msi_init(dev, s->msi_cap_off, s->xhci.numintrs, + true, false, &err); /* * Any error other than -ENOTSUP(board's MSI support is broken) * is a programming error @@ -144,22 +174,47 @@ static void usb_xhci_pci_realize(struct PCIDevice *dev, Error **errp) /* With msi=auto, we fall back to MSI off silently */ error_free(err); } + pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64, &s->xhci.mem); if (pci_bus_is_express(pci_get_bus(dev))) { - ret = pcie_endpoint_cap_init(dev, 0xa0); + ret = pcie_endpoint_cap_init(dev, s->pcie_cap_off); assert(ret > 0); } if (s->msix != ON_OFF_AUTO_OFF) { - /* TODO check for errors, and should fail when msix=on */ - msix_init(dev, s->xhci.numintrs, - &s->xhci.mem, 0, OFF_MSIX_TABLE, - &s->xhci.mem, 0, OFF_MSIX_PBA, - 0x90, NULL); + MemoryRegion *msix_bar = &s->xhci.mem; + + if (s->msix_bar_nr != 0) { + memory_region_init(&dev->msix_exclusive_bar, OBJECT(dev), + "xhci-msix", s->msix_bar_size); + msix_bar = &dev->msix_exclusive_bar; + pci_register_bar(dev, s->msix_bar_nr, + PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_TYPE_64, + msix_bar); + } + + ret = msix_init(dev, s->xhci.numintrs, + msix_bar, s->msix_bar_nr, s->msix_table_off, + msix_bar, s->msix_bar_nr, s->msix_pba_off, + s->msix_cap_off, &err); + if (ret == -ENOTSUP && s->msi == ON_OFF_AUTO_AUTO) { + /* report that msix is not supported, but do not error out */ + warn_report_err(err); + } else if (ret == -ENOTSUP) { + /* Can't satisfy user's explicit msix=on request, fail */ + error_append_hint(&err, "You have to use msix=auto (default) or " + "msix=off with this machine type.\n"); + error_propagate(errp, err); + return; + } else if (ret < 0) { + error_propagate(errp, err); + return; + } } s->xhci.as = pci_get_address_space(dev); } @@ -196,6 +251,16 @@ static void xhci_instance_init(Object *obj) PCI_DEVICE(obj)->cap_present |= QEMU_PCI_CAP_EXPRESS; object_initialize_child(obj, "xhci-core", &s->xhci, TYPE_XHCI); qdev_alias_all_properties(DEVICE(&s->xhci), obj); + + s->cache_line_size = 0x10; + s->pm_cap_off = 0; + s->pcie_cap_off = 0xa0; + s->msi_cap_off = 0x70; + s->msix_cap_off = 0x90; + s->msix_bar_nr = 0; + s->msix_bar_size = 0; + s->msix_table_off = 0x3000; + s->msix_pba_off = 0x3800; } static const Property xhci_pci_properties[] = { From patchwork Sat Jan 18 07:08:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicholas Piggin X-Patchwork-Id: 13944098 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A2538C02185 for ; Sat, 18 Jan 2025 07:10:16 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tZ2xh-0003HW-3n; Sat, 18 Jan 2025 02:09:41 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tZ2xf-0003HN-7w for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:39 -0500 Received: from mail-pl1-x632.google.com ([2607:f8b0:4864:20::632]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tZ2xc-0007rV-Tg for qemu-devel@nongnu.org; Sat, 18 Jan 2025 02:09:38 -0500 Received: by mail-pl1-x632.google.com with SMTP id d9443c01a7336-2165cb60719so52201175ad.0 for ; Fri, 17 Jan 2025 23:09:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1737184175; x=1737788975; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2jKdz++y7gS8MzwMLxg2+Nc3pBzePH5ZRQnJ2/K0PAc=; b=g49Izu3FeyFMM83QbCbLhgC5bgiqznKOjZrNCcjKgMUy5qFaEUMvdPkyNRRPrIvKo1 wSvGNfMEz/tbyKvB7rG40rNqKHKrwi2JusKHMo4Z7hK1DRYt3vjBoeGEoLtGvI+Qj13m hW78deftRng0KfSNZwXPe0TJDv/JNXpc/COjOdN4ukWzRj67YXL1ofIOkAkMkvzq3+gZ dQitvQJ6YSXMCqOTlrxSewQBRAj+KNGhXLZ3IK7iIb4UDu1VIs8RBVyrMYNKpE9YSeVk g+MYkZdEik6yxBpNa76g2PcvSIYGi0zKOQdrDAsmF45YnZf4LwGaVwdF2k/qxWHhESd/ 9WIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737184175; x=1737788975; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2jKdz++y7gS8MzwMLxg2+Nc3pBzePH5ZRQnJ2/K0PAc=; b=AeBbVBMBYwwZ6j3MJQdIRnfvGgmwDR/Y8H/JLDnn+PTHfPcGkYw1kKYC23f7m6c/Di SVvGuCf7KhEcjnqnoL9WJIczyYQw2eJ/91+8rm3XXGtj9zIqfUmrZT4JWxRhiJ7ttWIP pKs7L7iCXJCPk7qAfIl7/Lcd68Nd94xtt0/WDxz1IDdgZ/AQghhIjjQrozNzzkQZux7Z br5CL25kKW/BYK9eIpTiRew82qb501LH0xFEzcpXWdDZY9+bJQAFcPF0ujKldisx74cb PYDwb337kJG13B8IKFzom1mdTnYPmTPmTFXML+H5nWmEGQsip6epA4tYJGEZ5OYAG5L5 Yubg== X-Gm-Message-State: AOJu0YwmN5Lhh28OEtcDgIep1cTYh5BZ4K7LrrjtdR2SuOGFafhk/9kM rXzNAdJ5ibxDxvxFe6Bhxzebm87vvZrdD1ptjCs4f0ZgeZ+t2KV5WP44vg== X-Gm-Gg: ASbGncvbjGmvykjHzem3wwl1f90KfBc9kcNwWk83VEWV4qHcO69FWKyQp+DnjHPe2XG scOCBFXgV0t9xxI6EuA80OSytqfT3bY1QCxmgDtnvQnFIs/7Wa/cLD6Qojv53zVI0NROpSxaCnI //rTLUr55EGSUqchFj1OJUAJ52Zb8WNhrL3GXXvwL2kqsyL9i5UhWIRYDpeMuM8y5SrdvHn+dSJ 9moH7bOwCzZ0nV8CMR9bmg3YJTI28bHJVSPJv9KLgYNGIHS6ctALh1mzJAZPazTBoEwnoziQzdO eNbZn+c0pp1cgn1/qMgeiszs4bJ6 X-Google-Smtp-Source: AGHT+IHYDT2JiR4upm5IC6RzmFUuZFP8xCL10bMZqVsO1pigeXX2rxhFyrDUnBTp88n2JxMotJbHlA== X-Received: by 2002:a05:6a21:789a:b0:1e6:51d2:c8e3 with SMTP id adf61e73a8af0-1eb215f52a7mr10765445637.35.1737184175069; Fri, 17 Jan 2025 23:09:35 -0800 (PST) Received: from wheely.local0.net (124-169-212-233.tpgi.com.au. [124.169.212.233]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72dab9c95adsm3192880b3a.107.2025.01.17.23.09.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jan 2025 23:09:34 -0800 (PST) From: Nicholas Piggin To: qemu-devel@nongnu.org Cc: Nicholas Piggin , Paolo Bonzini , "Michael S. Tsirkin" , Marcel Apfelbaum , Fabiano Rosas , Laurent Vivier , Phil Dennis-Jordan Subject: [PATCH v2 8/8] hw/usb/hcd-xhci-pci: Add TI TUSB73X0 XHCI controller model Date: Sat, 18 Jan 2025 17:08:53 +1000 Message-ID: <20250118070853.653778-9-npiggin@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20250118070853.653778-1-npiggin@gmail.com> References: <20250118070853.653778-1-npiggin@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::632; envelope-from=npiggin@gmail.com; helo=mail-pl1-x632.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The TI TUSB73X0 controller has some interesting differences from NEC, notably a separate BAR for MSIX, and PM capabilities. The spec is freely available without sign-up. This controller is accepted by IBM Power proprietary firmware and software (when the subsystem IDs are set to Power servers, which is not done here). IBM code is picky about device support, so the NEC device can not be used. xhci qtests are added for this device. Signed-off-by: Nicholas Piggin --- include/hw/pci/pci_ids.h | 1 + include/hw/usb/xhci.h | 1 + hw/usb/hcd-xhci-ti.c | 88 +++++++++++++++++++++++++++++++++ tests/qtest/usb-hcd-xhci-test.c | 4 ++ hw/usb/Kconfig | 5 ++ hw/usb/meson.build | 1 + 6 files changed, 100 insertions(+) create mode 100644 hw/usb/hcd-xhci-ti.c diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index f1a53fea8d6..fdb692db513 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -182,6 +182,7 @@ #define PCI_VENDOR_ID_HP 0x103c #define PCI_VENDOR_ID_TI 0x104c +#define PCI_DEVICE_ID_TI_TUSB73X0 0x8241 #define PCI_VENDOR_ID_MOTOROLA 0x1057 #define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002 diff --git a/include/hw/usb/xhci.h b/include/hw/usb/xhci.h index 5c90e1373e5..203ec1fca32 100644 --- a/include/hw/usb/xhci.h +++ b/include/hw/usb/xhci.h @@ -3,6 +3,7 @@ #define TYPE_XHCI "base-xhci" #define TYPE_NEC_XHCI "nec-usb-xhci" +#define TYPE_TI_XHCI "ti-usb-xhci" #define TYPE_QEMU_XHCI "qemu-xhci" #define TYPE_XHCI_SYSBUS "sysbus-xhci" diff --git a/hw/usb/hcd-xhci-ti.c b/hw/usb/hcd-xhci-ti.c new file mode 100644 index 00000000000..c2f8fb04a52 --- /dev/null +++ b/hw/usb/hcd-xhci-ti.c @@ -0,0 +1,88 @@ +/* + * USB xHCI controller emulation + * Datasheet https://www.ti.com/product/TUSB7340 + * + * Copyright (c) 2011 Securiforest + * Date: 2011-05-11 ; Author: Hector Martin + * Based on usb-xhci-nec.c, emulates TI TUSB73X0 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "hw/usb.h" +#include "qemu/module.h" +#include "hw/pci/pci.h" +#include "hw/qdev-properties.h" + +#include "hcd-xhci-pci.h" + +OBJECT_DECLARE_SIMPLE_TYPE(XHCITiState, TI_XHCI) + +struct XHCITiState { + XHCIPciState parent_obj; + + uint32_t intrs; + uint32_t slots; +}; + +static Property ti_xhci_properties[] = { + DEFINE_PROP_UINT32("intrs", XHCITiState, intrs, 8), + DEFINE_PROP_UINT32("slots", XHCITiState, slots, XHCI_MAXSLOTS), +}; + +static void ti_xhci_instance_init(Object *obj) +{ + XHCIPciState *pci = XHCI_PCI(obj); + XHCITiState *ti = TI_XHCI(obj); + + pci->xhci.numintrs = ti->intrs; + pci->xhci.numslots = ti->slots; + + pci->cache_line_size = 0x0; + pci->pm_cap_off = 0x40; + pci->pcie_cap_off = 0x70; + pci->msi_cap_off = 0x48; + pci->msix_cap_off = 0xc0; + pci->msix_bar_nr = 0x2; + pci->msix_bar_size = 0x800000; + pci->msix_table_off = 0x0; + pci->msix_pba_off = 0x1000; +} + +static void ti_xhci_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + device_class_set_props(dc, ti_xhci_properties); + k->vendor_id = PCI_VENDOR_ID_TI; + k->device_id = PCI_DEVICE_ID_TI_TUSB73X0; + k->revision = 0x02; +} + +static const TypeInfo ti_xhci_info = { + .name = TYPE_TI_XHCI, + .parent = TYPE_XHCI_PCI, + .instance_size = sizeof(XHCITiState), + .instance_init = ti_xhci_instance_init, + .class_init = ti_xhci_class_init, +}; + +static void ti_xhci_register_types(void) +{ + type_register_static(&ti_xhci_info); +} + +type_init(ti_xhci_register_types) diff --git a/tests/qtest/usb-hcd-xhci-test.c b/tests/qtest/usb-hcd-xhci-test.c index 4efe7b69d4f..dc438cf35c7 100644 --- a/tests/qtest/usb-hcd-xhci-test.c +++ b/tests/qtest/usb-hcd-xhci-test.c @@ -65,6 +65,8 @@ typedef struct XHCIQState { PCI_VENDOR_ID_REDHAT) #define XHCI_NEC_ID (PCI_DEVICE_ID_NEC_UPD720200 << 16 | \ PCI_VENDOR_ID_NEC) +#define XHCI_TI_ID (PCI_DEVICE_ID_TI_TUSB73X0 << 16 | \ + PCI_VENDOR_ID_TI) /** * Locate, verify, and return a handle to the XHCI device. @@ -85,6 +87,7 @@ static QPCIDevice *get_xhci_device(QTestState *qts, uint32_t *fingerprint) switch (xhci_fingerprint) { case XHCI_QEMU_ID: case XHCI_NEC_ID: + case XHCI_TI_ID: break; default: /* Unknown device. */ @@ -610,6 +613,7 @@ int main(int argc, char **argv) TestData td[] = { { .device = "qemu-xhci", }, { .device = "nec-usb-xhci", }, + { .device = "ti-usb-xhci", }, }; g_test_init(&argc, &argv, NULL); diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig index 5fbecd2f43b..8e5c4747af9 100644 --- a/hw/usb/Kconfig +++ b/hw/usb/Kconfig @@ -49,6 +49,11 @@ config USB_XHCI_NEC default y if PCI_DEVICES select USB_XHCI_PCI +config USB_XHCI_TI + bool + default y if PCI_DEVICES + select USB_XHCI_PCI + config USB_XHCI_SYSBUS bool select USB_XHCI diff --git a/hw/usb/meson.build b/hw/usb/meson.build index 1b4d1507e41..b874a93f16e 100644 --- a/hw/usb/meson.build +++ b/hw/usb/meson.build @@ -23,6 +23,7 @@ system_ss.add(when: 'CONFIG_USB_XHCI', if_true: files('hcd-xhci.c')) system_ss.add(when: 'CONFIG_USB_XHCI_PCI', if_true: files('hcd-xhci-pci.c')) system_ss.add(when: 'CONFIG_USB_XHCI_SYSBUS', if_true: files('hcd-xhci-sysbus.c')) system_ss.add(when: 'CONFIG_USB_XHCI_NEC', if_true: files('hcd-xhci-nec.c')) +system_ss.add(when: 'CONFIG_USB_XHCI_TI', if_true: files('hcd-xhci-ti.c')) system_ss.add(when: 'CONFIG_USB_DWC2', if_true: files('hcd-dwc2.c')) system_ss.add(when: 'CONFIG_USB_DWC3', if_true: files('hcd-dwc3.c'))