@samitouri / QOSamiQemu / commits / d29f3f5cdd

hw/pcie: Support enabling flit mode

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 <Jonathan.Cameron@huawei.com> Tested-by: Dongjoo Seo <dongjoo.seo1@samsung.com> Signed-off-by: Davidlohr Bueso <dave@stgolabs.net> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20260204170936.43959-2-Jonathan.Cameron@huawei.com>

Davidlohr Bueso committed Feb 4, 2026 at 17:09 UTC d29f3f5cddb2614b3eebe216cce59ef9350db0a0
9 files changed +46 -20
hw/mem/cxl_type3.c
+4 -2
@@ -405,7 +405,7 @@ static void build_dvsecs(CXLType3Dev *ct3d)
405 dvsec = (uint8_t *)&(CXLDVSECPortFlexBus){
406 .cap = 0x26, /* 68B, IO, Mem, non-MLD */
407 .ctrl = 0x02, /* IO always enabled */
408 - .status = 0x26, /* same as capabilities */
408 + .status = ct3d->flitmode ? 0x6 : 0x26, /* lack of 68B */
409 .rcvd_mod_ts_data_phase1 = 0xef, /* WTF? */
410 };
411 cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE,
@@ -1315,7 +1315,8 @@ static void ct3d_reset(DeviceState *dev)
1315 uint32_t *reg_state = ct3d->cxl_cstate.crb.cache_mem_registers;
1316 uint32_t *write_msk = ct3d->cxl_cstate.crb.cache_mem_regs_write_mask;
1317
1318 - pcie_cap_fill_link_ep_usp(PCI_DEVICE(dev), ct3d->width, ct3d->speed);
1318 + pcie_cap_fill_link_ep_usp(PCI_DEVICE(dev), ct3d->width, ct3d->speed,
1319 + ct3d->flitmode);
1320 cxl_component_register_init_common(reg_state, write_msk, CXL2_TYPE3_DEVICE);
1321 cxl_device_register_init_t3(ct3d, CXL_T3_MSIX_MBOX);
1322
@@ -1354,6 +1355,7 @@ static const Property ct3_props[] = {
1355 speed, PCIE_LINK_SPEED_32),
1356 DEFINE_PROP_PCIE_LINK_WIDTH("x-width", CXLType3Dev,
1357 width, PCIE_LINK_WIDTH_16),
1358 + DEFINE_PROP_BOOL("x-256b-flit", CXLType3Dev, flitmode, false),
1359 };
1360
1361 static uint64_t get_lsa_size(CXLType3Dev *ct3d)
hw/pci-bridge/cxl_downstream.c
+5 -3
@@ -94,8 +94,9 @@ static void cxl_dsp_reset(DeviceState *qdev)
94 latch_registers(dsp);
95 }
96
97 -static void build_dvsecs(CXLComponentState *cxl)
97 +static void build_dvsecs(PCIDevice *d, CXLComponentState *cxl)
98 {
99 + PCIESlot *s = PCIE_SLOT(d);
100 uint8_t *dvsec;
101
102 dvsec = (uint8_t *)&(CXLDVSECPortExt){ 0 };
@@ -107,7 +108,7 @@ static void build_dvsecs(CXLComponentState *cxl)
108 dvsec = (uint8_t *)&(CXLDVSECPortFlexBus){
109 .cap = 0x27, /* Cache, IO, Mem, non-MLD */
110 .ctrl = 0x02, /* IO always enabled */
110 - .status = 0x26, /* same */
111 + .status = s->flitmode ? 0x6 : 0x26, /* lack of 68B */
112 .rcvd_mod_ts_data_phase1 = 0xef, /* WTF? */
113 };
114 cxl_component_create_dvsec(cxl, CXL2_DOWNSTREAM_PORT,
@@ -182,7 +183,7 @@ static void cxl_dsp_realize(PCIDevice *d, Error **errp)
183
184 cxl_cstate->dvsec_offset = CXL_DOWNSTREAM_PORT_DVSEC_OFFSET;
185 cxl_cstate->pdev = d;
185 - build_dvsecs(cxl_cstate);
186 + build_dvsecs(d, cxl_cstate);
187 cxl_component_register_block_init(OBJECT(d), cxl_cstate, TYPE_CXL_DSP);
188 pci_register_bar(d, CXL_COMPONENT_REG_BAR_IDX,
189 PCI_BASE_ADDRESS_SPACE_MEMORY |
@@ -217,6 +218,7 @@ static const Property cxl_dsp_props[] = {
218 speed, PCIE_LINK_SPEED_64),
219 DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot,
220 width, PCIE_LINK_WIDTH_16),
221 + DEFINE_PROP_BOOL("x-256b-flit", PCIESlot, flitmode, true),
222 };
223
224 static void cxl_dsp_class_init(ObjectClass *oc, const void *data)
hw/pci-bridge/cxl_root_port.c
+5 -3
@@ -104,8 +104,9 @@ static void latch_registers(CXLRootPort *crp)
104 cxl_component_register_init_common(reg_state, write_msk, CXL2_ROOT_PORT);
105 }
106
107 -static void build_dvsecs(CXLComponentState *cxl)
107 +static void build_dvsecs(PCIDevice *d, CXLComponentState *cxl)
108 {
109 + PCIESlot *s = PCIE_SLOT(d);
110 uint8_t *dvsec;
111
112 dvsec = (uint8_t *)&(CXLDVSECPortExt){ 0 };
@@ -126,7 +127,7 @@ static void build_dvsecs(CXLComponentState *cxl)
127 dvsec = (uint8_t *)&(CXLDVSECPortFlexBus){
128 .cap = 0x26, /* IO, Mem, non-MLD */
129 .ctrl = 0x2,
129 - .status = 0x26, /* same */
130 + .status = s->flitmode ? 0x6 : 0x26, /* lack of 68B */
131 .rcvd_mod_ts_data_phase1 = 0xef,
132 };
133 cxl_component_create_dvsec(cxl, CXL2_ROOT_PORT,
@@ -176,7 +177,7 @@ static void cxl_rp_realize(DeviceState *dev, Error **errp)
177
178 cxl_cstate->dvsec_offset = CXL_ROOT_PORT_DVSEC_OFFSET;
179 cxl_cstate->pdev = pci_dev;
179 - build_dvsecs(cxl_cstate);
180 + build_dvsecs(pci_dev, cxl_cstate);
181
182 cxl_component_register_block_init(OBJECT(pci_dev), cxl_cstate,
183 TYPE_CXL_ROOT_PORT);
@@ -211,6 +212,7 @@ static const Property gen_rp_props[] = {
212 speed, PCIE_LINK_SPEED_64),
213 DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot,
214 width, PCIE_LINK_WIDTH_32),
215 + DEFINE_PROP_BOOL("x-256b-flit", PCIESlot, flitmode, true),
216 };
217
218 static void cxl_rp_dvsec_write_config(PCIDevice *dev, uint32_t addr,
hw/pci-bridge/cxl_upstream.c
+9 -7
@@ -101,28 +101,29 @@ static void cxl_usp_reset(DeviceState *qdev)
101
102 pci_bridge_reset(qdev);
103 pcie_cap_deverr_reset(d);
104 - pcie_cap_fill_link_ep_usp(d, usp->width, usp->speed);
104 + pcie_cap_fill_link_ep_usp(d, usp->width, usp->speed, usp->flitmode);
105 latch_registers(usp);
106 }
107
108 -static void build_dvsecs(CXLComponentState *cxl)
108 +static void build_dvsecs(CXLUpstreamPort *usp)
109 {
110 + CXLComponentState *cxl_cstate = &usp->cxl_cstate;
111 uint8_t *dvsec;
112
113 dvsec = (uint8_t *)&(CXLDVSECPortExt){
114 .status = 0x1, /* Port Power Management Init Complete */
115 };
115 - cxl_component_create_dvsec(cxl, CXL2_UPSTREAM_PORT,
116 + cxl_component_create_dvsec(cxl_cstate, CXL2_UPSTREAM_PORT,
117 EXTENSIONS_PORT_DVSEC_LENGTH,
118 EXTENSIONS_PORT_DVSEC,
119 EXTENSIONS_PORT_DVSEC_REVID, dvsec);
120 dvsec = (uint8_t *)&(CXLDVSECPortFlexBus){
121 .cap = 0x27, /* Cache, IO, Mem, non-MLD */
122 .ctrl = 0x27, /* Cache, IO, Mem */
122 - .status = 0x26, /* same */
123 + .status = usp->flitmode ? 0x6 : 0x26, /* lack of 68B */
124 .rcvd_mod_ts_data_phase1 = 0xef, /* WTF? */
125 };
125 - cxl_component_create_dvsec(cxl, CXL2_UPSTREAM_PORT,
126 + cxl_component_create_dvsec(cxl_cstate, CXL2_UPSTREAM_PORT,
127 PCIE_CXL3_FLEXBUS_PORT_DVSEC_LENGTH,
128 PCIE_FLEXBUS_PORT_DVSEC,
129 PCIE_CXL3_FLEXBUS_PORT_DVSEC_REVID, dvsec);
@@ -132,7 +133,7 @@ static void build_dvsecs(CXLComponentState *cxl)
133 .reg0_base_lo = RBI_COMPONENT_REG | CXL_COMPONENT_REG_BAR_IDX,
134 .reg0_base_hi = 0,
135 };
135 - cxl_component_create_dvsec(cxl, CXL2_UPSTREAM_PORT,
136 + cxl_component_create_dvsec(cxl_cstate, CXL2_UPSTREAM_PORT,
137 REG_LOC_DVSEC_LENGTH, REG_LOC_DVSEC,
138 REG_LOC_DVSEC_REVID, dvsec);
139 }
@@ -327,7 +328,7 @@ static void cxl_usp_realize(PCIDevice *d, Error **errp)
328 }
329 cxl_cstate->dvsec_offset = CXL_UPSTREAM_PORT_DVSEC_OFFSET;
330 cxl_cstate->pdev = d;
330 - build_dvsecs(cxl_cstate);
331 + build_dvsecs(usp);
332 cxl_component_register_block_init(OBJECT(d), cxl_cstate, TYPE_CXL_USP);
333 pci_register_bar(d, CXL_COMPONENT_REG_BAR_IDX,
334 PCI_BASE_ADDRESS_SPACE_MEMORY |
@@ -369,6 +370,7 @@ static const Property cxl_upstream_props[] = {
370 speed, PCIE_LINK_SPEED_32),
371 DEFINE_PROP_PCIE_LINK_WIDTH("x-width", CXLUpstreamPort,
372 width, PCIE_LINK_WIDTH_16),
373 + DEFINE_PROP_BOOL("x-256b-flit", CXLUpstreamPort, flitmode, false),
374 };
375
376 static void cxl_upstream_class_init(ObjectClass *oc, const void *data)
hw/pci/pcie.c
+19 -4
@@ -113,7 +113,7 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version)
113
114 /* Includes setting the target speed default */
115 static void pcie_cap_fill_lnk(uint8_t *exp_cap, PCIExpLinkWidth width,
116 - PCIExpLinkSpeed speed)
116 + PCIExpLinkSpeed speed, bool flitmode)
117 {
118 /* Clear and fill LNKCAP from what was configured above */
119 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, PCIExpLinkWidth width,
158 PCI_EXP_LNKCAP2_SLS_64_0GB);
159 }
160 }
161 +
162 + if (flitmode) {
163 + pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA2,
164 + PCI_EXP_LNKSTA2_FLIT);
165 + }
166 }
167
168 void pcie_cap_fill_link_ep_usp(PCIDevice *dev, PCIExpLinkWidth width,
164 - PCIExpLinkSpeed speed)
169 + PCIExpLinkSpeed speed, bool flitmode)
170 {
171 uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
172
@@ -175,7 +180,7 @@ void pcie_cap_fill_link_ep_usp(PCIDevice *dev, PCIExpLinkWidth width,
180 QEMU_PCI_EXP_LNKSTA_NLW(width) |
181 QEMU_PCI_EXP_LNKSTA_CLS(speed));
182
178 - pcie_cap_fill_lnk(exp_cap, width, speed);
183 + pcie_cap_fill_lnk(exp_cap, width, speed, flitmode);
184 }
185
186 static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
@@ -212,7 +217,7 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
217 /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */
218 }
219
215 - pcie_cap_fill_lnk(exp_cap, s->width, s->speed);
220 + pcie_cap_fill_lnk(exp_cap, s->width, s->speed, s->flitmode);
221 }
222
223 int pcie_cap_init(PCIDevice *dev, uint8_t offset,
@@ -1175,6 +1180,8 @@ void pcie_sync_bridge_lnk(PCIDevice *bridge_dev)
1180 if (!target || !target->exp.exp_cap) {
1181 lnksta = lnkcap;
1182 } else {
1183 + uint16_t lnksta2;
1184 +
1185 lnksta = target->config_read(target,
1186 target->exp.exp_cap + PCI_EXP_LNKSTA,
1187 sizeof(lnksta));
@@ -1188,6 +1195,14 @@ void pcie_sync_bridge_lnk(PCIDevice *bridge_dev)
1195 lnksta &= ~PCI_EXP_LNKSTA_CLS;
1196 lnksta |= lnkcap & PCI_EXP_LNKCAP_SLS;
1197 }
1198 +
1199 + lnksta2 = target->config_read(target,
1200 + target->exp.exp_cap + PCI_EXP_LNKSTA2,
1201 + sizeof(lnksta2));
1202 + pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA2,
1203 + PCI_EXP_LNKSTA2_FLIT);
1204 + pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA2,
1205 + lnksta2 & PCI_EXP_LNKSTA2_FLIT);
1206 }
1207
1208 if (!(lnksta & PCI_EXP_LNKSTA_NLW)) {
include/hw/cxl/cxl_device.h
+1
@@ -726,6 +726,7 @@ struct CXLType3Dev {
726 /* PCIe link characteristics */
727 PCIExpLinkSpeed speed;
728 PCIExpLinkWidth width;
729 + bool flitmode;
730
731 /* DOE */
732 DOECap doe_cdat;
include/hw/pci-bridge/cxl_upstream_port.h
+1
@@ -15,6 +15,7 @@ typedef struct CXLUpstreamPort {
15
16 PCIExpLinkSpeed speed;
17 PCIExpLinkWidth width;
18 + bool flitmode;
19
20 DOECap doe_cdat;
21 uint64_t sn;
include/hw/pci/pcie.h
+1 -1
@@ -144,7 +144,7 @@ void pcie_ari_init(PCIDevice *dev, uint16_t offset);
144 void pcie_dev_ser_num_init(PCIDevice *dev, uint16_t offset, uint64_t ser_num);
145 void pcie_ats_init(PCIDevice *dev, uint16_t offset, bool aligned);
146 void pcie_cap_fill_link_ep_usp(PCIDevice *dev, PCIExpLinkWidth width,
147 - PCIExpLinkSpeed speed);
147 + PCIExpLinkSpeed speed, bool flitmode);
148
149 void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
150 Error **errp);
include/hw/pci/pcie_port.h
+1
@@ -58,6 +58,7 @@ struct PCIESlot {
58
59 PCIExpLinkSpeed speed;
60 PCIExpLinkWidth width;
61 + bool flitmode;
62
63 /* Disable ACS (really for a pcie_root_port) */
64 bool disable_acs;