@samitouri / QOSamiQemu / commits / be7ce15d35

hw/cxl: Get Physical Port State - update for PCIe flit mode

Recent support for 256B flits, was not accounted for in this FMAPI command that should be retrieving the current status of Physical Switch Ports. Note x-flit-mode control is via the downstream devices, so for USPs the property must be checked to establish support, but for DSPs this mode is always supported (control is with the next port downstream, typically the end point. All cases the linksta2 register may be queried to obtain current status. Note the PCI spec is a little confusing as it refers to this bit only being non 0 if Device Readiness Status (DRS) is in particular states (basically link trained) but Flit mode is a separate feature and DRS may not be present. It is not yet emulated in QEMU. So assume that we should reflect what states DRS would be reporting if it were actually present. One small thing to note is that the current link width for a port with nothing connected reports the same as the capability. This is odd but valid because the value under these circumstances is undefined (PCIe r6.2 table 7-26 Link Status Register - field Current Link Speed.) 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: <20260204173223.44122-3-Jonathan.Cameron@huawei.com>

Jonathan Cameron committed Feb 4, 2026 at 17:32 UTC be7ce15d350bad8ca636921448807b562bfa47c0
1 file changed +22 -2
hw/cxl/cxl-mailbox-utils.c
+22 -2
@@ -627,9 +627,26 @@ static CXLRetCode cmd_get_physical_port_state(const struct cxl_cmd *cmd,
627 port->config_state = CXL_PORT_CONFIG_STATE_DSP;
628 if (ds_dev) {
629 if (object_dynamic_cast(OBJECT(ds_dev), TYPE_CXL_TYPE3)) {
630 + uint16_t lnksta2;
631 +
632 + if (!port_dev->exp.exp_cap) {
633 + return CXL_MBOX_INTERNAL_ERROR;
634 + }
635 +
636 + lnksta2 = port_dev->config_read(port_dev,
637 + port_dev->exp.exp_cap + PCI_EXP_LNKSTA2,
638 + sizeof(lnksta2));
639 +
640 /* Assume MLD for now */
641 port->connected_device_type =
642 CXL_PORT_CONNECTED_DEV_TYPE_3_MLD;
643 + if (lnksta2 & PCI_EXP_LNKSTA2_FLIT) {
644 + port->connected_device_mode =
645 + CXL_PORT_CONNECTED_DEV_MODE_256B;
646 + } else {
647 + port->connected_device_mode =
648 + CXL_PORT_CONNECTED_DEV_MODE_68B_VH;
649 + }
650 } else {
651 port->connected_device_type =
652 CXL_PORT_CONNECTED_DEV_TYPE_PCIE;
@@ -642,12 +659,17 @@ static CXLRetCode cmd_get_physical_port_state(const struct cxl_cmd *cmd,
659 port->connected_device_mode =
660 CXL_PORT_CONNECTED_DEV_MODE_NOT_CXL_OR_DISCONN;
661 }
662 + /* DSP currently always support modes implemented in QEMU */
663 + port->supported_cxl_mode_bitmask = CXL_PORT_SUPPORTS_68B_VH |
664 + CXL_PORT_SUPPORTS_256B;
665 port->supported_ld_count = 3;
666 } else if (usp->port == in->ports[i]) { /* USP */
667 port_dev = PCI_DEVICE(usp);
668 port->config_state = CXL_PORT_CONFIG_STATE_USP;
669 port->connected_device_type = 0; /* Reserved for USP */
670 port->connected_device_mode = 0; /* Reserved for USP */
671 + port->supported_cxl_mode_bitmask = CXL_PORT_SUPPORTS_68B_VH |
672 + (CXL_USP(usp)->flitmode ? CXL_PORT_SUPPORTS_256B : 0);
673 } else {
674 return CXL_MBOX_INVALID_INPUT;
675 }
@@ -676,8 +698,6 @@ static CXLRetCode cmd_get_physical_port_state(const struct cxl_cmd *cmd,
698 /* TODO: Track down if we can get the rest of the info */
699 port->ltssm_state = 0x7;
700 port->first_lane_num = 0;
679 - port->link_state = 0;
680 - port->supported_cxl_mode_bitmask = CXL_PORT_SUPPORTS_68B_VH;
701 }
702
703 pl_size = sizeof(*out) + sizeof(*out->ports) * in->num_ports;