-
-
Save pgwipeout/ed3fda653417f6694f79ddd708e19640 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From ceae51b1cc0e5a5b42999274657bd55606193661 Mon Sep 17 00:00:00 2001 | |
From: =?UTF-8?q?Jari=20H=C3=A4m=C3=A4l=C3=A4inen?= <[email protected]> | |
Date: Sun, 22 Nov 2020 15:24:49 +0200 | |
Subject: [PATCH] nuumio: pcie: Reimplement rockchip PCIe bus scan delay | |
Reimplementation of my old Rockchip PCIe bus scan delay patch for | |
kernels >= 5.9. | |
Delay may fix panix with some PCIe devices, like LSI SAS 9201-8i with | |
SAS2008 chipset in my case. | |
Crash dump (customized Manjaro kernel before this patch): | |
[ 1.229856] SError Interrupt on CPU4, code 0xbf000002 -- SError | |
[ 1.229860] CPU: 4 PID: 1 Comm: swapper/0 Not tainted 5.9.9-2.0-MANJARO-ARM #1 | |
[ 1.229862] Hardware name: Pine64 RockPro64 v2.1 (DT) | |
[ 1.229864] pstate: 60000085 (nZCv daIf -PAN -UAO BTYPE=--) | |
[ 1.229866] pc : rockchip_pcie_rd_conf+0xb4/0x270 | |
[ 1.229868] lr : rockchip_pcie_rd_conf+0x1b4/0x270 | |
[ 1.229870] sp : ffff80001004b850 | |
[ 1.229872] x29: ffff80001004b850 x28: 0000000000000001 | |
[ 1.229877] x27: 0000000000000000 x26: ffff00007a795000 | |
[ 1.229882] x25: ffff00007a7910b0 x24: 0000000000000000 | |
[ 1.229887] x23: 0000000000000000 x22: ffff00007b3a4380 | |
[ 1.229891] x21: ffff80001004b8c4 x20: 0000000000000004 | |
[ 1.229895] x19: 0000000000100000 x18: 0000000000000020 | |
[ 1.229900] x17: 0000000000000001 x16: 0000000000000019 | |
[ 1.229904] x15: ffff00007b222fd8 x14: ffffffffffffffff | |
[ 1.229908] x13: ffff00007a79ba1c x12: ffff00007a79b290 | |
[ 1.229912] x11: 0101010101010101 x10: 7f7f7f7f7f7f7f7f | |
[ 1.229917] x9 : ff72646268756463 x8 : 0000000000000391 | |
[ 1.229921] x7 : ffff80001004b880 x6 : 0000000000000001 | |
[ 1.229925] x5 : 0000000000000000 x4 : 0000000000000000 | |
[ 1.229930] x3 : 0000000000c00008 x2 : 000000000080000a | |
[ 1.229934] x1 : 0000000000000000 x0 : ffff800014000000 | |
[ 1.229939] Kernel panic - not syncing: Asynchronous SError Interrupt | |
[ 1.229942] CPU: 4 PID: 1 Comm: swapper/0 Not tainted 5.9.9-2.0-MANJARO-ARM #1 | |
[ 1.229944] Hardware name: Pine64 RockPro64 v2.1 (DT) | |
[ 1.229946] Call trace: | |
[ 1.229948] dump_backtrace+0x0/0x1d0 | |
[ 1.229949] show_stack+0x18/0x24 | |
[ 1.229951] dump_stack+0xc0/0x118 | |
[ 1.229953] panic+0x148/0x320 | |
[ 1.229955] nmi_panic+0x8c/0x90 | |
[ 1.229956] arm64_serror_panic+0x78/0x84 | |
[ 1.229958] do_serror+0x15c/0x160 | |
[ 1.229960] el1_error+0x84/0x100 | |
[ 1.229962] rockchip_pcie_rd_conf+0xb4/0x270 | |
[ 1.229964] pci_bus_read_config_dword+0x6c/0xd0 | |
[ 1.229966] pci_bus_generic_read_dev_vendor_id+0x34/0x1b0 | |
[ 1.229968] pci_scan_single_device+0xa4/0x144 | |
[ 1.229970] pci_scan_slot+0x40/0x12c | |
[ 1.229972] pci_scan_child_bus_extend+0x58/0x34c | |
[ 1.229974] pci_scan_bridge_extend+0x310/0x590 | |
[ 1.229976] pci_scan_child_bus_extend+0x210/0x34c | |
[ 1.229978] pci_scan_root_bus_bridge+0x68/0xdc | |
[ 1.229980] pci_host_probe+0x18/0xc4 | |
[ 1.229981] rockchip_pcie_probe+0x204/0x330 | |
[ 1.229984] platform_drv_probe+0x54/0xb0 | |
[ 1.229985] really_probe+0xe8/0x500 | |
[ 1.229987] driver_probe_device+0xd8/0xf0 | |
[ 1.229989] device_driver_attach+0xc0/0xcc | |
[ 1.229991] __driver_attach+0xa4/0x170 | |
[ 1.229993] bus_for_each_dev+0x70/0xc0 | |
[ 1.229994] driver_attach+0x24/0x30 | |
[ 1.229996] bus_add_driver+0x140/0x234 | |
[ 1.229998] driver_register+0x78/0x130 | |
[ 1.230000] __platform_driver_register+0x4c/0x60 | |
[ 1.230002] rockchip_pcie_driver_init+0x1c/0x28 | |
[ 1.230004] do_one_initcall+0x54/0x1c0 | |
[ 1.230005] do_initcalls+0xf4/0x130 | |
[ 1.230007] kernel_init_freeable+0x144/0x19c | |
[ 1.230009] kernel_init+0x14/0x11c | |
[ 1.230011] ret_from_fork+0x10/0x34 | |
[ 1.230035] SMP: stopping secondary CPUs | |
[ 1.230037] Kernel Offset: disabled | |
[ 1.230039] CPU features: 0x0240022,2100200c | |
[ 1.230041] Memory Limit: none | |
--- | |
.../admin-guide/kernel-parameters.txt | 8 ++++++ | |
.../boot/dts/rockchip/rk3399-rockpro64.dtsi | 1 + | |
drivers/pci/controller/pcie-rockchip-host.c | 25 +++++++++++++++++++ | |
drivers/pci/controller/pcie-rockchip.c | 6 +++++ | |
drivers/pci/controller/pcie-rockchip.h | 2 ++ | |
5 files changed, 42 insertions(+) | |
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt | |
index 44fde25bb221..941dc943eb84 100644 | |
--- a/Documentation/admin-guide/kernel-parameters.txt | |
+++ b/Documentation/admin-guide/kernel-parameters.txt | |
@@ -3816,6 +3816,14 @@ | |
nomsi Do not use MSI for native PCIe PME signaling (this makes | |
all PCIe root ports use INTx for all services). | |
+ pcie_rockchip_host.bus_scan_delay= [PCIE] Delay in ms before | |
+ scanning PCIe bus in Rockchip PCIe host driver. Some PCIe | |
+ cards seem to need delays that can be several hundred ms. | |
+ If set to greater than or equal to 0 this parameter will | |
+ override delay that can be set in device tree. | |
+ Values less than 0 mean that this parameter is ignored. | |
+ default=-1 | |
+ | |
pcmv= [HW,PCMCIA] BadgePAD 4 | |
pd_ignore_unused | |
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | |
index 6e553ff47534..9ec248d1c4c3 100644 | |
--- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | |
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | |
@@ -548,6 +548,7 @@ &pcie0 { | |
pinctrl-0 = <&pcie_perst>; | |
vpcie12v-supply = <&vcc12v_dcin>; | |
vpcie3v3-supply = <&vcc3v3_pcie>; | |
+ bus-scan-delay-ms = <1000>; | |
status = "okay"; | |
}; | |
diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c | |
index 9705059523a6..632dac43a037 100644 | |
--- a/drivers/pci/controller/pcie-rockchip-host.c | |
+++ b/drivers/pci/controller/pcie-rockchip-host.c | |
@@ -24,6 +24,7 @@ | |
#include <linux/kernel.h> | |
#include <linux/mfd/syscon.h> | |
#include <linux/module.h> | |
+#include <linux/moduleparam.h> | |
#include <linux/of_address.h> | |
#include <linux/of_device.h> | |
#include <linux/of_pci.h> | |
@@ -39,6 +40,9 @@ | |
#include "../pci.h" | |
#include "pcie-rockchip.h" | |
+static int bus_scan_delay = -1; | |
+module_param_named(bus_scan_delay, bus_scan_delay, int, S_IRUGO); | |
+ | |
static void rockchip_pcie_enable_bw_int(struct rockchip_pcie *rockchip) | |
{ | |
u32 status; | |
@@ -942,6 +946,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev) | |
struct device *dev = &pdev->dev; | |
struct pci_host_bridge *bridge; | |
int err; | |
+ u32 delay = 0; | |
if (!dev->of_node) | |
return -ENODEV; | |
@@ -993,6 +998,26 @@ static int rockchip_pcie_probe(struct platform_device *pdev) | |
bridge->sysdata = rockchip; | |
bridge->ops = &rockchip_pcie_ops; | |
+ /* Checking if bus scan delay was given from command line and prefer | |
+ * that over the value in device tree (which defaults to 0 if not set). | |
+ */ | |
+ if (bus_scan_delay >= 0) { | |
+ delay = bus_scan_delay; | |
+ dev_info(dev, "wait %u ms (from command-line) before bus scan\n", delay); | |
+ } else { | |
+ delay = rockchip->bus_scan_delay; | |
+ dev_info(dev, "wait %u ms (from device tree) before bus scan\n", delay); | |
+ } | |
+ /* Workaround for some devices crashing on pci_host_probe / pci_scan_root_bus_bridge | |
+ * calls: sleep a bit before bus scan. Call trace gets to rockchip_pcie_rd_conf when | |
+ * trying to read vendor id (pci_bus_generic_read_dev_vendor_id is in call stack) | |
+ * before panicing. I have no idea why this works or what causes the panic. I just | |
+ * found this hack by luck when trying to "make it break differently if possible". | |
+ */ | |
+ if (delay > 0) { | |
+ msleep(delay); | |
+ } | |
+ | |
err = pci_host_probe(bridge); | |
if (err < 0) | |
goto err_remove_irq_domain; | |
diff --git a/drivers/pci/controller/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c | |
index 904dec0d3a88..e6c97f9944ba 100644 | |
--- a/drivers/pci/controller/pcie-rockchip.c | |
+++ b/drivers/pci/controller/pcie-rockchip.c | |
@@ -149,6 +149,12 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) | |
return PTR_ERR(rockchip->clk_pcie_pm); | |
} | |
+ err = of_property_read_u32(node, "bus-scan-delay-ms", &rockchip->bus_scan_delay); | |
+ if (err) { | |
+ dev_info(dev, "no bus scan delay, default to 0 ms\n"); | |
+ rockchip->bus_scan_delay = 0; | |
+ } | |
+ | |
return 0; | |
} | |
EXPORT_SYMBOL_GPL(rockchip_pcie_parse_dt); | |
diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h | |
index c7d0178fc8c2..52fd2108b704 100644 | |
--- a/drivers/pci/controller/pcie-rockchip.h | |
+++ b/drivers/pci/controller/pcie-rockchip.h | |
@@ -306,6 +306,8 @@ struct rockchip_pcie { | |
phys_addr_t msg_bus_addr; | |
bool is_rc; | |
struct resource *mem_res; | |
+ /* Bus scan delay is a workaround for some pcie devices causing crashes */ | |
+ u32 bus_scan_delay; | |
}; | |
static u32 rockchip_pcie_read(struct rockchip_pcie *rockchip, u32 reg) | |
-- | |
2.29.2 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment