Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'pci/trace'

- Add generic RAS tracepoint for hotplug events (Shuai Xue)

- Add RAS tracepoint for link speed changes (Shuai Xue)

* pci/trace:
Documentation: tracing: Add PCI tracepoint documentation
PCI: trace: Add RAS tracepoint to monitor link speed changes
PCI: trace: Add generic RAS tracepoint for hotplug event

+280 -15
+74
Documentation/trace/events-pci.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + =========================== 4 + Subsystem Trace Points: PCI 5 + =========================== 6 + 7 + Overview 8 + ======== 9 + The PCI tracing system provides tracepoints to monitor critical hardware events 10 + that can impact system performance and reliability. These events normally show 11 + up here: 12 + 13 + /sys/kernel/tracing/events/pci 14 + 15 + Cf. include/trace/events/pci.h for the events definitions. 16 + 17 + Available Tracepoints 18 + ===================== 19 + 20 + pci_hp_event 21 + ------------ 22 + 23 + Monitors PCI hotplug events including card insertion/removal and link 24 + state changes. 25 + :: 26 + 27 + pci_hp_event "%s slot:%s, event:%s\n" 28 + 29 + **Event Types**: 30 + 31 + * ``LINK_UP`` - PCIe link established 32 + * ``LINK_DOWN`` - PCIe link lost 33 + * ``CARD_PRESENT`` - Card detected in slot 34 + * ``CARD_NOT_PRESENT`` - Card removed from slot 35 + 36 + **Example Usage**:: 37 + 38 + # Enable the tracepoint 39 + echo 1 > /sys/kernel/debug/tracing/events/pci/pci_hp_event/enable 40 + 41 + # Monitor events (the following output is generated when a device is hotplugged) 42 + cat /sys/kernel/debug/tracing/trace_pipe 43 + irq/51-pciehp-88 [001] ..... 1311.177459: pci_hp_event: 0000:00:02.0 slot:10, event:CARD_PRESENT 44 + 45 + irq/51-pciehp-88 [001] ..... 1311.177566: pci_hp_event: 0000:00:02.0 slot:10, event:LINK_UP 46 + 47 + pcie_link_event 48 + --------------- 49 + 50 + Monitors PCIe link speed changes and provides detailed link status information. 51 + :: 52 + 53 + pcie_link_event "%s type:%d, reason:%d, cur_bus_speed:%d, max_bus_speed:%d, width:%u, flit_mode:%u, status:%s\n" 54 + 55 + **Parameters**: 56 + 57 + * ``type`` - PCIe device type (4=Root Port, etc.) 58 + * ``reason`` - Reason for link change: 59 + 60 + - ``0`` - Link retrain 61 + - ``1`` - Bus enumeration 62 + - ``2`` - Bandwidth notification enable 63 + - ``3`` - Bandwidth notification IRQ 64 + - ``4`` - Hotplug event 65 + 66 + 67 + **Example Usage**:: 68 + 69 + # Enable the tracepoint 70 + echo 1 > /sys/kernel/debug/tracing/events/pci/pcie_link_event/enable 71 + 72 + # Monitor events (the following output is generated when a device is hotplugged) 73 + cat /sys/kernel/debug/tracing/trace_pipe 74 + irq/51-pciehp-88 [001] ..... 381.545386: pcie_link_event: 0000:00:02.0 type:4, reason:4, cur_bus_speed:20, max_bus_speed:23, width:1, flit_mode:0, status:DLLLA
+1
Documentation/trace/index.rst
··· 54 54 events-power 55 55 events-nmi 56 56 events-msr 57 + events-pci 57 58 boottime-trace 58 59 histogram 59 60 histogram-design
+3
drivers/pci/Makefile
··· 48 48 obj-y += switch/ 49 49 50 50 subdir-ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG 51 + 52 + CFLAGS_trace.o := -I$(src) 53 + obj-$(CONFIG_TRACING) += trace.o
+25 -6
drivers/pci/hotplug/pciehp_ctrl.c
··· 19 19 #include <linux/types.h> 20 20 #include <linux/pm_runtime.h> 21 21 #include <linux/pci.h> 22 + #include <trace/events/pci.h> 22 23 23 24 #include "../pci.h" 24 25 #include "pciehp.h" ··· 245 244 case ON_STATE: 246 245 ctrl->state = POWEROFF_STATE; 247 246 mutex_unlock(&ctrl->state_lock); 248 - if (events & PCI_EXP_SLTSTA_DLLSC) 247 + if (events & PCI_EXP_SLTSTA_DLLSC) { 249 248 ctrl_info(ctrl, "Slot(%s): Link Down\n", 250 249 slot_name(ctrl)); 251 - if (events & PCI_EXP_SLTSTA_PDC) 250 + trace_pci_hp_event(pci_name(ctrl->pcie->port), 251 + slot_name(ctrl), 252 + PCI_HOTPLUG_LINK_DOWN); 253 + } 254 + if (events & PCI_EXP_SLTSTA_PDC) { 252 255 ctrl_info(ctrl, "Slot(%s): Card not present\n", 253 256 slot_name(ctrl)); 257 + trace_pci_hp_event(pci_name(ctrl->pcie->port), 258 + slot_name(ctrl), 259 + PCI_HOTPLUG_CARD_NOT_PRESENT); 260 + } 254 261 pciehp_disable_slot(ctrl, SURPRISE_REMOVAL); 255 262 break; 256 263 default: ··· 278 269 INDICATOR_NOOP); 279 270 ctrl_info(ctrl, "Slot(%s): Card not present\n", 280 271 slot_name(ctrl)); 272 + trace_pci_hp_event(pci_name(ctrl->pcie->port), 273 + slot_name(ctrl), 274 + PCI_HOTPLUG_CARD_NOT_PRESENT); 281 275 } 282 276 mutex_unlock(&ctrl->state_lock); 283 277 return; ··· 293 281 case OFF_STATE: 294 282 ctrl->state = POWERON_STATE; 295 283 mutex_unlock(&ctrl->state_lock); 296 - if (present) 284 + if (present) { 297 285 ctrl_info(ctrl, "Slot(%s): Card present\n", 298 286 slot_name(ctrl)); 299 - if (link_active) 300 - ctrl_info(ctrl, "Slot(%s): Link Up\n", 301 - slot_name(ctrl)); 287 + trace_pci_hp_event(pci_name(ctrl->pcie->port), 288 + slot_name(ctrl), 289 + PCI_HOTPLUG_CARD_PRESENT); 290 + } 291 + if (link_active) { 292 + ctrl_info(ctrl, "Slot(%s): Link Up\n", slot_name(ctrl)); 293 + trace_pci_hp_event(pci_name(ctrl->pcie->port), 294 + slot_name(ctrl), 295 + PCI_HOTPLUG_LINK_UP); 296 + } 302 297 ctrl->request_result = pciehp_enable_slot(ctrl); 303 298 break; 304 299 default:
+2 -1
drivers/pci/hotplug/pciehp_hpc.c
··· 320 320 } 321 321 322 322 pcie_capability_read_word(pdev, PCI_EXP_LNKSTA2, &linksta2); 323 - __pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status, linksta2); 323 + __pcie_update_link_speed(ctrl->pcie->port->subordinate, PCIE_HOTPLUG, 324 + lnk_status, linksta2); 324 325 325 326 if (!found) { 326 327 ctrl_info(ctrl, "Slot(%s): No device found\n",
+1 -1
drivers/pci/pci.c
··· 4553 4553 * Link Speed. 4554 4554 */ 4555 4555 if (pdev->subordinate) 4556 - pcie_update_link_speed(pdev->subordinate); 4556 + pcie_update_link_speed(pdev->subordinate, PCIE_LINK_RETRAIN); 4557 4557 4558 4558 return rc; 4559 4559 }
+19 -2
drivers/pci/pci.h
··· 5 5 #include <linux/align.h> 6 6 #include <linux/bitfield.h> 7 7 #include <linux/pci.h> 8 + #include <trace/events/pci.h> 8 9 9 10 struct pcie_tlp_log; 10 11 ··· 602 601 void __pcie_print_link_status(struct pci_dev *dev, bool verbose); 603 602 void pcie_report_downtraining(struct pci_dev *dev); 604 603 605 - static inline void __pcie_update_link_speed(struct pci_bus *bus, u16 linksta, u16 linksta2) 604 + enum pcie_link_change_reason { 605 + PCIE_LINK_RETRAIN, 606 + PCIE_ADD_BUS, 607 + PCIE_BWCTRL_ENABLE, 608 + PCIE_BWCTRL_IRQ, 609 + PCIE_HOTPLUG, 610 + }; 611 + 612 + static inline void __pcie_update_link_speed(struct pci_bus *bus, 613 + enum pcie_link_change_reason reason, 614 + u16 linksta, u16 linksta2) 606 615 { 607 616 bus->cur_bus_speed = pcie_link_speed[linksta & PCI_EXP_LNKSTA_CLS]; 608 617 bus->flit_mode = (linksta2 & PCI_EXP_LNKSTA2_FLIT) ? 1 : 0; 618 + 619 + trace_pcie_link_event(bus, 620 + reason, 621 + FIELD_GET(PCI_EXP_LNKSTA_NLW, linksta), 622 + linksta & PCI_EXP_LNKSTA_LINK_STATUS_MASK); 609 623 } 610 - void pcie_update_link_speed(struct pci_bus *bus); 624 + 625 + void pcie_update_link_speed(struct pci_bus *bus, enum pcie_link_change_reason reason); 611 626 612 627 /* Single Root I/O Virtualization */ 613 628 struct pci_sriov {
+2 -2
drivers/pci/pcie/bwctrl.c
··· 199 199 * Update after enabling notifications & clearing status bits ensures 200 200 * link speed is up to date. 201 201 */ 202 - pcie_update_link_speed(port->subordinate); 202 + pcie_update_link_speed(port->subordinate, PCIE_BWCTRL_ENABLE); 203 203 } 204 204 205 205 static void pcie_bwnotif_disable(struct pci_dev *port) ··· 234 234 * speed (inside pcie_update_link_speed()) after LBMS has been 235 235 * cleared to avoid missing link speed changes. 236 236 */ 237 - pcie_update_link_speed(port->subordinate); 237 + pcie_update_link_speed(port->subordinate, PCIE_BWCTRL_IRQ); 238 238 239 239 return IRQ_HANDLED; 240 240 }
+6 -3
drivers/pci/probe.c
··· 23 23 #include <linux/irqdomain.h> 24 24 #include <linux/pm_runtime.h> 25 25 #include <linux/bitfield.h> 26 + #include <trace/events/pci.h> 26 27 #include "pci.h" 27 28 28 29 static struct resource busn_resource = { ··· 821 820 } 822 821 EXPORT_SYMBOL_GPL(pci_speed_string); 823 822 824 - void pcie_update_link_speed(struct pci_bus *bus) 823 + void pcie_update_link_speed(struct pci_bus *bus, 824 + enum pcie_link_change_reason reason) 825 825 { 826 826 struct pci_dev *bridge = bus->self; 827 827 u16 linksta, linksta2; 828 828 829 829 pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta); 830 830 pcie_capability_read_word(bridge, PCI_EXP_LNKSTA2, &linksta2); 831 - __pcie_update_link_speed(bus, linksta, linksta2); 831 + 832 + __pcie_update_link_speed(bus, reason, linksta, linksta2); 832 833 } 833 834 EXPORT_SYMBOL_GPL(pcie_update_link_speed); 834 835 ··· 917 914 pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap); 918 915 bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS]; 919 916 920 - pcie_update_link_speed(bus); 917 + pcie_update_link_speed(bus, PCIE_ADD_BUS); 921 918 } 922 919 } 923 920
+11
drivers/pci/trace.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Tracepoints for PCI system 4 + * 5 + * Copyright (C) 2025 Alibaba Corporation 6 + */ 7 + 8 + #include <linux/pci.h> 9 + 10 + #define CREATE_TRACE_POINTS 11 + #include <trace/events/pci.h>
+129
include/trace/events/pci.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #undef TRACE_SYSTEM 3 + #define TRACE_SYSTEM pci 4 + 5 + #if !defined(_TRACE_HW_EVENT_PCI_H) || defined(TRACE_HEADER_MULTI_READ) 6 + #define _TRACE_HW_EVENT_PCI_H 7 + 8 + #include <uapi/linux/pci_regs.h> 9 + #include <linux/tracepoint.h> 10 + 11 + #define PCI_HOTPLUG_EVENT \ 12 + EM(PCI_HOTPLUG_LINK_UP, "LINK_UP") \ 13 + EM(PCI_HOTPLUG_LINK_DOWN, "LINK_DOWN") \ 14 + EM(PCI_HOTPLUG_CARD_PRESENT, "CARD_PRESENT") \ 15 + EMe(PCI_HOTPLUG_CARD_NOT_PRESENT, "CARD_NOT_PRESENT") 16 + 17 + /* Enums require being exported to userspace, for user tool parsing */ 18 + #undef EM 19 + #undef EMe 20 + #define EM(a, b) TRACE_DEFINE_ENUM(a); 21 + #define EMe(a, b) TRACE_DEFINE_ENUM(a); 22 + 23 + PCI_HOTPLUG_EVENT 24 + 25 + /* 26 + * Now redefine the EM() and EMe() macros to map the enums to the strings 27 + * that will be printed in the output. 28 + */ 29 + #undef EM 30 + #undef EMe 31 + #define EM(a, b) {a, b}, 32 + #define EMe(a, b) {a, b} 33 + 34 + /* 35 + * Note: For generic PCI hotplug events, we pass already-resolved strings 36 + * (port_name, slot) instead of driver-specific structures like 'struct 37 + * controller'. This is because different PCI hotplug drivers (pciehp, cpqphp, 38 + * ibmphp, shpchp) define their own versions of 'struct controller' with 39 + * different fields and helper functions. Using driver-specific structures would 40 + * make the tracepoint interface non-generic and cause compatibility issues 41 + * across different drivers. 42 + */ 43 + TRACE_EVENT(pci_hp_event, 44 + 45 + TP_PROTO(const char *port_name, 46 + const char *slot, 47 + const int event), 48 + 49 + TP_ARGS(port_name, slot, event), 50 + 51 + TP_STRUCT__entry( 52 + __string( port_name, port_name ) 53 + __string( slot, slot ) 54 + __field( int, event ) 55 + ), 56 + 57 + TP_fast_assign( 58 + __assign_str(port_name); 59 + __assign_str(slot); 60 + __entry->event = event; 61 + ), 62 + 63 + TP_printk("%s slot:%s, event:%s\n", 64 + __get_str(port_name), 65 + __get_str(slot), 66 + __print_symbolic(__entry->event, PCI_HOTPLUG_EVENT) 67 + ) 68 + ); 69 + 70 + #define PCI_EXP_LNKSTA_LINK_STATUS_MASK (PCI_EXP_LNKSTA_LBMS | \ 71 + PCI_EXP_LNKSTA_LABS | \ 72 + PCI_EXP_LNKSTA_LT | \ 73 + PCI_EXP_LNKSTA_DLLLA) 74 + 75 + #define LNKSTA_FLAGS \ 76 + { PCI_EXP_LNKSTA_LT, "LT"}, \ 77 + { PCI_EXP_LNKSTA_DLLLA, "DLLLA"}, \ 78 + { PCI_EXP_LNKSTA_LBMS, "LBMS"}, \ 79 + { PCI_EXP_LNKSTA_LABS, "LABS"} 80 + 81 + TRACE_EVENT(pcie_link_event, 82 + 83 + TP_PROTO(struct pci_bus *bus, 84 + unsigned int reason, 85 + unsigned int width, 86 + unsigned int status 87 + ), 88 + 89 + TP_ARGS(bus, reason, width, status), 90 + 91 + TP_STRUCT__entry( 92 + __string( port_name, pci_name(bus->self)) 93 + __field( unsigned int, type ) 94 + __field( unsigned int, reason ) 95 + __field( unsigned int, cur_bus_speed ) 96 + __field( unsigned int, max_bus_speed ) 97 + __field( unsigned int, width ) 98 + __field( unsigned int, flit_mode ) 99 + __field( unsigned int, link_status ) 100 + ), 101 + 102 + TP_fast_assign( 103 + __assign_str(port_name); 104 + __entry->type = pci_pcie_type(bus->self); 105 + __entry->reason = reason; 106 + __entry->cur_bus_speed = bus->cur_bus_speed; 107 + __entry->max_bus_speed = bus->max_bus_speed; 108 + __entry->width = width; 109 + __entry->flit_mode = bus->flit_mode; 110 + __entry->link_status = status; 111 + ), 112 + 113 + TP_printk("%s type:%d, reason:%d, cur_bus_speed:%d, max_bus_speed:%d, width:%u, flit_mode:%u, status:%s\n", 114 + __get_str(port_name), 115 + __entry->type, 116 + __entry->reason, 117 + __entry->cur_bus_speed, 118 + __entry->max_bus_speed, 119 + __entry->width, 120 + __entry->flit_mode, 121 + __print_flags((unsigned long)__entry->link_status, "|", 122 + LNKSTA_FLAGS) 123 + ) 124 + ); 125 + 126 + #endif /* _TRACE_HW_EVENT_PCI_H */ 127 + 128 + /* This part must be outside protection */ 129 + #include <trace/define_trace.h>
+7
include/uapi/linux/pci.h
··· 39 39 #define PCIIOC_MMAP_IS_MEM (PCIIOC_BASE | 0x02) /* Set mmap state to MEM space. */ 40 40 #define PCIIOC_WRITE_COMBINE (PCIIOC_BASE | 0x03) /* Enable/disable write-combining. */ 41 41 42 + enum pci_hotplug_event { 43 + PCI_HOTPLUG_LINK_UP, 44 + PCI_HOTPLUG_LINK_DOWN, 45 + PCI_HOTPLUG_CARD_PRESENT, 46 + PCI_HOTPLUG_CARD_NOT_PRESENT, 47 + }; 48 + 42 49 #endif /* _UAPILINUX_PCI_H */