PCI: dwc: Add debugfs property to provide LTSSM status of the PCIe link

Add the debugfs property to provide a view of the current link's LTSSM
status from the Root Port device.

Signed-off-by: Hans Zhang <18255117159@163.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Niklas Cassel <cassel@kernel.org>
Tested-by: Hrishikesh Deleep <hrishikesh.d@samsung.com>
Link: https://lore.kernel.org/r/20250223141848.231232-1-18255117159@163.com
[kwilczynski: commit log, refactor dw_ltssm_sts_string() to avoid
compilation errors on platforms that do not set CONFIG_PCIE_DW_HOST]
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
This commit is contained in:
Hans Zhang 2025-02-23 22:18:48 +08:00 committed by Krzysztof Wilczyński
parent 27491ac2cc
commit f0f3044d22
No known key found for this signature in database
GPG key ID: 7C64768D3DE334E7
3 changed files with 116 additions and 0 deletions

View file

@ -149,3 +149,9 @@ Description: (RW) Some lanes in the event list are lane specific events.
the lane number for which you wish the counter to be enabled,
disabled, or value dumped. Read will return the current
selected lane number. Lane0 is selected by default.
What: /sys/kernel/debug/dwc_pcie_<dev>/ltssm_status
Date: February 2025
Contact: Hans Zhang <18255117159@163.com>
Description: (RO) Read will return the current PCIe LTSSM state in both
string and raw value.

View file

@ -443,6 +443,72 @@ static ssize_t counter_value_read(struct file *file, char __user *buf,
return simple_read_from_buffer(buf, count, ppos, debugfs_buf, pos);
}
static const char *ltssm_status_string(enum dw_pcie_ltssm ltssm)
{
const char *str;
switch (ltssm) {
#define DW_PCIE_LTSSM_NAME(n) case n: str = #n; break
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_DETECT_QUIET);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_DETECT_ACT);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_POLL_ACTIVE);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_POLL_COMPLIANCE);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_POLL_CONFIG);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_PRE_DETECT_QUIET);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_DETECT_WAIT);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_CFG_LINKWD_START);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_CFG_LINKWD_ACEPT);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_CFG_LANENUM_WAI);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_CFG_LANENUM_ACEPT);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_CFG_COMPLETE);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_CFG_IDLE);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_RCVRY_LOCK);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_RCVRY_SPEED);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_RCVRY_RCVRCFG);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_RCVRY_IDLE);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_L0);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_L0S);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_L123_SEND_EIDLE);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_L1_IDLE);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_L2_IDLE);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_L2_WAKE);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_DISABLED_ENTRY);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_DISABLED_IDLE);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_DISABLED);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_LPBK_ENTRY);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_LPBK_ACTIVE);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_LPBK_EXIT);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_LPBK_EXIT_TIMEOUT);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_HOT_RESET_ENTRY);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_HOT_RESET);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_RCVRY_EQ0);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_RCVRY_EQ1);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_RCVRY_EQ2);
DW_PCIE_LTSSM_NAME(DW_PCIE_LTSSM_RCVRY_EQ3);
default:
str = "DW_PCIE_LTSSM_UNKNOWN";
break;
}
return str + strlen("DW_PCIE_LTSSM_");
}
static int ltssm_status_show(struct seq_file *s, void *v)
{
struct dw_pcie *pci = s->private;
enum dw_pcie_ltssm val;
val = dw_pcie_get_ltssm(pci);
seq_printf(s, "%s (0x%02x)\n", ltssm_status_string(val), val);
return 0;
}
static int ltssm_status_open(struct inode *inode, struct file *file)
{
return single_open(file, ltssm_status_show, inode->i_private);
}
#define dwc_debugfs_create(name) \
debugfs_create_file(#name, 0644, rasdes_debug, pci, \
&dbg_ ## name ## _fops)
@ -479,6 +545,11 @@ static const struct file_operations dwc_pcie_counter_value_ops = {
.read = counter_value_read,
};
static const struct file_operations dwc_pcie_ltssm_status_ops = {
.open = ltssm_status_open,
.read = seq_read,
};
static void dwc_pcie_rasdes_debugfs_deinit(struct dw_pcie *pci)
{
struct dwc_pcie_rasdes_info *rinfo = pci->debugfs->rasdes_info;
@ -565,6 +636,12 @@ err_deinit:
return ret;
}
static void dwc_pcie_ltssm_debugfs_init(struct dw_pcie *pci, struct dentry *dir)
{
debugfs_create_file("ltssm_status", 0444, dir, pci,
&dwc_pcie_ltssm_status_ops);
}
void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)
{
if (!pci->debugfs)
@ -595,4 +672,6 @@ void dwc_pcie_debugfs_init(struct dw_pcie *pci)
if (err)
dev_err(dev, "failed to initialize RAS DES debugfs, err=%d\n",
err);
dwc_pcie_ltssm_debugfs_init(pci, dir);
}

