* [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h)
[not found] <CGME20250522063149epcas5p13719600aa8f59313ff3dc2570c996aec@epcas5p1.samsung.com>
@ 2025-05-22 6:31 ` Vinayak Holikatti
2025-05-22 16:48 ` Fan Ni
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Vinayak Holikatti @ 2025-05-22 6:31 UTC (permalink / raw)
To: qemu-devel
Cc: gost.dev, linux-cxl, nifan.cxl, dave, vishak.g, krish.reddy,
a.manzanares, alok.rathore, Vinayak Holikatti
CXL spec 3.2 section 7.6.7.5.2 describes Get Head Info.
Signed-off-by: Vinayak Holikatti <vinayak.kh@samsung.com>
---
This patch is generated against Jonathan Cameron's branch cxl-2025-03-20
hw/cxl/cxl-mailbox-utils.c | 21 +++++++++
hw/cxl/mhsld/mhsld.c | 92 ++++++++++++++++++++++++++++++++++++-
hw/cxl/mhsld/mhsld.h | 26 +++++++++++
include/hw/cxl/cxl_device.h | 6 +++
4 files changed, 144 insertions(+), 1 deletion(-)
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index a02d130926..4f25caecea 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -122,6 +122,7 @@ enum {
#define MANAGEMENT_COMMAND 0x0
MHD = 0x55,
#define GET_MHD_INFO 0x0
+ #define GET_MHD_HEAD_INFO 0x1
};
/* CCI Message Format CXL r3.1 Figure 7-19 */
@@ -267,6 +268,23 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
return CXL_MBOX_UNSUPPORTED;
}
+/*
+ * CXL r3.2 section 7.6.7.5.2 - Get Multi-Headed Head Info (Opcode 5501h)
+ */
+static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
+ uint8_t *payload_in, size_t len_in,
+ uint8_t *payload_out, size_t *len_out,
+ CXLCCI *cci)
+{
+ CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
+ CXLType3Class *cvc = CXL_TYPE3_GET_CLASS(ct3d);
+ if (cvc->mhd_get_head_info) {
+ return cvc->mhd_get_head_info(cmd, payload_in, len_in, payload_out,
+ len_out, cci);
+ }
+ return CXL_MBOX_UNSUPPORTED;
+}
+
static CXLRetCode cmd_events_get_records(const struct cxl_cmd *cmd,
uint8_t *payload_in, size_t len_in,
uint8_t *payload_out, size_t *len_out,
@@ -3429,6 +3447,7 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
"MEDIA_AND_POISON_GET_SCAN_MEDIA_RESULTS",
cmd_media_get_scan_media_results, 0, 0 },
[MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
+ [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
};
static const struct cxl_cmd cxl_cmd_set_dcd[256][256] = {
@@ -3761,6 +3780,8 @@ static const struct cxl_cmd cxl_cmd_set_t3_fm_owned_ld_mctp[256][256] = {
[TIMESTAMP][GET] = { "TIMESTAMP_GET", cmd_timestamp_get, 0, 0 },
[TUNNEL][MANAGEMENT_COMMAND] = { "TUNNEL_MANAGEMENT_COMMAND",
cmd_tunnel_management_cmd, ~0, 0 },
+ [MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
+ [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
};
void cxl_initialize_t3_fm_owned_ld_mctpcci(CXLCCI *cci, DeviceState *d,
diff --git a/hw/cxl/mhsld/mhsld.c b/hw/cxl/mhsld/mhsld.c
index 9f633b3bed..981546b5ff 100644
--- a/hw/cxl/mhsld/mhsld.c
+++ b/hw/cxl/mhsld/mhsld.c
@@ -61,9 +61,57 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}
+/*
+ * CXL r3.2 section 7.6.7.5.2 - Get Head Info (Opcode 5501h)
+ *
+ * This command retrieves the number of heads, number of supported LDs,
+ * and Head-to-LD mapping of a Multi-Headed device.
+ */
+static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
+ uint8_t *payload_in, size_t len_in,
+ uint8_t *payload_out, size_t *len_out,
+ CXLCCI *cci)
+{
+ CXLMHSLDState *s = CXL_MHSLD(cci->d);
+ MHDGetHeadInfoInput *input = (void *)payload_in;
+ MHDGetHeadInfoOutput *output = (void *)payload_out;
+ int i = 0;
+
+ if (input->start_head > MHSLD_HEADS) {
+ return CXL_MBOX_INVALID_INPUT;
+ }
+
+ output->nr_heads = MIN((MHSLD_HEADS - input->start_head), input->nr_heads);
+ for (i = input->start_head; i < input->start_head + output->nr_heads; i++) {
+ output->head_info_list[i].port_number =
+ s->mhd_state->head_info_blocks[i].port_number;
+ output->head_info_list[i].max_link_width =
+ s->mhd_state->head_info_blocks[i].max_link_width;
+ output->head_info_list[i].nego_link_width =
+ s->mhd_state->head_info_blocks[i].nego_link_width;
+ output->head_info_list[i].supp_link_speeds_vector =
+ s->mhd_state->head_info_blocks[i].supp_link_speeds_vector;
+ output->head_info_list[i].max_link_speed =
+ s->mhd_state->head_info_blocks[i].max_link_speed;
+ output->head_info_list[i].current_link_speed =
+ s->mhd_state->head_info_blocks[i].current_link_speed;
+ output->head_info_list[i].ltssm_state =
+ s->mhd_state->head_info_blocks[i].ltssm_state;
+ output->head_info_list[i].first_nego_lane_num =
+ s->mhd_state->head_info_blocks[i].first_nego_lane_num;
+ output->head_info_list[i].link_state_flags =
+ s->mhd_state->head_info_blocks[i].link_state_flags;
+ }
+
+ *len_out = sizeof(*output) + output->nr_heads * sizeof(MHDHeadInfoBlock);
+ return CXL_MBOX_SUCCESS;
+}
+
static const struct cxl_cmd cxl_cmd_set_mhsld[256][256] = {
[MHSLD_MHD][GET_MHD_INFO] = {"GET_MULTI_HEADED_INFO",
cmd_mhd_get_info, 2, 0},
+ [MHSLD_MHD][GET_MHD_HEAD_INFO] = {"GET_HEAD_INFO",
+ cmd_mhd_get_head_info, 2, 0},
};
static const Property cxl_mhsld_props[] = {
@@ -166,6 +214,47 @@ static void cxl_mhsld_state_initialize(CXLMHSLDState *s, size_t dc_size)
s->mhd_state->nr_blocks = dc_size / MHSLD_BLOCK_SZ;
}
+
+static void cxl_mhsld_init_head_info(CXLMHSLDState *s, PCIDevice *pdev)
+{
+ uint16_t lnksta = 0;
+ uint16_t current_link_speed = 0;
+ uint16_t negotiated_link_width = 0;
+ uint16_t lnkcap = 0, lnkcap2 = 0;
+ uint16_t max_link_width = 0;
+ uint16_t max_link_speed = 0;
+ uint16_t supported_link_speeds_vector = 0;
+
+ lnksta = pdev->config_read(pdev,
+ pdev->exp.exp_cap + PCI_EXP_LNKSTA,
+ sizeof(lnksta));
+ lnkcap = pdev->config_read(pdev,
+ pdev->exp.exp_cap + PCI_EXP_LNKCAP,
+ sizeof(lnkcap));
+ lnkcap2 = pdev->config_read(pdev,
+ pdev->exp.exp_cap + PCI_EXP_LNKCAP2,
+ sizeof(lnkcap2));
+ supported_link_speeds_vector = (lnkcap2 & 0xFE) >> 1;
+ max_link_width = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
+ max_link_speed = lnkcap & PCI_EXP_LNKCAP_SLS;
+ current_link_speed = lnksta & PCI_EXP_LNKSTA_CLS;
+ negotiated_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4;
+
+ s->mhd_state->head_info_blocks[s->mhd_head].port_number = s->mhd_head;
+ s->mhd_state->head_info_blocks[s->mhd_head].max_link_width = max_link_width;
+ s->mhd_state->head_info_blocks[s->mhd_head].nego_link_width =
+ negotiated_link_width;
+ s->mhd_state->head_info_blocks[s->mhd_head].supp_link_speeds_vector =
+ supported_link_speeds_vector;
+ s->mhd_state->head_info_blocks[s->mhd_head].max_link_speed =
+ max_link_speed;
+ s->mhd_state->head_info_blocks[s->mhd_head].current_link_speed =
+ current_link_speed;
+ s->mhd_state->head_info_blocks[s->mhd_head].ltssm_state = 0x7;
+ s->mhd_state->head_info_blocks[s->mhd_head].first_nego_lane_num = 0;
+ s->mhd_state->head_info_blocks[s->mhd_head].link_state_flags = 0;
+}
+
/* Returns starting index of region in MHD map. */
static inline size_t cxl_mhsld_find_dc_region_start(PCIDevice *d,
CXLDCRegion *r)
@@ -376,7 +465,7 @@ static void cxl_mhsld_realize(PCIDevice *pci_dev, Error **errp)
}
cxl_mhsld_state_initialize(s, dc_size);
-
+ cxl_mhsld_init_head_info(s, pci_dev);
/* Set the LD ownership for this head to this system */
s->mhd_state->ldmap[s->mhd_head] = s->mhd_head;
return;
@@ -428,6 +517,7 @@ static void cxl_mhsld_class_init(ObjectClass *klass, void *data)
CXLType3Class *cvc = CXL_TYPE3_CLASS(klass);
cvc->mhd_get_info = cmd_mhd_get_info;
+ cvc->mhd_get_head_info = cmd_mhd_get_head_info;
cvc->mhd_access_valid = cxl_mhsld_access_valid;
cvc->mhd_reserve_extents = cxl_mhsld_reserve_extents;
cvc->mhd_reclaim_extents = cxl_mhsld_reclaim_extents;
diff --git a/hw/cxl/mhsld/mhsld.h b/hw/cxl/mhsld/mhsld.h
index e7ead1f0d2..c9fbec71ca 100644
--- a/hw/cxl/mhsld/mhsld.h
+++ b/hw/cxl/mhsld/mhsld.h
@@ -23,6 +23,18 @@
*/
#define MHSLD_HEADS (8)
+typedef struct MHDHeadInfoBlock {
+ uint8_t port_number;
+ uint8_t max_link_width;
+ uint8_t nego_link_width;
+ uint8_t supp_link_speeds_vector;
+ uint8_t max_link_speed;
+ uint8_t current_link_speed;
+ uint8_t ltssm_state;
+ uint8_t first_nego_lane_num;
+ uint8_t link_state_flags;
+} QEMU_PACKED MHDHeadInfoBlock;
+
/*
* The shared state cannot have 2 variable sized regions
* so we have to max out the ldmap.
@@ -32,6 +44,7 @@ typedef struct MHSLDSharedState {
uint8_t nr_lds;
uint8_t ldmap[MHSLD_HEADS];
uint64_t nr_blocks;
+ MHDHeadInfoBlock head_info_blocks[MHSLD_HEADS];
uint8_t blocks[];
} MHSLDSharedState;
@@ -52,6 +65,7 @@ struct CXLMHSLDClass {
enum {
MHSLD_MHD = 0x55,
#define GET_MHD_INFO 0x0
+ #define GET_MHD_HEAD_INFO 0x1
};
/*
@@ -72,4 +86,16 @@ typedef struct MHDGetInfoOutput {
uint16_t resv2;
uint8_t ldmap[];
} QEMU_PACKED MHDGetInfoOutput;
+
+typedef struct MHDGetHeadInfoInput {
+ uint8_t start_head;
+ uint8_t nr_heads;
+} QEMU_PACKED MHDGetHeadInfoInput;
+
+typedef struct MHDGetHeadInfoOutput {
+ uint8_t nr_heads;
+ uint8_t rsvd[3];
+ MHDHeadInfoBlock head_info_list[];
+} QEMU_PACKED MHDGetHeadInfoOutput;
+
#endif
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index ca515cab13..c93c71c45d 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -732,6 +732,12 @@ struct CXLType3Class {
uint8_t *payload_out,
size_t *len_out,
CXLCCI *cci);
+ CXLRetCode (*mhd_get_head_info)(const struct cxl_cmd *cmd,
+ uint8_t *payload_in,
+ size_t len_in,
+ uint8_t *payload_out,
+ size_t *len_out,
+ CXLCCI *cci);
bool (*mhd_access_valid)(PCIDevice *d, uint64_t addr, unsigned int size);
bool (*mhd_reserve_extents)(PCIDevice *d,
CxlDynamicCapacityExtentList *records,
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h)
2025-05-22 6:31 ` [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h) Vinayak Holikatti
@ 2025-05-22 16:48 ` Fan Ni
2025-07-01 12:59 ` Alok Rathore
2025-05-22 19:15 ` Davidlohr Bueso
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Fan Ni @ 2025-05-22 16:48 UTC (permalink / raw)
To: Vinayak Holikatti
Cc: qemu-devel, gost.dev, linux-cxl, nifan.cxl, dave, vishak.g,
krish.reddy, a.manzanares, alok.rathore
On Thu, May 22, 2025 at 12:01:35PM +0530, Vinayak Holikatti wrote:
> CXL spec 3.2 section 7.6.7.5.2 describes Get Head Info.
>
> Signed-off-by: Vinayak Holikatti <vinayak.kh@samsung.com>
> ---
> This patch is generated against Jonathan Cameron's branch cxl-2025-03-20
>
> hw/cxl/cxl-mailbox-utils.c | 21 +++++++++
> hw/cxl/mhsld/mhsld.c | 92 ++++++++++++++++++++++++++++++++++++-
> hw/cxl/mhsld/mhsld.h | 26 +++++++++++
> include/hw/cxl/cxl_device.h | 6 +++
> 4 files changed, 144 insertions(+), 1 deletion(-)
>
> diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
> index a02d130926..4f25caecea 100644
> --- a/hw/cxl/cxl-mailbox-utils.c
> +++ b/hw/cxl/cxl-mailbox-utils.c
> @@ -122,6 +122,7 @@ enum {
> #define MANAGEMENT_COMMAND 0x0
> MHD = 0x55,
> #define GET_MHD_INFO 0x0
> + #define GET_MHD_HEAD_INFO 0x1
> };
>
> /* CCI Message Format CXL r3.1 Figure 7-19 */
> @@ -267,6 +268,23 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
> return CXL_MBOX_UNSUPPORTED;
> }
>
> +/*
> + * CXL r3.2 section 7.6.7.5.2 - Get Multi-Headed Head Info (Opcode 5501h)
That does not match the section subject of the spec
Get Head Info (...
> + */
> +static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
> + uint8_t *payload_in, size_t len_in,
> + uint8_t *payload_out, size_t *len_out,
> + CXLCCI *cci)
The indent here is not right.
> +static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
> + uint8_t *payload_in, size_t len_in,
> +{
> + CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
> + CXLType3Class *cvc = CXL_TYPE3_GET_CLASS(ct3d);
> + if (cvc->mhd_get_head_info) {
> + return cvc->mhd_get_head_info(cmd, payload_in, len_in, payload_out,
> + len_out, cci);
indent needs fix.
> + }
> + return CXL_MBOX_UNSUPPORTED;
> +}
> +
> static CXLRetCode cmd_events_get_records(const struct cxl_cmd *cmd,
> uint8_t *payload_in, size_t len_in,
> uint8_t *payload_out, size_t *len_out,
> @@ -3429,6 +3447,7 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
> "MEDIA_AND_POISON_GET_SCAN_MEDIA_RESULTS",
> cmd_media_get_scan_media_results, 0, 0 },
> [MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
> + [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
> };
>
> static const struct cxl_cmd cxl_cmd_set_dcd[256][256] = {
> @@ -3761,6 +3780,8 @@ static const struct cxl_cmd cxl_cmd_set_t3_fm_owned_ld_mctp[256][256] = {
> [TIMESTAMP][GET] = { "TIMESTAMP_GET", cmd_timestamp_get, 0, 0 },
> [TUNNEL][MANAGEMENT_COMMAND] = { "TUNNEL_MANAGEMENT_COMMAND",
> cmd_tunnel_management_cmd, ~0, 0 },
> + [MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
> + [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
> };
>
> void cxl_initialize_t3_fm_owned_ld_mctpcci(CXLCCI *cci, DeviceState *d,
> diff --git a/hw/cxl/mhsld/mhsld.c b/hw/cxl/mhsld/mhsld.c
> index 9f633b3bed..981546b5ff 100644
> --- a/hw/cxl/mhsld/mhsld.c
> +++ b/hw/cxl/mhsld/mhsld.c
> @@ -61,9 +61,57 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
> return CXL_MBOX_SUCCESS;
> }
>
> +/*
> + * CXL r3.2 section 7.6.7.5.2 - Get Head Info (Opcode 5501h)
> + *
> + * This command retrieves the number of heads, number of supported LDs,
> + * and Head-to-LD mapping of a Multi-Headed device.
> + */
> +static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
> + uint8_t *payload_in, size_t len_in,
> + uint8_t *payload_out, size_t *len_out,
> + CXLCCI *cci)
> +{
> + CXLMHSLDState *s = CXL_MHSLD(cci->d);
> + MHDGetHeadInfoInput *input = (void *)payload_in;
> + MHDGetHeadInfoOutput *output = (void *)payload_out;
> + int i = 0;
> +
> + if (input->start_head > MHSLD_HEADS) {
Should be ">=" ?
Also, per the spec, we need also check the "number of heads" field, if
start_head and number of heads together point to a non-exist head, we
should return invalid input.
> + return CXL_MBOX_INVALID_INPUT;
> + }
> +
> + output->nr_heads = MIN((MHSLD_HEADS - input->start_head), input->nr_heads);
> + for (i = input->start_head; i < input->start_head + output->nr_heads; i++) {
> + output->head_info_list[i].port_number =
> + s->mhd_state->head_info_blocks[i].port_number;
> + output->head_info_list[i].max_link_width =
> + s->mhd_state->head_info_blocks[i].max_link_width;
> + output->head_info_list[i].nego_link_width =
> + s->mhd_state->head_info_blocks[i].nego_link_width;
> + output->head_info_list[i].supp_link_speeds_vector =
> + s->mhd_state->head_info_blocks[i].supp_link_speeds_vector;
> + output->head_info_list[i].max_link_speed =
> + s->mhd_state->head_info_blocks[i].max_link_speed;
> + output->head_info_list[i].current_link_speed =
> + s->mhd_state->head_info_blocks[i].current_link_speed;
> + output->head_info_list[i].ltssm_state =
> + s->mhd_state->head_info_blocks[i].ltssm_state;
> + output->head_info_list[i].first_nego_lane_num =
> + s->mhd_state->head_info_blocks[i].first_nego_lane_num;
> + output->head_info_list[i].link_state_flags =
> + s->mhd_state->head_info_blocks[i].link_state_flags;
> + }
> +
> + *len_out = sizeof(*output) + output->nr_heads * sizeof(MHDHeadInfoBlock);
> + return CXL_MBOX_SUCCESS;
> +}
> +
> static const struct cxl_cmd cxl_cmd_set_mhsld[256][256] = {
> [MHSLD_MHD][GET_MHD_INFO] = {"GET_MULTI_HEADED_INFO",
> cmd_mhd_get_info, 2, 0},
> + [MHSLD_MHD][GET_MHD_HEAD_INFO] = {"GET_HEAD_INFO",
> + cmd_mhd_get_head_info, 2, 0},
> };
>
> static const Property cxl_mhsld_props[] = {
> @@ -166,6 +214,47 @@ static void cxl_mhsld_state_initialize(CXLMHSLDState *s, size_t dc_size)
> s->mhd_state->nr_blocks = dc_size / MHSLD_BLOCK_SZ;
> }
>
> +
> +static void cxl_mhsld_init_head_info(CXLMHSLDState *s, PCIDevice *pdev)
> +{
> + uint16_t lnksta = 0;
> + uint16_t current_link_speed = 0;
> + uint16_t negotiated_link_width = 0;
> + uint16_t lnkcap = 0, lnkcap2 = 0;
> + uint16_t max_link_width = 0;
> + uint16_t max_link_speed = 0;
> + uint16_t supported_link_speeds_vector = 0;
> +
> + lnksta = pdev->config_read(pdev,
> + pdev->exp.exp_cap + PCI_EXP_LNKSTA,
> + sizeof(lnksta));
> + lnkcap = pdev->config_read(pdev,
> + pdev->exp.exp_cap + PCI_EXP_LNKCAP,
> + sizeof(lnkcap));
> + lnkcap2 = pdev->config_read(pdev,
> + pdev->exp.exp_cap + PCI_EXP_LNKCAP2,
> + sizeof(lnkcap2));
> + supported_link_speeds_vector = (lnkcap2 & 0xFE) >> 1;
> + max_link_width = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
> + max_link_speed = lnkcap & PCI_EXP_LNKCAP_SLS;
> + current_link_speed = lnksta & PCI_EXP_LNKSTA_CLS;
> + negotiated_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4;
> +
> + s->mhd_state->head_info_blocks[s->mhd_head].port_number = s->mhd_head;
> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_width = max_link_width;
> + s->mhd_state->head_info_blocks[s->mhd_head].nego_link_width =
> + negotiated_link_width;
> + s->mhd_state->head_info_blocks[s->mhd_head].supp_link_speeds_vector =
> + supported_link_speeds_vector;
> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_speed =
> + max_link_speed;
> + s->mhd_state->head_info_blocks[s->mhd_head].current_link_speed =
> + current_link_speed;
> + s->mhd_state->head_info_blocks[s->mhd_head].ltssm_state = 0x7;
> + s->mhd_state->head_info_blocks[s->mhd_head].first_nego_lane_num = 0;
> + s->mhd_state->head_info_blocks[s->mhd_head].link_state_flags = 0;
> +}
> +
> /* Returns starting index of region in MHD map. */
> static inline size_t cxl_mhsld_find_dc_region_start(PCIDevice *d,
> CXLDCRegion *r)
> @@ -376,7 +465,7 @@ static void cxl_mhsld_realize(PCIDevice *pci_dev, Error **errp)
> }
>
> cxl_mhsld_state_initialize(s, dc_size);
> -
> + cxl_mhsld_init_head_info(s, pci_dev);
> /* Set the LD ownership for this head to this system */
> s->mhd_state->ldmap[s->mhd_head] = s->mhd_head;
> return;
> @@ -428,6 +517,7 @@ static void cxl_mhsld_class_init(ObjectClass *klass, void *data)
>
> CXLType3Class *cvc = CXL_TYPE3_CLASS(klass);
> cvc->mhd_get_info = cmd_mhd_get_info;
> + cvc->mhd_get_head_info = cmd_mhd_get_head_info;
> cvc->mhd_access_valid = cxl_mhsld_access_valid;
> cvc->mhd_reserve_extents = cxl_mhsld_reserve_extents;
> cvc->mhd_reclaim_extents = cxl_mhsld_reclaim_extents;
> diff --git a/hw/cxl/mhsld/mhsld.h b/hw/cxl/mhsld/mhsld.h
> index e7ead1f0d2..c9fbec71ca 100644
> --- a/hw/cxl/mhsld/mhsld.h
> +++ b/hw/cxl/mhsld/mhsld.h
> @@ -23,6 +23,18 @@
> */
> #define MHSLD_HEADS (8)
>
> +typedef struct MHDHeadInfoBlock {
> + uint8_t port_number;
> + uint8_t max_link_width;
> + uint8_t nego_link_width;
> + uint8_t supp_link_speeds_vector;
> + uint8_t max_link_speed;
> + uint8_t current_link_speed;
> + uint8_t ltssm_state;
> + uint8_t first_nego_lane_num;
> + uint8_t link_state_flags;
> +} QEMU_PACKED MHDHeadInfoBlock;
> +
> /*
> * The shared state cannot have 2 variable sized regions
> * so we have to max out the ldmap.
> @@ -32,6 +44,7 @@ typedef struct MHSLDSharedState {
> uint8_t nr_lds;
> uint8_t ldmap[MHSLD_HEADS];
> uint64_t nr_blocks;
> + MHDHeadInfoBlock head_info_blocks[MHSLD_HEADS];
> uint8_t blocks[];
> } MHSLDSharedState;
>
> @@ -52,6 +65,7 @@ struct CXLMHSLDClass {
> enum {
> MHSLD_MHD = 0x55,
> #define GET_MHD_INFO 0x0
> + #define GET_MHD_HEAD_INFO 0x1
> };
>
> /*
> @@ -72,4 +86,16 @@ typedef struct MHDGetInfoOutput {
> uint16_t resv2;
> uint8_t ldmap[];
> } QEMU_PACKED MHDGetInfoOutput;
> +
> +typedef struct MHDGetHeadInfoInput {
> + uint8_t start_head;
> + uint8_t nr_heads;
> +} QEMU_PACKED MHDGetHeadInfoInput;
> +
> +typedef struct MHDGetHeadInfoOutput {
> + uint8_t nr_heads;
> + uint8_t rsvd[3];
> + MHDHeadInfoBlock head_info_list[];
s/head_info_list/head_info/
Fan
> +} QEMU_PACKED MHDGetHeadInfoOutput;
> +
> #endif
> diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
> index ca515cab13..c93c71c45d 100644
> --- a/include/hw/cxl/cxl_device.h
> +++ b/include/hw/cxl/cxl_device.h
> @@ -732,6 +732,12 @@ struct CXLType3Class {
> uint8_t *payload_out,
> size_t *len_out,
> CXLCCI *cci);
> + CXLRetCode (*mhd_get_head_info)(const struct cxl_cmd *cmd,
> + uint8_t *payload_in,
> + size_t len_in,
> + uint8_t *payload_out,
> + size_t *len_out,
> + CXLCCI *cci);
> bool (*mhd_access_valid)(PCIDevice *d, uint64_t addr, unsigned int size);
> bool (*mhd_reserve_extents)(PCIDevice *d,
> CxlDynamicCapacityExtentList *records,
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h)
2025-05-22 6:31 ` [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h) Vinayak Holikatti
2025-05-22 16:48 ` Fan Ni
@ 2025-05-22 19:15 ` Davidlohr Bueso
2025-07-01 13:05 ` Alok Rathore
2025-05-22 23:12 ` Anisa Su
2025-05-29 12:13 ` Jonathan Cameron
3 siblings, 1 reply; 9+ messages in thread
From: Davidlohr Bueso @ 2025-05-22 19:15 UTC (permalink / raw)
To: Vinayak Holikatti, Jonathan.Cameron
Cc: qemu-devel, gost.dev, linux-cxl, nifan.cxl, vishak.g, krish.reddy,
a.manzanares, alok.rathore
On Thu, 22 May 2025, Vinayak Holikatti wrote:
>CXL spec 3.2 section 7.6.7.5.2 describes Get Head Info.
So how was this tested? Ideally this now comes with a libcxlmi (or equivalent)
test case. See for example how Anisa is going about this with the FMAPI DCD
patches:
https://lore.kernel.org/linux-cxl/20250508001754.122180-1-anisa.su887@gmail.com/
>Signed-off-by: Vinayak Holikatti <vinayak.kh@samsung.com>
>---
>This patch is generated against Jonathan Cameron's branch cxl-2025-03-20
Adding him to the thread :)
>
> hw/cxl/cxl-mailbox-utils.c | 21 +++++++++
> hw/cxl/mhsld/mhsld.c | 92 ++++++++++++++++++++++++++++++++++++-
> hw/cxl/mhsld/mhsld.h | 26 +++++++++++
> include/hw/cxl/cxl_device.h | 6 +++
> 4 files changed, 144 insertions(+), 1 deletion(-)
>
>diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
>index a02d130926..4f25caecea 100644
>--- a/hw/cxl/cxl-mailbox-utils.c
>+++ b/hw/cxl/cxl-mailbox-utils.c
>@@ -122,6 +122,7 @@ enum {
> #define MANAGEMENT_COMMAND 0x0
> MHD = 0x55,
> #define GET_MHD_INFO 0x0
>+ #define GET_MHD_HEAD_INFO 0x1
> };
>
> /* CCI Message Format CXL r3.1 Figure 7-19 */
>@@ -267,6 +268,23 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
> return CXL_MBOX_UNSUPPORTED;
> }
>
>+/*
>+ * CXL r3.2 section 7.6.7.5.2 - Get Multi-Headed Head Info (Opcode 5501h)
>+ */
>+static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
>+ uint8_t *payload_in, size_t len_in,
>+ uint8_t *payload_out, size_t *len_out,
>+ CXLCCI *cci)
>+{
>+ CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
>+ CXLType3Class *cvc = CXL_TYPE3_GET_CLASS(ct3d);
>+ if (cvc->mhd_get_head_info) {
>+ return cvc->mhd_get_head_info(cmd, payload_in, len_in, payload_out,
>+ len_out, cci);
>+ }
>+ return CXL_MBOX_UNSUPPORTED;
>+}
>+
> static CXLRetCode cmd_events_get_records(const struct cxl_cmd *cmd,
> uint8_t *payload_in, size_t len_in,
> uint8_t *payload_out, size_t *len_out,
>@@ -3429,6 +3447,7 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
> "MEDIA_AND_POISON_GET_SCAN_MEDIA_RESULTS",
> cmd_media_get_scan_media_results, 0, 0 },
> [MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
>+ [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
> };
>
> static const struct cxl_cmd cxl_cmd_set_dcd[256][256] = {
>@@ -3761,6 +3780,8 @@ static const struct cxl_cmd cxl_cmd_set_t3_fm_owned_ld_mctp[256][256] = {
> [TIMESTAMP][GET] = { "TIMESTAMP_GET", cmd_timestamp_get, 0, 0 },
> [TUNNEL][MANAGEMENT_COMMAND] = { "TUNNEL_MANAGEMENT_COMMAND",
> cmd_tunnel_management_cmd, ~0, 0 },
>+ [MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
>+ [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
> };
>
> void cxl_initialize_t3_fm_owned_ld_mctpcci(CXLCCI *cci, DeviceState *d,
>diff --git a/hw/cxl/mhsld/mhsld.c b/hw/cxl/mhsld/mhsld.c
>index 9f633b3bed..981546b5ff 100644
>--- a/hw/cxl/mhsld/mhsld.c
>+++ b/hw/cxl/mhsld/mhsld.c
>@@ -61,9 +61,57 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
> return CXL_MBOX_SUCCESS;
> }
>
>+/*
>+ * CXL r3.2 section 7.6.7.5.2 - Get Head Info (Opcode 5501h)
>+ *
>+ * This command retrieves the number of heads, number of supported LDs,
>+ * and Head-to-LD mapping of a Multi-Headed device.
>+ */
>+static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
>+ uint8_t *payload_in, size_t len_in,
>+ uint8_t *payload_out, size_t *len_out,
>+ CXLCCI *cci)
>+{
>+ CXLMHSLDState *s = CXL_MHSLD(cci->d);
>+ MHDGetHeadInfoInput *input = (void *)payload_in;
>+ MHDGetHeadInfoOutput *output = (void *)payload_out;
>+ int i = 0;
>+
>+ if (input->start_head > MHSLD_HEADS) {
>+ return CXL_MBOX_INVALID_INPUT;
>+ }
>+
>+ output->nr_heads = MIN((MHSLD_HEADS - input->start_head), input->nr_heads);
>+ for (i = input->start_head; i < input->start_head + output->nr_heads; i++) {
>+ output->head_info_list[i].port_number =
>+ s->mhd_state->head_info_blocks[i].port_number;
>+ output->head_info_list[i].max_link_width =
>+ s->mhd_state->head_info_blocks[i].max_link_width;
>+ output->head_info_list[i].nego_link_width =
>+ s->mhd_state->head_info_blocks[i].nego_link_width;
>+ output->head_info_list[i].supp_link_speeds_vector =
>+ s->mhd_state->head_info_blocks[i].supp_link_speeds_vector;
>+ output->head_info_list[i].max_link_speed =
>+ s->mhd_state->head_info_blocks[i].max_link_speed;
>+ output->head_info_list[i].current_link_speed =
>+ s->mhd_state->head_info_blocks[i].current_link_speed;
>+ output->head_info_list[i].ltssm_state =
>+ s->mhd_state->head_info_blocks[i].ltssm_state;
>+ output->head_info_list[i].first_nego_lane_num =
>+ s->mhd_state->head_info_blocks[i].first_nego_lane_num;
>+ output->head_info_list[i].link_state_flags =
>+ s->mhd_state->head_info_blocks[i].link_state_flags;
>+ }
>+
>+ *len_out = sizeof(*output) + output->nr_heads * sizeof(MHDHeadInfoBlock);
>+ return CXL_MBOX_SUCCESS;
>+}
>+
> static const struct cxl_cmd cxl_cmd_set_mhsld[256][256] = {
> [MHSLD_MHD][GET_MHD_INFO] = {"GET_MULTI_HEADED_INFO",
> cmd_mhd_get_info, 2, 0},
>+ [MHSLD_MHD][GET_MHD_HEAD_INFO] = {"GET_HEAD_INFO",
>+ cmd_mhd_get_head_info, 2, 0},
> };
>
> static const Property cxl_mhsld_props[] = {
>@@ -166,6 +214,47 @@ static void cxl_mhsld_state_initialize(CXLMHSLDState *s, size_t dc_size)
> s->mhd_state->nr_blocks = dc_size / MHSLD_BLOCK_SZ;
> }
>
>+
>+static void cxl_mhsld_init_head_info(CXLMHSLDState *s, PCIDevice *pdev)
>+{
>+ uint16_t lnksta = 0;
>+ uint16_t current_link_speed = 0;
>+ uint16_t negotiated_link_width = 0;
>+ uint16_t lnkcap = 0, lnkcap2 = 0;
>+ uint16_t max_link_width = 0;
>+ uint16_t max_link_speed = 0;
>+ uint16_t supported_link_speeds_vector = 0;
>+
>+ lnksta = pdev->config_read(pdev,
>+ pdev->exp.exp_cap + PCI_EXP_LNKSTA,
>+ sizeof(lnksta));
>+ lnkcap = pdev->config_read(pdev,
>+ pdev->exp.exp_cap + PCI_EXP_LNKCAP,
>+ sizeof(lnkcap));
>+ lnkcap2 = pdev->config_read(pdev,
>+ pdev->exp.exp_cap + PCI_EXP_LNKCAP2,
>+ sizeof(lnkcap2));
>+ supported_link_speeds_vector = (lnkcap2 & 0xFE) >> 1;
>+ max_link_width = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
>+ max_link_speed = lnkcap & PCI_EXP_LNKCAP_SLS;
>+ current_link_speed = lnksta & PCI_EXP_LNKSTA_CLS;
>+ negotiated_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4;
>+
>+ s->mhd_state->head_info_blocks[s->mhd_head].port_number = s->mhd_head;
>+ s->mhd_state->head_info_blocks[s->mhd_head].max_link_width = max_link_width;
>+ s->mhd_state->head_info_blocks[s->mhd_head].nego_link_width =
>+ negotiated_link_width;
>+ s->mhd_state->head_info_blocks[s->mhd_head].supp_link_speeds_vector =
>+ supported_link_speeds_vector;
>+ s->mhd_state->head_info_blocks[s->mhd_head].max_link_speed =
>+ max_link_speed;
>+ s->mhd_state->head_info_blocks[s->mhd_head].current_link_speed =
>+ current_link_speed;
>+ s->mhd_state->head_info_blocks[s->mhd_head].ltssm_state = 0x7;
>+ s->mhd_state->head_info_blocks[s->mhd_head].first_nego_lane_num = 0;
>+ s->mhd_state->head_info_blocks[s->mhd_head].link_state_flags = 0;
>+}
>+
> /* Returns starting index of region in MHD map. */
> static inline size_t cxl_mhsld_find_dc_region_start(PCIDevice *d,
> CXLDCRegion *r)
>@@ -376,7 +465,7 @@ static void cxl_mhsld_realize(PCIDevice *pci_dev, Error **errp)
> }
>
> cxl_mhsld_state_initialize(s, dc_size);
>-
>+ cxl_mhsld_init_head_info(s, pci_dev);
> /* Set the LD ownership for this head to this system */
> s->mhd_state->ldmap[s->mhd_head] = s->mhd_head;
> return;
>@@ -428,6 +517,7 @@ static void cxl_mhsld_class_init(ObjectClass *klass, void *data)
>
> CXLType3Class *cvc = CXL_TYPE3_CLASS(klass);
> cvc->mhd_get_info = cmd_mhd_get_info;
>+ cvc->mhd_get_head_info = cmd_mhd_get_head_info;
> cvc->mhd_access_valid = cxl_mhsld_access_valid;
> cvc->mhd_reserve_extents = cxl_mhsld_reserve_extents;
> cvc->mhd_reclaim_extents = cxl_mhsld_reclaim_extents;
>diff --git a/hw/cxl/mhsld/mhsld.h b/hw/cxl/mhsld/mhsld.h
>index e7ead1f0d2..c9fbec71ca 100644
>--- a/hw/cxl/mhsld/mhsld.h
>+++ b/hw/cxl/mhsld/mhsld.h
>@@ -23,6 +23,18 @@
> */
> #define MHSLD_HEADS (8)
>
>+typedef struct MHDHeadInfoBlock {
>+ uint8_t port_number;
>+ uint8_t max_link_width;
>+ uint8_t nego_link_width;
>+ uint8_t supp_link_speeds_vector;
>+ uint8_t max_link_speed;
>+ uint8_t current_link_speed;
>+ uint8_t ltssm_state;
>+ uint8_t first_nego_lane_num;
>+ uint8_t link_state_flags;
>+} QEMU_PACKED MHDHeadInfoBlock;
>+
> /*
> * The shared state cannot have 2 variable sized regions
> * so we have to max out the ldmap.
>@@ -32,6 +44,7 @@ typedef struct MHSLDSharedState {
> uint8_t nr_lds;
> uint8_t ldmap[MHSLD_HEADS];
> uint64_t nr_blocks;
>+ MHDHeadInfoBlock head_info_blocks[MHSLD_HEADS];
> uint8_t blocks[];
> } MHSLDSharedState;
>
>@@ -52,6 +65,7 @@ struct CXLMHSLDClass {
> enum {
> MHSLD_MHD = 0x55,
> #define GET_MHD_INFO 0x0
>+ #define GET_MHD_HEAD_INFO 0x1
> };
>
> /*
>@@ -72,4 +86,16 @@ typedef struct MHDGetInfoOutput {
> uint16_t resv2;
> uint8_t ldmap[];
> } QEMU_PACKED MHDGetInfoOutput;
>+
>+typedef struct MHDGetHeadInfoInput {
>+ uint8_t start_head;
>+ uint8_t nr_heads;
>+} QEMU_PACKED MHDGetHeadInfoInput;
>+
>+typedef struct MHDGetHeadInfoOutput {
>+ uint8_t nr_heads;
>+ uint8_t rsvd[3];
>+ MHDHeadInfoBlock head_info_list[];
>+} QEMU_PACKED MHDGetHeadInfoOutput;
>+
> #endif
>diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
>index ca515cab13..c93c71c45d 100644
>--- a/include/hw/cxl/cxl_device.h
>+++ b/include/hw/cxl/cxl_device.h
>@@ -732,6 +732,12 @@ struct CXLType3Class {
> uint8_t *payload_out,
> size_t *len_out,
> CXLCCI *cci);
>+ CXLRetCode (*mhd_get_head_info)(const struct cxl_cmd *cmd,
>+ uint8_t *payload_in,
>+ size_t len_in,
>+ uint8_t *payload_out,
>+ size_t *len_out,
>+ CXLCCI *cci);
> bool (*mhd_access_valid)(PCIDevice *d, uint64_t addr, unsigned int size);
> bool (*mhd_reserve_extents)(PCIDevice *d,
> CxlDynamicCapacityExtentList *records,
>--
>2.34.1
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h)
2025-05-22 6:31 ` [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h) Vinayak Holikatti
2025-05-22 16:48 ` Fan Ni
2025-05-22 19:15 ` Davidlohr Bueso
@ 2025-05-22 23:12 ` Anisa Su
[not found] ` <CGME20250701131120epcas5p35fa8d12f058a82bc637c13d176dd0477@epcas5p3.samsung.com>
2025-05-29 12:13 ` Jonathan Cameron
3 siblings, 1 reply; 9+ messages in thread
From: Anisa Su @ 2025-05-22 23:12 UTC (permalink / raw)
To: Vinayak Holikatti
Cc: nifan.cxl, a.manzanares, alok.rathore, dave, gost.dev,
krish.reddy, linux-cxl, qemu-devel, vishak.g
On Thu, May 22, 2025 at 12:01:35PM +0530, Vinayak Holikatti wrote:
> CXL spec 3.2 section 7.6.7.5.2 describes Get Head Info.
>
> Signed-off-by: Vinayak Holikatti <vinayak.kh@samsung.com>
> ---
> This patch is generated against Jonathan Cameron's branch cxl-2025-03-20
>
> hw/cxl/cxl-mailbox-utils.c | 21 +++++++++
> hw/cxl/mhsld/mhsld.c | 92 ++++++++++++++++++++++++++++++++++++-
> hw/cxl/mhsld/mhsld.h | 26 +++++++++++
> include/hw/cxl/cxl_device.h | 6 +++
> 4 files changed, 144 insertions(+), 1 deletion(-)
>
> diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
> index a02d130926..4f25caecea 100644
> --- a/hw/cxl/cxl-mailbox-utils.c
> +++ b/hw/cxl/cxl-mailbox-utils.c
> @@ -122,6 +122,7 @@ enum {
> #define MANAGEMENT_COMMAND 0x0
> MHD = 0x55,
> #define GET_MHD_INFO 0x0
> + #define GET_MHD_HEAD_INFO 0x1
> };
>
> /* CCI Message Format CXL r3.1 Figure 7-19 */
> @@ -267,6 +268,23 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
> return CXL_MBOX_UNSUPPORTED;
> }
>
> +/*
> + * CXL r3.2 section 7.6.7.5.2 - Get Multi-Headed Head Info (Opcode 5501h)
> + */
> +static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
> + uint8_t *payload_in, size_t len_in,
> + uint8_t *payload_out, size_t *len_out,
> + CXLCCI *cci)
> +{
> + CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
> + CXLType3Class *cvc = CXL_TYPE3_GET_CLASS(ct3d);
> + if (cvc->mhd_get_head_info) {
> + return cvc->mhd_get_head_info(cmd, payload_in, len_in, payload_out,
> + len_out, cci);
> + }
> + return CXL_MBOX_UNSUPPORTED;
> +}
> +
> static CXLRetCode cmd_events_get_records(const struct cxl_cmd *cmd,
> uint8_t *payload_in, size_t len_in,
> uint8_t *payload_out, size_t *len_out,
> @@ -3429,6 +3447,7 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
> "MEDIA_AND_POISON_GET_SCAN_MEDIA_RESULTS",
> cmd_media_get_scan_media_results, 0, 0 },
> [MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
> + [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
The name here "GET_MULTI_HEADED_INFO" is the same as the previous command.
> };
>
...
> +
> +static void cxl_mhsld_init_head_info(CXLMHSLDState *s, PCIDevice *pdev)
> +{
> + uint16_t lnksta = 0;
> + uint16_t current_link_speed = 0;
> + uint16_t negotiated_link_width = 0;
> + uint16_t lnkcap = 0, lnkcap2 = 0;
> + uint16_t max_link_width = 0;
> + uint16_t max_link_speed = 0;
> + uint16_t supported_link_speeds_vector = 0;
> +
> + lnksta = pdev->config_read(pdev,
> + pdev->exp.exp_cap + PCI_EXP_LNKSTA,
> + sizeof(lnksta));
> + lnkcap = pdev->config_read(pdev,
> + pdev->exp.exp_cap + PCI_EXP_LNKCAP,
> + sizeof(lnkcap));
> + lnkcap2 = pdev->config_read(pdev,
> + pdev->exp.exp_cap + PCI_EXP_LNKCAP2,
> + sizeof(lnkcap2));
> + supported_link_speeds_vector = (lnkcap2 & 0xFE) >> 1;
> + max_link_width = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
> + max_link_speed = lnkcap & PCI_EXP_LNKCAP_SLS;
> + current_link_speed = lnksta & PCI_EXP_LNKSTA_CLS;
> + negotiated_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4;
> +
> + s->mhd_state->head_info_blocks[s->mhd_head].port_number = s->mhd_head;
> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_width = max_link_width;
> + s->mhd_state->head_info_blocks[s->mhd_head].nego_link_width =
> + negotiated_link_width;
> + s->mhd_state->head_info_blocks[s->mhd_head].supp_link_speeds_vector =
> + supported_link_speeds_vector;
> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_speed =
> + max_link_speed;
> + s->mhd_state->head_info_blocks[s->mhd_head].current_link_speed =
> + current_link_speed;
> + s->mhd_state->head_info_blocks[s->mhd_head].ltssm_state = 0x7;
I think it would be helpful to make a define for the ltssm states?
> + s->mhd_state->head_info_blocks[s->mhd_head].first_nego_lane_num = 0;
> + s->mhd_state->head_info_blocks[s->mhd_head].link_state_flags = 0;
> +}
> +
> /* Returns starting index of region in MHD map. */
> static inline size_t cxl_mhsld_find_dc_region_start(PCIDevice *d,
> CXLDCRegion *r)
> @@ -376,7 +465,7 @@ static void cxl_mhsld_realize(PCIDevice *pci_dev, Error **errp)
> }
>
> cxl_mhsld_state_initialize(s, dc_size);
> -
> + cxl_mhsld_init_head_info(s, pci_dev);
> /* Set the LD ownership for this head to this system */
> s->mhd_state->ldmap[s->mhd_head] = s->mhd_head;
> return;
> @@ -428,6 +517,7 @@ static void cxl_mhsld_class_init(ObjectClass *klass, void *data)
>
> CXLType3Class *cvc = CXL_TYPE3_CLASS(klass);
> cvc->mhd_get_info = cmd_mhd_get_info;
> + cvc->mhd_get_head_info = cmd_mhd_get_head_info;
> cvc->mhd_access_valid = cxl_mhsld_access_valid;
> cvc->mhd_reserve_extents = cxl_mhsld_reserve_extents;
> cvc->mhd_reclaim_extents = cxl_mhsld_reclaim_extents;
> diff --git a/hw/cxl/mhsld/mhsld.h b/hw/cxl/mhsld/mhsld.h
> index e7ead1f0d2..c9fbec71ca 100644
> --- a/hw/cxl/mhsld/mhsld.h
> +++ b/hw/cxl/mhsld/mhsld.h
> @@ -23,6 +23,18 @@
> */
> #define MHSLD_HEADS (8)
>
> +typedef struct MHDHeadInfoBlock {
> + uint8_t port_number;
> + uint8_t max_link_width;
> + uint8_t nego_link_width;
> + uint8_t supp_link_speeds_vector;
> + uint8_t max_link_speed;
> + uint8_t current_link_speed;
> + uint8_t ltssm_state;
> + uint8_t first_nego_lane_num;
> + uint8_t link_state_flags;
> +} QEMU_PACKED MHDHeadInfoBlock;
> +
> /*
> * The shared state cannot have 2 variable sized regions
> * so we have to max out the ldmap.
> @@ -32,6 +44,7 @@ typedef struct MHSLDSharedState {
> uint8_t nr_lds;
> uint8_t ldmap[MHSLD_HEADS];
> uint64_t nr_blocks;
> + MHDHeadInfoBlock head_info_blocks[MHSLD_HEADS];
> uint8_t blocks[];
> } MHSLDSharedState;
>
> @@ -52,6 +65,7 @@ struct CXLMHSLDClass {
> enum {
> MHSLD_MHD = 0x55,
> #define GET_MHD_INFO 0x0
> + #define GET_MHD_HEAD_INFO 0x1
> };
>
> /*
> @@ -72,4 +86,16 @@ typedef struct MHDGetInfoOutput {
> uint16_t resv2;
> uint8_t ldmap[];
> } QEMU_PACKED MHDGetInfoOutput;
> +
> +typedef struct MHDGetHeadInfoInput {
> + uint8_t start_head;
> + uint8_t nr_heads;
> +} QEMU_PACKED MHDGetHeadInfoInput;
> +
> +typedef struct MHDGetHeadInfoOutput {
> + uint8_t nr_heads;
> + uint8_t rsvd[3];
> + MHDHeadInfoBlock head_info_list[];
> +} QEMU_PACKED MHDGetHeadInfoOutput;
> +
> #endif
> diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
> index ca515cab13..c93c71c45d 100644
> --- a/include/hw/cxl/cxl_device.h
> +++ b/include/hw/cxl/cxl_device.h
> @@ -732,6 +732,12 @@ struct CXLType3Class {
> uint8_t *payload_out,
> size_t *len_out,
> CXLCCI *cci);
> + CXLRetCode (*mhd_get_head_info)(const struct cxl_cmd *cmd,
> + uint8_t *payload_in,
> + size_t len_in,
> + uint8_t *payload_out,
> + size_t *len_out,
> + CXLCCI *cci);
I think the indent here needs to be aligned with the open parentheses on
the first line of the function declaration
> bool (*mhd_access_valid)(PCIDevice *d, uint64_t addr, unsigned int size);
> bool (*mhd_reserve_extents)(PCIDevice *d,
> CxlDynamicCapacityExtentList *records,
> --
> 2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h)
2025-05-22 6:31 ` [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h) Vinayak Holikatti
` (2 preceding siblings ...)
2025-05-22 23:12 ` Anisa Su
@ 2025-05-29 12:13 ` Jonathan Cameron
2025-07-01 13:19 ` Alok Rathore
3 siblings, 1 reply; 9+ messages in thread
From: Jonathan Cameron @ 2025-05-29 12:13 UTC (permalink / raw)
To: Vinayak Holikatti
Cc: qemu-devel, gost.dev, linux-cxl, nifan.cxl, dave, vishak.g,
krish.reddy, a.manzanares, alok.rathore
On Thu, 22 May 2025 12:01:35 +0530
Vinayak Holikatti <vinayak.kh@samsung.com> wrote:
> CXL spec 3.2 section 7.6.7.5.2 describes Get Head Info.
>
> Signed-off-by: Vinayak Holikatti <vinayak.kh@samsung.com>
Hi Vinayak,
Some code simplification suggestions below.
> ---
> This patch is generated against Jonathan Cameron's branch cxl-2025-03-20
>
> hw/cxl/cxl-mailbox-utils.c | 21 +++++++++
> hw/cxl/mhsld/mhsld.c | 92 ++++++++++++++++++++++++++++++++++++-
> hw/cxl/mhsld/mhsld.h | 26 +++++++++++
> include/hw/cxl/cxl_device.h | 6 +++
> 4 files changed, 144 insertions(+), 1 deletion(-)
>
> diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
> index a02d130926..4f25caecea 100644
> --- a/hw/cxl/cxl-mailbox-utils.c
> +++ b/hw/cxl/cxl-mailbox-utils.c
> diff --git a/hw/cxl/mhsld/mhsld.c b/hw/cxl/mhsld/mhsld.c
> index 9f633b3bed..981546b5ff 100644
> --- a/hw/cxl/mhsld/mhsld.c
> +++ b/hw/cxl/mhsld/mhsld.c
> @@ -61,9 +61,57 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
> return CXL_MBOX_SUCCESS;
> }
>
> +/*
> + * CXL r3.2 section 7.6.7.5.2 - Get Head Info (Opcode 5501h)
> + *
> + * This command retrieves the number of heads, number of supported LDs,
> + * and Head-to-LD mapping of a Multi-Headed device.
> + */
> +static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
> + uint8_t *payload_in, size_t len_in,
> + uint8_t *payload_out, size_t *len_out,
> + CXLCCI *cci)
> +{
> + CXLMHSLDState *s = CXL_MHSLD(cci->d);
> + MHDGetHeadInfoInput *input = (void *)payload_in;
> + MHDGetHeadInfoOutput *output = (void *)payload_out;
> + int i = 0;
> +
> + if (input->start_head > MHSLD_HEADS) {
> + return CXL_MBOX_INVALID_INPUT;
> + }
> +
> + output->nr_heads = MIN((MHSLD_HEADS - input->start_head), input->nr_heads);
> + for (i = input->start_head; i < input->start_head + output->nr_heads; i++) {
Can we get away with a memcpy()? Any endian issues on any of these?
> + output->head_info_list[i].port_number =
> + s->mhd_state->head_info_blocks[i].port_number;
> + output->head_info_list[i].max_link_width =
> + s->mhd_state->head_info_blocks[i].max_link_width;
> + output->head_info_list[i].nego_link_width =
> + s->mhd_state->head_info_blocks[i].nego_link_width;
> + output->head_info_list[i].supp_link_speeds_vector =
> + s->mhd_state->head_info_blocks[i].supp_link_speeds_vector;
> + output->head_info_list[i].max_link_speed =
> + s->mhd_state->head_info_blocks[i].max_link_speed;
> + output->head_info_list[i].current_link_speed =
> + s->mhd_state->head_info_blocks[i].current_link_speed;
> + output->head_info_list[i].ltssm_state =
> + s->mhd_state->head_info_blocks[i].ltssm_state;
> + output->head_info_list[i].first_nego_lane_num =
> + s->mhd_state->head_info_blocks[i].first_nego_lane_num;
> + output->head_info_list[i].link_state_flags =
> + s->mhd_state->head_info_blocks[i].link_state_flags;
> + }
> +
> + *len_out = sizeof(*output) + output->nr_heads * sizeof(MHDHeadInfoBlock);
> + return CXL_MBOX_SUCCESS;
> +}
> static const Property cxl_mhsld_props[] = {
> @@ -166,6 +214,47 @@ static void cxl_mhsld_state_initialize(CXLMHSLDState *s, size_t dc_size)
> s->mhd_state->nr_blocks = dc_size / MHSLD_BLOCK_SZ;
> }
>
> +
> +static void cxl_mhsld_init_head_info(CXLMHSLDState *s, PCIDevice *pdev)
> +{
> + uint16_t lnksta = 0;
No need to initialize when they are always set below.
> + uint16_t current_link_speed = 0;
> + uint16_t negotiated_link_width = 0;
> + uint16_t lnkcap = 0, lnkcap2 = 0;
> + uint16_t max_link_width = 0;
> + uint16_t max_link_speed = 0;
Once you drop the unnecessary init combine width and speed on one line.
Or as below, get rid of most of these local variables entirely.
> + uint16_t supported_link_speeds_vector = 0;
> +
> + lnksta = pdev->config_read(pdev,
> + pdev->exp.exp_cap + PCI_EXP_LNKSTA,
> + sizeof(lnksta));
> + lnkcap = pdev->config_read(pdev,
> + pdev->exp.exp_cap + PCI_EXP_LNKCAP,
> + sizeof(lnkcap));
> + lnkcap2 = pdev->config_read(pdev,
> + pdev->exp.exp_cap + PCI_EXP_LNKCAP2,
> + sizeof(lnkcap2));
> + supported_link_speeds_vector = (lnkcap2 & 0xFE) >> 1;
Worth considering adding defines for that to incluw/hw/pci/pcie_regs.h
> + max_link_width = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
Use PCI_EXP_LNK_MLW_SHIFT to extract that.
(we should also tidy this up in physical port state.
> + max_link_speed = lnkcap & PCI_EXP_LNKCAP_SLS;
> + current_link_speed = lnksta & PCI_EXP_LNKSTA_CLS;
> + negotiated_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4;
Similar - there should be a suitable define for that shift.
> +
> + s->mhd_state->head_info_blocks[s->mhd_head].port_number = s->mhd_head;
I would use something like
s->mhd_state->head_info_blocks[s->mhd_head] = (MHDHeadInfoBlock) {
.max_link_width = lnkcap & PCI_EXP_LNKCAP_SLS,
.nego_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4, //with the define
.supp_link_speeds_vector = (lnkcap2 & 0xFE) >> 1,
etc
};
> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_width = max_link_width;
> + s->mhd_state->head_info_blocks[s->mhd_head].nego_link_width =
> + negotiated_link_width;
> + s->mhd_state->head_info_blocks[s->mhd_head].supp_link_speeds_vector =
> + supported_link_speeds_vector;
> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_speed =
> + max_link_speed;
> + s->mhd_state->head_info_blocks[s->mhd_head].current_link_speed =
> + current_link_speed;
> + s->mhd_state->head_info_blocks[s->mhd_head].ltssm_state = 0x7;
> + s->mhd_state->head_info_blocks[s->mhd_head].first_nego_lane_num = 0;
> + s->mhd_state->head_info_blocks[s->mhd_head].link_state_flags = 0;
> +}
> +
> /* Returns starting index of region in MHD map. */
> static inline size_t cxl_mhsld_find_dc_region_start(PCIDevice *d,
> CXLDCRegion *r)
> @@ -376,7 +465,7 @@ static void cxl_mhsld_realize(PCIDevice *pci_dev, Error **errp)
> }
>
> cxl_mhsld_state_initialize(s, dc_size);
> -
> + cxl_mhsld_init_head_info(s, pci_dev);
Avoid the white space noise by leaving a blank line here.
> /* Set the LD ownership for this head to this system */
> s->mhd_state->ldmap[s->mhd_head] = s->mhd_head;
> return;
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h)
2025-05-22 16:48 ` Fan Ni
@ 2025-07-01 12:59 ` Alok Rathore
0 siblings, 0 replies; 9+ messages in thread
From: Alok Rathore @ 2025-07-01 12:59 UTC (permalink / raw)
To: Fan Ni
Cc: qemu-devel, gost.dev, linux-cxl, dave, vishak.g, krish.reddy,
a.manzanares
[-- Attachment #1: Type: text/plain, Size: 12787 bytes --]
On 22/05/25 09:48AM, Fan Ni wrote:
>On Thu, May 22, 2025 at 12:01:35PM +0530, Vinayak Holikatti wrote:
>> CXL spec 3.2 section 7.6.7.5.2 describes Get Head Info.
>>
>> Signed-off-by: Vinayak Holikatti <vinayak.kh@samsung.com>
>> ---
>> This patch is generated against Jonathan Cameron's branch cxl-2025-03-20
>>
>> hw/cxl/cxl-mailbox-utils.c | 21 +++++++++
>> hw/cxl/mhsld/mhsld.c | 92 ++++++++++++++++++++++++++++++++++++-
>> hw/cxl/mhsld/mhsld.h | 26 +++++++++++
>> include/hw/cxl/cxl_device.h | 6 +++
>> 4 files changed, 144 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
>> index a02d130926..4f25caecea 100644
>> --- a/hw/cxl/cxl-mailbox-utils.c
>> +++ b/hw/cxl/cxl-mailbox-utils.c
>> @@ -122,6 +122,7 @@ enum {
>> #define MANAGEMENT_COMMAND 0x0
>> MHD = 0x55,
>> #define GET_MHD_INFO 0x0
>> + #define GET_MHD_HEAD_INFO 0x1
>> };
>>
>> /* CCI Message Format CXL r3.1 Figure 7-19 */
>> @@ -267,6 +268,23 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
>> return CXL_MBOX_UNSUPPORTED;
>> }
>>
>> +/*
>> + * CXL r3.2 section 7.6.7.5.2 - Get Multi-Headed Head Info (Opcode 5501h)
>That does not match the section subject of the spec
>Get Head Info (...
Thanks Fan Ni. Will fix in V1 patch.
>> + */
>> +static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
>> + uint8_t *payload_in, size_t len_in,
>> + uint8_t *payload_out, size_t *len_out,
>> + CXLCCI *cci)
>The indent here is not right.
Okay. Will fix in V1 patch.
>> +static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
>> + uint8_t *payload_in, size_t len_in,
>
>> +{
>> + CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
>> + CXLType3Class *cvc = CXL_TYPE3_GET_CLASS(ct3d);
>> + if (cvc->mhd_get_head_info) {
>> + return cvc->mhd_get_head_info(cmd, payload_in, len_in, payload_out,
>> + len_out, cci);
>
>indent needs fix.
Okay. Will fix in V1 patch.
>
>> + }
>> + return CXL_MBOX_UNSUPPORTED;
>> +}
>> +
>> static CXLRetCode cmd_events_get_records(const struct cxl_cmd *cmd,
>> uint8_t *payload_in, size_t len_in,
>> uint8_t *payload_out, size_t *len_out,
>> @@ -3429,6 +3447,7 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
>> "MEDIA_AND_POISON_GET_SCAN_MEDIA_RESULTS",
>> cmd_media_get_scan_media_results, 0, 0 },
>> [MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
>> + [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
>> };
>>
>> static const struct cxl_cmd cxl_cmd_set_dcd[256][256] = {
>> @@ -3761,6 +3780,8 @@ static const struct cxl_cmd cxl_cmd_set_t3_fm_owned_ld_mctp[256][256] = {
>> [TIMESTAMP][GET] = { "TIMESTAMP_GET", cmd_timestamp_get, 0, 0 },
>> [TUNNEL][MANAGEMENT_COMMAND] = { "TUNNEL_MANAGEMENT_COMMAND",
>> cmd_tunnel_management_cmd, ~0, 0 },
>> + [MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
>> + [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
>> };
>>
>> void cxl_initialize_t3_fm_owned_ld_mctpcci(CXLCCI *cci, DeviceState *d,
>> diff --git a/hw/cxl/mhsld/mhsld.c b/hw/cxl/mhsld/mhsld.c
>> index 9f633b3bed..981546b5ff 100644
>> --- a/hw/cxl/mhsld/mhsld.c
>> +++ b/hw/cxl/mhsld/mhsld.c
>> @@ -61,9 +61,57 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
>> return CXL_MBOX_SUCCESS;
>> }
>>
>> +/*
>> + * CXL r3.2 section 7.6.7.5.2 - Get Head Info (Opcode 5501h)
>> + *
>> + * This command retrieves the number of heads, number of supported LDs,
>> + * and Head-to-LD mapping of a Multi-Headed device.
>> + */
>> +static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
>> + uint8_t *payload_in, size_t len_in,
>> + uint8_t *payload_out, size_t *len_out,
>> + CXLCCI *cci)
>> +{
>> + CXLMHSLDState *s = CXL_MHSLD(cci->d);
>> + MHDGetHeadInfoInput *input = (void *)payload_in;
>> + MHDGetHeadInfoOutput *output = (void *)payload_out;
>> + int i = 0;
>> +
>> + if (input->start_head > MHSLD_HEADS) {
>
>Should be ">=" ?
Right. Head index starts from 0, so this condition should be there.
>
>Also, per the spec, we need also check the "number of heads" field, if
>start_head and number of heads together point to a non-exist head, we
>should return invalid input.
Yes. Will add this check in V1 patch.
>
>> + return CXL_MBOX_INVALID_INPUT;
>> + }
>> +
>> + output->nr_heads = MIN((MHSLD_HEADS - input->start_head), input->nr_heads);
>> + for (i = input->start_head; i < input->start_head + output->nr_heads; i++) {
>> + output->head_info_list[i].port_number =
>> + s->mhd_state->head_info_blocks[i].port_number;
>> + output->head_info_list[i].max_link_width =
>> + s->mhd_state->head_info_blocks[i].max_link_width;
>> + output->head_info_list[i].nego_link_width =
>> + s->mhd_state->head_info_blocks[i].nego_link_width;
>> + output->head_info_list[i].supp_link_speeds_vector =
>> + s->mhd_state->head_info_blocks[i].supp_link_speeds_vector;
>> + output->head_info_list[i].max_link_speed =
>> + s->mhd_state->head_info_blocks[i].max_link_speed;
>> + output->head_info_list[i].current_link_speed =
>> + s->mhd_state->head_info_blocks[i].current_link_speed;
>> + output->head_info_list[i].ltssm_state =
>> + s->mhd_state->head_info_blocks[i].ltssm_state;
>> + output->head_info_list[i].first_nego_lane_num =
>> + s->mhd_state->head_info_blocks[i].first_nego_lane_num;
>> + output->head_info_list[i].link_state_flags =
>> + s->mhd_state->head_info_blocks[i].link_state_flags;
>> + }
>> +
>> + *len_out = sizeof(*output) + output->nr_heads * sizeof(MHDHeadInfoBlock);
>> + return CXL_MBOX_SUCCESS;
>> +}
>> +
>> static const struct cxl_cmd cxl_cmd_set_mhsld[256][256] = {
>> [MHSLD_MHD][GET_MHD_INFO] = {"GET_MULTI_HEADED_INFO",
>> cmd_mhd_get_info, 2, 0},
>> + [MHSLD_MHD][GET_MHD_HEAD_INFO] = {"GET_HEAD_INFO",
>> + cmd_mhd_get_head_info, 2, 0},
>> };
>>
>> static const Property cxl_mhsld_props[] = {
>> @@ -166,6 +214,47 @@ static void cxl_mhsld_state_initialize(CXLMHSLDState *s, size_t dc_size)
>> s->mhd_state->nr_blocks = dc_size / MHSLD_BLOCK_SZ;
>> }
>>
>> +
>> +static void cxl_mhsld_init_head_info(CXLMHSLDState *s, PCIDevice *pdev)
>> +{
>> + uint16_t lnksta = 0;
>> + uint16_t current_link_speed = 0;
>> + uint16_t negotiated_link_width = 0;
>> + uint16_t lnkcap = 0, lnkcap2 = 0;
>> + uint16_t max_link_width = 0;
>> + uint16_t max_link_speed = 0;
>> + uint16_t supported_link_speeds_vector = 0;
>> +
>> + lnksta = pdev->config_read(pdev,
>> + pdev->exp.exp_cap + PCI_EXP_LNKSTA,
>> + sizeof(lnksta));
>> + lnkcap = pdev->config_read(pdev,
>> + pdev->exp.exp_cap + PCI_EXP_LNKCAP,
>> + sizeof(lnkcap));
>> + lnkcap2 = pdev->config_read(pdev,
>> + pdev->exp.exp_cap + PCI_EXP_LNKCAP2,
>> + sizeof(lnkcap2));
>> + supported_link_speeds_vector = (lnkcap2 & 0xFE) >> 1;
>> + max_link_width = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
>> + max_link_speed = lnkcap & PCI_EXP_LNKCAP_SLS;
>> + current_link_speed = lnksta & PCI_EXP_LNKSTA_CLS;
>> + negotiated_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4;
>> +
>> + s->mhd_state->head_info_blocks[s->mhd_head].port_number = s->mhd_head;
>> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_width = max_link_width;
>> + s->mhd_state->head_info_blocks[s->mhd_head].nego_link_width =
>> + negotiated_link_width;
>> + s->mhd_state->head_info_blocks[s->mhd_head].supp_link_speeds_vector =
>> + supported_link_speeds_vector;
>> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_speed =
>> + max_link_speed;
>> + s->mhd_state->head_info_blocks[s->mhd_head].current_link_speed =
>> + current_link_speed;
>> + s->mhd_state->head_info_blocks[s->mhd_head].ltssm_state = 0x7;
>> + s->mhd_state->head_info_blocks[s->mhd_head].first_nego_lane_num = 0;
>> + s->mhd_state->head_info_blocks[s->mhd_head].link_state_flags = 0;
>> +}
>> +
>> /* Returns starting index of region in MHD map. */
>> static inline size_t cxl_mhsld_find_dc_region_start(PCIDevice *d,
>> CXLDCRegion *r)
>> @@ -376,7 +465,7 @@ static void cxl_mhsld_realize(PCIDevice *pci_dev, Error **errp)
>> }
>>
>> cxl_mhsld_state_initialize(s, dc_size);
>> -
>> + cxl_mhsld_init_head_info(s, pci_dev);
>> /* Set the LD ownership for this head to this system */
>> s->mhd_state->ldmap[s->mhd_head] = s->mhd_head;
>> return;
>> @@ -428,6 +517,7 @@ static void cxl_mhsld_class_init(ObjectClass *klass, void *data)
>>
>> CXLType3Class *cvc = CXL_TYPE3_CLASS(klass);
>> cvc->mhd_get_info = cmd_mhd_get_info;
>> + cvc->mhd_get_head_info = cmd_mhd_get_head_info;
>> cvc->mhd_access_valid = cxl_mhsld_access_valid;
>> cvc->mhd_reserve_extents = cxl_mhsld_reserve_extents;
>> cvc->mhd_reclaim_extents = cxl_mhsld_reclaim_extents;
>> diff --git a/hw/cxl/mhsld/mhsld.h b/hw/cxl/mhsld/mhsld.h
>> index e7ead1f0d2..c9fbec71ca 100644
>> --- a/hw/cxl/mhsld/mhsld.h
>> +++ b/hw/cxl/mhsld/mhsld.h
>> @@ -23,6 +23,18 @@
>> */
>> #define MHSLD_HEADS (8)
>>
>> +typedef struct MHDHeadInfoBlock {
>> + uint8_t port_number;
>> + uint8_t max_link_width;
>> + uint8_t nego_link_width;
>> + uint8_t supp_link_speeds_vector;
>> + uint8_t max_link_speed;
>> + uint8_t current_link_speed;
>> + uint8_t ltssm_state;
>> + uint8_t first_nego_lane_num;
>> + uint8_t link_state_flags;
>> +} QEMU_PACKED MHDHeadInfoBlock;
>> +
>> /*
>> * The shared state cannot have 2 variable sized regions
>> * so we have to max out the ldmap.
>> @@ -32,6 +44,7 @@ typedef struct MHSLDSharedState {
>> uint8_t nr_lds;
>> uint8_t ldmap[MHSLD_HEADS];
>> uint64_t nr_blocks;
>> + MHDHeadInfoBlock head_info_blocks[MHSLD_HEADS];
>> uint8_t blocks[];
>> } MHSLDSharedState;
>>
>> @@ -52,6 +65,7 @@ struct CXLMHSLDClass {
>> enum {
>> MHSLD_MHD = 0x55,
>> #define GET_MHD_INFO 0x0
>> + #define GET_MHD_HEAD_INFO 0x1
>> };
>>
>> /*
>> @@ -72,4 +86,16 @@ typedef struct MHDGetInfoOutput {
>> uint16_t resv2;
>> uint8_t ldmap[];
>> } QEMU_PACKED MHDGetInfoOutput;
>> +
>> +typedef struct MHDGetHeadInfoInput {
>> + uint8_t start_head;
>> + uint8_t nr_heads;
>> +} QEMU_PACKED MHDGetHeadInfoInput;
>> +
>> +typedef struct MHDGetHeadInfoOutput {
>> + uint8_t nr_heads;
>> + uint8_t rsvd[3];
>> + MHDHeadInfoBlock head_info_list[];
>
>s/head_info_list/head_info/
Okay. Will use head_info in V1 patch.
>
>Fan
Thanks Fan Ni for reviewing the patch.
Alok
>
>> +} QEMU_PACKED MHDGetHeadInfoOutput;
>> +
>> #endif
>> diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
>> index ca515cab13..c93c71c45d 100644
>> --- a/include/hw/cxl/cxl_device.h
>> +++ b/include/hw/cxl/cxl_device.h
>> @@ -732,6 +732,12 @@ struct CXLType3Class {
>> uint8_t *payload_out,
>> size_t *len_out,
>> CXLCCI *cci);
>> + CXLRetCode (*mhd_get_head_info)(const struct cxl_cmd *cmd,
>> + uint8_t *payload_in,
>> + size_t len_in,
>> + uint8_t *payload_out,
>> + size_t *len_out,
>> + CXLCCI *cci);
>> bool (*mhd_access_valid)(PCIDevice *d, uint64_t addr, unsigned int size);
>> bool (*mhd_reserve_extents)(PCIDevice *d,
>> CxlDynamicCapacityExtentList *records,
>> --
>> 2.34.1
>>
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h)
2025-05-22 19:15 ` Davidlohr Bueso
@ 2025-07-01 13:05 ` Alok Rathore
0 siblings, 0 replies; 9+ messages in thread
From: Alok Rathore @ 2025-07-01 13:05 UTC (permalink / raw)
To: Davidlohr Bueso
Cc: Jonathan.Cameron, qemu-devel, gost.dev, linux-cxl, nifan.cxl,
vishak.g, krish.reddy, a.manzanares, alokrathore20
[-- Attachment #1: Type: text/plain, Size: 12007 bytes --]
On 22/05/25 12:15PM, Davidlohr Bueso wrote:
>On Thu, 22 May 2025, Vinayak Holikatti wrote:
>
>>CXL spec 3.2 section 7.6.7.5.2 describes Get Head Info.
>
>So how was this tested? Ideally this now comes with a libcxlmi (or equivalent)
>test case. See for example how Anisa is going about this with the FMAPI DCD
>patches:
>
>https://lore.kernel.org/linux-cxl/20250508001754.122180-1-anisa.su887@gmail.com/
Used libcxl-mi to test this feature. Will update the information in V1 patch.
>
>>Signed-off-by: Vinayak Holikatti <vinayak.kh@samsung.com>
>>---
>>This patch is generated against Jonathan Cameron's branch cxl-2025-03-20
>
>Adding him to the thread :)
>
>>
>>hw/cxl/cxl-mailbox-utils.c | 21 +++++++++
>>hw/cxl/mhsld/mhsld.c | 92 ++++++++++++++++++++++++++++++++++++-
>>hw/cxl/mhsld/mhsld.h | 26 +++++++++++
>>include/hw/cxl/cxl_device.h | 6 +++
>>4 files changed, 144 insertions(+), 1 deletion(-)
>>
>>diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
>>index a02d130926..4f25caecea 100644
>>--- a/hw/cxl/cxl-mailbox-utils.c
>>+++ b/hw/cxl/cxl-mailbox-utils.c
>>@@ -122,6 +122,7 @@ enum {
>> #define MANAGEMENT_COMMAND 0x0
>> MHD = 0x55,
>> #define GET_MHD_INFO 0x0
>>+ #define GET_MHD_HEAD_INFO 0x1
>>};
>>
>>/* CCI Message Format CXL r3.1 Figure 7-19 */
>>@@ -267,6 +268,23 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
>> return CXL_MBOX_UNSUPPORTED;
>>}
>>
>>+/*
>>+ * CXL r3.2 section 7.6.7.5.2 - Get Multi-Headed Head Info (Opcode 5501h)
>>+ */
>>+static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
>>+ uint8_t *payload_in, size_t len_in,
>>+ uint8_t *payload_out, size_t *len_out,
>>+ CXLCCI *cci)
>>+{
>>+ CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
>>+ CXLType3Class *cvc = CXL_TYPE3_GET_CLASS(ct3d);
>>+ if (cvc->mhd_get_head_info) {
>>+ return cvc->mhd_get_head_info(cmd, payload_in, len_in, payload_out,
>>+ len_out, cci);
>>+ }
>>+ return CXL_MBOX_UNSUPPORTED;
>>+}
>>+
>>static CXLRetCode cmd_events_get_records(const struct cxl_cmd *cmd,
>> uint8_t *payload_in, size_t len_in,
>> uint8_t *payload_out, size_t *len_out,
>>@@ -3429,6 +3447,7 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
>> "MEDIA_AND_POISON_GET_SCAN_MEDIA_RESULTS",
>> cmd_media_get_scan_media_results, 0, 0 },
>> [MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
>>+ [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
>>};
>>
>>static const struct cxl_cmd cxl_cmd_set_dcd[256][256] = {
>>@@ -3761,6 +3780,8 @@ static const struct cxl_cmd cxl_cmd_set_t3_fm_owned_ld_mctp[256][256] = {
>> [TIMESTAMP][GET] = { "TIMESTAMP_GET", cmd_timestamp_get, 0, 0 },
>> [TUNNEL][MANAGEMENT_COMMAND] = { "TUNNEL_MANAGEMENT_COMMAND",
>> cmd_tunnel_management_cmd, ~0, 0 },
>>+ [MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
>>+ [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
>>};
>>
>>void cxl_initialize_t3_fm_owned_ld_mctpcci(CXLCCI *cci, DeviceState *d,
>>diff --git a/hw/cxl/mhsld/mhsld.c b/hw/cxl/mhsld/mhsld.c
>>index 9f633b3bed..981546b5ff 100644
>>--- a/hw/cxl/mhsld/mhsld.c
>>+++ b/hw/cxl/mhsld/mhsld.c
>>@@ -61,9 +61,57 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
>> return CXL_MBOX_SUCCESS;
>>}
>>
>>+/*
>>+ * CXL r3.2 section 7.6.7.5.2 - Get Head Info (Opcode 5501h)
>>+ *
>>+ * This command retrieves the number of heads, number of supported LDs,
>>+ * and Head-to-LD mapping of a Multi-Headed device.
>>+ */
>>+static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
>>+ uint8_t *payload_in, size_t len_in,
>>+ uint8_t *payload_out, size_t *len_out,
>>+ CXLCCI *cci)
>>+{
>>+ CXLMHSLDState *s = CXL_MHSLD(cci->d);
>>+ MHDGetHeadInfoInput *input = (void *)payload_in;
>>+ MHDGetHeadInfoOutput *output = (void *)payload_out;
>>+ int i = 0;
>>+
>>+ if (input->start_head > MHSLD_HEADS) {
>>+ return CXL_MBOX_INVALID_INPUT;
>>+ }
>>+
>>+ output->nr_heads = MIN((MHSLD_HEADS - input->start_head), input->nr_heads);
>>+ for (i = input->start_head; i < input->start_head + output->nr_heads; i++) {
>>+ output->head_info_list[i].port_number =
>>+ s->mhd_state->head_info_blocks[i].port_number;
>>+ output->head_info_list[i].max_link_width =
>>+ s->mhd_state->head_info_blocks[i].max_link_width;
>>+ output->head_info_list[i].nego_link_width =
>>+ s->mhd_state->head_info_blocks[i].nego_link_width;
>>+ output->head_info_list[i].supp_link_speeds_vector =
>>+ s->mhd_state->head_info_blocks[i].supp_link_speeds_vector;
>>+ output->head_info_list[i].max_link_speed =
>>+ s->mhd_state->head_info_blocks[i].max_link_speed;
>>+ output->head_info_list[i].current_link_speed =
>>+ s->mhd_state->head_info_blocks[i].current_link_speed;
>>+ output->head_info_list[i].ltssm_state =
>>+ s->mhd_state->head_info_blocks[i].ltssm_state;
>>+ output->head_info_list[i].first_nego_lane_num =
>>+ s->mhd_state->head_info_blocks[i].first_nego_lane_num;
>>+ output->head_info_list[i].link_state_flags =
>>+ s->mhd_state->head_info_blocks[i].link_state_flags;
>>+ }
>>+
>>+ *len_out = sizeof(*output) + output->nr_heads * sizeof(MHDHeadInfoBlock);
>>+ return CXL_MBOX_SUCCESS;
>>+}
>>+
>>static const struct cxl_cmd cxl_cmd_set_mhsld[256][256] = {
>> [MHSLD_MHD][GET_MHD_INFO] = {"GET_MULTI_HEADED_INFO",
>> cmd_mhd_get_info, 2, 0},
>>+ [MHSLD_MHD][GET_MHD_HEAD_INFO] = {"GET_HEAD_INFO",
>>+ cmd_mhd_get_head_info, 2, 0},
>>};
>>
>>static const Property cxl_mhsld_props[] = {
>>@@ -166,6 +214,47 @@ static void cxl_mhsld_state_initialize(CXLMHSLDState *s, size_t dc_size)
>> s->mhd_state->nr_blocks = dc_size / MHSLD_BLOCK_SZ;
>>}
>>
>>+
>>+static void cxl_mhsld_init_head_info(CXLMHSLDState *s, PCIDevice *pdev)
>>+{
>>+ uint16_t lnksta = 0;
>>+ uint16_t current_link_speed = 0;
>>+ uint16_t negotiated_link_width = 0;
>>+ uint16_t lnkcap = 0, lnkcap2 = 0;
>>+ uint16_t max_link_width = 0;
>>+ uint16_t max_link_speed = 0;
>>+ uint16_t supported_link_speeds_vector = 0;
>>+
>>+ lnksta = pdev->config_read(pdev,
>>+ pdev->exp.exp_cap + PCI_EXP_LNKSTA,
>>+ sizeof(lnksta));
>>+ lnkcap = pdev->config_read(pdev,
>>+ pdev->exp.exp_cap + PCI_EXP_LNKCAP,
>>+ sizeof(lnkcap));
>>+ lnkcap2 = pdev->config_read(pdev,
>>+ pdev->exp.exp_cap + PCI_EXP_LNKCAP2,
>>+ sizeof(lnkcap2));
>>+ supported_link_speeds_vector = (lnkcap2 & 0xFE) >> 1;
>>+ max_link_width = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
>>+ max_link_speed = lnkcap & PCI_EXP_LNKCAP_SLS;
>>+ current_link_speed = lnksta & PCI_EXP_LNKSTA_CLS;
>>+ negotiated_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4;
>>+
>>+ s->mhd_state->head_info_blocks[s->mhd_head].port_number = s->mhd_head;
>>+ s->mhd_state->head_info_blocks[s->mhd_head].max_link_width = max_link_width;
>>+ s->mhd_state->head_info_blocks[s->mhd_head].nego_link_width =
>>+ negotiated_link_width;
>>+ s->mhd_state->head_info_blocks[s->mhd_head].supp_link_speeds_vector =
>>+ supported_link_speeds_vector;
>>+ s->mhd_state->head_info_blocks[s->mhd_head].max_link_speed =
>>+ max_link_speed;
>>+ s->mhd_state->head_info_blocks[s->mhd_head].current_link_speed =
>>+ current_link_speed;
>>+ s->mhd_state->head_info_blocks[s->mhd_head].ltssm_state = 0x7;
>>+ s->mhd_state->head_info_blocks[s->mhd_head].first_nego_lane_num = 0;
>>+ s->mhd_state->head_info_blocks[s->mhd_head].link_state_flags = 0;
>>+}
>>+
>>/* Returns starting index of region in MHD map. */
>>static inline size_t cxl_mhsld_find_dc_region_start(PCIDevice *d,
>> CXLDCRegion *r)
>>@@ -376,7 +465,7 @@ static void cxl_mhsld_realize(PCIDevice *pci_dev, Error **errp)
>> }
>>
>> cxl_mhsld_state_initialize(s, dc_size);
>>-
>>+ cxl_mhsld_init_head_info(s, pci_dev);
>> /* Set the LD ownership for this head to this system */
>> s->mhd_state->ldmap[s->mhd_head] = s->mhd_head;
>> return;
>>@@ -428,6 +517,7 @@ static void cxl_mhsld_class_init(ObjectClass *klass, void *data)
>>
>> CXLType3Class *cvc = CXL_TYPE3_CLASS(klass);
>> cvc->mhd_get_info = cmd_mhd_get_info;
>>+ cvc->mhd_get_head_info = cmd_mhd_get_head_info;
>> cvc->mhd_access_valid = cxl_mhsld_access_valid;
>> cvc->mhd_reserve_extents = cxl_mhsld_reserve_extents;
>> cvc->mhd_reclaim_extents = cxl_mhsld_reclaim_extents;
>>diff --git a/hw/cxl/mhsld/mhsld.h b/hw/cxl/mhsld/mhsld.h
>>index e7ead1f0d2..c9fbec71ca 100644
>>--- a/hw/cxl/mhsld/mhsld.h
>>+++ b/hw/cxl/mhsld/mhsld.h
>>@@ -23,6 +23,18 @@
>> */
>>#define MHSLD_HEADS (8)
>>
>>+typedef struct MHDHeadInfoBlock {
>>+ uint8_t port_number;
>>+ uint8_t max_link_width;
>>+ uint8_t nego_link_width;
>>+ uint8_t supp_link_speeds_vector;
>>+ uint8_t max_link_speed;
>>+ uint8_t current_link_speed;
>>+ uint8_t ltssm_state;
>>+ uint8_t first_nego_lane_num;
>>+ uint8_t link_state_flags;
>>+} QEMU_PACKED MHDHeadInfoBlock;
>>+
>>/*
>> * The shared state cannot have 2 variable sized regions
>> * so we have to max out the ldmap.
>>@@ -32,6 +44,7 @@ typedef struct MHSLDSharedState {
>> uint8_t nr_lds;
>> uint8_t ldmap[MHSLD_HEADS];
>> uint64_t nr_blocks;
>>+ MHDHeadInfoBlock head_info_blocks[MHSLD_HEADS];
>> uint8_t blocks[];
>>} MHSLDSharedState;
>>
>>@@ -52,6 +65,7 @@ struct CXLMHSLDClass {
>>enum {
>> MHSLD_MHD = 0x55,
>> #define GET_MHD_INFO 0x0
>>+ #define GET_MHD_HEAD_INFO 0x1
>>};
>>
>>/*
>>@@ -72,4 +86,16 @@ typedef struct MHDGetInfoOutput {
>> uint16_t resv2;
>> uint8_t ldmap[];
>>} QEMU_PACKED MHDGetInfoOutput;
>>+
>>+typedef struct MHDGetHeadInfoInput {
>>+ uint8_t start_head;
>>+ uint8_t nr_heads;
>>+} QEMU_PACKED MHDGetHeadInfoInput;
>>+
>>+typedef struct MHDGetHeadInfoOutput {
>>+ uint8_t nr_heads;
>>+ uint8_t rsvd[3];
>>+ MHDHeadInfoBlock head_info_list[];
>>+} QEMU_PACKED MHDGetHeadInfoOutput;
>>+
>>#endif
>>diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
>>index ca515cab13..c93c71c45d 100644
>>--- a/include/hw/cxl/cxl_device.h
>>+++ b/include/hw/cxl/cxl_device.h
>>@@ -732,6 +732,12 @@ struct CXLType3Class {
>> uint8_t *payload_out,
>> size_t *len_out,
>> CXLCCI *cci);
>>+ CXLRetCode (*mhd_get_head_info)(const struct cxl_cmd *cmd,
>>+ uint8_t *payload_in,
>>+ size_t len_in,
>>+ uint8_t *payload_out,
>>+ size_t *len_out,
>>+ CXLCCI *cci);
>> bool (*mhd_access_valid)(PCIDevice *d, uint64_t addr, unsigned int size);
>> bool (*mhd_reserve_extents)(PCIDevice *d,
>> CxlDynamicCapacityExtentList *records,
>>--
>>2.34.1
>>
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h)
[not found] ` <CGME20250701131120epcas5p35fa8d12f058a82bc637c13d176dd0477@epcas5p3.samsung.com>
@ 2025-07-01 13:11 ` Alok Rathore
0 siblings, 0 replies; 9+ messages in thread
From: Alok Rathore @ 2025-07-01 13:11 UTC (permalink / raw)
To: Anisa Su
Cc: nifan.cxl, a.manzanares, dave, gost.dev, krish.reddy, linux-cxl,
qemu-devel, vishak.g, alokrathore20
[-- Attachment #1: Type: text/plain, Size: 8555 bytes --]
On 22/05/25 11:12PM, Anisa Su wrote:
>On Thu, May 22, 2025 at 12:01:35PM +0530, Vinayak Holikatti wrote:
>> CXL spec 3.2 section 7.6.7.5.2 describes Get Head Info.
>>
>> Signed-off-by: Vinayak Holikatti <vinayak.kh@samsung.com>
>> ---
>> This patch is generated against Jonathan Cameron's branch cxl-2025-03-20
>>
>> hw/cxl/cxl-mailbox-utils.c | 21 +++++++++
>> hw/cxl/mhsld/mhsld.c | 92 ++++++++++++++++++++++++++++++++++++-
>> hw/cxl/mhsld/mhsld.h | 26 +++++++++++
>> include/hw/cxl/cxl_device.h | 6 +++
>> 4 files changed, 144 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
>> index a02d130926..4f25caecea 100644
>> --- a/hw/cxl/cxl-mailbox-utils.c
>> +++ b/hw/cxl/cxl-mailbox-utils.c
>> @@ -122,6 +122,7 @@ enum {
>> #define MANAGEMENT_COMMAND 0x0
>> MHD = 0x55,
>> #define GET_MHD_INFO 0x0
>> + #define GET_MHD_HEAD_INFO 0x1
>> };
>>
>> /* CCI Message Format CXL r3.1 Figure 7-19 */
>> @@ -267,6 +268,23 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
>> return CXL_MBOX_UNSUPPORTED;
>> }
>>
>> +/*
>> + * CXL r3.2 section 7.6.7.5.2 - Get Multi-Headed Head Info (Opcode 5501h)
>> + */
>> +static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
>> + uint8_t *payload_in, size_t len_in,
>> + uint8_t *payload_out, size_t *len_out,
>> + CXLCCI *cci)
>> +{
>> + CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
>> + CXLType3Class *cvc = CXL_TYPE3_GET_CLASS(ct3d);
>> + if (cvc->mhd_get_head_info) {
>> + return cvc->mhd_get_head_info(cmd, payload_in, len_in, payload_out,
>> + len_out, cci);
>> + }
>> + return CXL_MBOX_UNSUPPORTED;
>> +}
>> +
>> static CXLRetCode cmd_events_get_records(const struct cxl_cmd *cmd,
>> uint8_t *payload_in, size_t len_in,
>> uint8_t *payload_out, size_t *len_out,
>> @@ -3429,6 +3447,7 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
>> "MEDIA_AND_POISON_GET_SCAN_MEDIA_RESULTS",
>> cmd_media_get_scan_media_results, 0, 0 },
>> [MHD][GET_MHD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_info, 2, 0},
>> + [MHD][GET_MHD_HEAD_INFO] = { "GET_MULTI_HEADED_INFO", cmd_mhd_get_head_info, 2, 0},
>The name here "GET_MULTI_HEADED_INFO" is the same as the previous command.
Yes, It should be GET_HEAD_INFO. Will fix in V1 patch.
>> };
>>
>...
>> +
>> +static void cxl_mhsld_init_head_info(CXLMHSLDState *s, PCIDevice *pdev)
>> +{
>> + uint16_t lnksta = 0;
>> + uint16_t current_link_speed = 0;
>> + uint16_t negotiated_link_width = 0;
>> + uint16_t lnkcap = 0, lnkcap2 = 0;
>> + uint16_t max_link_width = 0;
>> + uint16_t max_link_speed = 0;
>> + uint16_t supported_link_speeds_vector = 0;
>> +
>> + lnksta = pdev->config_read(pdev,
>> + pdev->exp.exp_cap + PCI_EXP_LNKSTA,
>> + sizeof(lnksta));
>> + lnkcap = pdev->config_read(pdev,
>> + pdev->exp.exp_cap + PCI_EXP_LNKCAP,
>> + sizeof(lnkcap));
>> + lnkcap2 = pdev->config_read(pdev,
>> + pdev->exp.exp_cap + PCI_EXP_LNKCAP2,
>> + sizeof(lnkcap2));
>> + supported_link_speeds_vector = (lnkcap2 & 0xFE) >> 1;
>> + max_link_width = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
>> + max_link_speed = lnkcap & PCI_EXP_LNKCAP_SLS;
>> + current_link_speed = lnksta & PCI_EXP_LNKSTA_CLS;
>> + negotiated_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4;
>> +
>> + s->mhd_state->head_info_blocks[s->mhd_head].port_number = s->mhd_head;
>> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_width = max_link_width;
>> + s->mhd_state->head_info_blocks[s->mhd_head].nego_link_width =
>> + negotiated_link_width;
>> + s->mhd_state->head_info_blocks[s->mhd_head].supp_link_speeds_vector =
>> + supported_link_speeds_vector;
>> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_speed =
>> + max_link_speed;
>> + s->mhd_state->head_info_blocks[s->mhd_head].current_link_speed =
>> + current_link_speed;
>> + s->mhd_state->head_info_blocks[s->mhd_head].ltssm_state = 0x7;
>I think it would be helpful to make a define for the ltssm states?
Sure, Will fix in V1 patch
>> + s->mhd_state->head_info_blocks[s->mhd_head].first_nego_lane_num = 0;
>> + s->mhd_state->head_info_blocks[s->mhd_head].link_state_flags = 0;
>> +}
>> +
>> /* Returns starting index of region in MHD map. */
>> static inline size_t cxl_mhsld_find_dc_region_start(PCIDevice *d,
>> CXLDCRegion *r)
>> @@ -376,7 +465,7 @@ static void cxl_mhsld_realize(PCIDevice *pci_dev, Error **errp)
>> }
>>
>> cxl_mhsld_state_initialize(s, dc_size);
>> -
>> + cxl_mhsld_init_head_info(s, pci_dev);
>> /* Set the LD ownership for this head to this system */
>> s->mhd_state->ldmap[s->mhd_head] = s->mhd_head;
>> return;
>> @@ -428,6 +517,7 @@ static void cxl_mhsld_class_init(ObjectClass *klass, void *data)
>>
>> CXLType3Class *cvc = CXL_TYPE3_CLASS(klass);
>> cvc->mhd_get_info = cmd_mhd_get_info;
>> + cvc->mhd_get_head_info = cmd_mhd_get_head_info;
>> cvc->mhd_access_valid = cxl_mhsld_access_valid;
>> cvc->mhd_reserve_extents = cxl_mhsld_reserve_extents;
>> cvc->mhd_reclaim_extents = cxl_mhsld_reclaim_extents;
>> diff --git a/hw/cxl/mhsld/mhsld.h b/hw/cxl/mhsld/mhsld.h
>> index e7ead1f0d2..c9fbec71ca 100644
>> --- a/hw/cxl/mhsld/mhsld.h
>> +++ b/hw/cxl/mhsld/mhsld.h
>> @@ -23,6 +23,18 @@
>> */
>> #define MHSLD_HEADS (8)
>>
>> +typedef struct MHDHeadInfoBlock {
>> + uint8_t port_number;
>> + uint8_t max_link_width;
>> + uint8_t nego_link_width;
>> + uint8_t supp_link_speeds_vector;
>> + uint8_t max_link_speed;
>> + uint8_t current_link_speed;
>> + uint8_t ltssm_state;
>> + uint8_t first_nego_lane_num;
>> + uint8_t link_state_flags;
>> +} QEMU_PACKED MHDHeadInfoBlock;
>> +
>> /*
>> * The shared state cannot have 2 variable sized regions
>> * so we have to max out the ldmap.
>> @@ -32,6 +44,7 @@ typedef struct MHSLDSharedState {
>> uint8_t nr_lds;
>> uint8_t ldmap[MHSLD_HEADS];
>> uint64_t nr_blocks;
>> + MHDHeadInfoBlock head_info_blocks[MHSLD_HEADS];
>> uint8_t blocks[];
>> } MHSLDSharedState;
>>
>> @@ -52,6 +65,7 @@ struct CXLMHSLDClass {
>> enum {
>> MHSLD_MHD = 0x55,
>> #define GET_MHD_INFO 0x0
>> + #define GET_MHD_HEAD_INFO 0x1
>> };
>>
>> /*
>> @@ -72,4 +86,16 @@ typedef struct MHDGetInfoOutput {
>> uint16_t resv2;
>> uint8_t ldmap[];
>> } QEMU_PACKED MHDGetInfoOutput;
>> +
>> +typedef struct MHDGetHeadInfoInput {
>> + uint8_t start_head;
>> + uint8_t nr_heads;
>> +} QEMU_PACKED MHDGetHeadInfoInput;
>> +
>> +typedef struct MHDGetHeadInfoOutput {
>> + uint8_t nr_heads;
>> + uint8_t rsvd[3];
>> + MHDHeadInfoBlock head_info_list[];
>> +} QEMU_PACKED MHDGetHeadInfoOutput;
>> +
>> #endif
>> diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
>> index ca515cab13..c93c71c45d 100644
>> --- a/include/hw/cxl/cxl_device.h
>> +++ b/include/hw/cxl/cxl_device.h
>> @@ -732,6 +732,12 @@ struct CXLType3Class {
>> uint8_t *payload_out,
>> size_t *len_out,
>> CXLCCI *cci);
>> + CXLRetCode (*mhd_get_head_info)(const struct cxl_cmd *cmd,
>> + uint8_t *payload_in,
>> + size_t len_in,
>> + uint8_t *payload_out,
>> + size_t *len_out,
>> + CXLCCI *cci);
>I think the indent here needs to be aligned with the open parentheses on
>the first line of the function declaration
I’ll fix in V1 patch.
>> bool (*mhd_access_valid)(PCIDevice *d, uint64_t addr, unsigned int size);
>> bool (*mhd_reserve_extents)(PCIDevice *d,
>> CxlDynamicCapacityExtentList *records,
>> --
>> 2.34.1
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h)
2025-05-29 12:13 ` Jonathan Cameron
@ 2025-07-01 13:19 ` Alok Rathore
0 siblings, 0 replies; 9+ messages in thread
From: Alok Rathore @ 2025-07-01 13:19 UTC (permalink / raw)
To: Jonathan Cameron
Cc: qemu-devel, gost.dev, linux-cxl, nifan.cxl, dave, vishak.g,
krish.reddy, a.manzanares, alokrathore20
[-- Attachment #1: Type: text/plain, Size: 7636 bytes --]
On 29/05/25 01:13PM, Jonathan Cameron wrote:
>On Thu, 22 May 2025 12:01:35 +0530
>Vinayak Holikatti <vinayak.kh@samsung.com> wrote:
>
>> CXL spec 3.2 section 7.6.7.5.2 describes Get Head Info.
>>
>> Signed-off-by: Vinayak Holikatti <vinayak.kh@samsung.com>
>
>Hi Vinayak,
>
>Some code simplification suggestions below.
Thanks Jonathan for reviewing the patch.
Alok
>
>> ---
>> This patch is generated against Jonathan Cameron's branch cxl-2025-03-20
>>
>> hw/cxl/cxl-mailbox-utils.c | 21 +++++++++
>> hw/cxl/mhsld/mhsld.c | 92 ++++++++++++++++++++++++++++++++++++-
>> hw/cxl/mhsld/mhsld.h | 26 +++++++++++
>> include/hw/cxl/cxl_device.h | 6 +++
>> 4 files changed, 144 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
>> index a02d130926..4f25caecea 100644
>> --- a/hw/cxl/cxl-mailbox-utils.c
>> +++ b/hw/cxl/cxl-mailbox-utils.c
>
>> diff --git a/hw/cxl/mhsld/mhsld.c b/hw/cxl/mhsld/mhsld.c
>> index 9f633b3bed..981546b5ff 100644
>> --- a/hw/cxl/mhsld/mhsld.c
>> +++ b/hw/cxl/mhsld/mhsld.c
>> @@ -61,9 +61,57 @@ static CXLRetCode cmd_mhd_get_info(const struct cxl_cmd *cmd,
>> return CXL_MBOX_SUCCESS;
>> }
>>
>> +/*
>> + * CXL r3.2 section 7.6.7.5.2 - Get Head Info (Opcode 5501h)
>> + *
>> + * This command retrieves the number of heads, number of supported LDs,
>> + * and Head-to-LD mapping of a Multi-Headed device.
>> + */
>> +static CXLRetCode cmd_mhd_get_head_info(const struct cxl_cmd *cmd,
>> + uint8_t *payload_in, size_t len_in,
>> + uint8_t *payload_out, size_t *len_out,
>> + CXLCCI *cci)
>> +{
>> + CXLMHSLDState *s = CXL_MHSLD(cci->d);
>> + MHDGetHeadInfoInput *input = (void *)payload_in;
>> + MHDGetHeadInfoOutput *output = (void *)payload_out;
>> + int i = 0;
>> +
>> + if (input->start_head > MHSLD_HEADS) {
>> + return CXL_MBOX_INVALID_INPUT;
>> + }
>> +
>> + output->nr_heads = MIN((MHSLD_HEADS - input->start_head), input->nr_heads);
>> + for (i = input->start_head; i < input->start_head + output->nr_heads; i++) {
>
>Can we get away with a memcpy()? Any endian issues on any of these?
Sure, I’ll check with memcpy()
>
>> + output->head_info_list[i].port_number =
>> + s->mhd_state->head_info_blocks[i].port_number;
>> + output->head_info_list[i].max_link_width =
>> + s->mhd_state->head_info_blocks[i].max_link_width;
>> + output->head_info_list[i].nego_link_width =
>> + s->mhd_state->head_info_blocks[i].nego_link_width;
>> + output->head_info_list[i].supp_link_speeds_vector =
>> + s->mhd_state->head_info_blocks[i].supp_link_speeds_vector;
>> + output->head_info_list[i].max_link_speed =
>> + s->mhd_state->head_info_blocks[i].max_link_speed;
>> + output->head_info_list[i].current_link_speed =
>> + s->mhd_state->head_info_blocks[i].current_link_speed;
>> + output->head_info_list[i].ltssm_state =
>> + s->mhd_state->head_info_blocks[i].ltssm_state;
>> + output->head_info_list[i].first_nego_lane_num =
>> + s->mhd_state->head_info_blocks[i].first_nego_lane_num;
>> + output->head_info_list[i].link_state_flags =
>> + s->mhd_state->head_info_blocks[i].link_state_flags;
>> + }
>> +
>> + *len_out = sizeof(*output) + output->nr_heads * sizeof(MHDHeadInfoBlock);
>> + return CXL_MBOX_SUCCESS;
>> +}
>
>> static const Property cxl_mhsld_props[] = {
>> @@ -166,6 +214,47 @@ static void cxl_mhsld_state_initialize(CXLMHSLDState *s, size_t dc_size)
>> s->mhd_state->nr_blocks = dc_size / MHSLD_BLOCK_SZ;
>> }
>>
>> +
>> +static void cxl_mhsld_init_head_info(CXLMHSLDState *s, PCIDevice *pdev)
>> +{
>> + uint16_t lnksta = 0;
>
>No need to initialize when they are always set below.
Sure, I’ll fix in V1 patch.
>
>> + uint16_t current_link_speed = 0;
>> + uint16_t negotiated_link_width = 0;
>> + uint16_t lnkcap = 0, lnkcap2 = 0;
>> + uint16_t max_link_width = 0;
>> + uint16_t max_link_speed = 0;
>
>Once you drop the unnecessary init combine width and speed on one line.
>Or as below, get rid of most of these local variables entirely.
>
>> + uint16_t supported_link_speeds_vector = 0;
>> +
>> + lnksta = pdev->config_read(pdev,
>> + pdev->exp.exp_cap + PCI_EXP_LNKSTA,
>> + sizeof(lnksta));
>> + lnkcap = pdev->config_read(pdev,
>> + pdev->exp.exp_cap + PCI_EXP_LNKCAP,
>> + sizeof(lnkcap));
>> + lnkcap2 = pdev->config_read(pdev,
>> + pdev->exp.exp_cap + PCI_EXP_LNKCAP2,
>> + sizeof(lnkcap2));
>> + supported_link_speeds_vector = (lnkcap2 & 0xFE) >> 1;
>Worth considering adding defines for that to incluw/hw/pci/pcie_regs.h
Okay. I’ll add in V1 patch.
>
>> + max_link_width = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
>
>Use PCI_EXP_LNK_MLW_SHIFT to extract that.
>(we should also tidy this up in physical port state.
Sure. I’ll fix in V1 patch.
>
>
>> + max_link_speed = lnkcap & PCI_EXP_LNKCAP_SLS;
>> + current_link_speed = lnksta & PCI_EXP_LNKSTA_CLS;
>> + negotiated_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4;
>Similar - there should be a suitable define for that shift.
>> +
>> + s->mhd_state->head_info_blocks[s->mhd_head].port_number = s->mhd_head;
>
>I would use something like
>
> s->mhd_state->head_info_blocks[s->mhd_head] = (MHDHeadInfoBlock) {
> .max_link_width = lnkcap & PCI_EXP_LNKCAP_SLS,
> .nego_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4, //with the define
> .supp_link_speeds_vector = (lnkcap2 & 0xFE) >> 1,
>etc
> };
Sure, I’ll remove local variable and assign in this way.
>> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_width = max_link_width;
>> + s->mhd_state->head_info_blocks[s->mhd_head].nego_link_width =
>> + negotiated_link_width;
>> + s->mhd_state->head_info_blocks[s->mhd_head].supp_link_speeds_vector =
>> + supported_link_speeds_vector;
>> + s->mhd_state->head_info_blocks[s->mhd_head].max_link_speed =
>> + max_link_speed;
>> + s->mhd_state->head_info_blocks[s->mhd_head].current_link_speed =
>> + current_link_speed;
>> + s->mhd_state->head_info_blocks[s->mhd_head].ltssm_state = 0x7;
>> + s->mhd_state->head_info_blocks[s->mhd_head].first_nego_lane_num = 0;
>> + s->mhd_state->head_info_blocks[s->mhd_head].link_state_flags = 0;
>> +}
>> +
>> /* Returns starting index of region in MHD map. */
>> static inline size_t cxl_mhsld_find_dc_region_start(PCIDevice *d,
>> CXLDCRegion *r)
>> @@ -376,7 +465,7 @@ static void cxl_mhsld_realize(PCIDevice *pci_dev, Error **errp)
>> }
>>
>> cxl_mhsld_state_initialize(s, dc_size);
>> -
>> + cxl_mhsld_init_head_info(s, pci_dev);
>Avoid the white space noise by leaving a blank line here.
Okay, Will fix in V1 patch
>
>> /* Set the LD ownership for this head to this system */
>> s->mhd_state->ldmap[s->mhd_head] = s->mhd_head;
>> return;
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-07-01 14:12 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CGME20250522063149epcas5p13719600aa8f59313ff3dc2570c996aec@epcas5p1.samsung.com>
2025-05-22 6:31 ` [PATCH] Add support for FMAPI Get Mutliheaded Head info opcode (5501h) Vinayak Holikatti
2025-05-22 16:48 ` Fan Ni
2025-07-01 12:59 ` Alok Rathore
2025-05-22 19:15 ` Davidlohr Bueso
2025-07-01 13:05 ` Alok Rathore
2025-05-22 23:12 ` Anisa Su
[not found] ` <CGME20250701131120epcas5p35fa8d12f058a82bc637c13d176dd0477@epcas5p3.samsung.com>
2025-07-01 13:11 ` Alok Rathore
2025-05-29 12:13 ` Jonathan Cameron
2025-07-01 13:19 ` Alok Rathore
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).