diff --git a/LICENSE b/LICENSE index c9634a4..ae3132f 100644 --- a/LICENSE +++ b/LICENSE @@ -58,7 +58,7 @@ APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2024 Jackrabbit-Labs-LLC +Copyright 2024 Jackrabbit-Founders-LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Makefile b/Makefile index 862a82d..92f5ec6 100644 --- a/Makefile +++ b/Makefile @@ -13,18 +13,20 @@ # ****************************************************************************** CC=gcc -CFLAGS= -g3 -O0 -Wall -Wextra -MACROS=-D CSE_VERBOSE -INCLUDE_DIR=/usr/local/include -LIB_DIR=/usr/local/lib -INCLUDE_PATH=-I $(INCLUDE_DIR) -I /usr/include/glib-2.0 -I /usr/lib/`uname -m`-linux-gnu/glib-2.0/include/ -I /usr/lib64/glib-2.0/include -LIB_PATH=-L $(LIB_DIR) -LIBS=-l yamlloader -l yaml -l glib-2.0 -l mctp -l uuid -l ptrqueue -l fmapi -l emapi -l arrayutils -l pciutils -l timeutils -l pci +CFLAGS?= -g3 -O0 -Wall -Wextra +MACROS?=-D CSE_VERBOSE +INCLUDE_DIR?=/usr/local/include +LIB_DIR?=/usr/local/lib +LOCAL_INCLUDE_DIR?=./include +LOCAL_LIB_DIR?=./lib +INCLUDE_PATH=-I $(LOCAL_INCLUDE_DIR) -I $(INCLUDE_DIR) -I /usr/include/glib-2.0 -I /usr/lib/`uname -m`-linux-gnu/glib-2.0/include/ -I /usr/lib64/glib-2.0/include +LIB_PATH=-L $(LOCAL_LIB_DIR) -L $(LIB_DIR) +LIBS=-l yamlloader -l yaml -l glib-2.0 -l mctp -l uuid -l ptrqueue -l fmapi -l emapi -l arrayutils -l timeutils -l pci -l cxlstate -l pciutils TARGET=cse all: $(TARGET) -$(TARGET): main.c options.o state.o signals.o emapi_handler.o fmapi_handler.o fmapi_isc_handler.o fmapi_psc_handler.o fmapi_vsc_handler.o fmapi_mpc_handler.o fmapi_mcc_handler.o +$(TARGET): main.c options.o state.o signals.o emapi_handler.o fmapi_handler.o fmapi_isc_handler.o fmapi_psc_handler.o fmapi_vsc_handler.o fmapi_mpc_handler.o fmapi_mcc_handler.o $(CC) $^ $(CFLAGS) $(MACROS) $(INCLUDE_PATH) $(LIB_PATH) $(LIBS) -o $@ emapi_handler.o: emapi_handler.c emapi_handler.h @@ -66,8 +68,11 @@ doc: install: $(TARGET) sudo cp $(TARGET) /usr/local/bin/ +uninstall: + sudo rm /usr/local/bin/$(TARGET) + # List all non file name targets as PHONY -.PHONY: all clean doc install +.PHONY: all clean doc install uninstall # Variables # $^ Will expand to be all the sensitivity list diff --git a/README.md b/README.md index fa6c07d..78323eb 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,109 @@ -# Install +# Overview -Install the following Linux Packages: +CXL Switch Emulator (CSE) is a software application that emulates the +management path functionality of a CXL switch. It is compliant with the CXL +Fabric Management API of the CXL 2.0 specification. All CXL FM management +commands are sent using MCTP. -- libyaml libyaml-dev doxygen uuid-dev pciutils-dev +CSE listens for connections from a Fabric Manager (FM) over TCP on a default +port of 2508. Only one remote connection is supported at a time. After a +connection is terminated by the remote Fabric Manager, CSE will wait for +another connection. -Clone the following repositories from code.jrlabs.io +# Supported Operating System Versions -- JackrabbitLabs/array_utils.git -- JackrabbitLabs/ptr_queue.git -- JackrabbitLabs/duplex_queue.git -- JackrabbitLabs/yaml_loader.git -- JackrabbitLabs/mctp.git -- JackrabbitLabs/fmapi.git -- JackrabbitLabs/cse.git -- JackrabbitLabs/jack.git +- Ubuntu 23.10 +- Fedora 38, 39 -On each repository perform the following commands (in order listed above) +> Note: Ubuntu 22.04 is not supported. This is due to some newer PCI features that +> are missing from the 5.15 Linux kernel that ships with Ubuntu 22.04. + +# Building + +1. Install OS libraries + +Install the following build packages to compile the software on the following +operating systems. + +**Ubuntu:** + +```bash +apt install build-essential libglib2.0-dev libyaml-dev libpci-dev +``` + +**Fedora:** + +```bash +``` + +2. Build Dependencies + +To clone and build dependencies run: + +```bash +./builddeps.bash +``` + +3. Build + +After building the required dependencies run: + +```bash +make +``` + +# Usage + +1. Create host directory for memory mapped files + +CSE primarily emulates the management path functionality of a CXL switch and +does not emulate PCIe/CXL data path functionality. However, some CXL FM API +management commands enable the Fabric Manager to read or write to the memory +space of CXL Type-3 devices. To emulate these commands, CSE can be configured +to instantiate memory mapped files as backing stores. This will allow a Fabric +Manager such as [Jack](https://github.com/JackrabbitLabs/jack) to write to an +arbitrary location in the memory space of a CXL Type-3 device, and then read +back the contents of those locations. + +If the user does not wish to use the CXL LD CXL.io Memory Request commands, +this step can be skipped. + +The config.yaml file has a parameter that specifies the location of a folder +in the host file system where the memory mapped files will be located. The +default location is `/cxl`. This directory must exist if the user plans to use +the CXL LD CXL.io commands. + +While the target directory (e.g. /cxl) can reside on the root file system of +the host, it is recommended to use a tmpfs file system which can be created +with the following command: + +```bash +sudo mkdir /cxl +sudo mount -t tmpfs -o size=4G,mode=1777 cxl /cxl +``` + +This should be performed *before* starting the CSE application. + +The capacity of the tmpfs file system is dependent up on how much of the CXL +Type-3 device memory space needs to be written/read. The memory mapped files +are sparse allocated and will only consume the actually written capacity on +the tmpfs file system. + +> Note: memory mapped files are only created for virtual CXL device profiles +> that have a `mmap: 1` in their profile definition in the config.yaml file. + +2. Start the CSE application + +The CSE application can be launched with the following command: + +```bash +cse -lc config.yaml +``` + +The `-l` flag will configure CSE to produce log level output that states the +commands received and actions taken. + +3. Exit + +To exit the application, type `CTRL-C`. -- make -- make install - diff --git a/builddeps.bash b/builddeps.bash new file mode 100755 index 0000000..ee66090 --- /dev/null +++ b/builddeps.bash @@ -0,0 +1,62 @@ +#!/bin/bash +# ****************************************************************************** +# +# @file builddeps.bash +# +# @brief script to clone and build dependencies +# +# @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved. +# +# @date Apr 2024 +# @author Barrett Edwards +# +# ****************************************************************************** + +ARG=$1 +CUR=`pwd` +HOST=https://github.com/ +ORG=JackrabbitLabs +REPOS="array_utils time_utils pci_utils ptr_queue yaml_loader emapi fmapi cxl_state mctp" + +SRC=src +INC=include +LIB=lib + +if [ "${ARG}" = "clean" ] ; then + echo "Removing build dependencies" + rm -rf ${SRC} + rm -rf ${INC} + rm -rf ${LIB} + exit +fi + +# Create source directory if not present +if [ ! -d ${SRC} ] ; then + mkdir ${SRC} +fi +# Create include directory if not present +if [ ! -d ${INC} ] ; then + mkdir ${INC} +fi +# Create lib directory if not present +if [ ! -d ${LIB} ] ; then + mkdir ${LIB} +fi + +# Clone sub module repos into DST directory +for REPO in $REPOS ; do + echo "Cloning build dependencies" + git clone ${HOST}${ORG}/${REPO}.git ${SRC}/${REPO} +done + +# Build sub modules +for REPO in $REPOS ; do + echo "Building dependencies" + cd ${SRC}/${REPO}/ + make INCLUDE_DIR=${CUR}/${INC} LIB_DIR=${CUR}/${LIB} CFLAGS="-g3 -O0" install + cd ${CUR} +done + +# Issue completion message +echo "Completed building dependencies" + diff --git a/emapi_handler.c b/emapi_handler.c index b6c5c14..cb5b398 100644 --- a/emapi_handler.c +++ b/emapi_handler.c @@ -44,7 +44,7 @@ #include #include #include - +#include #include "signals.h" #include "options.h" @@ -231,22 +231,22 @@ static int emop_conn_dev(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: EM API Connect Device. PPID: %d Device: %d\n", now, ppid, dev); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs - if (ppid >= cxl_state->num_ports) + if (ppid >= cxls->num_ports) { - IFV(CLVB_ERRORS) printf("%s ERR: PPID out of range. PPID: %d Total: %d\n", now, ppid, cxl_state->num_ports); + IFV(CLVB_ERRORS) printf("%s ERR: PPID out of range. PPID: %d Total: %d\n", now, ppid, cxls->num_ports); goto send; } - if (dev >= cxl_state->num_devices) + if (dev >= cxls->num_devices) { - IFV(CLVB_ERRORS) printf("%s ERR: Device ID out of range. Device ID: %d Total: %d\n", now, dev, cxl_state->num_devices); + IFV(CLVB_ERRORS) printf("%s ERR: Device ID out of range. Device ID: %d Total: %d\n", now, dev, cxls->num_devices); goto send; } - if (cxl_state->devices[dev].name == NULL) + if (cxls->devices[dev].name == NULL) { IFV(CLVB_ERRORS) printf("%s ERR: Device is NULL. Device ID: %d\n", now, dev); goto send; @@ -255,7 +255,7 @@ static int emop_conn_dev(struct mctp *m, struct mctp_action *ma) IFV(CLVB_ACTIONS) printf("%s ACT: Connecting Device %d to PPID %d\n", now, dev, ppid); STEP // 10: Perform Action - state_connect_device(&cxl_state->ports[ppid], &cxl_state->devices[dev]); + cxls_connect(&cxls->ports[ppid], &cxls->devices[dev], cxls->dir); STEP // 11: Prepare Response Object @@ -268,7 +268,7 @@ static int emop_conn_dev(struct mctp *m, struct mctp_action *ma) send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if(len < 0) goto fail; @@ -370,21 +370,21 @@ static int emop_disconn_dev(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: EM API Disconnect Device. PPID: %d All: %d\n", now, ppid, all); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs if (all) { start = 0; - end = cxl_state->num_ports; + end = cxls->num_ports; } else { start = ppid; end = ppid+1; } - if (start >= cxl_state->num_ports) + if (start >= cxls->num_ports) { - IFV(CLVB_ERRORS) printf("%s ERR: PPID out of range. PPID: %d Total: %d\n", now, ppid, cxl_state->num_ports); + IFV(CLVB_ERRORS) printf("%s ERR: PPID out of range. PPID: %d Total: %d\n", now, ppid, cxls->num_ports); goto send; } @@ -392,12 +392,12 @@ static int emop_disconn_dev(struct mctp *m, struct mctp_action *ma) for ( i = start ; i < end ; i++ ) { // Validate if port is connected - if (cxl_state->ports[i].prsnt == 1) + if (cxls->ports[i].prsnt == 1) { IFV(CLVB_ACTIONS) printf("%s ACT: Disconnecting PPID %d\n", now, i); // Perform disconnect - state_disconnect_device(&cxl_state->ports[i]); + cxls_disconnect(&cxls->ports[i]); } } @@ -412,7 +412,7 @@ static int emop_disconn_dev(struct mctp *m, struct mctp_action *ma) send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto fail; @@ -479,7 +479,7 @@ static int emop_list_dev(struct mctp *m, struct mctp_action *ma) unsigned i, count; __u8 num_requested, start_num; - struct cse_device *d; + struct cxl_device *d; ENTER @@ -518,20 +518,20 @@ static int emop_list_dev(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: EM API list Devices. Start: %d Num: %d\n", now, start_num, num_requested); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs if (num_requested == 0) - num_requested = (cxl_state->num_devices - start_num); + num_requested = (cxls->num_devices - start_num); - if (start_num >= cxl_state->num_devices) + if (start_num >= cxls->num_devices) { IFV(CLVB_ERRORS) printf("%s ERR: Start num out of range. Start: %d Total: %d\n", now, start_num, num_requested); goto send; } - if ( (start_num + num_requested) >= cxl_state->num_devices) - num_requested = (cxl_state->num_devices - start_num); + if ( (start_num + num_requested) >= cxls->num_devices) + num_requested = (cxls->num_devices - start_num); STEP // 10: Perform Action IFV(CLVB_ACTIONS) printf("%s ACT: Responding with %d devices\n", now, num_requested); @@ -539,7 +539,7 @@ static int emop_list_dev(struct mctp *m, struct mctp_action *ma) STEP // 11: Prepare Response Object for ( i = 0 ; i < num_requested ; i++ ) { - d = &cxl_state->devices[start_num + i]; + d = &cxls->devices[start_num + i]; // Serialize the id number rspb->payload[len+0] = start_num + i; @@ -565,7 +565,7 @@ static int emop_list_dev(struct mctp *m, struct mctp_action *ma) send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); STEP // 15: Fill Response Header ma->rsp->len = emapi_fill_hdr(&rspm.hdr, EMMT_RSP, reqm.hdr.tag, rc, reqm.hdr.opcode, len, count, 0); diff --git a/fmapi_handler.c b/fmapi_handler.c index 5a81c0d..76ebc0d 100644 --- a/fmapi_handler.c +++ b/fmapi_handler.c @@ -46,8 +46,6 @@ #include "options.h" -#include "state.h" - #include #include "fmapi_handler.h" diff --git a/fmapi_isc_handler.c b/fmapi_isc_handler.c index 55d59a3..7adee48 100644 --- a/fmapi_isc_handler.c +++ b/fmapi_isc_handler.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "signals.h" #include "options.h" @@ -154,18 +155,18 @@ int fmop_isc_bos(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API ISC Background Operation Status\n", now); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs STEP // 10: Perform Action STEP // 11: Prepare Response Object - rsp.obj.isc_bos.running = cxl_state->bos_running; - rsp.obj.isc_bos.pcnt = cxl_state->bos_pcnt; - rsp.obj.isc_bos.opcode = cxl_state->bos_opcode; - rsp.obj.isc_bos.rc = cxl_state->bos_rc; - rsp.obj.isc_bos.ext = cxl_state->bos_ext; + rsp.obj.isc_bos.running = cxls->bos_running; + rsp.obj.isc_bos.pcnt = cxls->bos_pcnt; + rsp.obj.isc_bos.opcode = cxls->bos_opcode; + rsp.obj.isc_bos.rc = cxls->bos_rc; + rsp.obj.isc_bos.ext = cxls->bos_ext; STEP // 12: Serialize Response Object len = fmapi_serialize(rsp.buf->payload, &rsp.obj, fmapi_fmob_rsp(req.hdr.opcode)); @@ -176,7 +177,7 @@ int fmop_isc_bos(struct mctp *m, struct mctp_action *ma) //send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; @@ -268,19 +269,19 @@ int fmop_isc_id(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API ISC Identify\n", now); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs STEP // 10: Perform Action STEP // 11: Prepare Response Object - rsp.obj.isc_id_rsp.vid = cxl_state->vid; - rsp.obj.isc_id_rsp.did = cxl_state->did; - rsp.obj.isc_id_rsp.svid = cxl_state->svid; - rsp.obj.isc_id_rsp.ssid = cxl_state->ssid; - rsp.obj.isc_id_rsp.sn = cxl_state->sn; - rsp.obj.isc_id_rsp.size = cxl_state->max_msg_size_n; + rsp.obj.isc_id_rsp.vid = cxls->vid; + rsp.obj.isc_id_rsp.did = cxls->did; + rsp.obj.isc_id_rsp.svid = cxls->svid; + rsp.obj.isc_id_rsp.ssid = cxls->ssid; + rsp.obj.isc_id_rsp.sn = cxls->sn; + rsp.obj.isc_id_rsp.size = cxls->max_msg_size_n; STEP // 12: Serialize Response Object len = fmapi_serialize(rsp.buf->payload, &rsp.obj, fmapi_fmob_rsp(req.hdr.opcode)); @@ -291,7 +292,7 @@ int fmop_isc_id(struct mctp *m, struct mctp_action *ma) //send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; @@ -383,14 +384,14 @@ int fmop_isc_msg_limit_get(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API ISC Get Response Message Limit\n", now); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs STEP // 10: Perform Action STEP // 11: Prepare Response Object - rsp.obj.isc_msg_limit.limit = cxl_state->msg_rsp_limit_n; + rsp.obj.isc_msg_limit.limit = cxls->msg_rsp_limit_n; STEP // 12: Serialize Response Object len = fmapi_serialize(rsp.buf->payload, &rsp.obj, fmapi_fmob_rsp(req.hdr.opcode)); @@ -401,7 +402,7 @@ int fmop_isc_msg_limit_get(struct mctp *m, struct mctp_action *ma) //send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; @@ -493,7 +494,7 @@ int fmop_isc_msg_limit_set(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API ISC Set Response Message Limit\n", now); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs if (req.obj.isc_msg_limit.limit < 8 || req.obj.isc_msg_limit.limit > 20) @@ -503,10 +504,10 @@ int fmop_isc_msg_limit_set(struct mctp *m, struct mctp_action *ma) } STEP // 10: Perform Action - cxl_state->msg_rsp_limit_n = req.obj.isc_msg_limit.limit; + cxls->msg_rsp_limit_n = req.obj.isc_msg_limit.limit; STEP // 11: Prepare Response Object - rsp.obj.isc_msg_limit.limit = cxl_state->msg_rsp_limit_n; + rsp.obj.isc_msg_limit.limit = cxls->msg_rsp_limit_n; STEP // 12: Serialize Response Object len = fmapi_serialize(rsp.buf->payload, &rsp.obj, fmapi_fmob_rsp(req.hdr.opcode)); @@ -519,7 +520,7 @@ int fmop_isc_msg_limit_set(struct mctp *m, struct mctp_action *ma) send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); STEP // 15: Fill Response Header ma->rsp->len = fmapi_fill_hdr(&rsp.hdr, FMMT_RESP, req.hdr.tag, req.hdr.opcode, 0, len, rc, 0); diff --git a/fmapi_mcc_handler.c b/fmapi_mcc_handler.c index c054041..87879f7 100644 --- a/fmapi_mcc_handler.c +++ b/fmapi_mcc_handler.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "signals.h" #include "options.h" @@ -108,7 +109,7 @@ * 11: Serialize Response Header * 12: Return length of MF API Message (FMLN_HDR + object) */ -int fmop_mcc_get_ld_alloc(struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) +int fmop_mcc_get_ld_alloc(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) { INIT char now[ISO_TIME_BUF_LEN]; @@ -217,7 +218,7 @@ end: * 11: Serialize Response Header * 12: Return length of MF API Message (FMLN_HDR + object) */ -int fmop_mcc_get_qos_alloc(struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) +int fmop_mcc_get_qos_alloc(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) { INIT char now[ISO_TIME_BUF_LEN]; @@ -311,7 +312,7 @@ end: * 11: Serialize Response Header * 12: Return length of MF API Message (FMLN_HDR + object) */ -int fmop_mcc_get_qos_ctrl(struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) +int fmop_mcc_get_qos_ctrl(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) { INIT char now[ISO_TIME_BUF_LEN]; @@ -404,7 +405,7 @@ end: * 11: Serialize Response Header * 12: Return length of MF API Message (FMLN_HDR + object) */ -int fmop_mcc_get_qos_limit(struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) +int fmop_mcc_get_qos_limit(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) { INIT char now[ISO_TIME_BUF_LEN]; @@ -498,7 +499,7 @@ end: * 11: Serialize Response Header * 12: Return length of MF API Message (FMLN_HDR + object) */ -int fmop_mcc_get_qos_stat(struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) +int fmop_mcc_get_qos_stat(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) { INIT char now[ISO_TIME_BUF_LEN]; @@ -584,7 +585,7 @@ end: * 11: Serialize Response Header * 12: Return length of MF API Message (FMLN_HDR + object) */ -int fmop_mcc_info(struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) +int fmop_mcc_info(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) { INIT char now[ISO_TIME_BUF_LEN]; @@ -673,7 +674,7 @@ end: * 11: Serialize Response Header * 12: Return length of MF API Message (FMLN_HDR + object) */ -int fmop_mcc_set_ld_alloc(struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) +int fmop_mcc_set_ld_alloc(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) { INIT char now[ISO_TIME_BUF_LEN]; @@ -795,7 +796,7 @@ end: * 11: Serialize Response Header * 12: Return length of MF API Message (FMLN_HDR + object) */ -int fmop_mcc_set_qos_alloc(struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) +int fmop_mcc_set_qos_alloc(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) { INIT char now[ISO_TIME_BUF_LEN]; @@ -904,7 +905,7 @@ end: * 11: Serialize Response Header * 12: Return length of MF API Message (FMLN_HDR + object) */ -int fmop_mcc_set_qos_ctrl(struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) +int fmop_mcc_set_qos_ctrl(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) { INIT char now[ISO_TIME_BUF_LEN]; @@ -1006,7 +1007,7 @@ end: * 11: Serialize Response Header * 12: Return length of MF API Message (FMLN_HDR + object) */ -int fmop_mcc_set_qos_limit(struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) +int fmop_mcc_set_qos_limit(struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp) { INIT char now[ISO_TIME_BUF_LEN]; diff --git a/fmapi_mpc_handler.c b/fmapi_mpc_handler.c index 23bb3c3..04054ec 100644 --- a/fmapi_mpc_handler.c +++ b/fmapi_mpc_handler.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "signals.h" #include "options.h" @@ -82,16 +83,16 @@ /* PROTOTYPES ================================================================*/ -int fmop_mcc_get_ld_alloc (struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); -int fmop_mcc_get_qos_alloc (struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); -int fmop_mcc_get_qos_ctrl (struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); -int fmop_mcc_get_qos_limit (struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); -int fmop_mcc_get_qos_stat (struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); -int fmop_mcc_info (struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); -int fmop_mcc_set_ld_alloc (struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); -int fmop_mcc_set_qos_alloc (struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); -int fmop_mcc_set_qos_ctrl (struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); -int fmop_mcc_set_qos_limit (struct port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); +int fmop_mcc_get_ld_alloc (struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); +int fmop_mcc_get_qos_alloc (struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); +int fmop_mcc_get_qos_ctrl (struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); +int fmop_mcc_get_qos_limit (struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); +int fmop_mcc_get_qos_stat (struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); +int fmop_mcc_info (struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); +int fmop_mcc_set_ld_alloc (struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); +int fmop_mcc_set_qos_alloc (struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); +int fmop_mcc_set_qos_ctrl (struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); +int fmop_mcc_set_qos_limit (struct cxl_port *p, struct fmapi_msg *req, struct fmapi_msg *rsp); /* GLOBAL VARIABLES ==========================================================*/ @@ -133,7 +134,7 @@ int fmop_mpc_cfg(struct mctp *m, struct mctp_action *ma) unsigned rc; int rv, len; - struct port *p; + struct cxl_port *p; __u16 reg; ENTER @@ -170,17 +171,17 @@ int fmop_mpc_cfg(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API MPC LD CXL.io Config. PPID: %d LDID: %d\n", now, req.obj.mpc_cfg_req.ppid, req.obj.mpc_cfg_req.ldid); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs // Validate port number - if (req.obj.mpc_cfg_req.ppid >= cxl_state->num_ports) + if (req.obj.mpc_cfg_req.ppid >= cxls->num_ports) { IFV(CLVB_ERRORS) printf("%s ERR: Invalid Port number requested. PPID: %d\n", now, req.obj.mpc_cfg_req.ppid); goto send; } - p = &cxl_state->ports[req.obj.mpc_cfg_req.ppid]; + p = &cxls->ports[req.obj.mpc_cfg_req.ppid]; // Validate port is not bound //if ( !(p->state == FMPS_DISABLED) ) @@ -254,7 +255,7 @@ int fmop_mpc_cfg(struct mctp *m, struct mctp_action *ma) send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; @@ -313,7 +314,7 @@ int fmop_mpc_mem(struct mctp *m, struct mctp_action *ma) unsigned rc; int rv, len; - struct port *p; + struct cxl_port *p; __u64 base, max, ld_size, granularity; ENTER @@ -350,17 +351,17 @@ int fmop_mpc_mem(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API MPC LD CXL.io Mem. PPID: %d LDID: %d\n", now, req.obj.mpc_mem_req.ppid, req.obj.mpc_mem_req.ldid); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs // Validate port number - if (req.obj.mpc_mem_req.ppid >= cxl_state->num_ports) + if (req.obj.mpc_mem_req.ppid >= cxls->num_ports) { IFV(CLVB_ERRORS) printf("%s ERR: Invalid Port number requested. PPID: %d\n", now, req.obj.mpc_mem_req.ppid); goto send; } - p = &cxl_state->ports[req.obj.mpc_mem_req.ppid]; + p = &cxls->ports[req.obj.mpc_mem_req.ppid]; // Validate port is not bound //if ( !(p->state == FMPS_DISABLED) ) @@ -453,7 +454,7 @@ int fmop_mpc_mem(struct mctp *m, struct mctp_action *ma) send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; @@ -509,7 +510,7 @@ int fmop_mpc_tmc(struct mctp *m, struct mctp_action *ma) unsigned rc; int rv, len; - struct port *p; + struct cxl_port *p; ENTER STEP // 1: Initialize variables @@ -544,7 +545,7 @@ int fmop_mpc_tmc(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API MPC Tunneled Management Command. PPID: %d\n", now, req.obj.mpc_tmc_req.ppid); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs @@ -556,12 +557,12 @@ int fmop_mpc_tmc(struct mctp *m, struct mctp_action *ma) } // Validate port number - if (req.obj.mpc_tmc_req.ppid >= cxl_state->num_ports) + if (req.obj.mpc_tmc_req.ppid >= cxls->num_ports) { IFV(CLVB_ERRORS) printf("%s Invalid Port number requested. PPID: %d\n", now, req.obj.mpc_tmc_req.ppid); goto send; } - p = &cxl_state->ports[req.obj.mpc_tmc_req.ppid]; + p = &cxls->ports[req.obj.mpc_tmc_req.ppid]; // Validate device attached to port is an MLD port if ( !(p->dt == FMDT_CXL_TYPE_3 || p->dt == FMDT_CXL_TYPE_3_POOLED) ) @@ -637,7 +638,7 @@ sub: send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; diff --git a/fmapi_psc_handler.c b/fmapi_psc_handler.c index 6c42486..7b67eda 100644 --- a/fmapi_psc_handler.c +++ b/fmapi_psc_handler.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "signals.h" #include "options.h" @@ -121,7 +122,7 @@ int fmop_psc_cfg(struct mctp *m, struct mctp_action *ma) unsigned rc; int rv, len; - struct port *p; + struct cxl_port *p; __u16 reg; ENTER @@ -158,15 +159,15 @@ int fmop_psc_cfg(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API PSC CXL.io Config. PPID: %d\n", now, req.obj.psc_cfg_req.ppid); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs - if (req.obj.psc_cfg_req.ppid >= cxl_state->num_ports) + if (req.obj.psc_cfg_req.ppid >= cxls->num_ports) { - IFV(CLVB_ERRORS) printf("%s ERR: Requested PPDI exceeds number of ports present. Requested PPID: %d Present: %d\n", now, req.obj.psc_cfg_req.ppid, cxl_state->num_ports); + IFV(CLVB_ERRORS) printf("%s ERR: Requested PPDI exceeds number of ports present. Requested PPID: %d Present: %d\n", now, req.obj.psc_cfg_req.ppid, cxls->num_ports); goto send; } - p = &cxl_state->ports[req.obj.psc_cfg_req.ppid]; + p = &cxls->ports[req.obj.psc_cfg_req.ppid]; // Validate port is not bound or is an MLD port //if ( !(p->state == FMPS_DISABLED || p->ld > 0) ) @@ -222,7 +223,7 @@ int fmop_psc_cfg(struct mctp *m, struct mctp_action *ma) send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; @@ -315,14 +316,45 @@ int fmop_psc_id(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API PSC Identify Switch Device\n", now); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs STEP // 10: Perform Action STEP // 11: Prepare Response Object - state_conv_identity(cxl_state, &rsp.obj.psc_id_rsp); + { + struct cxl_switch *cs = cxls; + struct fmapi_psc_id_rsp *fi = &rsp.obj.psc_id_rsp; + + // Zero out destination + memset(fi, 0, sizeof(*fi)); + + // Copy static information + fi->ingress_port = cs->ingress_port; //!< Ingress Port ID + fi->num_ports = cs->num_ports; //!< Total number of physical ports + fi->num_vcss = cs->num_vcss; //!< Max number of VCSs + fi->num_vppbs = cs->num_vppbs; //!< Max number of vPPBs + fi->num_decoders = cs->num_decoders; //!< Number of HDM decoders available per USP + + // Compute dynamic information + for ( int i = 0 ; i < cs->num_ports ; i++ ) { + if ( cs->ports[i].state != FMPS_DISABLED ) + fi->active_ports[i/8] |= (0x01 << (i % 8)); + } + + for ( int i = 0 ; i < cs->num_vcss ; i++ ) { + if ( cs->vcss[i].state == FMVS_ENABLED) + fi->active_vcss[i/8] |= (0x01 << (i % 8)); + } + + for ( int i = 0 ; i < cs->num_vcss ; i++ ) { + for ( int j = 0 ; j < MAX_VPPBS_PER_VCS ; j++ ) { + if ( cs->vcss[i].vppbs[j].bind_status != FMBS_UNBOUND ) + fi->active_vppbs++; + } + } + } STEP // 12: Serialize Response Object len = fmapi_serialize(rsp.buf->payload, &rsp.obj, fmapi_fmob_rsp(req.hdr.opcode)); @@ -333,7 +365,7 @@ int fmop_psc_id(struct mctp *m, struct mctp_action *ma) //send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; @@ -429,7 +461,7 @@ int fmop_psc_port(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API PSC Get Physical Port Status. Num: %d\n", now, req.obj.psc_port_req.num); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs @@ -441,11 +473,35 @@ int fmop_psc_port(struct mctp *m, struct mctp_action *ma) id = req.obj.psc_port_req.ports[i]; // Validate portid - if (id >= cxl_state->num_ports) + if (id >= cxls->num_ports) continue; // Copy the data - state_conv_port_info(&cxl_state->ports[id], &rsp.obj.psc_port_rsp.list[i]); + struct cxl_port *src = &cxls->ports[id]; + struct fmapi_psc_port_info *dst = &rsp.obj.psc_port_rsp.list[i]; + + // Zero out destination + memset(dst, 0, sizeof(*dst)); + + // Copy static information + dst->ppid = src->ppid; //!< Physical Port ID + dst->state = src->state; //!< Current Port Configuration State [FMPS] + dst->dv = src->dv; //!< Connected Device CXL Version [FMDV] + dst->dt = src->dt; //!< Connected Device Type [FMDT] + dst->cv = src->cv; //!< Connected device CXL Version [FMCV] + dst->mlw = src->mlw; //!< Max link width + dst->nlw = src->nlw; //!< Negotiated link width [FMNW] + dst->speeds = src->speeds; //!< Supported Link speeds vector [FMSS] + dst->mls = src->mls; //!< Max Link Speed [FMMS] + dst->cls = src->cls; //!< Current Link Speed [FMMS] + dst->ltssm = src->ltssm; //!< LTSSM State [FMLS] + dst->lane = src->lane; //!< First negotiated lane number + dst->lane_rev = src->lane_rev;//!< Link State Flags [FMLF] and [FMLO] + dst->perst = src->perst; //!< Link State Flags [FMLF] and [FMLO] + dst->prsnt = src->prsnt; //!< Link State Flags [FMLF] and [FMLO] + dst->pwrctrl = src->pwrctrl; //!< Link State Flags [FMLF] and [FMLO] + dst->num_ld = src->ld; //!< Supported Logical Device (LDs) count + rsp.obj.psc_port_rsp.num++; } @@ -458,7 +514,7 @@ int fmop_psc_port(struct mctp *m, struct mctp_action *ma) //send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; @@ -517,7 +573,7 @@ int fmop_psc_port_ctrl(struct mctp *m, struct mctp_action *ma) unsigned rc; int rv, len; - struct port *p; + struct cxl_port *p; ENTER @@ -553,15 +609,15 @@ int fmop_psc_port_ctrl(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API PSC Physical Port Control. PPID: %d Opcode: %d\n", now, req.obj.psc_port_ctrl_req.ppid, req.obj.psc_port_ctrl_req.opcode); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs - if (req.obj.psc_port_ctrl_req.ppid >= cxl_state->num_ports) + if (req.obj.psc_port_ctrl_req.ppid >= cxls->num_ports) { - IFV(CLVB_ERRORS) printf("%s ERR: Requested PPID exceeds number of ports present. Requested PPID: %d Present: %d\n", now, req.obj.psc_port_ctrl_req.ppid, cxl_state->num_ports); + IFV(CLVB_ERRORS) printf("%s ERR: Requested PPID exceeds number of ports present. Requested PPID: %d Present: %d\n", now, req.obj.psc_port_ctrl_req.ppid, cxls->num_ports); goto send; } - p = &cxl_state->ports[req.obj.psc_port_ctrl_req.ppid]; + p = &cxls->ports[req.obj.psc_port_ctrl_req.ppid]; STEP // 10: Perform Action switch (req.obj.psc_port_ctrl_req.opcode) @@ -599,7 +655,7 @@ int fmop_psc_port_ctrl(struct mctp *m, struct mctp_action *ma) send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; diff --git a/fmapi_vsc_handler.c b/fmapi_vsc_handler.c index 0c7fd0a..bd6571d 100644 --- a/fmapi_vsc_handler.c +++ b/fmapi_vsc_handler.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "signals.h" #include "options.h" @@ -121,7 +122,7 @@ int fmop_vsc_aer(struct mctp *m, struct mctp_action *ma) unsigned rc; int rv, len; - struct vcs *v; + struct cxl_vcs *v; ENTER @@ -157,15 +158,15 @@ int fmop_vsc_aer(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API VSC Generate AER Event. VCSID: %d vPPBID: %d\n", now, req.obj.vsc_aer_req.vcsid, req.obj.vsc_aer_req.vppbid); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs - if (req.obj.vsc_aer_req.vcsid >= cxl_state->num_vcss) + if (req.obj.vsc_aer_req.vcsid >= cxls->num_vcss) { - IFV(CLVB_ERRORS) printf("%s ERR: Requested VCSID exceeds number of VCSs present. Requested VCSID: %d Present: %d\n", now, req.obj.vsc_aer_req.vcsid, cxl_state->num_vcss); + IFV(CLVB_ERRORS) printf("%s ERR: Requested VCSID exceeds number of VCSs present. Requested VCSID: %d Present: %d\n", now, req.obj.vsc_aer_req.vcsid, cxls->num_vcss); goto send; } - v = &cxl_state->vcss[req.obj.vsc_aer_req.vcsid]; + v = &cxls->vcss[req.obj.vsc_aer_req.vcsid]; // Validate vppbid if (req.obj.vsc_aer_req.vppbid >= v->num) @@ -188,7 +189,7 @@ int fmop_vsc_aer(struct mctp *m, struct mctp_action *ma) send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; @@ -247,9 +248,9 @@ int fmop_vsc_bind(struct mctp *m, struct mctp_action *ma) unsigned rc; int rv, len; - struct vcs *v; - struct vppb *b; - struct port *p; + struct cxl_vcs *v; + struct cxl_vppb *b; + struct cxl_port *p; ENTER @@ -285,20 +286,20 @@ int fmop_vsc_bind(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API VSC Bind vPPB. VCSID: %d vPPBID: %d PPID: %d LDID: 0x%04x\n", now, req.obj.vsc_bind_req.vcsid, req.obj.vsc_bind_req.vppbid, req.obj.vsc_bind_req.ppid, req.obj.vsc_bind_req.ldid); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs // Validate vcsid - if (req.obj.vsc_bind_req.vcsid >= cxl_state->num_vcss) + if (req.obj.vsc_bind_req.vcsid >= cxls->num_vcss) { IFV(CLVB_ERRORS) printf("%s ERR: VCS ID out of range. VCSID: %d\n", now, req.obj.vsc_bind_req.vcsid); goto send; } - v = &cxl_state->vcss[req.obj.vsc_bind_req.vcsid]; + v = &cxls->vcss[req.obj.vsc_bind_req.vcsid]; // Validate vppbid - if (req.obj.vsc_bind_req.vppbid >= cxl_state->vcss[req.obj.vsc_bind_req.vcsid].num) + if (req.obj.vsc_bind_req.vppbid >= cxls->vcss[req.obj.vsc_bind_req.vcsid].num) { IFV(CLVB_ERRORS) printf("%s ERR: vPPB ID out of range. vPPBID: %d\n", now, req.obj.vsc_bind_req.vppbid); goto send; @@ -306,12 +307,12 @@ int fmop_vsc_bind(struct mctp *m, struct mctp_action *ma) b = &v->vppbs[req.obj.vsc_bind_req.vppbid]; // Validate port id - if (req.obj.vsc_bind_req.ppid >= cxl_state->num_ports) + if (req.obj.vsc_bind_req.ppid >= cxls->num_ports) { IFV(CLVB_ERRORS) printf("%s ERR: PPID ID out of range. PPID: %d\n", now, req.obj.vsc_bind_req.ppid); goto send; } - p = &cxl_state->ports[req.obj.vsc_bind_req.ppid]; + p = &cxls->ports[req.obj.vsc_bind_req.ppid]; // Check bindability to this port @@ -371,11 +372,11 @@ int fmop_vsc_bind(struct mctp *m, struct mctp_action *ma) p->state = FMPS_DSP; // Update Background Operation Status - cxl_state->bos_running = 0; - cxl_state->bos_pcnt = 100; - cxl_state->bos_opcode = req.hdr.opcode; - cxl_state->bos_rc = FMRC_SUCCESS; - cxl_state->bos_ext = 0; + cxls->bos_running = 0; + cxls->bos_pcnt = 100; + cxls->bos_opcode = req.hdr.opcode; + cxls->bos_rc = FMRC_SUCCESS; + cxls->bos_ext = 0; STEP // 11: Prepare Response Object @@ -388,7 +389,7 @@ int fmop_vsc_bind(struct mctp *m, struct mctp_action *ma) send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; @@ -447,7 +448,7 @@ int fmop_vsc_info(struct mctp *m, struct mctp_action *ma) unsigned rc; int rv, len; - struct vcs *v; + struct cxl_vcs *v; unsigned i, k, stop, vppbid_start, vppbid_limit; struct fmapi_vsc_info_blk *blk; __u8 id; @@ -486,7 +487,7 @@ int fmop_vsc_info(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API VSC Get Virtual Switch Info. Num: %d\n", now, req.obj.vsc_info_req.num); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs @@ -505,11 +506,11 @@ int fmop_vsc_info(struct mctp *m, struct mctp_action *ma) break; // Skip VCS IDs that exceed current size - if (id >= cxl_state->num_vcss) + if (id >= cxls->num_vcss) continue; // Get pointers to objects to copy - v = &cxl_state->vcss[id]; // The struct vcs to copy from + v = &cxls->vcss[id]; // The struct vcs to copy from blk = &rsp.obj.vsc_info_rsp.list[i]; // The struct fmapi_vcs_info_blk to copy into // Zero out destination @@ -546,7 +547,7 @@ int fmop_vsc_info(struct mctp *m, struct mctp_action *ma) //send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; @@ -605,9 +606,9 @@ int fmop_vsc_unbind(struct mctp *m, struct mctp_action *ma) unsigned rc; int rv, len; - struct vcs *v; - struct vppb *b; - struct port *p; + struct cxl_vcs *v; + struct cxl_vppb *b; + struct cxl_port *p; ENTER @@ -643,20 +644,20 @@ int fmop_vsc_unbind(struct mctp *m, struct mctp_action *ma) IFV(CLVB_COMMANDS) printf("%s CMD: FM API VSC Unbind vPPB. VCSID: %d vPPBID: %d\n", now, req.obj.vsc_unbind_req.vcsid, req.obj.vsc_unbind_req.vppbid); STEP // 8: Obtain lock on switch state - pthread_mutex_lock(&cxl_state->mtx); + pthread_mutex_lock(&cxls->mtx); STEP // 9: Validate Inputs // Validate vcsid - if (req.obj.vsc_unbind_req.vcsid >= cxl_state->num_vcss) + if (req.obj.vsc_unbind_req.vcsid >= cxls->num_vcss) { IFV(CLVB_ERRORS) printf("%s ERR: VCS ID out of range. VCSID: %d\n", now, req.obj.vsc_unbind_req.vcsid); goto send; } - v = &cxl_state->vcss[req.obj.vsc_unbind_req.vcsid]; + v = &cxls->vcss[req.obj.vsc_unbind_req.vcsid]; // Validate vppbid - if (req.obj.vsc_unbind_req.vppbid >= cxl_state->vcss[req.obj.vsc_unbind_req.vcsid].num) + if (req.obj.vsc_unbind_req.vppbid >= cxls->vcss[req.obj.vsc_unbind_req.vcsid].num) { IFV(CLVB_ERRORS) printf("%s ERR: vPPB ID out of range. vPPBID: %d\n", now, req.obj.vsc_unbind_req.vppbid); goto send; @@ -671,13 +672,13 @@ int fmop_vsc_unbind(struct mctp *m, struct mctp_action *ma) } // Validate port id that the vppb was bound to - if (b->ppid >= cxl_state->num_ports) + if (b->ppid >= cxls->num_ports) { IFV(CLVB_ERRORS) printf("%s ERR: PPID of bound port out of range. PPID: %d\n", now, b->ppid); b->bind_status = FMBS_UNBOUND; goto send; } - p = &cxl_state->ports[b->ppid]; + p = &cxls->ports[b->ppid]; // Check bindability to this port @@ -697,11 +698,11 @@ int fmop_vsc_unbind(struct mctp *m, struct mctp_action *ma) b->ldid = 0; // Update Background Operation Status - cxl_state->bos_running = 0; - cxl_state->bos_pcnt = 100; - cxl_state->bos_opcode = req.hdr.opcode; - cxl_state->bos_rc = FMRC_SUCCESS; - cxl_state->bos_ext = 0; + cxls->bos_running = 0; + cxls->bos_pcnt = 100; + cxls->bos_opcode = req.hdr.opcode; + cxls->bos_rc = FMRC_SUCCESS; + cxls->bos_ext = 0; STEP // 11: Prepare Response Object @@ -714,7 +715,7 @@ int fmop_vsc_unbind(struct mctp *m, struct mctp_action *ma) send: STEP // 14: Release lock on switch state - pthread_mutex_unlock(&cxl_state->mtx); + pthread_mutex_unlock(&cxls->mtx); if (len < 0) goto end; diff --git a/main.c b/main.c index 731a7fb..9d826d6 100644 --- a/main.c +++ b/main.c @@ -35,6 +35,7 @@ * mctp_run() */ #include +#include #include "signals.h" @@ -65,6 +66,10 @@ #define IFV(u) if (opts[CLOP_VERBOSITY].u64 & u) +#define CSLN_PORTS 32 +#define CSLN_VCSS 32 +#define CSLN_VPPBS 256 + /* ENUMERATIONS ==============================================================*/ /* STRUCTS ===================================================================*/ @@ -97,6 +102,7 @@ int main(int argc, char* argv[]) struct mctp *m; // Initialize varaibles + cxls = NULL; stop_requested = 0; rv = 1; @@ -112,8 +118,8 @@ int main(int argc, char* argv[]) signals_register(); STEP // 2: Initialize global state array - cxl_state = state_init(32, 32, 256); - if (cxl_state == NULL) + cxls = cxls_init(CSLN_PORTS, CSLN_VCSS, CSLN_VPPBS); + if (cxls == NULL) { printf("Error: state init failed \n"); goto end_options; @@ -122,7 +128,7 @@ int main(int argc, char* argv[]) STEP // 3: Load state file if (opts[CLOP_CONFIG_FILE].set) { - rv = state_load(cxl_state, opts[CLOP_CONFIG_FILE].str); + rv = state_load(cxls, opts[CLOP_CONFIG_FILE].str); if (rv < 0) { printf("Error: state load config file failed \n"); @@ -130,11 +136,13 @@ int main(int argc, char* argv[]) } } - STEP // 4: Print the state +// STEP // 4: Build PCI Representation + + STEP // 5: Print the state if (opts[CLOP_PRINT_STATE].set) - state_print(cxl_state); + cxls_prnt(cxls); - STEP // 5: MCTP Init + STEP // 6: MCTP Init m = mctp_init(); if (m == NULL) goto end_state; @@ -150,7 +158,7 @@ int main(int argc, char* argv[]) // Set MCTP verbosity levels mctp_set_verbosity(m, opts[CLOP_MCTP_VERBOSITY].u64); - STEP // 6: Run MCTP + STEP // 7: Run MCTP rv = mctp_run(m, opts[CLOP_TCP_PORT].u16, opts[CLOP_TCP_ADDRESS].u32, MCRM_SERVER, 1, 1); if (rv != 0) { @@ -175,13 +183,13 @@ int main(int argc, char* argv[]) goto end_mctp; } - STEP // 7: While loop + STEP // 8: While loop while ( stop_requested == 0 ) { sleep(1); } - STEP // 8: Stop MCTP + STEP // 9: Stop MCTP mctp_stop(m); end_mctp: @@ -192,7 +200,7 @@ end_mctp: end_state: - state_free(cxl_state); + cxls_free(cxls); end_options: diff --git a/state.c b/state.c index eeb78f7..d42a806 100644 --- a/state.c +++ b/state.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 */ /** * @file state.c - * +cxl_ * * @brief Code file to manage the CXL switch state * * @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved. @@ -56,7 +56,7 @@ #include #include - +#include #include #include "options.h" @@ -91,11 +91,11 @@ /* PROTOTYPES ================================================================*/ -int state_load_devices(struct cxl_switch_state *state, GHashTable *ht); -int state_load_emulator(struct cxl_switch_state *state, GHashTable *ht); -int state_load_ports(struct cxl_switch_state *state, GHashTable *ht); -int state_load_switch(struct cxl_switch_state *state, GHashTable *ht); -int state_load_vcss(struct cxl_switch_state *state, GHashTable *ht); +int state_load_devices(struct cxl_switch *state, GHashTable *ht); +int state_load_emulator(struct cxl_switch *state, GHashTable *ht); +int state_load_ports(struct cxl_switch *state, GHashTable *ht); +int state_load_switch(struct cxl_switch *state, GHashTable *ht); +int state_load_vcss(struct cxl_switch *state, GHashTable *ht); void _parse_devices(gpointer key, gpointer value, gpointer user_data); void _parse_device(gpointer key, gpointer value, gpointer user_data); @@ -120,399 +120,14 @@ void state_print_pcie_cfg_space(__u8 *cfgspace, unsigned indent); /** * Global pointer to CXL Switch State */ -struct cxl_switch_state *cxl_state; +struct cxl_switch *cxls; /* FUNCTIONS =================================================================*/ -/** - * Convert state representation to fmapi representation for FM API Identify Switch Device - * - * @param[in] cs struct cxl_switch_state* to pull info from - * @param[out] fi struct fmapi_psc_ident* to put info into - */ -void state_conv_identity(struct cxl_switch_state *cs, struct fmapi_psc_id_rsp *fi) -{ - // Zero out destination - memset(fi, 0, sizeof(*fi)); - - // Copy static information - fi->ingress_port = cs->ingress_port; //!< Ingress Port ID - fi->num_ports = cs->num_ports; //!< Total number of physical ports - fi->num_vcss = cs->num_vcss; //!< Max number of VCSs - fi->num_vppbs = cs->num_vppbs; //!< Max number of vPPBs - fi->num_decoders = cs->num_decoders; //!< Number of HDM decoders available per USP - - // Compute dynamic information - for ( int i = 0 ; i < cs->num_ports ; i++ ) { - if ( cs->ports[i].state != FMPS_DISABLED ) - fi->active_ports[i/8] |= (0x01 << (i % 8)); - } - - for ( int i = 0 ; i < cs->num_vcss ; i++ ) { - if ( cs->vcss[i].state == FMVS_ENABLED) - fi->active_vcss[i/8] |= (0x01 << (i % 8)); - } - - for ( int i = 0 ; i < cs->num_vcss ; i++ ) { - for ( int j = 0 ; j < MAX_VPPBS_PER_VCS ; j++ ) { - if ( cs->vcss[i].vppbs[j].bind_status != FMBS_UNBOUND ) - fi->active_vppbs++; - } - } -} - -/** - * Convert state representation to fmapi representation for FM API Phy Port State Response - * - * @param[in] src struct cxl_switch_state* to pull info from - * @param[out] dst struct fmapi_psc_port_info* to put info into - */ -void state_conv_port_info(struct port *src, struct fmapi_psc_port_info *dst) -{ - // Zero out destination - memset(dst, 0, sizeof(*dst)); - - // Copy static information - dst->ppid = src->ppid; //!< Physical Port ID - dst->state = src->state; //!< Current Port Configuration State [FMPS] - dst->dv = src->dv; //!< Connected Device CXL Version [FMDV] - dst->dt = src->dt; //!< Connected Device Type [FMDT] - dst->cv = src->cv; //!< Connected device CXL Version [FMCV] - dst->mlw = src->mlw; //!< Max link width - dst->nlw = src->nlw; //!< Negotiated link width [FMNW] - dst->speeds = src->speeds; //!< Supported Link speeds vector [FMSS] - dst->mls = src->mls; //!< Max Link Speed [FMMS] - dst->cls = src->cls; //!< Current Link Speed [FMMS] - dst->ltssm = src->ltssm; //!< LTSSM State [FMLS] - dst->lane = src->lane; //!< First negotiated lane number - dst->lane_rev = src->lane_rev;//!< Link State Flags [FMLF] and [FMLO] - dst->perst = src->perst; //!< Link State Flags [FMLF] and [FMLO] - dst->prsnt = src->prsnt; //!< Link State Flags [FMLF] and [FMLO] - dst->pwrctrl = src->pwrctrl; //!< Link State Flags [FMLF] and [FMLO] - dst->num_ld = src->ld; //!< Supported Logical Device (LDs) count -} - -/** - * Convert state representation to fmapi representation for FM API Get Virtual CXL Switch info - * - * @param[in] src struct cxl_switch_state* to pull info from - * @param[out] dst struct fmapi_psc_port_info* to put info into - */ -void state_conv_vcs_info(struct vcs *src, struct fmapi_vsc_info_blk *dst) -{ - // Zero out destination - memset(dst, 0, sizeof(*dst)); - - // Copy static information - dst->vcsid = src->vcsid; //!< Virtual CXL Switch ID - dst->state = src->state; //!< VCS State [FMVS] - dst->uspid = src->uspid; //!< USP ID. Upstream physical port ID - dst->num = src->num; //!< Number of vPPBs - - //!< Variable array of PPB Status Blocksa - for (int i = 0 ; i < dst->num ; i++) { - dst->list[i].status = src->vppbs[i].bind_status; - dst->list[i].ppid = src->vppbs[i].ppid; - dst->list[i].ldid = src->vppbs[i].ldid; - } -} - -/** - * Free memory allocated by the CXL Switch State - * - * STEPS: - * 1: Destroy Mutex - * 2: Free pci config space memory - * 3: Free Port MLD config space - * 4: unmap memory space if present - * 5: Free Port MLD - * 6: Free VCSs - * 7: Free ports - * 8: Free devices - * 9: Free Switch State - */ -void state_free(struct cxl_switch_state *state) -{ - INIT - unsigned i, k; - struct port *p; - struct cse_device *d; - - ENTER - - if (state == NULL) - return; - - STEP // 1: Destroy mutex - pthread_mutex_destroy(&state->mtx); - - STEP // 2: Free pci config space memory - for ( i = 0 ; i < state->num_ports ; i++ ) - { - p = &state->ports[i]; - if ( p->cfgspace != NULL ) - { - free(p->cfgspace); - p->cfgspace = NULL; - } - } - - STEP // 3: Free Port MLD config space - for ( i = 0 ; i < state->num_ports ; i++ ) - { - p = &state->ports[i]; - if (p->mld != NULL) - { - for ( k = 0 ; k < MAX_LD ; k++ ) - { - if ( p->mld->cfgspace[k] != NULL ) - { - free(p->mld->cfgspace[k]); - p->mld->cfgspace[k] = NULL; - } - } - } - } - - STEP // 4: unmap memory space if present - for ( i = 0 ; i < state->num_ports ; i++ ) - { - p = &state->ports[i]; - if (p->mld != NULL) - { - if (p->mld->memspace != NULL) - { - munmap(p->mld->memspace, p->mld->memory_size); - p->mld->memspace = NULL; - } - - if (p->mld->file != NULL) - { - free(p->mld->file); - p->mld->file = NULL; - } - } - } - - STEP // 5: Free Port MLD - for ( i = 0 ; i < state->num_ports ; i++ ) - { - p = &state->ports[i]; - if (p->mld != NULL) - { - free(p->mld); - p->mld = NULL; - } - } - - STEP // 6: Free VCSs - if (state->vcss != NULL) - { - free(state->vcss); - state ->vcss = NULL; - } - - STEP // 7: Free Ports - if (state->ports != NULL) - { - free(state->ports); - state->ports = NULL; - } - - STEP // 8: Free devices - if (state->devices != NULL ) - { - for ( i = 0 ; i < state->len_devices ; i++ ) - { - d = &state->devices[i]; - - // Free device name string if present - if (d->name != NULL) - { - free(d->name); - d->name = NULL; - } - - // Free device pcie config space if present - if (d->cfgspace != NULL) - { - free(d->cfgspace); - d->cfgspace = NULL; - } - - // Free device MLD if present - if (d->mld != NULL) - { - free(d->mld); - d->mld = NULL; - } - } - - free(state->devices); - state->devices = NULL; - } - state->len_devices = 0; - state->num_devices = 0; - - STEP // 9: Free Switch State - if (state->dir != NULL) - { - free(state->dir); - state->dir = NULL; - } - - free(state); - state = NULL; - - EXIT(0) -} - -/** - * Initialize state object with default values - * - * @return struct state. Returns 0 upon error and sets errno - * - * STEPS - * 1: Validate inputs - * 2: Initalize State Identity - * 3: Initalize Ports - * 4: Initalize VCSs - * 5: Initalize PCIe config space register - */ -struct cxl_switch_state *state_init(unsigned ports, unsigned vcss, unsigned vppbs) -{ - INIT - unsigned i; - struct port *p; - struct vcs *v; - struct cxl_switch_state *state; - - ENTER - - STEP // 1: Validate inputs - if (ports > MAX_PORTS) - ports = MAX_PORTS; - if (vcss > MAX_VCSS) - vcss = MAX_VCSS; - if (vppbs > MAX_VPPBS) - vppbs = MAX_VPPBS; - - STEP // 2: Initalize State Identity - state = calloc(1, sizeof(struct cxl_switch_state)); - if(state == NULL) { - errno = ENOMEM; - goto end; - } - - // Initialize Identity information - state->version = 1; - state->vid = 0xb1b2; - state->did = 0xc1c2; - state->svid = 0xd1d2; - state->ssid = 0xe1e2; - state->sn = 0xa1a2a3a4a5a6a7a8; - state->ingress_port = 1; - state->num_ports = ports; - state->num_vcss = vcss; - state->num_vppbs = vppbs; - state->num_decoders = 42; - - // Initialize Mutex - pthread_mutex_init(&state->mtx, NULL); - - STEP // 3: Initalize Ports - state->ports = calloc(ports, sizeof(struct port)); - if(state->ports == NULL) { - errno = ENOMEM; - goto end_state; - } - - // Set default port values - for ( i = 0 ; i < ports ; i++ ) { - p = &state->ports[i]; - p->ppid = i; - p->state = FMPS_DISABLED; - p->dv = FMDV_NOT_CXL; - p->dt = FMDT_NONE; - p->cv = 0; - p->mlw = 16; - p->nlw = 0; - p->speeds = FMSS_PCIE5 | FMSS_PCIE4 | FMSS_PCIE3 | FMSS_PCIE2 | FMSS_PCIE1; - p->mls = FMMS_PCIE5; - p->cls = 0; - p->ltssm = FMLS_DISABLED; - p->lane = 0; - p->lane_rev = 0; - p->perst = 0; - p->prsnt = 0; - p->pwrctrl = 0; - p->ld = 0; - } - - STEP // 4: Initalize VCSs - state->vcss = calloc(vcss, sizeof(struct vcs)); - if(state->vcss == NULL) { - errno = ENOMEM; - goto end_ports; - } - - // Set default vcs values - for ( i = 0 ; i < vcss ; i++) { - v = &state->vcss[i]; - v->vcsid = i; - v->state = FMVS_DISABLED; - v->uspid = 0; - v->num = 0; - - // Set the vcs->vppb[] array to zero - memset(v->vppbs, 0, MAX_VPPBS_PER_VCS * sizeof(struct vppb)); - } - - STEP // 5: Initalize PCIe config space register - for ( i = 0 ; i < ports ; i++ ) - { - state->ports[i].cfgspace = calloc(1, CFG_SPACE_SIZE); - if(state->vcss == NULL) { - errno = ENOMEM; - goto end_cfgspace; - } - } - - goto end; - -end_cfgspace: - - for ( i = 0 ; i < ports ; i++ ) { - if( cxl_state->ports[i].cfgspace != NULL ) { - free(cxl_state->ports[i].cfgspace); - cxl_state->ports[i].cfgspace = NULL; - } - } - - free(state->vcss); - state->vcss = NULL; - -end_ports: - - free(state->ports); - state->ports = NULL; - -end_state: - - free(state); - state = NULL; - -end: - - EXIT(0) - - return state; -} - /** * Load config file and update state * - * @param state struct cxl_switch_state to fill + * @param state struct cxl_switch to fill * @param filename char * to yaml config file to load * @return Returns 0 on success, error code otherwise * @@ -526,7 +141,7 @@ end: * 7: Parse VCSs * 8: Free memory allocated for hash table */ -int state_load(struct cxl_switch_state *state, char *filename) +int state_load(struct cxl_switch *state, char *filename) { INIT int rv; @@ -602,7 +217,7 @@ end: * 2: Allocate memory for devices in state * 3: Parse each entry in the hash table */ -int state_load_devices(struct cxl_switch_state *state, GHashTable *ht) +int state_load_devices(struct cxl_switch *state, GHashTable *ht) { INIT int rv; @@ -619,7 +234,7 @@ int state_load_devices(struct cxl_switch_state *state, GHashTable *ht) goto end; STEP // 2: Allocate memory for devices in state - state->devices = calloc(INITIAL_NUM_DEVICES, sizeof(struct cse_device)); + state->devices = calloc(INITIAL_NUM_DEVICES, sizeof(struct cxl_device)); if (state->devices == NULL) goto end; state->len_devices = INITIAL_NUM_DEVICES; @@ -646,7 +261,7 @@ end: * 1: Obtain hash table * 2: Parse each entry in the hash table */ -int state_load_emulator(struct cxl_switch_state *state, GHashTable *ht) +int state_load_emulator(struct cxl_switch *state, GHashTable *ht) { INIT int rv; @@ -686,13 +301,13 @@ end: * 3: Parse each entry in the hash table * 4: Instantiate each port device */ -int state_load_ports(struct cxl_switch_state *state, GHashTable *ht) +int state_load_ports(struct cxl_switch *state, GHashTable *ht) { INIT int rv; unsigned i, k; yl_obj_t *ylo; - struct port *port; + struct cxl_port *port; ENTER @@ -733,7 +348,7 @@ int state_load_ports(struct cxl_switch_state *state, GHashTable *ht) for ( k = 0 ; k < state->num_devices ; k++ ) if (state->devices[k].name != NULL) if ( !strcmp(state->devices[k].name, port->device_name) ) - state_connect_device(port, &state->devices[k]); + cxls_connect(port, &state->devices[k], cxls->dir); } rv = 0; @@ -755,7 +370,7 @@ end: * 1: Obtain hash table * 2: Parse each entry in the hash table */ -int state_load_switch(struct cxl_switch_state *state, GHashTable *ht) +int state_load_switch(struct cxl_switch *state, GHashTable *ht) { INIT int rv; @@ -793,7 +408,7 @@ end: * 1: Obtain hash table * 2: Parse each entry in the hash table */ -int state_load_vcss(struct cxl_switch_state *state, GHashTable *ht) +int state_load_vcss(struct cxl_switch *state, GHashTable *ht) { INIT int rv; @@ -821,215 +436,6 @@ end: return rv; } -/** - * Copy data from a device definition to a port - * - * @param p struct port* to fill with data - * @param d struct cse_device* to pull the data from - * - * STEPS: - * 1: Copy basic parameters - * 2: Copy PCIe config space to the port - * 3: Copy MLD information if present - * 4: Memory Map a file if requested by the device profile - */ -int state_connect_device(struct port *p, struct cse_device *d) -{ - INIT - int rv; - unsigned i; - char filename[MAX_FILE_NAME_LEN]; - FILE *fp; - - ENTER - - // Initialize variables - rv = 1; - - // Validate Inputs - if (d->name == NULL) - goto end; - - STEP // 1: Copy basic parameters - p->dv = d->dv; - p->dt = d->dt; - p->cv = d->cv; - p->ltssm = FMLS_L0; - p->lane = 0; - p->lane_rev = 0; - p->perst = 0; - p->pwrctrl = 0; - p->ld = 0; - - // If the device definition says this is a rootport then set as an Upstream Port - if( d->rootport == 1 ) - p->state = FMPS_USP; - else - p->state = FMPS_DSP; - - // Pick the lower of the two widths - if (d->mlw < p->mlw) - p->nlw = d->mlw << 4; - else - p->nlw = p->mlw << 4; - - // Pick the lower of the two speeds - if (d->mls < p->mls) - p->cls = d->mls; - else - p->cls = p->mls; - - // Set present bit - p->prsnt = 1; - - STEP // 2: Copy PCIe config space to the port - memcpy(p->cfgspace, d->cfgspace, CFG_SPACE_SIZE); - - STEP // 3: Copy MLD information if present - if (d->mld != NULL) - { - p->ld = d->mld->num; - - // Allocate memory for MLD object in the port - p->mld = malloc(sizeof(struct mld)); - - // Copy MLD from device definition to port - memcpy(p->mld, d->mld, sizeof(struct mld)); - - for ( i = 0 ; i < d->mld->num ; i++ ) - { - // Allocate memory for each LD pcie config space - p->mld->cfgspace[i] = malloc(CFG_SPACE_SIZE); - - // Copy PCIe config space from device definition to port - memcpy(p->mld->cfgspace[i], d->cfgspace, CFG_SPACE_SIZE); - } - } - - STEP // 4: Memory Map a file if requested by the device profile - if (d->mld != NULL && d->mld->mmap == 1) - { - // Prepare filename - sprintf(filename, "%s/port%02d", cxl_state->dir, p->ppid); - - // Create file - fp = fopen(filename, "w+"); - if (fp == NULL) { - printf("Error: Could not open file: %s\n", filename); - goto end; - } - - // Truncate file to desired length - rv = ftruncate(fileno(fp), p->mld->memory_size); - if (rv != 0) { - printf("Error: Could not truncate file. Memory Size: 0x%llx errno: %d\n", p->mld->memory_size, errno); - goto end; - } - - // mmap file - p->mld->memspace = mmap(NULL, p->mld->memory_size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(fp), 0); - if (p->mld->memspace == NULL) { - printf("Error: Could not mmap the file. errno: %d\n", errno); - rv = 1; - goto end; - } - - // Save the filename to the port mld object - p->mld->file = strdup(filename); - - // Close file - fclose(fp); - - } - - rv = 0; - -end: - - return rv; -} - -/** - * Clear / Free data from a port device definition - * - * This function essemtially makes it appear as if the device has been removed from the slot - * - * @param p struct port* The port to clear of values - * - * STEPS: - * 1: Clear basic parameters - * 2: Clear PCIe config space - * 3: Free device name - * 4: Unmemmap MLD if present - * 5: Free PCIe cfg space for each ld - * 6: Free MLD if present - */ -int state_disconnect_device(struct port *p) -{ - INIT - int rv; - unsigned i; - - ENTER - - // Initialize variables - rv = 1; - - STEP // 1: Clear basic parameters - p->dv = 0; - p->dt = 0; - p->cv = 0; - p->nlw = 0; - p->cls = 0; - p->ltssm = 0; - p->lane = 0; - p->lane_rev = 0; - p->perst = 0; - p->prsnt = 0; - p->pwrctrl = 0; - p->ld = 0; - - STEP // 2: Clear PCIe config space - memset(p->cfgspace, 0, CFG_SPACE_SIZE); - - STEP // 3: Free device name - if (p->device_name != NULL) - { - free(p->device_name); - p->device_name = NULL; - } - - STEP // 4: Unmemmap MLD if present - if (p->mld != NULL && p->mld->memspace != NULL) - { - msync (p->mld->memspace, p->mld->memory_size, MS_SYNC); - munmap(p->mld->memspace, p->mld->memory_size); - p->mld->memspace = NULL; - } - - STEP // 5: Free PCIe cfg space for each ld - if (p->mld != NULL) - { - for ( i = 0 ; i < p->mld->num ; i++ ) { - if ( p->mld->cfgspace[i] != NULL ) { - free(p->mld->cfgspace[i]); - p->mld->cfgspace[i] = NULL; - } - } - } - - STEP // 6: Free MLD if present - if (p->mld != NULL) - { - free(p->mld); - p->mld = NULL; - } - - rv = 0; - - return rv; -} - /** * Function to parse a device entry in the hash table * @@ -1042,7 +448,7 @@ int state_disconnect_device(struct port *p) void _parse_devices(gpointer key, gpointer value, gpointer user_data) { INIT - struct cxl_switch_state *s; + struct cxl_switch *s; yl_obj_t *ylo, *ylo_did; unsigned did; void * ptr; @@ -1051,7 +457,7 @@ void _parse_devices(gpointer key, gpointer value, gpointer user_data) // Initialize varialbes ylo = (yl_obj_t*) value; - s = (struct cxl_switch_state*) user_data; + s = (struct cxl_switch*) user_data; IFV(CLVB_PARSE) printf("%d:%s Key: %s\n", gettid(), __FUNCTION__, (char*) key); @@ -1066,10 +472,10 @@ void _parse_devices(gpointer key, gpointer value, gpointer user_data) if (s->num_devices >= s->len_devices) { // Allocate more memory - ptr = calloc(s->len_devices + INITIAL_NUM_DEVICES, sizeof(struct cse_device)); + ptr = calloc(s->len_devices + INITIAL_NUM_DEVICES, sizeof(struct cxl_device)); // Copy the existing data to new buffer - memcpy(ptr, s->devices, s->num_devices * sizeof(struct cse_device)); + memcpy(ptr, s->devices, s->num_devices * sizeof(struct cxl_device)); // free old buffer free(s->devices); @@ -1103,7 +509,7 @@ void _parse_device(gpointer key, gpointer value, gpointer user_data) { INIT int rv; - struct cse_device *d; + struct cxl_device *d; yl_obj_t *ylo; ENTER @@ -1111,7 +517,7 @@ void _parse_device(gpointer key, gpointer value, gpointer user_data) // Initialize varialbes rv = 1; ylo = (yl_obj_t*) value; - d = (struct cse_device*) user_data; + d = (struct cxl_device*) user_data; STEP // 1: Verify the yaml loader object hash table is not NULL if (ylo->ht == NULL) @@ -1134,7 +540,7 @@ void _parse_device(gpointer key, gpointer value, gpointer user_data) { // Allocate memory for MLD struct if (d->mld == NULL) - d->mld = calloc(1, sizeof(struct mld)); + d->mld = calloc(1, sizeof(struct cxl_mld)); g_hash_table_foreach(ylo->ht, _parse_device_mld, d->mld); } @@ -1157,7 +563,7 @@ void _parse_device_mld(gpointer key, gpointer value, gpointer user_data) { INIT int rv; - struct mld *mld; + struct cxl_mld *mld; yl_obj_t *ylo; ENTER @@ -1165,7 +571,7 @@ void _parse_device_mld(gpointer key, gpointer value, gpointer user_data) // Initialize varialbes rv = 1; ylo = (yl_obj_t*) value; - mld = (struct mld*) user_data; + mld = (struct cxl_mld*) user_data; STEP // 1: Verify the yaml loader object string is not NULL if (ylo->str == NULL) @@ -1427,7 +833,7 @@ end: void _parse_device_port(gpointer key, gpointer value, gpointer user_data) { INIT - struct cse_device *d; + struct cxl_device *d; yl_obj_t *ylo; int rv; @@ -1436,7 +842,7 @@ void _parse_device_port(gpointer key, gpointer value, gpointer user_data) // Initialize varialbes rv = 1; ylo = (yl_obj_t*) value; - d = (struct cse_device*) user_data; + d = (struct cxl_device*) user_data; STEP // 1: Verify the yaml loader object string is not NULL if (ylo->str == NULL) @@ -1470,7 +876,7 @@ end: void _parse_emulator(gpointer key, gpointer value, gpointer user_data) { INIT - struct cxl_switch_state *s; + struct cxl_switch *s; yl_obj_t *ylo; int rv; @@ -1479,7 +885,7 @@ void _parse_emulator(gpointer key, gpointer value, gpointer user_data) // Initialize varialbes rv = 1; ylo = (yl_obj_t*) value; - s = (struct cxl_switch_state*) user_data; + s = (struct cxl_switch*) user_data; STEP // 1: Verify the yaml loader object string is not NULL if (ylo->str == NULL) @@ -1521,7 +927,7 @@ end: void _parse_switch(gpointer key, gpointer value, gpointer user_data) { INIT - struct cxl_switch_state *s; + struct cxl_switch *s; yl_obj_t *ylo; int rv; @@ -1530,7 +936,7 @@ void _parse_switch(gpointer key, gpointer value, gpointer user_data) // Initialize varialbes rv = 1; ylo = (yl_obj_t*) value; - s = (struct cxl_switch_state*) user_data; + s = (struct cxl_switch*) user_data; STEP // 1: Verify the yaml loader object string is not NULL if (ylo->str == NULL) @@ -1580,7 +986,7 @@ void _parse_ports(gpointer key, gpointer value, gpointer user_data) { INIT yl_obj_t *ylo; - struct port *ports; + struct cxl_port *ports; int rv, id; ENTER @@ -1588,7 +994,7 @@ void _parse_ports(gpointer key, gpointer value, gpointer user_data) // Initialize varialbes rv = 1; ylo = (yl_obj_t*) value; - ports = (struct port*) user_data; + ports = (struct cxl_port*) user_data; STEP // 1: Verify the yaml loader object hash table is not NULL if ( ylo->ht == NULL ) @@ -1619,7 +1025,7 @@ void _parse_port(gpointer key, gpointer value, gpointer user_data) { INIT yl_obj_t *ylo; - struct port *port; + struct cxl_port *port; int rv; ENTER @@ -1627,7 +1033,7 @@ void _parse_port(gpointer key, gpointer value, gpointer user_data) // Initialize varialbes rv = 1; ylo = (yl_obj_t*) value; - port = (struct port*) user_data; + port = (struct cxl_port*) user_data; STEP // 1: Verify the yaml loader object string is not NULL if ( ylo->str == NULL ) @@ -1660,7 +1066,7 @@ void _parse_vcss(gpointer key, gpointer value, gpointer user_data) { INIT yl_obj_t *ylo; - struct vcs *vcss; + struct cxl_vcs *vcss; int rv, id; ENTER @@ -1668,7 +1074,7 @@ void _parse_vcss(gpointer key, gpointer value, gpointer user_data) // Initialize varialbes rv = 1; ylo = (yl_obj_t*) value; - vcss = (struct vcs*) user_data; + vcss = (struct cxl_vcs*) user_data; STEP // 1: Verify the yaml loader object hash table is not NULL if ( ylo->ht == NULL ) @@ -1699,13 +1105,13 @@ void _parse_vcs(gpointer key, gpointer value, gpointer user_data) { INIT yl_obj_t *ylo; - struct vcs *vcs; + struct cxl_vcs *vcs; ENTER // Initialize varialbes ylo = (yl_obj_t*) value; - vcs = (struct vcs*) user_data; + vcs = (struct cxl_vcs*) user_data; STEP // 1: Assign KV pairs to state variables if ( ylo->str != NULL ) @@ -1737,7 +1143,7 @@ void _parse_vppbs(gpointer key, gpointer value, gpointer user_data) { INIT yl_obj_t *ylo; - struct vppb *vppbs; + struct cxl_vppb *vppbs; int rv, id; ENTER @@ -1745,7 +1151,7 @@ void _parse_vppbs(gpointer key, gpointer value, gpointer user_data) // Initialize varialbes rv = 1; ylo = (yl_obj_t*) value; - vppbs = (struct vppb*) user_data; + vppbs = (struct cxl_vppb*) user_data; STEP // 1: Verify the yaml loader object hash table is not NULL if ( ylo->ht == NULL ) @@ -1776,7 +1182,7 @@ void _parse_vppb(gpointer key, gpointer value, gpointer user_data) { INIT yl_obj_t *ylo; - struct vppb *vppb; + struct cxl_vppb *vppb; int rv; ENTER @@ -1784,7 +1190,7 @@ void _parse_vppb(gpointer key, gpointer value, gpointer user_data) // Initialize varialbes rv = 1; ylo = (yl_obj_t*) value; - vppb = (struct vppb*) user_data; + vppb = (struct cxl_vppb*) user_data; STEP // 1: Verify the yaml loader object string is not NULL if ( ylo->str == NULL ) @@ -1805,245 +1211,3 @@ end: EXIT(rv) } -/** - * Print the CXL Switch State - */ -void state_print(struct cxl_switch_state *state) -{ - state_print_identity(state, 0); - state_print_ports(state, 0); - state_print_vcss(state, 0); -} - -/** - * Print the Device List - */ -void state_print_devices(struct cxl_switch_state *s) -{ - struct cse_device *d; - - if (s->devices == NULL) - return; - - for ( unsigned i = 0 ; i < s->num_devices ; i++ ) - { - d = &s->devices[i]; - - printf("%s:\n", d->name); - printf(" Port:\n"); - printf(" dt: %2d - %s\n", d->dt, fmdt(d->dt)); - printf(" dv: %2d - %s\n", d->dv, fmdv(d->dv)); - printf(" cv: %2d - %s\n", d->cv, fmvc(d->cv)); - printf(" mlw: %2d\n", d->mlw); - - pcie_prnt_cfgspace(d->cfgspace, 2); - } -} - -/** - * Print the CXL Switch Idenfity Information - * - * @param struct cxl_switch_state* to print - * @param indent The number of spaces to indent the printed text - */ -void state_print_identity(struct cxl_switch_state *s, unsigned indent) -{ - char space[MAX_INDENT] = " "; - - // Handle indent - if (indent >= MAX_INDENT) - indent = MAX_INDENT; - space[indent] = 0; - - // Print fields - printf("%singress_port: %u\n", space, s->ingress_port); - printf("%snum_ports: %u\n", space, s->num_ports); - printf("%snum_vcss: %u\n", space, s->num_vcss); - printf("%snum_vppbs: %u\n", space, s->num_vppbs); - printf("%snum_decoders: %u\n", space, s->num_decoders); - printf("%sdir: %s\n", space, s->dir); - -} - -/** - * Print CXL MLD Info - * - * @param mld struct mld* to use to print - * @param indent The number of spaces to indent the printed text - */ -void state_print_mld(struct mld *mld, unsigned indent) -{ - char space[MAX_INDENT] = " "; - - // Handle indent - if (indent >= MAX_INDENT) - indent = MAX_INDENT; - space[indent] = 0; - - printf("%sMulti-Logical Device:\n", space); - - space[indent] = ' '; - space[indent+2] = 0; - - printf("%sMemory Size 0x%016llx\n", space, mld->memory_size); - printf("%sNum LD %d\n", space, mld->num); - printf("%sEgress Port Congestion Supported %d\n", space, mld->epc); - printf("%sTemporary Throughput Reduction Supported %d\n", space, mld->ttr); - printf("%sGranularity %d - %s\n", space, mld->granularity, fmmg(mld->granularity)); - printf("%sEgress Port Congestion Enabled %d\n", space, mld->epc_en); - printf("%sTemporary Throughput Reduction Enabled %d\n", space, mld->ttr_en); - printf("%sEgress Moderate Percentage %d\n", space, mld->egress_mod_pcnt); - printf("%sEgress Severe Percentage %d\n", space, mld->egress_sev_pcnt); - printf("%sBackpressure Sample Interval %d\n", space, mld->sample_interval); - printf("%sReqCmpBasis %d\n", space, mld->rcb); - printf("%sCompletion Collection Interval %d\n", space, mld->comp_interval); - printf("%sBackpressure Average Percentage %d\n", space, mld->bp_avg_pcnt); - printf("%smmap %d\n", space, mld->mmap); - printf("%smmap file %s\n", space, mld->file); - printf("\n"); - printf("%sLDID Range 1 Range 2 Alloc BW BW Limit\n", space); - printf("%s---- ------------------ ------------------ -------- --------\n", space); - for ( int i = 0 ; i < mld->num ; i++ ) - printf("%s%4d: 0x%016llx 0x%016llx %8d %8d\n", space, i, mld->rng1[i], mld->rng2[i], mld->alloc_bw[i], mld->bw_limit[i]); -} - -/** - * Print CXL Ports - * - * @param struct cxl_switch_stat* to use to print - * @param indent The number of spaces to indent the printed text - */ -void state_print_ports(struct cxl_switch_state *s, unsigned indent) -{ - char space[MAX_INDENT] = " "; - - // Handle indent - if (indent >= MAX_INDENT) - indent = MAX_INDENT; - space[indent] = 0; - - // Print fields - printf("%sports:\n", space); - - for (int i = 0 ; i < s->num_ports ; i++) { - printf("%s %02u:\n", space,i); - state_print_port(&s->ports[i], indent + 2 + INDENT); - } -} - -/** - * Print the CXL Port Information - * - * @param struct port* to print - * @param indent The number of spaces to indent the printed text - */ -void state_print_port(struct port *p, unsigned indent) -{ - char space[MAX_INDENT] = " "; - - // Handle indent - if (indent >= MAX_INDENT) - indent = MAX_INDENT; - space[indent] = 0; - - // Print fields - printf("%sstate: %u\t\t%s\n", space, p->state, fmps(p->state)); - printf("%sdv: %u\t\t%s\n", space, p->dv, fmdv(p->dv)); - printf("%sdt: %u\t\t%s\n", space, p->dt, fmdt(p->dt)); - printf("%scv: 0x%02x\n", space, p->cv); - printf("%smax_link_width: %u\n", space, p->mlw); - printf("%sneg_link_width: %u\n", space, p->nlw); - printf("%sspeeds: 0x%02x\n", space, p->speeds); - printf("%smax_link_speed: %u\t\t%s\n", space, p->mls, fmms(p->mls)); - printf("%scur_link_speed: %u\t\t%s\n", space, p->cls, fmms(p->cls)); - printf("%sltssm: %u\t\t%s\n", space, p->ltssm, fmls(p->ltssm)); - printf("%sfirst_lane: %u\n", space, p->lane); - printf("%sLane Reversal State %d\n", space, p->lane_rev); - printf("%sPCIe Reset State %d\n", space, p->perst); - printf("%sPort Presence pin state %d\n", space, p->prsnt); - printf("%sPower Control State %d\n", space, p->pwrctrl); - printf("%sld: %u\n", space, p->ld); - printf("%sDevice Name %s\n", space, p->device_name); - - if (p->cfgspace != NULL) { - pcie_prnt_cfgspace(p->cfgspace, indent); - autl_prnt_buf(p->cfgspace, 1024, 16, 1); - } - - if (p->mld != NULL) - state_print_mld(p->mld, indent); -} - -/** - * Print the CXL VCS List - * - * @param struct cxl_switch_state* to print from - * @param indent The number of spaces to indent the printed text - */ -void state_print_vcss(struct cxl_switch_state *s, unsigned indent) -{ - char space[MAX_INDENT] = " "; - - // Handle indent - if (indent >= MAX_INDENT) - indent = MAX_INDENT; - space[indent] = 0; - - // Print fields - printf("%svcss:\n", space); - - for (int i = 0 ; i < s->num_vcss ; i++) { - printf("%s %02u:\n", space, i); - state_print_vcs(&s->vcss[i], indent + 2 + INDENT); - } -} - -/** - * Print information for a single CXL VCS - * - * @param struct vcs* to print - * @param indent The number of spaces to indent the printed text - */ -void state_print_vcs(struct vcs *v, unsigned indent) -{ - char space[MAX_INDENT] = " "; - - // Handle indent - if (indent >= MAX_INDENT) - indent = MAX_INDENT; - space[indent] = 0; - - // Print fields of the VCS - printf("%sstate: %u\t\t%s\n", space, v->state, fmvs(v->state)); - printf("%suspid: %u\n", space, v->uspid); - printf("%snum_vppb: %u\n", space, v->num); - printf("%svppbs:\n", space); - - // Print the vPPBs of the VCS - for (int i = 0 ; i < v->num ; i++) { - printf("%s %u:\n", space, i); - state_print_vppb(&v->vppbs[i], indent + 2 + INDENT); - } -} - -/** - * Print information for a single CXL vPPB - * - * @param struct vppb* to print - * @param indent The number of spaces to indent the printed text - */ -void state_print_vppb(struct vppb *b, unsigned indent) -{ - char space[MAX_INDENT] = " "; - - // Handle indent - if (indent >= MAX_INDENT) - indent = MAX_INDENT; - space[indent] = 0; - - // Print fields of the VCS - printf("%sldid: %u\n", space, b->ldid); - printf("%sppid: %u\n", space, b->ppid); - printf("%sbind_status: %u\t\t%s\n", space, b->bind_status, fmbs(b->bind_status)); -} - diff --git a/state.h b/state.h index d8d1f26..5c7bc99 100644 --- a/state.h +++ b/state.h @@ -25,6 +25,7 @@ #include #include +#include /* MACROS ====================================================================*/ @@ -45,198 +46,12 @@ /* STRUCTS ===================================================================*/ - -/** - * Multi Logical Device Object* - * - * This device aggregates all the descriptors for a CXL MLD Logical Device - * - * CXL 2.0 v1.0 Table 111,112,113,116,117,118,119 - */ -struct mld { - - /* LD Info: Table 111*/ - __u64 memory_size; //!< Total device memory capacity - __u16 num; //!< Number of Logical Devices supported - __u8 epc; //!< Egress Port Congestion Supported - __u8 ttr; //!< Temporary Throughput Reduction Supported - - /* LD Allocations: Table 112,113 */ - __u8 granularity; //!< Memory Granularity [FMMG] - __u64 rng1[FM_MAX_NUM_LD]; //!< Range 1 Allocation Multiplier - __u64 rng2[FM_MAX_NUM_LD]; //!< Range 2 Allocation Multiplier - - /* LD QoS Control parameters: Table 116*/ - __u8 epc_en; //!< QoS Telem: Egress Port Congestion Enable. Bitfield [FMQT] - __u8 ttr_en; //!< QoS Telem: Temporary Throuhput Reduction Enable. Bitfield [FMQT] - __u8 egress_mod_pcnt; //!< Egress Moderate Percentage: Threshold in percent for Egress Port Congestion mechanism to indicate moderate congestion. Valid range is 1-100. Default is 10. - __u8 egress_sev_pcnt; //!< Egress Severe Percentage: Threshold in percent for Egress Port Congestion mechanism to indicate severe congestion. Valid range is 1-100. Default is 25 - __u8 sample_interval; //!< Backpressure Sample Interval: Interval in ns for Egress Port Congestion mechanism to take samples. Valid range is 0-15. Default is 8 (800 ns of history). Value of 0 disables the mechanism. - __u16 rcb; //!< ReqCmpBasis. Estimated maximum sustained sum of requests and recent responses across the entire device, serving as the basis for QoS Limit Fraction. Valid range is 0-65,535. Value of 0 disables the mechanism. Default is 0. - __u8 comp_interval; //!< Completion Collection Interval: Interval in ns for Completion Counting mechanism to collect the number of transmitted responses in a single counter. Valid range is 0-255. Default is 64 - - /* LD QoS Status: Table 117*/ - __u8 bp_avg_pcnt; //!< Backpressure Average Percentage: Current snapshot of the measured Egress Port average congestion. Table 117 - - /* LD QoS Allocated BW Fractions: Table 118 */ - __u8 alloc_bw[FM_MAX_NUM_LD]; - - /* LD QoS BW Limit Fractions: Table 119 */ - __u8 bw_limit[FM_MAX_NUM_LD]; - - __u8 *cfgspace[FM_MAX_NUM_LD]; //!< Buffers representing PCIe config space for each logical device - - __u8 mmap; //!< Direction to mmap a file for the memory space - char *file; //!< Filename for mmaped file - __u8 *memspace; //!< Buffer representing memory space for entire logical device -}; - -/** - * Virtual PCIe-to-PCIe Bridge Object - * - * CXL 2.0 v1.0 Table 99 - */ -struct vppb { - __u16 vppbid; //!< Index of this vPPB in the state->vppbs[] array - __u8 bind_status; //!< PBB Binding Status [FMBS] - __u8 ppid; //!< Physical port number of bound port - __u16 ldid; //!< ID of LD bound to port from MLD on associated physical port -}; - -/** - * Virtual CXL Switch Object - * - * CXL 2.0 v1.0 Table 99 - */ -struct vcs { - __u8 vcsid; //!< VCS ID - Index of this vcs in the state->vcss[] array - __u8 state; //!< Virtual CXL switch State [FMVS] - __u8 uspid; //!< USP Physical Port ID - __u8 num; //!< Number of vPPBs - - //!< Array of pointers to vPPB objects - struct vppb vppbs[MAX_VPPBS_PER_VCS]; -}; - -/** - * CXL Switch Port Object - * - * CXL 2.0 v1.0 Table 92 - */ -struct port { - __u8 ppid; //!< Port ID - Index of this port in the state->ports[] array - __u8 state; //!< Current Port Configuration State [FMPS] - __u8 dv; //!< Connected Device CXL version [FMDV] - __u8 dt; //!< Connected device type [FMDT] - __u8 cv; //!< Connected CXL version bitmask [FMVC] - __u8 mlw; //!< Max Link Width. Integer number of lanes (1,2,4,8,16) - __u8 nlw; //!< Negotiated Link Width [FMNW] - __u8 speeds; //!< Supported Link Speeds Vector [FMSS] - __u8 mls; //!< Maximum Link Speed [FMMS] - __u8 cls; //!< Current Link Speed [FMMS] - __u8 ltssm; //!< LTSSM State [FMLS] - __u8 lane; //!< First negotiated lane number (Integer lane number) - - /** Link State Flags [FMLF] [FMLO] */ - __u8 lane_rev; //!< Lane reversal state. 0=standard, 1=rev [FMLO] - __u8 perst; //!< PCIe Reset State PERST# - __u8 prsnt; //!< Port Presence pin state PRSNT# - __u8 pwrctrl; //!< Power Control State (PWR_CTRL) - - __u8 ld; //!< Additional supported LD Count (beyond 1) - __u8 *cfgspace; //!< Buffer representing PCIe config space - struct mld *mld; //!< State for MLD - char *device_name; //!< Name of device used to populate this port -}; - -struct cse_device -{ - char *name; //!< Name of device - __u8 rootport; //!< Root Port Device. 1=root, 2=endpoint - __u8 dv; //!< Connected Device CXL version [FMDV] - __u8 dt; //!< Connected device type [FMDT] - __u8 cv; //!< Connected CXL version bitmask [FMVC] - __u8 mlw; //!< Maximum Link Width. Integer number of lanes (1,2,4,8,16) - __u8 mls; //!< Maximum Link Speed [FMMS] - __u8 *cfgspace; //!< Buffer representing PCIe config space - struct mld *mld; //!< MLD info if this is an MLD -}; - -/** - * CXL Switch State Identify Information - * - * CXL 2.0 v1 Table 89 - */ -struct cxl_switch_state { - __u8 version; //!< Device Management Version - - __u16 vid; //!< PCIe Vendor ID - __u16 did; //!< PCIe Device ID - __u16 svid; //!< PCIe Subsystem Vendor ID - __u16 ssid; //!< PCIe Subsystem ID - __u64 sn; //!< Device Serial Number - __u8 max_msg_size_n; //!< Max fmapi msg size. 2^n - - __u8 msg_rsp_limit_n; //!< Message Response Limit n of 2^n - - __u8 bos_running; //!< Background operation status 0=none, 1=running - __u8 bos_pcnt; //!< Background operation percent complete [0-100] - __u16 bos_opcode; //!< Background operation opcode - __u16 bos_rc; //!< Background operation return code - __u16 bos_ext; //!< Background operation Extended Vendor Status - - __u8 ingress_port; //!< Ingress Port ID - __u8 num_ports; //!< Total number of physical ports - __u8 num_vcss; //!< Max number of VCSs - __u16 num_vppbs; //!< Max number of vPPBs - __u16 active_vppbs; //!< Number of active vPPBs - __u8 num_decoders; //!< Number of HDM decoders available per USP - - struct port *ports; //!< array of Port objects - struct vcs *vcss; //!< array of VCS objects - - struct cse_device *devices; //!< array of device definitions - __u16 len_devices; //!< Number of entries supported in devices array - __u16 num_devices; //!< Number of entries in devices array - - /* Port defaults */ - __u8 mlw; //!< Max Link Width. Integer number of lanes (1,2,4,8,16) - __u8 speeds; //!< Supported Link Speeds Vector [FMSS] - __u8 mls; //!< Maximum Link Speed [FMMS] - char *dir; //!< Filepath to directory for instantiated memory - - pthread_mutex_t mtx; //!< Mutex to control access to this object -}; - - /* PROTOTYPES ================================================================*/ -struct cxl_switch_state *state_init(unsigned ports, unsigned vcss, unsigned vppbs); -int state_load(struct cxl_switch_state *s, char *filename); -void state_free(struct cxl_switch_state *s); - -int state_connect_device(struct port *p, struct cse_device *d); -int state_disconnect_device(struct port *p); - -/* Conversion Functions */ -void state_conv_identity(struct cxl_switch_state *src, struct fmapi_psc_id_rsp *dst); -void state_conv_port_info(struct port *src, struct fmapi_psc_port_info *dst); -void state_conv_vcs_info(struct vcs *src, struct fmapi_vsc_info_blk *dst); - -/* Print Functions */ -void state_print(struct cxl_switch_state *s); -void state_print_identity(struct cxl_switch_state *s, unsigned indent); -void state_print_ports(struct cxl_switch_state *s, unsigned indent); -void state_print_port(struct port *p, unsigned indent); -void state_print_vcss(struct cxl_switch_state *s, unsigned indent); -void state_print_vcs(struct vcs *v, unsigned indent); -void state_print_vppb(struct vppb *b, unsigned indent); -void state_print_mld(struct mld *mld, unsigned indent); - -void state_print_devices(struct cxl_switch_state *s); +int state_load(struct cxl_switch *s, char *filename); /* GLOBAL VARIABLES ==========================================================*/ -extern struct cxl_switch_state *cxl_state; +extern struct cxl_switch *cxls; #endif //ifndef _STATE_H