|
| 1 | +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| 2 | +From: retro98boy <retro98boy@qq.com> |
| 3 | +Date: Wed, 25 Feb 2026 05:18:04 +0800 |
| 4 | +Subject: HACK: Ignore SError to enable rk3399 PCIe bus enumeration |
| 5 | + |
| 6 | +--- |
| 7 | + arch/arm64/kernel/traps.c | 19 ++++ |
| 8 | + drivers/pci/controller/pcie-rockchip-host.c | 50 ++++++++++ |
| 9 | + 2 files changed, 69 insertions(+) |
| 10 | + |
| 11 | +diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c |
| 12 | +index 111111111111..222222222222 100644 |
| 13 | +--- a/arch/arm64/kernel/traps.c |
| 14 | ++++ b/arch/arm64/kernel/traps.c |
| 15 | +@@ -976,8 +976,27 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned long esr) |
| 16 | + } |
| 17 | + } |
| 18 | + |
| 19 | ++bool rk3399_pcie_ignore_serror_enabled __read_mostly = false; |
| 20 | ++EXPORT_SYMBOL(rk3399_pcie_ignore_serror_enabled); |
| 21 | ++ |
| 22 | ++static int __init setup_rk3399_pcie_serror_handling(char *str) |
| 23 | ++{ |
| 24 | ++ rk3399_pcie_ignore_serror_enabled = true; |
| 25 | ++ pr_info("HACK: Ignore SError to enable rk3399 PCIe bus enumeration\n"); |
| 26 | ++ return 1; |
| 27 | ++} |
| 28 | ++__setup("rk3399_pcie_ignore_serror", setup_rk3399_pcie_serror_handling); |
| 29 | ++ |
| 30 | + void do_serror(struct pt_regs *regs, unsigned long esr) |
| 31 | + { |
| 32 | ++ if(rk3399_pcie_ignore_serror_enabled) { |
| 33 | ++ if (esr >> ESR_ELx_EC_SHIFT == ESR_ELx_EC_SERROR) { |
| 34 | ++ pr_debug("Ignoring SError Interrupt on CPU%d\n", |
| 35 | ++ smp_processor_id()); |
| 36 | ++ return; |
| 37 | ++ } |
| 38 | ++ } |
| 39 | ++ |
| 40 | + /* non-RAS errors are not containable */ |
| 41 | + if (!arm64_is_ras_serror(esr) || arm64_is_fatal_ras_serror(regs, esr)) |
| 42 | + arm64_serror_panic(regs, esr); |
| 43 | +diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c |
| 44 | +index 111111111111..222222222222 100644 |
| 45 | +--- a/drivers/pci/controller/pcie-rockchip-host.c |
| 46 | ++++ b/drivers/pci/controller/pcie-rockchip-host.c |
| 47 | +@@ -923,8 +923,58 @@ static int rockchip_pcie_resume_noirq(struct device *dev) |
| 48 | + return err; |
| 49 | + } |
| 50 | + |
| 51 | ++extern bool rk3399_pcie_ignore_serror_enabled; |
| 52 | + static int rockchip_pcie_probe(struct platform_device *pdev) |
| 53 | + { |
| 54 | ++ /* |
| 55 | ++ * When a PCIe device sends an unknown message, |
| 56 | ++ * the RK3399 triggers either a synchronous error or an SError. |
| 57 | ++ * If triggered by the A72 (via memory-mapped I/O), it results in an SError, |
| 58 | ++ * whereas the A53 results in a synchronous error. |
| 59 | ++ * To allow the RK3399 to continue PCIe enumeration, we can hijack and ignore these errors. |
| 60 | ++ * Since hijacking SErrors is simpler—requiring only a modification to the do_serror function, |
| 61 | ++ * we should pin the PCIe probe process to CPU4 (A72). |
| 62 | ++ * More detail, see: |
| 63 | ++ * https://forum.pine64.org/showthread.php?tid=6329&pid=65064 |
| 64 | ++ * https://lore.kernel.org/linux-pci/CAMdYzYoTwjKz4EN8PtD5pZfu3+SX+68JL+dfvmCrSnLL=K6Few@mail.gmail.com/ |
| 65 | ++ * https://lkml.org/lkml/2020/4/27/1041 |
| 66 | ++ */ |
| 67 | ++ if (rk3399_pcie_ignore_serror_enabled) { |
| 68 | ++ int try_count = 0; |
| 69 | ++ unsigned long start_jiffies = jiffies; |
| 70 | ++ int max_retries = 50; // Wait for a maximum of 50 × 10 = 500ms |
| 71 | ++ |
| 72 | ++ dev_info(&pdev->dev, "Checking CPU4 availability...\n"); |
| 73 | ++ |
| 74 | ++ while (!cpu_online(4) && try_count < max_retries) { |
| 75 | ++ try_count++; |
| 76 | ++ dev_info(&pdev->dev, |
| 77 | ++ "Wait CPU4: try=%d, elapsed=%u ms\n", |
| 78 | ++ try_count, |
| 79 | ++ jiffies_to_msecs(jiffies - start_jiffies)); |
| 80 | ++ msleep(10); |
| 81 | ++ } |
| 82 | ++ |
| 83 | ++ if (cpu_online(4)) { |
| 84 | ++ struct cpumask mask; |
| 85 | ++ cpumask_clear(&mask); |
| 86 | ++ cpumask_set_cpu(4, &mask); |
| 87 | ++ |
| 88 | ++ if (set_cpus_allowed_ptr(current, &mask) == 0) { |
| 89 | ++ dev_info( |
| 90 | ++ &pdev->dev, |
| 91 | ++ "Success: Probe migrated to CPU4 at try %d (%u ms)\n", |
| 92 | ++ try_count, |
| 93 | ++ jiffies_to_msecs(jiffies - |
| 94 | ++ start_jiffies)); |
| 95 | ++ } |
| 96 | ++ } else { |
| 97 | ++ dev_err(&pdev->dev, |
| 98 | ++ "Fail: CPU4 timeout after %d tries. Probing on CPU%d\n", |
| 99 | ++ try_count, smp_processor_id()); |
| 100 | ++ } |
| 101 | ++ } |
| 102 | ++ |
| 103 | + struct rockchip_pcie *rockchip; |
| 104 | + struct device *dev = &pdev->dev; |
| 105 | + struct pci_host_bridge *bridge; |
| 106 | +-- |
| 107 | +Armbian |
| 108 | + |
0 commit comments