* [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging
@ 2025-02-11 19:24 Terry Bowman
2025-02-11 19:24 ` [PATCH v7 01/17] PCI/AER: Introduce 'struct cxl_err_handlers' and add to 'struct pci_driver' Terry Bowman
` (16 more replies)
0 siblings, 17 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
This patchset (v7) was a quick respin from the v6 patchset. v7 includes
fixes to correctly rebase changes into the expected patch.
The first 6 patches update the existing AER service driver to support CXL
PCIe Port Protocol Error handling and reporting. This includes AER service
driver changes for adding correctable and uncorrectable error support, CXL
specific recovery handling, and addition of CXL driver callback handlers.
The following 10 patches address CXL driver support for CXL PCIe Port
Protocol Errors. This includes the following changes to the CXL drivers:
mapping CXL components' RAS registers, interface updates for common
Restricted CXL host (RCH) and Virtual Hierarchy (VH) modes, adding CXL
Port Protocol Error handlers, introducing CXL tracing for CXL PCIe Port
devices, and adding capability to assign/clear CXL PCIe Port Protocol
Error handlers.
The patches mentioned above also includes a new patch to log the CXL
and PCIe names using dev_name() in the port error trace routines.
Example output is below and in the commit message.
The final patch is new to v6 and changes the Endpoint and RCH DP handling
to use CXL handling instead of PCIe handling. This was not initially
planned to be included in this patchset but found it would be more complex
to support both CXL errors (for CXL ports) and PCIe errors (for Endpoints
and RCH DPs) in the same driver. This final patch completes the support
for all CXL devices to use the CXL handling path.
Also, this patchset includes the removal of a patch present in previous
revisions. The previous patchset added changes to aer_get_device_error_info()
to read USP AER info and has been removed from this version. As a result, in
the case of a USP UCE fatal error the AER is not logged but CXL handlers do
attempt to read and log the RAS.
History details from the RFC can be found here:
https://lore.kernel.org/linux-cxl/20240617200411.1426554-1-terry.bowman@amd.com/
Testing:
========
Below are test results for this patchset using QEMU with CXL Root
Port(RP, 0C:00.0), CXL Upstream Switch Port(USP, 0D:00.0), and CXL
Downstream Switch Port(DSP, 0E:00.0), and Endpoint (EP, 0F:00.0).
The sub-topology for testing is:
---------------------
| CXL RP - 0C:00.0 |
---------------------
|
---------------------
| CXL USP - 0D:00.0 |
---------------------
|
---------------------
| CXL DSP - 0E:00.0 |
---------------------
|
---------------------
| CXL EP - 0F:00.0 |
---------------------
root@tbowman-cxl:~# lspci -t
-+-[0000:00]-+-00.0
| +-01.0
| +-02.0
| +-03.0
| +-1f.0
| +-1f.2
| \-1f.3
\-[0000:0c]---00.0-[0d-0f]----00.0-[0e-0f]----00.0-[0f]----00.0
The topology was created with:
${qemu} -boot menu=on \
-cpu host \
-nographic \
-monitor telnet:127.0.0.1:1234,server,nowait \
-M virt,cxl=on \
-chardev stdio,id=s1,signal=off,mux=on -serial none \
-device isa-serial,chardev=s1 -mon chardev=s1,mode=readline \
-machine q35,cxl=on \
-m 16G,maxmem=24G,slots=8 \
-cpu EPYC-v3 \
-smp 16 \
-accel kvm \
-drive file=${img},format=raw,index=0,media=disk \
-device e1000,netdev=user.0 \
-netdev user,id=user.0,hostfwd=tcp::5555-:22 \
-object memory-backend-file,id=cxl-mem0,share=on,mem-path=/tmp/cxltest.raw,size=256M \
-object memory-backend-file,id=cxl-lsa0,share=on,mem-path=/tmp/lsa0.raw,size=256M \
-device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1 \
-device cxl-rp,port=0,bus=cxl.1,id=root_port0,chassis=0,slot=0 \
-device cxl-upstream,bus=root_port0,id=us0 \
-device cxl-downstream,port=0,bus=us0,id=swport0,chassis=0,slot=4 \
-device cxl-type3,bus=swport0,volatile-memdev=cxl-mem0,lsa=cxl-lsa0,id=cxl-vmem0 \
-M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k
This was tested using the aer-inject tool updated to support CE and UCE
internal Protocol Error injection. CXL port RAS was set using a test patch (not
upstreamed but can provide if needed).
== Root Port Correctable Error ==
root@tbowman-cxl:~/aer-inject# ./root-ce-inject.sh
pcieport 0000:0c:00.0: aer_inject: Injecting errors 00004000/00000000 into device 0000:0c:00.0
pcieport 0000:0c:00.0: AER: Correctable error message received from 0000:0c:00.0
pcieport 0000:0c:00.0: CXL Bus Error: severity=Correctable, type=Transaction Layer, (Receiver ID)
pcieport 0000:0c:00.0: device [8086:7075] error status/mask=00004000/0000a000
pcieport 0000:0c:00.0: [14] CorrIntErr
aer_event: 0000:0c:00.0 CXL Bus Error: severity=Corrected, Corrected Internal Error, TLP Header=Not available
cxl_port_aer_correctable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status='Received Error From Physical Layer'
== Root Port UnCorrectable Error ==
root@tbowman-cxl:~/aer-inject# ./root-uce-inject.sh
pcieport 0000:0c:00.0: aer_inject: Injecting errors 00000000/00400000 into device 0000:0c:00.0
pcieport 0000:0c:00.0: AER: Uncorrectable (Fatal) error message received from 0000:0c:00.0
pcieport 0000:0c:00.0: CXL Bus Error: severity=Uncorrectable (Fatal), type=Transaction Layer, (Receiver ID)
pcieport 0000:0c:00.0: device [8086:7075] error status/mask=00400000/02000000
pcieport 0000:0c:00.0: [22] UncorrIntErr
aer_event: 0000:0c:00.0 CXL Bus Error: severity=Fatal, Uncorrectable Internal Error, TLP Header=Not available
cxl_port_aer_uncorrectable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable '
cxl_detach_ep: cxl_mem mem3: disconnect mem3 from port2
cxl_detach_ep: cxl_mem mem3: disconnect mem3 from port1
cxl_detach_ep: cxl_mem mem0: disconnect mem0 from port2
cxl_detach_ep: cxl_mem mem0: disconnect mem0 from port1
cxl_detach_ep: cxl_mem mem2: disconnect mem2 from port2
cxl_detach_ep: cxl_mem mem2: disconnect mem2 from port1
cxl_detach_ep: cxl_mem mem1: disconnect mem1 from port2
cxl_detach_ep: cxl_mem mem1: delete port2
cxl_detach_ep: cxl_mem mem1: disconnect mem1 from port1
Kernel panic - not syncing: CXL cachemem error.
CPU: 10 UID: 0 PID: 146 Comm: irq/24-aerdrv Tainted: G E 6.13.0-rc5-amdsos-cxldbg-gc0a8083c0d66-dirty #5207
Tainted: [E]=UNSIGNED_MODULE
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0x27/0x90
dump_stack+0x10/0x20
panic+0x33e/0x380
? preempt_count_add+0x4b/0xc0
cxl_do_recovery+0xcb/0xd0
aer_isr+0x64f/0x700
? free_cpumask_var+0x9/0x10
? kfree+0x259/0x2e0
irq_thread_fn+0x28/0x70
irq_thread+0x179/0x240
? srso_return_thunk+0x5/0x5f
? __pfx_irq_thread_fn+0x10/0x10
? __pfx_irq_thread_dtor+0x10/0x10
? __pfx_irq_thread+0x10/0x10
kthread+0xf5/0x130
? __pfx_kthread+0x10/0x10
ret_from_fork+0x3c/0x60
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1a/0x30
</TASK>
Kernel Offset: 0x5800000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
---[ end Kernel panic - not syncing: CXL cachemem error. ]---
== Upstream Port Correctable Error ==
root@tbowman-cxl:~/aer-inject# ./us-ce-inject.sh
pcieport 0000:0c:00.0: aer_inject: Injecting errors 00004000/00000000 into device 0000:0d:00.0
pcieport 0000:0c:00.0: AER: Correctable error message received from 0000:0d:00.0
pcieport 0000:0d:00.0: CXL Bus Error: severity=Correctable, type=Transaction Layer, (Receiver ID)
pcieport 0000:0d:00.0: device [19e5:a128] error status/mask=00004000/0000a000
pcieport 0000:0d:00.0: [14] CorrIntErr
aer_event: 0000:0d:00.0 CXL Bus Error: severity=Corrected, Corrected Internal Error, TLP Header=Not available
cxl_port_aer_correctable_error: device=port2 (0000:0d:00.0) parent=port1 (0000:0c:00.0) status='Received Error From Physical Layer'
== Upstream Port UnCorrectable Error ==
root@tbowman-cxl:~/aer-inject# ./us-uce-inject.sh
pcieport 0000:0c:00.0: aer_inject: Injecting errors 00000000/00400000 into device 0000:0d:00.0
pcieport 0000:0c:00.0: AER: Uncorrectable (Fatal) error message received from 0000:0d:00.0
pcieport 0000:0d:00.0: AER: CXL Bus Error: severity=Uncorrectable (Fatal), type=Inaccessible, (Unregistered Agent ID)
aer_event: 0000:0d:00.0 CXL Bus Error: severity=Fatal, , TLP Header=Not available
cxl_port_aer_uncorrectable_error: device=port2 (0000:0d:00.0) parent=port1 (0000:0c:00.0) status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte $
cxl_detach_ep: cxl_mem mem2: disconnect mem2 from port2
cxl_detach_ep: cxl_mem mem2: disconnect mem2 from port1
cxl_detach_ep: cxl_mem mem3: disconnect mem3 from port2
cxl_detach_ep: cxl_mem mem3: disconnect mem3 from port1
cxl_detach_ep: cxl_mem mem0: disconnect mem0 from port2
cxl_detach_ep: cxl_mem mem0: disconnect mem0 from port1
cxl_detach_ep: cxl_mem mem1: disconnect mem1 from port2
cxl_detach_ep: cxl_mem mem1: delete port2
cxl_detach_ep: cxl_mem mem1: disconnect mem1 from port1
Kernel panic - not syncing: CXL cachemem error.
CPU: 10 UID: 0 PID: 147 Comm: irq/24-aerdrv Tainted: G E 6.13.0-rc5-amdsos-cxldbg-ge0fa85845e09-dirty #5226
Tainted: [E]=UNSIGNED_MODULE
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0x27/0x90
dump_stack+0x10/0x20
panic+0x33e/0x380
? preempt_count_add+0x4b/0xc0
cxl_do_recovery+0xd2/0xe0
aer_isr+0x355/0x6a0
? free_cpumask_var+0x9/0x10
? kfree+0x259/0x2e0
irq_thread_fn+0x28/0x70
irq_thread+0x179/0x240
? srso_return_thunk+0x5/0x5f
? __pfx_irq_thread_fn+0x10/0x10
? __pfx_irq_thread_dtor+0x10/0x10
? __pfx_irq_thread+0x10/0x10
kthread+0xf5/0x130
? __pfx_kthread+0x10/0x10
ret_from_fork+0x3c/0x60
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1a/0x30
</TASK>
Kernel Offset: 0x10c00000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
---[ end Kernel panic - not syncing: CXL cachemem error. ]---
== Downstream Port Correctable Error ==
root@tbowman-cxl:~/aer-inject# ./ds-ce-inject.sh
pcieport 0000:0c:00.0: aer_inject: Injecting errors 00004000/00000000 into device 0000:0e:00.0
pcieport 0000:0c:00.0: AER: Correctable error message received from 0000:0e:00.0
pcieport 0000:0e:00.0: CXL Bus Error: severity=Correctable, type=Transaction Layer, (Receiver ID)
pcieport 0000:0e:00.0: device [19e5:a129] error status/mask=00004000/0000a000
pcieport 0000:0e:00.0: [14] CorrIntErr
aer_event: 0000:0e:00.0 CXL Bus Error: severity=Corrected, Corrected Internal Error, TLP Header=Not available
cxl_port_aer_correctable_error: device=port2 (0000:0e:00.0) parent=port1 (0000:0d:00.0) status='Received Error From Physical Layer'
== Downstream Port UnCorrectable Error ==
root@tbowman-cxl:~/aer-inject# ./ds-uce-inject.sh
pcieport 0000:0c:00.0: aer_inject: Injecting errors 00000000/00400000 into device 0000:0e:00.0
pcieport 0000:0c:00.0: AER: Uncorrectable (Fatal) error message received from 0000:0e:00.0
pcieport 0000:0e:00.0: CXL Bus Error: severity=Uncorrectable (Fatal), type=Transaction Layer, (Receiver ID)
pcieport 0000:0e:00.0: device [19e5:a129] error status/mask=00400000/02000000
pcieport 0000:0e:00.0: [22] UncorrIntErr
aer_event: 0000:0e:00.0 CXL Bus Error: severity=Fatal, Uncorrectable Internal Error, TLP Header=Not available
cxl_detach_ep: cxl_mem mem3: disconnect mem3 from port2
cxl_detach_ep: cxl_mem mem3: disconnect mem3 from port1
Kernel panic - not syncing: CXL cachemem error.
CPU: 10 UID: 0 PID: 147 Comm: irq/24-aerdrv Tainted: G E 6.13.0-rc5-amdsos-cxldbg-gc0a8083c0d66-dirty #5207
Tainted: [E]=UNSIGNED_MODULE
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0x27/0x90
dump_stack+0x10/0x20
panic+0x33e/0x380
? preempt_count_add+0x4b/0xc0
cxl_do_recovery+0xcb/0xd0
aer_isr+0x64f/0x700
? free_cpumask_var+0x9/0x10
? kfree+0x259/0x2e0
irq_thread_fn+0x28/0x70
irq_thread+0x179/0x240
? srso_return_thunk+0x5/0x5f
? __pfx_irq_thread_fn+0x10/0x10
? __pfx_irq_thread_dtor+0x10/0x10
? __pfx_irq_thread+0x10/0x10
kthread+0xf5/0x130
? __pfx_kthread+0x10/0x10
ret_from_fork+0x3c/0x60
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1a/0x30
</TASK>
Kernel Offset: 0xe400000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
---[ end Kernel panic - not syncing: CXL cachemem error. ]---
== Endpoint Correctable Error ==
root@tbowman-cxl:~/aer-inject# ./ep-ce-inject.sh
pcieport 0000:0c:00.0: aer_inject: Injecting errors 00004000/00000000 into device 0000:0f:00.0
pcieport 0000:0c:00.0: AER: Correctable error message received from 0000:0f:00.0
cxl_pci 0000:0f:00.0: CXL Bus Error: severity=Correctable, type=Transaction Layer, (Receiver ID)
cxl_pci 0000:0f:00.0: device [8086:0d93] error status/mask=00004000/00000000
cxl_pci 0000:0f:00.0: [14] CorrIntErr
aer_event: 0000:0f:00.0 CXL Bus Error: severity=Corrected, Corrected Internal Error, TLP Header=Not available
cxl_aer_correctable_error: memdev=mem0 host=0000:0f:00.0 serial=0: status: 'Received Error From Physical Layer'
== Endpoint UnCorrectable Error ==
root@tbowman-cxl:~/aer-inject# ./ep-uce-inject.sh
pcieport 0000:0c:00.0: aer_inject: Injecting errors 00000000/00400000 into device 0000:0f:00.0
pcieport 0000:0c:00.0: AER: Uncorrectable (Fatal) error message received from 0000:0f:00.0
cxl_pci 0000:0f:00.0: AER: CXL Bus Error: severity=Uncorrectable (Fatal), type=Inaccessible, (Unregistered Agent ID)
aer_event: 0000:0f:00.0 CXL Bus Error: severity=Fatal, , TLP Header=Not available
cxl_aer_uncorrectable_error: memdev=mem0 host=0000:0f:00.0 serial=0: status: 'Memory Byte Enable Parity Error' first_error: 'Memory '
cxl_detach_ep: cxl_mem mem0: disconnect mem0 from port2
cxl_detach_ep: cxl_mem mem0: disconnect mem0 from port1
Kernel panic - not syncing: CXL cachemem error.
CPU: 10 UID: 0 PID: 147 Comm: irq/24-aerdrv Tainted: G E 6.13.0-rc5-amdsos-cxldbg-ge0fa85845e09-dirty #5225
Tainted: [E]=UNSIGNED_MODULE
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0x27/0x90
dump_stack+0x10/0x20
panic+0x33e/0x380
cxl_do_recovery+0xd2/0xe0
aer_isr+0x355/0x6a0
? free_cpumask_var+0x9/0x10
? kfree+0x259/0x2e0
irq_thread_fn+0x28/0x70
irq_thread+0x179/0x240
? srso_return_thunk+0x5/0x5f
? __pfx_irq_thread_fn+0x10/0x10
? __pfx_irq_thread_dtor+0x10/0x10
? __pfx_irq_thread+0x10/0x10
kthread+0xf5/0x130
? __pfx_kthread+0x10/0x10
ret_from_fork+0x3c/0x60
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1a/0x30
</TASK>
Kernel Offset: 0x5c00000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
---[ end Kernel panic - not syncing: CXL cachemem error. ]---
Changes
=======
Changes in v6 -> v7:
[Terry] Move updated trace routine call to later patch. Was causing build
error.
Changes in v5 -> v6:
[Ira] Move pcie_is_cxl(dev) define to a inline function
[Ira] Update returning value from pcie_is_cxl_port() to bool w/o cast
[Ira] Change cxl_report_error_detected() cleanup to return correct bool
[Ira] Introduce and use PCI_ERS_RESULT_PANIC
[Ira] Reuse comment for PCIe and CXL recovery paths
[Jonathan] Add type check in for cxl_handle_cor_ras() and cxl_handle_ras()
[Jonathan] cxl_uport/dport_init_ras_reporting(), added a mutex.
[Jonathan] Add logging example to patches updating trace output
[Jonathan] Make parameter 'const' to eliminate for cast in match_uport()
[Jonathan] Use __free() in cxl_pci_port_ras()
[Terry] Add patch to log the PCIe SBDF along with CXL device name
[Terry] Add patch to handle CXL endpoint and RCH DP errors as CXL errors
[Terry] Remove patch w USP UCE fatal support @ aer_get_device_error_info()
[Terry] Rebase to 5585e342e8d3 (cxl/next)
[Gregory] Pre-initialize pointer to NULL in cxl_pci_port_ras()
[Gregory] Move AER driver bus name detection to a static function
Changes in v4 -> v5:
[Alejandro] Refactor cxl_walk_bridge to simplify 'status' variable usage
[Alejandro] Add WARN_ONCE() in __cxl_handle_ras() and cxl_handle_cor_ras()
[Ming] Remove unnecessary NULL check in cxl_pci_port_ras()
[Terry] Add failure check for call to to_cxl_port() in cxl_pci_port_ras()
[Ming] Use port->dev for call to devm_add_action_or_reset() in
cxl_dport_init_ras_reporting() and cxl_uport_init_ras_reporting()
[Jonathan] Use get_device()/put_device() to prevent race condition in
cxl_clear_port_error_handlers() and cxl_clear_port_error_handlers()
[Terry] Commit message cleanup. Capitalize keywords from CXL and PCI
specifications
Changes in v3 -> v4:
[Lukas] Capitalize PCIe and CXL device names as in specifications
[Lukas] Move call to pcie_is_cxl() into cxl_port_devsec()
[Lukas] Correct namespace spelling
[Lukas] Removed export from pcie_is_cxl_port()
[Lukas] Simplify 'if' blocks in cxl_handle_error()
[Lukas] Change panic message to remove redundant 'panic' text
[Ming] Update to call cxl_dport_init_ras_reporting() in RCH case
[lkp@intel] 'host' parameter is already removed. Remove parameter description too.
[Terry] Added field description for cxl_err_handlers in pci.h comment block
Changes in v1 -> v2:
[Jonathan] Remove extra NULL check and cleanup in cxl_pci_port_ras()
[Jonathan] Update description to DSP map patch description
[Jonathan] Update cxl_pci_port_ras() to check for NULL port
[Jonathan] Dont call handler before handler port changes are present (patch order)
[Bjorn] Fix linebreak in cover sheet URL
[Bjorn] Remove timestamps from test logs in cover sheet
[Bjorn] Retitle AER commits to use "PCI/AER:"
[Bjorn] Retitle patch#3 to use renaming instead of refactoring
[Bjorn] Fix base commit-id on cover sheet
[Bjorn] Add VH spec reference/citation
[Terry] Removed last 2 patches to enable internal errors. Is not needed
because internal errors are enabled in AER driver.
[Dan] Create cxl_do_recovery() and pci_driver::cxl_err_handlers.
[Dan] Use kernel panic in CXL recovery
[Dan] cxl_port_hndlrs -> cxl_port_error_handlers
Terry Bowman (17):
PCI/AER: Introduce 'struct cxl_err_handlers' and add to 'struct
pci_driver'
PCI/AER: Rename AER driver's interfaces to also indicate CXL PCIe Port
support
CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and
pcie_is_cxl_port()
PCI/AER: Modify AER driver logging to report CXL or PCIe bus error
type
PCI/AER: Add CXL PCIe Port correctable error support in AER service
driver
PCI/AER: Add CXL PCIe Port uncorrectable error recovery in AER service
driver
cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS
registers
cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
cxl/pci: Update RAS handler interfaces to also support CXL PCIe Ports
cxl/pci: Add log message and add type check in existing RAS handlers
cxl/pci: Change find_cxl_port() to non-static
cxl/pci: Add error handler for CXL PCIe Port RAS errors
cxl/pci: Add trace logging for CXL PCIe Port RAS errors
cxl/pci: Update CXL Port RAS logging to also display PCIe SBDF
cxl/pci: Add support to assign and clear pci_driver::cxl_err_handlers
PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch
Ports
cxl/pci: Handle CXL Endpoint and RCH Protocol Errors separately from
PCIe errors
drivers/cxl/core/core.h | 2 +
drivers/cxl/core/pci.c | 261 ++++++++++++++++++++++++++--------
drivers/cxl/core/port.c | 4 +-
drivers/cxl/core/trace.h | 57 ++++++++
drivers/cxl/cxl.h | 10 +-
drivers/cxl/cxlpci.h | 3 +-
drivers/cxl/mem.c | 39 ++++-
drivers/cxl/pci.c | 10 +-
drivers/pci/pci.c | 13 ++
drivers/pci/pci.h | 3 +
drivers/pci/pcie/aer.c | 99 ++++++++-----
drivers/pci/pcie/err.c | 58 ++++++++
drivers/pci/probe.c | 10 ++
include/linux/aer.h | 1 +
include/linux/pci.h | 18 +++
include/ras/ras_event.h | 9 +-
include/uapi/linux/pci_regs.h | 3 +-
17 files changed, 486 insertions(+), 114 deletions(-)
base-commit: 5585e342e8d38cc598279bdb87f235f8b954dd5a
--
2.34.1
^ permalink raw reply [flat|nested] 94+ messages in thread
* [PATCH v7 01/17] PCI/AER: Introduce 'struct cxl_err_handlers' and add to 'struct pci_driver'
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 20:25 ` Bjorn Helgaas
2025-02-11 20:42 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 02/17] PCI/AER: Rename AER driver's interfaces to also indicate CXL PCIe Port support Terry Bowman
` (15 subsequent siblings)
16 siblings, 2 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
CXL.io is implemented on top of PCIe Protocol Errors. But, CXL.io and PCIe
have different handling requirements for uncorrectable errors (UCE).
The PCIe AER service driver may attempt recovering PCIe devices with
UCE while recovery is not used for CXL.io. Recovery is not used in the
CXL.io case because of potential corruption on what can be system memory.
Create pci_driver::cxl_err_handlers structure similar to
pci_driver::error_handler. Create handlers for correctable and
uncorrectable CXL.io error handling.
The CXL error handlers will be used in future patches adding CXL PCIe
Port Protocol Error handling.
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Fan Ni <fan.ni@samsung.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
---
include/linux/pci.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 47b31ad724fa..1d62e785ae1f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -884,6 +884,14 @@ struct pci_error_handlers {
void (*cor_error_detected)(struct pci_dev *dev);
};
+/* Compute Express Link (CXL) bus error event callbacks */
+struct cxl_error_handlers {
+ /* CXL bus error detected on this device */
+ pci_ers_result_t (*error_detected)(struct pci_dev *dev);
+
+ /* Allow device driver to record more details of a correctable error */
+ void (*cor_error_detected)(struct pci_dev *dev);
+};
struct module;
@@ -929,6 +937,7 @@ struct module;
* @sriov_get_vf_total_msix: PF driver callback to get the total number of
* MSI-X vectors available for distribution to the VFs.
* @err_handler: See Documentation/PCI/pci-error-recovery.rst
+ * @cxl_err_handler: Compute Express Link specific error handlers.
* @groups: Sysfs attribute groups.
* @dev_groups: Attributes attached to the device that will be
* created once it is bound to the driver.
@@ -954,6 +963,7 @@ struct pci_driver {
int (*sriov_set_msix_vec_count)(struct pci_dev *vf, int msix_vec_count); /* On PF */
u32 (*sriov_get_vf_total_msix)(struct pci_dev *pf);
const struct pci_error_handlers *err_handler;
+ const struct cxl_error_handlers *cxl_err_handler;
const struct attribute_group **groups;
const struct attribute_group **dev_groups;
struct device_driver driver;
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 02/17] PCI/AER: Rename AER driver's interfaces to also indicate CXL PCIe Port support
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
2025-02-11 19:24 ` [PATCH v7 01/17] PCI/AER: Introduce 'struct cxl_err_handlers' and add to 'struct pci_driver' Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 20:26 ` Bjorn Helgaas
2025-02-11 20:44 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port() Terry Bowman
` (14 subsequent siblings)
16 siblings, 2 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
The AER service driver already includes support for Restricted CXL host
(RCH) Downstream Port Protocol Error handling. The current implementation
is based on CXL1.1 using a Root Complex Event Collector.
Rename function interfaces and parameters where necessary to include
virtual hierarchy (VH) mode CXL PCIe Port error handling alongside the RCH
handling.[1] The CXL PCIe Port Protocol Error handling support will be
added in a future patch.
Limit changes to renaming variable and function names. No functional
changes are added.
[1] CXL 3.1 Spec, 9.12.2 CXL Virtual Hierarchy
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Fan Ni <fan.ni@samsung.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
---
drivers/pci/pcie/aer.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index 508474e17183..6e8de77d0fc4 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -1024,7 +1024,7 @@ static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
return 0;
}
-static void cxl_rch_handle_error(struct pci_dev *dev, struct aer_err_info *info)
+static void cxl_handle_error(struct pci_dev *dev, struct aer_err_info *info)
{
/*
* Internal errors of an RCEC indicate an AER error in an
@@ -1047,30 +1047,30 @@ static int handles_cxl_error_iter(struct pci_dev *dev, void *data)
return *handles_cxl;
}
-static bool handles_cxl_errors(struct pci_dev *rcec)
+static bool handles_cxl_errors(struct pci_dev *dev)
{
bool handles_cxl = false;
- if (pci_pcie_type(rcec) == PCI_EXP_TYPE_RC_EC &&
- pcie_aer_is_native(rcec))
- pcie_walk_rcec(rcec, handles_cxl_error_iter, &handles_cxl);
+ if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC &&
+ pcie_aer_is_native(dev))
+ pcie_walk_rcec(dev, handles_cxl_error_iter, &handles_cxl);
return handles_cxl;
}
-static void cxl_rch_enable_rcec(struct pci_dev *rcec)
+static void cxl_enable_internal_errors(struct pci_dev *dev)
{
- if (!handles_cxl_errors(rcec))
+ if (!handles_cxl_errors(dev))
return;
- pci_aer_unmask_internal_errors(rcec);
- pci_info(rcec, "CXL: Internal errors unmasked");
+ pci_aer_unmask_internal_errors(dev);
+ pci_info(dev, "CXL: Internal errors unmasked");
}
#else
-static inline void cxl_rch_enable_rcec(struct pci_dev *dev) { }
-static inline void cxl_rch_handle_error(struct pci_dev *dev,
- struct aer_err_info *info) { }
+static inline void cxl_enable_internal_errors(struct pci_dev *dev) { }
+static inline void cxl_handle_error(struct pci_dev *dev,
+ struct aer_err_info *info) { }
#endif
/**
@@ -1108,7 +1108,7 @@ static void pci_aer_handle_error(struct pci_dev *dev, struct aer_err_info *info)
static void handle_error_source(struct pci_dev *dev, struct aer_err_info *info)
{
- cxl_rch_handle_error(dev, info);
+ cxl_handle_error(dev, info);
pci_aer_handle_error(dev, info);
pci_dev_put(dev);
}
@@ -1491,7 +1491,7 @@ static int aer_probe(struct pcie_device *dev)
return status;
}
- cxl_rch_enable_rcec(port);
+ cxl_enable_internal_errors(port);
aer_enable_rootport(rpc);
pci_info(port, "enabled with IRQ %d\n", dev->irq);
return 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port()
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
2025-02-11 19:24 ` [PATCH v7 01/17] PCI/AER: Introduce 'struct cxl_err_handlers' and add to 'struct pci_driver' Terry Bowman
2025-02-11 19:24 ` [PATCH v7 02/17] PCI/AER: Rename AER driver's interfaces to also indicate CXL PCIe Port support Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 20:28 ` Bjorn Helgaas
` (2 more replies)
2025-02-11 19:24 ` [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type Terry Bowman
` (13 subsequent siblings)
16 siblings, 3 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
CXL and AER drivers need the ability to identify CXL devices and CXL port
devices.
First, add set_pcie_cxl() with logic checking for CXL Flexbus DVSEC
presence. The CXL Flexbus DVSEC presence is used because it is required
for all the CXL PCIe devices.[1]
Add boolean 'struct pci_dev::is_cxl' with the purpose to cache the CXL
Flexbus presence.
Add pcie_is_cxl() as a macro to return 'struct pci_dev::is_cxl'.
Add pcie_is_cxl_port() to check if a device is a CXL Root Port, CXL
Upstream Switch Port, or CXL Downstream Switch Port. Also, verify the
CXL Extensions DVSEC for Ports is present.[1]
[1] CXL 3.1 Spec, 8.1.1 PCIe Designated Vendor-Specific Extended
Capability (DVSEC) ID Assignment, Table 8-2
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Fan Ni <fan.ni@samsung.com>
---
drivers/pci/pci.c | 13 +++++++++++++
drivers/pci/probe.c | 10 ++++++++++
include/linux/pci.h | 5 +++++
include/uapi/linux/pci_regs.h | 3 ++-
4 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 869d204a70a3..a2d8b41dd043 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -5032,6 +5032,19 @@ static u16 cxl_port_dvsec(struct pci_dev *dev)
PCI_DVSEC_CXL_PORT);
}
+inline bool pcie_is_cxl(struct pci_dev *pci_dev)
+{
+ return pci_dev->is_cxl;
+}
+
+bool pcie_is_cxl_port(struct pci_dev *dev)
+{
+ if (!pcie_is_cxl(dev))
+ return false;
+
+ return (cxl_port_dvsec(dev) > 0);
+}
+
static bool cxl_sbr_masked(struct pci_dev *dev)
{
u16 dvsec, reg;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index b6536ed599c3..7737b9ce7a83 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1676,6 +1676,14 @@ static void set_pcie_thunderbolt(struct pci_dev *dev)
dev->is_thunderbolt = 1;
}
+static void set_pcie_cxl(struct pci_dev *dev)
+{
+ u16 dvsec = pci_find_dvsec_capability(dev, PCI_VENDOR_ID_CXL,
+ PCI_DVSEC_CXL_FLEXBUS);
+ if (dvsec)
+ dev->is_cxl = 1;
+}
+
static void set_pcie_untrusted(struct pci_dev *dev)
{
struct pci_dev *parent = pci_upstream_bridge(dev);
@@ -2006,6 +2014,8 @@ int pci_setup_device(struct pci_dev *dev)
/* Need to have dev->cfg_size ready */
set_pcie_thunderbolt(dev);
+ set_pcie_cxl(dev);
+
set_pcie_untrusted(dev);
if (pci_is_pcie(dev))
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 1d62e785ae1f..82a0401c58d3 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -452,6 +452,7 @@ struct pci_dev {
unsigned int is_hotplug_bridge:1;
unsigned int shpc_managed:1; /* SHPC owned by shpchp */
unsigned int is_thunderbolt:1; /* Thunderbolt controller */
+ unsigned int is_cxl:1; /* Compute Express Link (CXL) */
/*
* Devices marked being untrusted are the ones that can potentially
* execute DMA attacks and similar. They are typically connected
@@ -741,6 +742,10 @@ static inline bool pci_is_vga(struct pci_dev *pdev)
return false;
}
+bool pcie_is_cxl(struct pci_dev *pci_dev);
+
+bool pcie_is_cxl_port(struct pci_dev *dev);
+
#define for_each_pci_bridge(dev, bus) \
list_for_each_entry(dev, &bus->devices, bus_list) \
if (!pci_is_bridge(dev)) {} else
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 3445c4970e4d..dbc0f23d8c82 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -1208,9 +1208,10 @@
#define PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL 0x00ff0000
#define PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX 0xff000000
-/* Compute Express Link (CXL r3.1, sec 8.1.5) */
+/* Compute Express Link (CXL r3.1, sec 8.1) */
#define PCI_DVSEC_CXL_PORT 3
#define PCI_DVSEC_CXL_PORT_CTL 0x0c
#define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR 0x00000001
+#define PCI_DVSEC_CXL_FLEXBUS 7
#endif /* LINUX_PCI_REGS_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (2 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port() Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 20:28 ` Bjorn Helgaas
2025-02-11 23:47 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 05/17] PCI/AER: Add CXL PCIe Port correctable error support in AER service driver Terry Bowman
` (12 subsequent siblings)
16 siblings, 2 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
The AER driver and aer_event tracing currently log 'PCIe Bus Type'
for all errors.
Update the driver and aer_event tracing to log 'CXL Bus Type' for CXL
device errors.
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Fan Ni <fan.ni@samsung.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
---
drivers/pci/pcie/aer.c | 14 ++++++++------
include/ras/ras_event.h | 9 ++++++---
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index 6e8de77d0fc4..f99a1c6fb274 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -694,13 +694,14 @@ static void __aer_print_error(struct pci_dev *dev,
void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
{
+ const char *bus_type = pcie_is_cxl(dev) ? "CXL" : "PCIe";
int layer, agent;
int id = pci_dev_id(dev);
const char *level;
if (!info->status) {
- pci_err(dev, "PCIe Bus Error: severity=%s, type=Inaccessible, (Unregistered Agent ID)\n",
- aer_error_severity_string[info->severity]);
+ pci_err(dev, "%s Bus Error: severity=%s, type=Inaccessible, (Unregistered Agent ID)\n",
+ bus_type, aer_error_severity_string[info->severity]);
goto out;
}
@@ -709,8 +710,8 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
level = (info->severity == AER_CORRECTABLE) ? KERN_WARNING : KERN_ERR;
- pci_printk(level, dev, "PCIe Bus Error: severity=%s, type=%s, (%s)\n",
- aer_error_severity_string[info->severity],
+ pci_printk(level, dev, "%s Bus Error: severity=%s, type=%s, (%s)\n",
+ bus_type, aer_error_severity_string[info->severity],
aer_error_layer[layer], aer_agent_string[agent]);
pci_printk(level, dev, " device [%04x:%04x] error status/mask=%08x/%08x\n",
@@ -725,7 +726,7 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
if (info->id && info->error_dev_num > 1 && info->id == id)
pci_err(dev, " Error of this Agent is reported first\n");
- trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
+ trace_aer_event(dev_name(&dev->dev), bus_type, (info->status & ~info->mask),
info->severity, info->tlp_header_valid, &info->tlp);
}
@@ -759,6 +760,7 @@ EXPORT_SYMBOL_GPL(cper_severity_to_aer);
void pci_print_aer(struct pci_dev *dev, int aer_severity,
struct aer_capability_regs *aer)
{
+ const char *bus_type = pcie_is_cxl(dev) ? "CXL" : "PCIe";
int layer, agent, tlp_header_valid = 0;
u32 status, mask;
struct aer_err_info info;
@@ -793,7 +795,7 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
if (tlp_header_valid)
pcie_print_tlp_log(dev, &aer->header_log, dev_fmt(" "));
- trace_aer_event(dev_name(&dev->dev), (status & ~mask),
+ trace_aer_event(dev_name(&dev->dev), bus_type, (status & ~mask),
aer_severity, tlp_header_valid, &aer->header_log);
}
EXPORT_SYMBOL_NS_GPL(pci_print_aer, "CXL");
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index e5f7ee0864e7..1bf8e7050ba8 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -297,15 +297,17 @@ TRACE_EVENT(non_standard_event,
TRACE_EVENT(aer_event,
TP_PROTO(const char *dev_name,
+ const char *bus_type,
const u32 status,
const u8 severity,
const u8 tlp_header_valid,
struct pcie_tlp_log *tlp),
- TP_ARGS(dev_name, status, severity, tlp_header_valid, tlp),
+ TP_ARGS(dev_name, bus_type, status, severity, tlp_header_valid, tlp),
TP_STRUCT__entry(
__string( dev_name, dev_name )
+ __string( bus_type, bus_type )
__field( u32, status )
__field( u8, severity )
__field( u8, tlp_header_valid)
@@ -314,6 +316,7 @@ TRACE_EVENT(aer_event,
TP_fast_assign(
__assign_str(dev_name);
+ __assign_str(bus_type);
__entry->status = status;
__entry->severity = severity;
__entry->tlp_header_valid = tlp_header_valid;
@@ -325,8 +328,8 @@ TRACE_EVENT(aer_event,
}
),
- TP_printk("%s PCIe Bus Error: severity=%s, %s, TLP Header=%s\n",
- __get_str(dev_name),
+ TP_printk("%s %s Bus Error: severity=%s, %s, TLP Header=%s\n",
+ __get_str(dev_name), __get_str(bus_type),
__entry->severity == AER_CORRECTABLE ? "Corrected" :
__entry->severity == AER_FATAL ?
"Fatal" : "Uncorrected, non-fatal",
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 05/17] PCI/AER: Add CXL PCIe Port correctable error support in AER service driver
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (3 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 20:28 ` Bjorn Helgaas
2025-02-11 23:58 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery " Terry Bowman
` (11 subsequent siblings)
16 siblings, 2 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
The AER service driver supports handling Downstream Port Protocol Errors in
Restricted CXL host (RCH) mode also known as CXL1.1. It needs the same
functionality for CXL PCIe Ports operating in Virtual Hierarchy (VH)
mode.[1]
CXL and PCIe Protocol Error handling have different requirements that
necessitate a separate handling path. The AER service driver may try to
recover PCIe uncorrectable non-fatal errors (UCE). The same recovery is not
suitable for CXL PCIe Port devices because of potential for system memory
corruption. Instead, CXL Protocol Error handling must use a kernel panic
in the case of a fatal or non-fatal UCE. The AER driver's PCIe Protocol
Error handling does not panic the kernel in response to a UCE.
Introduce a separate path for CXL Protocol Error handling in the AER
service driver. This will allow CXL Protocol Errors to use CXL specific
handling instead of PCIe handling. Add the CXL specific changes without
affecting or adding functionality in the PCIe handling.
Make this update alongside the existing Downstream Port RCH error handling
logic, extending support to CXL PCIe Ports in VH mode.
Remove is_internal_error(). is_internal_error() was used to determine if
an AER error was a CXL error. Instead, now rely on pcie_is_cxl_port() to
indicate the error is a CXL error.
The uncorrectable error (UCE) handling will be added in a future patch.
[1] CXL 3.1 Spec, 12.2.2 CXL Root Ports, Downstream Switch Ports, and
Upstream Switch Ports
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
---
drivers/pci/pcie/aer.c | 47 ++++++++++++++++++++++++++++--------------
1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index f99a1c6fb274..34ec0958afff 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -989,14 +989,6 @@ static bool cxl_error_is_native(struct pci_dev *dev)
return (pcie_ports_native || host->native_aer);
}
-static bool is_internal_error(struct aer_err_info *info)
-{
- if (info->severity == AER_CORRECTABLE)
- return info->status & PCI_ERR_COR_INTERNAL;
-
- return info->status & PCI_ERR_UNC_INTN;
-}
-
static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
{
struct aer_err_info *info = (struct aer_err_info *)data;
@@ -1033,9 +1025,23 @@ static void cxl_handle_error(struct pci_dev *dev, struct aer_err_info *info)
* RCH's downstream port. Check and handle them in the CXL.mem
* device driver.
*/
- if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC &&
- is_internal_error(info))
- pcie_walk_rcec(dev, cxl_rch_handle_error_iter, info);
+ if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC)
+ return pcie_walk_rcec(dev, cxl_rch_handle_error_iter, info);
+
+ if (info->severity == AER_CORRECTABLE) {
+ struct pci_driver *pdrv = dev->driver;
+ int aer = dev->aer_cap;
+
+ if (aer)
+ pci_write_config_dword(dev, aer + PCI_ERR_COR_STATUS,
+ info->status);
+
+ if (pdrv && pdrv->cxl_err_handler &&
+ pdrv->cxl_err_handler->cor_error_detected)
+ pdrv->cxl_err_handler->cor_error_detected(dev);
+
+ pcie_clear_device_status(dev);
+ }
}
static int handles_cxl_error_iter(struct pci_dev *dev, void *data)
@@ -1053,9 +1059,13 @@ static bool handles_cxl_errors(struct pci_dev *dev)
{
bool handles_cxl = false;
- if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC &&
- pcie_aer_is_native(dev))
+ if (!pcie_aer_is_native(dev))
+ return false;
+
+ if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC)
pcie_walk_rcec(dev, handles_cxl_error_iter, &handles_cxl);
+ else
+ handles_cxl = pcie_is_cxl_port(dev);
return handles_cxl;
}
@@ -1073,6 +1083,10 @@ static void cxl_enable_internal_errors(struct pci_dev *dev)
static inline void cxl_enable_internal_errors(struct pci_dev *dev) { }
static inline void cxl_handle_error(struct pci_dev *dev,
struct aer_err_info *info) { }
+static bool handles_cxl_errors(struct pci_dev *dev)
+{
+ return false;
+}
#endif
/**
@@ -1110,8 +1124,11 @@ static void pci_aer_handle_error(struct pci_dev *dev, struct aer_err_info *info)
static void handle_error_source(struct pci_dev *dev, struct aer_err_info *info)
{
- cxl_handle_error(dev, info);
- pci_aer_handle_error(dev, info);
+ if (handles_cxl_errors(dev))
+ cxl_handle_error(dev, info);
+ else
+ pci_aer_handle_error(dev, info);
+
pci_dev_put(dev);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery in AER service driver
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (4 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 05/17] PCI/AER: Add CXL PCIe Port correctable error support in AER service driver Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 20:29 ` Bjorn Helgaas
` (5 more replies)
2025-02-11 19:24 ` [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers Terry Bowman
` (10 subsequent siblings)
16 siblings, 6 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Existing recovery procedure for PCIe uncorrectable errors (UCE) does not
apply to CXL devices. Recovery can not be used for CXL devices because of
potential corruption on what can be system memory. Also, current PCIe UCE
recovery, in the case of a Root Port (RP) or Downstream Switch Port (DSP),
does not begin at the RP/DSP but begins at the first downstream device.
This will miss handling CXL Protocol Errors in a CXL RP or DSP. A separate
CXL recovery is needed because of the different handling requirements
Add a new function, cxl_do_recovery() using the following.
Add cxl_walk_bridge() to iterate the detected error's sub-topology.
cxl_walk_bridge() is similar to pci_walk_bridge() but the CXL flavor
will begin iteration at the RP or DSP rather than beginning at the
first downstream device.
pci_walk_bridge() is candidate to possibly reuse cxl_walk_bridge() but
needs further investigation. This will be left for future improvement
to make the CXL and PCI handling paths more common.
Add cxl_report_error_detected() as an analog to report_error_detected().
It will call pci_driver::cxl_err_handlers for each iterated downstream
device. The pci_driver::cxl_err_handler's UCE handler returns a boolean
indicating if there was a UCE error detected during handling.
cxl_do_recovery() uses the status from cxl_report_error_detected() to
determine how to proceed. Non-fatal CXL UCE errors will be treated as
fatal. If a UCE was present during handling then cxl_do_recovery()
will kernel panic.
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
---
drivers/pci/pci.h | 3 +++
drivers/pci/pcie/aer.c | 4 +++
drivers/pci/pcie/err.c | 58 ++++++++++++++++++++++++++++++++++++++++++
include/linux/pci.h | 3 +++
4 files changed, 68 insertions(+)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 01e51db8d285..deb193b387af 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -722,6 +722,9 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
pci_channel_state_t state,
pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev));
+/* CXL error reporting and handling */
+void cxl_do_recovery(struct pci_dev *dev);
+
bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
int pcie_retrain_link(struct pci_dev *pdev, bool use_lt);
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index 34ec0958afff..ee38db08d005 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -1012,6 +1012,8 @@ static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
err_handler->error_detected(dev, pci_channel_io_normal);
else if (info->severity == AER_FATAL)
err_handler->error_detected(dev, pci_channel_io_frozen);
+
+ cxl_do_recovery(dev);
}
out:
device_unlock(&dev->dev);
@@ -1041,6 +1043,8 @@ static void cxl_handle_error(struct pci_dev *dev, struct aer_err_info *info)
pdrv->cxl_err_handler->cor_error_detected(dev);
pcie_clear_device_status(dev);
+ } else {
+ cxl_do_recovery(dev);
}
}
diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
index 31090770fffc..05f2d1ef4c36 100644
--- a/drivers/pci/pcie/err.c
+++ b/drivers/pci/pcie/err.c
@@ -24,6 +24,9 @@
static pci_ers_result_t merge_result(enum pci_ers_result orig,
enum pci_ers_result new)
{
+ if (new == PCI_ERS_RESULT_PANIC)
+ return PCI_ERS_RESULT_PANIC;
+
if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
return PCI_ERS_RESULT_NO_AER_DRIVER;
@@ -276,3 +279,58 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
return status;
}
+
+static void cxl_walk_bridge(struct pci_dev *bridge,
+ int (*cb)(struct pci_dev *, void *),
+ void *userdata)
+{
+ if (cb(bridge, userdata))
+ return;
+
+ if (bridge->subordinate)
+ pci_walk_bus(bridge->subordinate, cb, userdata);
+}
+
+static int cxl_report_error_detected(struct pci_dev *dev, void *data)
+{
+ const struct cxl_error_handlers *cxl_err_handler;
+ pci_ers_result_t vote, *result = data;
+ struct pci_driver *pdrv;
+
+ device_lock(&dev->dev);
+ pdrv = dev->driver;
+ if (!pdrv || !pdrv->cxl_err_handler ||
+ !pdrv->cxl_err_handler->error_detected)
+ goto out;
+
+ cxl_err_handler = pdrv->cxl_err_handler;
+ vote = cxl_err_handler->error_detected(dev);
+ *result = merge_result(*result, vote);
+out:
+ device_unlock(&dev->dev);
+ return 0;
+}
+
+void cxl_do_recovery(struct pci_dev *dev)
+{
+ struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
+ pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
+
+ cxl_walk_bridge(dev, cxl_report_error_detected, &status);
+ if (status == PCI_ERS_RESULT_PANIC)
+ panic("CXL cachemem error.");
+
+ /*
+ * If we have native control of AER, clear error status in the device
+ * that detected the error. If the platform retained control of AER,
+ * it is responsible for clearing this status. In that case, the
+ * signaling device may not even be visible to the OS.
+ */
+ if (host->native_aer || pcie_ports_native) {
+ pcie_clear_device_status(dev);
+ pci_aer_clear_nonfatal_status(dev);
+ pci_aer_clear_fatal_status(dev);
+ }
+
+ pci_info(dev, "CXL uncorrectable error.\n");
+}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 82a0401c58d3..5b539b5bf0d1 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -864,6 +864,9 @@ enum pci_ers_result {
/* No AER capabilities registered for the driver */
PCI_ERS_RESULT_NO_AER_DRIVER = (__force pci_ers_result_t) 6,
+
+ /* System is unstable, panic */
+ PCI_ERS_RESULT_PANIC = (__force pci_ers_result_t) 7,
};
/* PCI bus error event callbacks */
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (5 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery " Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 22:40 ` Dave Jiang
` (2 more replies)
2025-02-11 19:24 ` [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream " Terry Bowman
` (9 subsequent siblings)
16 siblings, 3 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
The CXL mem driver (cxl_mem) currently maps and caches a pointer to RAS
registers for the endpoint's Root Port. The same needs to be done for
each of the CXL Downstream Switch Ports and CXL Root Ports found between
the endpoint and CXL Host Bridge.
Introduce cxl_init_ep_ports_aer() to be called for each CXL Port in the
sub-topology between the endpoint and the CXL Host Bridge. This function
will determine if there are CXL Downstream Switch Ports or CXL Root Ports
associated with this Port. The same check will be added in the future for
upstream switch ports.
Move the RAS register map logic from cxl_dport_map_ras() into
cxl_dport_init_ras_reporting(). This eliminates the need for the helper
function, cxl_dport_map_ras().
cxl_init_ep_ports_aer() calls cxl_dport_init_ras_reporting() to map
the RAS registers for CXL Downstream Switch Ports and CXL Root Ports.
cxl_dport_init_ras_reporting() must check for previously mapped registers
before mapping. This is required because multiple Endpoints under a CXL
switch may share an upstream CXL Root Port, CXL Downstream Switch Port,
or CXL Downstream Switch Port. Ensure the RAS registers are only mapped
once.
Introduce a mutex for synchronizing accesses to the cached RAS mapping.
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Alejandro Lucero <alucerop@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
---
drivers/cxl/core/pci.c | 42 ++++++++++++++++++++----------------------
drivers/cxl/cxl.h | 6 ++----
drivers/cxl/mem.c | 31 +++++++++++++++++++++++++++++--
3 files changed, 51 insertions(+), 28 deletions(-)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index a5c65f79db18..143c853a52c4 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -24,6 +24,8 @@ static unsigned short media_ready_timeout = 60;
module_param(media_ready_timeout, ushort, 0644);
MODULE_PARM_DESC(media_ready_timeout, "seconds to wait for media ready");
+static DEFINE_MUTEX(ras_init_mutex);
+
struct cxl_walk_context {
struct pci_bus *bus;
struct cxl_port *port;
@@ -749,18 +751,6 @@ static void cxl_dport_map_rch_aer(struct cxl_dport *dport)
}
}
-static void cxl_dport_map_ras(struct cxl_dport *dport)
-{
- struct cxl_register_map *map = &dport->reg_map;
- struct device *dev = dport->dport_dev;
-
- if (!map->component_map.ras.valid)
- dev_dbg(dev, "RAS registers not found\n");
- else if (cxl_map_component_regs(map, &dport->regs.component,
- BIT(CXL_CM_CAP_CAP_ID_RAS)))
- dev_dbg(dev, "Failed to map RAS capability.\n");
-}
-
static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
{
void __iomem *aer_base = dport->regs.dport_aer;
@@ -788,22 +778,30 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
/**
* cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
* @dport: the cxl_dport that needs to be initialized
- * @host: host device for devm operations
*/
-void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
+void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
{
- dport->reg_map.host = host;
- cxl_dport_map_ras(dport);
-
- if (dport->rch) {
- struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport->dport_dev);
-
- if (!host_bridge->native_aer)
- return;
+ struct device *dport_dev = dport->dport_dev;
+ struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport_dev);
+ dport->reg_map.host = dport_dev;
+ if (dport->rch && host_bridge->native_aer) {
cxl_dport_map_rch_aer(dport);
cxl_disable_rch_root_ints(dport);
}
+
+ /* dport may have more than 1 downstream EP. Check if already mapped. */
+ mutex_lock(&ras_init_mutex);
+ if (dport->regs.ras) {
+ mutex_unlock(&ras_init_mutex);
+ return;
+ }
+
+ if (cxl_map_component_regs(&dport->reg_map, &dport->regs.component,
+ BIT(CXL_CM_CAP_CAP_ID_RAS)))
+ dev_err(dport_dev, "Failed to map RAS capability\n");
+ mutex_unlock(&ras_init_mutex);
+
}
EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 6baec4ba9141..82d0a8555a11 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -754,11 +754,9 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
resource_size_t rcrb);
#ifdef CONFIG_PCIEAER_CXL
-void cxl_setup_parent_dport(struct device *host, struct cxl_dport *dport);
-void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host);
+void cxl_dport_init_ras_reporting(struct cxl_dport *dport);
#else
-static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport,
- struct device *host) { }
+static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport) { }
#endif
struct cxl_decoder *to_cxl_decoder(struct device *dev);
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 9675243bd05b..8c1144bbc058 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -45,6 +45,31 @@ static int cxl_mem_dpa_show(struct seq_file *file, void *data)
return 0;
}
+static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type)
+{
+ struct pci_dev *pdev;
+
+ if (!dev || !dev_is_pci(dev))
+ return false;
+
+ pdev = to_pci_dev(dev);
+
+ return (pci_pcie_type(pdev) == pcie_type);
+}
+
+static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
+{
+ struct cxl_dport *dport = ep->dport;
+
+ if (dport) {
+ struct device *dport_dev = dport->dport_dev;
+
+ if (dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_DOWNSTREAM) ||
+ dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT))
+ cxl_dport_init_ras_reporting(dport);
+ }
+}
+
static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
struct cxl_dport *parent_dport)
{
@@ -52,6 +77,9 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
struct cxl_port *endpoint, *iter, *down;
int rc;
+ if (parent_dport->rch)
+ cxl_dport_init_ras_reporting(parent_dport);
+
/*
* Now that the path to the root is established record all the
* intervening ports in the chain.
@@ -62,6 +90,7 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
ep = cxl_ep_load(iter, cxlmd);
ep->next = down;
+ cxl_init_ep_ports_aer(ep);
}
/* Note: endpoint port component registers are derived from @cxlds */
@@ -166,8 +195,6 @@ static int cxl_mem_probe(struct device *dev)
else
endpoint_parent = &parent_port->dev;
- cxl_dport_init_ras_reporting(dport, dev);
-
scoped_guard(device, endpoint_parent) {
if (!endpoint_parent->driver) {
dev_err(dev, "CXL port topology %s not enabled\n",
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (6 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 23:02 ` Dave Jiang
` (2 more replies)
2025-02-11 19:24 ` [PATCH v7 09/17] cxl/pci: Update RAS handler interfaces to also support CXL PCIe Ports Terry Bowman
` (8 subsequent siblings)
16 siblings, 3 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
pointer to the CXL Upstream Port's mapped RAS registers.
Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
register mapping. This is similar to the existing
cxl_dport_init_ras_reporting() but for USP devices.
The USP may have multiple downstream endpoints. Before mapping RAS
registers check if the registers are already mapped.
Introduce a mutex for synchronizing accesses to the cached RAS
mapping.
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
---
drivers/cxl/core/pci.c | 19 ++++++++++++++++++-
drivers/cxl/cxl.h | 4 ++++
drivers/cxl/mem.c | 8 ++++++++
3 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 143c853a52c4..25513b9a8aff 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -775,6 +775,24 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
}
+void cxl_uport_init_ras_reporting(struct cxl_port *port)
+{
+
+ /* uport may have more than 1 downstream EP. Check if already mapped. */
+ mutex_lock(&ras_init_mutex);
+ if (port->uport_regs.ras) {
+ mutex_unlock(&ras_init_mutex);
+ return;
+ }
+
+ port->reg_map.host = &port->dev;
+ if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
+ BIT(CXL_CM_CAP_CAP_ID_RAS)))
+ dev_err(&port->dev, "Failed to map RAS capability\n");
+ mutex_unlock(&ras_init_mutex);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
+
/**
* cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
* @dport: the cxl_dport that needs to be initialized
@@ -801,7 +819,6 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
BIT(CXL_CM_CAP_CAP_ID_RAS)))
dev_err(dport_dev, "Failed to map RAS capability\n");
mutex_unlock(&ras_init_mutex);
-
}
EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 82d0a8555a11..49f29a3ef68e 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -581,6 +581,7 @@ struct cxl_dax_region {
* @parent_dport: dport that points to this port in the parent
* @decoder_ida: allocator for decoder ids
* @reg_map: component and ras register mapping parameters
+ * @uport_regs: mapped component registers
* @nr_dports: number of entries in @dports
* @hdm_end: track last allocated HDM decoder instance for allocation ordering
* @commit_end: cursor to track highest committed decoder for commit ordering
@@ -602,6 +603,7 @@ struct cxl_port {
struct cxl_dport *parent_dport;
struct ida decoder_ida;
struct cxl_register_map reg_map;
+ struct cxl_component_regs uport_regs;
int nr_dports;
int hdm_end;
int commit_end;
@@ -755,8 +757,10 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
#ifdef CONFIG_PCIEAER_CXL
void cxl_dport_init_ras_reporting(struct cxl_dport *dport);
+void cxl_uport_init_ras_reporting(struct cxl_port *port);
#else
static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport) { }
+static inline void cxl_uport_init_ras_reporting(struct cxl_port *port) { }
#endif
struct cxl_decoder *to_cxl_decoder(struct device *dev);
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 8c1144bbc058..541cabca434e 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -60,6 +60,7 @@ static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type)
static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
{
struct cxl_dport *dport = ep->dport;
+ struct cxl_port *port = ep->next;
if (dport) {
struct device *dport_dev = dport->dport_dev;
@@ -68,6 +69,13 @@ static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT))
cxl_dport_init_ras_reporting(dport);
}
+
+ if (port) {
+ struct device *uport_dev = port->uport_dev;
+
+ if (dev_is_cxl_pci(uport_dev, PCI_EXP_TYPE_UPSTREAM))
+ cxl_uport_init_ras_reporting(port);
+ }
}
static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 09/17] cxl/pci: Update RAS handler interfaces to also support CXL PCIe Ports
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (7 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream " Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 23:26 ` Dave Jiang
2025-02-14 15:19 ` Jonathan Cameron
2025-02-11 19:24 ` [PATCH v7 10/17] cxl/pci: Add log message and add type check in existing RAS handlers Terry Bowman
` (7 subsequent siblings)
16 siblings, 2 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
CXL PCIe Port Protocol Error handling support will be added to the
CXL drivers in the future. In preparation, rename the existing
interfaces to support handling all CXL PCIe Port Protocol Errors.
The driver's RAS support functions currently rely on a 'struct
cxl_dev_state' type parameter, which is not available for CXL Port
devices. However, since the same CXL RAS capability structure is
needed across most CXL components and devices, a common handling
approach should be adopted.
To accommodate this, update the __cxl_handle_cor_ras() and
__cxl_handle_ras() functions to use a `struct device` instead of
`struct cxl_dev_state`.
No functional changes are introduced.
[1] CXL 3.1 Spec, 8.2.4 CXL.cache and CXL.mem Registers
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Alejandro Lucero <alucerop@amd.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
---
drivers/cxl/core/pci.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 25513b9a8aff..69bb030aa8e1 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -652,7 +652,7 @@ void read_cdat_data(struct cxl_port *port)
}
EXPORT_SYMBOL_NS_GPL(read_cdat_data, "CXL");
-static void __cxl_handle_cor_ras(struct cxl_dev_state *cxlds,
+static void __cxl_handle_cor_ras(struct device *dev,
void __iomem *ras_base)
{
void __iomem *addr;
@@ -665,13 +665,13 @@ static void __cxl_handle_cor_ras(struct cxl_dev_state *cxlds,
status = readl(addr);
if (status & CXL_RAS_CORRECTABLE_STATUS_MASK) {
writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
- trace_cxl_aer_correctable_error(cxlds->cxlmd, status);
+ trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
}
}
static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
{
- return __cxl_handle_cor_ras(cxlds, cxlds->regs.ras);
+ return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
}
/* CXL spec rev3.0 8.2.4.16.1 */
@@ -695,8 +695,7 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)
* Log the state of the RAS status registers and prepare them to log the
* next error status. Return 1 if reset needed.
*/
-static bool __cxl_handle_ras(struct cxl_dev_state *cxlds,
- void __iomem *ras_base)
+static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
{
u32 hl[CXL_HEADERLOG_SIZE_U32];
void __iomem *addr;
@@ -723,7 +722,7 @@ static bool __cxl_handle_ras(struct cxl_dev_state *cxlds,
}
header_log_copy(ras_base, hl);
- trace_cxl_aer_uncorrectable_error(cxlds->cxlmd, status, fe, hl);
+ trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
return true;
@@ -731,7 +730,7 @@ static bool __cxl_handle_ras(struct cxl_dev_state *cxlds,
static bool cxl_handle_endpoint_ras(struct cxl_dev_state *cxlds)
{
- return __cxl_handle_ras(cxlds, cxlds->regs.ras);
+ return __cxl_handle_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
}
#ifdef CONFIG_PCIEAER_CXL
@@ -825,13 +824,13 @@ EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
static void cxl_handle_rdport_cor_ras(struct cxl_dev_state *cxlds,
struct cxl_dport *dport)
{
- return __cxl_handle_cor_ras(cxlds, dport->regs.ras);
+ return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, dport->regs.ras);
}
static bool cxl_handle_rdport_ras(struct cxl_dev_state *cxlds,
struct cxl_dport *dport)
{
- return __cxl_handle_ras(cxlds, dport->regs.ras);
+ return __cxl_handle_ras(&cxlds->cxlmd->dev, dport->regs.ras);
}
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 10/17] cxl/pci: Add log message and add type check in existing RAS handlers
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (8 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 09/17] cxl/pci: Update RAS handler interfaces to also support CXL PCIe Ports Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 23:28 ` Dave Jiang
2025-02-12 22:59 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 11/17] cxl/pci: Change find_cxl_port() to non-static Terry Bowman
` (6 subsequent siblings)
16 siblings, 2 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
The CXL RAS handlers do not currently log if the RAS registers are
unmapped. This is needed in order to help debug CXL error handling. Update
the CXL driver to log a warning message if the RAS register block is
unmapped.
Also, add type check before processing EP or RCH DP.
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
---
drivers/cxl/core/pci.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 69bb030aa8e1..af809e7cbe3b 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -658,15 +658,19 @@ static void __cxl_handle_cor_ras(struct device *dev,
void __iomem *addr;
u32 status;
- if (!ras_base)
+ if (!ras_base) {
+ dev_warn_once(dev, "CXL RAS register block is not mapped");
return;
+ }
addr = ras_base + CXL_RAS_CORRECTABLE_STATUS_OFFSET;
status = readl(addr);
- if (status & CXL_RAS_CORRECTABLE_STATUS_MASK) {
- writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
+ if (!(status & CXL_RAS_CORRECTABLE_STATUS_MASK))
+ return;
+ writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
+
+ if (is_cxl_memdev(dev))
trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
- }
}
static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
@@ -702,8 +706,10 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
u32 status;
u32 fe;
- if (!ras_base)
+ if (!ras_base) {
+ dev_warn_once(dev, "CXL RAS register block is not mapped");
return false;
+ }
addr = ras_base + CXL_RAS_UNCORRECTABLE_STATUS_OFFSET;
status = readl(addr);
@@ -722,7 +728,9 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
}
header_log_copy(ras_base, hl);
- trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
+ if (is_cxl_memdev(dev))
+ trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
+
writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
return true;
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 11/17] cxl/pci: Change find_cxl_port() to non-static
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (9 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 10/17] cxl/pci: Add log message and add type check in existing RAS handlers Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 23:42 ` Dave Jiang
2025-02-13 23:15 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors Terry Bowman
` (5 subsequent siblings)
16 siblings, 2 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
CXL PCIe Port Protocol Error support will be added in the future. This
requires searching for a CXL PCIe Port device in the CXL topology as
provided by find_cxl_port(). But, find_cxl_port() is defined static
and as a result is not callable outside of this source file.
Update the find_cxl_port() declaration to be non-static.
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
---
drivers/cxl/core/core.h | 2 ++
drivers/cxl/core/port.c | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index a20ea2b7d1a4..796334f2ad6c 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -118,5 +118,7 @@ int cxl_port_get_switch_dport_bandwidth(struct cxl_port *port,
struct access_coordinate *c);
int cxl_gpf_port_setup(struct device *dport_dev, struct cxl_port *port);
+struct cxl_port *find_cxl_port(struct device *dport_dev,
+ struct cxl_dport **dport);
#endif /* __CXL_CORE_H__ */
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index f9501a16b390..ae6471e4ebff 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -1352,8 +1352,8 @@ static struct cxl_port *__find_cxl_port(struct cxl_find_port_ctx *ctx)
return NULL;
}
-static struct cxl_port *find_cxl_port(struct device *dport_dev,
- struct cxl_dport **dport)
+struct cxl_port *find_cxl_port(struct device *dport_dev,
+ struct cxl_dport **dport)
{
struct cxl_find_port_ctx ctx = {
.dport_dev = dport_dev,
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (10 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 11/17] cxl/pci: Change find_cxl_port() to non-static Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-12 0:11 ` Dave Jiang
` (2 more replies)
2025-02-11 19:24 ` [PATCH v7 13/17] cxl/pci: Add trace logging " Terry Bowman
` (4 subsequent siblings)
16 siblings, 3 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Introduce correctable and uncorrectable (UCE) CXL PCIe Port Protocol Error
handlers.
The handlers will be called with a 'struct pci_dev' parameter
indicating the CXL Port device requiring handling. The CXL PCIe Port
device's underlying 'struct device' will match the port device in the
CXL topology.
Use the PCIe Port's device object to find the matching CXL Upstream Switch
Port, CXL Downstream Switch Port, or CXL Root Port in the CXL topology. The
matching CXL Port device should contain a cached reference to the RAS
register block. The cached RAS block will be used in handling the error.
Invoke the existing __cxl_handle_ras() or __cxl_handle_cor_ras() using
a reference to the RAS registers as a parameter. These functions will use
the RAS register reference to indicate an error and clear the device's RAS
status.
Update __cxl_handle_ras() to return PCI_ERS_RESULT_PANIC in the case
an error is present in the RAS status. Otherwise, return
PCI_ERS_RESULT_NONE.
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
---
drivers/cxl/core/pci.c | 81 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 77 insertions(+), 4 deletions(-)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index af809e7cbe3b..3f13d9dfb610 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -699,7 +699,7 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)
* Log the state of the RAS status registers and prepare them to log the
* next error status. Return 1 if reset needed.
*/
-static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
+static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
{
u32 hl[CXL_HEADERLOG_SIZE_U32];
void __iomem *addr;
@@ -708,13 +708,13 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
if (!ras_base) {
dev_warn_once(dev, "CXL RAS register block is not mapped");
- return false;
+ return PCI_ERS_RESULT_NONE;
}
addr = ras_base + CXL_RAS_UNCORRECTABLE_STATUS_OFFSET;
status = readl(addr);
if (!(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK))
- return false;
+ return PCI_ERS_RESULT_NONE;
/* If multiple errors, log header points to first error from ctrl reg */
if (hweight32(status) > 1) {
@@ -733,7 +733,7 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
- return true;
+ return PCI_ERS_RESULT_PANIC;
}
static bool cxl_handle_endpoint_ras(struct cxl_dev_state *cxlds)
@@ -782,6 +782,79 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
}
+static int match_uport(struct device *dev, const void *data)
+{
+ const struct device *uport_dev = data;
+ struct cxl_port *port;
+
+ if (!is_cxl_port(dev))
+ return 0;
+
+ port = to_cxl_port(dev);
+
+ return port->uport_dev == uport_dev;
+}
+
+static void __iomem *cxl_pci_port_ras(struct pci_dev *pdev, struct device **dev)
+{
+ void __iomem *ras_base;
+
+ if (!pdev || !*dev) {
+ pr_err("Failed, parameter is NULL");
+ return NULL;
+ }
+
+ if ((pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) ||
+ (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM)) {
+ struct cxl_port *port __free(put_cxl_port);
+ struct cxl_dport *dport = NULL;
+
+ port = find_cxl_port(&pdev->dev, &dport);
+ if (!port) {
+ pci_err(pdev, "Failed to find root/dport in CXL topology\n");
+ return NULL;
+ }
+
+ ras_base = dport ? dport->regs.ras : NULL;
+ *dev = &port->dev;
+ } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_UPSTREAM) {
+ struct device *port_dev __free(put_device);
+ struct cxl_port *port;
+
+ port_dev = bus_find_device(&cxl_bus_type, NULL, &pdev->dev,
+ match_uport);
+ if (!port_dev || !is_cxl_port(port_dev)) {
+ pci_err(pdev, "Failed to find uport in CXL topology\n");
+ return NULL;
+ }
+
+ port = to_cxl_port(port_dev);
+ ras_base = port ? port->uport_regs.ras : NULL;
+ *dev = port_dev;
+ } else {
+ pci_err(pdev, "Unsupported device type\n");
+ ras_base = NULL;
+ }
+
+ return ras_base;
+}
+
+static void cxl_port_cor_error_detected(struct pci_dev *pdev)
+{
+ struct device *dev;
+ void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
+
+ __cxl_handle_cor_ras(dev, ras_base);
+}
+
+static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
+{
+ struct device *dev;
+ void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
+
+ return __cxl_handle_ras(dev, ras_base);
+}
+
void cxl_uport_init_ras_reporting(struct cxl_port *port)
{
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 13/17] cxl/pci: Add trace logging for CXL PCIe Port RAS errors
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (11 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-12 0:11 ` Gregory Price
` (2 more replies)
2025-02-11 19:24 ` [PATCH v7 14/17] cxl/pci: Update CXL Port RAS logging to also display PCIe SBDF Terry Bowman
` (3 subsequent siblings)
16 siblings, 3 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
The CXL drivers use kernel trace functions for logging Endpoint and
Restricted CXL host (RCH) Downstream Port RAS errors. Similar functionality
is required for CXL Root Ports, CXL Downstream Switch Ports, and CXL
Upstream Switch Ports.
Introduce trace logging functions for both RAS correctable and
uncorrectable errors specific to CXL PCIe Ports. Additionally, update
the CXL Port Protocol Error handlers to invoke these new trace functions.
Examples of the output from these changes is below.
Correctable error:
cxl_port_aer_correctable_error: device=port1 parent=root0 status='Received Error From Physical Layer'
Uncorrectable error:
cxl_port_aer_uncorrectable_error: device=port1 parent=root0 status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Erro'
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Alejandro Lucero <alucerop@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
drivers/cxl/core/pci.c | 4 ++++
drivers/cxl/core/trace.h | 47 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 3f13d9dfb610..9a3090dae46a 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -671,6 +671,8 @@ static void __cxl_handle_cor_ras(struct device *dev,
if (is_cxl_memdev(dev))
trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
+ else if (is_cxl_port(dev))
+ trace_cxl_port_aer_correctable_error(dev, status);
}
static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
@@ -730,6 +732,8 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
header_log_copy(ras_base, hl);
if (is_cxl_memdev(dev))
trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
+ else if (is_cxl_port(dev))
+ trace_cxl_port_aer_uncorrectable_error(dev, status, fe, hl);
writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
diff --git a/drivers/cxl/core/trace.h b/drivers/cxl/core/trace.h
index cea706b683b5..b536233ac210 100644
--- a/drivers/cxl/core/trace.h
+++ b/drivers/cxl/core/trace.h
@@ -48,6 +48,34 @@
{ CXL_RAS_UC_IDE_RX_ERR, "IDE Rx Error" } \
)
+TRACE_EVENT(cxl_port_aer_uncorrectable_error,
+ TP_PROTO(struct device *dev, u32 status, u32 fe, u32 *hl),
+ TP_ARGS(dev, status, fe, hl),
+ TP_STRUCT__entry(
+ __string(devname, dev_name(dev))
+ __string(parent, dev_name(dev->parent))
+ __field(u32, status)
+ __field(u32, first_error)
+ __array(u32, header_log, CXL_HEADERLOG_SIZE_U32)
+ ),
+ TP_fast_assign(
+ __assign_str(devname);
+ __assign_str(parent);
+ __entry->status = status;
+ __entry->first_error = fe;
+ /*
+ * Embed the 512B headerlog data for user app retrieval and
+ * parsing, but no need to print this in the trace buffer.
+ */
+ memcpy(__entry->header_log, hl, CXL_HEADERLOG_SIZE);
+ ),
+ TP_printk("device=%s parent=%s status: '%s' first_error: '%s'",
+ __get_str(devname), __get_str(parent),
+ show_uc_errs(__entry->status),
+ show_uc_errs(__entry->first_error)
+ )
+);
+
TRACE_EVENT(cxl_aer_uncorrectable_error,
TP_PROTO(const struct cxl_memdev *cxlmd, u32 status, u32 fe, u32 *hl),
TP_ARGS(cxlmd, status, fe, hl),
@@ -96,6 +124,25 @@ TRACE_EVENT(cxl_aer_uncorrectable_error,
{ CXL_RAS_CE_PHYS_LAYER_ERR, "Received Error From Physical Layer" } \
)
+TRACE_EVENT(cxl_port_aer_correctable_error,
+ TP_PROTO(struct device *dev, u32 status),
+ TP_ARGS(dev, status),
+ TP_STRUCT__entry(
+ __string(devname, dev_name(dev))
+ __string(parent, dev_name(dev->parent))
+ __field(u32, status)
+ ),
+ TP_fast_assign(
+ __assign_str(devname);
+ __assign_str(parent);
+ __entry->status = status;
+ ),
+ TP_printk("device=%s parent=%s status='%s'",
+ __get_str(devname), __get_str(parent),
+ show_ce_errs(__entry->status)
+ )
+);
+
TRACE_EVENT(cxl_aer_correctable_error,
TP_PROTO(const struct cxl_memdev *cxlmd, u32 status),
TP_ARGS(cxlmd, status),
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 14/17] cxl/pci: Update CXL Port RAS logging to also display PCIe SBDF
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (12 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 13/17] cxl/pci: Add trace logging " Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-12 0:21 ` Dave Jiang
2025-02-12 23:30 ` Alison Schofield
2025-02-11 19:24 ` [PATCH v7 15/17] cxl/pci: Add support to assign and clear pci_driver::cxl_err_handlers Terry Bowman
` (2 subsequent siblings)
16 siblings, 2 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
CXL RAS errors are currently logged using the associated CXL port's name
returned from devname(). They are typically named with 'port1', 'port2',
etc. to indicate the hierarchial location in the CXL topology. But, this
doesn't clearly indicate the CXL card or slot reporting the error.
Update the logging to also log the corresponding PCIe devname. This will
give a PCIe SBDF or ACPI object name (in case of CXL HB). This will provide
details helping users understand which physical slot and card has the
error.
Below is example output after making these changes.
Correctable error example output:
cxl_port_aer_correctable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status='Received Error From Physical Layer'
Uncorrectable error example output:
cxl_port_aer_uncorrectable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Error'
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
---
drivers/cxl/core/pci.c | 39 +++++++++++++++++++------------------
drivers/cxl/core/trace.h | 42 +++++++++++++++++++++++++---------------
2 files changed, 46 insertions(+), 35 deletions(-)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 9a3090dae46a..f154dcf6dfda 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -652,14 +652,14 @@ void read_cdat_data(struct cxl_port *port)
}
EXPORT_SYMBOL_NS_GPL(read_cdat_data, "CXL");
-static void __cxl_handle_cor_ras(struct device *dev,
+static void __cxl_handle_cor_ras(struct device *cxl_dev, struct device *pcie_dev,
void __iomem *ras_base)
{
void __iomem *addr;
u32 status;
if (!ras_base) {
- dev_warn_once(dev, "CXL RAS register block is not mapped");
+ dev_warn_once(cxl_dev, "CXL RAS register block is not mapped");
return;
}
@@ -669,15 +669,15 @@ static void __cxl_handle_cor_ras(struct device *dev,
return;
writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
- if (is_cxl_memdev(dev))
- trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
- else if (is_cxl_port(dev))
- trace_cxl_port_aer_correctable_error(dev, status);
+ if (is_cxl_memdev(cxl_dev))
+ trace_cxl_aer_correctable_error(to_cxl_memdev(cxl_dev), status);
+ else if (is_cxl_port(cxl_dev))
+ trace_cxl_port_aer_correctable_error(cxl_dev, pcie_dev, status);
}
static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
{
- return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
+ return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, NULL, cxlds->regs.ras);
}
/* CXL spec rev3.0 8.2.4.16.1 */
@@ -701,7 +701,8 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)
* Log the state of the RAS status registers and prepare them to log the
* next error status. Return 1 if reset needed.
*/
-static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
+static pci_ers_result_t __cxl_handle_ras(struct device *cxl_dev, struct device *pcie_dev,
+ void __iomem *ras_base)
{
u32 hl[CXL_HEADERLOG_SIZE_U32];
void __iomem *addr;
@@ -709,7 +710,7 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
u32 fe;
if (!ras_base) {
- dev_warn_once(dev, "CXL RAS register block is not mapped");
+ dev_warn_once(cxl_dev, "CXL RAS register block is not mapped");
return PCI_ERS_RESULT_NONE;
}
@@ -730,10 +731,10 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
}
header_log_copy(ras_base, hl);
- if (is_cxl_memdev(dev))
- trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
- else if (is_cxl_port(dev))
- trace_cxl_port_aer_uncorrectable_error(dev, status, fe, hl);
+ if (is_cxl_memdev(cxl_dev))
+ trace_cxl_aer_uncorrectable_error(to_cxl_memdev(cxl_dev), status, fe, hl);
+ else if (is_cxl_port(cxl_dev))
+ trace_cxl_port_aer_uncorrectable_error(cxl_dev, pcie_dev, status, fe, hl);
writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
@@ -742,7 +743,7 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
static bool cxl_handle_endpoint_ras(struct cxl_dev_state *cxlds)
{
- return __cxl_handle_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
+ return __cxl_handle_ras(&cxlds->cxlmd->dev, NULL, cxlds->regs.ras);
}
#ifdef CONFIG_PCIEAER_CXL
@@ -814,7 +815,7 @@ static void __iomem *cxl_pci_port_ras(struct pci_dev *pdev, struct device **dev)
struct cxl_dport *dport = NULL;
port = find_cxl_port(&pdev->dev, &dport);
- if (!port) {
+ if (!port || !is_cxl_port(&port->dev)) {
pci_err(pdev, "Failed to find root/dport in CXL topology\n");
return NULL;
}
@@ -848,7 +849,7 @@ static void cxl_port_cor_error_detected(struct pci_dev *pdev)
struct device *dev;
void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
- __cxl_handle_cor_ras(dev, ras_base);
+ __cxl_handle_cor_ras(dev, &pdev->dev, ras_base);
}
static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
@@ -856,7 +857,7 @@ static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
struct device *dev;
void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
- return __cxl_handle_ras(dev, ras_base);
+ return __cxl_handle_ras(dev, &pdev->dev, ras_base);
}
void cxl_uport_init_ras_reporting(struct cxl_port *port)
@@ -909,13 +910,13 @@ EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
static void cxl_handle_rdport_cor_ras(struct cxl_dev_state *cxlds,
struct cxl_dport *dport)
{
- return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, dport->regs.ras);
+ return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, NULL, dport->regs.ras);
}
static bool cxl_handle_rdport_ras(struct cxl_dev_state *cxlds,
struct cxl_dport *dport)
{
- return __cxl_handle_ras(&cxlds->cxlmd->dev, dport->regs.ras);
+ return __cxl_handle_ras(&cxlds->cxlmd->dev, NULL, dport->regs.ras);
}
/*
diff --git a/drivers/cxl/core/trace.h b/drivers/cxl/core/trace.h
index b536233ac210..a74803f4aa22 100644
--- a/drivers/cxl/core/trace.h
+++ b/drivers/cxl/core/trace.h
@@ -49,18 +49,22 @@
)
TRACE_EVENT(cxl_port_aer_uncorrectable_error,
- TP_PROTO(struct device *dev, u32 status, u32 fe, u32 *hl),
- TP_ARGS(dev, status, fe, hl),
+ TP_PROTO(struct device *cxl_dev, struct device *pcie_dev, u32 status, u32 fe, u32 *hl),
+ TP_ARGS(cxl_dev, pcie_dev, status, fe, hl),
TP_STRUCT__entry(
- __string(devname, dev_name(dev))
- __string(parent, dev_name(dev->parent))
+ __string(cxl_name, dev_name(cxl_dev))
+ __string(cxl_parent_name, dev_name(cxl_dev->parent))
+ __string(pcie_name, dev_name(pcie_dev))
+ __string(pcie_parent_name, dev_name(pcie_dev->parent))
__field(u32, status)
__field(u32, first_error)
__array(u32, header_log, CXL_HEADERLOG_SIZE_U32)
),
TP_fast_assign(
- __assign_str(devname);
- __assign_str(parent);
+ __assign_str(cxl_name);
+ __assign_str(cxl_parent_name);
+ __assign_str(pcie_name);
+ __assign_str(pcie_parent_name);
__entry->status = status;
__entry->first_error = fe;
/*
@@ -69,8 +73,9 @@ TRACE_EVENT(cxl_port_aer_uncorrectable_error,
*/
memcpy(__entry->header_log, hl, CXL_HEADERLOG_SIZE);
),
- TP_printk("device=%s parent=%s status: '%s' first_error: '%s'",
- __get_str(devname), __get_str(parent),
+ TP_printk("device=%s (%s) parent=%s (%s) status: '%s' first_error: '%s'",
+ __get_str(cxl_name), __get_str(pcie_name),
+ __get_str(cxl_parent_name), __get_str(pcie_parent_name),
show_uc_errs(__entry->status),
show_uc_errs(__entry->first_error)
)
@@ -125,20 +130,25 @@ TRACE_EVENT(cxl_aer_uncorrectable_error,
)
TRACE_EVENT(cxl_port_aer_correctable_error,
- TP_PROTO(struct device *dev, u32 status),
- TP_ARGS(dev, status),
+ TP_PROTO(struct device *cxl_dev, struct device *pcie_dev, u32 status),
+ TP_ARGS(cxl_dev, pcie_dev, status),
TP_STRUCT__entry(
- __string(devname, dev_name(dev))
- __string(parent, dev_name(dev->parent))
+ __string(cxl_name, dev_name(cxl_dev))
+ __string(cxl_parent_name, dev_name(cxl_dev->parent))
+ __string(pcie_name, dev_name(pcie_dev))
+ __string(pcie_parent_name, dev_name(pcie_dev->parent))
__field(u32, status)
),
TP_fast_assign(
- __assign_str(devname);
- __assign_str(parent);
+ __assign_str(cxl_name);
+ __assign_str(cxl_parent_name);
+ __assign_str(pcie_name);
+ __assign_str(pcie_parent_name);
__entry->status = status;
),
- TP_printk("device=%s parent=%s status='%s'",
- __get_str(devname), __get_str(parent),
+ TP_printk("device=%s (%s) parent=%s (%s) status='%s'",
+ __get_str(cxl_name), __get_str(pcie_name),
+ __get_str(cxl_parent_name), __get_str(pcie_parent_name),
show_ce_errs(__entry->status)
)
);
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 15/17] cxl/pci: Add support to assign and clear pci_driver::cxl_err_handlers
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (13 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 14/17] cxl/pci: Update CXL Port RAS logging to also display PCIe SBDF Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-12 0:38 ` Dave Jiang
2025-02-14 2:29 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 16/17] PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch Ports Terry Bowman
2025-02-11 19:24 ` [PATCH v7 17/17] cxl/pci: Handle CXL Endpoint and RCH Protocol Errors separately from PCIe errors Terry Bowman
16 siblings, 2 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
pci_driver::cxl_err_handlers are not currently assigned handler callbacks.
The handlers can't be set in the pci_driver static definition because the
CXL PCIe Port devices are bound to the portdrv driver which is not CXL
driver aware.
Add cxl_assign_port_error_handlers() in the cxl_core module. This
function will assign the default handlers for a CXL PCIe Port device.
When the CXL Port (cxl_port or cxl_dport) is destroyed the device's
pci_driver::cxl_err_handlers must be set to NULL indicating they should no
longer be used.
Create cxl_clear_port_error_handlers() and register it to be called
when the CXL Port device (cxl_port or cxl_dport) is destroyed.
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
---
drivers/cxl/core/pci.c | 59 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 57 insertions(+), 2 deletions(-)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index f154dcf6dfda..03ae21a944e0 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -860,8 +860,39 @@ static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
return __cxl_handle_ras(dev, &pdev->dev, ras_base);
}
+static const struct cxl_error_handlers cxl_port_error_handlers = {
+ .error_detected = cxl_port_error_detected,
+ .cor_error_detected = cxl_port_cor_error_detected,
+};
+
+static void cxl_assign_port_error_handlers(struct pci_dev *pdev)
+{
+ struct pci_driver *pdrv;
+
+ if (!pdev || !pdev->driver || !get_device(&pdev->dev))
+ return;
+
+ pdrv = pdev->driver;
+ pdrv->cxl_err_handler = &cxl_port_error_handlers;
+ put_device(&pdev->dev);
+}
+
+static void cxl_clear_port_error_handlers(void *data)
+{
+ struct pci_dev *pdev = data;
+ struct pci_driver *pdrv;
+
+ if (!pdev || !pdev->driver || !get_device(&pdev->dev))
+ return;
+
+ pdrv = pdev->driver;
+ pdrv->cxl_err_handler = NULL;
+ put_device(&pdev->dev);
+}
+
void cxl_uport_init_ras_reporting(struct cxl_port *port)
{
+ struct pci_dev *pdev = to_pci_dev(port->uport_dev);
/* uport may have more than 1 downstream EP. Check if already mapped. */
mutex_lock(&ras_init_mutex);
@@ -872,9 +903,15 @@ void cxl_uport_init_ras_reporting(struct cxl_port *port)
port->reg_map.host = &port->dev;
if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
- BIT(CXL_CM_CAP_CAP_ID_RAS)))
+ BIT(CXL_CM_CAP_CAP_ID_RAS))) {
dev_err(&port->dev, "Failed to map RAS capability\n");
+ mutex_unlock(&ras_init_mutex);
+ return;
+ }
mutex_unlock(&ras_init_mutex);
+
+ cxl_assign_port_error_handlers(pdev);
+ devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
}
EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
@@ -886,6 +923,8 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
{
struct device *dport_dev = dport->dport_dev;
struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport_dev);
+ struct pci_dev *pdev = to_pci_dev(dport_dev);
+ struct cxl_port *port;
dport->reg_map.host = dport_dev;
if (dport->rch && host_bridge->native_aer) {
@@ -901,9 +940,25 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
}
if (cxl_map_component_regs(&dport->reg_map, &dport->regs.component,
- BIT(CXL_CM_CAP_CAP_ID_RAS)))
+ BIT(CXL_CM_CAP_CAP_ID_RAS))) {
dev_err(dport_dev, "Failed to map RAS capability\n");
+ mutex_unlock(&ras_init_mutex);
+ return;
+ }
mutex_unlock(&ras_init_mutex);
+
+ if (dport->rch)
+ return;
+
+ port = find_cxl_port(dport_dev, NULL);
+ if (!port) {
+ dev_err(dport_dev, "Failed to find upstream port\n");
+ return;
+ }
+
+ cxl_assign_port_error_handlers(pdev);
+ devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
+ put_device(&port->dev);
}
EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 16/17] PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch Ports
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (14 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 15/17] cxl/pci: Add support to assign and clear pci_driver::cxl_err_handlers Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-11 20:25 ` Bjorn Helgaas
` (2 more replies)
2025-02-11 19:24 ` [PATCH v7 17/17] cxl/pci: Handle CXL Endpoint and RCH Protocol Errors separately from PCIe errors Terry Bowman
16 siblings, 3 replies; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
The AER service driver enables PCIe Uncorrectable Internal Errors (UIE) and
Correctable Internal errors (CIE) for CXL Root Ports. The UIE and CIE are
used in reporting CXL Protocol Errors. The same UIE/CIE enablement is
needed for CXL Upstream Switch Ports and CXL Downstream Switch Ports
inorder to notify the associated Root Port and OS.[1]
Export the AER service driver's pci_aer_unmask_internal_errors() function
to CXL namespace.
Remove the function's dependency on the CONFIG_PCIEAER_CXL kernel config
because it is now an exported function.
Call pci_aer_unmask_internal_errors() during RAS initialization in:
cxl_uport_init_ras_reporting() and cxl_dport_init_ras_reporting().
[1] PCIe Base Spec r6.2-1.0, 6.2.3.2.2 Masking Individual Errors
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
drivers/cxl/core/pci.c | 2 ++
drivers/pci/pcie/aer.c | 3 ++-
include/linux/aer.h | 1 +
3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 03ae21a944e0..36e686a31045 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -912,6 +912,7 @@ void cxl_uport_init_ras_reporting(struct cxl_port *port)
cxl_assign_port_error_handlers(pdev);
devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
+ pci_aer_unmask_internal_errors(pdev);
}
EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
@@ -959,6 +960,7 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
cxl_assign_port_error_handlers(pdev);
devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
put_device(&port->dev);
+ pci_aer_unmask_internal_errors(pdev);
}
EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index ee38db08d005..8e3a60411610 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -948,7 +948,7 @@ static bool find_source_device(struct pci_dev *parent,
* Note: AER must be enabled and supported by the device which must be
* checked in advance, e.g. with pcie_aer_is_native().
*/
-static void pci_aer_unmask_internal_errors(struct pci_dev *dev)
+void pci_aer_unmask_internal_errors(struct pci_dev *dev)
{
int aer = dev->aer_cap;
u32 mask;
@@ -961,6 +961,7 @@ static void pci_aer_unmask_internal_errors(struct pci_dev *dev)
mask &= ~PCI_ERR_COR_INTERNAL;
pci_write_config_dword(dev, aer + PCI_ERR_COR_MASK, mask);
}
+EXPORT_SYMBOL_NS_GPL(pci_aer_unmask_internal_errors, "CXL");
static bool is_cxl_mem_dev(struct pci_dev *dev)
{
diff --git a/include/linux/aer.h b/include/linux/aer.h
index 947b63091902..a54545796edc 100644
--- a/include/linux/aer.h
+++ b/include/linux/aer.h
@@ -61,5 +61,6 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
int cper_severity_to_aer(int cper_severity);
void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
int severity, struct aer_capability_regs *aer_regs);
+void pci_aer_unmask_internal_errors(struct pci_dev *dev);
#endif //_AER_H_
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* [PATCH v7 17/17] cxl/pci: Handle CXL Endpoint and RCH Protocol Errors separately from PCIe errors
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
` (15 preceding siblings ...)
2025-02-11 19:24 ` [PATCH v7 16/17] PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch Ports Terry Bowman
@ 2025-02-11 19:24 ` Terry Bowman
2025-02-14 2:43 ` Dan Williams
16 siblings, 1 reply; 94+ messages in thread
From: Terry Bowman @ 2025-02-11 19:24 UTC (permalink / raw)
To: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot, terry.bowman,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
CXL Endpoint and Restricted CXL Host (RCH) Downstream Port Protocol Errors
are currently treated as PCIe errors, which does not properly process CXL
uncorrectable (UCE) errors. When a CXL device encounters an uncorrectable
Protocol Error, the system should panic to prevent potential CXL memory
corruption.
Treat CXL Endpoint Protocol Errors as CXL errors. This requires updates in
the CXL and AER drivers.
Update the CXL Endpoint driver with a new declaration for struct
cxl_error_handlers named cxl_ep_error_handlers. Move the existing CE and
UCE handler assignments from cxl_error_handlers to the new
cxl_ep_error_handlers. Remove the 'state' parameter from the UCE handler
interface because it is not used in CXL recovery.
Update the AER driver to associate CXL Protocol errors with CXL error
handling. Change detection in handles_cxl_errors() from using
pcie_is_cxl_port() to instead use pcie_is_cxl().
Update AER driver to use CXL handlers for RCH handling.
Signed-off-by: Terry Bowman <terry.bowman@amd.com>
---
drivers/cxl/core/pci.c | 26 +++++---------------------
drivers/cxl/cxlpci.h | 3 +--
drivers/cxl/pci.c | 10 +++++++---
drivers/pci/pcie/aer.c | 11 ++++++-----
4 files changed, 19 insertions(+), 31 deletions(-)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 36e686a31045..18d47a14959e 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -1075,8 +1075,7 @@ void cxl_cor_error_detected(struct pci_dev *pdev)
}
EXPORT_SYMBOL_NS_GPL(cxl_cor_error_detected, "CXL");
-pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
- pci_channel_state_t state)
+pci_ers_result_t cxl_error_detected(struct pci_dev *pdev)
{
struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
struct cxl_memdev *cxlmd = cxlds->cxlmd;
@@ -1088,7 +1087,7 @@ pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
dev_warn(&pdev->dev,
"%s: memdev disabled, abort error handling\n",
dev_name(dev));
- return PCI_ERS_RESULT_DISCONNECT;
+ return PCI_ERS_RESULT_PANIC;
}
if (cxlds->rcd)
@@ -1102,26 +1101,11 @@ pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
ue = cxl_handle_endpoint_ras(cxlds);
}
-
- switch (state) {
- case pci_channel_io_normal:
- if (ue) {
- device_release_driver(dev);
- return PCI_ERS_RESULT_NEED_RESET;
- }
- return PCI_ERS_RESULT_CAN_RECOVER;
- case pci_channel_io_frozen:
- dev_warn(&pdev->dev,
- "%s: frozen state error detected, disable CXL.mem\n",
- dev_name(dev));
+ if (ue) {
device_release_driver(dev);
- return PCI_ERS_RESULT_NEED_RESET;
- case pci_channel_io_perm_failure:
- dev_warn(&pdev->dev,
- "failure state error detected, request disconnect\n");
- return PCI_ERS_RESULT_DISCONNECT;
+ return PCI_ERS_RESULT_PANIC;
}
- return PCI_ERS_RESULT_NEED_RESET;
+ return PCI_ERS_RESULT_CAN_RECOVER;
}
EXPORT_SYMBOL_NS_GPL(cxl_error_detected, "CXL");
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
index 54e219b0049e..4b8910d934d5 100644
--- a/drivers/cxl/cxlpci.h
+++ b/drivers/cxl/cxlpci.h
@@ -133,6 +133,5 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
struct cxl_endpoint_dvsec_info *info);
void read_cdat_data(struct cxl_port *port);
void cxl_cor_error_detected(struct pci_dev *pdev);
-pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
- pci_channel_state_t state);
+pci_ers_result_t cxl_error_detected(struct pci_dev *pdev);
#endif /* __CXL_PCI_H__ */
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index b2c943a4de0a..520570741402 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -1104,11 +1104,14 @@ static void cxl_reset_done(struct pci_dev *pdev)
}
}
-static const struct pci_error_handlers cxl_error_handlers = {
+static const struct cxl_error_handlers cxl_ep_error_handlers = {
.error_detected = cxl_error_detected,
+ .cor_error_detected = cxl_cor_error_detected,
+};
+
+static const struct pci_error_handlers pcie_ep_error_handlers = {
.slot_reset = cxl_slot_reset,
.resume = cxl_error_resume,
- .cor_error_detected = cxl_cor_error_detected,
.reset_done = cxl_reset_done,
};
@@ -1116,7 +1119,8 @@ static struct pci_driver cxl_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = cxl_mem_pci_tbl,
.probe = cxl_pci_probe,
- .err_handler = &cxl_error_handlers,
+ .err_handler = &pcie_ep_error_handlers,
+ .cxl_err_handler = &cxl_ep_error_handlers,
.dev_groups = cxl_rcd_groups,
.driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index 8e3a60411610..07c888fd4c08 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -993,7 +993,7 @@ static bool cxl_error_is_native(struct pci_dev *dev)
static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
{
struct aer_err_info *info = (struct aer_err_info *)data;
- const struct pci_error_handlers *err_handler;
+ const struct cxl_error_handlers *err_handler;
if (!is_cxl_mem_dev(dev) || !cxl_error_is_native(dev))
return 0;
@@ -1001,7 +1001,8 @@ static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
/* protect dev->driver */
device_lock(&dev->dev);
- err_handler = dev->driver ? dev->driver->err_handler : NULL;
+ err_handler = dev->driver ? dev->driver->cxl_err_handler : NULL;
+
if (!err_handler)
goto out;
@@ -1010,9 +1011,9 @@ static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
err_handler->cor_error_detected(dev);
} else if (err_handler->error_detected) {
if (info->severity == AER_NONFATAL)
- err_handler->error_detected(dev, pci_channel_io_normal);
+ err_handler->error_detected(dev);
else if (info->severity == AER_FATAL)
- err_handler->error_detected(dev, pci_channel_io_frozen);
+ err_handler->error_detected(dev);
cxl_do_recovery(dev);
}
@@ -1070,7 +1071,7 @@ static bool handles_cxl_errors(struct pci_dev *dev)
if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC)
pcie_walk_rcec(dev, handles_cxl_error_iter, &handles_cxl);
else
- handles_cxl = pcie_is_cxl_port(dev);
+ handles_cxl = pcie_is_cxl(dev);
return handles_cxl;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 94+ messages in thread
* Re: [PATCH v7 16/17] PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch Ports
2025-02-11 19:24 ` [PATCH v7 16/17] PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch Ports Terry Bowman
@ 2025-02-11 20:25 ` Bjorn Helgaas
2025-02-11 20:40 ` Bowman, Terry
2025-02-12 0:40 ` Dave Jiang
2025-02-14 2:35 ` Dan Williams
2 siblings, 1 reply; 94+ messages in thread
From: Bjorn Helgaas @ 2025-02-11 20:25 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:43PM -0600, Terry Bowman wrote:
> The AER service driver enables PCIe Uncorrectable Internal Errors (UIE) and
> Correctable Internal errors (CIE) for CXL Root Ports. The UIE and CIE are
> used in reporting CXL Protocol Errors. The same UIE/CIE enablement is
> needed for CXL Upstream Switch Ports and CXL Downstream Switch Ports
> inorder to notify the associated Root Port and OS.[1]
>
> Export the AER service driver's pci_aer_unmask_internal_errors() function
> to CXL namespace.
>
> Remove the function's dependency on the CONFIG_PCIEAER_CXL kernel config
> because it is now an exported function.
>
> Call pci_aer_unmask_internal_errors() during RAS initialization in:
> cxl_uport_init_ras_reporting() and cxl_dport_init_ras_reporting().
>
> [1] PCIe Base Spec r6.2-1.0, 6.2.3.2.2 Masking Individual Errors
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
I'd say this is really a CXL-centric change, given that
pci_aer_unmask_internal_errors() is only used for CXL and it's
exported in the CXL namespace. So I would use
cxl/pci: ...
in the subject.
> ---
> drivers/cxl/core/pci.c | 2 ++
> drivers/pci/pcie/aer.c | 3 ++-
> include/linux/aer.h | 1 +
> 3 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 03ae21a944e0..36e686a31045 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -912,6 +912,7 @@ void cxl_uport_init_ras_reporting(struct cxl_port *port)
>
> cxl_assign_port_error_handlers(pdev);
> devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
> + pci_aer_unmask_internal_errors(pdev);
> }
> EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
>
> @@ -959,6 +960,7 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
> cxl_assign_port_error_handlers(pdev);
> devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
> put_device(&port->dev);
> + pci_aer_unmask_internal_errors(pdev);
> }
> EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index ee38db08d005..8e3a60411610 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -948,7 +948,7 @@ static bool find_source_device(struct pci_dev *parent,
> * Note: AER must be enabled and supported by the device which must be
> * checked in advance, e.g. with pcie_aer_is_native().
> */
> -static void pci_aer_unmask_internal_errors(struct pci_dev *dev)
> +void pci_aer_unmask_internal_errors(struct pci_dev *dev)
> {
> int aer = dev->aer_cap;
> u32 mask;
> @@ -961,6 +961,7 @@ static void pci_aer_unmask_internal_errors(struct pci_dev *dev)
> mask &= ~PCI_ERR_COR_INTERNAL;
> pci_write_config_dword(dev, aer + PCI_ERR_COR_MASK, mask);
> }
> +EXPORT_SYMBOL_NS_GPL(pci_aer_unmask_internal_errors, "CXL");
>
> static bool is_cxl_mem_dev(struct pci_dev *dev)
> {
> diff --git a/include/linux/aer.h b/include/linux/aer.h
> index 947b63091902..a54545796edc 100644
> --- a/include/linux/aer.h
> +++ b/include/linux/aer.h
> @@ -61,5 +61,6 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
> int cper_severity_to_aer(int cper_severity);
> void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
> int severity, struct aer_capability_regs *aer_regs);
> +void pci_aer_unmask_internal_errors(struct pci_dev *dev);
> #endif //_AER_H_
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 01/17] PCI/AER: Introduce 'struct cxl_err_handlers' and add to 'struct pci_driver'
2025-02-11 19:24 ` [PATCH v7 01/17] PCI/AER: Introduce 'struct cxl_err_handlers' and add to 'struct pci_driver' Terry Bowman
@ 2025-02-11 20:25 ` Bjorn Helgaas
2025-02-11 20:42 ` Dan Williams
1 sibling, 0 replies; 94+ messages in thread
From: Bjorn Helgaas @ 2025-02-11 20:25 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:28PM -0600, Terry Bowman wrote:
> CXL.io is implemented on top of PCIe Protocol Errors. But, CXL.io and PCIe
> have different handling requirements for uncorrectable errors (UCE).
>
> The PCIe AER service driver may attempt recovering PCIe devices with
> UCE while recovery is not used for CXL.io. Recovery is not used in the
> CXL.io case because of potential corruption on what can be system memory.
>
> Create pci_driver::cxl_err_handlers structure similar to
> pci_driver::error_handler. Create handlers for correctable and
> uncorrectable CXL.io error handling.
>
> The CXL error handlers will be used in future patches adding CXL PCIe
> Port Protocol Error handling.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
> include/linux/pci.h | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 47b31ad724fa..1d62e785ae1f 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -884,6 +884,14 @@ struct pci_error_handlers {
> void (*cor_error_detected)(struct pci_dev *dev);
> };
>
> +/* Compute Express Link (CXL) bus error event callbacks */
> +struct cxl_error_handlers {
> + /* CXL bus error detected on this device */
> + pci_ers_result_t (*error_detected)(struct pci_dev *dev);
> +
> + /* Allow device driver to record more details of a correctable error */
> + void (*cor_error_detected)(struct pci_dev *dev);
> +};
>
> struct module;
>
> @@ -929,6 +937,7 @@ struct module;
> * @sriov_get_vf_total_msix: PF driver callback to get the total number of
> * MSI-X vectors available for distribution to the VFs.
> * @err_handler: See Documentation/PCI/pci-error-recovery.rst
> + * @cxl_err_handler: Compute Express Link specific error handlers.
> * @groups: Sysfs attribute groups.
> * @dev_groups: Attributes attached to the device that will be
> * created once it is bound to the driver.
> @@ -954,6 +963,7 @@ struct pci_driver {
> int (*sriov_set_msix_vec_count)(struct pci_dev *vf, int msix_vec_count); /* On PF */
> u32 (*sriov_get_vf_total_msix)(struct pci_dev *pf);
> const struct pci_error_handlers *err_handler;
> + const struct cxl_error_handlers *cxl_err_handler;
> const struct attribute_group **groups;
> const struct attribute_group **dev_groups;
> struct device_driver driver;
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 02/17] PCI/AER: Rename AER driver's interfaces to also indicate CXL PCIe Port support
2025-02-11 19:24 ` [PATCH v7 02/17] PCI/AER: Rename AER driver's interfaces to also indicate CXL PCIe Port support Terry Bowman
@ 2025-02-11 20:26 ` Bjorn Helgaas
2025-02-11 20:44 ` Dan Williams
1 sibling, 0 replies; 94+ messages in thread
From: Bjorn Helgaas @ 2025-02-11 20:26 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:29PM -0600, Terry Bowman wrote:
> The AER service driver already includes support for Restricted CXL host
> (RCH) Downstream Port Protocol Error handling. The current implementation
> is based on CXL1.1 using a Root Complex Event Collector.
>
> Rename function interfaces and parameters where necessary to include
> virtual hierarchy (VH) mode CXL PCIe Port error handling alongside the RCH
> handling.[1] The CXL PCIe Port Protocol Error handling support will be
> added in a future patch.
>
> Limit changes to renaming variable and function names. No functional
> changes are added.
>
> [1] CXL 3.1 Spec, 9.12.2 CXL Virtual Hierarchy
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
> drivers/pci/pcie/aer.c | 28 ++++++++++++++--------------
> 1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index 508474e17183..6e8de77d0fc4 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -1024,7 +1024,7 @@ static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
> return 0;
> }
>
> -static void cxl_rch_handle_error(struct pci_dev *dev, struct aer_err_info *info)
> +static void cxl_handle_error(struct pci_dev *dev, struct aer_err_info *info)
> {
> /*
> * Internal errors of an RCEC indicate an AER error in an
> @@ -1047,30 +1047,30 @@ static int handles_cxl_error_iter(struct pci_dev *dev, void *data)
> return *handles_cxl;
> }
>
> -static bool handles_cxl_errors(struct pci_dev *rcec)
> +static bool handles_cxl_errors(struct pci_dev *dev)
> {
> bool handles_cxl = false;
>
> - if (pci_pcie_type(rcec) == PCI_EXP_TYPE_RC_EC &&
> - pcie_aer_is_native(rcec))
> - pcie_walk_rcec(rcec, handles_cxl_error_iter, &handles_cxl);
> + if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC &&
> + pcie_aer_is_native(dev))
> + pcie_walk_rcec(dev, handles_cxl_error_iter, &handles_cxl);
>
> return handles_cxl;
> }
>
> -static void cxl_rch_enable_rcec(struct pci_dev *rcec)
> +static void cxl_enable_internal_errors(struct pci_dev *dev)
> {
> - if (!handles_cxl_errors(rcec))
> + if (!handles_cxl_errors(dev))
> return;
>
> - pci_aer_unmask_internal_errors(rcec);
> - pci_info(rcec, "CXL: Internal errors unmasked");
> + pci_aer_unmask_internal_errors(dev);
> + pci_info(dev, "CXL: Internal errors unmasked");
> }
>
> #else
> -static inline void cxl_rch_enable_rcec(struct pci_dev *dev) { }
> -static inline void cxl_rch_handle_error(struct pci_dev *dev,
> - struct aer_err_info *info) { }
> +static inline void cxl_enable_internal_errors(struct pci_dev *dev) { }
> +static inline void cxl_handle_error(struct pci_dev *dev,
> + struct aer_err_info *info) { }
> #endif
>
> /**
> @@ -1108,7 +1108,7 @@ static void pci_aer_handle_error(struct pci_dev *dev, struct aer_err_info *info)
>
> static void handle_error_source(struct pci_dev *dev, struct aer_err_info *info)
> {
> - cxl_rch_handle_error(dev, info);
> + cxl_handle_error(dev, info);
> pci_aer_handle_error(dev, info);
> pci_dev_put(dev);
> }
> @@ -1491,7 +1491,7 @@ static int aer_probe(struct pcie_device *dev)
> return status;
> }
>
> - cxl_rch_enable_rcec(port);
> + cxl_enable_internal_errors(port);
> aer_enable_rootport(rpc);
> pci_info(port, "enabled with IRQ %d\n", dev->irq);
> return 0;
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port()
2025-02-11 19:24 ` [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port() Terry Bowman
@ 2025-02-11 20:28 ` Bjorn Helgaas
2025-02-11 20:38 ` Bowman, Terry
2025-02-11 22:33 ` Dan Williams
2025-03-04 19:11 ` Ira Weiny
2 siblings, 1 reply; 94+ messages in thread
From: Bjorn Helgaas @ 2025-02-11 20:28 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:30PM -0600, Terry Bowman wrote:
> CXL and AER drivers need the ability to identify CXL devices and CXL port
> devices.
>
> First, add set_pcie_cxl() with logic checking for CXL Flexbus DVSEC
> presence. The CXL Flexbus DVSEC presence is used because it is required
> for all the CXL PCIe devices.[1]
>
> Add boolean 'struct pci_dev::is_cxl' with the purpose to cache the CXL
> Flexbus presence.
>
> Add pcie_is_cxl() as a macro to return 'struct pci_dev::is_cxl'.
>
> Add pcie_is_cxl_port() to check if a device is a CXL Root Port, CXL
> Upstream Switch Port, or CXL Downstream Switch Port. Also, verify the
> CXL Extensions DVSEC for Ports is present.[1]
>
> [1] CXL 3.1 Spec, 8.1.1 PCIe Designated Vendor-Specific Extended
> Capability (DVSEC) ID Assignment, Table 8-2
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
But I would change the subject to:
PCI/CXL: ...
since this only changes drivers/pci files.
> ---
> drivers/pci/pci.c | 13 +++++++++++++
> drivers/pci/probe.c | 10 ++++++++++
> include/linux/pci.h | 5 +++++
> include/uapi/linux/pci_regs.h | 3 ++-
> 4 files changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 869d204a70a3..a2d8b41dd043 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -5032,6 +5032,19 @@ static u16 cxl_port_dvsec(struct pci_dev *dev)
> PCI_DVSEC_CXL_PORT);
> }
>
> +inline bool pcie_is_cxl(struct pci_dev *pci_dev)
> +{
> + return pci_dev->is_cxl;
> +}
> +
> +bool pcie_is_cxl_port(struct pci_dev *dev)
> +{
> + if (!pcie_is_cxl(dev))
> + return false;
> +
> + return (cxl_port_dvsec(dev) > 0);
> +}
> +
> static bool cxl_sbr_masked(struct pci_dev *dev)
> {
> u16 dvsec, reg;
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index b6536ed599c3..7737b9ce7a83 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -1676,6 +1676,14 @@ static void set_pcie_thunderbolt(struct pci_dev *dev)
> dev->is_thunderbolt = 1;
> }
>
> +static void set_pcie_cxl(struct pci_dev *dev)
> +{
> + u16 dvsec = pci_find_dvsec_capability(dev, PCI_VENDOR_ID_CXL,
> + PCI_DVSEC_CXL_FLEXBUS);
> + if (dvsec)
> + dev->is_cxl = 1;
> +}
> +
> static void set_pcie_untrusted(struct pci_dev *dev)
> {
> struct pci_dev *parent = pci_upstream_bridge(dev);
> @@ -2006,6 +2014,8 @@ int pci_setup_device(struct pci_dev *dev)
> /* Need to have dev->cfg_size ready */
> set_pcie_thunderbolt(dev);
>
> + set_pcie_cxl(dev);
> +
> set_pcie_untrusted(dev);
>
> if (pci_is_pcie(dev))
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 1d62e785ae1f..82a0401c58d3 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -452,6 +452,7 @@ struct pci_dev {
> unsigned int is_hotplug_bridge:1;
> unsigned int shpc_managed:1; /* SHPC owned by shpchp */
> unsigned int is_thunderbolt:1; /* Thunderbolt controller */
> + unsigned int is_cxl:1; /* Compute Express Link (CXL) */
> /*
> * Devices marked being untrusted are the ones that can potentially
> * execute DMA attacks and similar. They are typically connected
> @@ -741,6 +742,10 @@ static inline bool pci_is_vga(struct pci_dev *pdev)
> return false;
> }
>
> +bool pcie_is_cxl(struct pci_dev *pci_dev);
> +
> +bool pcie_is_cxl_port(struct pci_dev *dev);
> +
> #define for_each_pci_bridge(dev, bus) \
> list_for_each_entry(dev, &bus->devices, bus_list) \
> if (!pci_is_bridge(dev)) {} else
> diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
> index 3445c4970e4d..dbc0f23d8c82 100644
> --- a/include/uapi/linux/pci_regs.h
> +++ b/include/uapi/linux/pci_regs.h
> @@ -1208,9 +1208,10 @@
> #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL 0x00ff0000
> #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX 0xff000000
>
> -/* Compute Express Link (CXL r3.1, sec 8.1.5) */
> +/* Compute Express Link (CXL r3.1, sec 8.1) */
> #define PCI_DVSEC_CXL_PORT 3
> #define PCI_DVSEC_CXL_PORT_CTL 0x0c
> #define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR 0x00000001
> +#define PCI_DVSEC_CXL_FLEXBUS 7
>
> #endif /* LINUX_PCI_REGS_H */
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type
2025-02-11 19:24 ` [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type Terry Bowman
@ 2025-02-11 20:28 ` Bjorn Helgaas
2025-02-11 23:47 ` Dan Williams
1 sibling, 0 replies; 94+ messages in thread
From: Bjorn Helgaas @ 2025-02-11 20:28 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:31PM -0600, Terry Bowman wrote:
> The AER driver and aer_event tracing currently log 'PCIe Bus Type'
> for all errors.
>
> Update the driver and aer_event tracing to log 'CXL Bus Type' for CXL
> device errors.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
> drivers/pci/pcie/aer.c | 14 ++++++++------
> include/ras/ras_event.h | 9 ++++++---
> 2 files changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index 6e8de77d0fc4..f99a1c6fb274 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -694,13 +694,14 @@ static void __aer_print_error(struct pci_dev *dev,
>
> void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
> {
> + const char *bus_type = pcie_is_cxl(dev) ? "CXL" : "PCIe";
> int layer, agent;
> int id = pci_dev_id(dev);
> const char *level;
>
> if (!info->status) {
> - pci_err(dev, "PCIe Bus Error: severity=%s, type=Inaccessible, (Unregistered Agent ID)\n",
> - aer_error_severity_string[info->severity]);
> + pci_err(dev, "%s Bus Error: severity=%s, type=Inaccessible, (Unregistered Agent ID)\n",
> + bus_type, aer_error_severity_string[info->severity]);
> goto out;
> }
>
> @@ -709,8 +710,8 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
>
> level = (info->severity == AER_CORRECTABLE) ? KERN_WARNING : KERN_ERR;
>
> - pci_printk(level, dev, "PCIe Bus Error: severity=%s, type=%s, (%s)\n",
> - aer_error_severity_string[info->severity],
> + pci_printk(level, dev, "%s Bus Error: severity=%s, type=%s, (%s)\n",
> + bus_type, aer_error_severity_string[info->severity],
> aer_error_layer[layer], aer_agent_string[agent]);
>
> pci_printk(level, dev, " device [%04x:%04x] error status/mask=%08x/%08x\n",
> @@ -725,7 +726,7 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
> if (info->id && info->error_dev_num > 1 && info->id == id)
> pci_err(dev, " Error of this Agent is reported first\n");
>
> - trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
> + trace_aer_event(dev_name(&dev->dev), bus_type, (info->status & ~info->mask),
> info->severity, info->tlp_header_valid, &info->tlp);
> }
>
> @@ -759,6 +760,7 @@ EXPORT_SYMBOL_GPL(cper_severity_to_aer);
> void pci_print_aer(struct pci_dev *dev, int aer_severity,
> struct aer_capability_regs *aer)
> {
> + const char *bus_type = pcie_is_cxl(dev) ? "CXL" : "PCIe";
> int layer, agent, tlp_header_valid = 0;
> u32 status, mask;
> struct aer_err_info info;
> @@ -793,7 +795,7 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
> if (tlp_header_valid)
> pcie_print_tlp_log(dev, &aer->header_log, dev_fmt(" "));
>
> - trace_aer_event(dev_name(&dev->dev), (status & ~mask),
> + trace_aer_event(dev_name(&dev->dev), bus_type, (status & ~mask),
> aer_severity, tlp_header_valid, &aer->header_log);
> }
> EXPORT_SYMBOL_NS_GPL(pci_print_aer, "CXL");
> diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
> index e5f7ee0864e7..1bf8e7050ba8 100644
> --- a/include/ras/ras_event.h
> +++ b/include/ras/ras_event.h
> @@ -297,15 +297,17 @@ TRACE_EVENT(non_standard_event,
>
> TRACE_EVENT(aer_event,
> TP_PROTO(const char *dev_name,
> + const char *bus_type,
> const u32 status,
> const u8 severity,
> const u8 tlp_header_valid,
> struct pcie_tlp_log *tlp),
>
> - TP_ARGS(dev_name, status, severity, tlp_header_valid, tlp),
> + TP_ARGS(dev_name, bus_type, status, severity, tlp_header_valid, tlp),
>
> TP_STRUCT__entry(
> __string( dev_name, dev_name )
> + __string( bus_type, bus_type )
> __field( u32, status )
> __field( u8, severity )
> __field( u8, tlp_header_valid)
> @@ -314,6 +316,7 @@ TRACE_EVENT(aer_event,
>
> TP_fast_assign(
> __assign_str(dev_name);
> + __assign_str(bus_type);
> __entry->status = status;
> __entry->severity = severity;
> __entry->tlp_header_valid = tlp_header_valid;
> @@ -325,8 +328,8 @@ TRACE_EVENT(aer_event,
> }
> ),
>
> - TP_printk("%s PCIe Bus Error: severity=%s, %s, TLP Header=%s\n",
> - __get_str(dev_name),
> + TP_printk("%s %s Bus Error: severity=%s, %s, TLP Header=%s\n",
> + __get_str(dev_name), __get_str(bus_type),
> __entry->severity == AER_CORRECTABLE ? "Corrected" :
> __entry->severity == AER_FATAL ?
> "Fatal" : "Uncorrected, non-fatal",
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 05/17] PCI/AER: Add CXL PCIe Port correctable error support in AER service driver
2025-02-11 19:24 ` [PATCH v7 05/17] PCI/AER: Add CXL PCIe Port correctable error support in AER service driver Terry Bowman
@ 2025-02-11 20:28 ` Bjorn Helgaas
2025-02-11 23:58 ` Dan Williams
1 sibling, 0 replies; 94+ messages in thread
From: Bjorn Helgaas @ 2025-02-11 20:28 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:32PM -0600, Terry Bowman wrote:
> The AER service driver supports handling Downstream Port Protocol Errors in
> Restricted CXL host (RCH) mode also known as CXL1.1. It needs the same
> functionality for CXL PCIe Ports operating in Virtual Hierarchy (VH)
> mode.[1]
>
> CXL and PCIe Protocol Error handling have different requirements that
> necessitate a separate handling path. The AER service driver may try to
> recover PCIe uncorrectable non-fatal errors (UCE). The same recovery is not
> suitable for CXL PCIe Port devices because of potential for system memory
> corruption. Instead, CXL Protocol Error handling must use a kernel panic
> in the case of a fatal or non-fatal UCE. The AER driver's PCIe Protocol
> Error handling does not panic the kernel in response to a UCE.
>
> Introduce a separate path for CXL Protocol Error handling in the AER
> service driver. This will allow CXL Protocol Errors to use CXL specific
> handling instead of PCIe handling. Add the CXL specific changes without
> affecting or adding functionality in the PCIe handling.
>
> Make this update alongside the existing Downstream Port RCH error handling
> logic, extending support to CXL PCIe Ports in VH mode.
>
> Remove is_internal_error(). is_internal_error() was used to determine if
> an AER error was a CXL error. Instead, now rely on pcie_is_cxl_port() to
> indicate the error is a CXL error.
>
> The uncorrectable error (UCE) handling will be added in a future patch.
>
> [1] CXL 3.1 Spec, 12.2.2 CXL Root Ports, Downstream Switch Ports, and
> Upstream Switch Ports
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
> drivers/pci/pcie/aer.c | 47 ++++++++++++++++++++++++++++--------------
> 1 file changed, 32 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index f99a1c6fb274..34ec0958afff 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -989,14 +989,6 @@ static bool cxl_error_is_native(struct pci_dev *dev)
> return (pcie_ports_native || host->native_aer);
> }
>
> -static bool is_internal_error(struct aer_err_info *info)
> -{
> - if (info->severity == AER_CORRECTABLE)
> - return info->status & PCI_ERR_COR_INTERNAL;
> -
> - return info->status & PCI_ERR_UNC_INTN;
> -}
> -
> static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
> {
> struct aer_err_info *info = (struct aer_err_info *)data;
> @@ -1033,9 +1025,23 @@ static void cxl_handle_error(struct pci_dev *dev, struct aer_err_info *info)
> * RCH's downstream port. Check and handle them in the CXL.mem
> * device driver.
> */
> - if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC &&
> - is_internal_error(info))
> - pcie_walk_rcec(dev, cxl_rch_handle_error_iter, info);
> + if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC)
> + return pcie_walk_rcec(dev, cxl_rch_handle_error_iter, info);
> +
> + if (info->severity == AER_CORRECTABLE) {
> + struct pci_driver *pdrv = dev->driver;
> + int aer = dev->aer_cap;
> +
> + if (aer)
> + pci_write_config_dword(dev, aer + PCI_ERR_COR_STATUS,
> + info->status);
> +
> + if (pdrv && pdrv->cxl_err_handler &&
> + pdrv->cxl_err_handler->cor_error_detected)
> + pdrv->cxl_err_handler->cor_error_detected(dev);
> +
> + pcie_clear_device_status(dev);
> + }
> }
>
> static int handles_cxl_error_iter(struct pci_dev *dev, void *data)
> @@ -1053,9 +1059,13 @@ static bool handles_cxl_errors(struct pci_dev *dev)
> {
> bool handles_cxl = false;
>
> - if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC &&
> - pcie_aer_is_native(dev))
> + if (!pcie_aer_is_native(dev))
> + return false;
> +
> + if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC)
> pcie_walk_rcec(dev, handles_cxl_error_iter, &handles_cxl);
> + else
> + handles_cxl = pcie_is_cxl_port(dev);
>
> return handles_cxl;
> }
> @@ -1073,6 +1083,10 @@ static void cxl_enable_internal_errors(struct pci_dev *dev)
> static inline void cxl_enable_internal_errors(struct pci_dev *dev) { }
> static inline void cxl_handle_error(struct pci_dev *dev,
> struct aer_err_info *info) { }
> +static bool handles_cxl_errors(struct pci_dev *dev)
> +{
> + return false;
> +}
> #endif
>
> /**
> @@ -1110,8 +1124,11 @@ static void pci_aer_handle_error(struct pci_dev *dev, struct aer_err_info *info)
>
> static void handle_error_source(struct pci_dev *dev, struct aer_err_info *info)
> {
> - cxl_handle_error(dev, info);
> - pci_aer_handle_error(dev, info);
> + if (handles_cxl_errors(dev))
> + cxl_handle_error(dev, info);
> + else
> + pci_aer_handle_error(dev, info);
> +
> pci_dev_put(dev);
> }
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery in AER service driver
2025-02-11 19:24 ` [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery " Terry Bowman
@ 2025-02-11 20:29 ` Bjorn Helgaas
2025-02-11 21:59 ` Dave Jiang
` (4 subsequent siblings)
5 siblings, 0 replies; 94+ messages in thread
From: Bjorn Helgaas @ 2025-02-11 20:29 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:33PM -0600, Terry Bowman wrote:
> Existing recovery procedure for PCIe uncorrectable errors (UCE) does not
> apply to CXL devices. Recovery can not be used for CXL devices because of
> potential corruption on what can be system memory. Also, current PCIe UCE
> recovery, in the case of a Root Port (RP) or Downstream Switch Port (DSP),
> does not begin at the RP/DSP but begins at the first downstream device.
> This will miss handling CXL Protocol Errors in a CXL RP or DSP. A separate
> CXL recovery is needed because of the different handling requirements
>
> Add a new function, cxl_do_recovery() using the following.
>
> Add cxl_walk_bridge() to iterate the detected error's sub-topology.
> cxl_walk_bridge() is similar to pci_walk_bridge() but the CXL flavor
> will begin iteration at the RP or DSP rather than beginning at the
> first downstream device.
>
> pci_walk_bridge() is candidate to possibly reuse cxl_walk_bridge() but
> needs further investigation. This will be left for future improvement
> to make the CXL and PCI handling paths more common.
>
> Add cxl_report_error_detected() as an analog to report_error_detected().
> It will call pci_driver::cxl_err_handlers for each iterated downstream
> device. The pci_driver::cxl_err_handler's UCE handler returns a boolean
> indicating if there was a UCE error detected during handling.
>
> cxl_do_recovery() uses the status from cxl_report_error_detected() to
> determine how to proceed. Non-fatal CXL UCE errors will be treated as
> fatal. If a UCE was present during handling then cxl_do_recovery()
> will kernel panic.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
> drivers/pci/pci.h | 3 +++
> drivers/pci/pcie/aer.c | 4 +++
> drivers/pci/pcie/err.c | 58 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/pci.h | 3 +++
> 4 files changed, 68 insertions(+)
>
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 01e51db8d285..deb193b387af 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -722,6 +722,9 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
> pci_channel_state_t state,
> pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev));
>
> +/* CXL error reporting and handling */
> +void cxl_do_recovery(struct pci_dev *dev);
> +
> bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
> int pcie_retrain_link(struct pci_dev *pdev, bool use_lt);
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index 34ec0958afff..ee38db08d005 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -1012,6 +1012,8 @@ static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
> err_handler->error_detected(dev, pci_channel_io_normal);
> else if (info->severity == AER_FATAL)
> err_handler->error_detected(dev, pci_channel_io_frozen);
> +
> + cxl_do_recovery(dev);
> }
> out:
> device_unlock(&dev->dev);
> @@ -1041,6 +1043,8 @@ static void cxl_handle_error(struct pci_dev *dev, struct aer_err_info *info)
> pdrv->cxl_err_handler->cor_error_detected(dev);
>
> pcie_clear_device_status(dev);
> + } else {
> + cxl_do_recovery(dev);
> }
> }
>
> diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
> index 31090770fffc..05f2d1ef4c36 100644
> --- a/drivers/pci/pcie/err.c
> +++ b/drivers/pci/pcie/err.c
> @@ -24,6 +24,9 @@
> static pci_ers_result_t merge_result(enum pci_ers_result orig,
> enum pci_ers_result new)
> {
> + if (new == PCI_ERS_RESULT_PANIC)
> + return PCI_ERS_RESULT_PANIC;
> +
> if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
> return PCI_ERS_RESULT_NO_AER_DRIVER;
>
> @@ -276,3 +279,58 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
>
> return status;
> }
> +
> +static void cxl_walk_bridge(struct pci_dev *bridge,
> + int (*cb)(struct pci_dev *, void *),
> + void *userdata)
> +{
> + if (cb(bridge, userdata))
> + return;
> +
> + if (bridge->subordinate)
> + pci_walk_bus(bridge->subordinate, cb, userdata);
> +}
> +
> +static int cxl_report_error_detected(struct pci_dev *dev, void *data)
> +{
> + const struct cxl_error_handlers *cxl_err_handler;
> + pci_ers_result_t vote, *result = data;
> + struct pci_driver *pdrv;
> +
> + device_lock(&dev->dev);
> + pdrv = dev->driver;
> + if (!pdrv || !pdrv->cxl_err_handler ||
> + !pdrv->cxl_err_handler->error_detected)
> + goto out;
> +
> + cxl_err_handler = pdrv->cxl_err_handler;
> + vote = cxl_err_handler->error_detected(dev);
> + *result = merge_result(*result, vote);
> +out:
> + device_unlock(&dev->dev);
> + return 0;
> +}
> +
> +void cxl_do_recovery(struct pci_dev *dev)
> +{
> + struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
> + pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
> +
> + cxl_walk_bridge(dev, cxl_report_error_detected, &status);
> + if (status == PCI_ERS_RESULT_PANIC)
> + panic("CXL cachemem error.");
> +
> + /*
> + * If we have native control of AER, clear error status in the device
> + * that detected the error. If the platform retained control of AER,
> + * it is responsible for clearing this status. In that case, the
> + * signaling device may not even be visible to the OS.
> + */
> + if (host->native_aer || pcie_ports_native) {
> + pcie_clear_device_status(dev);
> + pci_aer_clear_nonfatal_status(dev);
> + pci_aer_clear_fatal_status(dev);
> + }
> +
> + pci_info(dev, "CXL uncorrectable error.\n");
> +}
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 82a0401c58d3..5b539b5bf0d1 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -864,6 +864,9 @@ enum pci_ers_result {
>
> /* No AER capabilities registered for the driver */
> PCI_ERS_RESULT_NO_AER_DRIVER = (__force pci_ers_result_t) 6,
> +
> + /* System is unstable, panic */
> + PCI_ERS_RESULT_PANIC = (__force pci_ers_result_t) 7,
> };
>
> /* PCI bus error event callbacks */
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port()
2025-02-11 20:28 ` Bjorn Helgaas
@ 2025-02-11 20:38 ` Bowman, Terry
0 siblings, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-02-11 20:38 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/2025 2:28 PM, Bjorn Helgaas wrote:
> On Tue, Feb 11, 2025 at 01:24:30PM -0600, Terry Bowman wrote:
>> CXL and AER drivers need the ability to identify CXL devices and CXL port
>> devices.
>>
>> First, add set_pcie_cxl() with logic checking for CXL Flexbus DVSEC
>> presence. The CXL Flexbus DVSEC presence is used because it is required
>> for all the CXL PCIe devices.[1]
>>
>> Add boolean 'struct pci_dev::is_cxl' with the purpose to cache the CXL
>> Flexbus presence.
>>
>> Add pcie_is_cxl() as a macro to return 'struct pci_dev::is_cxl'.
>>
>> Add pcie_is_cxl_port() to check if a device is a CXL Root Port, CXL
>> Upstream Switch Port, or CXL Downstream Switch Port. Also, verify the
>> CXL Extensions DVSEC for Ports is present.[1]
>>
>> [1] CXL 3.1 Spec, 8.1.1 PCIe Designated Vendor-Specific Extended
>> Capability (DVSEC) ID Assignment, Table 8-2
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
>> Reviewed-by: Fan Ni <fan.ni@samsung.com>
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
>
> But I would change the subject to:
>
> PCI/CXL: ...
>
> since this only changes drivers/pci files.
I'll change to PCI/CXL. Thanks for the review and 'acks'.
Terry
>> ---
>> drivers/pci/pci.c | 13 +++++++++++++
>> drivers/pci/probe.c | 10 ++++++++++
>> include/linux/pci.h | 5 +++++
>> include/uapi/linux/pci_regs.h | 3 ++-
>> 4 files changed, 30 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>> index 869d204a70a3..a2d8b41dd043 100644
>> --- a/drivers/pci/pci.c
>> +++ b/drivers/pci/pci.c
>> @@ -5032,6 +5032,19 @@ static u16 cxl_port_dvsec(struct pci_dev *dev)
>> PCI_DVSEC_CXL_PORT);
>> }
>>
>> +inline bool pcie_is_cxl(struct pci_dev *pci_dev)
>> +{
>> + return pci_dev->is_cxl;
>> +}
>> +
>> +bool pcie_is_cxl_port(struct pci_dev *dev)
>> +{
>> + if (!pcie_is_cxl(dev))
>> + return false;
>> +
>> + return (cxl_port_dvsec(dev) > 0);
>> +}
>> +
>> static bool cxl_sbr_masked(struct pci_dev *dev)
>> {
>> u16 dvsec, reg;
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index b6536ed599c3..7737b9ce7a83 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -1676,6 +1676,14 @@ static void set_pcie_thunderbolt(struct pci_dev *dev)
>> dev->is_thunderbolt = 1;
>> }
>>
>> +static void set_pcie_cxl(struct pci_dev *dev)
>> +{
>> + u16 dvsec = pci_find_dvsec_capability(dev, PCI_VENDOR_ID_CXL,
>> + PCI_DVSEC_CXL_FLEXBUS);
>> + if (dvsec)
>> + dev->is_cxl = 1;
>> +}
>> +
>> static void set_pcie_untrusted(struct pci_dev *dev)
>> {
>> struct pci_dev *parent = pci_upstream_bridge(dev);
>> @@ -2006,6 +2014,8 @@ int pci_setup_device(struct pci_dev *dev)
>> /* Need to have dev->cfg_size ready */
>> set_pcie_thunderbolt(dev);
>>
>> + set_pcie_cxl(dev);
>> +
>> set_pcie_untrusted(dev);
>>
>> if (pci_is_pcie(dev))
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index 1d62e785ae1f..82a0401c58d3 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -452,6 +452,7 @@ struct pci_dev {
>> unsigned int is_hotplug_bridge:1;
>> unsigned int shpc_managed:1; /* SHPC owned by shpchp */
>> unsigned int is_thunderbolt:1; /* Thunderbolt controller */
>> + unsigned int is_cxl:1; /* Compute Express Link (CXL) */
>> /*
>> * Devices marked being untrusted are the ones that can potentially
>> * execute DMA attacks and similar. They are typically connected
>> @@ -741,6 +742,10 @@ static inline bool pci_is_vga(struct pci_dev *pdev)
>> return false;
>> }
>>
>> +bool pcie_is_cxl(struct pci_dev *pci_dev);
>> +
>> +bool pcie_is_cxl_port(struct pci_dev *dev);
>> +
>> #define for_each_pci_bridge(dev, bus) \
>> list_for_each_entry(dev, &bus->devices, bus_list) \
>> if (!pci_is_bridge(dev)) {} else
>> diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
>> index 3445c4970e4d..dbc0f23d8c82 100644
>> --- a/include/uapi/linux/pci_regs.h
>> +++ b/include/uapi/linux/pci_regs.h
>> @@ -1208,9 +1208,10 @@
>> #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL 0x00ff0000
>> #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX 0xff000000
>>
>> -/* Compute Express Link (CXL r3.1, sec 8.1.5) */
>> +/* Compute Express Link (CXL r3.1, sec 8.1) */
>> #define PCI_DVSEC_CXL_PORT 3
>> #define PCI_DVSEC_CXL_PORT_CTL 0x0c
>> #define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR 0x00000001
>> +#define PCI_DVSEC_CXL_FLEXBUS 7
>>
>> #endif /* LINUX_PCI_REGS_H */
>> --
>> 2.34.1
>>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 16/17] PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch Ports
2025-02-11 20:25 ` Bjorn Helgaas
@ 2025-02-11 20:40 ` Bowman, Terry
0 siblings, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-02-11 20:40 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/2025 2:25 PM, Bjorn Helgaas wrote:
> On Tue, Feb 11, 2025 at 01:24:43PM -0600, Terry Bowman wrote:
>> The AER service driver enables PCIe Uncorrectable Internal Errors (UIE) and
>> Correctable Internal errors (CIE) for CXL Root Ports. The UIE and CIE are
>> used in reporting CXL Protocol Errors. The same UIE/CIE enablement is
>> needed for CXL Upstream Switch Ports and CXL Downstream Switch Ports
>> inorder to notify the associated Root Port and OS.[1]
>>
>> Export the AER service driver's pci_aer_unmask_internal_errors() function
>> to CXL namespace.
>>
>> Remove the function's dependency on the CONFIG_PCIEAER_CXL kernel config
>> because it is now an exported function.
>>
>> Call pci_aer_unmask_internal_errors() during RAS initialization in:
>> cxl_uport_init_ras_reporting() and cxl_dport_init_ras_reporting().
>>
>> [1] PCIe Base Spec r6.2-1.0, 6.2.3.2.2 Masking Individual Errors
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
>
> I'd say this is really a CXL-centric change, given that
> pci_aer_unmask_internal_errors() is only used for CXL and it's
> exported in the CXL namespace. So I would use
>
> cxl/pci: ...
>
> in the subject.
Yes, I'll change to cxl/pci. Thanks for reviewing.
Terry
>> ---
>> drivers/cxl/core/pci.c | 2 ++
>> drivers/pci/pcie/aer.c | 3 ++-
>> include/linux/aer.h | 1 +
>> 3 files changed, 5 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>> index 03ae21a944e0..36e686a31045 100644
>> --- a/drivers/cxl/core/pci.c
>> +++ b/drivers/cxl/core/pci.c
>> @@ -912,6 +912,7 @@ void cxl_uport_init_ras_reporting(struct cxl_port *port)
>>
>> cxl_assign_port_error_handlers(pdev);
>> devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
>> + pci_aer_unmask_internal_errors(pdev);
>> }
>> EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
>>
>> @@ -959,6 +960,7 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
>> cxl_assign_port_error_handlers(pdev);
>> devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
>> put_device(&port->dev);
>> + pci_aer_unmask_internal_errors(pdev);
>> }
>> EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
>>
>> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
>> index ee38db08d005..8e3a60411610 100644
>> --- a/drivers/pci/pcie/aer.c
>> +++ b/drivers/pci/pcie/aer.c
>> @@ -948,7 +948,7 @@ static bool find_source_device(struct pci_dev *parent,
>> * Note: AER must be enabled and supported by the device which must be
>> * checked in advance, e.g. with pcie_aer_is_native().
>> */
>> -static void pci_aer_unmask_internal_errors(struct pci_dev *dev)
>> +void pci_aer_unmask_internal_errors(struct pci_dev *dev)
>> {
>> int aer = dev->aer_cap;
>> u32 mask;
>> @@ -961,6 +961,7 @@ static void pci_aer_unmask_internal_errors(struct pci_dev *dev)
>> mask &= ~PCI_ERR_COR_INTERNAL;
>> pci_write_config_dword(dev, aer + PCI_ERR_COR_MASK, mask);
>> }
>> +EXPORT_SYMBOL_NS_GPL(pci_aer_unmask_internal_errors, "CXL");
>>
>> static bool is_cxl_mem_dev(struct pci_dev *dev)
>> {
>> diff --git a/include/linux/aer.h b/include/linux/aer.h
>> index 947b63091902..a54545796edc 100644
>> --- a/include/linux/aer.h
>> +++ b/include/linux/aer.h
>> @@ -61,5 +61,6 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
>> int cper_severity_to_aer(int cper_severity);
>> void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
>> int severity, struct aer_capability_regs *aer_regs);
>> +void pci_aer_unmask_internal_errors(struct pci_dev *dev);
>> #endif //_AER_H_
>>
>> --
>> 2.34.1
>>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 01/17] PCI/AER: Introduce 'struct cxl_err_handlers' and add to 'struct pci_driver'
2025-02-11 19:24 ` [PATCH v7 01/17] PCI/AER: Introduce 'struct cxl_err_handlers' and add to 'struct pci_driver' Terry Bowman
2025-02-11 20:25 ` Bjorn Helgaas
@ 2025-02-11 20:42 ` Dan Williams
1 sibling, 0 replies; 94+ messages in thread
From: Dan Williams @ 2025-02-11 20:42 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> CXL.io is implemented on top of PCIe Protocol Errors. But, CXL.io and PCIe
> have different handling requirements for uncorrectable errors (UCE).
>
> The PCIe AER service driver may attempt recovering PCIe devices with
> UCE while recovery is not used for CXL.io. Recovery is not used in the
> CXL.io case because of potential corruption on what can be system memory.
>
> Create pci_driver::cxl_err_handlers structure similar to
> pci_driver::error_handler. Create handlers for correctable and
> uncorrectable CXL.io error handling.
>
> The CXL error handlers will be used in future patches adding CXL PCIe
> Port Protocol Error handling.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Looks good to me.
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 02/17] PCI/AER: Rename AER driver's interfaces to also indicate CXL PCIe Port support
2025-02-11 19:24 ` [PATCH v7 02/17] PCI/AER: Rename AER driver's interfaces to also indicate CXL PCIe Port support Terry Bowman
2025-02-11 20:26 ` Bjorn Helgaas
@ 2025-02-11 20:44 ` Dan Williams
1 sibling, 0 replies; 94+ messages in thread
From: Dan Williams @ 2025-02-11 20:44 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> The AER service driver already includes support for Restricted CXL host
> (RCH) Downstream Port Protocol Error handling. The current implementation
> is based on CXL1.1 using a Root Complex Event Collector.
>
> Rename function interfaces and parameters where necessary to include
> virtual hierarchy (VH) mode CXL PCIe Port error handling alongside the RCH
> handling.[1] The CXL PCIe Port Protocol Error handling support will be
> added in a future patch.
>
> Limit changes to renaming variable and function names. No functional
> changes are added.
>
> [1] CXL 3.1 Spec, 9.12.2 CXL Virtual Hierarchy
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Looks good:
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery in AER service driver
2025-02-11 19:24 ` [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery " Terry Bowman
2025-02-11 20:29 ` Bjorn Helgaas
@ 2025-02-11 21:59 ` Dave Jiang
2025-02-12 0:02 ` Gregory Price
` (3 subsequent siblings)
5 siblings, 0 replies; 94+ messages in thread
From: Dave Jiang @ 2025-02-11 21:59 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 12:24 PM, Terry Bowman wrote:
> Existing recovery procedure for PCIe uncorrectable errors (UCE) does not
> apply to CXL devices. Recovery can not be used for CXL devices because of
> potential corruption on what can be system memory. Also, current PCIe UCE
> recovery, in the case of a Root Port (RP) or Downstream Switch Port (DSP),
> does not begin at the RP/DSP but begins at the first downstream device.
> This will miss handling CXL Protocol Errors in a CXL RP or DSP. A separate
> CXL recovery is needed because of the different handling requirements
>
> Add a new function, cxl_do_recovery() using the following.
>
> Add cxl_walk_bridge() to iterate the detected error's sub-topology.
> cxl_walk_bridge() is similar to pci_walk_bridge() but the CXL flavor
> will begin iteration at the RP or DSP rather than beginning at the
> first downstream device.
>
> pci_walk_bridge() is candidate to possibly reuse cxl_walk_bridge() but
> needs further investigation. This will be left for future improvement
> to make the CXL and PCI handling paths more common.
>
> Add cxl_report_error_detected() as an analog to report_error_detected().
> It will call pci_driver::cxl_err_handlers for each iterated downstream
> device. The pci_driver::cxl_err_handler's UCE handler returns a boolean
> indicating if there was a UCE error detected during handling.
>
> cxl_do_recovery() uses the status from cxl_report_error_detected() to
> determine how to proceed. Non-fatal CXL UCE errors will be treated as
> fatal. If a UCE was present during handling then cxl_do_recovery()
> will kernel panic.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/pci/pci.h | 3 +++
> drivers/pci/pcie/aer.c | 4 +++
> drivers/pci/pcie/err.c | 58 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/pci.h | 3 +++
> 4 files changed, 68 insertions(+)
>
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 01e51db8d285..deb193b387af 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -722,6 +722,9 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
> pci_channel_state_t state,
> pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev));
>
> +/* CXL error reporting and handling */
> +void cxl_do_recovery(struct pci_dev *dev);
> +
> bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
> int pcie_retrain_link(struct pci_dev *pdev, bool use_lt);
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index 34ec0958afff..ee38db08d005 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -1012,6 +1012,8 @@ static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
> err_handler->error_detected(dev, pci_channel_io_normal);
> else if (info->severity == AER_FATAL)
> err_handler->error_detected(dev, pci_channel_io_frozen);
> +
> + cxl_do_recovery(dev);
> }
> out:
> device_unlock(&dev->dev);
> @@ -1041,6 +1043,8 @@ static void cxl_handle_error(struct pci_dev *dev, struct aer_err_info *info)
> pdrv->cxl_err_handler->cor_error_detected(dev);
>
> pcie_clear_device_status(dev);
> + } else {
> + cxl_do_recovery(dev);
> }
> }
>
> diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
> index 31090770fffc..05f2d1ef4c36 100644
> --- a/drivers/pci/pcie/err.c
> +++ b/drivers/pci/pcie/err.c
> @@ -24,6 +24,9 @@
> static pci_ers_result_t merge_result(enum pci_ers_result orig,
> enum pci_ers_result new)
> {
> + if (new == PCI_ERS_RESULT_PANIC)
> + return PCI_ERS_RESULT_PANIC;
> +
> if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
> return PCI_ERS_RESULT_NO_AER_DRIVER;
>
> @@ -276,3 +279,58 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
>
> return status;
> }
> +
> +static void cxl_walk_bridge(struct pci_dev *bridge,
> + int (*cb)(struct pci_dev *, void *),
> + void *userdata)
> +{
> + if (cb(bridge, userdata))
> + return;
> +
> + if (bridge->subordinate)
> + pci_walk_bus(bridge->subordinate, cb, userdata);
> +}
> +
> +static int cxl_report_error_detected(struct pci_dev *dev, void *data)
> +{
> + const struct cxl_error_handlers *cxl_err_handler;
> + pci_ers_result_t vote, *result = data;
> + struct pci_driver *pdrv;
> +
> + device_lock(&dev->dev);
> + pdrv = dev->driver;
> + if (!pdrv || !pdrv->cxl_err_handler ||
> + !pdrv->cxl_err_handler->error_detected)
> + goto out;
> +
> + cxl_err_handler = pdrv->cxl_err_handler;
> + vote = cxl_err_handler->error_detected(dev);
> + *result = merge_result(*result, vote);
> +out:
> + device_unlock(&dev->dev);
> + return 0;
> +}
> +
> +void cxl_do_recovery(struct pci_dev *dev)
> +{
> + struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
> + pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
> +
> + cxl_walk_bridge(dev, cxl_report_error_detected, &status);
> + if (status == PCI_ERS_RESULT_PANIC)
> + panic("CXL cachemem error.");
> +
> + /*
> + * If we have native control of AER, clear error status in the device
> + * that detected the error. If the platform retained control of AER,
> + * it is responsible for clearing this status. In that case, the
> + * signaling device may not even be visible to the OS.
> + */
> + if (host->native_aer || pcie_ports_native) {
> + pcie_clear_device_status(dev);
> + pci_aer_clear_nonfatal_status(dev);
> + pci_aer_clear_fatal_status(dev);
> + }
> +
> + pci_info(dev, "CXL uncorrectable error.\n");
> +}
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 82a0401c58d3..5b539b5bf0d1 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -864,6 +864,9 @@ enum pci_ers_result {
>
> /* No AER capabilities registered for the driver */
> PCI_ERS_RESULT_NO_AER_DRIVER = (__force pci_ers_result_t) 6,
> +
> + /* System is unstable, panic */
> + PCI_ERS_RESULT_PANIC = (__force pci_ers_result_t) 7,
> };
>
> /* PCI bus error event callbacks */
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port()
2025-02-11 19:24 ` [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port() Terry Bowman
2025-02-11 20:28 ` Bjorn Helgaas
@ 2025-02-11 22:33 ` Dan Williams
2025-02-12 19:07 ` Bowman, Terry
2025-03-04 19:11 ` Ira Weiny
2 siblings, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-11 22:33 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> CXL and AER drivers need the ability to identify CXL devices and CXL port
> devices.
>
> First, add set_pcie_cxl() with logic checking for CXL Flexbus DVSEC
> presence. The CXL Flexbus DVSEC presence is used because it is required
> for all the CXL PCIe devices.[1]
>
> Add boolean 'struct pci_dev::is_cxl' with the purpose to cache the CXL
> Flexbus presence.
>
> Add pcie_is_cxl() as a macro to return 'struct pci_dev::is_cxl'.
>
> Add pcie_is_cxl_port() to check if a device is a CXL Root Port, CXL
> Upstream Switch Port, or CXL Downstream Switch Port. Also, verify the
> CXL Extensions DVSEC for Ports is present.[1]
>
> [1] CXL 3.1 Spec, 8.1.1 PCIe Designated Vendor-Specific Extended
> Capability (DVSEC) ID Assignment, Table 8-2
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
> ---
> drivers/pci/pci.c | 13 +++++++++++++
> drivers/pci/probe.c | 10 ++++++++++
> include/linux/pci.h | 5 +++++
> include/uapi/linux/pci_regs.h | 3 ++-
> 4 files changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 869d204a70a3..a2d8b41dd043 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -5032,6 +5032,19 @@ static u16 cxl_port_dvsec(struct pci_dev *dev)
> PCI_DVSEC_CXL_PORT);
> }
>
> +inline bool pcie_is_cxl(struct pci_dev *pci_dev)
> +{
> + return pci_dev->is_cxl;
> +}
> +
> +bool pcie_is_cxl_port(struct pci_dev *dev)
> +{
> + if (!pcie_is_cxl(dev))
> + return false;
> +
> + return (cxl_port_dvsec(dev) > 0);
At first I was concerned that this adds a capability list walk during
error handling, but patch 17 takes pcie_is_cxl_port() out of the
handles_cxl_errors() path.
It is still used in the aer_probe() path which means enumeration can
potentially race a CXL link up event.
I think this is fine for now because the CXL core has the same top-down
vs bottom-up race, and the CXL SBR code also shares the same race
problem.
A follow-on change needs to arrange for cxl_port_probe() to
enable/disable internal errors, because that path knows that a link has
been negotiated with an endpoint and that the CXL link details should be
stable.
> +}
> +
> static bool cxl_sbr_masked(struct pci_dev *dev)
> {
> u16 dvsec, reg;
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index b6536ed599c3..7737b9ce7a83 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -1676,6 +1676,14 @@ static void set_pcie_thunderbolt(struct pci_dev *dev)
> dev->is_thunderbolt = 1;
> }
>
> +static void set_pcie_cxl(struct pci_dev *dev)
> +{
> + u16 dvsec = pci_find_dvsec_capability(dev, PCI_VENDOR_ID_CXL,
> + PCI_DVSEC_CXL_FLEXBUS);
> + if (dvsec)
> + dev->is_cxl = 1;
> +}
Similar race problem here as it is premature to check for this DVSEC on
disconnected ports.
For now, lets add a comment to include/uapi/linux/pci_regs.h along the
lines of:
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 3445c4970e4d..32df7abdd23c 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -1208,7 +1208,13 @@
#define PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL 0x00ff0000
#define PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX 0xff000000
-/* Compute Express Link (CXL r3.1, sec 8.1.5) */
+/*
+ * Compute Express Link (CXL r3.1, sec 8.1)
+ *
+ * Note that CXL DVSEC id 3 and 7 to be ignored when the CXL link state
+ * is "disconnected" (CXL r3.1, sec 9.12.3). Re-enumerate these
+ * registers on downstream link-up events.
+ */
#define PCI_DVSEC_CXL_PORT 3
#define PCI_DVSEC_CXL_PORT_CTL 0x0c
#define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR 0x00000001
...to at least remind our future selves that there is work to do here to
make the implementation robust against hot-plug scenarios.
With that you can add:
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply related [flat|nested] 94+ messages in thread
* Re: [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers
2025-02-11 19:24 ` [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers Terry Bowman
@ 2025-02-11 22:40 ` Dave Jiang
2025-02-12 1:23 ` Dan Williams
2025-02-12 22:28 ` Alison Schofield
2 siblings, 0 replies; 94+ messages in thread
From: Dave Jiang @ 2025-02-11 22:40 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 12:24 PM, Terry Bowman wrote:
> The CXL mem driver (cxl_mem) currently maps and caches a pointer to RAS
> registers for the endpoint's Root Port. The same needs to be done for
> each of the CXL Downstream Switch Ports and CXL Root Ports found between
> the endpoint and CXL Host Bridge.
>
> Introduce cxl_init_ep_ports_aer() to be called for each CXL Port in the
> sub-topology between the endpoint and the CXL Host Bridge. This function
> will determine if there are CXL Downstream Switch Ports or CXL Root Ports
> associated with this Port. The same check will be added in the future for
> upstream switch ports.
>
> Move the RAS register map logic from cxl_dport_map_ras() into
> cxl_dport_init_ras_reporting(). This eliminates the need for the helper
> function, cxl_dport_map_ras().
>
> cxl_init_ep_ports_aer() calls cxl_dport_init_ras_reporting() to map
> the RAS registers for CXL Downstream Switch Ports and CXL Root Ports.
>
> cxl_dport_init_ras_reporting() must check for previously mapped registers
> before mapping. This is required because multiple Endpoints under a CXL
> switch may share an upstream CXL Root Port, CXL Downstream Switch Port,
> or CXL Downstream Switch Port. Ensure the RAS registers are only mapped
> once.
>
> Introduce a mutex for synchronizing accesses to the cached RAS mapping.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Couple minor comments below.
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/pci.c | 42 ++++++++++++++++++++----------------------
> drivers/cxl/cxl.h | 6 ++----
> drivers/cxl/mem.c | 31 +++++++++++++++++++++++++++++--
> 3 files changed, 51 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index a5c65f79db18..143c853a52c4 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -24,6 +24,8 @@ static unsigned short media_ready_timeout = 60;
> module_param(media_ready_timeout, ushort, 0644);
> MODULE_PARM_DESC(media_ready_timeout, "seconds to wait for media ready");
>
> +static DEFINE_MUTEX(ras_init_mutex);
> +
> struct cxl_walk_context {
> struct pci_bus *bus;
> struct cxl_port *port;
> @@ -749,18 +751,6 @@ static void cxl_dport_map_rch_aer(struct cxl_dport *dport)
> }
> }
>
> -static void cxl_dport_map_ras(struct cxl_dport *dport)
> -{
> - struct cxl_register_map *map = &dport->reg_map;
> - struct device *dev = dport->dport_dev;
> -
> - if (!map->component_map.ras.valid)
> - dev_dbg(dev, "RAS registers not found\n");
> - else if (cxl_map_component_regs(map, &dport->regs.component,
> - BIT(CXL_CM_CAP_CAP_ID_RAS)))
> - dev_dbg(dev, "Failed to map RAS capability.\n");
> -}
> -
> static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
> {
> void __iomem *aer_base = dport->regs.dport_aer;
> @@ -788,22 +778,30 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
> /**
> * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
> * @dport: the cxl_dport that needs to be initialized
> - * @host: host device for devm operations
> */
> -void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
> +void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
> {
> - dport->reg_map.host = host;
> - cxl_dport_map_ras(dport);
> -
> - if (dport->rch) {
> - struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport->dport_dev);
> -
> - if (!host_bridge->native_aer)
> - return;
> + struct device *dport_dev = dport->dport_dev;
> + struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport_dev);
>
> + dport->reg_map.host = dport_dev;
> + if (dport->rch && host_bridge->native_aer) {
> cxl_dport_map_rch_aer(dport);
> cxl_disable_rch_root_ints(dport);
> }
> +
> + /* dport may have more than 1 downstream EP. Check if already mapped. */
> + mutex_lock(&ras_init_mutex);
I think you can just call guard() here and not deal with unlock?
> + if (dport->regs.ras) {
> + mutex_unlock(&ras_init_mutex);
> + return;
> + }
> +
> + if (cxl_map_component_regs(&dport->reg_map, &dport->regs.component,
> + BIT(CXL_CM_CAP_CAP_ID_RAS)))
> + dev_err(dport_dev, "Failed to map RAS capability\n");
> + mutex_unlock(&ras_init_mutex);
> +
> }
> EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
>
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index 6baec4ba9141..82d0a8555a11 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -754,11 +754,9 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
> resource_size_t rcrb);
>
> #ifdef CONFIG_PCIEAER_CXL
> -void cxl_setup_parent_dport(struct device *host, struct cxl_dport *dport);
> -void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host);
> +void cxl_dport_init_ras_reporting(struct cxl_dport *dport);
> #else
> -static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport,
> - struct device *host) { }
> +static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport) { }
> #endif
>
> struct cxl_decoder *to_cxl_decoder(struct device *dev);
> diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
> index 9675243bd05b..8c1144bbc058 100644
> --- a/drivers/cxl/mem.c
> +++ b/drivers/cxl/mem.c
> @@ -45,6 +45,31 @@ static int cxl_mem_dpa_show(struct seq_file *file, void *data)
> return 0;
> }
>
> +static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type)
> +{
> + struct pci_dev *pdev;
> +
> + if (!dev || !dev_is_pci(dev))
> + return false;
> +
> + pdev = to_pci_dev(dev);
> +
> + return (pci_pcie_type(pdev) == pcie_type);
> +}
dev_is_pcie_type()?
DJ
> +
> +static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
> +{
> + struct cxl_dport *dport = ep->dport;
> +
> + if (dport) {
> + struct device *dport_dev = dport->dport_dev;
> +
> + if (dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_DOWNSTREAM) ||
> + dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT))
> + cxl_dport_init_ras_reporting(dport);
> + }
> +}
> +
> static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
> struct cxl_dport *parent_dport)
> {
> @@ -52,6 +77,9 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
> struct cxl_port *endpoint, *iter, *down;
> int rc;
>
> + if (parent_dport->rch)
> + cxl_dport_init_ras_reporting(parent_dport);
> +
> /*
> * Now that the path to the root is established record all the
> * intervening ports in the chain.
> @@ -62,6 +90,7 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
>
> ep = cxl_ep_load(iter, cxlmd);
> ep->next = down;
> + cxl_init_ep_ports_aer(ep);
> }
>
> /* Note: endpoint port component registers are derived from @cxlds */
> @@ -166,8 +195,6 @@ static int cxl_mem_probe(struct device *dev)
> else
> endpoint_parent = &parent_port->dev;
>
> - cxl_dport_init_ras_reporting(dport, dev);
> -
> scoped_guard(device, endpoint_parent) {
> if (!endpoint_parent->driver) {
> dev_err(dev, "CXL port topology %s not enabled\n",
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
2025-02-11 19:24 ` [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream " Terry Bowman
@ 2025-02-11 23:02 ` Dave Jiang
2025-02-12 2:00 ` Dan Williams
2025-02-14 15:15 ` Jonathan Cameron
2 siblings, 0 replies; 94+ messages in thread
From: Dave Jiang @ 2025-02-11 23:02 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 12:24 PM, Terry Bowman wrote:
> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
>
> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
> pointer to the CXL Upstream Port's mapped RAS registers.
>
> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
> register mapping. This is similar to the existing
> cxl_dport_init_ras_reporting() but for USP devices.
>
> The USP may have multiple downstream endpoints. Before mapping RAS
> registers check if the registers are already mapped.
>
> Introduce a mutex for synchronizing accesses to the cached RAS
> mapping.
s/Introduce a mutex/Use the ras_init_mutex/ since it was introduced in the previous patch.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Just a minor comment below
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/pci.c | 19 ++++++++++++++++++-
> drivers/cxl/cxl.h | 4 ++++
> drivers/cxl/mem.c | 8 ++++++++
> 3 files changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 143c853a52c4..25513b9a8aff 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -775,6 +775,24 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
> writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
> }
>
> +void cxl_uport_init_ras_reporting(struct cxl_port *port)
> +{
> +
> + /* uport may have more than 1 downstream EP. Check if already mapped. */
> + mutex_lock(&ras_init_mutex);
You can use guard() here.
> + if (port->uport_regs.ras) {
> + mutex_unlock(&ras_init_mutex);
> + return;
> + }
> +
> + port->reg_map.host = &port->dev;
> + if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
> + BIT(CXL_CM_CAP_CAP_ID_RAS)))
> + dev_err(&port->dev, "Failed to map RAS capability\n");
> + mutex_unlock(&ras_init_mutex);
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
> +
> /**
> * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
> * @dport: the cxl_dport that needs to be initialized
> @@ -801,7 +819,6 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
> BIT(CXL_CM_CAP_CAP_ID_RAS)))
> dev_err(dport_dev, "Failed to map RAS capability\n");
> mutex_unlock(&ras_init_mutex);
> -
> }
> EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
>
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index 82d0a8555a11..49f29a3ef68e 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -581,6 +581,7 @@ struct cxl_dax_region {
> * @parent_dport: dport that points to this port in the parent
> * @decoder_ida: allocator for decoder ids
> * @reg_map: component and ras register mapping parameters
> + * @uport_regs: mapped component registers
> * @nr_dports: number of entries in @dports
> * @hdm_end: track last allocated HDM decoder instance for allocation ordering
> * @commit_end: cursor to track highest committed decoder for commit ordering
> @@ -602,6 +603,7 @@ struct cxl_port {
> struct cxl_dport *parent_dport;
> struct ida decoder_ida;
> struct cxl_register_map reg_map;
> + struct cxl_component_regs uport_regs;
> int nr_dports;
> int hdm_end;
> int commit_end;
> @@ -755,8 +757,10 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
>
> #ifdef CONFIG_PCIEAER_CXL
> void cxl_dport_init_ras_reporting(struct cxl_dport *dport);
> +void cxl_uport_init_ras_reporting(struct cxl_port *port);
> #else
> static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport) { }
> +static inline void cxl_uport_init_ras_reporting(struct cxl_port *port) { }
> #endif
>
> struct cxl_decoder *to_cxl_decoder(struct device *dev);
> diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
> index 8c1144bbc058..541cabca434e 100644
> --- a/drivers/cxl/mem.c
> +++ b/drivers/cxl/mem.c
> @@ -60,6 +60,7 @@ static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type)
> static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
> {
> struct cxl_dport *dport = ep->dport;
> + struct cxl_port *port = ep->next;
>
> if (dport) {
> struct device *dport_dev = dport->dport_dev;
> @@ -68,6 +69,13 @@ static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
> dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT))
> cxl_dport_init_ras_reporting(dport);
> }
> +
> + if (port) {
> + struct device *uport_dev = port->uport_dev;
> +
> + if (dev_is_cxl_pci(uport_dev, PCI_EXP_TYPE_UPSTREAM))
> + cxl_uport_init_ras_reporting(port);
> + }
> }
>
> static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 09/17] cxl/pci: Update RAS handler interfaces to also support CXL PCIe Ports
2025-02-11 19:24 ` [PATCH v7 09/17] cxl/pci: Update RAS handler interfaces to also support CXL PCIe Ports Terry Bowman
@ 2025-02-11 23:26 ` Dave Jiang
2025-02-14 15:19 ` Jonathan Cameron
1 sibling, 0 replies; 94+ messages in thread
From: Dave Jiang @ 2025-02-11 23:26 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 12:24 PM, Terry Bowman wrote:
> CXL PCIe Port Protocol Error handling support will be added to the
> CXL drivers in the future. In preparation, rename the existing
> interfaces to support handling all CXL PCIe Port Protocol Errors.
>
> The driver's RAS support functions currently rely on a 'struct
> cxl_dev_state' type parameter, which is not available for CXL Port
> devices. However, since the same CXL RAS capability structure is
> needed across most CXL components and devices, a common handling
> approach should be adopted.
>
> To accommodate this, update the __cxl_handle_cor_ras() and
> __cxl_handle_ras() functions to use a `struct device` instead of
> `struct cxl_dev_state`.
>
> No functional changes are introduced.
>
> [1] CXL 3.1 Spec, 8.2.4 CXL.cache and CXL.mem Registers
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/pci.c | 17 ++++++++---------
> 1 file changed, 8 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 25513b9a8aff..69bb030aa8e1 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -652,7 +652,7 @@ void read_cdat_data(struct cxl_port *port)
> }
> EXPORT_SYMBOL_NS_GPL(read_cdat_data, "CXL");
>
> -static void __cxl_handle_cor_ras(struct cxl_dev_state *cxlds,
> +static void __cxl_handle_cor_ras(struct device *dev,
> void __iomem *ras_base)
> {
> void __iomem *addr;
> @@ -665,13 +665,13 @@ static void __cxl_handle_cor_ras(struct cxl_dev_state *cxlds,
> status = readl(addr);
> if (status & CXL_RAS_CORRECTABLE_STATUS_MASK) {
> writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
> - trace_cxl_aer_correctable_error(cxlds->cxlmd, status);
> + trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
> }
> }
>
> static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
> {
> - return __cxl_handle_cor_ras(cxlds, cxlds->regs.ras);
> + return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
> }
>
> /* CXL spec rev3.0 8.2.4.16.1 */
> @@ -695,8 +695,7 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)
> * Log the state of the RAS status registers and prepare them to log the
> * next error status. Return 1 if reset needed.
> */
> -static bool __cxl_handle_ras(struct cxl_dev_state *cxlds,
> - void __iomem *ras_base)
> +static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
> {
> u32 hl[CXL_HEADERLOG_SIZE_U32];
> void __iomem *addr;
> @@ -723,7 +722,7 @@ static bool __cxl_handle_ras(struct cxl_dev_state *cxlds,
> }
>
> header_log_copy(ras_base, hl);
> - trace_cxl_aer_uncorrectable_error(cxlds->cxlmd, status, fe, hl);
> + trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
> writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
>
> return true;
> @@ -731,7 +730,7 @@ static bool __cxl_handle_ras(struct cxl_dev_state *cxlds,
>
> static bool cxl_handle_endpoint_ras(struct cxl_dev_state *cxlds)
> {
> - return __cxl_handle_ras(cxlds, cxlds->regs.ras);
> + return __cxl_handle_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
> }
>
> #ifdef CONFIG_PCIEAER_CXL
> @@ -825,13 +824,13 @@ EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
> static void cxl_handle_rdport_cor_ras(struct cxl_dev_state *cxlds,
> struct cxl_dport *dport)
> {
> - return __cxl_handle_cor_ras(cxlds, dport->regs.ras);
> + return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, dport->regs.ras);
> }
>
> static bool cxl_handle_rdport_ras(struct cxl_dev_state *cxlds,
> struct cxl_dport *dport)
> {
> - return __cxl_handle_ras(cxlds, dport->regs.ras);
> + return __cxl_handle_ras(&cxlds->cxlmd->dev, dport->regs.ras);
> }
>
> /*
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 10/17] cxl/pci: Add log message and add type check in existing RAS handlers
2025-02-11 19:24 ` [PATCH v7 10/17] cxl/pci: Add log message and add type check in existing RAS handlers Terry Bowman
@ 2025-02-11 23:28 ` Dave Jiang
2025-02-12 22:59 ` Dan Williams
1 sibling, 0 replies; 94+ messages in thread
From: Dave Jiang @ 2025-02-11 23:28 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 12:24 PM, Terry Bowman wrote:
> The CXL RAS handlers do not currently log if the RAS registers are
> unmapped. This is needed in order to help debug CXL error handling. Update
> the CXL driver to log a warning message if the RAS register block is
> unmapped.
>
> Also, add type check before processing EP or RCH DP.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/pci.c | 20 ++++++++++++++------
> 1 file changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 69bb030aa8e1..af809e7cbe3b 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -658,15 +658,19 @@ static void __cxl_handle_cor_ras(struct device *dev,
> void __iomem *addr;
> u32 status;
>
> - if (!ras_base)
> + if (!ras_base) {
> + dev_warn_once(dev, "CXL RAS register block is not mapped");
> return;
> + }
>
> addr = ras_base + CXL_RAS_CORRECTABLE_STATUS_OFFSET;
> status = readl(addr);
> - if (status & CXL_RAS_CORRECTABLE_STATUS_MASK) {
> - writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
> + if (!(status & CXL_RAS_CORRECTABLE_STATUS_MASK))
> + return;
> + writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
> +
> + if (is_cxl_memdev(dev))
> trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
> - }
> }
>
> static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
> @@ -702,8 +706,10 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
> u32 status;
> u32 fe;
>
> - if (!ras_base)
> + if (!ras_base) {
> + dev_warn_once(dev, "CXL RAS register block is not mapped");
> return false;
> + }
>
> addr = ras_base + CXL_RAS_UNCORRECTABLE_STATUS_OFFSET;
> status = readl(addr);
> @@ -722,7 +728,9 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
> }
>
> header_log_copy(ras_base, hl);
> - trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
> + if (is_cxl_memdev(dev))
> + trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
> +
> writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
>
> return true;
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 11/17] cxl/pci: Change find_cxl_port() to non-static
2025-02-11 19:24 ` [PATCH v7 11/17] cxl/pci: Change find_cxl_port() to non-static Terry Bowman
@ 2025-02-11 23:42 ` Dave Jiang
2025-02-13 23:15 ` Dan Williams
1 sibling, 0 replies; 94+ messages in thread
From: Dave Jiang @ 2025-02-11 23:42 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 12:24 PM, Terry Bowman wrote:
> CXL PCIe Port Protocol Error support will be added in the future. This
> requires searching for a CXL PCIe Port device in the CXL topology as
> provided by find_cxl_port(). But, find_cxl_port() is defined static
> and as a result is not callable outside of this source file.
>
> Update the find_cxl_port() declaration to be non-static.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
I think this could've went with the same patch that's doing the calling of this function.
> ---
> drivers/cxl/core/core.h | 2 ++
> drivers/cxl/core/port.c | 4 ++--
> 2 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
> index a20ea2b7d1a4..796334f2ad6c 100644
> --- a/drivers/cxl/core/core.h
> +++ b/drivers/cxl/core/core.h
> @@ -118,5 +118,7 @@ int cxl_port_get_switch_dport_bandwidth(struct cxl_port *port,
> struct access_coordinate *c);
>
> int cxl_gpf_port_setup(struct device *dport_dev, struct cxl_port *port);
> +struct cxl_port *find_cxl_port(struct device *dport_dev,
> + struct cxl_dport **dport);
>
> #endif /* __CXL_CORE_H__ */
> diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
> index f9501a16b390..ae6471e4ebff 100644
> --- a/drivers/cxl/core/port.c
> +++ b/drivers/cxl/core/port.c
> @@ -1352,8 +1352,8 @@ static struct cxl_port *__find_cxl_port(struct cxl_find_port_ctx *ctx)
> return NULL;
> }
>
> -static struct cxl_port *find_cxl_port(struct device *dport_dev,
> - struct cxl_dport **dport)
> +struct cxl_port *find_cxl_port(struct device *dport_dev,
> + struct cxl_dport **dport)
> {
> struct cxl_find_port_ctx ctx = {
> .dport_dev = dport_dev,
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type
2025-02-11 19:24 ` [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type Terry Bowman
2025-02-11 20:28 ` Bjorn Helgaas
@ 2025-02-11 23:47 ` Dan Williams
2025-02-12 19:15 ` Bowman, Terry
1 sibling, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-11 23:47 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> The AER driver and aer_event tracing currently log 'PCIe Bus Type'
> for all errors.
>
> Update the driver and aer_event tracing to log 'CXL Bus Type' for CXL
> device errors.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
> ---
> drivers/pci/pcie/aer.c | 14 ++++++++------
> include/ras/ras_event.h | 9 ++++++---
> 2 files changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index 6e8de77d0fc4..f99a1c6fb274 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -694,13 +694,14 @@ static void __aer_print_error(struct pci_dev *dev,
>
> void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
> {
> + const char *bus_type = pcie_is_cxl(dev) ? "CXL" : "PCIe";
I was expecting that this would be more than just a CXL link check
because CXL AER events are only a subset of the events that can trigger
an AER interrupt on a CXL device.
Also, with CXL protocol errors the TLP log is sourced from CXL RAS
registers and is distinct from the PCIe ->tlp in 'struct aer_err_info'.
All that to say that I think this patch probably wants to decorate the
bus type in 'struct aer_err_info' and then use that rather than just the ->is_cxl
flag of the device.
In the interest of moving the patch set along perhaps just do something
like this for now and circle back to make it more sophisticated later:
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 01e51db8d285..eed098c134a6 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -533,6 +533,7 @@ static inline bool pci_dev_test_and_set_removed(struct pci_dev *dev)
struct aer_err_info {
struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES];
int error_dev_num;
+ bool is_cxl;
unsigned int id:16;
@@ -549,6 +550,11 @@ struct aer_err_info {
struct pcie_tlp_log tlp; /* TLP Header */
};
+static inline const char *aer_err_bus(struct aer_err_info *info)
+{
+ return info->is_cxl ? "CXL" : "PCIe";
+}
+
int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info);
void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index 508474e17183..405f15c878ff 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -1211,6 +1211,7 @@ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
/* Must reset in this function */
info->status = 0;
info->tlp_header_valid = 0;
+ info->is_cxl = dev->is_cxl;
/* The device might not support AER */
if (!aer)
Other than that, this patch looks good to me:
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
^ permalink raw reply related [flat|nested] 94+ messages in thread
* Re: [PATCH v7 05/17] PCI/AER: Add CXL PCIe Port correctable error support in AER service driver
2025-02-11 19:24 ` [PATCH v7 05/17] PCI/AER: Add CXL PCIe Port correctable error support in AER service driver Terry Bowman
2025-02-11 20:28 ` Bjorn Helgaas
@ 2025-02-11 23:58 ` Dan Williams
2025-02-12 21:52 ` Bowman, Terry
1 sibling, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-11 23:58 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> The AER service driver supports handling Downstream Port Protocol Errors in
> Restricted CXL host (RCH) mode also known as CXL1.1. It needs the same
> functionality for CXL PCIe Ports operating in Virtual Hierarchy (VH)
> mode.[1]
>
> CXL and PCIe Protocol Error handling have different requirements that
> necessitate a separate handling path. The AER service driver may try to
> recover PCIe uncorrectable non-fatal errors (UCE). The same recovery is not
> suitable for CXL PCIe Port devices because of potential for system memory
> corruption. Instead, CXL Protocol Error handling must use a kernel panic
> in the case of a fatal or non-fatal UCE. The AER driver's PCIe Protocol
> Error handling does not panic the kernel in response to a UCE.
>
> Introduce a separate path for CXL Protocol Error handling in the AER
> service driver. This will allow CXL Protocol Errors to use CXL specific
> handling instead of PCIe handling. Add the CXL specific changes without
> affecting or adding functionality in the PCIe handling.
>
> Make this update alongside the existing Downstream Port RCH error handling
> logic, extending support to CXL PCIe Ports in VH mode.
>
> Remove is_internal_error(). is_internal_error() was used to determine if
> an AER error was a CXL error. Instead, now rely on pcie_is_cxl_port() to
> indicate the error is a CXL error.
Wait, pcie_is_cxl_port() in isolation is insufficient, right? In other
words, I would expect that when the response may escalate to panic()
that the code should be reasonably certain that this *is* a CXL error.
At a minimum that is:
pcie_is_cxl_port() && is_internal_error()
...or am I missing something that it makes it unlikely that a standard
PCIe error or other internal error type will not be thrown by a
pcie_is_cxl_port() device?
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery in AER service driver
2025-02-11 19:24 ` [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery " Terry Bowman
2025-02-11 20:29 ` Bjorn Helgaas
2025-02-11 21:59 ` Dave Jiang
@ 2025-02-12 0:02 ` Gregory Price
2025-02-12 0:24 ` Dan Williams
` (2 subsequent siblings)
5 siblings, 0 replies; 94+ messages in thread
From: Gregory Price @ 2025-02-12 0:02 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:33PM -0600, Terry Bowman wrote:
> cxl_do_recovery() uses the status from cxl_report_error_detected() to
> determine how to proceed. Non-fatal CXL UCE errors will be treated as
> fatal. If a UCE was present during handling then cxl_do_recovery()
> will kernel panic.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 13/17] cxl/pci: Add trace logging for CXL PCIe Port RAS errors
2025-02-11 19:24 ` [PATCH v7 13/17] cxl/pci: Add trace logging " Terry Bowman
@ 2025-02-12 0:11 ` Gregory Price
2025-02-12 0:17 ` Dave Jiang
2025-02-14 2:21 ` Dan Williams
2 siblings, 0 replies; 94+ messages in thread
From: Gregory Price @ 2025-02-12 0:11 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:40PM -0600, Terry Bowman wrote:
> The CXL drivers use kernel trace functions for logging Endpoint and
> Restricted CXL host (RCH) Downstream Port RAS errors. Similar functionality
> is required for CXL Root Ports, CXL Downstream Switch Ports, and CXL
> Upstream Switch Ports.
>
> Introduce trace logging functions for both RAS correctable and
> uncorrectable errors specific to CXL PCIe Ports. Additionally, update
> the CXL Port Protocol Error handlers to invoke these new trace functions.
>
> Examples of the output from these changes is below.
>
> Correctable error:
> cxl_port_aer_correctable_error: device=port1 parent=root0 status='Received Error From Physical Layer'
>
> Uncorrectable error:
> cxl_port_aer_uncorrectable_error: device=port1 parent=root0 status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Erro'
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Gregory Price <gourry@gourry.net>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors
2025-02-11 19:24 ` [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors Terry Bowman
@ 2025-02-12 0:11 ` Dave Jiang
2025-02-12 16:34 ` Bowman, Terry
2025-02-14 2:18 ` Dan Williams
2025-03-05 0:22 ` Ira Weiny
2 siblings, 1 reply; 94+ messages in thread
From: Dave Jiang @ 2025-02-12 0:11 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 12:24 PM, Terry Bowman wrote:
> Introduce correctable and uncorrectable (UCE) CXL PCIe Port Protocol Error
> handlers.
>
> The handlers will be called with a 'struct pci_dev' parameter
> indicating the CXL Port device requiring handling. The CXL PCIe Port
> device's underlying 'struct device' will match the port device in the
> CXL topology.
>
> Use the PCIe Port's device object to find the matching CXL Upstream Switch
> Port, CXL Downstream Switch Port, or CXL Root Port in the CXL topology. The
> matching CXL Port device should contain a cached reference to the RAS
> register block. The cached RAS block will be used in handling the error.
>
> Invoke the existing __cxl_handle_ras() or __cxl_handle_cor_ras() using
> a reference to the RAS registers as a parameter. These functions will use
> the RAS register reference to indicate an error and clear the device's RAS
> status.
>
> Update __cxl_handle_ras() to return PCI_ERS_RESULT_PANIC in the case
> an error is present in the RAS status. Otherwise, return
> PCI_ERS_RESULT_NONE.
Maybe a comment on why the change?
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> ---
> drivers/cxl/core/pci.c | 81 +++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 77 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index af809e7cbe3b..3f13d9dfb610 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -699,7 +699,7 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)
> * Log the state of the RAS status registers and prepare them to log the
> * next error status. Return 1 if reset needed.
> */
> -static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
> +static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
> {
> u32 hl[CXL_HEADERLOG_SIZE_U32];
> void __iomem *addr;
> @@ -708,13 +708,13 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>
> if (!ras_base) {
> dev_warn_once(dev, "CXL RAS register block is not mapped");
> - return false;
> + return PCI_ERS_RESULT_NONE;
> }
>
> addr = ras_base + CXL_RAS_UNCORRECTABLE_STATUS_OFFSET;
> status = readl(addr);
> if (!(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK))
> - return false;
> + return PCI_ERS_RESULT_NONE;
>
> /* If multiple errors, log header points to first error from ctrl reg */
> if (hweight32(status) > 1) {
> @@ -733,7 +733,7 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>
> writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
>
> - return true;
> + return PCI_ERS_RESULT_PANIC;
> }
>
> static bool cxl_handle_endpoint_ras(struct cxl_dev_state *cxlds)
> @@ -782,6 +782,79 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
> writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
> }
>
> +static int match_uport(struct device *dev, const void *data)
> +{
> + const struct device *uport_dev = data;
> + struct cxl_port *port;
> +
> + if (!is_cxl_port(dev))
> + return 0;
> +
> + port = to_cxl_port(dev);
> +
> + return port->uport_dev == uport_dev;
> +}
> +
> +static void __iomem *cxl_pci_port_ras(struct pci_dev *pdev, struct device **dev)
> +{
> + void __iomem *ras_base;
> +
> + if (!pdev || !*dev) {
> + pr_err("Failed, parameter is NULL");
> + return NULL;
> + }
> +
> + if ((pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) ||
> + (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM)) {
Can probably just do a switch block here for the type?
> + struct cxl_port *port __free(put_cxl_port);
> + struct cxl_dport *dport = NULL;
> +
> + port = find_cxl_port(&pdev->dev, &dport);
Just declare port inline:
struct cxl_port *port __free(put_cxl_port) =
find_cxl_port(&pdev->dev, &dport);
> + if (!port) {
> + pci_err(pdev, "Failed to find root/dport in CXL topology\n");
> + return NULL;
> + }
> +
> + ras_base = dport ? dport->regs.ras : NULL;
> + *dev = &port->dev;
> + } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_UPSTREAM) {
> + struct device *port_dev __free(put_device);
same comment here as above
DJ
> + struct cxl_port *port;
> +
> + port_dev = bus_find_device(&cxl_bus_type, NULL, &pdev->dev,
> + match_uport);
> + if (!port_dev || !is_cxl_port(port_dev)) {
> + pci_err(pdev, "Failed to find uport in CXL topology\n");
> + return NULL;
> + }
> +
> + port = to_cxl_port(port_dev);
> + ras_base = port ? port->uport_regs.ras : NULL;
> + *dev = port_dev;
> + } else {
> + pci_err(pdev, "Unsupported device type\n");
> + ras_base = NULL;
> + }
> +
> + return ras_base;
> +}
> +
> +static void cxl_port_cor_error_detected(struct pci_dev *pdev)
> +{
> + struct device *dev;
> + void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
> +
> + __cxl_handle_cor_ras(dev, ras_base);
> +}
> +
> +static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
> +{
> + struct device *dev;
> + void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
> +
> + return __cxl_handle_ras(dev, ras_base);
> +}
> +
> void cxl_uport_init_ras_reporting(struct cxl_port *port)
> {
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 13/17] cxl/pci: Add trace logging for CXL PCIe Port RAS errors
2025-02-11 19:24 ` [PATCH v7 13/17] cxl/pci: Add trace logging " Terry Bowman
2025-02-12 0:11 ` Gregory Price
@ 2025-02-12 0:17 ` Dave Jiang
2025-02-12 0:19 ` Dave Jiang
2025-02-12 16:23 ` Bowman, Terry
2025-02-14 2:21 ` Dan Williams
2 siblings, 2 replies; 94+ messages in thread
From: Dave Jiang @ 2025-02-12 0:17 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 12:24 PM, Terry Bowman wrote:
> The CXL drivers use kernel trace functions for logging Endpoint and
> Restricted CXL host (RCH) Downstream Port RAS errors. Similar functionality
> is required for CXL Root Ports, CXL Downstream Switch Ports, and CXL
> Upstream Switch Ports.
>
> Introduce trace logging functions for both RAS correctable and
> uncorrectable errors specific to CXL PCIe Ports. Additionally, update
> the CXL Port Protocol Error handlers to invoke these new trace functions.
>
> Examples of the output from these changes is below.
>
> Correctable error:
> cxl_port_aer_correctable_error: device=port1 parent=root0 status='Received Error From Physical Layer'
Is there any way to identify if the error comes from the USP or DSP? Specifically the PCI devname for the specific port?
>
> Uncorrectable error:
> cxl_port_aer_uncorrectable_error: device=port1 parent=root0 status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Erro'
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/pci.c | 4 ++++
> drivers/cxl/core/trace.h | 47 ++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 51 insertions(+)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 3f13d9dfb610..9a3090dae46a 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -671,6 +671,8 @@ static void __cxl_handle_cor_ras(struct device *dev,
>
> if (is_cxl_memdev(dev))
> trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
> + else if (is_cxl_port(dev))
> + trace_cxl_port_aer_correctable_error(dev, status);
> }
>
> static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
> @@ -730,6 +732,8 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
> header_log_copy(ras_base, hl);
> if (is_cxl_memdev(dev))
> trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
> + else if (is_cxl_port(dev))
> + trace_cxl_port_aer_uncorrectable_error(dev, status, fe, hl);
>
> writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
>
> diff --git a/drivers/cxl/core/trace.h b/drivers/cxl/core/trace.h
> index cea706b683b5..b536233ac210 100644
> --- a/drivers/cxl/core/trace.h
> +++ b/drivers/cxl/core/trace.h
> @@ -48,6 +48,34 @@
> { CXL_RAS_UC_IDE_RX_ERR, "IDE Rx Error" } \
> )
>
> +TRACE_EVENT(cxl_port_aer_uncorrectable_error,
> + TP_PROTO(struct device *dev, u32 status, u32 fe, u32 *hl),
> + TP_ARGS(dev, status, fe, hl),
> + TP_STRUCT__entry(
> + __string(devname, dev_name(dev))
> + __string(parent, dev_name(dev->parent))
> + __field(u32, status)
> + __field(u32, first_error)
> + __array(u32, header_log, CXL_HEADERLOG_SIZE_U32)
> + ),
> + TP_fast_assign(
> + __assign_str(devname);
> + __assign_str(parent);
> + __entry->status = status;
> + __entry->first_error = fe;
> + /*
> + * Embed the 512B headerlog data for user app retrieval and
> + * parsing, but no need to print this in the trace buffer.
> + */
> + memcpy(__entry->header_log, hl, CXL_HEADERLOG_SIZE);
> + ),
> + TP_printk("device=%s parent=%s status: '%s' first_error: '%s'",
> + __get_str(devname), __get_str(parent),
> + show_uc_errs(__entry->status),
> + show_uc_errs(__entry->first_error)
> + )
> +);
> +
> TRACE_EVENT(cxl_aer_uncorrectable_error,
> TP_PROTO(const struct cxl_memdev *cxlmd, u32 status, u32 fe, u32 *hl),
> TP_ARGS(cxlmd, status, fe, hl),
> @@ -96,6 +124,25 @@ TRACE_EVENT(cxl_aer_uncorrectable_error,
> { CXL_RAS_CE_PHYS_LAYER_ERR, "Received Error From Physical Layer" } \
> )
>
> +TRACE_EVENT(cxl_port_aer_correctable_error,
> + TP_PROTO(struct device *dev, u32 status),
> + TP_ARGS(dev, status),
> + TP_STRUCT__entry(
> + __string(devname, dev_name(dev))
> + __string(parent, dev_name(dev->parent))
> + __field(u32, status)
> + ),
> + TP_fast_assign(
> + __assign_str(devname);
> + __assign_str(parent);
> + __entry->status = status;
> + ),
> + TP_printk("device=%s parent=%s status='%s'",
> + __get_str(devname), __get_str(parent),
> + show_ce_errs(__entry->status)
> + )
> +);
> +
> TRACE_EVENT(cxl_aer_correctable_error,
> TP_PROTO(const struct cxl_memdev *cxlmd, u32 status),
> TP_ARGS(cxlmd, status),
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 13/17] cxl/pci: Add trace logging for CXL PCIe Port RAS errors
2025-02-12 0:17 ` Dave Jiang
@ 2025-02-12 0:19 ` Dave Jiang
2025-02-12 16:23 ` Bowman, Terry
1 sibling, 0 replies; 94+ messages in thread
From: Dave Jiang @ 2025-02-12 0:19 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 5:17 PM, Dave Jiang wrote:
>
>
> On 2/11/25 12:24 PM, Terry Bowman wrote:
>> The CXL drivers use kernel trace functions for logging Endpoint and
>> Restricted CXL host (RCH) Downstream Port RAS errors. Similar functionality
>> is required for CXL Root Ports, CXL Downstream Switch Ports, and CXL
>> Upstream Switch Ports.
>>
>> Introduce trace logging functions for both RAS correctable and
>> uncorrectable errors specific to CXL PCIe Ports. Additionally, update
>> the CXL Port Protocol Error handlers to invoke these new trace functions.
>>
>> Examples of the output from these changes is below.
>>
>> Correctable error:
>> cxl_port_aer_correctable_error: device=port1 parent=root0 status='Received Error From Physical Layer'
>
> Is there any way to identify if the error comes from the USP or DSP? Specifically the PCI devname for the specific port?
Hah I spoke too soon. You addressed it in the next patch. :)
DJ
>>
>> Uncorrectable error:
>> cxl_port_aer_uncorrectable_error: device=port1 parent=root0 status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Erro'
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> Reviewed-by: Alejandro Lucero <alucerop@amd.com>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
>
>> ---
>> drivers/cxl/core/pci.c | 4 ++++
>> drivers/cxl/core/trace.h | 47 ++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 51 insertions(+)
>>
>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>> index 3f13d9dfb610..9a3090dae46a 100644
>> --- a/drivers/cxl/core/pci.c
>> +++ b/drivers/cxl/core/pci.c
>> @@ -671,6 +671,8 @@ static void __cxl_handle_cor_ras(struct device *dev,
>>
>> if (is_cxl_memdev(dev))
>> trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
>> + else if (is_cxl_port(dev))
>> + trace_cxl_port_aer_correctable_error(dev, status);
>> }
>>
>> static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
>> @@ -730,6 +732,8 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
>> header_log_copy(ras_base, hl);
>> if (is_cxl_memdev(dev))
>> trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
>> + else if (is_cxl_port(dev))
>> + trace_cxl_port_aer_uncorrectable_error(dev, status, fe, hl);
>>
>> writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
>>
>> diff --git a/drivers/cxl/core/trace.h b/drivers/cxl/core/trace.h
>> index cea706b683b5..b536233ac210 100644
>> --- a/drivers/cxl/core/trace.h
>> +++ b/drivers/cxl/core/trace.h
>> @@ -48,6 +48,34 @@
>> { CXL_RAS_UC_IDE_RX_ERR, "IDE Rx Error" } \
>> )
>>
>> +TRACE_EVENT(cxl_port_aer_uncorrectable_error,
>> + TP_PROTO(struct device *dev, u32 status, u32 fe, u32 *hl),
>> + TP_ARGS(dev, status, fe, hl),
>> + TP_STRUCT__entry(
>> + __string(devname, dev_name(dev))
>> + __string(parent, dev_name(dev->parent))
>> + __field(u32, status)
>> + __field(u32, first_error)
>> + __array(u32, header_log, CXL_HEADERLOG_SIZE_U32)
>> + ),
>> + TP_fast_assign(
>> + __assign_str(devname);
>> + __assign_str(parent);
>> + __entry->status = status;
>> + __entry->first_error = fe;
>> + /*
>> + * Embed the 512B headerlog data for user app retrieval and
>> + * parsing, but no need to print this in the trace buffer.
>> + */
>> + memcpy(__entry->header_log, hl, CXL_HEADERLOG_SIZE);
>> + ),
>> + TP_printk("device=%s parent=%s status: '%s' first_error: '%s'",
>> + __get_str(devname), __get_str(parent),
>> + show_uc_errs(__entry->status),
>> + show_uc_errs(__entry->first_error)
>> + )
>> +);
>> +
>> TRACE_EVENT(cxl_aer_uncorrectable_error,
>> TP_PROTO(const struct cxl_memdev *cxlmd, u32 status, u32 fe, u32 *hl),
>> TP_ARGS(cxlmd, status, fe, hl),
>> @@ -96,6 +124,25 @@ TRACE_EVENT(cxl_aer_uncorrectable_error,
>> { CXL_RAS_CE_PHYS_LAYER_ERR, "Received Error From Physical Layer" } \
>> )
>>
>> +TRACE_EVENT(cxl_port_aer_correctable_error,
>> + TP_PROTO(struct device *dev, u32 status),
>> + TP_ARGS(dev, status),
>> + TP_STRUCT__entry(
>> + __string(devname, dev_name(dev))
>> + __string(parent, dev_name(dev->parent))
>> + __field(u32, status)
>> + ),
>> + TP_fast_assign(
>> + __assign_str(devname);
>> + __assign_str(parent);
>> + __entry->status = status;
>> + ),
>> + TP_printk("device=%s parent=%s status='%s'",
>> + __get_str(devname), __get_str(parent),
>> + show_ce_errs(__entry->status)
>> + )
>> +);
>> +
>> TRACE_EVENT(cxl_aer_correctable_error,
>> TP_PROTO(const struct cxl_memdev *cxlmd, u32 status),
>> TP_ARGS(cxlmd, status),
>
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 14/17] cxl/pci: Update CXL Port RAS logging to also display PCIe SBDF
2025-02-11 19:24 ` [PATCH v7 14/17] cxl/pci: Update CXL Port RAS logging to also display PCIe SBDF Terry Bowman
@ 2025-02-12 0:21 ` Dave Jiang
2025-02-12 16:20 ` Bowman, Terry
2025-02-12 23:30 ` Alison Schofield
1 sibling, 1 reply; 94+ messages in thread
From: Dave Jiang @ 2025-02-12 0:21 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 12:24 PM, Terry Bowman wrote:
> CXL RAS errors are currently logged using the associated CXL port's name
> returned from devname(). They are typically named with 'port1', 'port2',
> etc. to indicate the hierarchial location in the CXL topology. But, this
> doesn't clearly indicate the CXL card or slot reporting the error.
>
> Update the logging to also log the corresponding PCIe devname. This will
> give a PCIe SBDF or ACPI object name (in case of CXL HB). This will provide
> details helping users understand which physical slot and card has the
> error.
>
> Below is example output after making these changes.
>
> Correctable error example output:
> cxl_port_aer_correctable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status='Received Error From Physical Layer'
>
> Uncorrectable error example output:
> cxl_port_aer_uncorrectable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Error'
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
I wonder if there's any benefit in identifying if the PCIe device is USP or DSP...
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/pci.c | 39 +++++++++++++++++++------------------
> drivers/cxl/core/trace.h | 42 +++++++++++++++++++++++++---------------
> 2 files changed, 46 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 9a3090dae46a..f154dcf6dfda 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -652,14 +652,14 @@ void read_cdat_data(struct cxl_port *port)
> }
> EXPORT_SYMBOL_NS_GPL(read_cdat_data, "CXL");
>
> -static void __cxl_handle_cor_ras(struct device *dev,
> +static void __cxl_handle_cor_ras(struct device *cxl_dev, struct device *pcie_dev,
> void __iomem *ras_base)
> {
> void __iomem *addr;
> u32 status;
>
> if (!ras_base) {
> - dev_warn_once(dev, "CXL RAS register block is not mapped");
> + dev_warn_once(cxl_dev, "CXL RAS register block is not mapped");
> return;
> }
>
> @@ -669,15 +669,15 @@ static void __cxl_handle_cor_ras(struct device *dev,
> return;
> writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
>
> - if (is_cxl_memdev(dev))
> - trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
> - else if (is_cxl_port(dev))
> - trace_cxl_port_aer_correctable_error(dev, status);
> + if (is_cxl_memdev(cxl_dev))
> + trace_cxl_aer_correctable_error(to_cxl_memdev(cxl_dev), status);
> + else if (is_cxl_port(cxl_dev))
> + trace_cxl_port_aer_correctable_error(cxl_dev, pcie_dev, status);
> }
>
> static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
> {
> - return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
> + return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, NULL, cxlds->regs.ras);
> }
>
> /* CXL spec rev3.0 8.2.4.16.1 */
> @@ -701,7 +701,8 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)
> * Log the state of the RAS status registers and prepare them to log the
> * next error status. Return 1 if reset needed.
> */
> -static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
> +static pci_ers_result_t __cxl_handle_ras(struct device *cxl_dev, struct device *pcie_dev,
> + void __iomem *ras_base)
> {
> u32 hl[CXL_HEADERLOG_SIZE_U32];
> void __iomem *addr;
> @@ -709,7 +710,7 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
> u32 fe;
>
> if (!ras_base) {
> - dev_warn_once(dev, "CXL RAS register block is not mapped");
> + dev_warn_once(cxl_dev, "CXL RAS register block is not mapped");
> return PCI_ERS_RESULT_NONE;
> }
>
> @@ -730,10 +731,10 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
> }
>
> header_log_copy(ras_base, hl);
> - if (is_cxl_memdev(dev))
> - trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
> - else if (is_cxl_port(dev))
> - trace_cxl_port_aer_uncorrectable_error(dev, status, fe, hl);
> + if (is_cxl_memdev(cxl_dev))
> + trace_cxl_aer_uncorrectable_error(to_cxl_memdev(cxl_dev), status, fe, hl);
> + else if (is_cxl_port(cxl_dev))
> + trace_cxl_port_aer_uncorrectable_error(cxl_dev, pcie_dev, status, fe, hl);
>
> writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
>
> @@ -742,7 +743,7 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
>
> static bool cxl_handle_endpoint_ras(struct cxl_dev_state *cxlds)
> {
> - return __cxl_handle_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
> + return __cxl_handle_ras(&cxlds->cxlmd->dev, NULL, cxlds->regs.ras);
> }
>
> #ifdef CONFIG_PCIEAER_CXL
> @@ -814,7 +815,7 @@ static void __iomem *cxl_pci_port_ras(struct pci_dev *pdev, struct device **dev)
> struct cxl_dport *dport = NULL;
>
> port = find_cxl_port(&pdev->dev, &dport);
> - if (!port) {
> + if (!port || !is_cxl_port(&port->dev)) {
> pci_err(pdev, "Failed to find root/dport in CXL topology\n");
> return NULL;
> }
> @@ -848,7 +849,7 @@ static void cxl_port_cor_error_detected(struct pci_dev *pdev)
> struct device *dev;
> void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
>
> - __cxl_handle_cor_ras(dev, ras_base);
> + __cxl_handle_cor_ras(dev, &pdev->dev, ras_base);
> }
>
> static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
> @@ -856,7 +857,7 @@ static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
> struct device *dev;
> void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
>
> - return __cxl_handle_ras(dev, ras_base);
> + return __cxl_handle_ras(dev, &pdev->dev, ras_base);
> }
>
> void cxl_uport_init_ras_reporting(struct cxl_port *port)
> @@ -909,13 +910,13 @@ EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
> static void cxl_handle_rdport_cor_ras(struct cxl_dev_state *cxlds,
> struct cxl_dport *dport)
> {
> - return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, dport->regs.ras);
> + return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, NULL, dport->regs.ras);
> }
>
> static bool cxl_handle_rdport_ras(struct cxl_dev_state *cxlds,
> struct cxl_dport *dport)
> {
> - return __cxl_handle_ras(&cxlds->cxlmd->dev, dport->regs.ras);
> + return __cxl_handle_ras(&cxlds->cxlmd->dev, NULL, dport->regs.ras);
> }
>
> /*
> diff --git a/drivers/cxl/core/trace.h b/drivers/cxl/core/trace.h
> index b536233ac210..a74803f4aa22 100644
> --- a/drivers/cxl/core/trace.h
> +++ b/drivers/cxl/core/trace.h
> @@ -49,18 +49,22 @@
> )
>
> TRACE_EVENT(cxl_port_aer_uncorrectable_error,
> - TP_PROTO(struct device *dev, u32 status, u32 fe, u32 *hl),
> - TP_ARGS(dev, status, fe, hl),
> + TP_PROTO(struct device *cxl_dev, struct device *pcie_dev, u32 status, u32 fe, u32 *hl),
> + TP_ARGS(cxl_dev, pcie_dev, status, fe, hl),
> TP_STRUCT__entry(
> - __string(devname, dev_name(dev))
> - __string(parent, dev_name(dev->parent))
> + __string(cxl_name, dev_name(cxl_dev))
> + __string(cxl_parent_name, dev_name(cxl_dev->parent))
> + __string(pcie_name, dev_name(pcie_dev))
> + __string(pcie_parent_name, dev_name(pcie_dev->parent))
> __field(u32, status)
> __field(u32, first_error)
> __array(u32, header_log, CXL_HEADERLOG_SIZE_U32)
> ),
> TP_fast_assign(
> - __assign_str(devname);
> - __assign_str(parent);
> + __assign_str(cxl_name);
> + __assign_str(cxl_parent_name);
> + __assign_str(pcie_name);
> + __assign_str(pcie_parent_name);
> __entry->status = status;
> __entry->first_error = fe;
> /*
> @@ -69,8 +73,9 @@ TRACE_EVENT(cxl_port_aer_uncorrectable_error,
> */
> memcpy(__entry->header_log, hl, CXL_HEADERLOG_SIZE);
> ),
> - TP_printk("device=%s parent=%s status: '%s' first_error: '%s'",
> - __get_str(devname), __get_str(parent),
> + TP_printk("device=%s (%s) parent=%s (%s) status: '%s' first_error: '%s'",
> + __get_str(cxl_name), __get_str(pcie_name),
> + __get_str(cxl_parent_name), __get_str(pcie_parent_name),
> show_uc_errs(__entry->status),
> show_uc_errs(__entry->first_error)
> )
> @@ -125,20 +130,25 @@ TRACE_EVENT(cxl_aer_uncorrectable_error,
> )
>
> TRACE_EVENT(cxl_port_aer_correctable_error,
> - TP_PROTO(struct device *dev, u32 status),
> - TP_ARGS(dev, status),
> + TP_PROTO(struct device *cxl_dev, struct device *pcie_dev, u32 status),
> + TP_ARGS(cxl_dev, pcie_dev, status),
> TP_STRUCT__entry(
> - __string(devname, dev_name(dev))
> - __string(parent, dev_name(dev->parent))
> + __string(cxl_name, dev_name(cxl_dev))
> + __string(cxl_parent_name, dev_name(cxl_dev->parent))
> + __string(pcie_name, dev_name(pcie_dev))
> + __string(pcie_parent_name, dev_name(pcie_dev->parent))
> __field(u32, status)
> ),
> TP_fast_assign(
> - __assign_str(devname);
> - __assign_str(parent);
> + __assign_str(cxl_name);
> + __assign_str(cxl_parent_name);
> + __assign_str(pcie_name);
> + __assign_str(pcie_parent_name);
> __entry->status = status;
> ),
> - TP_printk("device=%s parent=%s status='%s'",
> - __get_str(devname), __get_str(parent),
> + TP_printk("device=%s (%s) parent=%s (%s) status='%s'",
> + __get_str(cxl_name), __get_str(pcie_name),
> + __get_str(cxl_parent_name), __get_str(pcie_parent_name),
> show_ce_errs(__entry->status)
> )
> );
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery in AER service driver
2025-02-11 19:24 ` [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery " Terry Bowman
` (2 preceding siblings ...)
2025-02-12 0:02 ` Gregory Price
@ 2025-02-12 0:24 ` Dan Williams
2025-02-14 19:36 ` Bowman, Terry
2025-02-14 15:11 ` Jonathan Cameron
2025-02-14 17:36 ` Fan Ni
5 siblings, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-12 0:24 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> Existing recovery procedure for PCIe uncorrectable errors (UCE) does not
> apply to CXL devices. Recovery can not be used for CXL devices because of
> potential corruption on what can be system memory. Also, current PCIe UCE
> recovery, in the case of a Root Port (RP) or Downstream Switch Port (DSP),
> does not begin at the RP/DSP but begins at the first downstream device.
> This will miss handling CXL Protocol Errors in a CXL RP or DSP. A separate
> CXL recovery is needed because of the different handling requirements
>
> Add a new function, cxl_do_recovery() using the following.
>
> Add cxl_walk_bridge() to iterate the detected error's sub-topology.
> cxl_walk_bridge() is similar to pci_walk_bridge() but the CXL flavor
> will begin iteration at the RP or DSP rather than beginning at the
> first downstream device.
>
> pci_walk_bridge() is candidate to possibly reuse cxl_walk_bridge() but
> needs further investigation. This will be left for future improvement
> to make the CXL and PCI handling paths more common.
>
> Add cxl_report_error_detected() as an analog to report_error_detected().
> It will call pci_driver::cxl_err_handlers for each iterated downstream
> device. The pci_driver::cxl_err_handler's UCE handler returns a boolean
> indicating if there was a UCE error detected during handling.
>
> cxl_do_recovery() uses the status from cxl_report_error_detected() to
> determine how to proceed. Non-fatal CXL UCE errors will be treated as
> fatal. If a UCE was present during handling then cxl_do_recovery()
> will kernel panic.
For what this is:
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
...and perhaps it addresses my concern on the prior patch that
->error_detected() is responsible for the safety of checking that in
fact a CXL internal error / UCE was detected.
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 15/17] cxl/pci: Add support to assign and clear pci_driver::cxl_err_handlers
2025-02-11 19:24 ` [PATCH v7 15/17] cxl/pci: Add support to assign and clear pci_driver::cxl_err_handlers Terry Bowman
@ 2025-02-12 0:38 ` Dave Jiang
2025-02-14 2:29 ` Dan Williams
1 sibling, 0 replies; 94+ messages in thread
From: Dave Jiang @ 2025-02-12 0:38 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 12:24 PM, Terry Bowman wrote:
> pci_driver::cxl_err_handlers are not currently assigned handler callbacks.
> The handlers can't be set in the pci_driver static definition because the
> CXL PCIe Port devices are bound to the portdrv driver which is not CXL
> driver aware.
>
> Add cxl_assign_port_error_handlers() in the cxl_core module. This
> function will assign the default handlers for a CXL PCIe Port device.
>
> When the CXL Port (cxl_port or cxl_dport) is destroyed the device's
> pci_driver::cxl_err_handlers must be set to NULL indicating they should no
> longer be used.
>
> Create cxl_clear_port_error_handlers() and register it to be called
> when the CXL Port device (cxl_port or cxl_dport) is destroyed.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/pci.c | 59 ++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 57 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index f154dcf6dfda..03ae21a944e0 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -860,8 +860,39 @@ static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
> return __cxl_handle_ras(dev, &pdev->dev, ras_base);
> }
>
> +static const struct cxl_error_handlers cxl_port_error_handlers = {
> + .error_detected = cxl_port_error_detected,
> + .cor_error_detected = cxl_port_cor_error_detected,
> +};
> +
> +static void cxl_assign_port_error_handlers(struct pci_dev *pdev)
> +{
> + struct pci_driver *pdrv;
> +
> + if (!pdev || !pdev->driver || !get_device(&pdev->dev))
> + return;
> +
> + pdrv = pdev->driver;
> + pdrv->cxl_err_handler = &cxl_port_error_handlers;
> + put_device(&pdev->dev);
> +}
> +
> +static void cxl_clear_port_error_handlers(void *data)
> +{
> + struct pci_dev *pdev = data;
> + struct pci_driver *pdrv;
> +
> + if (!pdev || !pdev->driver || !get_device(&pdev->dev))
> + return;
> +
> + pdrv = pdev->driver;
> + pdrv->cxl_err_handler = NULL;
> + put_device(&pdev->dev);
> +}
> +
> void cxl_uport_init_ras_reporting(struct cxl_port *port)
> {
> + struct pci_dev *pdev = to_pci_dev(port->uport_dev);
>
> /* uport may have more than 1 downstream EP. Check if already mapped. */
> mutex_lock(&ras_init_mutex);
> @@ -872,9 +903,15 @@ void cxl_uport_init_ras_reporting(struct cxl_port *port)
>
> port->reg_map.host = &port->dev;
> if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
> - BIT(CXL_CM_CAP_CAP_ID_RAS)))
> + BIT(CXL_CM_CAP_CAP_ID_RAS))) {
> dev_err(&port->dev, "Failed to map RAS capability\n");
> + mutex_unlock(&ras_init_mutex);
> + return;
> + }
> mutex_unlock(&ras_init_mutex);
> +
> + cxl_assign_port_error_handlers(pdev);
> + devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
> }
> EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
>
> @@ -886,6 +923,8 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
> {
> struct device *dport_dev = dport->dport_dev;
> struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport_dev);
> + struct pci_dev *pdev = to_pci_dev(dport_dev);
> + struct cxl_port *port;
>
> dport->reg_map.host = dport_dev;
> if (dport->rch && host_bridge->native_aer) {
> @@ -901,9 +940,25 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
> }
>
> if (cxl_map_component_regs(&dport->reg_map, &dport->regs.component,
> - BIT(CXL_CM_CAP_CAP_ID_RAS)))
> + BIT(CXL_CM_CAP_CAP_ID_RAS))) {
> dev_err(dport_dev, "Failed to map RAS capability\n");
> + mutex_unlock(&ras_init_mutex);
> + return;
> + }
> mutex_unlock(&ras_init_mutex);
> +
> + if (dport->rch)
> + return;
> +
> + port = find_cxl_port(dport_dev, NULL);
> + if (!port) {
> + dev_err(dport_dev, "Failed to find upstream port\n");
> + return;
> + }
> +
> + cxl_assign_port_error_handlers(pdev);
> + devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
> + put_device(&port->dev);
> }
> EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 16/17] PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch Ports
2025-02-11 19:24 ` [PATCH v7 16/17] PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch Ports Terry Bowman
2025-02-11 20:25 ` Bjorn Helgaas
@ 2025-02-12 0:40 ` Dave Jiang
2025-02-14 2:35 ` Dan Williams
2 siblings, 0 replies; 94+ messages in thread
From: Dave Jiang @ 2025-02-12 0:40 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/25 12:24 PM, Terry Bowman wrote:
> The AER service driver enables PCIe Uncorrectable Internal Errors (UIE) and
> Correctable Internal errors (CIE) for CXL Root Ports. The UIE and CIE are
> used in reporting CXL Protocol Errors. The same UIE/CIE enablement is
> needed for CXL Upstream Switch Ports and CXL Downstream Switch Ports
> inorder to notify the associated Root Port and OS.[1]
>
> Export the AER service driver's pci_aer_unmask_internal_errors() function
> to CXL namespace.
>
> Remove the function's dependency on the CONFIG_PCIEAER_CXL kernel config
> because it is now an exported function.
>
> Call pci_aer_unmask_internal_errors() during RAS initialization in:
> cxl_uport_init_ras_reporting() and cxl_dport_init_ras_reporting().
>
> [1] PCIe Base Spec r6.2-1.0, 6.2.3.2.2 Masking Individual Errors
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> drivers/cxl/core/pci.c | 2 ++
> drivers/pci/pcie/aer.c | 3 ++-
> include/linux/aer.h | 1 +
> 3 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 03ae21a944e0..36e686a31045 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -912,6 +912,7 @@ void cxl_uport_init_ras_reporting(struct cxl_port *port)
>
> cxl_assign_port_error_handlers(pdev);
> devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
> + pci_aer_unmask_internal_errors(pdev);
> }
> EXPORT_SYMBOL_NS_GPL(cxl_uport_init_ras_reporting, "CXL");
>
> @@ -959,6 +960,7 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
> cxl_assign_port_error_handlers(pdev);
> devm_add_action_or_reset(&port->dev, cxl_clear_port_error_handlers, pdev);
> put_device(&port->dev);
> + pci_aer_unmask_internal_errors(pdev);
> }
> EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index ee38db08d005..8e3a60411610 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -948,7 +948,7 @@ static bool find_source_device(struct pci_dev *parent,
> * Note: AER must be enabled and supported by the device which must be
> * checked in advance, e.g. with pcie_aer_is_native().
> */
> -static void pci_aer_unmask_internal_errors(struct pci_dev *dev)
> +void pci_aer_unmask_internal_errors(struct pci_dev *dev)
> {
> int aer = dev->aer_cap;
> u32 mask;
> @@ -961,6 +961,7 @@ static void pci_aer_unmask_internal_errors(struct pci_dev *dev)
> mask &= ~PCI_ERR_COR_INTERNAL;
> pci_write_config_dword(dev, aer + PCI_ERR_COR_MASK, mask);
> }
> +EXPORT_SYMBOL_NS_GPL(pci_aer_unmask_internal_errors, "CXL");
>
> static bool is_cxl_mem_dev(struct pci_dev *dev)
> {
> diff --git a/include/linux/aer.h b/include/linux/aer.h
> index 947b63091902..a54545796edc 100644
> --- a/include/linux/aer.h
> +++ b/include/linux/aer.h
> @@ -61,5 +61,6 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
> int cper_severity_to_aer(int cper_severity);
> void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
> int severity, struct aer_capability_regs *aer_regs);
> +void pci_aer_unmask_internal_errors(struct pci_dev *dev);
> #endif //_AER_H_
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers
2025-02-11 19:24 ` [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers Terry Bowman
2025-02-11 22:40 ` Dave Jiang
@ 2025-02-12 1:23 ` Dan Williams
2025-02-13 15:43 ` Bowman, Terry
2025-02-12 22:28 ` Alison Schofield
2 siblings, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-12 1:23 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> The CXL mem driver (cxl_mem) currently maps and caches a pointer to RAS
> registers for the endpoint's Root Port. The same needs to be done for
> each of the CXL Downstream Switch Ports and CXL Root Ports found between
> the endpoint and CXL Host Bridge.
>
> Introduce cxl_init_ep_ports_aer() to be called for each CXL Port in the
> sub-topology between the endpoint and the CXL Host Bridge. This function
> will determine if there are CXL Downstream Switch Ports or CXL Root Ports
> associated with this Port. The same check will be added in the future for
> upstream switch ports.
>
> Move the RAS register map logic from cxl_dport_map_ras() into
> cxl_dport_init_ras_reporting(). This eliminates the need for the helper
> function, cxl_dport_map_ras().
Not sure about the motivation here...
> cxl_init_ep_ports_aer() calls cxl_dport_init_ras_reporting() to map
> the RAS registers for CXL Downstream Switch Ports and CXL Root Ports.
Ok, makes sense...
> cxl_dport_init_ras_reporting() must check for previously mapped registers
> before mapping. This is required because multiple Endpoints under a CXL
> switch may share an upstream CXL Root Port, CXL Downstream Switch Port,
> or CXL Downstream Switch Port. Ensure the RAS registers are only mapped
> once.
Sounds broken. Every device upstream-port only has one downstream port.
A CXL switch config looks like this:
│
┌──────────┼────────────┐
│SWITCH ┌┴─┐ │
│ │UP│ │
│ └─┬┘ │
│ ┌──────┼─────┐ │
│ │ │ │ │
│ ┌┴─┐ ┌─┴┐ ┌─┴┐ │
│ │DP│ │DP│ │DP│ │
│ └┬─┘ └─┬┘ └─┬┘ │
└────┼──────┼─────┼─────┘
┌┴─┐ ┌─┴┐ ┌─┴┐
│EP│ │EP│ │EP│
└──┘ └──┘ └──┘
...so how can an endpoint ever find that its immediate parent downstream
port has already been mapped?
> Introduce a mutex for synchronizing accesses to the cached RAS mapping.
I suspect the motivation for the lock and "previously mapped" check was
due to noticing that the ras registers are not being unmapped, but
that's due to a devm bug below.
Even if it were the case that multiple resources need to share 1 devm
mapping, that would need to look something like the logic around
cxl_detach_ep(). In that arrangement, the first endpoint in the door
sets up the 'struct cxl_port' and its 'struct cxl_dport' instances, and
the last endpoint out the door tears it all down and turns off the
lights.
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
> ---
> drivers/cxl/core/pci.c | 42 ++++++++++++++++++++----------------------
> drivers/cxl/cxl.h | 6 ++----
> drivers/cxl/mem.c | 31 +++++++++++++++++++++++++++++--
> 3 files changed, 51 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index a5c65f79db18..143c853a52c4 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -24,6 +24,8 @@ static unsigned short media_ready_timeout = 60;
> module_param(media_ready_timeout, ushort, 0644);
> MODULE_PARM_DESC(media_ready_timeout, "seconds to wait for media ready");
>
> +static DEFINE_MUTEX(ras_init_mutex);
> +
> struct cxl_walk_context {
> struct pci_bus *bus;
> struct cxl_port *port;
> @@ -749,18 +751,6 @@ static void cxl_dport_map_rch_aer(struct cxl_dport *dport)
> }
> }
>
> -static void cxl_dport_map_ras(struct cxl_dport *dport)
> -{
> - struct cxl_register_map *map = &dport->reg_map;
> - struct device *dev = dport->dport_dev;
> -
> - if (!map->component_map.ras.valid)
> - dev_dbg(dev, "RAS registers not found\n");
> - else if (cxl_map_component_regs(map, &dport->regs.component,
> - BIT(CXL_CM_CAP_CAP_ID_RAS)))
> - dev_dbg(dev, "Failed to map RAS capability.\n");
> -}
> -
> static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
> {
> void __iomem *aer_base = dport->regs.dport_aer;
> @@ -788,22 +778,30 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
> /**
> * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
> * @dport: the cxl_dport that needs to be initialized
> - * @host: host device for devm operations
> */
> -void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
> +void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
> {
> - dport->reg_map.host = host;
> - cxl_dport_map_ras(dport);
> -
> - if (dport->rch) {
> - struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport->dport_dev);
> -
> - if (!host_bridge->native_aer)
> - return;
> + struct device *dport_dev = dport->dport_dev;
> + struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport_dev);
>
> + dport->reg_map.host = dport_dev;
This seems to be confused about how devm works. @host is passed in
because the cxl_memdev instance being probed in cxl_mem_probe() is doing
setup work on behalf of @dport_dev.
When the cxl_memdev goes through a ->remove() event, unbind from
cxl_mem, it tears down that mapping.
However, when using @dport_dev as the devm host, that mapping will not
be torn down until either the @dport_dev goes through a ->remove() event
or the device is unregistered altogether. There is no CXL subsystem
coordination with a driver for @dport_dev. The PCIe portdrv might have
an interest in it, but CXL can not depend on portdrv to map CXL
registers or keep the device bound while CXL has an interest those
registers. The devres_release_all() triggered by a
"device_del(@dport_dev)" is also uncoordinated with any CXL interest. In
general, it is a devm anti-pattern to depend on a device_del() event to
trigger devres_release_all().
> + if (dport->rch && host_bridge->native_aer) {
> cxl_dport_map_rch_aer(dport);
> cxl_disable_rch_root_ints(dport);
> }
> +
> + /* dport may have more than 1 downstream EP. Check if already mapped. */
> + mutex_lock(&ras_init_mutex);
I suspect this lock and check got added to workaround "Failed to request
region" messages coming out of devm_cxl_iomap_block() in testing? Per
above, that's not "more than 1 downstream EPi", that's "failure to clean
up the last mapping for the next cxl_mem_probe() event of the same
endpoint".
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
2025-02-11 19:24 ` [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream " Terry Bowman
2025-02-11 23:02 ` Dave Jiang
@ 2025-02-12 2:00 ` Dan Williams
2025-02-14 19:46 ` Bowman, Terry
2025-02-14 15:15 ` Jonathan Cameron
2 siblings, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-12 2:00 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
>
> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
> pointer to the CXL Upstream Port's mapped RAS registers.
>
> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
> register mapping. This is similar to the existing
> cxl_dport_init_ras_reporting() but for USP devices.
>
> The USP may have multiple downstream endpoints. Before mapping RAS
> registers check if the registers are already mapped.
Yes, now this sharing makes sense, but the ras_init_mutex +
cxl_init_ep_ports_aer() approach to solving it is broken.
> Introduce a mutex for synchronizing accesses to the cached RAS
> mapping.
In this case, especially for VH configs, you should just be able to map
the RAS registers once from cxl_endpoint_port_probe(). That will
naturally only be called once when the first endpoint arrives, and will
never be torn down until the last cxl_detach_ep() event triggers
delete_switch_port().
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 14/17] cxl/pci: Update CXL Port RAS logging to also display PCIe SBDF
2025-02-12 0:21 ` Dave Jiang
@ 2025-02-12 16:20 ` Bowman, Terry
0 siblings, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-02-12 16:20 UTC (permalink / raw)
To: Dave Jiang, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/2025 6:21 PM, Dave Jiang wrote:
>
> On 2/11/25 12:24 PM, Terry Bowman wrote:
>> CXL RAS errors are currently logged using the associated CXL port's name
>> returned from devname(). They are typically named with 'port1', 'port2',
>> etc. to indicate the hierarchial location in the CXL topology. But, this
>> doesn't clearly indicate the CXL card or slot reporting the error.
>>
>> Update the logging to also log the corresponding PCIe devname. This will
>> give a PCIe SBDF or ACPI object name (in case of CXL HB). This will provide
>> details helping users understand which physical slot and card has the
>> error.
>>
>> Below is example output after making these changes.
>>
>> Correctable error example output:
>> cxl_port_aer_correctable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status='Received Error From Physical Layer'
>>
>> Uncorrectable error example output:
>> cxl_port_aer_uncorrectable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Error'
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> I wonder if there's any benefit in identifying if the PCIe device is USP or DSP...
>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
That would be nice for the user. I'll add it to the TODO list.
Thanks for reviewing.
Terry
>> ---
>> drivers/cxl/core/pci.c | 39 +++++++++++++++++++------------------
>> drivers/cxl/core/trace.h | 42 +++++++++++++++++++++++++---------------
>> 2 files changed, 46 insertions(+), 35 deletions(-)
>>
>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>> index 9a3090dae46a..f154dcf6dfda 100644
>> --- a/drivers/cxl/core/pci.c
>> +++ b/drivers/cxl/core/pci.c
>> @@ -652,14 +652,14 @@ void read_cdat_data(struct cxl_port *port)
>> }
>> EXPORT_SYMBOL_NS_GPL(read_cdat_data, "CXL");
>>
>> -static void __cxl_handle_cor_ras(struct device *dev,
>> +static void __cxl_handle_cor_ras(struct device *cxl_dev, struct device *pcie_dev,
>> void __iomem *ras_base)
>> {
>> void __iomem *addr;
>> u32 status;
>>
>> if (!ras_base) {
>> - dev_warn_once(dev, "CXL RAS register block is not mapped");
>> + dev_warn_once(cxl_dev, "CXL RAS register block is not mapped");
>> return;
>> }
>>
>> @@ -669,15 +669,15 @@ static void __cxl_handle_cor_ras(struct device *dev,
>> return;
>> writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
>>
>> - if (is_cxl_memdev(dev))
>> - trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
>> - else if (is_cxl_port(dev))
>> - trace_cxl_port_aer_correctable_error(dev, status);
>> + if (is_cxl_memdev(cxl_dev))
>> + trace_cxl_aer_correctable_error(to_cxl_memdev(cxl_dev), status);
>> + else if (is_cxl_port(cxl_dev))
>> + trace_cxl_port_aer_correctable_error(cxl_dev, pcie_dev, status);
>> }
>>
>> static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
>> {
>> - return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
>> + return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, NULL, cxlds->regs.ras);
>> }
>>
>> /* CXL spec rev3.0 8.2.4.16.1 */
>> @@ -701,7 +701,8 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)
>> * Log the state of the RAS status registers and prepare them to log the
>> * next error status. Return 1 if reset needed.
>> */
>> -static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>> +static pci_ers_result_t __cxl_handle_ras(struct device *cxl_dev, struct device *pcie_dev,
>> + void __iomem *ras_base)
>> {
>> u32 hl[CXL_HEADERLOG_SIZE_U32];
>> void __iomem *addr;
>> @@ -709,7 +710,7 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
>> u32 fe;
>>
>> if (!ras_base) {
>> - dev_warn_once(dev, "CXL RAS register block is not mapped");
>> + dev_warn_once(cxl_dev, "CXL RAS register block is not mapped");
>> return PCI_ERS_RESULT_NONE;
>> }
>>
>> @@ -730,10 +731,10 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
>> }
>>
>> header_log_copy(ras_base, hl);
>> - if (is_cxl_memdev(dev))
>> - trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
>> - else if (is_cxl_port(dev))
>> - trace_cxl_port_aer_uncorrectable_error(dev, status, fe, hl);
>> + if (is_cxl_memdev(cxl_dev))
>> + trace_cxl_aer_uncorrectable_error(to_cxl_memdev(cxl_dev), status, fe, hl);
>> + else if (is_cxl_port(cxl_dev))
>> + trace_cxl_port_aer_uncorrectable_error(cxl_dev, pcie_dev, status, fe, hl);
>>
>> writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
>>
>> @@ -742,7 +743,7 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
>>
>> static bool cxl_handle_endpoint_ras(struct cxl_dev_state *cxlds)
>> {
>> - return __cxl_handle_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
>> + return __cxl_handle_ras(&cxlds->cxlmd->dev, NULL, cxlds->regs.ras);
>> }
>>
>> #ifdef CONFIG_PCIEAER_CXL
>> @@ -814,7 +815,7 @@ static void __iomem *cxl_pci_port_ras(struct pci_dev *pdev, struct device **dev)
>> struct cxl_dport *dport = NULL;
>>
>> port = find_cxl_port(&pdev->dev, &dport);
>> - if (!port) {
>> + if (!port || !is_cxl_port(&port->dev)) {
>> pci_err(pdev, "Failed to find root/dport in CXL topology\n");
>> return NULL;
>> }
>> @@ -848,7 +849,7 @@ static void cxl_port_cor_error_detected(struct pci_dev *pdev)
>> struct device *dev;
>> void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
>>
>> - __cxl_handle_cor_ras(dev, ras_base);
>> + __cxl_handle_cor_ras(dev, &pdev->dev, ras_base);
>> }
>>
>> static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
>> @@ -856,7 +857,7 @@ static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
>> struct device *dev;
>> void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
>>
>> - return __cxl_handle_ras(dev, ras_base);
>> + return __cxl_handle_ras(dev, &pdev->dev, ras_base);
>> }
>>
>> void cxl_uport_init_ras_reporting(struct cxl_port *port)
>> @@ -909,13 +910,13 @@ EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
>> static void cxl_handle_rdport_cor_ras(struct cxl_dev_state *cxlds,
>> struct cxl_dport *dport)
>> {
>> - return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, dport->regs.ras);
>> + return __cxl_handle_cor_ras(&cxlds->cxlmd->dev, NULL, dport->regs.ras);
>> }
>>
>> static bool cxl_handle_rdport_ras(struct cxl_dev_state *cxlds,
>> struct cxl_dport *dport)
>> {
>> - return __cxl_handle_ras(&cxlds->cxlmd->dev, dport->regs.ras);
>> + return __cxl_handle_ras(&cxlds->cxlmd->dev, NULL, dport->regs.ras);
>> }
>>
>> /*
>> diff --git a/drivers/cxl/core/trace.h b/drivers/cxl/core/trace.h
>> index b536233ac210..a74803f4aa22 100644
>> --- a/drivers/cxl/core/trace.h
>> +++ b/drivers/cxl/core/trace.h
>> @@ -49,18 +49,22 @@
>> )
>>
>> TRACE_EVENT(cxl_port_aer_uncorrectable_error,
>> - TP_PROTO(struct device *dev, u32 status, u32 fe, u32 *hl),
>> - TP_ARGS(dev, status, fe, hl),
>> + TP_PROTO(struct device *cxl_dev, struct device *pcie_dev, u32 status, u32 fe, u32 *hl),
>> + TP_ARGS(cxl_dev, pcie_dev, status, fe, hl),
>> TP_STRUCT__entry(
>> - __string(devname, dev_name(dev))
>> - __string(parent, dev_name(dev->parent))
>> + __string(cxl_name, dev_name(cxl_dev))
>> + __string(cxl_parent_name, dev_name(cxl_dev->parent))
>> + __string(pcie_name, dev_name(pcie_dev))
>> + __string(pcie_parent_name, dev_name(pcie_dev->parent))
>> __field(u32, status)
>> __field(u32, first_error)
>> __array(u32, header_log, CXL_HEADERLOG_SIZE_U32)
>> ),
>> TP_fast_assign(
>> - __assign_str(devname);
>> - __assign_str(parent);
>> + __assign_str(cxl_name);
>> + __assign_str(cxl_parent_name);
>> + __assign_str(pcie_name);
>> + __assign_str(pcie_parent_name);
>> __entry->status = status;
>> __entry->first_error = fe;
>> /*
>> @@ -69,8 +73,9 @@ TRACE_EVENT(cxl_port_aer_uncorrectable_error,
>> */
>> memcpy(__entry->header_log, hl, CXL_HEADERLOG_SIZE);
>> ),
>> - TP_printk("device=%s parent=%s status: '%s' first_error: '%s'",
>> - __get_str(devname), __get_str(parent),
>> + TP_printk("device=%s (%s) parent=%s (%s) status: '%s' first_error: '%s'",
>> + __get_str(cxl_name), __get_str(pcie_name),
>> + __get_str(cxl_parent_name), __get_str(pcie_parent_name),
>> show_uc_errs(__entry->status),
>> show_uc_errs(__entry->first_error)
>> )
>> @@ -125,20 +130,25 @@ TRACE_EVENT(cxl_aer_uncorrectable_error,
>> )
>>
>> TRACE_EVENT(cxl_port_aer_correctable_error,
>> - TP_PROTO(struct device *dev, u32 status),
>> - TP_ARGS(dev, status),
>> + TP_PROTO(struct device *cxl_dev, struct device *pcie_dev, u32 status),
>> + TP_ARGS(cxl_dev, pcie_dev, status),
>> TP_STRUCT__entry(
>> - __string(devname, dev_name(dev))
>> - __string(parent, dev_name(dev->parent))
>> + __string(cxl_name, dev_name(cxl_dev))
>> + __string(cxl_parent_name, dev_name(cxl_dev->parent))
>> + __string(pcie_name, dev_name(pcie_dev))
>> + __string(pcie_parent_name, dev_name(pcie_dev->parent))
>> __field(u32, status)
>> ),
>> TP_fast_assign(
>> - __assign_str(devname);
>> - __assign_str(parent);
>> + __assign_str(cxl_name);
>> + __assign_str(cxl_parent_name);
>> + __assign_str(pcie_name);
>> + __assign_str(pcie_parent_name);
>> __entry->status = status;
>> ),
>> - TP_printk("device=%s parent=%s status='%s'",
>> - __get_str(devname), __get_str(parent),
>> + TP_printk("device=%s (%s) parent=%s (%s) status='%s'",
>> + __get_str(cxl_name), __get_str(pcie_name),
>> + __get_str(cxl_parent_name), __get_str(pcie_parent_name),
>> show_ce_errs(__entry->status)
>> )
>> );
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 13/17] cxl/pci: Add trace logging for CXL PCIe Port RAS errors
2025-02-12 0:17 ` Dave Jiang
2025-02-12 0:19 ` Dave Jiang
@ 2025-02-12 16:23 ` Bowman, Terry
1 sibling, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-02-12 16:23 UTC (permalink / raw)
To: Dave Jiang, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/2025 6:17 PM, Dave Jiang wrote:
>
> On 2/11/25 12:24 PM, Terry Bowman wrote:
>> The CXL drivers use kernel trace functions for logging Endpoint and
>> Restricted CXL host (RCH) Downstream Port RAS errors. Similar functionality
>> is required for CXL Root Ports, CXL Downstream Switch Ports, and CXL
>> Upstream Switch Ports.
>>
>> Introduce trace logging functions for both RAS correctable and
>> uncorrectable errors specific to CXL PCIe Ports. Additionally, update
>> the CXL Port Protocol Error handlers to invoke these new trace functions.
>>
>> Examples of the output from these changes is below.
>>
>> Correctable error:
>> cxl_port_aer_correctable_error: device=port1 parent=root0 status='Received Error From Physical Layer'
> Is there any way to identify if the error comes from the USP or DSP? Specifically the PCI devname for the specific port?
Yes, the PCIe device type can be converted to a string for logging (USP, DSP, RP, etc).
Terry
>> Uncorrectable error:
>> cxl_port_aer_uncorrectable_error: device=port1 parent=root0 status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Erro'
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> Reviewed-by: Alejandro Lucero <alucerop@amd.com>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
>
>> ---
>> drivers/cxl/core/pci.c | 4 ++++
>> drivers/cxl/core/trace.h | 47 ++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 51 insertions(+)
>>
>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>> index 3f13d9dfb610..9a3090dae46a 100644
>> --- a/drivers/cxl/core/pci.c
>> +++ b/drivers/cxl/core/pci.c
>> @@ -671,6 +671,8 @@ static void __cxl_handle_cor_ras(struct device *dev,
>>
>> if (is_cxl_memdev(dev))
>> trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
>> + else if (is_cxl_port(dev))
>> + trace_cxl_port_aer_correctable_error(dev, status);
>> }
>>
>> static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
>> @@ -730,6 +732,8 @@ static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_b
>> header_log_copy(ras_base, hl);
>> if (is_cxl_memdev(dev))
>> trace_cxl_aer_uncorrectable_error(to_cxl_memdev(dev), status, fe, hl);
>> + else if (is_cxl_port(dev))
>> + trace_cxl_port_aer_uncorrectable_error(dev, status, fe, hl);
>>
>> writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
>>
>> diff --git a/drivers/cxl/core/trace.h b/drivers/cxl/core/trace.h
>> index cea706b683b5..b536233ac210 100644
>> --- a/drivers/cxl/core/trace.h
>> +++ b/drivers/cxl/core/trace.h
>> @@ -48,6 +48,34 @@
>> { CXL_RAS_UC_IDE_RX_ERR, "IDE Rx Error" } \
>> )
>>
>> +TRACE_EVENT(cxl_port_aer_uncorrectable_error,
>> + TP_PROTO(struct device *dev, u32 status, u32 fe, u32 *hl),
>> + TP_ARGS(dev, status, fe, hl),
>> + TP_STRUCT__entry(
>> + __string(devname, dev_name(dev))
>> + __string(parent, dev_name(dev->parent))
>> + __field(u32, status)
>> + __field(u32, first_error)
>> + __array(u32, header_log, CXL_HEADERLOG_SIZE_U32)
>> + ),
>> + TP_fast_assign(
>> + __assign_str(devname);
>> + __assign_str(parent);
>> + __entry->status = status;
>> + __entry->first_error = fe;
>> + /*
>> + * Embed the 512B headerlog data for user app retrieval and
>> + * parsing, but no need to print this in the trace buffer.
>> + */
>> + memcpy(__entry->header_log, hl, CXL_HEADERLOG_SIZE);
>> + ),
>> + TP_printk("device=%s parent=%s status: '%s' first_error: '%s'",
>> + __get_str(devname), __get_str(parent),
>> + show_uc_errs(__entry->status),
>> + show_uc_errs(__entry->first_error)
>> + )
>> +);
>> +
>> TRACE_EVENT(cxl_aer_uncorrectable_error,
>> TP_PROTO(const struct cxl_memdev *cxlmd, u32 status, u32 fe, u32 *hl),
>> TP_ARGS(cxlmd, status, fe, hl),
>> @@ -96,6 +124,25 @@ TRACE_EVENT(cxl_aer_uncorrectable_error,
>> { CXL_RAS_CE_PHYS_LAYER_ERR, "Received Error From Physical Layer" } \
>> )
>>
>> +TRACE_EVENT(cxl_port_aer_correctable_error,
>> + TP_PROTO(struct device *dev, u32 status),
>> + TP_ARGS(dev, status),
>> + TP_STRUCT__entry(
>> + __string(devname, dev_name(dev))
>> + __string(parent, dev_name(dev->parent))
>> + __field(u32, status)
>> + ),
>> + TP_fast_assign(
>> + __assign_str(devname);
>> + __assign_str(parent);
>> + __entry->status = status;
>> + ),
>> + TP_printk("device=%s parent=%s status='%s'",
>> + __get_str(devname), __get_str(parent),
>> + show_ce_errs(__entry->status)
>> + )
>> +);
>> +
>> TRACE_EVENT(cxl_aer_correctable_error,
>> TP_PROTO(const struct cxl_memdev *cxlmd, u32 status),
>> TP_ARGS(cxlmd, status),
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors
2025-02-12 0:11 ` Dave Jiang
@ 2025-02-12 16:34 ` Bowman, Terry
0 siblings, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-02-12 16:34 UTC (permalink / raw)
To: Dave Jiang, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/2025 6:11 PM, Dave Jiang wrote:
>
> On 2/11/25 12:24 PM, Terry Bowman wrote:
>> Introduce correctable and uncorrectable (UCE) CXL PCIe Port Protocol Error
>> handlers.
>>
>> The handlers will be called with a 'struct pci_dev' parameter
>> indicating the CXL Port device requiring handling. The CXL PCIe Port
>> device's underlying 'struct device' will match the port device in the
>> CXL topology.
>>
>> Use the PCIe Port's device object to find the matching CXL Upstream Switch
>> Port, CXL Downstream Switch Port, or CXL Root Port in the CXL topology. The
>> matching CXL Port device should contain a cached reference to the RAS
>> register block. The cached RAS block will be used in handling the error.
>>
>> Invoke the existing __cxl_handle_ras() or __cxl_handle_cor_ras() using
>> a reference to the RAS registers as a parameter. These functions will use
>> the RAS register reference to indicate an error and clear the device's RAS
>> status.
>>
>> Update __cxl_handle_ras() to return PCI_ERS_RESULT_PANIC in the case
>> an error is present in the RAS status. Otherwise, return
>> PCI_ERS_RESULT_NONE.
> Maybe a comment on why the change?
Ok.
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> ---
>> drivers/cxl/core/pci.c | 81 +++++++++++++++++++++++++++++++++++++++---
>> 1 file changed, 77 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>> index af809e7cbe3b..3f13d9dfb610 100644
>> --- a/drivers/cxl/core/pci.c
>> +++ b/drivers/cxl/core/pci.c
>> @@ -699,7 +699,7 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)
>> * Log the state of the RAS status registers and prepare them to log the
>> * next error status. Return 1 if reset needed.
>> */
>> -static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>> +static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>> {
>> u32 hl[CXL_HEADERLOG_SIZE_U32];
>> void __iomem *addr;
>> @@ -708,13 +708,13 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>>
>> if (!ras_base) {
>> dev_warn_once(dev, "CXL RAS register block is not mapped");
>> - return false;
>> + return PCI_ERS_RESULT_NONE;
>> }
>>
>> addr = ras_base + CXL_RAS_UNCORRECTABLE_STATUS_OFFSET;
>> status = readl(addr);
>> if (!(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK))
>> - return false;
>> + return PCI_ERS_RESULT_NONE;
>>
>> /* If multiple errors, log header points to first error from ctrl reg */
>> if (hweight32(status) > 1) {
>> @@ -733,7 +733,7 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>>
>> writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
>>
>> - return true;
>> + return PCI_ERS_RESULT_PANIC;
>> }
>>
>> static bool cxl_handle_endpoint_ras(struct cxl_dev_state *cxlds)
>> @@ -782,6 +782,79 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>> writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
>> }
>>
>> +static int match_uport(struct device *dev, const void *data)
>> +{
>> + const struct device *uport_dev = data;
>> + struct cxl_port *port;
>> +
>> + if (!is_cxl_port(dev))
>> + return 0;
>> +
>> + port = to_cxl_port(dev);
>> +
>> + return port->uport_dev == uport_dev;
>> +}
>> +
>> +static void __iomem *cxl_pci_port_ras(struct pci_dev *pdev, struct device **dev)
>> +{
>> + void __iomem *ras_base;
>> +
>> + if (!pdev || !*dev) {
>> + pr_err("Failed, parameter is NULL");
>> + return NULL;
>> + }
>> +
>> + if ((pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) ||
>> + (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM)) {
> Can probably just do a switch block here for the type?
>
>> + struct cxl_port *port __free(put_cxl_port);
>> + struct cxl_dport *dport = NULL;
>> +
>> + port = find_cxl_port(&pdev->dev, &dport);
> Just declare port inline:
>
> struct cxl_port *port __free(put_cxl_port) =
> find_cxl_port(&pdev->dev, &dport);
>
>> + if (!port) {
>> + pci_err(pdev, "Failed to find root/dport in CXL topology\n");
>> + return NULL;
>> + }
>> +
>> + ras_base = dport ? dport->regs.ras : NULL;
>> + *dev = &port->dev;
>> + } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_UPSTREAM) {
>> + struct device *port_dev __free(put_device);
> same comment here as above
>
> DJ
Thanks Dave, I'll incorporate these changes into v8.
Terry
>> + struct cxl_port *port;
>> +
>> + port_dev = bus_find_device(&cxl_bus_type, NULL, &pdev->dev,
>> + match_uport);
>> + if (!port_dev || !is_cxl_port(port_dev)) {
>> + pci_err(pdev, "Failed to find uport in CXL topology\n");
>> + return NULL;
>> + }
>> +
>> + port = to_cxl_port(port_dev);
>> + ras_base = port ? port->uport_regs.ras : NULL;
>> + *dev = port_dev;
>> + } else {
>> + pci_err(pdev, "Unsupported device type\n");
>> + ras_base = NULL;
>> + }
>> +
>> + return ras_base;
>> +}
>> +
>> +static void cxl_port_cor_error_detected(struct pci_dev *pdev)
>> +{
>> + struct device *dev;
>> + void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
>> +
>> + __cxl_handle_cor_ras(dev, ras_base);
>> +}
>> +
>> +static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
>> +{
>> + struct device *dev;
>> + void __iomem *ras_base = cxl_pci_port_ras(pdev, &dev);
>> +
>> + return __cxl_handle_ras(dev, ras_base);
>> +}
>> +
>> void cxl_uport_init_ras_reporting(struct cxl_port *port)
>> {
>>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port()
2025-02-11 22:33 ` Dan Williams
@ 2025-02-12 19:07 ` Bowman, Terry
2025-02-12 19:51 ` Dan Williams
0 siblings, 1 reply; 94+ messages in thread
From: Bowman, Terry @ 2025-02-12 19:07 UTC (permalink / raw)
To: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/2025 4:33 PM, Dan Williams wrote:
> Terry Bowman wrote:
>> CXL and AER drivers need the ability to identify CXL devices and CXL port
>> devices.
>>
>> First, add set_pcie_cxl() with logic checking for CXL Flexbus DVSEC
>> presence. The CXL Flexbus DVSEC presence is used because it is required
>> for all the CXL PCIe devices.[1]
>>
>> Add boolean 'struct pci_dev::is_cxl' with the purpose to cache the CXL
>> Flexbus presence.
>>
>> Add pcie_is_cxl() as a macro to return 'struct pci_dev::is_cxl'.
>>
>> Add pcie_is_cxl_port() to check if a device is a CXL Root Port, CXL
>> Upstream Switch Port, or CXL Downstream Switch Port. Also, verify the
>> CXL Extensions DVSEC for Ports is present.[1]
>>
>> [1] CXL 3.1 Spec, 8.1.1 PCIe Designated Vendor-Specific Extended
>> Capability (DVSEC) ID Assignment, Table 8-2
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
>> Reviewed-by: Fan Ni <fan.ni@samsung.com>
>> ---
>> drivers/pci/pci.c | 13 +++++++++++++
>> drivers/pci/probe.c | 10 ++++++++++
>> include/linux/pci.h | 5 +++++
>> include/uapi/linux/pci_regs.h | 3 ++-
>> 4 files changed, 30 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>> index 869d204a70a3..a2d8b41dd043 100644
>> --- a/drivers/pci/pci.c
>> +++ b/drivers/pci/pci.c
>> @@ -5032,6 +5032,19 @@ static u16 cxl_port_dvsec(struct pci_dev *dev)
>> PCI_DVSEC_CXL_PORT);
>> }
>>
>> +inline bool pcie_is_cxl(struct pci_dev *pci_dev)
>> +{
>> + return pci_dev->is_cxl;
>> +}
>> +
>> +bool pcie_is_cxl_port(struct pci_dev *dev)
>> +{
>> + if (!pcie_is_cxl(dev))
>> + return false;
>> +
>> + return (cxl_port_dvsec(dev) > 0);
> At first I was concerned that this adds a capability list walk during
> error handling, but patch 17 takes pcie_is_cxl_port() out of the
> handles_cxl_errors() path.
>
> It is still used in the aer_probe() path which means enumeration can
> potentially race a CXL link up event.
>
> I think this is fine for now because the CXL core has the same top-down
> vs bottom-up race, and the CXL SBR code also shares the same race
> problem.
>
> A follow-on change needs to arrange for cxl_port_probe() to
> enable/disable internal errors, because that path knows that a link has
> been negotiated with an endpoint and that the CXL link details should be
> stable.
>
>> +}
>> +
>> static bool cxl_sbr_masked(struct pci_dev *dev)
>> {
>> u16 dvsec, reg;
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index b6536ed599c3..7737b9ce7a83 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -1676,6 +1676,14 @@ static void set_pcie_thunderbolt(struct pci_dev *dev)
>> dev->is_thunderbolt = 1;
>> }
>>
>> +static void set_pcie_cxl(struct pci_dev *dev)
>> +{
>> + u16 dvsec = pci_find_dvsec_capability(dev, PCI_VENDOR_ID_CXL,
>> + PCI_DVSEC_CXL_FLEXBUS);
>> + if (dvsec)
>> + dev->is_cxl = 1;
>> +}
> Similar race problem here as it is premature to check for this DVSEC on
> disconnected ports.
>
> For now, lets add a comment to include/uapi/linux/pci_regs.h along the
> lines of:
>
> diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
> index 3445c4970e4d..32df7abdd23c 100644
> --- a/include/uapi/linux/pci_regs.h
> +++ b/include/uapi/linux/pci_regs.h
> @@ -1208,7 +1208,13 @@
> #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL 0x00ff0000
> #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX 0xff000000
>
> -/* Compute Express Link (CXL r3.1, sec 8.1.5) */
> +/*
> + * Compute Express Link (CXL r3.1, sec 8.1)
> + *
> + * Note that CXL DVSEC id 3 and 7 to be ignored when the CXL link state
> + * is "disconnected" (CXL r3.1, sec 9.12.3). Re-enumerate these
> + * registers on downstream link-up events.
> + */
> #define PCI_DVSEC_CXL_PORT 3
> #define PCI_DVSEC_CXL_PORT_CTL 0x0c
> #define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR 0x00000001
>
> ...to at least remind our future selves that there is work to do here to
> make the implementation robust against hot-plug scenarios.
>
> With that you can add:
>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Ok, I will add the comment.
Would you like for me to add the enable/disable internal error logic to cxl_port_probe()? I can but want to confirm.
Thanks for reviewing.
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type
2025-02-11 23:47 ` Dan Williams
@ 2025-02-12 19:15 ` Bowman, Terry
2025-02-12 19:57 ` Dan Williams
0 siblings, 1 reply; 94+ messages in thread
From: Bowman, Terry @ 2025-02-12 19:15 UTC (permalink / raw)
To: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/2025 5:47 PM, Dan Williams wrote:
> Terry Bowman wrote:
>> The AER driver and aer_event tracing currently log 'PCIe Bus Type'
>> for all errors.
>>
>> Update the driver and aer_event tracing to log 'CXL Bus Type' for CXL
>> device errors.
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
>> Reviewed-by: Fan Ni <fan.ni@samsung.com>
>> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
>> Reviewed-by: Gregory Price <gourry@gourry.net>
>> ---
>> drivers/pci/pcie/aer.c | 14 ++++++++------
>> include/ras/ras_event.h | 9 ++++++---
>> 2 files changed, 14 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
>> index 6e8de77d0fc4..f99a1c6fb274 100644
>> --- a/drivers/pci/pcie/aer.c
>> +++ b/drivers/pci/pcie/aer.c
>> @@ -694,13 +694,14 @@ static void __aer_print_error(struct pci_dev *dev,
>>
>> void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
>> {
>> + const char *bus_type = pcie_is_cxl(dev) ? "CXL" : "PCIe";
> I was expecting that this would be more than just a CXL link check
> because CXL AER events are only a subset of the events that can trigger
> an AER interrupt on a CXL device.
>
> Also, with CXL protocol errors the TLP log is sourced from CXL RAS
> registers and is distinct from the PCIe ->tlp in 'struct aer_err_info'.
>
> All that to say that I think this patch probably wants to decorate the
> bus type in 'struct aer_err_info' and then use that rather than just the ->is_cxl
> flag of the device.
>
> In the interest of moving the patch set along perhaps just do something
> like this for now and circle back to make it more sophisticated later:
>
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 01e51db8d285..eed098c134a6 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -533,6 +533,7 @@ static inline bool pci_dev_test_and_set_removed(struct pci_dev *dev)
> struct aer_err_info {
> struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES];
> int error_dev_num;
> + bool is_cxl;
>
> unsigned int id:16;
>
> @@ -549,6 +550,11 @@ struct aer_err_info {
> struct pcie_tlp_log tlp; /* TLP Header */
> };
>
> +static inline const char *aer_err_bus(struct aer_err_info *info)
> +{
> + return info->is_cxl ? "CXL" : "PCIe";
> +}
> +
> int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info);
> void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index 508474e17183..405f15c878ff 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -1211,6 +1211,7 @@ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
> /* Must reset in this function */
> info->status = 0;
> info->tlp_header_valid = 0;
> + info->is_cxl = dev->is_cxl;
>
> /* The device might not support AER */
> if (!aer)
>
> Other than that, this patch looks good to me:
>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Ok. I can add is_cxl to 'struct aer_err_info'. Shall I set it by reading the
alternate protocol link state?
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port()
2025-02-12 19:07 ` Bowman, Terry
@ 2025-02-12 19:51 ` Dan Williams
0 siblings, 0 replies; 94+ messages in thread
From: Dan Williams @ 2025-02-12 19:51 UTC (permalink / raw)
To: Bowman, Terry, Dan Williams, linux-cxl, linux-kernel, linux-pci,
nifan.cxl, dave, jonathan.cameron, dave.jiang, alison.schofield,
vishal.l.verma, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Bowman, Terry wrote:
[..]
> >
> > Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Ok, I will add the comment.
>
> Would you like for me to add the enable/disable internal error logic to cxl_port_probe()? I can but want to confirm.
If it's quick, go ahead. Otherwise I think it is ok to leave it in
aer_probe() for now if only because this is not the only place in the
CXL stack that needs to be fixed up to honor the fact that DVSEC 3 and 7
are only reliable post link-up.
I.e. the other places I know of are:
- cxl_acpi: fails to probe for cachemem component registers on
disconnected root ports
- cxl_switch_port_probe(): enumerates all dports even though not all may
be link up yet
So, in the interest of moving this set forward, that wider fix can be
deferred to a later rework series that address all the dynamic DVSEC 3,7
issues.
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type
2025-02-12 19:15 ` Bowman, Terry
@ 2025-02-12 19:57 ` Dan Williams
2025-02-12 21:08 ` Bowman, Terry
0 siblings, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-12 19:57 UTC (permalink / raw)
To: Bowman, Terry, Dan Williams, linux-cxl, linux-kernel, linux-pci,
nifan.cxl, dave, jonathan.cameron, dave.jiang, alison.schofield,
vishal.l.verma, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Bowman, Terry wrote:
[..]
> > Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Ok. I can add is_cxl to 'struct aer_err_info'. Shall I set it by reading the
> alternate protocol link state?
I am thinking no because dev->is_cxl at least indicates that a CXL link
was up at some point, and racing CXL link down is not something the
error core can reasonably mitigate.
In the end I think that it should be something like:
info->is_cxl = dev->is_cxl && is_internal_error()
...on the expectation that a CXL device is unlikely to multiplex
internal errors across CXL protocol error events and device-specific
internal events. Even if a device *did* multiplex those I think it is
reasonable for the kernel to treat a device-specific UCE the same as a
CXL protocol UCE and panic the system.
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type
2025-02-12 19:57 ` Dan Williams
@ 2025-02-12 21:08 ` Bowman, Terry
2025-02-12 21:17 ` Lukas Wunner
0 siblings, 1 reply; 94+ messages in thread
From: Bowman, Terry @ 2025-02-12 21:08 UTC (permalink / raw)
To: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/12/2025 1:57 PM, Dan Williams wrote:
> Bowman, Terry wrote:
> [..]
>>> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
>> Ok. I can add is_cxl to 'struct aer_err_info'. Shall I set it by reading the
>> alternate protocol link state?
> I am thinking no because dev->is_cxl at least indicates that a CXL link
> was up at some point, and racing CXL link down is not something the
> error core can reasonably mitigate.
>
> In the end I think that it should be something like:
>
> info->is_cxl = dev->is_cxl && is_internal_error()
>
> ...on the expectation that a CXL device is unlikely to multiplex
> internal errors across CXL protocol error events and device-specific
> internal events. Even if a device *did* multiplex those I think it is
> reasonable for the kernel to treat a device-specific UCE the same as a
> CXL protocol UCE and panic the system.
Ok.
I found in using is_internal_error() (v5) a USP with fatal UCE will not have AER status
populated in aer_info structure, only the severity field is populated (see
aer_get_device_error_info()). The aer_info is not populated because concern reading
the USP's AER (config space) when the upstream link state is invalid. Calling
is_internal_error() in this case will return false because the uncorrectable internal error (UIE) bit is 0 and proceed to treat as a PCIe error.
How do you want to proceed to handle the UCE protocol error in this case?
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type
2025-02-12 21:08 ` Bowman, Terry
@ 2025-02-12 21:17 ` Lukas Wunner
0 siblings, 0 replies; 94+ messages in thread
From: Lukas Wunner @ 2025-02-12 21:17 UTC (permalink / raw)
To: Bowman, Terry
Cc: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, ming.li,
PradeepVineshReddy.Kodamati
On Wed, Feb 12, 2025 at 03:08:10PM -0600, Bowman, Terry wrote:
> I found in using is_internal_error() (v5) a USP with fatal UCE will not
> have AER status populated in aer_info structure, only the severity field
> is populated (see aer_get_device_error_info()). The aer_info is not
> populated because concern reading the USP's AER (config space) when
> the upstream link state is invalid. Calling is_internal_error() in this
> case will return false because the uncorrectable internal error (UIE) bit
> is 0 and proceed to treat as a PCIe error.
> How do you want to proceed to handle the UCE protocol error in this case?
Shuai Xue is proposing a solution in this pending patch:
https://lore.kernel.org/r/20250207093500.70885-5-xueshuai@linux.alibaba.com/
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 05/17] PCI/AER: Add CXL PCIe Port correctable error support in AER service driver
2025-02-11 23:58 ` Dan Williams
@ 2025-02-12 21:52 ` Bowman, Terry
0 siblings, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-02-12 21:52 UTC (permalink / raw)
To: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/2025 5:58 PM, Dan Williams wrote:
> Terry Bowman wrote:
>> The AER service driver supports handling Downstream Port Protocol Errors in
>> Restricted CXL host (RCH) mode also known as CXL1.1. It needs the same
>> functionality for CXL PCIe Ports operating in Virtual Hierarchy (VH)
>> mode.[1]
>>
>> CXL and PCIe Protocol Error handling have different requirements that
>> necessitate a separate handling path. The AER service driver may try to
>> recover PCIe uncorrectable non-fatal errors (UCE). The same recovery is not
>> suitable for CXL PCIe Port devices because of potential for system memory
>> corruption. Instead, CXL Protocol Error handling must use a kernel panic
>> in the case of a fatal or non-fatal UCE. The AER driver's PCIe Protocol
>> Error handling does not panic the kernel in response to a UCE.
>>
>> Introduce a separate path for CXL Protocol Error handling in the AER
>> service driver. This will allow CXL Protocol Errors to use CXL specific
>> handling instead of PCIe handling. Add the CXL specific changes without
>> affecting or adding functionality in the PCIe handling.
>>
>> Make this update alongside the existing Downstream Port RCH error handling
>> logic, extending support to CXL PCIe Ports in VH mode.
>>
>> Remove is_internal_error(). is_internal_error() was used to determine if
>> an AER error was a CXL error. Instead, now rely on pcie_is_cxl_port() to
>> indicate the error is a CXL error.
> Wait, pcie_is_cxl_port() in isolation is insufficient, right? In other
> words, I would expect that when the response may escalate to panic()
> that the code should be reasonably certain that this *is* a CXL error.
> At a minimum that is:
>
> pcie_is_cxl_port() && is_internal_error()
>
> ...or am I missing something that it makes it unlikely that a standard
> PCIe error or other internal error type will not be thrown by a
> pcie_is_cxl_port() device?
I thought it was sufficient. In the CXL path the AER is logged. The PCIe handlers are not
called but then again the portbus driver doesn't implement a CE handler and the UCE
handler only updates the return result. That applies to all port devices.
And obviously CXL RAS is logged in the CXL path. If the CXL device errors are
handled in the PCIe path then CXL RAS will not be logged.
I have changed directions to implement what you want. I'm only replying here
to explain why I implemented as I did.
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers
2025-02-11 19:24 ` [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers Terry Bowman
2025-02-11 22:40 ` Dave Jiang
2025-02-12 1:23 ` Dan Williams
@ 2025-02-12 22:28 ` Alison Schofield
2025-02-12 22:37 ` Bowman, Terry
2 siblings, 1 reply; 94+ messages in thread
From: Alison Schofield @ 2025-02-12 22:28 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, vishal.l.verma, dan.j.williams,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:34PM -0600, Terry Bowman wrote:
> The CXL mem driver (cxl_mem) currently maps and caches a pointer to RAS
> registers for the endpoint's Root Port. The same needs to be done for
> each of the CXL Downstream Switch Ports and CXL Root Ports found between
> the endpoint and CXL Host Bridge.
>
> Introduce cxl_init_ep_ports_aer() to be called for each CXL Port in the
> sub-topology between the endpoint and the CXL Host Bridge. This function
> will determine if there are CXL Downstream Switch Ports or CXL Root Ports
> associated with this Port. The same check will be added in the future for
> upstream switch ports.
>
> Move the RAS register map logic from cxl_dport_map_ras() into
> cxl_dport_init_ras_reporting(). This eliminates the need for the helper
> function, cxl_dport_map_ras().
>
> cxl_init_ep_ports_aer() calls cxl_dport_init_ras_reporting() to map
> the RAS registers for CXL Downstream Switch Ports and CXL Root Ports.
>
> cxl_dport_init_ras_reporting() must check for previously mapped registers
> before mapping. This is required because multiple Endpoints under a CXL
> switch may share an upstream CXL Root Port, CXL Downstream Switch Port,
> or CXL Downstream Switch Port. Ensure the RAS registers are only mapped
> once.
snip
> @@ -788,22 +778,30 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
> /**
> * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
> * @dport: the cxl_dport that needs to be initialized
> - * @host: host device for devm operations
> */
> -void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
> +void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
> {
With this change an update to cxl-test is needed.
This func was wrapped to make sure no mocked dports are sent to
cxl_dport_init_ras_reporting().
2c402bd2e85b ("cxl/test: Skip cxl_setup_parent_dport() for emulated dports")
This works for me:
diff --git a/tools/testing/cxl/test/mock.c b/tools/testing/cxl/test/mock.c
index af2594e4f35d..1252165bffba 100644
--- a/tools/testing/cxl/test/mock.c
+++ b/tools/testing/cxl/test/mock.c
@@ -299,13 +299,13 @@ void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port)
}
EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, "CXL");
-void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
+void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport)
{
int index;
struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
if (!ops || !ops->is_mock_port(dport->dport_dev))
- cxl_dport_init_ras_reporting(dport, host);
+ cxl_dport_init_ras_reporting(dport);
put_cxl_mock_ops(index);
}
snip to end
^ permalink raw reply related [flat|nested] 94+ messages in thread
* Re: [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers
2025-02-12 22:28 ` Alison Schofield
@ 2025-02-12 22:37 ` Bowman, Terry
0 siblings, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-02-12 22:37 UTC (permalink / raw)
To: Alison Schofield
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, vishal.l.verma, dan.j.williams,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/12/2025 4:28 PM, Alison Schofield wrote:
> On Tue, Feb 11, 2025 at 01:24:34PM -0600, Terry Bowman wrote:
>> The CXL mem driver (cxl_mem) currently maps and caches a pointer to RAS
>> registers for the endpoint's Root Port. The same needs to be done for
>> each of the CXL Downstream Switch Ports and CXL Root Ports found between
>> the endpoint and CXL Host Bridge.
>>
>> Introduce cxl_init_ep_ports_aer() to be called for each CXL Port in the
>> sub-topology between the endpoint and the CXL Host Bridge. This function
>> will determine if there are CXL Downstream Switch Ports or CXL Root Ports
>> associated with this Port. The same check will be added in the future for
>> upstream switch ports.
>>
>> Move the RAS register map logic from cxl_dport_map_ras() into
>> cxl_dport_init_ras_reporting(). This eliminates the need for the helper
>> function, cxl_dport_map_ras().
>>
>> cxl_init_ep_ports_aer() calls cxl_dport_init_ras_reporting() to map
>> the RAS registers for CXL Downstream Switch Ports and CXL Root Ports.
>>
>> cxl_dport_init_ras_reporting() must check for previously mapped registers
>> before mapping. This is required because multiple Endpoints under a CXL
>> switch may share an upstream CXL Root Port, CXL Downstream Switch Port,
>> or CXL Downstream Switch Port. Ensure the RAS registers are only mapped
>> once.
> snip
>
>> @@ -788,22 +778,30 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>> /**
>> * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
>> * @dport: the cxl_dport that needs to be initialized
>> - * @host: host device for devm operations
>> */
>> -void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
>> +void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
>> {
> With this change an update to cxl-test is needed.
> This func was wrapped to make sure no mocked dports are sent to
> cxl_dport_init_ras_reporting().
>
> 2c402bd2e85b ("cxl/test: Skip cxl_setup_parent_dport() for emulated dports")
>
> This works for me:
> diff --git a/tools/testing/cxl/test/mock.c b/tools/testing/cxl/test/mock.c
> index af2594e4f35d..1252165bffba 100644
> --- a/tools/testing/cxl/test/mock.c
> +++ b/tools/testing/cxl/test/mock.c
> @@ -299,13 +299,13 @@ void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port)
> }
> EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, "CXL");
>
> -void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
> +void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport)
> {
> int index;
> struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
>
> if (!ops || !ops->is_mock_port(dport->dport_dev))
> - cxl_dport_init_ras_reporting(dport, host);
> + cxl_dport_init_ras_reporting(dport);
>
> put_cxl_mock_ops(index);
> }
>
>
>
> snip to end
Thanks. I'll add this to the patchset.
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 10/17] cxl/pci: Add log message and add type check in existing RAS handlers
2025-02-11 19:24 ` [PATCH v7 10/17] cxl/pci: Add log message and add type check in existing RAS handlers Terry Bowman
2025-02-11 23:28 ` Dave Jiang
@ 2025-02-12 22:59 ` Dan Williams
2025-02-13 0:08 ` Bowman, Terry
1 sibling, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-12 22:59 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> The CXL RAS handlers do not currently log if the RAS registers are
> unmapped. This is needed in order to help debug CXL error handling. Update
> the CXL driver to log a warning message if the RAS register block is
> unmapped.
>
> Also, add type check before processing EP or RCH DP.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
> ---
> drivers/cxl/core/pci.c | 20 ++++++++++++++------
> 1 file changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 69bb030aa8e1..af809e7cbe3b 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -658,15 +658,19 @@ static void __cxl_handle_cor_ras(struct device *dev,
> void __iomem *addr;
> u32 status;
>
> - if (!ras_base)
> + if (!ras_base) {
> + dev_warn_once(dev, "CXL RAS register block is not mapped");
> return;
> + }
>
> addr = ras_base + CXL_RAS_CORRECTABLE_STATUS_OFFSET;
> status = readl(addr);
> - if (status & CXL_RAS_CORRECTABLE_STATUS_MASK) {
> - writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
> + if (!(status & CXL_RAS_CORRECTABLE_STATUS_MASK))
> + return;
> + writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
> +
> + if (is_cxl_memdev(dev))
> trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
I think trace_cxl_aer_correctable_error() should always fire and this
should somehow be unified with the CPER record trace-event for protocol
errors.
The only usage of @memdev in this trace is retrieving the device serial
number. If the device is not a memdev then print zero for the serial
number, or something like that.
In the end RAS daemon should only need to enable one trace event to get
protocol errors and header logs from ports or endpoints, either
natively, or via CPER.
> - }
> }
>
> static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
> @@ -702,8 +706,10 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
> u32 status;
> u32 fe;
>
> - if (!ras_base)
> + if (!ras_base) {
> + dev_warn_once(dev, "CXL RAS register block is not mapped");
Is this a "never can happen" print? It seems like an oversight in an
upper layer to get this far down error reporting without the registers
mapped.
Like maybe this is a bug in a driver that should crash, or the driver
should not be registering broken error handlers?
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 14/17] cxl/pci: Update CXL Port RAS logging to also display PCIe SBDF
2025-02-11 19:24 ` [PATCH v7 14/17] cxl/pci: Update CXL Port RAS logging to also display PCIe SBDF Terry Bowman
2025-02-12 0:21 ` Dave Jiang
@ 2025-02-12 23:30 ` Alison Schofield
2025-02-12 23:34 ` Bowman, Terry
1 sibling, 1 reply; 94+ messages in thread
From: Alison Schofield @ 2025-02-12 23:30 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, vishal.l.verma, dan.j.williams,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:41PM -0600, Terry Bowman wrote:
> CXL RAS errors are currently logged using the associated CXL port's name
> returned from devname(). They are typically named with 'port1', 'port2',
> etc. to indicate the hierarchial location in the CXL topology. But, this
> doesn't clearly indicate the CXL card or slot reporting the error.
>
> Update the logging to also log the corresponding PCIe devname. This will
> give a PCIe SBDF or ACPI object name (in case of CXL HB). This will provide
> details helping users understand which physical slot and card has the
> error.
>
> Below is example output after making these changes.
>
> Correctable error example output:
> cxl_port_aer_correctable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status='Received Error From Physical Layer'
>
> Uncorrectable error example output:
> cxl_port_aer_uncorrectable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Error'
snip
>
>
> TRACE_EVENT(cxl_port_aer_uncorrectable_error,
> - TP_PROTO(struct device *dev, u32 status, u32 fe, u32 *hl),
> - TP_ARGS(dev, status, fe, hl),
> + TP_PROTO(struct device *cxl_dev, struct device *pcie_dev, u32 status, u32 fe, u32 *hl),
> + TP_ARGS(cxl_dev, pcie_dev, status, fe, hl),
> TP_STRUCT__entry(
> - __string(devname, dev_name(dev))
> - __string(parent, dev_name(dev->parent))
> + __string(cxl_name, dev_name(cxl_dev))
> + __string(cxl_parent_name, dev_name(cxl_dev->parent))
> + __string(pcie_name, dev_name(pcie_dev))
> + __string(pcie_parent_name, dev_name(pcie_dev->parent))
I get the rename of devname->cxl_name and parent->cxl_parent_name
since now we have pcie names too. How about making those changes
in the previous patch where devname and parent are introduced. Then
this patch doesn't have any changes other than adding the pcie names.
Having said that, should/can this merge with the patch before it?
snip
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 14/17] cxl/pci: Update CXL Port RAS logging to also display PCIe SBDF
2025-02-12 23:30 ` Alison Schofield
@ 2025-02-12 23:34 ` Bowman, Terry
0 siblings, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-02-12 23:34 UTC (permalink / raw)
To: Alison Schofield
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, vishal.l.verma, dan.j.williams,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/12/2025 5:30 PM, Alison Schofield wrote:
> On Tue, Feb 11, 2025 at 01:24:41PM -0600, Terry Bowman wrote:
>> CXL RAS errors are currently logged using the associated CXL port's name
>> returned from devname(). They are typically named with 'port1', 'port2',
>> etc. to indicate the hierarchial location in the CXL topology. But, this
>> doesn't clearly indicate the CXL card or slot reporting the error.
>>
>> Update the logging to also log the corresponding PCIe devname. This will
>> give a PCIe SBDF or ACPI object name (in case of CXL HB). This will provide
>> details helping users understand which physical slot and card has the
>> error.
>>
>> Below is example output after making these changes.
>>
>> Correctable error example output:
>> cxl_port_aer_correctable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status='Received Error From Physical Layer'
>>
>> Uncorrectable error example output:
>> cxl_port_aer_uncorrectable_error: device=port1 (0000:0c:00.0) parent=root0 (pci0000:0c) status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Error'
> snip
>>
>> TRACE_EVENT(cxl_port_aer_uncorrectable_error,
>> - TP_PROTO(struct device *dev, u32 status, u32 fe, u32 *hl),
>> - TP_ARGS(dev, status, fe, hl),
>> + TP_PROTO(struct device *cxl_dev, struct device *pcie_dev, u32 status, u32 fe, u32 *hl),
>> + TP_ARGS(cxl_dev, pcie_dev, status, fe, hl),
>> TP_STRUCT__entry(
>> - __string(devname, dev_name(dev))
>> - __string(parent, dev_name(dev->parent))
>> + __string(cxl_name, dev_name(cxl_dev))
>> + __string(cxl_parent_name, dev_name(cxl_dev->parent))
>> + __string(pcie_name, dev_name(pcie_dev))
>> + __string(pcie_parent_name, dev_name(pcie_dev->parent))
> I get the rename of devname->cxl_name and parent->cxl_parent_name
> since now we have pcie names too. How about making those changes
> in the previous patch where devname and parent are introduced. Then
> this patch doesn't have any changes other than adding the pcie names.
>
> Having said that, should/can this merge with the patch before it?
>
>
> snip
Yes. I'll merge the 2 patches.
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 10/17] cxl/pci: Add log message and add type check in existing RAS handlers
2025-02-12 22:59 ` Dan Williams
@ 2025-02-13 0:08 ` Bowman, Terry
2025-02-14 15:28 ` Jonathan Cameron
0 siblings, 1 reply; 94+ messages in thread
From: Bowman, Terry @ 2025-02-13 0:08 UTC (permalink / raw)
To: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/12/2025 4:59 PM, Dan Williams wrote:
> Terry Bowman wrote:
>> The CXL RAS handlers do not currently log if the RAS registers are
>> unmapped. This is needed in order to help debug CXL error handling. Update
>> the CXL driver to log a warning message if the RAS register block is
>> unmapped.
>>
>> Also, add type check before processing EP or RCH DP.
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
>> Reviewed-by: Gregory Price <gourry@gourry.net>
>> ---
>> drivers/cxl/core/pci.c | 20 ++++++++++++++------
>> 1 file changed, 14 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>> index 69bb030aa8e1..af809e7cbe3b 100644
>> --- a/drivers/cxl/core/pci.c
>> +++ b/drivers/cxl/core/pci.c
>> @@ -658,15 +658,19 @@ static void __cxl_handle_cor_ras(struct device *dev,
>> void __iomem *addr;
>> u32 status;
>>
>> - if (!ras_base)
>> + if (!ras_base) {
>> + dev_warn_once(dev, "CXL RAS register block is not mapped");
>> return;
>> + }
>>
>> addr = ras_base + CXL_RAS_CORRECTABLE_STATUS_OFFSET;
>> status = readl(addr);
>> - if (status & CXL_RAS_CORRECTABLE_STATUS_MASK) {
>> - writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
>> + if (!(status & CXL_RAS_CORRECTABLE_STATUS_MASK))
>> + return;
>> + writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
>> +
>> + if (is_cxl_memdev(dev))
>> trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
> I think trace_cxl_aer_correctable_error() should always fire and this
> should somehow be unified with the CPER record trace-event for protocol
> errors.
>
> The only usage of @memdev in this trace is retrieving the device serial
> number. If the device is not a memdev then print zero for the serial
> number, or something like that.
>
> In the end RAS daemon should only need to enable one trace event to get
> protocol errors and header logs from ports or endpoints, either
> natively, or via CPER.
>
That would be: we use 'struct *device' instead of 'struct *cxl_memdev'
and pass serial# in as a parameter (0 in non-EP cases)?
>> - }
>> }
>>
>> static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
>> @@ -702,8 +706,10 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>> u32 status;
>> u32 fe;
>>
>> - if (!ras_base)
>> + if (!ras_base) {
>> + dev_warn_once(dev, "CXL RAS register block is not mapped");
> Is this a "never can happen" print? It seems like an oversight in an
> upper layer to get this far down error reporting without the registers
> mapped.
>
> Like maybe this is a bug in a driver that should crash, or the driver
> should not be registering broken error handlers?
Correct. The error handler assignment and enablement is gated by RAS mapping
in cxl_uport_init_ras_reporting() and cxl_dport_init_ras_reporting().
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers
2025-02-12 1:23 ` Dan Williams
@ 2025-02-13 15:43 ` Bowman, Terry
2025-02-14 21:24 ` Dan Williams
0 siblings, 1 reply; 94+ messages in thread
From: Bowman, Terry @ 2025-02-13 15:43 UTC (permalink / raw)
To: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/2025 7:23 PM, Dan Williams wrote:
> Terry Bowman wrote:
>> The CXL mem driver (cxl_mem) currently maps and caches a pointer to RAS
>> registers for the endpoint's Root Port. The same needs to be done for
>> each of the CXL Downstream Switch Ports and CXL Root Ports found between
>> the endpoint and CXL Host Bridge.
>>
>> Introduce cxl_init_ep_ports_aer() to be called for each CXL Port in the
>> sub-topology between the endpoint and the CXL Host Bridge. This function
>> will determine if there are CXL Downstream Switch Ports or CXL Root Ports
>> associated with this Port. The same check will be added in the future for
>> upstream switch ports.
>>
>> Move the RAS register map logic from cxl_dport_map_ras() into
>> cxl_dport_init_ras_reporting(). This eliminates the need for the helper
>> function, cxl_dport_map_ras().
> Not sure about the motivation here...
>
>> cxl_init_ep_ports_aer() calls cxl_dport_init_ras_reporting() to map
>> the RAS registers for CXL Downstream Switch Ports and CXL Root Ports.
> Ok, makes sense...
>
>> cxl_dport_init_ras_reporting() must check for previously mapped registers
>> before mapping. This is required because multiple Endpoints under a CXL
>> switch may share an upstream CXL Root Port, CXL Downstream Switch Port,
>> or CXL Downstream Switch Port. Ensure the RAS registers are only mapped
>> once.
> Sounds broken. Every device upstream-port only has one downstream port.
>
> A CXL switch config looks like this:
>
> │
> ┌──────────┼────────────┐
> │SWITCH ┌┴─┐ │
> │ │UP│ │
> │ └─┬┘ │
> │ ┌──────┼─────┐ │
> │ │ │ │ │
> │ ┌┴─┐ ┌─┴┐ ┌─┴┐ │
> │ │DP│ │DP│ │DP│ │
> │ └┬─┘ └─┬┘ └─┬┘ │
> └────┼──────┼─────┼─────┘
> ┌┴─┐ ┌─┴┐ ┌─┴┐
> │EP│ │EP│ │EP│
> └──┘ └──┘ └──┘
>
> ...so how can an endpoint ever find that its immediate parent downstream
> port has already been mapped?
┌─┴─┐
│RP1│
└─┬─┘
┌───────────┼───────────┐
│SWITCH ┌─┴─┐ │
│ │UP1│ │ RP1 - 0c:00.0
│ └─┬─┘ │ UP1 - 0d:00.0
│ ┌──────┼─────┐ │ DP1 - 0e:00.0
│ │ │ │ │
│ ┌─┴─┐ ┌─┴─┐ ┌─┴─┐ │
│ │DP1│ │DP2│ │DP3│ │
│ └─┬─┘ └─┬─┘ └─┬─┘ │
└────┼──────┼─────┼─────┘
┌─┴─┐ ┌─┴─┐ ┌─┴─┐
│EP1│ │EP2│ │EP3│
└───┘ └───┘ └───┘
It cant but the root RP and USP have duplicate calls for each EP in the example diagram.
The function's purpose is to map RAS registers and cache the address. This reuses the
same function for RP and DSP. The DSP will never be previously mapped as you indicated.
>> Introduce a mutex for synchronizing accesses to the cached RAS mapping.
> I suspect the motivation for the lock and "previously mapped" check was
> due to noticing that the ras registers are not being unmapped, but
> that's due to a devm bug below.
The synchronization was added as result of review recommendation because it is
a racy area. It's possible that multiple endpoints using the same switch could
call this function from devm_cxl_add_endpoints()->cxl_init_ep_ports().
> Even if it were the case that multiple resources need to share 1 devm
> mapping, that would need to look something like the logic around
> cxl_detach_ep(). In that arrangement, the first endpoint in the door
> sets up the 'struct cxl_port' and its 'struct cxl_dport' instances, and
> the last endpoint out the door tears it all down and turns off the
> lights.
>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> Reviewed-by: Alejandro Lucero <alucerop@amd.com>
>> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>> Reviewed-by: Gregory Price <gourry@gourry.net>
>> ---
>> drivers/cxl/core/pci.c | 42 ++++++++++++++++++++----------------------
>> drivers/cxl/cxl.h | 6 ++----
>> drivers/cxl/mem.c | 31 +++++++++++++++++++++++++++++--
>> 3 files changed, 51 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>> index a5c65f79db18..143c853a52c4 100644
>> --- a/drivers/cxl/core/pci.c
>> +++ b/drivers/cxl/core/pci.c
>> @@ -24,6 +24,8 @@ static unsigned short media_ready_timeout = 60;
>> module_param(media_ready_timeout, ushort, 0644);
>> MODULE_PARM_DESC(media_ready_timeout, "seconds to wait for media ready");
>>
>> +static DEFINE_MUTEX(ras_init_mutex);
>> +
>> struct cxl_walk_context {
>> struct pci_bus *bus;
>> struct cxl_port *port;
>> @@ -749,18 +751,6 @@ static void cxl_dport_map_rch_aer(struct cxl_dport *dport)
>> }
>> }
>>
>> -static void cxl_dport_map_ras(struct cxl_dport *dport)
>> -{
>> - struct cxl_register_map *map = &dport->reg_map;
>> - struct device *dev = dport->dport_dev;
>> -
>> - if (!map->component_map.ras.valid)
>> - dev_dbg(dev, "RAS registers not found\n");
>> - else if (cxl_map_component_regs(map, &dport->regs.component,
>> - BIT(CXL_CM_CAP_CAP_ID_RAS)))
>> - dev_dbg(dev, "Failed to map RAS capability.\n");
>> -}
>> -
>> static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>> {
>> void __iomem *aer_base = dport->regs.dport_aer;
>> @@ -788,22 +778,30 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>> /**
>> * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
>> * @dport: the cxl_dport that needs to be initialized
>> - * @host: host device for devm operations
>> */
>> -void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
>> +void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
>> {
>> - dport->reg_map.host = host;
>> - cxl_dport_map_ras(dport);
>> -
>> - if (dport->rch) {
>> - struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport->dport_dev);
>> -
>> - if (!host_bridge->native_aer)
>> - return;
>> + struct device *dport_dev = dport->dport_dev;
>> + struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport_dev);
>>
>> + dport->reg_map.host = dport_dev;
> This seems to be confused about how devm works. @host is passed in
> because the cxl_memdev instance being probed in cxl_mem_probe() is doing
> setup work on behalf of @dport_dev.
>
> When the cxl_memdev goes through a ->remove() event, unbind from
> cxl_mem, it tears down that mapping.
>
> However, when using @dport_dev as the devm host, that mapping will not
> be torn down until either the @dport_dev goes through a ->remove() event
> or the device is unregistered altogether. There is no CXL subsystem
> coordination with a driver for @dport_dev. The PCIe portdrv might have
> an interest in it, but CXL can not depend on portdrv to map CXL
> registers or keep the device bound while CXL has an interest those
> registers. The devres_release_all() triggered by a
> "device_del(@dport_dev)" is also uncoordinated with any CXL interest. In
> general, it is a devm anti-pattern to depend on a device_del() event to
> trigger devres_release_all().
>
>
>> + if (dport->rch && host_bridge->native_aer) {
>> cxl_dport_map_rch_aer(dport);
>> cxl_disable_rch_root_ints(dport);
>> }
>> +
>> + /* dport may have more than 1 downstream EP. Check if already mapped. */
>> + mutex_lock(&ras_init_mutex);
> I suspect this lock and check got added to workaround "Failed to request
> region" messages coming out of devm_cxl_iomap_block() in testing? Per
> above, that's not "more than 1 downstream EPi", that's "failure to clean
> up the last mapping for the next cxl_mem_probe() event of the same
> endpoint".
Synchronization was added to handle the concurrent accesses. I never observed
issues due to the race condition for RP and USP but I confirmed through further
testing it is a real potential issue for the RP and USP.
You recommended, in the next patch, to map USP RAS registers from cxl_endpoint_port_probe().
Would you like the RP and DSP mapping to be called from cxl_endpoint_port_probe() as well? Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 11/17] cxl/pci: Change find_cxl_port() to non-static
2025-02-11 19:24 ` [PATCH v7 11/17] cxl/pci: Change find_cxl_port() to non-static Terry Bowman
2025-02-11 23:42 ` Dave Jiang
@ 2025-02-13 23:15 ` Dan Williams
1 sibling, 0 replies; 94+ messages in thread
From: Dan Williams @ 2025-02-13 23:15 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> CXL PCIe Port Protocol Error support will be added in the future. This
> requires searching for a CXL PCIe Port device in the CXL topology as
> provided by find_cxl_port(). But, find_cxl_port() is defined static
> and as a result is not callable outside of this source file.
>
> Update the find_cxl_port() declaration to be non-static.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
> ---
> drivers/cxl/core/core.h | 2 ++
> drivers/cxl/core/port.c | 4 ++--
> 2 files changed, 4 insertions(+), 2 deletions(-)
Looks ok, but this tiny patch has no justification by itself and should
be squashed with the first consumer.
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors
2025-02-11 19:24 ` [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors Terry Bowman
2025-02-12 0:11 ` Dave Jiang
@ 2025-02-14 2:18 ` Dan Williams
2025-02-14 21:43 ` Bowman, Terry
2025-03-05 0:22 ` Ira Weiny
2 siblings, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-14 2:18 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> Introduce correctable and uncorrectable (UCE) CXL PCIe Port Protocol Error
> handlers.
>
> The handlers will be called with a 'struct pci_dev' parameter
> indicating the CXL Port device requiring handling. The CXL PCIe Port
> device's underlying 'struct device' will match the port device in the
> CXL topology.
>
> Use the PCIe Port's device object to find the matching CXL Upstream Switch
> Port, CXL Downstream Switch Port, or CXL Root Port in the CXL topology. The
> matching CXL Port device should contain a cached reference to the RAS
> register block. The cached RAS block will be used in handling the error.
>
> Invoke the existing __cxl_handle_ras() or __cxl_handle_cor_ras() using
> a reference to the RAS registers as a parameter. These functions will use
> the RAS register reference to indicate an error and clear the device's RAS
> status.
>
> Update __cxl_handle_ras() to return PCI_ERS_RESULT_PANIC in the case
> an error is present in the RAS status. Otherwise, return
> PCI_ERS_RESULT_NONE.
So I have been having this nagging feeling while reviewing this set that
perhaps the CXL error handlers should not be 'struct pci_error_handlers'
relative to a 'struct pci_driver', but instead 'struct
cxl_error_handlers' that are added to 'struct cxl_driver', in particular
'cxl_port_driver'.
See below for what I *think* are insurmountable problems when a PCI
error handler is tasked with looking up @ras_base in a race free manner.
Note I say "think" because I could be misreading or missing some other
circumstance that makes this ok, so do please challenge if you think I
missed something because what follows below is another major direction
change.
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> ---
> drivers/cxl/core/pci.c | 81 +++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 77 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index af809e7cbe3b..3f13d9dfb610 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -699,7 +699,7 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)
> * Log the state of the RAS status registers and prepare them to log the
> * next error status. Return 1 if reset needed.
> */
> -static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
> +static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
> {
> u32 hl[CXL_HEADERLOG_SIZE_U32];
> void __iomem *addr;
> @@ -708,13 +708,13 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>
> if (!ras_base) {
> dev_warn_once(dev, "CXL RAS register block is not mapped");
> - return false;
> + return PCI_ERS_RESULT_NONE;
> }
>
> addr = ras_base + CXL_RAS_UNCORRECTABLE_STATUS_OFFSET;
> status = readl(addr);
> if (!(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK))
> - return false;
> + return PCI_ERS_RESULT_NONE;
>
> /* If multiple errors, log header points to first error from ctrl reg */
> if (hweight32(status) > 1) {
> @@ -733,7 +733,7 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>
> writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
>
> - return true;
> + return PCI_ERS_RESULT_PANIC;
> }
>
> static bool cxl_handle_endpoint_ras(struct cxl_dev_state *cxlds)
> @@ -782,6 +782,79 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
> writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
> }
>
> +static int match_uport(struct device *dev, const void *data)
> +{
> + const struct device *uport_dev = data;
> + struct cxl_port *port;
> +
> + if (!is_cxl_port(dev))
> + return 0;
> +
> + port = to_cxl_port(dev);
> +
> + return port->uport_dev == uport_dev;
> +}
> +
> +static void __iomem *cxl_pci_port_ras(struct pci_dev *pdev, struct device **dev)
> +{
> + void __iomem *ras_base;
> +
> + if (!pdev || !*dev) {
> + pr_err("Failed, parameter is NULL");
> + return NULL;
> + }
> +
> + if ((pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) ||
> + (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM)) {
> + struct cxl_port *port __free(put_cxl_port);
> + struct cxl_dport *dport = NULL;
> +
> + port = find_cxl_port(&pdev->dev, &dport);
side comment: please always declare and assign scope-based-cleanup
variables on the same line, i.e.:
struct cxl_port *port __free(put_cxl_port) =
find_cxl_port(&pdev->dev, &dport);
Yes, that means violating the coding-style rule of preferring variable
declarations at the top of blocks. This is for 2 reasons:
* The variable is uninitialized. If future refactoring injects an early
exit then unitialized garbage gets passed to put_cxl_port().
* The cosmetic order of the declaration is not the unwind order. If
future refactoring introduces other scope-based-cleanup variables it
requires additional cleanup to move the declaration to satisfy unwind
dependencies.
> + if (!port) {
> + pci_err(pdev, "Failed to find root/dport in CXL topology\n");
> + return NULL;
> + }
> +
> + ras_base = dport ? dport->regs.ras : NULL;
> + *dev = &port->dev;
Ok, so here is where the trouble I was alluding to earlier begins. At
this point we leave this scope which means @port will have its reference
dropped and may be freed by the time the caller tries to use it.
Additionally, @ras_base is only valid while @port->dev.driver is set. In
this set, cxl_do_recovery() is only holding the device lock of @pdev
which means nothing synchronizes against @ras_base pointing to garbage
because a cxl_port was unbound / unplugged / disabled while error
recovery was running.
Both of those problems go away if upon entry to ->error_detected() it
can already be assumed that the context holds both a 'struct cxl_port'
object reference, and the device_lock() for that object.
As for how to fix it, one idea is to have the AER core post CXL events
to their own fifo for the CXL core to handle. Something like have
aer_isr_one_error(), upon detection of an internal error on a CXL port
device, post the 'struct aer_err_source' to a new kfifo and wake up a
CXL core thread to run cxl_do_recovery() against the CXL port device
topology instead of the PCI device topology.
Essentially, the main point of cxl_do_recovery() is the acknowledgement
that the PCI core does not have the context to judge the severity of
CXL events, or fully annotate events with all the potential kernel
objects impacted by an event. It is also the case that we need a common
landing spot for PCI AER notified CXL error events and ACPI GHES
notified CXL CPER records. So both PCI AER, and CPER notified errors
need to end up in the same cxl_do_recovery() path that walks the CXL
port topology.
The CXL Type-2 series is showing uptake on accelerators registering
'struct cxl_memdev' objects to report their CXL.mem capabilities. I
imagine that effort would eventually end up with a scheme that
accelerators can register a cxl_error_handler instance with that memdev
to get involved in potentially recovering CXL.mem errors. For example,
it may be the case that CXL error isolation finally has a viable use
case when the accelerator knows it is the only device impacted by an
isolation event and can safely reset that entire host-bridge to recover.
That is difficult to achieve in the PCI error handler context.
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 13/17] cxl/pci: Add trace logging for CXL PCIe Port RAS errors
2025-02-11 19:24 ` [PATCH v7 13/17] cxl/pci: Add trace logging " Terry Bowman
2025-02-12 0:11 ` Gregory Price
2025-02-12 0:17 ` Dave Jiang
@ 2025-02-14 2:21 ` Dan Williams
2025-02-14 15:34 ` Jonathan Cameron
2 siblings, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-14 2:21 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> The CXL drivers use kernel trace functions for logging Endpoint and
> Restricted CXL host (RCH) Downstream Port RAS errors. Similar functionality
> is required for CXL Root Ports, CXL Downstream Switch Ports, and CXL
> Upstream Switch Ports.
>
> Introduce trace logging functions for both RAS correctable and
> uncorrectable errors specific to CXL PCIe Ports. Additionally, update
> the CXL Port Protocol Error handlers to invoke these new trace functions.
>
> Examples of the output from these changes is below.
>
> Correctable error:
> cxl_port_aer_correctable_error: device=port1 parent=root0 status='Received Error From Physical Layer'
>
> Uncorrectable error:
> cxl_port_aer_uncorrectable_error: device=port1 parent=root0 status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Erro'
Oh, so this solves the problem I was worried about earlier where it
looked like protocol errors only got notified if the event was a memdev.
I still think it would be worthwhile to make this one unified
trace-event rather than multiple.
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 15/17] cxl/pci: Add support to assign and clear pci_driver::cxl_err_handlers
2025-02-11 19:24 ` [PATCH v7 15/17] cxl/pci: Add support to assign and clear pci_driver::cxl_err_handlers Terry Bowman
2025-02-12 0:38 ` Dave Jiang
@ 2025-02-14 2:29 ` Dan Williams
1 sibling, 0 replies; 94+ messages in thread
From: Dan Williams @ 2025-02-14 2:29 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> pci_driver::cxl_err_handlers are not currently assigned handler callbacks.
> The handlers can't be set in the pci_driver static definition because the
> CXL PCIe Port devices are bound to the portdrv driver which is not CXL
> driver aware.
>
> Add cxl_assign_port_error_handlers() in the cxl_core module. This
> function will assign the default handlers for a CXL PCIe Port device.
>
> When the CXL Port (cxl_port or cxl_dport) is destroyed the device's
> pci_driver::cxl_err_handlers must be set to NULL indicating they should no
> longer be used.
>
> Create cxl_clear_port_error_handlers() and register it to be called
> when the CXL Port device (cxl_port or cxl_dport) is destroyed.
This is another complication that naturally goes away with
cxl_error_handlers are instances that get attached to 'struct
cxl_driver' instances rather tha 'struct pci_driver' instances.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
> ---
> drivers/cxl/core/pci.c | 59 ++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 57 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index f154dcf6dfda..03ae21a944e0 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -860,8 +860,39 @@ static pci_ers_result_t cxl_port_error_detected(struct pci_dev *pdev)
> return __cxl_handle_ras(dev, &pdev->dev, ras_base);
> }
>
> +static const struct cxl_error_handlers cxl_port_error_handlers = {
> + .error_detected = cxl_port_error_detected,
> + .cor_error_detected = cxl_port_cor_error_detected,
> +};
> +
> +static void cxl_assign_port_error_handlers(struct pci_dev *pdev)
> +{
> + struct pci_driver *pdrv;
> +
> + if (!pdev || !pdev->driver || !get_device(&pdev->dev))
> + return;
> +
> + pdrv = pdev->driver;
> + pdrv->cxl_err_handler = &cxl_port_error_handlers;
Nothing is holding the @pdev device_lock(), so @pdev->driver may go NULL
immediately after reading it.
Also, it is possible for a 'struct cxl_port' to exist even though its
uport_dev (pci_dev) is not attached to a driver. This would seem to
result in unpredictable behavior from one kernel to the next as the PCIe
portdrv situation evolves.
Lastly, I do not like the precedent of not being able to read a 'struct
pci_driver' template and be assured that it captures all possible error
handlers, or even worse, this unceremoniously overrides a PCI driver
that thinks it knows what the CXL error handlers should be.
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 16/17] PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch Ports
2025-02-11 19:24 ` [PATCH v7 16/17] PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch Ports Terry Bowman
2025-02-11 20:25 ` Bjorn Helgaas
2025-02-12 0:40 ` Dave Jiang
@ 2025-02-14 2:35 ` Dan Williams
2 siblings, 0 replies; 94+ messages in thread
From: Dan Williams @ 2025-02-14 2:35 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> The AER service driver enables PCIe Uncorrectable Internal Errors (UIE) and
> Correctable Internal errors (CIE) for CXL Root Ports. The UIE and CIE are
> used in reporting CXL Protocol Errors. The same UIE/CIE enablement is
> needed for CXL Upstream Switch Ports and CXL Downstream Switch Ports
> inorder to notify the associated Root Port and OS.[1]
>
> Export the AER service driver's pci_aer_unmask_internal_errors() function
> to CXL namespace.
>
> Remove the function's dependency on the CONFIG_PCIEAER_CXL kernel config
> because it is now an exported function.
>
> Call pci_aer_unmask_internal_errors() during RAS initialization in:
> cxl_uport_init_ras_reporting() and cxl_dport_init_ras_reporting().
>
> [1] PCIe Base Spec r6.2-1.0, 6.2.3.2.2 Masking Individual Errors
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
I wonder if this should save+unmask and restore the prior state when the
cxl_port detaches from the port driver?
I guess we can wait to see if this causes problems since internal errors
should be more predictable / reliable on CXL devices compared to generic
PCIe devices where Linux never enabled internal errors previously.
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 17/17] cxl/pci: Handle CXL Endpoint and RCH Protocol Errors separately from PCIe errors
2025-02-11 19:24 ` [PATCH v7 17/17] cxl/pci: Handle CXL Endpoint and RCH Protocol Errors separately from PCIe errors Terry Bowman
@ 2025-02-14 2:43 ` Dan Williams
0 siblings, 0 replies; 94+ messages in thread
From: Dan Williams @ 2025-02-14 2:43 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> CXL Endpoint and Restricted CXL Host (RCH) Downstream Port Protocol Errors
> are currently treated as PCIe errors, which does not properly process CXL
> uncorrectable (UCE) errors. When a CXL device encounters an uncorrectable
> Protocol Error, the system should panic to prevent potential CXL memory
> corruption.
>
> Treat CXL Endpoint Protocol Errors as CXL errors. This requires updates in
> the CXL and AER drivers.
>
> Update the CXL Endpoint driver with a new declaration for struct
> cxl_error_handlers named cxl_ep_error_handlers. Move the existing CE and
> UCE handler assignments from cxl_error_handlers to the new
> cxl_ep_error_handlers. Remove the 'state' parameter from the UCE handler
> interface because it is not used in CXL recovery.
>
> Update the AER driver to associate CXL Protocol errors with CXL error
> handling. Change detection in handles_cxl_errors() from using
> pcie_is_cxl_port() to instead use pcie_is_cxl().
This all looks ok for what it is, but given the prior discussion about
cxl_error_handlers only running in the CXL domain I think this will
result in the cxl_pci driver having even less to do.
The cxl_core will default register port error handlers that can panic on
notification. The cxl_pci driver's only job is then responding to PCI
events and registering CXL objects to let the core handle.
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery in AER service driver
2025-02-11 19:24 ` [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery " Terry Bowman
` (3 preceding siblings ...)
2025-02-12 0:24 ` Dan Williams
@ 2025-02-14 15:11 ` Jonathan Cameron
2025-02-18 15:43 ` Bowman, Terry
2025-02-14 17:36 ` Fan Ni
5 siblings, 1 reply; 94+ messages in thread
From: Jonathan Cameron @ 2025-02-14 15:11 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave, dave.jiang,
alison.schofield, vishal.l.verma, dan.j.williams, bhelgaas,
mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, 11 Feb 2025 13:24:33 -0600
Terry Bowman <terry.bowman@amd.com> wrote:
> Existing recovery procedure for PCIe uncorrectable errors (UCE) does not
> apply to CXL devices. Recovery can not be used for CXL devices because of
> potential corruption on what can be system memory. Also, current PCIe UCE
> recovery, in the case of a Root Port (RP) or Downstream Switch Port (DSP),
> does not begin at the RP/DSP but begins at the first downstream device.
> This will miss handling CXL Protocol Errors in a CXL RP or DSP. A separate
> CXL recovery is needed because of the different handling requirements
>
> Add a new function, cxl_do_recovery() using the following.
>
> Add cxl_walk_bridge() to iterate the detected error's sub-topology.
> cxl_walk_bridge() is similar to pci_walk_bridge() but the CXL flavor
> will begin iteration at the RP or DSP rather than beginning at the
Hi Terry,
Trivial nitpick but you wrap point is shrinking wrt to the previous paragraph.
Just looks odd rather than actually mattering :)
> first downstream device.
>
> pci_walk_bridge() is candidate to possibly reuse cxl_walk_bridge() but
> needs further investigation. This will be left for future improvement
> to make the CXL and PCI handling paths more common.
>
> Add cxl_report_error_detected() as an analog to report_error_detected().
> It will call pci_driver::cxl_err_handlers for each iterated downstream
> device. The pci_driver::cxl_err_handler's UCE handler returns a boolean
> indicating if there was a UCE error detected during handling.
>
> cxl_do_recovery() uses the status from cxl_report_error_detected() to
> determine how to proceed. Non-fatal CXL UCE errors will be treated as
> fatal. If a UCE was present during handling then cxl_do_recovery()
> will kernel panic.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
One trivial suggestion inline. Probably something for another day!
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> drivers/pci/pci.h | 3 +++
> drivers/pci/pcie/aer.c | 4 +++
> drivers/pci/pcie/err.c | 58 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/pci.h | 3 +++
> 4 files changed, 68 insertions(+)
>
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 01e51db8d285..deb193b387af 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -722,6 +722,9 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
> pci_channel_state_t state,
> pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev));
>
> +/* CXL error reporting and handling */
> +void cxl_do_recovery(struct pci_dev *dev);
> +
> bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
> int pcie_retrain_link(struct pci_dev *pdev, bool use_lt);
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index 34ec0958afff..ee38db08d005 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -1012,6 +1012,8 @@ static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
> err_handler->error_detected(dev, pci_channel_io_normal);
> else if (info->severity == AER_FATAL)
> err_handler->error_detected(dev, pci_channel_io_frozen);
> +
> + cxl_do_recovery(dev);
> }
> out:
> device_unlock(&dev->dev);
> @@ -1041,6 +1043,8 @@ static void cxl_handle_error(struct pci_dev *dev, struct aer_err_info *info)
> pdrv->cxl_err_handler->cor_error_detected(dev);
>
> pcie_clear_device_status(dev);
> + } else {
> + cxl_do_recovery(dev);
> }
> }
>
> diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
> index 31090770fffc..05f2d1ef4c36 100644
> --- a/drivers/pci/pcie/err.c
> +++ b/drivers/pci/pcie/err.c
> @@ -24,6 +24,9 @@
> static pci_ers_result_t merge_result(enum pci_ers_result orig,
> enum pci_ers_result new)
> {
> + if (new == PCI_ERS_RESULT_PANIC)
> + return PCI_ERS_RESULT_PANIC;
> +
> if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
> return PCI_ERS_RESULT_NO_AER_DRIVER;
>
> @@ -276,3 +279,58 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
>
> return status;
> }
> +
> +static void cxl_walk_bridge(struct pci_dev *bridge,
> + int (*cb)(struct pci_dev *, void *),
> + void *userdata)
> +{
> + if (cb(bridge, userdata))
> + return;
> +
> + if (bridge->subordinate)
> + pci_walk_bus(bridge->subordinate, cb, userdata);
> +}
> +
> +static int cxl_report_error_detected(struct pci_dev *dev, void *data)
> +{
> + const struct cxl_error_handlers *cxl_err_handler;
> + pci_ers_result_t vote, *result = data;
> + struct pci_driver *pdrv;
> +
> + device_lock(&dev->dev);
Could use
guard(device)(&dev->dev);
> + pdrv = dev->driver;
> + if (!pdrv || !pdrv->cxl_err_handler ||
> + !pdrv->cxl_err_handler->error_detected)
> + goto out;
allowing you to return here.
Same approach would simplify the rch code as well.
> +
> + cxl_err_handler = pdrv->cxl_err_handler;
> + vote = cxl_err_handler->error_detected(dev);
> + *result = merge_result(*result, vote);
> +out:
> + device_unlock(&dev->dev);
> + return 0;
> +}
> +
> +void cxl_do_recovery(struct pci_dev *dev)
> +{
> + struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
> + pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
> +
> + cxl_walk_bridge(dev, cxl_report_error_detected, &status);
> + if (status == PCI_ERS_RESULT_PANIC)
> + panic("CXL cachemem error.");
> +
> + /*
> + * If we have native control of AER, clear error status in the device
> + * that detected the error. If the platform retained control of AER,
> + * it is responsible for clearing this status. In that case, the
> + * signaling device may not even be visible to the OS.
> + */
> + if (host->native_aer || pcie_ports_native) {
> + pcie_clear_device_status(dev);
> + pci_aer_clear_nonfatal_status(dev);
> + pci_aer_clear_fatal_status(dev);
> + }
> +
> + pci_info(dev, "CXL uncorrectable error.\n");
> +}
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
2025-02-11 19:24 ` [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream " Terry Bowman
2025-02-11 23:02 ` Dave Jiang
2025-02-12 2:00 ` Dan Williams
@ 2025-02-14 15:15 ` Jonathan Cameron
2025-02-14 19:50 ` Bowman, Terry
2 siblings, 1 reply; 94+ messages in thread
From: Jonathan Cameron @ 2025-02-14 15:15 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave, dave.jiang,
alison.schofield, vishal.l.verma, dan.j.williams, bhelgaas,
mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, 11 Feb 2025 13:24:35 -0600
Terry Bowman <terry.bowman@amd.com> wrote:
> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
>
> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
> pointer to the CXL Upstream Port's mapped RAS registers.
>
> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
> register mapping. This is similar to the existing
> cxl_dport_init_ras_reporting() but for USP devices.
>
> The USP may have multiple downstream endpoints. Before mapping RAS
> registers check if the registers are already mapped.
>
> Introduce a mutex for synchronizing accesses to the cached RAS
> mapping.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
> /**
> * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
> * @dport: the cxl_dport that needs to be initialized
> @@ -801,7 +819,6 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
> BIT(CXL_CM_CAP_CAP_ID_RAS)))
> dev_err(dport_dev, "Failed to map RAS capability\n");
> mutex_unlock(&ras_init_mutex);
> -
Grumpy hat (it is Friday afternoon). Shouldn't be in this patch!
> }
> EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 09/17] cxl/pci: Update RAS handler interfaces to also support CXL PCIe Ports
2025-02-11 19:24 ` [PATCH v7 09/17] cxl/pci: Update RAS handler interfaces to also support CXL PCIe Ports Terry Bowman
2025-02-11 23:26 ` Dave Jiang
@ 2025-02-14 15:19 ` Jonathan Cameron
1 sibling, 0 replies; 94+ messages in thread
From: Jonathan Cameron @ 2025-02-14 15:19 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave, dave.jiang,
alison.schofield, vishal.l.verma, dan.j.williams, bhelgaas,
mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, 11 Feb 2025 13:24:36 -0600
Terry Bowman <terry.bowman@amd.com> wrote:
> CXL PCIe Port Protocol Error handling support will be added to the
> CXL drivers in the future. In preparation, rename the existing
> interfaces to support handling all CXL PCIe Port Protocol Errors.
>
> The driver's RAS support functions currently rely on a 'struct
> cxl_dev_state' type parameter, which is not available for CXL Port
> devices. However, since the same CXL RAS capability structure is
> needed across most CXL components and devices, a common handling
> approach should be adopted.
>
> To accommodate this, update the __cxl_handle_cor_ras() and
> __cxl_handle_ras() functions to use a `struct device` instead of
> `struct cxl_dev_state`.
>
> No functional changes are introduced.
>
> [1] CXL 3.1 Spec, 8.2.4 CXL.cache and CXL.mem Registers
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Reviewed-by: Gregory Price <gourry@gourry.net>
Seems fine to me as well.
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 10/17] cxl/pci: Add log message and add type check in existing RAS handlers
2025-02-13 0:08 ` Bowman, Terry
@ 2025-02-14 15:28 ` Jonathan Cameron
0 siblings, 0 replies; 94+ messages in thread
From: Jonathan Cameron @ 2025-02-14 15:28 UTC (permalink / raw)
To: Bowman, Terry
Cc: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
dave.jiang, alison.schofield, vishal.l.verma, bhelgaas, mahesh,
ira.weiny, oohall, Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati, shiju.jose
On Wed, 12 Feb 2025 18:08:13 -0600
"Bowman, Terry" <terry.bowman@amd.com> wrote:
> On 2/12/2025 4:59 PM, Dan Williams wrote:
> > Terry Bowman wrote:
> >> The CXL RAS handlers do not currently log if the RAS registers are
> >> unmapped. This is needed in order to help debug CXL error handling. Update
> >> the CXL driver to log a warning message if the RAS register block is
> >> unmapped.
> >>
> >> Also, add type check before processing EP or RCH DP.
> >>
> >> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> >> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> >> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> >> Reviewed-by: Gregory Price <gourry@gourry.net>
> >> ---
> >> drivers/cxl/core/pci.c | 20 ++++++++++++++------
> >> 1 file changed, 14 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> >> index 69bb030aa8e1..af809e7cbe3b 100644
> >> --- a/drivers/cxl/core/pci.c
> >> +++ b/drivers/cxl/core/pci.c
> >> @@ -658,15 +658,19 @@ static void __cxl_handle_cor_ras(struct device *dev,
> >> void __iomem *addr;
> >> u32 status;
> >>
> >> - if (!ras_base)
> >> + if (!ras_base) {
> >> + dev_warn_once(dev, "CXL RAS register block is not mapped");
> >> return;
> >> + }
> >>
> >> addr = ras_base + CXL_RAS_CORRECTABLE_STATUS_OFFSET;
> >> status = readl(addr);
> >> - if (status & CXL_RAS_CORRECTABLE_STATUS_MASK) {
> >> - writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
> >> + if (!(status & CXL_RAS_CORRECTABLE_STATUS_MASK))
> >> + return;
> >> + writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
> >> +
> >> + if (is_cxl_memdev(dev))
> >> trace_cxl_aer_correctable_error(to_cxl_memdev(dev), status);
> > I think trace_cxl_aer_correctable_error() should always fire and this
> > should somehow be unified with the CPER record trace-event for protocol
> > errors.
> >
> > The only usage of @memdev in this trace is retrieving the device serial
> > number. If the device is not a memdev then print zero for the serial
> > number, or something like that.
> >
> > In the end RAS daemon should only need to enable one trace event to get
> > protocol errors and header logs from ports or endpoints, either
> > natively, or via CPER.
> >
> That would be: we use 'struct *device' instead of 'struct *cxl_memdev'
> and pass serial# in as a parameter (0 in non-EP cases)?
For a USP may well have a serial number cap. Might be worth getting it?
slightly nasty thing here will be change of memdev=%s to devname=%s or
similar. Meh. It's a TP_printk() I'm not sure anyone will care.
Need to be careful with the tracepoint itself though and the rasdaemon
etc handling.
https://github.com/mchehab/rasdaemon/blob/master/ras-cxl-handler.c#L351
We may have to just add another field.
>
> >> - }
> >> }
> >>
> >> static void cxl_handle_endpoint_cor_ras(struct cxl_dev_state *cxlds)
> >> @@ -702,8 +706,10 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
> >> u32 status;
> >> u32 fe;
> >>
> >> - if (!ras_base)
> >> + if (!ras_base) {
> >> + dev_warn_once(dev, "CXL RAS register block is not mapped");
> > Is this a "never can happen" print? It seems like an oversight in an
> > upper layer to get this far down error reporting without the registers
> > mapped.
> >
> > Like maybe this is a bug in a driver that should crash, or the driver
> > should not be registering broken error handlers?
> Correct. The error handler assignment and enablement is gated by RAS mapping
> in cxl_uport_init_ras_reporting() and cxl_dport_init_ras_reporting().
>
> Terry
>
>
>
>
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 13/17] cxl/pci: Add trace logging for CXL PCIe Port RAS errors
2025-02-14 2:21 ` Dan Williams
@ 2025-02-14 15:34 ` Jonathan Cameron
0 siblings, 0 replies; 94+ messages in thread
From: Jonathan Cameron @ 2025-02-14 15:34 UTC (permalink / raw)
To: Dan Williams
Cc: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
dave.jiang, alison.schofield, vishal.l.verma, bhelgaas, mahesh,
ira.weiny, oohall, Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Thu, 13 Feb 2025 18:21:11 -0800
Dan Williams <dan.j.williams@intel.com> wrote:
> Terry Bowman wrote:
> > The CXL drivers use kernel trace functions for logging Endpoint and
> > Restricted CXL host (RCH) Downstream Port RAS errors. Similar functionality
> > is required for CXL Root Ports, CXL Downstream Switch Ports, and CXL
> > Upstream Switch Ports.
> >
> > Introduce trace logging functions for both RAS correctable and
> > uncorrectable errors specific to CXL PCIe Ports. Additionally, update
> > the CXL Port Protocol Error handlers to invoke these new trace functions.
> >
> > Examples of the output from these changes is below.
> >
> > Correctable error:
> > cxl_port_aer_correctable_error: device=port1 parent=root0 status='Received Error From Physical Layer'
> >
> > Uncorrectable error:
> > cxl_port_aer_uncorrectable_error: device=port1 parent=root0 status: 'Memory Byte Enable Parity Error' first_error: 'Memory Byte Enable Parity Erro'
>
> Oh, so this solves the problem I was worried about earlier where it
> looked like protocol errors only got notified if the event was a memdev.
> I still think it would be worthwhile to make this one unified
> trace-event rather than multiple.
I'd go with a 'maybe'. Absolutely would have made sense if this
had been the intent from the start. Now we are going to end
up with at least some tracepoint fields that are mutually exclusive.
E.g. Switch ports aren't going to want to set memdev.
Might be easier to just keep them separate. However this will get
messier anyway when type 2 devices come along.
Jonathan
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery in AER service driver
2025-02-11 19:24 ` [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery " Terry Bowman
` (4 preceding siblings ...)
2025-02-14 15:11 ` Jonathan Cameron
@ 2025-02-14 17:36 ` Fan Ni
5 siblings, 0 replies; 94+ messages in thread
From: Fan Ni @ 2025-02-14 17:36 UTC (permalink / raw)
To: Terry Bowman
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On Tue, Feb 11, 2025 at 01:24:33PM -0600, Terry Bowman wrote:
> Existing recovery procedure for PCIe uncorrectable errors (UCE) does not
> apply to CXL devices. Recovery can not be used for CXL devices because of
> potential corruption on what can be system memory. Also, current PCIe UCE
> recovery, in the case of a Root Port (RP) or Downstream Switch Port (DSP),
> does not begin at the RP/DSP but begins at the first downstream device.
> This will miss handling CXL Protocol Errors in a CXL RP or DSP. A separate
> CXL recovery is needed because of the different handling requirements
>
> Add a new function, cxl_do_recovery() using the following.
>
> Add cxl_walk_bridge() to iterate the detected error's sub-topology.
> cxl_walk_bridge() is similar to pci_walk_bridge() but the CXL flavor
> will begin iteration at the RP or DSP rather than beginning at the
> first downstream device.
>
> pci_walk_bridge() is candidate to possibly reuse cxl_walk_bridge() but
> needs further investigation. This will be left for future improvement
> to make the CXL and PCI handling paths more common.
>
> Add cxl_report_error_detected() as an analog to report_error_detected().
> It will call pci_driver::cxl_err_handlers for each iterated downstream
> device. The pci_driver::cxl_err_handler's UCE handler returns a boolean
> indicating if there was a UCE error detected during handling.
>
> cxl_do_recovery() uses the status from cxl_report_error_detected() to
> determine how to proceed. Non-fatal CXL UCE errors will be treated as
> fatal. If a UCE was present during handling then cxl_do_recovery()
> will kernel panic.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Fan Ni <fan.ni@samsung.com>
> ---
> drivers/pci/pci.h | 3 +++
> drivers/pci/pcie/aer.c | 4 +++
> drivers/pci/pcie/err.c | 58 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/pci.h | 3 +++
> 4 files changed, 68 insertions(+)
>
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 01e51db8d285..deb193b387af 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -722,6 +722,9 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
> pci_channel_state_t state,
> pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev));
>
> +/* CXL error reporting and handling */
> +void cxl_do_recovery(struct pci_dev *dev);
> +
> bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
> int pcie_retrain_link(struct pci_dev *pdev, bool use_lt);
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index 34ec0958afff..ee38db08d005 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -1012,6 +1012,8 @@ static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
> err_handler->error_detected(dev, pci_channel_io_normal);
> else if (info->severity == AER_FATAL)
> err_handler->error_detected(dev, pci_channel_io_frozen);
> +
> + cxl_do_recovery(dev);
> }
> out:
> device_unlock(&dev->dev);
> @@ -1041,6 +1043,8 @@ static void cxl_handle_error(struct pci_dev *dev, struct aer_err_info *info)
> pdrv->cxl_err_handler->cor_error_detected(dev);
>
> pcie_clear_device_status(dev);
> + } else {
> + cxl_do_recovery(dev);
> }
> }
>
> diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
> index 31090770fffc..05f2d1ef4c36 100644
> --- a/drivers/pci/pcie/err.c
> +++ b/drivers/pci/pcie/err.c
> @@ -24,6 +24,9 @@
> static pci_ers_result_t merge_result(enum pci_ers_result orig,
> enum pci_ers_result new)
> {
> + if (new == PCI_ERS_RESULT_PANIC)
> + return PCI_ERS_RESULT_PANIC;
> +
> if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
> return PCI_ERS_RESULT_NO_AER_DRIVER;
>
> @@ -276,3 +279,58 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
>
> return status;
> }
> +
> +static void cxl_walk_bridge(struct pci_dev *bridge,
> + int (*cb)(struct pci_dev *, void *),
> + void *userdata)
> +{
> + if (cb(bridge, userdata))
> + return;
> +
> + if (bridge->subordinate)
> + pci_walk_bus(bridge->subordinate, cb, userdata);
> +}
> +
> +static int cxl_report_error_detected(struct pci_dev *dev, void *data)
> +{
> + const struct cxl_error_handlers *cxl_err_handler;
> + pci_ers_result_t vote, *result = data;
> + struct pci_driver *pdrv;
> +
> + device_lock(&dev->dev);
> + pdrv = dev->driver;
> + if (!pdrv || !pdrv->cxl_err_handler ||
> + !pdrv->cxl_err_handler->error_detected)
> + goto out;
> +
> + cxl_err_handler = pdrv->cxl_err_handler;
> + vote = cxl_err_handler->error_detected(dev);
> + *result = merge_result(*result, vote);
> +out:
> + device_unlock(&dev->dev);
> + return 0;
> +}
> +
> +void cxl_do_recovery(struct pci_dev *dev)
> +{
> + struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
> + pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
> +
> + cxl_walk_bridge(dev, cxl_report_error_detected, &status);
> + if (status == PCI_ERS_RESULT_PANIC)
> + panic("CXL cachemem error.");
> +
> + /*
> + * If we have native control of AER, clear error status in the device
> + * that detected the error. If the platform retained control of AER,
> + * it is responsible for clearing this status. In that case, the
> + * signaling device may not even be visible to the OS.
> + */
> + if (host->native_aer || pcie_ports_native) {
> + pcie_clear_device_status(dev);
> + pci_aer_clear_nonfatal_status(dev);
> + pci_aer_clear_fatal_status(dev);
> + }
> +
> + pci_info(dev, "CXL uncorrectable error.\n");
> +}
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 82a0401c58d3..5b539b5bf0d1 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -864,6 +864,9 @@ enum pci_ers_result {
>
> /* No AER capabilities registered for the driver */
> PCI_ERS_RESULT_NO_AER_DRIVER = (__force pci_ers_result_t) 6,
> +
> + /* System is unstable, panic */
> + PCI_ERS_RESULT_PANIC = (__force pci_ers_result_t) 7,
> };
>
> /* PCI bus error event callbacks */
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery in AER service driver
2025-02-12 0:24 ` Dan Williams
@ 2025-02-14 19:36 ` Bowman, Terry
0 siblings, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-02-14 19:36 UTC (permalink / raw)
To: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/2025 6:24 PM, Dan Williams wrote:
> Terry Bowman wrote:
>> Existing recovery procedure for PCIe uncorrectable errors (UCE) does not
>> apply to CXL devices. Recovery can not be used for CXL devices because of
>> potential corruption on what can be system memory. Also, current PCIe UCE
>> recovery, in the case of a Root Port (RP) or Downstream Switch Port (DSP),
>> does not begin at the RP/DSP but begins at the first downstream device.
>> This will miss handling CXL Protocol Errors in a CXL RP or DSP. A separate
>> CXL recovery is needed because of the different handling requirements
>>
>> Add a new function, cxl_do_recovery() using the following.
>>
>> Add cxl_walk_bridge() to iterate the detected error's sub-topology.
>> cxl_walk_bridge() is similar to pci_walk_bridge() but the CXL flavor
>> will begin iteration at the RP or DSP rather than beginning at the
>> first downstream device.
>>
>> pci_walk_bridge() is candidate to possibly reuse cxl_walk_bridge() but
>> needs further investigation. This will be left for future improvement
>> to make the CXL and PCI handling paths more common.
>>
>> Add cxl_report_error_detected() as an analog to report_error_detected().
>> It will call pci_driver::cxl_err_handlers for each iterated downstream
>> device. The pci_driver::cxl_err_handler's UCE handler returns a boolean
>> indicating if there was a UCE error detected during handling.
>>
>> cxl_do_recovery() uses the status from cxl_report_error_detected() to
>> determine how to proceed. Non-fatal CXL UCE errors will be treated as
>> fatal. If a UCE was present during handling then cxl_do_recovery()
>> will kernel panic.
> For what this is:
>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
>
> ...and perhaps it addresses my concern on the prior patch that
> ->error_detected() is responsible for the safety of checking that in
> fact a CXL internal error / UCE was detected.
Thanks Dan
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
2025-02-12 2:00 ` Dan Williams
@ 2025-02-14 19:46 ` Bowman, Terry
2025-02-14 21:29 ` Dan Williams
0 siblings, 1 reply; 94+ messages in thread
From: Bowman, Terry @ 2025-02-14 19:46 UTC (permalink / raw)
To: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/11/2025 8:00 PM, Dan Williams wrote:
> Terry Bowman wrote:
>> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
>>
>> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
>> pointer to the CXL Upstream Port's mapped RAS registers.
>>
>> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
>> register mapping. This is similar to the existing
>> cxl_dport_init_ras_reporting() but for USP devices.
>>
>> The USP may have multiple downstream endpoints. Before mapping RAS
>> registers check if the registers are already mapped.
> Yes, now this sharing makes sense, but the ras_init_mutex +
> cxl_init_ep_ports_aer() approach to solving it is broken.
>
>> Introduce a mutex for synchronizing accesses to the cached RAS
>> mapping.
> In this case, especially for VH configs, you should just be able to map
> the RAS registers once from cxl_endpoint_port_probe(). That will
> naturally only be called once when the first endpoint arrives, and will
> never be torn down until the last cxl_detach_ep() event triggers
> delete_switch_port().
There is still RPs and USPs that will be called for mapping more than once,
right? This will require synchronization, right?
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
2025-02-14 15:15 ` Jonathan Cameron
@ 2025-02-14 19:50 ` Bowman, Terry
0 siblings, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-02-14 19:50 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave, dave.jiang,
alison.schofield, vishal.l.verma, dan.j.williams, bhelgaas,
mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/14/2025 9:15 AM, Jonathan Cameron wrote:
> On Tue, 11 Feb 2025 13:24:35 -0600
> Terry Bowman <terry.bowman@amd.com> wrote:
>
>> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
>>
>> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
>> pointer to the CXL Upstream Port's mapped RAS registers.
>>
>> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
>> register mapping. This is similar to the existing
>> cxl_dport_init_ras_reporting() but for USP devices.
>>
>> The USP may have multiple downstream endpoints. Before mapping RAS
>> registers check if the registers are already mapped.
>>
>> Introduce a mutex for synchronizing accesses to the cached RAS
>> mapping.
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> Reviewed-by: Gregory Price <gourry@gourry.net>
>> /**
>> * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
>> * @dport: the cxl_dport that needs to be initialized
>> @@ -801,7 +819,6 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport)
>> BIT(CXL_CM_CAP_CAP_ID_RAS)))
>> dev_err(dport_dev, "Failed to map RAS capability\n");
>> mutex_unlock(&ras_init_mutex);
>> -
> Grumpy hat (it is Friday afternoon). Shouldn't be in this patch!
Thanks. This is removed from this patch in next revision.
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers
2025-02-13 15:43 ` Bowman, Terry
@ 2025-02-14 21:24 ` Dan Williams
2025-02-14 22:23 ` Bowman, Terry
0 siblings, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-14 21:24 UTC (permalink / raw)
To: Bowman, Terry, Dan Williams, linux-cxl, linux-kernel, linux-pci,
nifan.cxl, dave, jonathan.cameron, dave.jiang, alison.schofield,
vishal.l.verma, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Bowman, Terry wrote:
>
>
> On 2/11/2025 7:23 PM, Dan Williams wrote:
> > Terry Bowman wrote:
> >> The CXL mem driver (cxl_mem) currently maps and caches a pointer to RAS
> >> registers for the endpoint's Root Port. The same needs to be done for
> >> each of the CXL Downstream Switch Ports and CXL Root Ports found between
> >> the endpoint and CXL Host Bridge.
> >>
> >> Introduce cxl_init_ep_ports_aer() to be called for each CXL Port in the
> >> sub-topology between the endpoint and the CXL Host Bridge. This function
> >> will determine if there are CXL Downstream Switch Ports or CXL Root Ports
> >> associated with this Port. The same check will be added in the future for
> >> upstream switch ports.
> >>
> >> Move the RAS register map logic from cxl_dport_map_ras() into
> >> cxl_dport_init_ras_reporting(). This eliminates the need for the helper
> >> function, cxl_dport_map_ras().
> > Not sure about the motivation here...
> >
> >> cxl_init_ep_ports_aer() calls cxl_dport_init_ras_reporting() to map
> >> the RAS registers for CXL Downstream Switch Ports and CXL Root Ports.
> > Ok, makes sense...
> >
> >> cxl_dport_init_ras_reporting() must check for previously mapped registers
> >> before mapping. This is required because multiple Endpoints under a CXL
> >> switch may share an upstream CXL Root Port, CXL Downstream Switch Port,
> >> or CXL Downstream Switch Port. Ensure the RAS registers are only mapped
> >> once.
> > Sounds broken. Every device upstream-port only has one downstream port.
> >
> > A CXL switch config looks like this:
> >
> > │
> > ┌──────────┼────────────┐
> > │SWITCH ┌┴─┐ │
> > │ │UP│ │
> > │ └─┬┘ │
> > │ ┌──────┼─────┐ │
> > │ │ │ │ │
> > │ ┌┴─┐ ┌─┴┐ ┌─┴┐ │
> > │ │DP│ │DP│ │DP│ │
> > │ └┬─┘ └─┬┘ └─┬┘ │
> > └────┼──────┼─────┼─────┘
> > ┌┴─┐ ┌─┴┐ ┌─┴┐
> > │EP│ │EP│ │EP│
> > └──┘ └──┘ └──┘
> >
> > ...so how can an endpoint ever find that its immediate parent downstream
> > port has already been mapped?
>
>
> ┌─┴─┐
> │RP1│
> └─┬─┘
> ┌───────────┼───────────┐
> │SWITCH ┌─┴─┐ │
> │ │UP1│ │ RP1 - 0c:00.0
> │ └─┬─┘ │ UP1 - 0d:00.0
> │ ┌──────┼─────┐ │ DP1 - 0e:00.0
> │ │ │ │ │
> │ ┌─┴─┐ ┌─┴─┐ ┌─┴─┐ │
> │ │DP1│ │DP2│ │DP3│ │
> │ └─┬─┘ └─┬─┘ └─┬─┘ │
> └────┼──────┼─────┼─────┘
> ┌─┴─┐ ┌─┴─┐ ┌─┴─┐
> │EP1│ │EP2│ │EP3│
> └───┘ └───┘ └───┘
>
>
> It cant but the root RP and USP have duplicate calls for each EP in the example diagram.
> The function's purpose is to map RAS registers and cache the address. This reuses the
> same function for RP and DSP. The DSP will never be previously mapped as you indicated.
Are you talking about in the current code, which should have already
reported problems due to multiple overlapping mappings, or with the
proposed changes? Can you clarify the sequenece of calls that triggers
the multiple mappings of RP1?
Also, if EP1 and EP2 race to establish the RP1 mapping, then wouldn't
EP1 and EP2 also race to tear it down? What prevents EP2 from unmapping
RP1 if EP1 still needs it mapped?
I would prefer that rather than EP1 being responsible for mapping RP1
RAS, and a lock to prevent EP2 and EP3 from also repeating that, it
should be UP1 in cxl_switch_port_probe() taking responsibility for
mapping RP1 RAS.
One of the known problems with cxl_switch_port_probe() is that it
enumerates all dports regardless of attachment. That would be where I
would expect problems of dports already going through initialization
prematurely in advance of an endpoint showing up. However, that's a
different fix.
[..]
> >> +
> >> + /* dport may have more than 1 downstream EP. Check if already mapped. */
> >> + mutex_lock(&ras_init_mutex);
> > I suspect this lock and check got added to workaround "Failed to request
> > region" messages coming out of devm_cxl_iomap_block() in testing? Per
> > above, that's not "more than 1 downstream EPi", that's "failure to clean
> > up the last mapping for the next cxl_mem_probe() event of the same
> > endpoint".
> Synchronization was added to handle the concurrent accesses. I never observed
> issues due to the race condition for RP and USP but I confirmed through further
> testing it is a real potential issue for the RP and USP.
It is still not clear to me how this singleton lock helps when multiple
EPs are sharing a resource that both races init and shutdown.
> You recommended, in the next patch, to map USP RAS registers from cxl_endpoint_port_probe().
> Would you like the RP and DSP mapping to be called from cxl_endpoint_port_probe() as well? Terry
I think it is broken for an EP to be reaching through a switch to
initialize a shared resource at the RP level. Each level of the
hierarchy should take care of its immediate parent. We need this
bottom-up incremental arrangement due to the way that CXL hides
register blocks until CXL link up.
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream Switch Port RAS registers
2025-02-14 19:46 ` Bowman, Terry
@ 2025-02-14 21:29 ` Dan Williams
0 siblings, 0 replies; 94+ messages in thread
From: Dan Williams @ 2025-02-14 21:29 UTC (permalink / raw)
To: Bowman, Terry, Dan Williams, linux-cxl, linux-kernel, linux-pci,
nifan.cxl, dave, jonathan.cameron, dave.jiang, alison.schofield,
vishal.l.verma, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Bowman, Terry wrote:
>
>
> On 2/11/2025 8:00 PM, Dan Williams wrote:
> > Terry Bowman wrote:
> >> Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers.
> >>
> >> Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a
> >> pointer to the CXL Upstream Port's mapped RAS registers.
> >>
> >> Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS
> >> register mapping. This is similar to the existing
> >> cxl_dport_init_ras_reporting() but for USP devices.
> >>
> >> The USP may have multiple downstream endpoints. Before mapping RAS
> >> registers check if the registers are already mapped.
> > Yes, now this sharing makes sense, but the ras_init_mutex +
> > cxl_init_ep_ports_aer() approach to solving it is broken.
> >
> >> Introduce a mutex for synchronizing accesses to the cached RAS
> >> mapping.
> > In this case, especially for VH configs, you should just be able to map
> > the RAS registers once from cxl_endpoint_port_probe(). That will
> > naturally only be called once when the first endpoint arrives, and will
> > never be torn down until the last cxl_detach_ep() event triggers
> > delete_switch_port().
> There is still RPs and USPs that will be called for mapping more than once,
> right? This will require synchronization, right?
I feel like this would be a symptom of endpoint registration doing too
much work. endpoint ports should only care about enabling RAS in their
immediate upstream dport. So, what seems to be missing is upstream ports
doing the same for their upstream dport.
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors
2025-02-14 2:18 ` Dan Williams
@ 2025-02-14 21:43 ` Bowman, Terry
2025-02-15 0:20 ` Dan Williams
0 siblings, 1 reply; 94+ messages in thread
From: Bowman, Terry @ 2025-02-14 21:43 UTC (permalink / raw)
To: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/13/2025 8:18 PM, Dan Williams wrote:
> Terry Bowman wrote:
>> Introduce correctable and uncorrectable (UCE) CXL PCIe Port Protocol Error
>> handlers.
>>
>> The handlers will be called with a 'struct pci_dev' parameter
>> indicating the CXL Port device requiring handling. The CXL PCIe Port
>> device's underlying 'struct device' will match the port device in the
>> CXL topology.
>>
>> Use the PCIe Port's device object to find the matching CXL Upstream Switch
>> Port, CXL Downstream Switch Port, or CXL Root Port in the CXL topology. The
>> matching CXL Port device should contain a cached reference to the RAS
>> register block. The cached RAS block will be used in handling the error.
>>
>> Invoke the existing __cxl_handle_ras() or __cxl_handle_cor_ras() using
>> a reference to the RAS registers as a parameter. These functions will use
>> the RAS register reference to indicate an error and clear the device's RAS
>> status.
>>
>> Update __cxl_handle_ras() to return PCI_ERS_RESULT_PANIC in the case
>> an error is present in the RAS status. Otherwise, return
>> PCI_ERS_RESULT_NONE.
> So I have been having this nagging feeling while reviewing this set that
> perhaps the CXL error handlers should not be 'struct pci_error_handlers'
> relative to a 'struct pci_driver', but instead 'struct
> cxl_error_handlers' that are added to 'struct cxl_driver', in particular
> 'cxl_port_driver'.
>
> See below for what I *think* are insurmountable problems when a PCI
> error handler is tasked with looking up @ras_base in a race free manner.
> Note I say "think" because I could be misreading or missing some other
> circumstance that makes this ok, so do please challenge if you think I
> missed something because what follows below is another major direction
> change.
>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
>> ---
>> drivers/cxl/core/pci.c | 81 +++++++++++++++++++++++++++++++++++++++---
>> 1 file changed, 77 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
>> index af809e7cbe3b..3f13d9dfb610 100644
>> --- a/drivers/cxl/core/pci.c
>> +++ b/drivers/cxl/core/pci.c
>> @@ -699,7 +699,7 @@ static void header_log_copy(void __iomem *ras_base, u32 *log)
>> * Log the state of the RAS status registers and prepare them to log the
>> * next error status. Return 1 if reset needed.
>> */
>> -static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>> +static pci_ers_result_t __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>> {
>> u32 hl[CXL_HEADERLOG_SIZE_U32];
>> void __iomem *addr;
>> @@ -708,13 +708,13 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>>
>> if (!ras_base) {
>> dev_warn_once(dev, "CXL RAS register block is not mapped");
>> - return false;
>> + return PCI_ERS_RESULT_NONE;
>> }
>>
>> addr = ras_base + CXL_RAS_UNCORRECTABLE_STATUS_OFFSET;
>> status = readl(addr);
>> if (!(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK))
>> - return false;
>> + return PCI_ERS_RESULT_NONE;
>>
>> /* If multiple errors, log header points to first error from ctrl reg */
>> if (hweight32(status) > 1) {
>> @@ -733,7 +733,7 @@ static bool __cxl_handle_ras(struct device *dev, void __iomem *ras_base)
>>
>> writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
>>
>> - return true;
>> + return PCI_ERS_RESULT_PANIC;
>> }
>>
>> static bool cxl_handle_endpoint_ras(struct cxl_dev_state *cxlds)
>> @@ -782,6 +782,79 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
>> writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND);
>> }
>>
>> +static int match_uport(struct device *dev, const void *data)
>> +{
>> + const struct device *uport_dev = data;
>> + struct cxl_port *port;
>> +
>> + if (!is_cxl_port(dev))
>> + return 0;
>> +
>> + port = to_cxl_port(dev);
>> +
>> + return port->uport_dev == uport_dev;
>> +}
>> +
>> +static void __iomem *cxl_pci_port_ras(struct pci_dev *pdev, struct device **dev)
>> +{
>> + void __iomem *ras_base;
>> +
>> + if (!pdev || !*dev) {
>> + pr_err("Failed, parameter is NULL");
>> + return NULL;
>> + }
>> +
>> + if ((pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) ||
>> + (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM)) {
>> + struct cxl_port *port __free(put_cxl_port);
>> + struct cxl_dport *dport = NULL;
>> +
>> + port = find_cxl_port(&pdev->dev, &dport);
> side comment: please always declare and assign scope-based-cleanup
> variables on the same line, i.e.:
>
> struct cxl_port *port __free(put_cxl_port) =
> find_cxl_port(&pdev->dev, &dport);
>
> Yes, that means violating the coding-style rule of preferring variable
> declarations at the top of blocks. This is for 2 reasons:
>
> * The variable is uninitialized. If future refactoring injects an early
> exit then unitialized garbage gets passed to put_cxl_port().
>
> * The cosmetic order of the declaration is not the unwind order. If
> future refactoring introduces other scope-based-cleanup variables it
> requires additional cleanup to move the declaration to satisfy unwind
> dependencies.
Got it. Thanks for pointing out.
>> + if (!port) {
>> + pci_err(pdev, "Failed to find root/dport in CXL topology\n");
>> + return NULL;
>> + }
>> +
>> + ras_base = dport ? dport->regs.ras : NULL;
>> + *dev = &port->dev;
> Ok, so here is where the trouble I was alluding to earlier begins. At
> this point we leave this scope which means @port will have its reference
> dropped and may be freed by the time the caller tries to use it.
>
> Additionally, @ras_base is only valid while @port->dev.driver is set. In
> this set, cxl_do_recovery() is only holding the device lock of @pdev
> which means nothing synchronizes against @ras_base pointing to garbage
> because a cxl_port was unbound / unplugged / disabled while error
> recovery was running.
>
> Both of those problems go away if upon entry to ->error_detected() it
> can already be assumed that the context holds both a 'struct cxl_port'
> object reference, and the device_lock() for that object.
I think the question is will there be much gained by taking the lock
earlier? The difference between the current implementation and the
proposed would be when the reference (or lock) is taken: cxl_report_error()
or cxl_port_error_detected()/cxl_port_cor_error_detected(). It's only a
few function calls difference but the biggest difference is in the CXL
topology search without reference or lock protection (you point at here).
> As for how to fix it, one idea is to have the AER core post CXL events
> to their own fifo for the CXL core to handle. Something like have
> aer_isr_one_error(), upon detection of an internal error on a CXL port
> device, post the 'struct aer_err_source' to a new kfifo and wake up a
> CXL core thread to run cxl_do_recovery() against the CXL port device
> topology instead of the PCI device topology.
>
> Essentially, the main point of cxl_do_recovery() is the acknowledgement
> that the PCI core does not have the context to judge the severity of
> CXL events, or fully annotate events with all the potential kernel
> objects impacted by an event. It is also the case that we need a common
> landing spot for PCI AER notified CXL error events and ACPI GHES
> notified CXL CPER records. So both PCI AER, and CPER notified errors
> need to end up in the same cxl_do_recovery() path that walks the CXL
> port topology.
Understood, it would fold in the GHES CPER too.
> The CXL Type-2 series is showing uptake on accelerators registering
> 'struct cxl_memdev' objects to report their CXL.mem capabilities. I
> imagine that effort would eventually end up with a scheme that
> accelerators can register a cxl_error_handler instance with that memdev
> to get involved in potentially recovering CXL.mem errors. For example,
> it may be the case that CXL error isolation finally has a viable use
> case when the accelerator knows it is the only device impacted by an
> isolation event and can safely reset that entire host-bridge to recover.
> That is difficult to achieve in the PCI error handler context.
Which directory do you see the CXL error handling and support landing
in: pci/pcie/ or cxl/core/ or elsewhere ?
Should we consider submitting this patchset first and then adding the CXL
kfifo changes you mention? It sounds like we need this for FW-first and
could be reused to solve the OS-first issue (time without a lock).
Or, if you like I can start to add the CXL kfifo changes now.
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers
2025-02-14 21:24 ` Dan Williams
@ 2025-02-14 22:23 ` Bowman, Terry
2025-02-14 22:42 ` Dan Williams
0 siblings, 1 reply; 94+ messages in thread
From: Bowman, Terry @ 2025-02-14 22:23 UTC (permalink / raw)
To: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/14/2025 3:24 PM, Dan Williams wrote:
> Bowman, Terry wrote:
>>
>> On 2/11/2025 7:23 PM, Dan Williams wrote:
>>> Terry Bowman wrote:
>>>> The CXL mem driver (cxl_mem) currently maps and caches a pointer to RAS
>>>> registers for the endpoint's Root Port. The same needs to be done for
>>>> each of the CXL Downstream Switch Ports and CXL Root Ports found between
>>>> the endpoint and CXL Host Bridge.
>>>>
>>>> Introduce cxl_init_ep_ports_aer() to be called for each CXL Port in the
>>>> sub-topology between the endpoint and the CXL Host Bridge. This function
>>>> will determine if there are CXL Downstream Switch Ports or CXL Root Ports
>>>> associated with this Port. The same check will be added in the future for
>>>> upstream switch ports.
>>>>
>>>> Move the RAS register map logic from cxl_dport_map_ras() into
>>>> cxl_dport_init_ras_reporting(). This eliminates the need for the helper
>>>> function, cxl_dport_map_ras().
>>> Not sure about the motivation here...
>>>
>>>> cxl_init_ep_ports_aer() calls cxl_dport_init_ras_reporting() to map
>>>> the RAS registers for CXL Downstream Switch Ports and CXL Root Ports.
>>> Ok, makes sense...
>>>
>>>> cxl_dport_init_ras_reporting() must check for previously mapped registers
>>>> before mapping. This is required because multiple Endpoints under a CXL
>>>> switch may share an upstream CXL Root Port, CXL Downstream Switch Port,
>>>> or CXL Downstream Switch Port. Ensure the RAS registers are only mapped
>>>> once.
>>> Sounds broken. Every device upstream-port only has one downstream port.
>>>
>>> A CXL switch config looks like this:
>>>
>>> │
>>> ┌──────────┼────────────┐
>>> │SWITCH ┌┴─┐ │
>>> │ │UP│ │
>>> │ └─┬┘ │
>>> │ ┌──────┼─────┐ │
>>> │ │ │ │ │
>>> │ ┌┴─┐ ┌─┴┐ ┌─┴┐ │
>>> │ │DP│ │DP│ │DP│ │
>>> │ └┬─┘ └─┬┘ └─┬┘ │
>>> └────┼──────┼─────┼─────┘
>>> ┌┴─┐ ┌─┴┐ ┌─┴┐
>>> │EP│ │EP│ │EP│
>>> └──┘ └──┘ └──┘
>>>
>>> ...so how can an endpoint ever find that its immediate parent downstream
>>> port has already been mapped?
>>
>> ┌─┴─┐
>> │RP1│
>> └─┬─┘
>> ┌───────────┼───────────┐
>> │SWITCH ┌─┴─┐ │
>> │ │UP1│ │ RP1 - 0c:00.0
>> │ └─┬─┘ │ UP1 - 0d:00.0
>> │ ┌──────┼─────┐ │ DP1 - 0e:00.0
>> │ │ │ │ │
>> │ ┌─┴─┐ ┌─┴─┐ ┌─┴─┐ │
>> │ │DP1│ │DP2│ │DP3│ │
>> │ └─┬─┘ └─┬─┘ └─┬─┘ │
>> └────┼──────┼─────┼─────┘
>> ┌─┴─┐ ┌─┴─┐ ┌─┴─┐
>> │EP1│ │EP2│ │EP3│
>> └───┘ └───┘ └───┘
>>
>>
>> It cant but the root RP and USP have duplicate calls for each EP in the example diagram.
>> The function's purpose is to map RAS registers and cache the address. This reuses the
>> same function for RP and DSP. The DSP will never be previously mapped as you indicated.
> Are you talking about in the current code, which should have already
> reported problems due to multiple overlapping mappings, or with the
> proposed changes? Can you clarify the sequenece of calls that triggers
> the multiple mappings of RP1?
Yes, in this thread I was discussing the current implementation. The
multiple calls to map RPs and USPs occur with the below calls. It iterates from
endpoint to RP. From patches 7 and 8 (v7):
devm_cxl_add_endpoint() cxl_init_ep_ports_aer(ep) - Calls for each port between EP and RP.cxl_dport_init_ras_reporting() - Maps DP/RP RAS
> Also, if EP1 and EP2 race to establish the RP1 mapping, then wouldn't
> EP1 and EP2 also race to tear it down? What prevents EP2 from unmapping
> RP1 if EP1 still needs it mapped?
>
> I would prefer that rather than EP1 being responsible for mapping RP1
> RAS, and a lock to prevent EP2 and EP3 from also repeating that, it
> should be UP1 in cxl_switch_port_probe() taking responsibility for
> mapping RP1 RAS.
>
> One of the known problems with cxl_switch_port_probe() is that it
> enumerates all dports regardless of attachment. That would be where I
> would expect problems of dports already going through initialization
> prematurely in advance of an endpoint showing up. However, that's a
> different fix.
Yes, there is a problem with the unmapping. Your recommendation is a good
idea.
Shouldn't cxl_switch_port_probe() map UP1 RAS as well?
> [..]
>>>> +
>>>> + /* dport may have more than 1 downstream EP. Check if already mapped. */
>>>> + mutex_lock(&ras_init_mutex);
>>> I suspect this lock and check got added to workaround "Failed to request
>>> region" messages coming out of devm_cxl_iomap_block() in testing? Per
>>> above, that's not "more than 1 downstream EPi", that's "failure to clean
>>> up the last mapping for the next cxl_mem_probe() event of the same
>>> endpoint".
>> Synchronization was added to handle the concurrent accesses. I never observed
>> issues due to the race condition for RP and USP but I confirmed through further
>> testing it is a real potential issue for the RP and USP.
> It is still not clear to me how this singleton lock helps when multiple
> EPs are sharing a resource that both races init and shutdown.
It doesn't. I overlooked the chaotic unmap situation unfortunately.
>> You recommended, in the next patch, to map USP RAS registers from cxl_endpoint_port_probe().
>> Would you like the RP and DSP mapping to be called from cxl_endpoint_port_probe() as well? Terry
> I think it is broken for an EP to be reaching through a switch to
> initialize a shared resource at the RP level. Each level of the
> hierarchy should take care of its immediate parent. We need this
> bottom-up incremental arrangement due to the way that CXL hides
> register blocks until CXL link up.
Ok, understood. I have already moved over the port iteration that was in cxl_init_ep_ports_aer() to cxl_endpoint_port_probe(). I now need to change the logic that iterates EP to RP to be more localized (just to the endpoint's immediate DSP/RP). And from your comments above I understand I need to update the cxl_switch_port_probe() to map upstream RP (DSP for multi-level SW).Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers
2025-02-14 22:23 ` Bowman, Terry
@ 2025-02-14 22:42 ` Dan Williams
0 siblings, 0 replies; 94+ messages in thread
From: Dan Williams @ 2025-02-14 22:42 UTC (permalink / raw)
To: Bowman, Terry, Dan Williams, linux-cxl, linux-kernel, linux-pci,
nifan.cxl, dave, jonathan.cameron, dave.jiang, alison.schofield,
vishal.l.verma, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Bowman, Terry wrote:
>
>
> On 2/14/2025 3:24 PM, Dan Williams wrote:
> > Bowman, Terry wrote:
> >>
> >> On 2/11/2025 7:23 PM, Dan Williams wrote:
> >>> Terry Bowman wrote:
> >>>> The CXL mem driver (cxl_mem) currently maps and caches a pointer to RAS
> >>>> registers for the endpoint's Root Port. The same needs to be done for
> >>>> each of the CXL Downstream Switch Ports and CXL Root Ports found between
> >>>> the endpoint and CXL Host Bridge.
> >>>>
> >>>> Introduce cxl_init_ep_ports_aer() to be called for each CXL Port in the
> >>>> sub-topology between the endpoint and the CXL Host Bridge. This function
> >>>> will determine if there are CXL Downstream Switch Ports or CXL Root Ports
> >>>> associated with this Port. The same check will be added in the future for
> >>>> upstream switch ports.
> >>>>
> >>>> Move the RAS register map logic from cxl_dport_map_ras() into
> >>>> cxl_dport_init_ras_reporting(). This eliminates the need for the helper
> >>>> function, cxl_dport_map_ras().
> >>> Not sure about the motivation here...
> >>>
> >>>> cxl_init_ep_ports_aer() calls cxl_dport_init_ras_reporting() to map
> >>>> the RAS registers for CXL Downstream Switch Ports and CXL Root Ports.
> >>> Ok, makes sense...
> >>>
> >>>> cxl_dport_init_ras_reporting() must check for previously mapped registers
> >>>> before mapping. This is required because multiple Endpoints under a CXL
> >>>> switch may share an upstream CXL Root Port, CXL Downstream Switch Port,
> >>>> or CXL Downstream Switch Port. Ensure the RAS registers are only mapped
> >>>> once.
> >>> Sounds broken. Every device upstream-port only has one downstream port.
> >>>
> >>> A CXL switch config looks like this:
> >>>
> >>> │
> >>> ┌──────────┼────────────┐
> >>> │SWITCH ┌┴─┐ │
> >>> │ │UP│ │
> >>> │ └─┬┘ │
> >>> │ ┌──────┼─────┐ │
> >>> │ │ │ │ │
> >>> │ ┌┴─┐ ┌─┴┐ ┌─┴┐ │
> >>> │ │DP│ │DP│ │DP│ │
> >>> │ └┬─┘ └─┬┘ └─┬┘ │
> >>> └────┼──────┼─────┼─────┘
> >>> ┌┴─┐ ┌─┴┐ ┌─┴┐
> >>> │EP│ │EP│ │EP│
> >>> └──┘ └──┘ └──┘
> >>>
> >>> ...so how can an endpoint ever find that its immediate parent downstream
> >>> port has already been mapped?
> >>
> >> ┌─┴─┐
> >> │RP1│
> >> └─┬─┘
> >> ┌───────────┼───────────┐
> >> │SWITCH ┌─┴─┐ │
> >> │ │UP1│ │ RP1 - 0c:00.0
> >> │ └─┬─┘ │ UP1 - 0d:00.0
> >> │ ┌──────┼─────┐ │ DP1 - 0e:00.0
> >> │ │ │ │ │
> >> │ ┌─┴─┐ ┌─┴─┐ ┌─┴─┐ │
> >> │ │DP1│ │DP2│ │DP3│ │
> >> │ └─┬─┘ └─┬─┘ └─┬─┘ │
> >> └────┼──────┼─────┼─────┘
> >> ┌─┴─┐ ┌─┴─┐ ┌─┴─┐
> >> │EP1│ │EP2│ │EP3│
> >> └───┘ └───┘ └───┘
> >>
> >>
> >> It cant but the root RP and USP have duplicate calls for each EP in the example diagram.
> >> The function's purpose is to map RAS registers and cache the address. This reuses the
> >> same function for RP and DSP. The DSP will never be previously mapped as you indicated.
> > Are you talking about in the current code, which should have already
> > reported problems due to multiple overlapping mappings, or with the
> > proposed changes? Can you clarify the sequenece of calls that triggers
> > the multiple mappings of RP1?
> Yes, in this thread I was discussing the current implementation. The
> multiple calls to map RPs and USPs occur with the below calls. It iterates from
> endpoint to RP. From patches 7 and 8 (v7):
>
> devm_cxl_add_endpoint() cxl_init_ep_ports_aer(ep) - Calls for each port between EP and RP.cxl_dport_init_ras_reporting() - Maps DP/RP RAS
Ah, thanks, I missed that. I misread the patch and thought that
cxl_init_ep_ports_aer() was only being called for the immediate dport
parent.
>
> > Also, if EP1 and EP2 race to establish the RP1 mapping, then wouldn't
> > EP1 and EP2 also race to tear it down? What prevents EP2 from unmapping
> > RP1 if EP1 still needs it mapped?
> >
> > I would prefer that rather than EP1 being responsible for mapping RP1
> > RAS, and a lock to prevent EP2 and EP3 from also repeating that, it
> > should be UP1 in cxl_switch_port_probe() taking responsibility for
> > mapping RP1 RAS.
> >
> > One of the known problems with cxl_switch_port_probe() is that it
> > enumerates all dports regardless of attachment. That would be where I
> > would expect problems of dports already going through initialization
> > prematurely in advance of an endpoint showing up. However, that's a
> > different fix.
> Yes, there is a problem with the unmapping. Your recommendation is a good
> idea.
>
> Shouldn't cxl_switch_port_probe() map UP1 RAS as well?
Yes, that would naturally fit there I think, especially because it
naturally handles the case of the port and mapping staying alive until
the last endpooint in that topology is removed.
> Ok, understood. I have already moved over the port iteration that was
> in cxl_init_ep_ports_aer() to cxl_endpoint_port_probe(). I now need to
> change the logic that iterates EP to RP to be more localized (just to
> the endpoint's immediate DSP/RP). And from your comments above I
> understand I need to update the cxl_switch_port_probe() to map
> upstream RP (DSP for multi-level SW).Terry
Sounds good, thanks Terry!
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors
2025-02-14 21:43 ` Bowman, Terry
@ 2025-02-15 0:20 ` Dan Williams
2025-02-18 15:33 ` Bowman, Terry
0 siblings, 1 reply; 94+ messages in thread
From: Dan Williams @ 2025-02-15 0:20 UTC (permalink / raw)
To: Bowman, Terry, Dan Williams, linux-cxl, linux-kernel, linux-pci,
nifan.cxl, dave, jonathan.cameron, dave.jiang, alison.schofield,
vishal.l.verma, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Bowman, Terry wrote:
[..]
> > Ok, so here is where the trouble I was alluding to earlier begins. At
> > this point we leave this scope which means @port will have its reference
> > dropped and may be freed by the time the caller tries to use it.
> >
> > Additionally, @ras_base is only valid while @port->dev.driver is set. In
> > this set, cxl_do_recovery() is only holding the device lock of @pdev
> > which means nothing synchronizes against @ras_base pointing to garbage
> > because a cxl_port was unbound / unplugged / disabled while error
> > recovery was running.
> >
> > Both of those problems go away if upon entry to ->error_detected() it
> > can already be assumed that the context holds both a 'struct cxl_port'
> > object reference, and the device_lock() for that object.
>
> I think the question is will there be much gained by taking the lock
> earlier? The difference between the current implementation and the
> proposed would be when the reference (or lock) is taken: cxl_report_error()
> or cxl_port_error_detected()/cxl_port_cor_error_detected(). It's only a
> few function calls difference but the biggest difference is in the CXL
> topology search without reference or lock protection (you point at here).
My point is that this series is holding the *wrong* device_lock():
I.e.:
> +static int cxl_report_error_detected(struct pci_dev *dev, void *data)
> +{
> + const struct cxl_error_handlers *cxl_err_handler;
> + pci_ers_result_t vote, *result = data;
> + struct pci_driver *pdrv;
> +
> + device_lock(&dev->dev);
This lock against the PCI device does nothing to protect against unbind events for the cxl_port
object...
> + pdrv = dev->driver;
> + if (!pdrv || !pdrv->cxl_err_handler ||
> + !pdrv->cxl_err_handler->error_detected)
> + goto out;
> +
> + cxl_err_handler = pdrv->cxl_err_handler;
> + vote = cxl_err_handler->error_detected(dev);
...subsequently any usage of @ras_base in this ->error_detected() is
racy.
> + *result = merge_result(*result, vote);
> +out:
> + device_unlock(&dev->dev);
[..]
> Which directory do you see the CXL error handling and support landing
> in: pci/pcie/ or cxl/core/ or elsewhere ?
In cxl/core/, that's the only place that understands CXL port topology
and the lifetime rules for dport RAS register mappings.
> Should we consider submitting this patchset first and then adding the CXL
> kfifo changes you mention? It sounds like we need this for FW-first and
> could be reused to solve the OS-first issue (time without a lock).
The problem is that the PCI core is always built-in and the CXL core is
modular. Without a kfifo() and a registration scheme the CXL core could
not remain modular.
> Or, if you like I can start to add the CXL kfifo changes now.
I feel like there's enough examples of kfifo in error handling to make
this not too burdensome, but let me know if you disagree. Otherwise,
would need to spend the time to figure out how to keep the test
environment functioning (cxl-test depends on modular core builds).
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors
2025-02-15 0:20 ` Dan Williams
@ 2025-02-18 15:33 ` Bowman, Terry
2025-02-18 17:15 ` Dan Williams
0 siblings, 1 reply; 94+ messages in thread
From: Bowman, Terry @ 2025-02-18 15:33 UTC (permalink / raw)
To: Dan Williams, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
bhelgaas, mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/14/2025 6:20 PM, Dan Williams wrote:
> Bowman, Terry wrote:
> [..]
>>> Ok, so here is where the trouble I was alluding to earlier begins. At
>>> this point we leave this scope which means @port will have its reference
>>> dropped and may be freed by the time the caller tries to use it.
>>>
>>> Additionally, @ras_base is only valid while @port->dev.driver is set. In
>>> this set, cxl_do_recovery() is only holding the device lock of @pdev
>>> which means nothing synchronizes against @ras_base pointing to garbage
>>> because a cxl_port was unbound / unplugged / disabled while error
>>> recovery was running.
>>>
>>> Both of those problems go away if upon entry to ->error_detected() it
>>> can already be assumed that the context holds both a 'struct cxl_port'
>>> object reference, and the device_lock() for that object.
>> I think the question is will there be much gained by taking the lock
>> earlier? The difference between the current implementation and the
>> proposed would be when the reference (or lock) is taken: cxl_report_error()
>> or cxl_port_error_detected()/cxl_port_cor_error_detected(). It's only a
>> few function calls difference but the biggest difference is in the CXL
>> topology search without reference or lock protection (you point at here).
> My point is that this series is holding the *wrong* device_lock():
>
> I.e.:
>
>> +static int cxl_report_error_detected(struct pci_dev *dev, void *data)
>> +{
>> + const struct cxl_error_handlers *cxl_err_handler;
>> + pci_ers_result_t vote, *result = data;
>> + struct pci_driver *pdrv;
>> +
>> + device_lock(&dev->dev);
> This lock against the PCI device does nothing to protect against unbind events for the cxl_port
> object...
I'll update to use the CXL device instead of the PCI device.
>> + pdrv = dev->driver;
>> + if (!pdrv || !pdrv->cxl_err_handler ||
>> + !pdrv->cxl_err_handler->error_detected)
>> + goto out;
>> +
>> + cxl_err_handler = pdrv->cxl_err_handler;
>> + vote = cxl_err_handler->error_detected(dev);
> ...subsequently any usage of @ras_base in this ->error_detected() is
> racy.
>
>> + *result = merge_result(*result, vote);
>> +out:
>> + device_unlock(&dev->dev);
> [..]
>> Which directory do you see the CXL error handling and support landing
>> in: pci/pcie/ or cxl/core/ or elsewhere ?
> In cxl/core/, that's the only place that understands CXL port topology
> and the lifetime rules for dport RAS register mappings.
>
>> Should we consider submitting this patchset first and then adding the CXL
>> kfifo changes you mention? It sounds like we need this for FW-first and
>> could be reused to solve the OS-first issue (time without a lock).
> The problem is that the PCI core is always built-in and the CXL core is
> modular. Without a kfifo() and a registration scheme the CXL core could
> not remain modular.
>
>> Or, if you like I can start to add the CXL kfifo changes now.
> I feel like there's enough examples of kfifo in error handling to make
> this not too burdensome, but let me know if you disagree. Otherwise,
> would need to spend the time to figure out how to keep the test
> environment functioning (cxl-test depends on modular core builds).
Thanks for the feedback. Yes, there are several examples and Smita is using for
FW-first as well. Correct me if I'm wrong but the goal in this case is
for the FW-first and OS-first to use the same kfifo.
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery in AER service driver
2025-02-14 15:11 ` Jonathan Cameron
@ 2025-02-18 15:43 ` Bowman, Terry
0 siblings, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-02-18 15:43 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave, dave.jiang,
alison.schofield, vishal.l.verma, dan.j.williams, bhelgaas,
mahesh, ira.weiny, oohall, Benjamin.Cheatham, rrichter,
nathan.fontenot, Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
On 2/14/2025 9:11 AM, Jonathan Cameron wrote:
> On Tue, 11 Feb 2025 13:24:33 -0600
> Terry Bowman <terry.bowman@amd.com> wrote:
>
>> Existing recovery procedure for PCIe uncorrectable errors (UCE) does not
>> apply to CXL devices. Recovery can not be used for CXL devices because of
>> potential corruption on what can be system memory. Also, current PCIe UCE
>> recovery, in the case of a Root Port (RP) or Downstream Switch Port (DSP),
>> does not begin at the RP/DSP but begins at the first downstream device.
>> This will miss handling CXL Protocol Errors in a CXL RP or DSP. A separate
>> CXL recovery is needed because of the different handling requirements
>>
>> Add a new function, cxl_do_recovery() using the following.
>>
>> Add cxl_walk_bridge() to iterate the detected error's sub-topology.
>> cxl_walk_bridge() is similar to pci_walk_bridge() but the CXL flavor
>> will begin iteration at the RP or DSP rather than beginning at the
> Hi Terry,
>
> Trivial nitpick but you wrap point is shrinking wrt to the previous paragraph.
> Just looks odd rather than actually mattering :)
I'll take more notice of this in the next revision. Thanks for the feedback.
>> first downstream device.
>>
>> pci_walk_bridge() is candidate to possibly reuse cxl_walk_bridge() but
>> needs further investigation. This will be left for future improvement
>> to make the CXL and PCI handling paths more common.
>>
>> Add cxl_report_error_detected() as an analog to report_error_detected().
>> It will call pci_driver::cxl_err_handlers for each iterated downstream
>> device. The pci_driver::cxl_err_handler's UCE handler returns a boolean
>> indicating if there was a UCE error detected during handling.
>>
>> cxl_do_recovery() uses the status from cxl_report_error_detected() to
>> determine how to proceed. Non-fatal CXL UCE errors will be treated as
>> fatal. If a UCE was present during handling then cxl_do_recovery()
>> will kernel panic.
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> One trivial suggestion inline. Probably something for another day!
>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Thanks Jonathan.
>> ---
>> drivers/pci/pci.h | 3 +++
>> drivers/pci/pcie/aer.c | 4 +++
>> drivers/pci/pcie/err.c | 58 ++++++++++++++++++++++++++++++++++++++++++
>> include/linux/pci.h | 3 +++
>> 4 files changed, 68 insertions(+)
>>
>> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
>> index 01e51db8d285..deb193b387af 100644
>> --- a/drivers/pci/pci.h
>> +++ b/drivers/pci/pci.h
>> @@ -722,6 +722,9 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
>> pci_channel_state_t state,
>> pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev));
>>
>> +/* CXL error reporting and handling */
>> +void cxl_do_recovery(struct pci_dev *dev);
>> +
>> bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
>> int pcie_retrain_link(struct pci_dev *pdev, bool use_lt);
>>
>> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
>> index 34ec0958afff..ee38db08d005 100644
>> --- a/drivers/pci/pcie/aer.c
>> +++ b/drivers/pci/pcie/aer.c
>> @@ -1012,6 +1012,8 @@ static int cxl_rch_handle_error_iter(struct pci_dev *dev, void *data)
>> err_handler->error_detected(dev, pci_channel_io_normal);
>> else if (info->severity == AER_FATAL)
>> err_handler->error_detected(dev, pci_channel_io_frozen);
>> +
>> + cxl_do_recovery(dev);
>> }
>> out:
>> device_unlock(&dev->dev);
>> @@ -1041,6 +1043,8 @@ static void cxl_handle_error(struct pci_dev *dev, struct aer_err_info *info)
>> pdrv->cxl_err_handler->cor_error_detected(dev);
>>
>> pcie_clear_device_status(dev);
>> + } else {
>> + cxl_do_recovery(dev);
>> }
>> }
>>
>> diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
>> index 31090770fffc..05f2d1ef4c36 100644
>> --- a/drivers/pci/pcie/err.c
>> +++ b/drivers/pci/pcie/err.c
>> @@ -24,6 +24,9 @@
>> static pci_ers_result_t merge_result(enum pci_ers_result orig,
>> enum pci_ers_result new)
>> {
>> + if (new == PCI_ERS_RESULT_PANIC)
>> + return PCI_ERS_RESULT_PANIC;
>> +
>> if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
>> return PCI_ERS_RESULT_NO_AER_DRIVER;
>>
>> @@ -276,3 +279,58 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
>>
>> return status;
>> }
>> +
>> +static void cxl_walk_bridge(struct pci_dev *bridge,
>> + int (*cb)(struct pci_dev *, void *),
>> + void *userdata)
>> +{
>> + if (cb(bridge, userdata))
>> + return;
>> +
>> + if (bridge->subordinate)
>> + pci_walk_bus(bridge->subordinate, cb, userdata);
>> +}
>> +
>> +static int cxl_report_error_detected(struct pci_dev *dev, void *data)
>> +{
>> + const struct cxl_error_handlers *cxl_err_handler;
>> + pci_ers_result_t vote, *result = data;
>> + struct pci_driver *pdrv;
>> +
>> + device_lock(&dev->dev);
> Could use
> guard(device)(&dev->dev);
>
>> + pdrv = dev->driver;
>> + if (!pdrv || !pdrv->cxl_err_handler ||
>> + !pdrv->cxl_err_handler->error_detected)
>> + goto out;
> allowing you to return here.
>
> Same approach would simplify the rch code as well.
Yes, I'll change to use a guard() here. I'll have to use the CXL device (not the PCI
device) as Dan pointed out. Also, this will be moved out of AER driver and into CXL core.
Regards,
Terry
>> +
>> + cxl_err_handler = pdrv->cxl_err_handler;
>> + vote = cxl_err_handler->error_detected(dev);
>> + *result = merge_result(*result, vote);
>> +out:
>> + device_unlock(&dev->dev);
>> + return 0;
>> +}
>> +
>> +void cxl_do_recovery(struct pci_dev *dev)
>> +{
>> + struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
>> + pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
>> +
>> + cxl_walk_bridge(dev, cxl_report_error_detected, &status);
>> + if (status == PCI_ERS_RESULT_PANIC)
>> + panic("CXL cachemem error.");
>> +
>> + /*
>> + * If we have native control of AER, clear error status in the device
>> + * that detected the error. If the platform retained control of AER,
>> + * it is responsible for clearing this status. In that case, the
>> + * signaling device may not even be visible to the OS.
>> + */
>> + if (host->native_aer || pcie_ports_native) {
>> + pcie_clear_device_status(dev);
>> + pci_aer_clear_nonfatal_status(dev);
>> + pci_aer_clear_fatal_status(dev);
>> + }
>> +
>> + pci_info(dev, "CXL uncorrectable error.\n");
>> +}
>
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors
2025-02-18 15:33 ` Bowman, Terry
@ 2025-02-18 17:15 ` Dan Williams
0 siblings, 0 replies; 94+ messages in thread
From: Dan Williams @ 2025-02-18 17:15 UTC (permalink / raw)
To: Bowman, Terry, Dan Williams, linux-cxl, linux-kernel, linux-pci,
nifan.cxl, dave, jonathan.cameron, dave.jiang, alison.schofield,
vishal.l.verma, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Bowman, Terry wrote:
[..]
> >> Or, if you like I can start to add the CXL kfifo changes now.
> > I feel like there's enough examples of kfifo in error handling to make
> > this not too burdensome, but let me know if you disagree. Otherwise,
> > would need to spend the time to figure out how to keep the test
> > environment functioning (cxl-test depends on modular core builds).
>
> Thanks for the feedback. Yes, there are several examples and Smita is using for
> FW-first as well. Correct me if I'm wrong but the goal in this case is
> for the FW-first and OS-first to use the same kfifo.
Not necessarily, the leaf handlers should unify around
cxl_do_recovery(), however you will notice that CPER PCIe AER events get
routed to the aer_recover_ring kfifo and native PCIe AER events get
collected by the aer_rpc.aer_fifo. Both of those route to
pcie_do_recovery() on the backend.
The CXL kfifo is to allow the CXL subsystem to remain modular and only
minimally burden the PCIe AER flow with just enough logic to determine
"not a PCIe AER event".
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port()
2025-02-11 19:24 ` [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port() Terry Bowman
2025-02-11 20:28 ` Bjorn Helgaas
2025-02-11 22:33 ` Dan Williams
@ 2025-03-04 19:11 ` Ira Weiny
2 siblings, 0 replies; 94+ messages in thread
From: Ira Weiny @ 2025-03-04 19:11 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> CXL and AER drivers need the ability to identify CXL devices and CXL port
> devices.
>
> First, add set_pcie_cxl() with logic checking for CXL Flexbus DVSEC
> presence. The CXL Flexbus DVSEC presence is used because it is required
> for all the CXL PCIe devices.[1]
>
> Add boolean 'struct pci_dev::is_cxl' with the purpose to cache the CXL
> Flexbus presence.
>
> Add pcie_is_cxl() as a macro to return 'struct pci_dev::is_cxl'.
>
> Add pcie_is_cxl_port() to check if a device is a CXL Root Port, CXL
> Upstream Switch Port, or CXL Downstream Switch Port. Also, verify the
> CXL Extensions DVSEC for Ports is present.[1]
>
> [1] CXL 3.1 Spec, 8.1.1 PCIe Designated Vendor-Specific Extended
> Capability (DVSEC) ID Assignment, Table 8-2
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
[snip]
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors
2025-02-11 19:24 ` [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors Terry Bowman
2025-02-12 0:11 ` Dave Jiang
2025-02-14 2:18 ` Dan Williams
@ 2025-03-05 0:22 ` Ira Weiny
2025-03-06 13:50 ` Bowman, Terry
2025-03-06 13:50 ` Bowman, Terry
2 siblings, 2 replies; 94+ messages in thread
From: Ira Weiny @ 2025-03-05 0:22 UTC (permalink / raw)
To: Terry Bowman, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, ira.weiny, oohall,
Benjamin.Cheatham, rrichter, nathan.fontenot,
Smita.KoralahalliChannabasappa, lukas, ming.li,
PradeepVineshReddy.Kodamati
Terry Bowman wrote:
> Introduce correctable and uncorrectable (UCE) CXL PCIe Port Protocol Error
> handlers.
>
> The handlers will be called with a 'struct pci_dev' parameter
> indicating the CXL Port device requiring handling. The CXL PCIe Port
> device's underlying 'struct device' will match the port device in the
> CXL topology.
>
> Use the PCIe Port's device object to find the matching CXL Upstream Switch
> Port, CXL Downstream Switch Port, or CXL Root Port in the CXL topology. The
> matching CXL Port device should contain a cached reference to the RAS
> register block. The cached RAS block will be used in handling the error.
>
> Invoke the existing __cxl_handle_ras() or __cxl_handle_cor_ras() using
> a reference to the RAS registers as a parameter. These functions will use
> the RAS register reference to indicate an error and clear the device's RAS
> status.
>
> Update __cxl_handle_ras() to return PCI_ERS_RESULT_PANIC in the case
> an error is present in the RAS status. Otherwise, return
> PCI_ERS_RESULT_NONE.
>
> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
[snip]
> +
> +static void cxl_port_cor_error_detected(struct pci_dev *pdev)
This causes a build error in this patch because it is defined but not used
until later.
Might be worth deferring to the future patch?
Ira
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors
2025-03-05 0:22 ` Ira Weiny
@ 2025-03-06 13:50 ` Bowman, Terry
2025-03-06 13:50 ` Bowman, Terry
1 sibling, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-03-06 13:50 UTC (permalink / raw)
To: Ira Weiny, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, oohall, Benjamin.Cheatham,
rrichter, nathan.fontenot, Smita.KoralahalliChannabasappa, lukas,
ming.li, PradeepVineshReddy.Kodamati
On 3/4/2025 6:22 PM, Ira Weiny wrote:
> Terry Bowman wrote:
>> Introduce correctable and uncorrectable (UCE) CXL PCIe Port Protocol Error
>> handlers.
>>
>> The handlers will be called with a 'struct pci_dev' parameter
>> indicating the CXL Port device requiring handling. The CXL PCIe Port
>> device's underlying 'struct device' will match the port device in the
>> CXL topology.
>>
>> Use the PCIe Port's device object to find the matching CXL Upstream Switch
>> Port, CXL Downstream Switch Port, or CXL Root Port in the CXL topology. The
>> matching CXL Port device should contain a cached reference to the RAS
>> register block. The cached RAS block will be used in handling the error.
>>
>> Invoke the existing __cxl_handle_ras() or __cxl_handle_cor_ras() using
>> a reference to the RAS registers as a parameter. These functions will use
>> the RAS register reference to indicate an error and clear the device's RAS
>> status.
>>
>> Update __cxl_handle_ras() to return PCI_ERS_RESULT_PANIC in the case
>> an error is present in the RAS status. Otherwise, return
>> PCI_ERS_RESULT_NONE.
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> [snip]
>
>> +
>> +static void cxl_port_cor_error_detected(struct pci_dev *pdev)
> This causes a build error in this patch because it is defined but not used
> until later.
>
> Might be worth deferring to the future patch?
>
> Ira
Hi Ira,
Thanks. I moved the patchset to prevent the warning.
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors
2025-03-05 0:22 ` Ira Weiny
2025-03-06 13:50 ` Bowman, Terry
@ 2025-03-06 13:50 ` Bowman, Terry
1 sibling, 0 replies; 94+ messages in thread
From: Bowman, Terry @ 2025-03-06 13:50 UTC (permalink / raw)
To: Ira Weiny, linux-cxl, linux-kernel, linux-pci, nifan.cxl, dave,
jonathan.cameron, dave.jiang, alison.schofield, vishal.l.verma,
dan.j.williams, bhelgaas, mahesh, oohall, Benjamin.Cheatham,
rrichter, nathan.fontenot, Smita.KoralahalliChannabasappa, lukas,
ming.li, PradeepVineshReddy.Kodamati
On 3/4/2025 6:22 PM, Ira Weiny wrote:
> Terry Bowman wrote:
>> Introduce correctable and uncorrectable (UCE) CXL PCIe Port Protocol Error
>> handlers.
>>
>> The handlers will be called with a 'struct pci_dev' parameter
>> indicating the CXL Port device requiring handling. The CXL PCIe Port
>> device's underlying 'struct device' will match the port device in the
>> CXL topology.
>>
>> Use the PCIe Port's device object to find the matching CXL Upstream Switch
>> Port, CXL Downstream Switch Port, or CXL Root Port in the CXL topology. The
>> matching CXL Port device should contain a cached reference to the RAS
>> register block. The cached RAS block will be used in handling the error.
>>
>> Invoke the existing __cxl_handle_ras() or __cxl_handle_cor_ras() using
>> a reference to the RAS registers as a parameter. These functions will use
>> the RAS register reference to indicate an error and clear the device's RAS
>> status.
>>
>> Update __cxl_handle_ras() to return PCI_ERS_RESULT_PANIC in the case
>> an error is present in the RAS status. Otherwise, return
>> PCI_ERS_RESULT_NONE.
>>
>> Signed-off-by: Terry Bowman <terry.bowman@amd.com>
> [snip]
>
>> +
>> +static void cxl_port_cor_error_detected(struct pci_dev *pdev)
> This causes a build error in this patch because it is defined but not used
> until later.
>
> Might be worth deferring to the future patch?
>
> Ira
Hi Ira,
Thanks. I moved the patch to prevent the warning.
Terry
^ permalink raw reply [flat|nested] 94+ messages in thread
end of thread, other threads:[~2025-03-06 13:50 UTC | newest]
Thread overview: 94+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-11 19:24 [PATCH v7 00/17] Enable CXL PCIe port protocol error handling and logging Terry Bowman
2025-02-11 19:24 ` [PATCH v7 01/17] PCI/AER: Introduce 'struct cxl_err_handlers' and add to 'struct pci_driver' Terry Bowman
2025-02-11 20:25 ` Bjorn Helgaas
2025-02-11 20:42 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 02/17] PCI/AER: Rename AER driver's interfaces to also indicate CXL PCIe Port support Terry Bowman
2025-02-11 20:26 ` Bjorn Helgaas
2025-02-11 20:44 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 03/17] CXL/PCI: Introduce PCIe helper functions pcie_is_cxl() and pcie_is_cxl_port() Terry Bowman
2025-02-11 20:28 ` Bjorn Helgaas
2025-02-11 20:38 ` Bowman, Terry
2025-02-11 22:33 ` Dan Williams
2025-02-12 19:07 ` Bowman, Terry
2025-02-12 19:51 ` Dan Williams
2025-03-04 19:11 ` Ira Weiny
2025-02-11 19:24 ` [PATCH v7 04/17] PCI/AER: Modify AER driver logging to report CXL or PCIe bus error type Terry Bowman
2025-02-11 20:28 ` Bjorn Helgaas
2025-02-11 23:47 ` Dan Williams
2025-02-12 19:15 ` Bowman, Terry
2025-02-12 19:57 ` Dan Williams
2025-02-12 21:08 ` Bowman, Terry
2025-02-12 21:17 ` Lukas Wunner
2025-02-11 19:24 ` [PATCH v7 05/17] PCI/AER: Add CXL PCIe Port correctable error support in AER service driver Terry Bowman
2025-02-11 20:28 ` Bjorn Helgaas
2025-02-11 23:58 ` Dan Williams
2025-02-12 21:52 ` Bowman, Terry
2025-02-11 19:24 ` [PATCH v7 06/17] PCI/AER: Add CXL PCIe Port uncorrectable error recovery " Terry Bowman
2025-02-11 20:29 ` Bjorn Helgaas
2025-02-11 21:59 ` Dave Jiang
2025-02-12 0:02 ` Gregory Price
2025-02-12 0:24 ` Dan Williams
2025-02-14 19:36 ` Bowman, Terry
2025-02-14 15:11 ` Jonathan Cameron
2025-02-18 15:43 ` Bowman, Terry
2025-02-14 17:36 ` Fan Ni
2025-02-11 19:24 ` [PATCH v7 07/17] cxl/pci: Map CXL PCIe Root Port and Downstream Switch Port RAS registers Terry Bowman
2025-02-11 22:40 ` Dave Jiang
2025-02-12 1:23 ` Dan Williams
2025-02-13 15:43 ` Bowman, Terry
2025-02-14 21:24 ` Dan Williams
2025-02-14 22:23 ` Bowman, Terry
2025-02-14 22:42 ` Dan Williams
2025-02-12 22:28 ` Alison Schofield
2025-02-12 22:37 ` Bowman, Terry
2025-02-11 19:24 ` [PATCH v7 08/17] cxl/pci: Map CXL PCIe Upstream " Terry Bowman
2025-02-11 23:02 ` Dave Jiang
2025-02-12 2:00 ` Dan Williams
2025-02-14 19:46 ` Bowman, Terry
2025-02-14 21:29 ` Dan Williams
2025-02-14 15:15 ` Jonathan Cameron
2025-02-14 19:50 ` Bowman, Terry
2025-02-11 19:24 ` [PATCH v7 09/17] cxl/pci: Update RAS handler interfaces to also support CXL PCIe Ports Terry Bowman
2025-02-11 23:26 ` Dave Jiang
2025-02-14 15:19 ` Jonathan Cameron
2025-02-11 19:24 ` [PATCH v7 10/17] cxl/pci: Add log message and add type check in existing RAS handlers Terry Bowman
2025-02-11 23:28 ` Dave Jiang
2025-02-12 22:59 ` Dan Williams
2025-02-13 0:08 ` Bowman, Terry
2025-02-14 15:28 ` Jonathan Cameron
2025-02-11 19:24 ` [PATCH v7 11/17] cxl/pci: Change find_cxl_port() to non-static Terry Bowman
2025-02-11 23:42 ` Dave Jiang
2025-02-13 23:15 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 12/17] cxl/pci: Add error handler for CXL PCIe Port RAS errors Terry Bowman
2025-02-12 0:11 ` Dave Jiang
2025-02-12 16:34 ` Bowman, Terry
2025-02-14 2:18 ` Dan Williams
2025-02-14 21:43 ` Bowman, Terry
2025-02-15 0:20 ` Dan Williams
2025-02-18 15:33 ` Bowman, Terry
2025-02-18 17:15 ` Dan Williams
2025-03-05 0:22 ` Ira Weiny
2025-03-06 13:50 ` Bowman, Terry
2025-03-06 13:50 ` Bowman, Terry
2025-02-11 19:24 ` [PATCH v7 13/17] cxl/pci: Add trace logging " Terry Bowman
2025-02-12 0:11 ` Gregory Price
2025-02-12 0:17 ` Dave Jiang
2025-02-12 0:19 ` Dave Jiang
2025-02-12 16:23 ` Bowman, Terry
2025-02-14 2:21 ` Dan Williams
2025-02-14 15:34 ` Jonathan Cameron
2025-02-11 19:24 ` [PATCH v7 14/17] cxl/pci: Update CXL Port RAS logging to also display PCIe SBDF Terry Bowman
2025-02-12 0:21 ` Dave Jiang
2025-02-12 16:20 ` Bowman, Terry
2025-02-12 23:30 ` Alison Schofield
2025-02-12 23:34 ` Bowman, Terry
2025-02-11 19:24 ` [PATCH v7 15/17] cxl/pci: Add support to assign and clear pci_driver::cxl_err_handlers Terry Bowman
2025-02-12 0:38 ` Dave Jiang
2025-02-14 2:29 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 16/17] PCI/AER: Enable internal errors for CXL Upstream and Downstream Switch Ports Terry Bowman
2025-02-11 20:25 ` Bjorn Helgaas
2025-02-11 20:40 ` Bowman, Terry
2025-02-12 0:40 ` Dave Jiang
2025-02-14 2:35 ` Dan Williams
2025-02-11 19:24 ` [PATCH v7 17/17] cxl/pci: Handle CXL Endpoint and RCH Protocol Errors separately from PCIe errors Terry Bowman
2025-02-14 2:43 ` Dan Williams
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox