* [PATCH v1 0/3] misc: amd-sbi: Add TBAI trace-buffer access over I3C
@ 2026-11-11 5:40 Akshay Gupta
2026-11-11 5:40 ` [PATCH v1 1/3] misc: amd-sbi: use sized DMA-safe I3C tx/rx buffers Akshay Gupta
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Akshay Gupta @ 2026-11-11 5:40 UTC (permalink / raw)
To: linux-kernel, linux-doc
Cc: arnd, gregkh, corbet, skhan, rdunlap, linux,
naveenkrishna.chatradhi, Anand.Umarji, Akshay Gupta
The Trace Buffer Acquire Interface (TBAI) in the Thermal Management
(THM) block lets a Board Management Controller (BMC) read
microprocessor (MP) trace data over SB-TSI. The BMC does not program
the trace-buffer destination address space. It selects a look-up
table (LUT) index and an entry offset, and the SoC returns the
payload.
amd-sbi already exposes SB-TSI register transfers on /dev/sbtsi-* for
both I2C and I3C. TBAI is a second protocol on that same I3C target:
a 5-byte request and up to 32 bytes of read data. It is not available
over I2C. This series adds it as a new ioctl and does not change the
existing register-transfer ABI.
Userspace interface:
SBTBAI_IOCTL_CMD is
_IOWR(SB_BASE_IOCTL_NR, 5, struct apml_tbai_msg)
on the same /dev/sbtsi-* node as SBTSI_IOCTL_REG_XFER_CMD.
- I3C only. On an I2C SB-TSI device the ioctl returns -EOPNOTSUPP.
- Acquire (command 0x31) reads 1 to 32 dwords from a LUT index and a
16-bit entry offset. One transaction carries at most 8 dwords, so
the driver splits a larger read and advances the offset between
chunks.
- Flush (command 0x32) resets the TBAI logic. The acquire fields in
the request are ignored, and the 4-byte flush status is returned
in data_out.
- A trace-buffer target error is returned as -EPROTOTYPE. fw_ret_code
holds the status word (AMD_SBI_TBAI_TBT_ERR*) and data_out is
cleared. A 1-dword reply equal to one of those status values is
always reported as an error, because it cannot be told apart from
trace data.
- A short read returns -EMSGSIZE. The partial buffer is not copied
back to userspace.
- logging_en and the padding bytes must be zero.
- TBAI and TSI register transfers share the device lock, so the two
ioctls cannot interleave on the bus.
Series:
1. Name and size the I3C DMA buffers. Register access still uses
2 transmit bytes and 1 receive byte. Both buffers stay aligned to
ARCH_DMA_MINALIGN.
2. Add SBTBAI_IOCTL_CMD, the UAPI in include/uapi/misc/amd-apml.h, and
grow the shared I3C buffers to 5 transmit bytes and 32 receive
bytes.
3. Document the ioctl in Documentation/misc-devices/amd-sbi.rst.
Testing:
- Built the driver and checked that I3C SB-TSI register reads and
writes still work after the buffer change.
- On I3C hardware: acquire, flush, short read, and a trace-buffer
target error.
- On I2C, SBTBAI_IOCTL_CMD returns -EOPNOTSUPP.
- Built the amd-sbi documentation, including the new kernel-doc
reference, with no new warnings.
Akshay Gupta (1):
misc: amd-sbi: Add TBAI trace-buffer access over I3C
Prathima (2):
misc: amd-sbi: use sized DMA-safe I3C tx/rx buffers
docs: amd-sbi: document TBAI trace-buffer ioctl
Documentation/misc-devices/amd-sbi.rst | 60 +++++++-
drivers/misc/amd-sbi/tsi-core.c | 198 ++++++++++++++++++++++++-
drivers/misc/amd-sbi/tsi-core.h | 15 +-
include/uapi/misc/amd-apml.h | 78 ++++++++++
4 files changed, 344 insertions(+), 7 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v1 1/3] misc: amd-sbi: use sized DMA-safe I3C tx/rx buffers
2026-11-11 5:40 [PATCH v1 0/3] misc: amd-sbi: Add TBAI trace-buffer access over I3C Akshay Gupta
@ 2026-11-11 5:40 ` Akshay Gupta
2026-11-11 5:40 ` [PATCH v1 2/3] misc: amd-sbi: Add TBAI trace-buffer access over I3C Akshay Gupta
2026-11-11 5:40 ` [PATCH v1 3/3] docs: amd-sbi: document TBAI trace-buffer ioctl Akshay Gupta
2 siblings, 0 replies; 4+ messages in thread
From: Akshay Gupta @ 2026-11-11 5:40 UTC (permalink / raw)
To: linux-kernel, linux-doc
Cc: arnd, gregkh, corbet, skhan, rdunlap, linux,
naveenkrishna.chatradhi, Anand.Umarji, Prathima Lk, Akshay Gupta
From: Prathima Lk <Prathima.Lk@amd.com>
This change replaces the open-coded tx[2] array and single-byte scalar rx
field in struct sbtsi_i3c_priv with named, sized buffers (SBTSI_TX_LEN and
SBTSI_RX_LEN) and makes rx a proper array. The motivation is an upcoming
patch adding the SB-TSI Trace Buffer Acquire Interface, which shares the
same I3C target core and needs larger buffers. Preparing the sizes now
lets that follow-up patch grow the buffers without reworking the struct or
register access code.
Each buffer stays aligned to ARCH_DMA_MINALIGN for
DMA safety on noncoherent platforms. Affected areas are tsi-core.c and
tsi-core.h.
Tested by building the driver and verifying I3C register reads
and writes still function correctly on the target hardware.
Signed-off-by: Prathima Lk <Prathima.Lk@amd.com>
Signed-off-by: Akshay Gupta <Akshay.Gupta@amd.com>
---
drivers/misc/amd-sbi/tsi-core.c | 4 ++--
drivers/misc/amd-sbi/tsi-core.h | 8 ++++++--
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/misc/amd-sbi/tsi-core.c b/drivers/misc/amd-sbi/tsi-core.c
index 5c178702c67a..1920e4dc7b67 100644
--- a/drivers/misc/amd-sbi/tsi-core.c
+++ b/drivers/misc/amd-sbi/tsi-core.c
@@ -60,13 +60,13 @@ static int sbtsi_i3c_read(struct sbtsi_data *data, u8 reg, u8 *val)
/* Read the data byte into a separate buffer (DMA_FROM_DEVICE). */
xfers[1].rnw = true;
xfers[1].len = 1;
- xfers[1].data.in = &priv->rx;
+ xfers[1].data.in = priv->rx;
ret = i3c_device_do_xfers(data->i3cdev, xfers, 2, I3C_SDR);
if (ret)
return ret;
- *val = priv->rx;
+ *val = priv->rx[0];
return ret;
}
diff --git a/drivers/misc/amd-sbi/tsi-core.h b/drivers/misc/amd-sbi/tsi-core.h
index 4cf55c46230e..8efe7e220f4a 100644
--- a/drivers/misc/amd-sbi/tsi-core.h
+++ b/drivers/misc/amd-sbi/tsi-core.h
@@ -11,6 +11,10 @@
#include <linux/cache.h>
#include <linux/misc/tsi.h>
+/* SB-TSI register access transaction sizes in bytes. */
+#define SBTSI_TX_LEN 2 /* [0] register address, [1] value */
+#define SBTSI_RX_LEN 1 /* single data byte */
+
/**
* struct sbtsi_i3c_priv - per-device state for I3C SBTSI (includes DMA-safe buffers)
* @data: public device state exposed via dev_set_drvdata()
@@ -19,8 +23,8 @@
*/
struct sbtsi_i3c_priv {
struct sbtsi_data data;
- u8 tx[2];
- u8 rx __aligned(ARCH_DMA_MINALIGN);
+ u8 tx[SBTSI_TX_LEN] __aligned(ARCH_DMA_MINALIGN);
+ u8 rx[SBTSI_RX_LEN] __aligned(ARCH_DMA_MINALIGN);
};
int create_misc_tsi_device(struct sbtsi_data *data, struct device *dev);
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v1 2/3] misc: amd-sbi: Add TBAI trace-buffer access over I3C
2026-11-11 5:40 [PATCH v1 0/3] misc: amd-sbi: Add TBAI trace-buffer access over I3C Akshay Gupta
2026-11-11 5:40 ` [PATCH v1 1/3] misc: amd-sbi: use sized DMA-safe I3C tx/rx buffers Akshay Gupta
@ 2026-11-11 5:40 ` Akshay Gupta
2026-11-11 5:40 ` [PATCH v1 3/3] docs: amd-sbi: document TBAI trace-buffer ioctl Akshay Gupta
2 siblings, 0 replies; 4+ messages in thread
From: Akshay Gupta @ 2026-11-11 5:40 UTC (permalink / raw)
To: linux-kernel, linux-doc
Cc: arnd, gregkh, corbet, skhan, rdunlap, linux,
naveenkrishna.chatradhi, Anand.Umarji, Akshay Gupta, Prathima Lk
The Trace Buffer Acquire Interface (TBAI) in the Thermal Management
(THM) block allows the Board Management Controller (BMC) to access
MP trace data without managing the trace buffer's destination address
space.
Add TBAI support to the amd-sbi driver through a new SBTBAI_IOCTL_CMD
ioctl for acquire and flush operations. The ioctl is supported only
when the SB-TSI device is attached over I3C.
The acquire operation reads trace data in chunks of up to 32 dwords,
advances the entry offset between chunks, and reports trace-buffer
target errors returned in fw_ret_code. Add the corresponding UAPI
structures, command indices, and error codes, and enlarge the shared
I3C buffers to accommodate TBAI transfers.
Tested on I3C hardware with acquire, flush, short-read, and
trace-buffer target error cases. Confirmed that the I2C path returns
-EOPNOTSUPP.
Co-developed-by: Prathima Lk <Prathima.Lk@amd.com>
Signed-off-by: Prathima Lk <Prathima.Lk@amd.com>
Signed-off-by: Akshay Gupta <Akshay.Gupta@amd.com>
---
drivers/misc/amd-sbi/tsi-core.c | 194 ++++++++++++++++++++++++++++++++
drivers/misc/amd-sbi/tsi-core.h | 13 ++-
include/uapi/misc/amd-apml.h | 78 +++++++++++++
3 files changed, 280 insertions(+), 5 deletions(-)
diff --git a/drivers/misc/amd-sbi/tsi-core.c b/drivers/misc/amd-sbi/tsi-core.c
index 1920e4dc7b67..7e79c7eb3fde 100644
--- a/drivers/misc/amd-sbi/tsi-core.c
+++ b/drivers/misc/amd-sbi/tsi-core.c
@@ -8,11 +8,29 @@
#include <linux/fs.h>
#include <linux/ioctl.h>
+#include <linux/limits.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/uaccess.h>
+#include <linux/unaligned.h>
#include <uapi/misc/amd-apml.h>
#include "tsi-core.h"
+#define TBAI_WR_LEN 0x4 /* Input length (excludes command byte) */
+#define TBAI_REQ_LEN 0x5 /* Full request: command byte + TBAI_WR_LEN */
+#define TBAI_FLUSH_RD_LEN 0x4 /* flush buffer read length */
+#define MAX_PROTO_RD_SZ 32 /* Maximum bytes read in one transaction */
+#define BYTES_PER_DWORD 0x4 /* Number of bytes in dword */
+
+#define TBAI_IN_LUT_INDEX 0
+#define TBAI_IN_OFF_LO 1
+#define TBAI_IN_OFF_HI 2
+#define TBAI_IN_DWORD_COUNT 3
+
+/* Maximum dwords possible to read in one transaction */
+#define MAX_DWORDS_READ 0x8
+#define TBAI_OFFSET_HI_SHIFT 8 /* offset high byte bit position */
+
static inline struct sbtsi_i3c_priv *to_sbtsi_i3c_priv(struct sbtsi_data *data)
{
return container_of(data, struct sbtsi_i3c_priv, data);
@@ -136,6 +154,180 @@ static int apml_tsi_reg_xfer(struct sbtsi_data *data,
return ret;
}
+/* True if the single-dword reply is a trace buffer target (TBT) error status word */
+static bool tbai_is_tbt_err(u32 status)
+{
+ switch (status) {
+ case AMD_SBI_TBAI_TBT_ERR0:
+ case AMD_SBI_TBAI_TBT_ERR1:
+ case AMD_SBI_TBAI_TBT_ERR2:
+ case AMD_SBI_TBAI_TBT_ERR5:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static int tbai_protocol(struct sbtsi_data *data, u8 cmd, u8 *input, u8 count,
+ u8 *output, u16 *transferred_len)
+{
+ struct sbtsi_i3c_priv *priv = to_sbtsi_i3c_priv(data);
+ struct i3c_xfer xfers[2] = { };
+ int ret;
+
+ if (count > MAX_PROTO_RD_SZ)
+ return -EINVAL;
+
+ priv->tx[0] = cmd;
+ memcpy(&priv->tx[1], input, TBAI_WR_LEN);
+ xfers[0].len = TBAI_REQ_LEN;
+ xfers[0].data.out = priv->tx;
+ xfers[1].rnw = true;
+ xfers[1].len = count;
+ xfers[1].data.in = priv->rx;
+ memset(priv->rx, 0, count);
+
+ ret = i3c_device_do_xfers(data->i3cdev, xfers, ARRAY_SIZE(xfers), I3C_SDR);
+ if (ret)
+ return ret;
+ /* The I3C master returns the received length in xfers.len */
+ *transferred_len = xfers[1].len;
+ memcpy(output, priv->rx, count);
+ return 0;
+}
+
+static int flush_trace_buffer(struct sbtsi_data *data,
+ struct apml_tbai_msg *msg)
+{
+ /* Flush resets the whole TBAI logic; request bytes 2-5 are reserved */
+ u8 input[TBAI_WR_LEN] = { };
+ u16 transferred_len;
+ int ret;
+
+ msg->fw_ret_code = 0;
+
+ ret = tbai_protocol(data, msg->reg_in[AMD_SBI_TBAI_CMD_INDEX], input,
+ TBAI_FLUSH_RD_LEN, msg->data_out.bytes_out,
+ &transferred_len);
+ if (ret)
+ return ret;
+
+ if (transferred_len != TBAI_FLUSH_RD_LEN)
+ ret = -EMSGSIZE;
+
+ return ret;
+}
+
+static int acquire_trace_buffer(struct sbtsi_data *data,
+ struct apml_tbai_msg *msg)
+{
+ u32 total_dwords, expected_len, data_read = 0, status = 0;
+ u16 offset, offset_new, transferred_len;
+ u8 input[TBAI_WR_LEN] = { };
+ int dword_read, i, ret = 0, dword_remain;
+
+ msg->fw_ret_code = 0;
+ /* Dwords to read from user*/
+ total_dwords = msg->reg_in[AMD_SBI_TBAI_DWORD_RD_INDEX];
+ dword_remain = total_dwords;
+ /* Extract the offset to update, if more than 8 Dwords require to read */
+ offset = (u16)msg->reg_in[AMD_SBI_TBAI_OFFSET_LO] |
+ ((u16)msg->reg_in[AMD_SBI_TBAI_OFFSET_HI] << TBAI_OFFSET_HI_SHIFT);
+
+ /* If Dwords to read is 0 or more than 32, return */
+ if (!total_dwords || total_dwords > AMD_SBI_MAX_TBAI_DWORDS)
+ return -EINVAL;
+
+ /* Offset of the last chunk must fit in the 16-bit entry offset */
+ if ((u32)offset + (total_dwords - 1) / MAX_DWORDS_READ * MAX_PROTO_RD_SZ > U16_MAX)
+ return -EINVAL;
+
+ /*
+ * Set required variables to read dwords
+ * Maximum dwords supported from TBAI protocol is 8
+ */
+ for (i = 0; i <= total_dwords / MAX_DWORDS_READ && dword_remain > 0; i++) {
+ if (dword_remain > MAX_DWORDS_READ) {
+ dword_remain -= MAX_DWORDS_READ;
+ dword_read = MAX_DWORDS_READ;
+ } else {
+ dword_read = dword_remain;
+ dword_remain = 0;
+ }
+ /* update offset if more than 8 Dwords require to read */
+ offset_new = i * MAX_PROTO_RD_SZ + offset;
+ input[TBAI_IN_LUT_INDEX] = msg->reg_in[AMD_SBI_TBAI_LUT_INDEX];
+ input[TBAI_IN_OFF_LO] = offset_new & U8_MAX;
+ input[TBAI_IN_OFF_HI] = (offset_new >> TBAI_OFFSET_HI_SHIFT) & U8_MAX;
+ input[TBAI_IN_DWORD_COUNT] = dword_read - 1;
+
+ expected_len = dword_read * BYTES_PER_DWORD;
+ ret = tbai_protocol(data, msg->reg_in[AMD_SBI_TBAI_CMD_INDEX], input,
+ expected_len,
+ &msg->data_out.bytes_out[i * MAX_PROTO_RD_SZ],
+ &transferred_len);
+ if (ret)
+ return ret;
+
+ data_read += transferred_len;
+ /* A 1-dword reply matching a TBT error code is always taken as an error */
+ if (transferred_len == BYTES_PER_DWORD) {
+ status = get_unaligned_le32(&msg->data_out.bytes_out[i * MAX_PROTO_RD_SZ]);
+ if (tbai_is_tbt_err(status)) {
+ msg->fw_ret_code = status;
+ /* No trace data is returned on error, as with -EMSGSIZE */
+ memset(&msg->data_out, 0, sizeof(msg->data_out));
+ ret = -EPROTOTYPE;
+ return ret;
+ }
+ }
+
+ if (transferred_len < expected_len)
+ break;
+ }
+ if (data_read != (total_dwords * BYTES_PER_DWORD))
+ ret = -EMSGSIZE;
+
+ return ret;
+}
+
+static int apml_tbai_reg_xfer(struct sbtsi_data *data,
+ struct apml_tbai_msg __user *arg)
+{
+ struct apml_tbai_msg msg = { };
+ int ret;
+
+ /* TBAI is only available over I3C */
+ if (!data->is_i3c)
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&msg, arg, sizeof(struct apml_tbai_msg)))
+ return -EFAULT;
+ if (msg.logging_en || msg.pad[0] || msg.pad[1] || msg.pad[2])
+ return -EINVAL;
+
+ scoped_guard(sbtsi, data) {
+ if (data->detached)
+ return -ENODEV;
+
+ if (msg.reg_in[AMD_SBI_TBAI_CMD_INDEX] == AMD_SBI_TBAI_ACQUIRE)
+ ret = acquire_trace_buffer(data, &msg);
+ else if (msg.reg_in[AMD_SBI_TBAI_CMD_INDEX] == AMD_SBI_TBAI_FLUSH)
+ ret = flush_trace_buffer(data, &msg);
+ else
+ ret = -EINVAL;
+ }
+
+ /* Partial data is not returned on a short read */
+ if (ret && ret != -EPROTOTYPE)
+ return ret;
+
+ if (copy_to_user(arg, &msg, sizeof(struct apml_tbai_msg)))
+ return -EFAULT;
+
+ return ret;
+}
+
static int sbtsi_open(struct inode *inode, struct file *fp)
{
struct sbtsi_data *data;
@@ -169,6 +361,8 @@ static long sbtsi_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
switch (cmd) {
case SBTSI_IOCTL_REG_XFER_CMD:
return apml_tsi_reg_xfer(data, argp);
+ case SBTBAI_IOCTL_CMD:
+ return apml_tbai_reg_xfer(data, argp);
default:
return -ENOTTY;
}
diff --git a/drivers/misc/amd-sbi/tsi-core.h b/drivers/misc/amd-sbi/tsi-core.h
index 8efe7e220f4a..0b38c0b60b8f 100644
--- a/drivers/misc/amd-sbi/tsi-core.h
+++ b/drivers/misc/amd-sbi/tsi-core.h
@@ -11,15 +11,18 @@
#include <linux/cache.h>
#include <linux/misc/tsi.h>
-/* SB-TSI register access transaction sizes in bytes. */
-#define SBTSI_TX_LEN 2 /* [0] register address, [1] value */
-#define SBTSI_RX_LEN 1 /* single data byte */
+/* Maximum SB-TSI I3C transaction sizes in bytes (register access and TBAI). */
+#define SBTSI_TX_LEN 5
+#define SBTSI_RX_LEN 32
/**
* struct sbtsi_i3c_priv - per-device state for I3C SBTSI (includes DMA-safe buffers)
* @data: public device state exposed via dev_set_drvdata()
- * @tx: outgoing I3C bytes (DMA_TO_DEVICE); [0] register address, [1] value
- * @rx: incoming I3C data byte (DMA_FROM_DEVICE)
+ * @tx: outgoing I3C bytes (DMA_TO_DEVICE); for TSI register access
+ * [0] register address, [1] value; for TBAI [0] command,
+ * [1..4] input
+ * @rx: incoming I3C data bytes (DMA_FROM_DEVICE); TSI register read
+ * returns one byte, TBAI returns up to SBTSI_RX_LEN bytes
*/
struct sbtsi_i3c_priv {
struct sbtsi_data data;
diff --git a/include/uapi/misc/amd-apml.h b/include/uapi/misc/amd-apml.h
index 8a85f79b0938..85741b8f4c21 100644
--- a/include/uapi/misc/amd-apml.h
+++ b/include/uapi/misc/amd-apml.h
@@ -10,6 +10,24 @@
/* Mailbox data size for data_in and data_out */
#define AMD_SBI_MB_DATA_SIZE 4
+/* TBAI trace-buffer access message. */
+#define AMD_SBI_MAX_TBAI_DWORDS 32
+#define AMD_SBI_MAX_TBAI_BYTES 128
+#define AMD_SBI_TBAI_INPUT_BYTES 5
+#define AMD_SBI_TBAI_CMD_INDEX 0
+#define AMD_SBI_TBAI_LUT_INDEX 1
+#define AMD_SBI_TBAI_OFFSET_LO 2
+#define AMD_SBI_TBAI_OFFSET_HI 3
+#define AMD_SBI_TBAI_DWORD_RD_INDEX 4
+#define AMD_SBI_TBAI_ACQUIRE 0x31
+#define AMD_SBI_TBAI_FLUSH 0x32
+
+/* Trace buffer target error status reported in fw_ret_code */
+#define AMD_SBI_TBAI_TBT_ERR0 0xDEADBEE0
+#define AMD_SBI_TBAI_TBT_ERR1 0xDEADBEE1
+#define AMD_SBI_TBAI_TBT_ERR2 0xDEADBEE2
+#define AMD_SBI_TBAI_TBT_ERR5 0xDEADBEE5
+
struct apml_mbox_msg {
/*
* Mailbox Message ID
@@ -80,6 +98,35 @@ struct apml_tsi_xfer_msg {
__u8 pad; /* Explicit padding */
};
+/* TBAI trace-buffer access message. */
+struct apml_tbai_msg {
+ /*
+ * Output trace-buffer data read back; accessed either as dwords_out
+ * (up to AMD_SBI_MAX_TBAI_DWORDS dwords) or bytes_out
+ * (up to AMD_SBI_MAX_TBAI_BYTES bytes)
+ */
+ union {
+ __u32 dwords_out[AMD_SBI_MAX_TBAI_DWORDS];
+ __u8 bytes_out[AMD_SBI_MAX_TBAI_BYTES];
+ } data_out;
+ __u32 logging_en; /* Reserved, must be zero */
+ __u32 fw_ret_code; /* TBT error status */
+ /*
+ * Input register bytes written to the device:
+ * [0] command ID (AMD_SBI_TBAI_ACQUIRE: acquire buffer,
+ * AMD_SBI_TBAI_FLUSH: flush/clear buffer)
+ * [1] LUT index; the LUT holds the programmed destination trace
+ * buffer target (TBT) address for each TraceBufferIndex
+ * [2] entry offset low byte
+ * [3] entry offset high byte
+ * [4] Dwords to read (1 to AMD_SBI_MAX_TBAI_DWORDS)
+ * [1]...[4] are used only by AMD_SBI_TBAI_ACQUIRE; flush ignores
+ * them as it resets the TBAI logic for all LUT indices.
+ */
+ __u8 reg_in[AMD_SBI_TBAI_INPUT_BYTES];
+ __u8 pad[3]; /* Explicit padding */
+};
+
/*
* AMD sideband interface base IOCTL
*/
@@ -172,4 +219,35 @@ struct apml_tsi_xfer_msg {
*/
#define SBTSI_IOCTL_REG_XFER_CMD _IOWR(SB_BASE_IOCTL_NR, 4, struct apml_tsi_xfer_msg)
+/**
+ * DOC: SBTBAI_IOCTL_CMD
+ *
+ * @Parameters
+ *
+ * @struct apml_tbai_msg
+ * Pointer to the &struct apml_tbai_msg that will contain the trace-buffer
+ * access information
+ *
+ * @Description
+ * IOCTL command for APML TBAI messages using generic _IOWR
+ * The IOCTL provides userspace APML TBAI trace-buffer access.
+ * TBAI is only available when the SB-TSI device is attached over I3C.
+ *
+ * @Return
+ * 0 on a full read/flush, otherwise:
+ *
+ * * -EOPNOTSUPP: the SB-TSI device is attached over I2C.
+ *
+ * The following are TBAI operation-status codes reported for the
+ * acquire/flush request itself; they are not generic ioctl(2) errors:
+ *
+ * * -EMSGSIZE: short read; less data returned than requested.
+ * data_out is not updated.
+ * * -EPROTOTYPE: trace buffer target (TBT) error; fw_ret_code holds the
+ * AMD_SBI_TBAI_TBT_ERR* code and data_out is zeroed. A 1-dword reply
+ * carrying one of these values cannot be told apart from trace data
+ * and is always reported as an error.
+ */
+#define SBTBAI_IOCTL_CMD _IOWR(SB_BASE_IOCTL_NR, 5, struct apml_tbai_msg)
+
#endif /*_AMD_APML_H_*/
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v1 3/3] docs: amd-sbi: document TBAI trace-buffer ioctl
2026-11-11 5:40 [PATCH v1 0/3] misc: amd-sbi: Add TBAI trace-buffer access over I3C Akshay Gupta
2026-11-11 5:40 ` [PATCH v1 1/3] misc: amd-sbi: use sized DMA-safe I3C tx/rx buffers Akshay Gupta
2026-11-11 5:40 ` [PATCH v1 2/3] misc: amd-sbi: Add TBAI trace-buffer access over I3C Akshay Gupta
@ 2026-11-11 5:40 ` Akshay Gupta
2 siblings, 0 replies; 4+ messages in thread
From: Akshay Gupta @ 2026-11-11 5:40 UTC (permalink / raw)
To: linux-kernel, linux-doc
Cc: arnd, gregkh, corbet, skhan, rdunlap, linux,
naveenkrishna.chatradhi, Anand.Umarji, Prathima Lk, Akshay Gupta
From: Prathima Lk <Prathima.Lk@amd.com>
This change documents the SB-TSI Trace Buffer Acquire Interface (TBAI)
in the amd-sbi guide. It adds a prose section describing the shared
/dev/sbtsi-* node, the I3C-only requirement, the acquire and flush
operations, their return codes, and the serialization with register
access under the device lock.
It also adds the SBTBAI_IOCTL_CMD kernel-doc reference under Driver
IOCTLs and lists the ioctl define in the user-space usage list.
The documentation build was run locally to confirm the new section
and kernel-doc references render without warnings or errors.
Signed-off-by: Prathima Lk <Prathima.Lk@amd.com>
Signed-off-by: Akshay Gupta <Akshay.Gupta@amd.com>
---
Documentation/misc-devices/amd-sbi.rst | 60 +++++++++++++++++++++++++-
1 file changed, 59 insertions(+), 1 deletion(-)
diff --git a/Documentation/misc-devices/amd-sbi.rst b/Documentation/misc-devices/amd-sbi.rst
index 648d743903b7..9cf7c003d00c 100644
--- a/Documentation/misc-devices/amd-sbi.rst
+++ b/Documentation/misc-devices/amd-sbi.rst
@@ -53,7 +53,7 @@ SBTSI device
sbtsi driver under the drivers/misc/amd-sbi creates miscdevice
/dev/sbtsi-* to let user space programs run APML TSI register transfer
-commands.
+and, on I3C targets, TBAI trace-buffer commands.
The driver supports both I2C and I3C transports for SB-TSI targets.
The transport is selected by the bus where the device is enumerated.
@@ -68,10 +68,64 @@ Misc device:
crw------- 1 root root 10, 116 Apr 2 05:22 /dev/sbtsi-4c
+Characteristics of the dev node:
+ * Different xfer protocols are defined:
+ * TSI register xfer (SBTSI_IOCTL_REG_XFER_CMD)
+ * TBAI trace-buffer access (SBTBAI_IOCTL_CMD), I3C only
+ * Requests from both ioctls are serialized under the same device lock.
+
Access restrictions:
* Only root user is allowed to open the file.
* APML TSI Register transfer access is read-write.
+Trace Buffer Acquire Interface (TBAI)
+===========================================
+
+Trace Buffer Acquire Interface (TBAI) is defined in the Thermal
+Management (THM) block for the BMC(external controller) to access the
+Microprocessor's (MP) trace data, and the interface abstracts away the
+Trace buffer target address space for the trace buffer destination.
+
+Trace buffer target (TBT) refers to the on-die destination of a trace
+buffer entry.
+
+The Distributed Trace Buffer feature is to have a common debug tracing
+solution for all MPs, that is natively visible to the BMC (APML/MCTP).
+Each MP (bootcode and off-chip FW) puts trace logs into its local buffer
+and provides an interface called Debug Trace Buffer Acquire
+Interface using SB-TSI registers for the BMC to fetch the debug
+trace data through the THM out of band (OOB) I3C.
+
+TBAI is accessed with SBTBAI_IOCTL_CMD on the same /dev/sbtsi-* node
+as SBTSI_IOCTL_REG_XFER_CMD. It is only supported when the SB-TSI
+target is attached over I3C; on I2C the ioctl returns -EOPNOTSUPP.
+TBAI requests and TSI register transfers share the device lock, so
+they never interleave on the bus.
+
+Two operations are supported, selected by the command byte in the request:
+ * Trace Buffer Acquire (0x31): read 1 to 32 DWORDs of trace data from a
+ given look-up-table (LUT) index and entry offset.
+ * Trace Buffer Flush (0x32): reset the TBAI internal logic when the trace
+ buffer target does not respond. The 32-bit flush status (0xDEADBEEF)
+ is returned in the first DWORD of data_out, low byte first;
+ fw_ret_code is 0.
+
+The ioctl returns:
+ * 0: the request completed. All requested DWORDs are valid in the
+ fixed data_out array of struct apml_tbai_msg.
+ * -EPROTOTYPE: the trace buffer target reported an error. fw_ret_code
+ holds the AMD_SBI_TBAI_TBT_ERR* code and data_out is zeroed.
+ * -EMSGSIZE: the device returned less data than requested. Nothing is
+ copied back to the message.
+ * -EOPNOTSUPP: if the SB-TSI device is attached over I2C.
+
+After -EPROTOTYPE or -EMSGSIZE, issue a Trace Buffer Flush before
+retrying the acquire.
+
+reg_in[4] is the actual number of DWORDs to read, from 1 to
+AMD_SBI_MAX_TBAI_DWORDS. The driver handles the hardware encoding and
+splits requests larger than 8 DWORDs into multiple transactions.
+
SBTSI hwmon interface
=====================
@@ -126,6 +180,9 @@ Driver IOCTLs
.. c:macro:: SBTSI_IOCTL_REG_XFER_CMD
.. kernel-doc:: include/uapi/misc/amd-apml.h
:doc: SBTSI_IOCTL_REG_XFER_CMD
+.. c:macro:: SBTBAI_IOCTL_CMD
+.. kernel-doc:: include/uapi/misc/amd-apml.h
+ :doc: SBTBAI_IOCTL_CMD
User-space usage
================
@@ -166,6 +223,7 @@ The following IOCTLs are defined:
``#define SBRMI_IOCTL_MCAMSR_CMD _IOWR(SB_BASE_IOCTL_NR, 2, struct apml_mcamsr_msg)``
``#define SBRMI_IOCTL_REG_XFER_CMD _IOWR(SB_BASE_IOCTL_NR, 3, struct apml_reg_xfer_msg)``
``#define SBTSI_IOCTL_REG_XFER_CMD _IOWR(SB_BASE_IOCTL_NR, 4, struct apml_tsi_xfer_msg)``
+``#define SBTBAI_IOCTL_CMD _IOWR(SB_BASE_IOCTL_NR, 5, struct apml_tbai_msg)``
User space C-APIs are made available by esmi_oob_library, hosted at
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-11 5:41 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-11 5:40 [PATCH v1 0/3] misc: amd-sbi: Add TBAI trace-buffer access over I3C Akshay Gupta
2026-11-11 5:40 ` [PATCH v1 1/3] misc: amd-sbi: use sized DMA-safe I3C tx/rx buffers Akshay Gupta
2026-11-11 5:40 ` [PATCH v1 2/3] misc: amd-sbi: Add TBAI trace-buffer access over I3C Akshay Gupta
2026-11-11 5:40 ` [PATCH v1 3/3] docs: amd-sbi: document TBAI trace-buffer ioctl Akshay Gupta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®