On Tue, Feb 24, 2026 at 05:22:35PM +0200, Ilpo Järvinen wrote:
> On Thu, 22 Jan 2026, 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 or link broken during test.
> > Implement the pci controller tracepoint for recording LTSSM and rate.
> >
> > Signed-off-by: Shawn Lin <[email protected]>
> > ---
> >
> > Changes in v4:
> > - use TRACE_EVENT_FN to notify when to start and stop the tracepoint,
> > and export pci_ltssm_tp_enabled() for host drivers to use
> >
> > Changes in v3:
> > - add TRACE_DEFINE_ENUM for all enums(Steven Rostedt)
> >
> > Changes in v2: None
> >
> > drivers/pci/trace.c | 20 ++++++++++++
> > include/linux/pci.h | 4 +++
> > include/trace/events/pci_controller.h | 57
> > +++++++++++++++++++++++++++++++++++
> > 3 files changed, 81 insertions(+)
> > create mode 100644 include/trace/events/pci_controller.h
> >
> > diff --git a/drivers/pci/trace.c b/drivers/pci/trace.c
> > index cf11abc..d351a51 100644
> > --- a/drivers/pci/trace.c
> > +++ b/drivers/pci/trace.c
> > @@ -9,3 +9,23 @@
> >
> > #define CREATE_TRACE_POINTS
> > #include <trace/events/pci.h>
> > +#include <trace/events/pci_controller.h>
> > +
> > +static atomic_t pcie_ltssm_tp_enabled = ATOMIC_INIT(0);
> > +
> > +bool pci_ltssm_tp_enabled(void)
> > +{
> > + return atomic_read(&pcie_ltssm_tp_enabled) > 0;
> > +}
> > +EXPORT_SYMBOL(pci_ltssm_tp_enabled);
> > +
> > +int pci_ltssm_tp_reg(void)
> > +{
> > + atomic_inc(&pcie_ltssm_tp_enabled);
> > + return 0;
> > +}
> > +
> > +void pci_ltssm_tp_unreg(void)
> > +{
> > + atomic_dec(&pcie_ltssm_tp_enabled);
> > +}
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index e7cb527..ac25a3e 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -2770,6 +2770,10 @@ static inline struct eeh_dev
> > *pci_dev_to_eeh_dev(struct pci_dev *pdev)
> > }
> > #endif
> >
> > +#ifdef CONFIG_TRACING
> > +bool pci_ltssm_tp_enabled(void);
> > +#endif
> > +
> > void pci_add_dma_alias(struct pci_dev *dev, u8 devfn_from, unsigned
> > nr_devfns);
> > bool pci_devs_are_dma_aliases(struct pci_dev *dev1, struct pci_dev *dev2);
> > int pci_for_each_dma_alias(struct pci_dev *pdev,
> > diff --git a/include/trace/events/pci_controller.h
> > b/include/trace/events/pci_controller.h
> > new file mode 100644
> > index 0000000..db4a960
> > --- /dev/null
> > +++ b/include/trace/events/pci_controller.h
> > @@ -0,0 +1,57 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#undef TRACE_SYSTEM
> > +#define TRACE_SYSTEM pci_controller
>
> I find putting this into "pci_controller" little odd as LTSSM is related
> to PCIe links/ports. To me looks something that belongs to the existing
> include/trace/events/pci.h.
>
I suggested 'pci_controller.h' since these tracepoints are only going to be used
by the controller drivers. Putting it under 'pci.h' will imply that these can be
used by the client drivers also.
- Mani
> > +#if !defined(_TRACE_HW_EVENT_PCI_CONTROLLER_H) ||
> > defined(TRACE_HEADER_MULTI_READ)
> > +#define _TRACE_HW_EVENT_PCI_CONTROLLER_H
> > +
> > +#include <uapi/linux/pci_regs.h>
> > +#include <linux/tracepoint.h>
> > +
> > +TRACE_DEFINE_ENUM(PCIE_SPEED_2_5GT);
> > +TRACE_DEFINE_ENUM(PCIE_SPEED_5_0GT);
> > +TRACE_DEFINE_ENUM(PCIE_SPEED_8_0GT);
> > +TRACE_DEFINE_ENUM(PCIE_SPEED_16_0GT);
> > +TRACE_DEFINE_ENUM(PCIE_SPEED_32_0GT);
> > +TRACE_DEFINE_ENUM(PCIE_SPEED_64_0GT);
> > +TRACE_DEFINE_ENUM(PCI_SPEED_UNKNOWN);
> > +
> > +extern int pci_ltssm_tp_reg(void);
> > +extern void pci_ltssm_tp_unreg(void);
> > +
> > +TRACE_EVENT_FN(pcie_ltssm_state_transition,
> > + TP_PROTO(const char *dev_name, const char *state, u32 rate),
> > + TP_ARGS(dev_name, state, rate),
> > +
> > + TP_STRUCT__entry(
> > + __string(dev_name, dev_name)
> > + __string(state, state)
> > + __field(u32, rate)
> > + ),
> > +
> > + TP_fast_assign(
> > + __assign_str(dev_name);
> > + __assign_str(state);
> > + __entry->rate = rate;
> > + ),
> > +
> > + TP_printk("dev: %s state: %s rate: %s",
> > + __get_str(dev_name), __get_str(state),
> > + __print_symbolic(__entry->rate,
> > + { PCIE_SPEED_2_5GT, "2.5 GT/s" },
> > + { PCIE_SPEED_5_0GT, "5.0 GT/s" },
> > + { PCIE_SPEED_8_0GT, "8.0 GT/s" },
> > + { PCIE_SPEED_16_0GT, "16.0 GT/s" },
> > + { PCIE_SPEED_32_0GT, "32.0 GT/s" },
> > + { PCIE_SPEED_64_0GT, "64.0 GT/s" },
> > + { PCI_SPEED_UNKNOWN, "Unknown" }
>
> Why are these done inline instead of using EM/EMe()? Or simply with
> pci_speed_string()?
>
>
> Unrelated to this, sadly I failed to notice Shuai's version of
> pcie_link_event() did not translate link speeds (my own version used
> pci_speed_string()).
>
> > + )
> > + ),
> > +
> > + pci_ltssm_tp_reg, pci_ltssm_tp_unreg
> > +);
> > +
> > +#endif /* _TRACE_HW_EVENT_PCI_CONTROLLER_H */
> > +
> > +/* This part must be outside protection */
> > +#include <trace/define_trace.h>
> >
>
> --
> i.
>
--
மணிவண்ணன் சதாசிவம்