diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch new file mode 100644 index 000000000..3ba6fd56e --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch @@ -0,0 +1,392 @@ +From e734cd91f288838a491a75e16f3a09d353079139 Mon Sep 17 00:00:00 2001 +From: "Jason M. Bills" <jason.m.bills@intel.com> +Date: Wed, 4 Apr 2018 13:52:39 -0700 +Subject: [PATCH] Add support for new PECI commands + +Signed-off-by: Jason M. Bills <jason.m.bills@intel.com> +--- + drivers/peci/peci-core.c | 200 ++++++++++++++++++++++++++++++++++++++++ + include/uapi/linux/peci-ioctl.h | 109 ++++++++++++++++++++++ + 2 files changed, 309 insertions(+) + +diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c +index fac8c72dcda8..62dada99afee 100644 +--- a/drivers/peci/peci-core.c ++++ b/drivers/peci/peci-core.c +@@ -242,6 +242,9 @@ static int peci_scan_cmd_mask(struct peci_adapter *adapter) + adapter->cmd_mask |= BIT(PECI_CMD_GET_TEMP); + adapter->cmd_mask |= BIT(PECI_CMD_GET_DIB); + adapter->cmd_mask |= BIT(PECI_CMD_PING); ++ adapter->cmd_mask |= BIT(PECI_CMD_RD_END_PT_CFG); ++ adapter->cmd_mask |= BIT(PECI_CMD_CRASHDUMP_DISC); ++ adapter->cmd_mask |= BIT(PECI_CMD_CRASHDUMP_GET_FRAME); + + return rc; + } +@@ -515,6 +518,197 @@ static int peci_ioctl_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) + return rc; + } + ++static int peci_ioctl_rd_end_pt_cfg(struct peci_adapter *adapter, void *vmsg) ++{ ++ struct peci_rd_end_pt_cfg_msg *umsg = vmsg; ++ struct peci_xfer_msg msg; ++ u32 address; ++ int rc = 0; ++ ++ switch (umsg->msg_type) { ++ case RDENDPTCFG_TYPE_LOCAL_PCI: ++ case RDENDPTCFG_TYPE_PCI: ++ /** ++ * Per the PECI spec, the read length must be a byte, word, ++ * or dword ++ */ ++ if (umsg->rx_len != 1 && umsg->rx_len != 2 && ++ umsg->rx_len != 4) { ++ dev_dbg(&adapter->dev, ++ "Invalid read length, rx_len: %d\n", ++ umsg->rx_len); ++ return -EINVAL; ++ } ++ ++ address = umsg->params.pci_cfg.reg; /* [11:0] - Register */ ++ address |= (u32)umsg->params.pci_cfg.function ++ << 12; /* [14:12] - Function */ ++ address |= (u32)umsg->params.pci_cfg.device ++ << 15; /* [19:15] - Device */ ++ address |= (u32)umsg->params.pci_cfg.bus ++ << 20; /* [27:20] - Bus */ ++ /* [31:28] - Reserved */ ++ msg.addr = umsg->addr; ++ msg.tx_len = RDENDPTCFG_PCI_WRITE_LEN; ++ msg.rx_len = RDENDPTCFG_READ_LEN_BASE + umsg->rx_len; ++ msg.tx_buf[0] = RDENDPTCFG_PECI_CMD; ++ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */ ++ msg.tx_buf[2] = umsg->msg_type; /* Message Type */ ++ msg.tx_buf[3] = 0x00; /* Endpoint ID */ ++ msg.tx_buf[4] = 0x00; /* Reserved */ ++ msg.tx_buf[5] = 0x00; /* Reserved */ ++ msg.tx_buf[6] = RDENDPTCFG_ADDR_TYPE_PCI; /* Address Type */ ++ msg.tx_buf[7] = umsg->params.pci_cfg.seg; /* PCI Segment */ ++ msg.tx_buf[8] = (u8)address; /* LSB - PCI Config Address */ ++ msg.tx_buf[9] = (u8)(address >> 8); /* PCI Config Address */ ++ msg.tx_buf[10] = (u8)(address >> 16); /* PCI Config Address */ ++ msg.tx_buf[11] = ++ (u8)(address >> 24); /* MSB - PCI Config Address */ ++ break; ++ case RDENDPTCFG_TYPE_MMIO: ++ /** ++ * Per the PECI spec, the read length must be a byte, word, ++ * dword, or qword ++ */ ++ if (umsg->rx_len != 1 && umsg->rx_len != 2 && ++ umsg->rx_len != 4 && umsg->rx_len != 8) { ++ dev_dbg(&adapter->dev, ++ "Invalid read length, rx_len: %d\n", ++ umsg->rx_len); ++ return -EINVAL; ++ } ++ /** ++ * Per the PECI spec, the address type must specify either DWORD ++ * or QWORD ++ */ ++ if (umsg->params.mmio.addr_type != ++ RDENDPTCFG_ADDR_TYPE_MMIO_D && ++ umsg->params.mmio.addr_type != ++ RDENDPTCFG_ADDR_TYPE_MMIO_Q) { ++ dev_dbg(&adapter->dev, ++ "Invalid address type, addr_type: %d\n", ++ umsg->params.mmio.addr_type); ++ return -EINVAL; ++ } ++ ++ address = umsg->params.mmio.function; /* [2:0] - Function */ ++ address |= (u32)umsg->params.mmio.device ++ << 3; /* [7:3] - Device */ ++ ++ msg.addr = umsg->addr; ++ msg.tx_len = RDENDPTCFG_MMIO_D_WRITE_LEN; ++ msg.rx_len = RDENDPTCFG_READ_LEN_BASE + umsg->rx_len; ++ msg.tx_buf[0] = RDENDPTCFG_PECI_CMD; ++ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */ ++ msg.tx_buf[2] = umsg->msg_type; /* Message Type */ ++ msg.tx_buf[3] = 0x00; /* Endpoint ID */ ++ msg.tx_buf[4] = 0x00; /* Reserved */ ++ msg.tx_buf[5] = umsg->params.mmio.bar; /* BAR # */ ++ msg.tx_buf[6] = umsg->params.mmio.addr_type; /* Address Type */ ++ msg.tx_buf[7] = umsg->params.mmio.seg; /* PCI Segment */ ++ msg.tx_buf[8] = (u8)address; /* Function/Device */ ++ msg.tx_buf[9] = umsg->params.mmio.bus; /* PCI Bus */ ++ msg.tx_buf[10] = (u8)umsg->params.mmio ++ .offset; /* LSB - Register Offset */ ++ msg.tx_buf[11] = (u8)(umsg->params.mmio.offset ++ >> 8); /* Register Offset */ ++ msg.tx_buf[12] = (u8)(umsg->params.mmio.offset ++ >> 16); /* Register Offset */ ++ msg.tx_buf[13] = (u8)(umsg->params.mmio.offset ++ >> 24); /* MSB - DWORD Register Offset */ ++ if (umsg->params.mmio.addr_type ++ == RDENDPTCFG_ADDR_TYPE_MMIO_Q) { ++ msg.tx_len = RDENDPTCFG_MMIO_Q_WRITE_LEN; ++ msg.tx_buf[14] = (u8)(umsg->params.mmio.offset ++ >> 32); /* Register Offset */ ++ msg.tx_buf[15] = (u8)(umsg->params.mmio.offset ++ >> 40); /* Register Offset */ ++ msg.tx_buf[16] = (u8)(umsg->params.mmio.offset ++ >> 48); /* Register Offset */ ++ msg.tx_buf[17] = ++ (u8)(umsg->params.mmio.offset ++ >> 56); /* MSB - QWORD Register Offset */ ++ } ++ break; ++ } ++ ++ rc = peci_xfer_with_retries(adapter, &msg, false); ++ if (!rc) ++ memcpy(umsg->data, &msg.rx_buf[1], umsg->rx_len); ++ ++ return rc; ++} ++ ++static int peci_ioctl_crashdump_disc(struct peci_adapter *adapter, void *vmsg) ++{ ++ struct peci_crashdump_disc_msg *umsg = vmsg; ++ struct peci_xfer_msg msg; ++ int rc = 0; ++ ++ /* Per the EDS, the read length must be a byte, word, or qword */ ++ if (umsg->rx_len != 1 && umsg->rx_len != 2 && umsg->rx_len != 8) { ++ dev_dbg(&adapter->dev, "Invalid read length, rx_len: %d\n", ++ umsg->rx_len); ++ return -EINVAL; ++ } ++ ++ msg.addr = umsg->addr; ++ msg.tx_len = CRASHDUMP_DISC_WRITE_LEN; ++ msg.rx_len = CRASHDUMP_DISC_READ_LEN_BASE + umsg->rx_len; ++ msg.tx_buf[0] = CRASHDUMP_CMD; ++ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */ ++ /* Host ID is 0 for PECI 3.0 */ ++ msg.tx_buf[2] = CRASHDUMP_DISC_VERSION; ++ msg.tx_buf[3] = CRASHDUMP_DISC_OPCODE; ++ msg.tx_buf[4] = umsg->subopcode; ++ msg.tx_buf[5] = umsg->param0; ++ msg.tx_buf[6] = (u8)umsg->param1; ++ msg.tx_buf[7] = (u8)(umsg->param1 >> 8); ++ msg.tx_buf[8] = umsg->param2; ++ ++ rc = peci_xfer_with_retries(adapter, &msg, false); ++ if (!rc) ++ memcpy(umsg->data, &msg.rx_buf[1], umsg->rx_len); ++ ++ return rc; ++} ++ ++static int peci_ioctl_crashdump_get_frame(struct peci_adapter *adapter, ++ void *vmsg) ++{ ++ struct peci_crashdump_get_frame_msg *umsg = vmsg; ++ struct peci_xfer_msg msg; ++ int rc = 0; ++ ++ /* Per the EDS, the read length must be a qword or dqword */ ++ if (umsg->rx_len != 8 && umsg->rx_len != 16) { ++ dev_dbg(&adapter->dev, "Invalid read length, rx_len: %d\n", ++ umsg->rx_len); ++ return -EINVAL; ++ } ++ ++ msg.addr = umsg->addr; ++ msg.tx_len = CRASHDUMP_GET_FRAME_WRITE_LEN; ++ msg.rx_len = CRASHDUMP_GET_FRAME_READ_LEN_BASE + umsg->rx_len; ++ msg.tx_buf[0] = CRASHDUMP_CMD; ++ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */ ++ /* Host ID is 0 for PECI 3.0 */ ++ msg.tx_buf[2] = CRASHDUMP_GET_FRAME_VERSION; ++ msg.tx_buf[3] = CRASHDUMP_GET_FRAME_OPCODE; ++ msg.tx_buf[4] = (u8)umsg->param0; ++ msg.tx_buf[5] = (u8)(umsg->param0 >> 8); ++ msg.tx_buf[6] = (u8)umsg->param1; ++ msg.tx_buf[7] = (u8)(umsg->param1 >> 8); ++ msg.tx_buf[8] = (u8)umsg->param2; ++ msg.tx_buf[8] = (u8)(umsg->param2 >> 8); ++ ++ rc = peci_xfer_with_retries(adapter, &msg, false); ++ if (!rc) ++ memcpy(umsg->data, &msg.rx_buf[1], umsg->rx_len); ++ ++ return rc; ++} ++ + typedef int (*peci_ioctl_fn_type)(struct peci_adapter *, void *); + + static const peci_ioctl_fn_type peci_ioctl_fn[PECI_CMD_MAX] = { +@@ -530,6 +724,9 @@ static const peci_ioctl_fn_type peci_ioctl_fn[PECI_CMD_MAX] = { + NULL, /* Reserved */ + peci_ioctl_rd_pci_cfg_local, + peci_ioctl_wr_pci_cfg_local, ++ peci_ioctl_rd_end_pt_cfg, ++ peci_ioctl_crashdump_disc, ++ peci_ioctl_crashdump_get_frame, + }; + + /** +@@ -592,6 +789,9 @@ static long peci_ioctl(struct file *file, unsigned int iocmd, unsigned long arg) + case PECI_IOC_RD_PCI_CFG: + case PECI_IOC_RD_PCI_CFG_LOCAL: + case PECI_IOC_WR_PCI_CFG_LOCAL: ++ case PECI_IOC_RD_END_PT_CFG: ++ case PECI_IOC_CRASHDUMP_DISC: ++ case PECI_IOC_CRASHDUMP_GET_FRAME: + cmd = _IOC_NR(iocmd); + msg_len = _IOC_SIZE(iocmd); + break; +diff --git a/include/uapi/linux/peci-ioctl.h b/include/uapi/linux/peci-ioctl.h +index a6dae71cbff5..5040d1cb4a3d 100644 +--- a/include/uapi/linux/peci-ioctl.h ++++ b/include/uapi/linux/peci-ioctl.h +@@ -31,6 +31,40 @@ + #define PKG_ID_MICROCODE_REV 0x0004 /* CPU Microcode Update Revision */ + #define PKG_ID_MACHINE_CHECK_STATUS 0x0005 /* Machine Check Status */ + ++/* RdEndPointCfg Parameters */ ++enum rdendptcfg_msg_type { ++ RDENDPTCFG_TYPE_LOCAL_PCI = 0x03, ++ RDENDPTCFG_TYPE_PCI = 0x04, ++ RDENDPTCFG_TYPE_MMIO = 0x05, ++}; ++ ++enum rdendptcfg_addr_type { ++ RDENDPTCFG_ADDR_TYPE_PCI = 0x04, ++ RDENDPTCFG_ADDR_TYPE_MMIO_D = 0x05, ++ RDENDPTCFG_ADDR_TYPE_MMIO_Q = 0x06, ++}; ++ ++/* Crashdump Parameters */ ++enum crashdump_agent { ++ CRASHDUMP_CORE = 0x00, ++ CRASHDUMP_TOR = 0x01, ++}; ++ ++enum crashdump_discovery_sub_opcode { ++ CRASHDUMP_ENABLED = 0x00, ++ CRASHDUMP_NUM_AGENTS = 0x01, ++ CRASHDUMP_AGENT_DATA = 0x02, ++}; ++ ++enum crashdump_agent_data_param { ++ CRASHDUMP_AGENT_ID = 0x00, ++ CRASHDUMP_AGENT_PARAM = 0x01, ++}; ++ ++enum crashdump_agent_param { ++ CRASHDUMP_PAYLOAD_SIZE = 0x00, ++}; ++ + /* RdPkgConfig Index */ + #define MBX_INDEX_CPU_ID 0 /* Package Identifier Read */ + #define MBX_INDEX_VR_DEBUG 1 /* VR Debug */ +@@ -136,6 +170,22 @@ + #define WRPCICFGLOCAL_READ_LEN 1 + #define WRPCICFGLOCAL_PECI_CMD 0xe5 + ++#define RDENDPTCFG_PCI_WRITE_LEN 0x0C ++#define RDENDPTCFG_MMIO_D_WRITE_LEN 0x0E ++#define RDENDPTCFG_MMIO_Q_WRITE_LEN 0x12 ++#define RDENDPTCFG_READ_LEN_BASE 1 ++#define RDENDPTCFG_PECI_CMD 0xC1 ++ ++#define CRASHDUMP_DISC_WRITE_LEN 9 ++#define CRASHDUMP_DISC_READ_LEN_BASE 1 ++#define CRASHDUMP_DISC_VERSION 1 ++#define CRASHDUMP_DISC_OPCODE 1 ++#define CRASHDUMP_GET_FRAME_WRITE_LEN 10 ++#define CRASHDUMP_GET_FRAME_READ_LEN_BASE 1 ++#define CRASHDUMP_GET_FRAME_VERSION 3 ++#define CRASHDUMP_GET_FRAME_OPCODE 3 ++#define CRASHDUMP_CMD 0x71 ++ + #define PECI_BUFFER_SIZE 32 + + /** +@@ -172,6 +222,9 @@ enum peci_cmd { + PECI_CMD_WR_PCI_CFG, + PECI_CMD_RD_PCI_CFG_LOCAL, + PECI_CMD_WR_PCI_CFG_LOCAL, ++ PECI_CMD_RD_END_PT_CFG, ++ PECI_CMD_CRASHDUMP_DISC, ++ PECI_CMD_CRASHDUMP_GET_FRAME, + PECI_CMD_MAX + }; + +@@ -366,6 +419,50 @@ struct peci_wr_pci_cfg_local_msg { + __u32 value; + } __attribute__((__packed__)); + ++struct peci_rd_end_pt_cfg_msg { ++ __u8 addr; ++ __u8 msg_type; ++ union { ++ struct { ++ __u8 seg; ++ __u8 bus; ++ __u8 device; ++ __u8 function; ++ __u16 reg; ++ } pci_cfg; ++ struct { ++ __u8 seg; ++ __u8 bus; ++ __u8 device; ++ __u8 function; ++ __u8 bar; ++ __u8 addr_type; ++ __u64 offset; ++ } mmio; ++ } params; ++ __u8 rx_len; ++ __u8 data[8]; ++} __attribute__((__packed__)); ++ ++struct peci_crashdump_disc_msg { ++ __u8 addr; ++ __u8 subopcode; ++ __u8 param0; ++ __u16 param1; ++ __u8 param2; ++ __u8 rx_len; ++ __u8 data[8]; ++} __attribute__((__packed__)); ++ ++struct peci_crashdump_get_frame_msg { ++ __u8 addr; ++ __u16 param0; ++ __u16 param1; ++ __u16 param2; ++ __u8 rx_len; ++ __u8 data[16]; ++} __attribute__((__packed__)); ++ + #define PECI_IOC_BASE 0xb7 + + #define PECI_IOC_XFER \ +@@ -400,4 +497,16 @@ struct peci_wr_pci_cfg_local_msg { + _IOWR(PECI_IOC_BASE, PECI_CMD_WR_PCI_CFG_LOCAL, \ + struct peci_wr_pci_cfg_local_msg) + ++#define PECI_IOC_RD_END_PT_CFG \ ++ _IOWR(PECI_IOC_BASE, PECI_CMD_RD_END_PT_CFG, \ ++ struct peci_rd_end_pt_cfg_msg) ++ ++#define PECI_IOC_CRASHDUMP_DISC \ ++ _IOWR(PECI_IOC_BASE, PECI_CMD_CRASHDUMP_DISC, \ ++ struct peci_crashdump_disc_msg) ++ ++#define PECI_IOC_CRASHDUMP_GET_FRAME \ ++ _IOWR(PECI_IOC_BASE, PECI_CMD_CRASHDUMP_GET_FRAME, \ ++ struct peci_crashdump_get_frame_msg) ++ + #endif /* __PECI_IOCTL_H */ +-- +2.7.4 + |