View file

@ -330,9 +330,40 @@ enum dw_pcie_ltssm {
/* Need to align with PCIE_PORT_DEBUG0 bits 0:5 */
DW_PCIE_LTSSM_DETECT_QUIET = 0x0,
DW_PCIE_LTSSM_DETECT_ACT = 0x1,
DW_PCIE_LTSSM_POLL_ACTIVE = 0x2,
DW_PCIE_LTSSM_POLL_COMPLIANCE = 0x3,
DW_PCIE_LTSSM_POLL_CONFIG = 0x4,
DW_PCIE_LTSSM_PRE_DETECT_QUIET = 0x5,
DW_PCIE_LTSSM_DETECT_WAIT = 0x6,
DW_PCIE_LTSSM_CFG_LINKWD_START = 0x7,
DW_PCIE_LTSSM_CFG_LINKWD_ACEPT = 0x8,
DW_PCIE_LTSSM_CFG_LANENUM_WAI = 0x9,
DW_PCIE_LTSSM_CFG_LANENUM_ACEPT = 0xa,
DW_PCIE_LTSSM_CFG_COMPLETE = 0xb,
DW_PCIE_LTSSM_CFG_IDLE = 0xc,
DW_PCIE_LTSSM_RCVRY_LOCK = 0xd,
DW_PCIE_LTSSM_RCVRY_SPEED = 0xe,
DW_PCIE_LTSSM_RCVRY_RCVRCFG = 0xf,
DW_PCIE_LTSSM_RCVRY_IDLE = 0x10,
DW_PCIE_LTSSM_L0 = 0x11,
DW_PCIE_LTSSM_L0S = 0x12,
DW_PCIE_LTSSM_L123_SEND_EIDLE = 0x13,
DW_PCIE_LTSSM_L1_IDLE = 0x14,
DW_PCIE_LTSSM_L2_IDLE = 0x15,
DW_PCIE_LTSSM_L2_WAKE = 0x16,
DW_PCIE_LTSSM_DISABLED_ENTRY = 0x17,
DW_PCIE_LTSSM_DISABLED_IDLE = 0x18,
DW_PCIE_LTSSM_DISABLED = 0x19,
DW_PCIE_LTSSM_LPBK_ENTRY = 0x1a,
DW_PCIE_LTSSM_LPBK_ACTIVE = 0x1b,
DW_PCIE_LTSSM_LPBK_EXIT = 0x1c,
DW_PCIE_LTSSM_LPBK_EXIT_TIMEOUT = 0x1d,
DW_PCIE_LTSSM_HOT_RESET_ENTRY = 0x1e,
DW_PCIE_LTSSM_HOT_RESET = 0x1f,
DW_PCIE_LTSSM_RCVRY_EQ0 = 0x20,
DW_PCIE_LTSSM_RCVRY_EQ1 = 0x21,
DW_PCIE_LTSSM_RCVRY_EQ2 = 0x22,
DW_PCIE_LTSSM_RCVRY_EQ3 = 0x23,
DW_PCIE_LTSSM_UNKNOWN = 0xFFFFFFFF,
};