From nobody Sat Feb 7 07:11:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1770207193; cv=none; d=zohomail.com; s=zohoarc; b=jWLSEAEW0l+O3jMcYky8BgaVT/ASwLuvZX/hOa4s3FZaTsOpR2gQvokOUqge5i8MlkOLXelftu1vdO8i7limU0aqjYvg73qXecVIZ7pITjWDpgbubRi0aN2rODozoP2AEDK12FrGeZudaDV8hICPGMxIo2mYLT4p+FSf5P9Xows= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1770207193; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=/Ngs5bGuHEYapDVPYtpBcjTnzFEL6hbyYrhP6sPOaAk=; b=EaB4zS9zsIa7mICCJaUlBc6bjtNK+2YUyxe3t2PZ5h0YRIjhkkuxzrMJ/jiHWzNWxs/9C+h5QJrV3xRWwO48efDuxbGTV36ZFy6Watl3yVikkO7dP/6n1QME8zN3JhtSA3iiqFFi2r8HTydgorS4LaEpuS55Ipg/FNFC5LFH9cM= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1770207193331149.18865145064535; Wed, 4 Feb 2026 04:13:13 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vnbko-0005ud-Rq; Wed, 04 Feb 2026 07:13:06 -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 1vnbki-0005tS-5Z for qemu-devel@nongnu.org; Wed, 04 Feb 2026 07:13:01 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vnbkc-0007HK-07 for qemu-devel@nongnu.org; Wed, 04 Feb 2026 07:12:58 -0500 Received: from mail.maildlp.com (unknown [172.18.224.83]) by frasgout.his.huawei.com (SkyGuard) with ESMTPS id 4f5fNR22H4zHnHMj; Wed, 4 Feb 2026 20:11:51 +0800 (CST) Received: from dubpeml500005.china.huawei.com (unknown [7.214.145.207]) by mail.maildlp.com (Postfix) with ESMTPS id 8AE4540572; Wed, 4 Feb 2026 20:12:52 +0800 (CST) Received: from SecurePC-101-06.huawei.com (10.122.19.247) by dubpeml500005.china.huawei.com (7.214.145.207) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 4 Feb 2026 12:12:50 +0000 To: Michael Tsirkin , , Davidlohr Bueso CC: , , Ravi Shankar , Marcel Apfelbaum , Markus Armbruster , Michael Roth Subject: [PATCH qemu v6 1/7] hw/pcie: Support enabling flit mode Date: Wed, 4 Feb 2026 12:12:09 +0000 Message-ID: <20260204121215.68897-2-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260204121215.68897-1-Jonathan.Cameron@huawei.com> References: <20260204121215.68897-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.122.19.247] X-ClientProxiedBy: lhrpeml500012.china.huawei.com (7.191.174.4) To dubpeml500005.china.huawei.com (7.214.145.207) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, 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: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Jonathan Cameron From: Jonathan Cameron via qemu development Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1770207195484158500 Content-Type: text/plain; charset="utf-8" From: Davidlohr Bueso PCIe Flit Mode, introduced with the PCIe 6.0 specification, is a fundamental change in how data is transmitted over the bus to improve transfer rates. It shifts from variable-sized Transaction Layer Packets (TLPs) to fixed 256-byte Flow Control Units (FLITs). As with the link speed and width training, have ad-hoc property for setting the flit mode and allow CXL components to make use of it. For the CXL root port and dsp cases, always report flit mode but the actual value after 'training' will depend on the downstream device configuration. Suggested-by: Jonathan Cameron Tested-by: Dongjoo Seo Signed-off-by: Davidlohr Bueso Signed-off-by: Jonathan Cameron --- include/hw/cxl/cxl_device.h | 1 + include/hw/pci-bridge/cxl_upstream_port.h | 1 + include/hw/pci/pcie.h | 2 +- include/hw/pci/pcie_port.h | 1 + hw/mem/cxl_type3.c | 6 ++++-- hw/pci-bridge/cxl_downstream.c | 8 +++++--- hw/pci-bridge/cxl_root_port.c | 8 +++++--- hw/pci-bridge/cxl_upstream.c | 16 +++++++++------- hw/pci/pcie.c | 23 +++++++++++++++++++---- 9 files changed, 46 insertions(+), 20 deletions(-) diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h index d5906afb19a5..7d9236db8c85 100644 --- a/include/hw/cxl/cxl_device.h +++ b/include/hw/cxl/cxl_device.h @@ -726,6 +726,7 @@ struct CXLType3Dev { /* PCIe link characteristics */ PCIExpLinkSpeed speed; PCIExpLinkWidth width; + bool flitmode; =20 /* DOE */ DOECap doe_cdat; diff --git a/include/hw/pci-bridge/cxl_upstream_port.h b/include/hw/pci-bri= dge/cxl_upstream_port.h index f208397ffe96..e3d6a27acc86 100644 --- a/include/hw/pci-bridge/cxl_upstream_port.h +++ b/include/hw/pci-bridge/cxl_upstream_port.h @@ -15,6 +15,7 @@ typedef struct CXLUpstreamPort { =20 PCIExpLinkSpeed speed; PCIExpLinkWidth width; + bool flitmode; =20 DOECap doe_cdat; uint64_t sn; diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index fc02aeb169f1..0a1cbb8728f3 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -144,7 +144,7 @@ void pcie_ari_init(PCIDevice *dev, uint16_t offset); void pcie_dev_ser_num_init(PCIDevice *dev, uint16_t offset, uint64_t ser_n= um); void pcie_ats_init(PCIDevice *dev, uint16_t offset, bool aligned); void pcie_cap_fill_link_ep_usp(PCIDevice *dev, PCIExpLinkWidth width, - PCIExpLinkSpeed speed); + PCIExpLinkSpeed speed, bool flitmode); =20 void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *d= ev, Error **errp); diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h index 7cd7af8cfa4b..53cd64c5edff 100644 --- a/include/hw/pci/pcie_port.h +++ b/include/hw/pci/pcie_port.h @@ -58,6 +58,7 @@ struct PCIESlot { =20 PCIExpLinkSpeed speed; PCIExpLinkWidth width; + bool flitmode; =20 /* Disable ACS (really for a pcie_root_port) */ bool disable_acs; diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index 85694707e2e4..3c7ecd8c48bc 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -405,7 +405,7 @@ static void build_dvsecs(CXLType3Dev *ct3d) dvsec =3D (uint8_t *)&(CXLDVSECPortFlexBus){ .cap =3D 0x26, /* 68B, IO, Mem, non-MLD */ .ctrl =3D 0x02, /* IO always enabled */ - .status =3D 0x26, /* same as capabilities */ + .status =3D ct3d->flitmode ? 0x6 : 0x26, /* lack = of 68B */ .rcvd_mod_ts_data_phase1 =3D 0xef, /* WTF? */ }; cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE, @@ -1315,7 +1315,8 @@ static void ct3d_reset(DeviceState *dev) uint32_t *reg_state =3D ct3d->cxl_cstate.crb.cache_mem_registers; uint32_t *write_msk =3D ct3d->cxl_cstate.crb.cache_mem_regs_write_mask; =20 - pcie_cap_fill_link_ep_usp(PCI_DEVICE(dev), ct3d->width, ct3d->speed); + pcie_cap_fill_link_ep_usp(PCI_DEVICE(dev), ct3d->width, ct3d->speed, + ct3d->flitmode); cxl_component_register_init_common(reg_state, write_msk, CXL2_TYPE3_DE= VICE); cxl_device_register_init_t3(ct3d, CXL_T3_MSIX_MBOX); =20 @@ -1354,6 +1355,7 @@ static const Property ct3_props[] =3D { speed, PCIE_LINK_SPEED_32), DEFINE_PROP_PCIE_LINK_WIDTH("x-width", CXLType3Dev, width, PCIE_LINK_WIDTH_16), + DEFINE_PROP_BOOL("x-256b-flit", CXLType3Dev, flitmode, false), }; =20 static uint64_t get_lsa_size(CXLType3Dev *ct3d) diff --git a/hw/pci-bridge/cxl_downstream.c b/hw/pci-bridge/cxl_downstream.c index f7b131e67e8e..64086d8ec2f2 100644 --- a/hw/pci-bridge/cxl_downstream.c +++ b/hw/pci-bridge/cxl_downstream.c @@ -94,8 +94,9 @@ static void cxl_dsp_reset(DeviceState *qdev) latch_registers(dsp); } =20 -static void build_dvsecs(CXLComponentState *cxl) +static void build_dvsecs(PCIDevice *d, CXLComponentState *cxl) { + PCIESlot *s =3D PCIE_SLOT(d); uint8_t *dvsec; =20 dvsec =3D (uint8_t *)&(CXLDVSECPortExt){ 0 }; @@ -107,7 +108,7 @@ static void build_dvsecs(CXLComponentState *cxl) dvsec =3D (uint8_t *)&(CXLDVSECPortFlexBus){ .cap =3D 0x27, /* Cache, IO, Mem, non-MLD */ .ctrl =3D 0x02, /* IO always enabled */ - .status =3D 0x26, /* same */ + .status =3D s->flitmode ? 0x6 : 0x26, /* lack of = 68B */ .rcvd_mod_ts_data_phase1 =3D 0xef, /* WTF? */ }; cxl_component_create_dvsec(cxl, CXL2_DOWNSTREAM_PORT, @@ -182,7 +183,7 @@ static void cxl_dsp_realize(PCIDevice *d, Error **errp) =20 cxl_cstate->dvsec_offset =3D CXL_DOWNSTREAM_PORT_DVSEC_OFFSET; cxl_cstate->pdev =3D d; - build_dvsecs(cxl_cstate); + build_dvsecs(d, cxl_cstate); cxl_component_register_block_init(OBJECT(d), cxl_cstate, TYPE_CXL_DSP); pci_register_bar(d, CXL_COMPONENT_REG_BAR_IDX, PCI_BASE_ADDRESS_SPACE_MEMORY | @@ -217,6 +218,7 @@ static const Property cxl_dsp_props[] =3D { speed, PCIE_LINK_SPEED_64), DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot, width, PCIE_LINK_WIDTH_16), + DEFINE_PROP_BOOL("x-256b-flit", PCIESlot, flitmode, true), }; =20 static void cxl_dsp_class_init(ObjectClass *oc, const void *data) diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c index 197d3148d201..5641048084a4 100644 --- a/hw/pci-bridge/cxl_root_port.c +++ b/hw/pci-bridge/cxl_root_port.c @@ -104,8 +104,9 @@ static void latch_registers(CXLRootPort *crp) cxl_component_register_init_common(reg_state, write_msk, CXL2_ROOT_POR= T); } =20 -static void build_dvsecs(CXLComponentState *cxl) +static void build_dvsecs(PCIDevice *d, CXLComponentState *cxl) { + PCIESlot *s =3D PCIE_SLOT(d); uint8_t *dvsec; =20 dvsec =3D (uint8_t *)&(CXLDVSECPortExt){ 0 }; @@ -126,7 +127,7 @@ static void build_dvsecs(CXLComponentState *cxl) dvsec =3D (uint8_t *)&(CXLDVSECPortFlexBus){ .cap =3D 0x26, /* IO, Mem, non-MLD */ .ctrl =3D 0x2, - .status =3D 0x26, /* same */ + .status =3D s->flitmode ? 0x6 : 0x26, /* lack of = 68B */ .rcvd_mod_ts_data_phase1 =3D 0xef, }; cxl_component_create_dvsec(cxl, CXL2_ROOT_PORT, @@ -176,7 +177,7 @@ static void cxl_rp_realize(DeviceState *dev, Error **er= rp) =20 cxl_cstate->dvsec_offset =3D CXL_ROOT_PORT_DVSEC_OFFSET; cxl_cstate->pdev =3D pci_dev; - build_dvsecs(cxl_cstate); + build_dvsecs(pci_dev, cxl_cstate); =20 cxl_component_register_block_init(OBJECT(pci_dev), cxl_cstate, TYPE_CXL_ROOT_PORT); @@ -211,6 +212,7 @@ static const Property gen_rp_props[] =3D { speed, PCIE_LINK_SPEED_64), DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot, width, PCIE_LINK_WIDTH_32), + DEFINE_PROP_BOOL("x-256b-flit", PCIESlot, flitmode, true), }; =20 static void cxl_rp_dvsec_write_config(PCIDevice *dev, uint32_t addr, diff --git a/hw/pci-bridge/cxl_upstream.c b/hw/pci-bridge/cxl_upstream.c index 6d708fadc253..c352d11dc7b7 100644 --- a/hw/pci-bridge/cxl_upstream.c +++ b/hw/pci-bridge/cxl_upstream.c @@ -101,28 +101,29 @@ static void cxl_usp_reset(DeviceState *qdev) =20 pci_bridge_reset(qdev); pcie_cap_deverr_reset(d); - pcie_cap_fill_link_ep_usp(d, usp->width, usp->speed); + pcie_cap_fill_link_ep_usp(d, usp->width, usp->speed, usp->flitmode); latch_registers(usp); } =20 -static void build_dvsecs(CXLComponentState *cxl) +static void build_dvsecs(CXLUpstreamPort *usp) { + CXLComponentState *cxl_cstate =3D &usp->cxl_cstate; uint8_t *dvsec; =20 dvsec =3D (uint8_t *)&(CXLDVSECPortExt){ .status =3D 0x1, /* Port Power Management Init Complete */ }; - cxl_component_create_dvsec(cxl, CXL2_UPSTREAM_PORT, + cxl_component_create_dvsec(cxl_cstate, CXL2_UPSTREAM_PORT, EXTENSIONS_PORT_DVSEC_LENGTH, EXTENSIONS_PORT_DVSEC, EXTENSIONS_PORT_DVSEC_REVID, dvsec); dvsec =3D (uint8_t *)&(CXLDVSECPortFlexBus){ .cap =3D 0x27, /* Cache, IO, Mem, non-MLD */ .ctrl =3D 0x27, /* Cache, IO, Mem */ - .status =3D 0x26, /* same */ + .status =3D usp->flitmode ? 0x6 : 0x26, /* lack o= f 68B */ .rcvd_mod_ts_data_phase1 =3D 0xef, /* WTF? */ }; - cxl_component_create_dvsec(cxl, CXL2_UPSTREAM_PORT, + cxl_component_create_dvsec(cxl_cstate, CXL2_UPSTREAM_PORT, PCIE_CXL3_FLEXBUS_PORT_DVSEC_LENGTH, PCIE_FLEXBUS_PORT_DVSEC, PCIE_CXL3_FLEXBUS_PORT_DVSEC_REVID, dvsec); @@ -132,7 +133,7 @@ static void build_dvsecs(CXLComponentState *cxl) .reg0_base_lo =3D RBI_COMPONENT_REG | CXL_COMPONENT_REG_BAR_IDX, .reg0_base_hi =3D 0, }; - cxl_component_create_dvsec(cxl, CXL2_UPSTREAM_PORT, + cxl_component_create_dvsec(cxl_cstate, CXL2_UPSTREAM_PORT, REG_LOC_DVSEC_LENGTH, REG_LOC_DVSEC, REG_LOC_DVSEC_REVID, dvsec); } @@ -327,7 +328,7 @@ static void cxl_usp_realize(PCIDevice *d, Error **errp) } cxl_cstate->dvsec_offset =3D CXL_UPSTREAM_PORT_DVSEC_OFFSET; cxl_cstate->pdev =3D d; - build_dvsecs(cxl_cstate); + build_dvsecs(usp); cxl_component_register_block_init(OBJECT(d), cxl_cstate, TYPE_CXL_USP); pci_register_bar(d, CXL_COMPONENT_REG_BAR_IDX, PCI_BASE_ADDRESS_SPACE_MEMORY | @@ -369,6 +370,7 @@ static const Property cxl_upstream_props[] =3D { speed, PCIE_LINK_SPEED_32), DEFINE_PROP_PCIE_LINK_WIDTH("x-width", CXLUpstreamPort, width, PCIE_LINK_WIDTH_16), + DEFINE_PROP_BOOL("x-256b-flit", CXLUpstreamPort, flitmode, false), }; =20 static void cxl_upstream_class_init(ObjectClass *oc, const void *data) diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index c481c16c0f57..6cc6e848b6bf 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -113,7 +113,7 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t = type, uint8_t version) =20 /* Includes setting the target speed default */ static void pcie_cap_fill_lnk(uint8_t *exp_cap, PCIExpLinkWidth width, - PCIExpLinkSpeed speed) + PCIExpLinkSpeed speed, bool flitmode) { /* Clear and fill LNKCAP from what was configured above */ pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP, @@ -158,10 +158,15 @@ static void pcie_cap_fill_lnk(uint8_t *exp_cap, PCIEx= pLinkWidth width, PCI_EXP_LNKCAP2_SLS_64_0GB); } } + + if (flitmode) { + pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA2, + PCI_EXP_LNKSTA2_FLIT); + } } =20 void pcie_cap_fill_link_ep_usp(PCIDevice *dev, PCIExpLinkWidth width, - PCIExpLinkSpeed speed) + PCIExpLinkSpeed speed, bool flitmode) { uint8_t *exp_cap =3D dev->config + dev->exp.exp_cap; =20 @@ -175,7 +180,7 @@ void pcie_cap_fill_link_ep_usp(PCIDevice *dev, PCIExpLi= nkWidth width, QEMU_PCI_EXP_LNKSTA_NLW(width) | QEMU_PCI_EXP_LNKSTA_CLS(speed)); =20 - pcie_cap_fill_lnk(exp_cap, width, speed); + pcie_cap_fill_lnk(exp_cap, width, speed, flitmode); } =20 static void pcie_cap_fill_slot_lnk(PCIDevice *dev) @@ -212,7 +217,7 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev) /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */ } =20 - pcie_cap_fill_lnk(exp_cap, s->width, s->speed); + pcie_cap_fill_lnk(exp_cap, s->width, s->speed, s->flitmode); } =20 int pcie_cap_init(PCIDevice *dev, uint8_t offset, @@ -1175,6 +1180,8 @@ void pcie_sync_bridge_lnk(PCIDevice *bridge_dev) if (!target || !target->exp.exp_cap) { lnksta =3D lnkcap; } else { + uint16_t lnksta2; + lnksta =3D target->config_read(target, target->exp.exp_cap + PCI_EXP_LNKSTA, sizeof(lnksta)); @@ -1188,6 +1195,14 @@ void pcie_sync_bridge_lnk(PCIDevice *bridge_dev) lnksta &=3D ~PCI_EXP_LNKSTA_CLS; lnksta |=3D lnkcap & PCI_EXP_LNKCAP_SLS; } + + lnksta2 =3D target->config_read(target, + target->exp.exp_cap + PCI_EXP_LNKSTA= 2, + sizeof(lnksta2)); + pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA2, + PCI_EXP_LNKSTA2_FLIT); + pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA2, + lnksta2 & PCI_EXP_LNKSTA2_FLIT); } =20 if (!(lnksta & PCI_EXP_LNKSTA_NLW)) { --=20 2.51.0