[PATCH 1/2] PCI: dwc: Add LTSSM tracing support to debugfs

Krishna Chaitanya Chundru krishna.chundru at oss.qualcomm.com
Wed Jan 7 02:09:26 PST 2026



On 1/7/2026 3:11 PM, Shawn Lin wrote:
> 在 2026/01/07 星期三 17:12, Krishna Chaitanya Chundru 写道:
>>
>>
>> On 1/6/2026 2:48 PM, Shawn Lin wrote:
>>> Some platforms may provide LTSSM trace functionality, recording 
>>> historical
>>> LTSSM state transition information. This is very useful for 
>>> debugging, such
>>> as when certain devices cannot be recognized. Add an ltssm_trace 
>>> operation
>>> node in debugfs for platform which could provide these information 
>>> to show
>>> the LTSSM history.
>>>
>>> Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
>>> ---
>>>   .../controller/dwc/pcie-designware-debugfs.c  | 44 
>>> +++++++++++++++++++
>>>   drivers/pci/controller/dwc/pcie-designware.h  |  6 +++
>>>   2 files changed, 50 insertions(+)
>>>
>>> diff --git a/drivers/pci/controller/dwc/pcie-designware-debugfs.c b/ 
>>> drivers/pci/controller/dwc/pcie-designware-debugfs.c
>>> index df98fee69892..569e8e078ef2 100644
>>> --- a/drivers/pci/controller/dwc/pcie-designware-debugfs.c
>>> +++ b/drivers/pci/controller/dwc/pcie-designware-debugfs.c
>>> @@ -511,6 +511,38 @@ static int ltssm_status_open(struct inode 
>>> *inode, struct file *file)
>>>       return single_open(file, ltssm_status_show, inode->i_private);
>>>   }
>>> +static struct dw_pcie_ltssm_history *dw_pcie_ltssm_trace(struct 
>>> dw_pcie *pci)
>>> +{
>>> +    if (pci->ops && pci->ops->ltssm_trace)
>>> +        return pci->ops->ltssm_trace(pci);
>>> +
>>> +    return NULL;
>>> +}
>>> +
>>> +static int ltssm_trace_show(struct seq_file *s, void *v)
>>> +{
>>> +    struct dw_pcie *pci = s->private;
>>> +    struct dw_pcie_ltssm_history *history;
>>> +    enum dw_pcie_ltssm val;
>>> +    u32 loop;
>>> +
>>> +    history = dw_pcie_ltssm_trace(pci);
>>> +    if (!history)
>>> +        return 0;
>>> +
>>> +    for (loop = 0; loop < history->count; loop++) {
>>> +        val = history->states[loop];
>>> +        seq_printf(s, "%s (0x%02x)\n", ltssm_status_string(val), val);
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int ltssm_trace_open(struct inode *inode, struct file *file)
>>> +{
>>> +    return single_open(file, ltssm_trace_show, inode->i_private);
>>> +}
>>> +
>>>   #define dwc_debugfs_create(name)            \
>>>   debugfs_create_file(#name, 0644, rasdes_debug, pci,    \
>>>               &dbg_ ## name ## _fops)
>>> @@ -552,6 +584,11 @@ static const struct file_operations 
>>> dwc_pcie_ltssm_status_ops = {
>>>       .read = seq_read,
>>>   };
>>> +static const struct file_operations dwc_pcie_ltssm_trace_ops = {
>>> +    .open = ltssm_trace_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;
>>> @@ -644,6 +681,12 @@ static void dwc_pcie_ltssm_debugfs_init(struct 
>>> dw_pcie *pci, struct dentry *dir)
>>>                   &dwc_pcie_ltssm_status_ops);
>>>   }
>>> +static void dwc_pcie_ltssm_trace_debugfs_init(struct dw_pcie *pci, 
>>> struct dentry *dir)
>>> +{
>>> +    debugfs_create_file("ltssm_trace", 0444, dir, pci,
>>> +                &dwc_pcie_ltssm_trace_ops);
>> Can we have this as the sysfs, so that if there is some issue in 
>> production devices where debugfs is not available,
>> we can use this to see LTSSM state figure out the issue.
>>
>
> Thanks for the input. I think the ltssm_trace is debug in nature, just 
> like the existing ltssm and rasdes_debug nodes, so it probably fits 
> better under debugfs for consistency. Moreover, given most time we
> combine rasdes_debug and ltssmm history to debug issues, if we split it
> out, we’d end up with two separate debugging areas, which feels a bit
> fragmented and less clear. 
Rasdes has statistics and err injection along with debug feature, we can 
have them
as debugfs only since they will not help in debugging production issues. 
For others like
ltssm, lane_detect & rx_valid we can have in sysfs.

- Krishna Chaitanya.
>
>
>> - Krishna Chaitanya.
>>> +}
>>> +
>>>   static int dw_pcie_ptm_check_capability(void *drvdata)
>>>   {
>>>       struct dw_pcie *pci = drvdata;
>>> @@ -922,6 +965,7 @@ void dwc_pcie_debugfs_init(struct dw_pcie *pci, 
>>> enum dw_pcie_device_mode mode)
>>>               err);
>>>       dwc_pcie_ltssm_debugfs_init(pci, dir);
>>> +    dwc_pcie_ltssm_trace_debugfs_init(pci, dir);
>>>       pci->mode = mode;
>>>       pci->ptm_debugfs = pcie_ptm_create_debugfs(pci->dev, pci,
>>> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/ 
>>> pci/controller/dwc/pcie-designware.h
>>> index 5cd27f5739f1..0df18995b7fe 100644
>>> --- a/drivers/pci/controller/dwc/pcie-designware.h
>>> +++ b/drivers/pci/controller/dwc/pcie-designware.h
>>> @@ -395,6 +395,11 @@ enum dw_pcie_ltssm {
>>>       DW_PCIE_LTSSM_UNKNOWN = 0xFFFFFFFF,
>>>   };
>>> +struct dw_pcie_ltssm_history {
>>> +    enum dw_pcie_ltssm *states;
>>> +    u32 count;
>>> +};
>>> +
>>>   struct dw_pcie_ob_atu_cfg {
>>>       int index;
>>>       int type;
>>> @@ -499,6 +504,7 @@ struct dw_pcie_ops {
>>>                     size_t size, u32 val);
>>>       bool    (*link_up)(struct dw_pcie *pcie);
>>>       enum dw_pcie_ltssm (*get_ltssm)(struct dw_pcie *pcie);
>>> +    struct dw_pcie_ltssm_history * (*ltssm_trace)(struct dw_pcie 
>>> *pcie);
>>>       int    (*start_link)(struct dw_pcie *pcie);
>>>       void    (*stop_link)(struct dw_pcie *pcie);
>>>       int    (*assert_perst)(struct dw_pcie *pcie, bool assert);
>>
>>
>




More information about the Linux-rockchip mailing list