From: Arpit Kumar <arpit1.kumar@samsung.com>
To: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: qemu-devel@nongnu.org, gost.dev@samsung.com,
linux-cxl@vger.kernel.org, nifan.cxl@gmail.com,
dave@stgolabs.net, vishak.g@samsung.com, krish.reddy@samsung.com,
a.manzanares@samsung.com, alok.rathore@samsung.com
Subject: Re: [PATCH 1/3] hw/cxl: Storing physical ports info during enumeration
Date: Tue, 17 Jun 2025 15:16:25 +0530 [thread overview]
Message-ID: <20250617094625.i2j7ewin7fy2b2nj@test-PowerEdge-R740xd> (raw)
In-Reply-To: <20250610152121.00004dda@huawei.com>
[-- Attachment #1: Type: text/plain, Size: 13848 bytes --]
On 10/06/25 03:21PM, Jonathan Cameron wrote:
>On Mon, 2 Jun 2025 19:29:40 +0530
>Arpit Kumar <arpit1.kumar@samsung.com> wrote:
>
>> Physical ports info is stored for both mailbox cci &
>> mctp based cci type as per spec CXL r3.2 Table 8-230: Physical Switch
>>
>> Signed-off-by: Arpit Kumar <arpit1.kumar@samsung.com>
>Hi Arpit,
>
>Sorry for slow response. I got behind on reviews in general and missed
>this in the backlog!
>
>Anyhow, main comment is that this is mostly a refactor that only makes
>sense in a single patch with what you have in patch 2.
>
>Don't introduce duplicate infrastructure for so few usecases. It means
>we can't just look at he diff and see what was added vs what was removed.
>Much cleaner to just have a single refactoring patch.
Thanks Jonathan for the review. Will combine the first 2 patches and
apply changes as suggested in the next iteration(V2) of the patch
series.
>> ---
>> hw/cxl/cxl-mailbox-utils.c | 166 ++++++++++++++++++++++++++++++++++++
>> include/hw/cxl/cxl_device.h | 28 ++++++
>> 2 files changed, 194 insertions(+)
>>
>> diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
>> index a02d130926..680055c6c0 100644
>> --- a/hw/cxl/cxl-mailbox-utils.c
>> +++ b/hw/cxl/cxl-mailbox-utils.c
>> @@ -124,6 +124,64 @@ enum {
>> #define GET_MHD_INFO 0x0
>> };
>>
>> +/* link state flags */
>Naming makes that clear (which is great) so I'd drop the comment.
>
okay
>> +#define LINK_STATE_FLAG_LANE_REVERSED (1 << 0)
>
>BIT(0) from qemu/bitops.h
>
got it
>> +#define LINK_STATE_FLAG_PERST_ASSERTED (1 << 1)
>> +#define LINK_STATE_FLAG_PRSNT (1 << 2)
>> +#define LINK_STATE_FLAG_POWER_OFF (1 << 3)
>> +
>> +/* physical port control info - CXL r3.2 table 7-19 */
>> +typedef enum {
>> + PORT_DISABLED = 0,
>> + BIND_IN_PROGRESS = 1,
>> + UNBIND_IN_PROGRESS = 2,
>> + DSP = 3,
>> + USP = 4,
>> + FABRIC_PORT = 5,
>> + INVALID_PORT_ID = 15
>> +} current_port_config_state;
>
>These aren't used as types really but more as defines.
>Hence I'd be tempted to make them defines. Also provide
>defines for the masks.
>
>Namespace the defines so it is obvious which field
>they are in.
>
Will the below changes be the right way to proceed?
#define CXL_PORT_CONFIG_STATE_DISABLED 0x0
#define CXL_PORT_CONFIG_STATE_BIND_IN_PROGRESS 0x1 etc.
>> +
>> +typedef enum {
>> + NOT_CXL_OR_DISCONNECTED = 0x00,
>> + RCD_MODE = 0x01,
>> + CXL_68B_FLIT_AND_VH_MODE = 0x02,
>> + STANDARD_256B_FLIT_MODE = 0x03,
>> + CXL_LATENCY_OPTIMIZED_256B_FLIT_MODE = 0x04,
>> + PBR_MODE = 0x05
>> +} connected_device_mode;
>> +
>> +typedef enum {
>> + NO_DEVICE_DETECTED = 0,
>> + PCIE_DEVICE = 1,
>> + CXL_TYPE_1_DEVICE = 2,
>> + CXL_TYPE_2_DEVICE_OR_HBR_SWITCH = 3,
>> + CXL_TYPE_3_SLD = 4,
>> + CXL_TYPE_3_MLD = 5,
>> + PBR_COMPONENT = 6
>> +} connected_device_type;
>> +
>> +typedef enum {
>> + CXL_RCD_MODE = 0x00,
>> + CXL_68B_FLIT_AND_VH_CAPABLE = 0x01,
>> + CXL_256B_FLIT_CAPABLE = 0x02,
>> + CXL_LATENCY_OPTIMIZED_256B_FLIT = 0x03,
>> + CXL_PBR_CAPABLE = 0x04
>> +} supported_cxl_modes;
>> +
>> +typedef enum {
>> + LTSSM_DETECT = 0x00,
>> + LTSSM_POLLING = 0x01,
>> + LTSSM_CONFIGURATION = 0x02,
>> + LTSSM_RECOVERY = 0x03,
>> + LTSSM_L0 = 0x04,
>> + LTSSM_L0S = 0x05,
>> + LTSSM_L1 = 0x06,
>> + LTSSM_L2 = 0x07,
>> + LTSSM_DISABLED = 0x08,
>> + LTSSM_LOOPBACK = 0x09,
>> + LTSSM_HOT_RESET = 0x0A
>> +} LTSSM_State;
>> +
>> /* CCI Message Format CXL r3.1 Figure 7-19 */
>> typedef struct CXLCCIMessage {
>> uint8_t category;
>> @@ -3686,6 +3744,112 @@ void cxl_add_cci_commands(CXLCCI *cci, const struct cxl_cmd (*cxl_cmd_set)[256],
>> cxl_rebuild_cel(cci);
>> }
>>
>> +static CXLRetCode cxl_set_port_type(struct phy_port *ports, int pnum,
>> + CXLCCI *cci)
>> +{
>> + PCIDevice *port_dev;
>> + uint16_t lnkcap, lnkcap2, lnksta;
>> + int i = pnum;
>I'd just use pnum for all the indexes. This local variable doesn't add
>much readability.
>
okay
>> + if (!cci) {
>
>As below. No need to defend against bugs so only check if there is a
>chance cci might not be set.
>
right, thanks for pointing out.
>> + return CXL_MBOX_INTERNAL_ERROR;
>> + }
>> +
>
>Don't interleave declarations and cod.e
>
got it
>> + PCIBus *bus = &PCI_BRIDGE(cci->d)->sec_bus;
>> + PCIEPort *usp = PCIE_PORT(cci->d);
>
>blank line after declarations - of include this
>in the declarations as
> PCIEDevice *port_dev = pcie_find_port_by_pn(bus, i);
>
>However that is reasonable expensive, so maybe do the usp case first?
>
got it
>
>> + port_dev = pcie_find_port_by_pn(bus, i);
>> +
>> + if (port_dev) { /* DSP */
>> + PCIDevice *ds_dev = pci_bridge_get_sec_bus(PCI_BRIDGE(port_dev))
>> + ->devices[0];
>> + ports->pport_info[i].port_id = i;
>
>This is not affected by USP or DSP, so drop it out of this if / else.
>
okay
>> + ports->pport_info[i].current_port_config_state = DSP;
>> + ports->active_port_bitmask[i / 8] |= (1 << i % 8);
>
>As below - this is currently set but not read, so I'd bring it in as part of
>the patch that uses it.
>
>Independent of port type, so doesn't belong in the if/else.
>
okay
>
>> + if (ds_dev) {
>> + if (object_dynamic_cast(OBJECT(ds_dev), TYPE_CXL_TYPE3)) {
>> + ports->pport_info[i].connected_device_type = CXL_TYPE_3_MLD;
>
>Hmm. We should make this controllable (vs SLD). I made this up in the existing
>code and probably shouldn't have done :(
>
got it, will currently change it to CXL_TYPE_3_SLD in next iteration of
patch series. However, once we add support for MLD, will make this
controllable as suggested.
>> + } else {
>> + ports->pport_info[i].connected_device_type = PCIE_DEVICE;
>> + }
>> + } else {
>> + ports->pport_info[i].connected_device_type = NO_DEVICE_DETECTED;
>> + }
>> + ports->pport_info[i].supported_ld_count = 3;
>> + } else if (usp->port == i) { /* USP */
>> + port_dev = PCI_DEVICE(usp);
>> + ports->pport_info[i].port_id = i;
>> + ports->pport_info[i].current_port_config_state = USP;
>> + ports->pport_info[i].connected_device_type = NO_DEVICE_DETECTED;
>> + ports->active_port_bitmask[i / 8] |= (1 << i % 8);
>> + } else {
>> + return CXL_MBOX_INVALID_INPUT;
>> + }
>> +
>> + if (!port_dev->exp.exp_cap) {
>> + return CXL_MBOX_INTERNAL_ERROR;
>> + }
>> +
>> + lnksta = port_dev->config_read(port_dev,
>> + port_dev->exp.exp_cap + PCI_EXP_LNKSTA,
>> + sizeof(lnksta));
>> + lnkcap = port_dev->config_read(port_dev,
>> + port_dev->exp.exp_cap + PCI_EXP_LNKCAP,
>> + sizeof(lnkcap));
>> + lnkcap2 = port_dev->config_read(port_dev,
>> + port_dev->exp.exp_cap + PCI_EXP_LNKCAP2,
>> + sizeof(lnkcap2));
>> +
>> + ports->pport_info[i].max_link_width = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
>> + ports->pport_info[i].negotiated_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4;
>> + ports->pport_info[i].supported_link_speeds_vector = (lnkcap2 & 0xFE) >> 1;
>> + ports->pport_info[i].max_link_speed = lnkcap & PCI_EXP_LNKCAP_SLS;
>> + ports->pport_info[i].current_link_speed = lnksta & PCI_EXP_LNKSTA_CLS;
>> +
>> + ports->pport_info[i].ltssm_state = LTSSM_L2;
>> + ports->pport_info[i].first_negotiated_lane_num = 0;
>> + ports->pport_info[i].link_state_flags = 0;
>> + ports->pport_info[i].supported_cxl_modes = CXL_256B_FLIT_CAPABLE;
>> + ports->pport_info[i].connected_device_mode = STANDARD_256B_FLIT_MODE;
>> +
>> + return CXL_MBOX_SUCCESS;
>> +}
>> +
>> +static CXLRetCode cxl_set_phy_port_info(CXLCCI *cci)
>> +{
>> + uint8_t phy_port_num;
>> + if (!cci) {
>
>What is this defending against? At least for now the cci
>is definitely not null where this function is used.
>
got it
>> + return CXL_MBOX_INTERNAL_ERROR;
>> + }
>> +
>> + PCIEPort *usp = PCIE_PORT(cci->d);
>
>Don't mix declarations and code. Declarations still typically
>go at the top.
>
got it
>> + PCIBus *bus = &PCI_BRIDGE(cci->d)->sec_bus;
>> + struct phy_port *ports = &cci->pports;
>> + int num_phys_ports = pcie_count_ds_ports(bus) + 1;
>> + if (num_phys_ports < 0) {
>
>Given add 1 this is always false and the check serve no
>purpose.
>
right, thanks for pointing this out
>> + return CXL_MBOX_INTERNAL_ERROR;
>> + }
>> +
>> + ports->num_ports = num_phys_ports;
>> + phy_port_num = usp->port;
>> +
>> + cxl_set_port_type(ports, phy_port_num, cci); /* usp */
>
>USP for comment given it's an acronym.
>
okay
>> +
>> + for (int devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
>
>Maybe use pci_for_each_device_under_bus() ?
>
okay
>> + PCIDevice *dev = bus->devices[devfn];
>> +
>> + if (dev) {
>> + phy_port_num = PCIE_PORT(dev)->port;
>> + const char *typename = object_get_typename(OBJECT(dev));
>
>Normally in qemu we just use a dynamic cast to identify types rather than
>matching on names. I'd prefer that approach here.
>
>if (object_dynamic_cast(OBJECT(dev), TYPE_CXL_DSP)
>
>
got it
>> +
>> + if ((strcmp(typename, "cxl-downstream") == 0)) {
>> + cxl_set_port_type(ports, phy_port_num, cci);
>> + } else {
>> + return CXL_MBOX_INTERNAL_ERROR;
>> + }
>> + }
>> + }
>> + return CXL_MBOX_SUCCESS;
>> +}
>> +
>> void cxl_initialize_mailbox_swcci(CXLCCI *cci, DeviceState *intf,
>> DeviceState *d, size_t payload_max)
>> {
>> @@ -3693,6 +3857,7 @@ void cxl_initialize_mailbox_swcci(CXLCCI *cci, DeviceState *intf,
>> cci->d = d;
>> cci->intf = intf;
>> cxl_init_cci(cci, payload_max);
>> + cxl_set_phy_port_info(cci); /* store port info */
>> }
>>
>> void cxl_initialize_mailbox_t3(CXLCCI *cci, DeviceState *d, size_t payload_max)
>> @@ -3797,4 +3962,5 @@ void cxl_initialize_usp_mctpcci(CXLCCI *cci, DeviceState *d, DeviceState *intf,
>> cci->d = d;
>> cci->intf = intf;
>> cxl_init_cci(cci, payload_max);
>> + cxl_set_phy_port_info(cci); /* store port info */
>
>I'd not bother with the comment. The naming of the function is clear enough.
>
okay
>> }
>> diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
>> index ca515cab13..9eb128a1e8 100644
>> --- a/include/hw/cxl/cxl_device.h
>> +++ b/include/hw/cxl/cxl_device.h
>> @@ -127,6 +127,31 @@
>> CXL_NUM_CHMU_INSTANCES * (1 << 16), \
>> (1 << 16))
>>
>> +/* CXL r3.2 Table 7-19: Port Info */
>> +struct cxl_phy_port_info {
>
>There is one of these in cxl-mailbox-utils.c already. Pull it out
>as part of this patch. That may mean combining patches 1 and 2.
>
>
>> + uint8_t port_id;
>> + uint8_t current_port_config_state;
>
>I'd pull the field defines and masks etc alongside the structure
>definition.
>
okay
>
>> + uint8_t connected_device_mode;
>> + uint8_t rsv1;
>> + uint8_t connected_device_type;
>> + uint8_t supported_cxl_modes;
>> + uint8_t max_link_width;
>> + uint8_t negotiated_link_width;
>> + uint8_t supported_link_speeds_vector;
>> + uint8_t max_link_speed;
>> + uint8_t current_link_speed;
>> + uint8_t ltssm_state;
>> + uint8_t first_negotiated_lane_num;
>> + uint16_t link_state_flags;
>> + uint8_t supported_ld_count;
>> +} QEMU_PACKED;
>> +
>> +struct phy_port {
>> + uint8_t num_ports;
>> + uint8_t active_port_bitmask[0x20];
>
>Why that size? Also not used yet - so maybe bring this in where
>you need it?
>
>> + struct cxl_phy_port_info pport_info[PCI_DEVFN_MAX];
>
>I think there are lower limits than that on how many ports
>we can have on a given bus + does this actually care about
>the limits from one bus? Request is per switch, not per
>virtual heirarchy. So we might be limited by number of unique
>port numbers.
>
>Today we only have one VCH so maybe this is fine for now.
>
>
Right, the request is per switch and not per virtual heirarchy.
According to CXL r3.2 Table 7-16, length of number of physical ports
is 1 byte which accounts for 256 physical ports. So, will
#define CXL_MAX_PHY_PORTS 256 and change the length of pport_info[] to
it.
>> +};
>> +
>> /* CXL r3.1 Table 8-34: Command Return Codes */
>> typedef enum {
>> CXL_MBOX_SUCCESS = 0x0,
>> @@ -223,6 +248,9 @@ typedef struct CXLCCI {
>> /* get log capabilities */
>> const CXLLogCapabilities *supported_log_cap;
>>
>> + /*physical ports information */
>
>Space after /*
>
>Run checkpatch.pl over qemu patches. I 'think' it would have
>caught this trivial thing.
>
I did run checkpatch.pl but it didn't catch this. will recheck for such
trivial things moving forward.
>> + struct phy_port pports;
>Storing this in the CCI is a little odd seeing (as opposed to
>in the USP - maybe DSP) as there is only one answer to this query whichever
>CCI we come in on.
>
>For similar things we do have firmware update in there which
>is a mixture of device side stuff and CCI specific handling.
>That might ideally be split up. Obviously not something for
>this patch, but maybe we can avoid making CCI more bloated?
>
>To me it seems reasonable to store this in the port and set
>it up whether or not the cci is connected.
>
got it, will try the implementation accordingly. It will be helpful if could share some
reference on handling the same.
>> +
>> /* background command handling (times in ms) */
>> struct {
>> uint16_t opcode;
>
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
next prev parent reply other threads:[~2025-06-17 10:21 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CGME20250602140008epcas5p25fce01492de105da3cdc0aaa533f6ebc@epcas5p2.samsung.com>
2025-06-02 13:59 ` [PATCH 0/3] FM-API Physical switch command set update Arpit Kumar
2025-06-02 13:59 ` [PATCH 1/3] hw/cxl: Storing physical ports info during enumeration Arpit Kumar
2025-06-10 14:21 ` Jonathan Cameron
2025-06-17 9:46 ` Arpit Kumar [this message]
2025-06-18 11:31 ` Jonathan Cameron
2025-06-02 13:59 ` [PATCH 2/3] hw/cxl: Simplified Identify Switch Device & Get Physical Port State Arpit Kumar
2025-06-10 14:29 ` Jonathan Cameron
2025-06-17 10:01 ` Arpit Kumar
2025-06-02 13:59 ` [PATCH 3/3] hw/cxl: Add Physical Port Control (Opcode 5102h) Arpit Kumar
2025-06-10 14:45 ` Jonathan Cameron
2025-06-17 10:11 ` Arpit Kumar
2025-06-18 11:32 ` Jonathan Cameron
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250617094625.i2j7ewin7fy2b2nj@test-PowerEdge-R740xd \
--to=arpit1.kumar@samsung.com \
--cc=Jonathan.Cameron@huawei.com \
--cc=a.manzanares@samsung.com \
--cc=alok.rathore@samsung.com \
--cc=dave@stgolabs.net \
--cc=gost.dev@samsung.com \
--cc=krish.reddy@samsung.com \
--cc=linux-cxl@vger.kernel.org \
--cc=nifan.cxl@gmail.com \
--cc=qemu-devel@nongnu.org \
--cc=vishak.g@samsung.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox