From bd7b016c6323bc1dab3ca72c7065755327aa951b Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 23 Nov 2023 23:28:42 -0500 Subject: [PATCH] Fixes for 5.10 Signed-off-by: Sasha Levin --- ...ipq6018-fix-tcsr_mutex-register-size.patch | 45 ++ ...om-ipq6018-switch-tcsr-mutex-to-mmio.patch | 60 ++ ...dd-device-0bda-887b-to-device-tables.patch | 67 ++ ...dd-device-13d3-3571-to-device-tables.patch | 65 ++ ...-add-0bda-b85b-for-fn-link-rtl8852be.patch | 75 ++ ...add-realtek-rtl8852be-support-id-0x0.patch | 70 ++ ...add-rtw8852be-device-13d3-3570-to-de.patch | 68 ++ ...x-buffer-overflow-detection-in-trans.patch | 87 +++ ...c-dra7xx-use-the-common-msi-irq_chip.patch | 168 ++++ ...wc-drop-the-.set_num_vectors-host-op.patch | 137 ++++ ...ework-the-driver-to-support-exynos54.patch | 646 ++++++++++++++++ ...-dbi2-and-addr_space-resource-setup-.patch | 707 +++++++++++++++++ ...-dwc-move-dw_pcie_msi_init-into-core.patch | 309 ++++++++ ...-dw_pcie_setup_rc-to-dwc-common-code.patch | 278 +++++++ ...-move-link-handling-into-common-code.patch | 723 ++++++++++++++++++ ...-interrupt-setup-into-dwc-common-cod.patch | 323 ++++++++ .../pci-dwc-rework-msi-initialization.patch | 218 ++++++ ...xynos-don-t-discard-.remove-callback.patch | 60 ++ ...ove-redundant-initialization-of-vari.patch | 48 ++ ...-platform_get_irq-to-get-the-interru.patch | 69 ++ queue-5.10/series | 22 + ...eson-fix-hard-lockup-on-crtscts-mode.patch | 101 +++ ...eson-retrieve-port-fifo-size-from-dt.patch | 55 ++ 23 files changed, 4401 insertions(+) create mode 100644 queue-5.10/arm64-dts-qcom-ipq6018-fix-tcsr_mutex-register-size.patch create mode 100644 queue-5.10/arm64-dts-qcom-ipq6018-switch-tcsr-mutex-to-mmio.patch create mode 100644 queue-5.10/bluetooth-add-device-0bda-887b-to-device-tables.patch create mode 100644 queue-5.10/bluetooth-add-device-13d3-3571-to-device-tables.patch create mode 100644 queue-5.10/bluetooth-btusb-add-0bda-b85b-for-fn-link-rtl8852be.patch create mode 100644 queue-5.10/bluetooth-btusb-add-realtek-rtl8852be-support-id-0x0.patch create mode 100644 queue-5.10/bluetooth-btusb-add-rtw8852be-device-13d3-3570-to-de.patch create mode 100644 queue-5.10/cpufreq-stats-fix-buffer-overflow-detection-in-trans.patch create mode 100644 queue-5.10/pci-dwc-dra7xx-use-the-common-msi-irq_chip.patch create mode 100644 queue-5.10/pci-dwc-drop-the-.set_num_vectors-host-op.patch create mode 100644 queue-5.10/pci-dwc-exynos-rework-the-driver-to-support-exynos54.patch create mode 100644 queue-5.10/pci-dwc-move-dbi-dbi2-and-addr_space-resource-setup-.patch create mode 100644 queue-5.10/pci-dwc-move-dw_pcie_msi_init-into-core.patch create mode 100644 queue-5.10/pci-dwc-move-dw_pcie_setup_rc-to-dwc-common-code.patch create mode 100644 queue-5.10/pci-dwc-move-link-handling-into-common-code.patch create mode 100644 queue-5.10/pci-dwc-move-msi-interrupt-setup-into-dwc-common-cod.patch create mode 100644 queue-5.10/pci-dwc-rework-msi-initialization.patch create mode 100644 queue-5.10/pci-exynos-don-t-discard-.remove-callback.patch create mode 100644 queue-5.10/serial-meson-remove-redundant-initialization-of-vari.patch create mode 100644 queue-5.10/serial-meson-use-platform_get_irq-to-get-the-interru.patch create mode 100644 queue-5.10/tty-serial-meson-fix-hard-lockup-on-crtscts-mode.patch create mode 100644 queue-5.10/tty-serial-meson-retrieve-port-fifo-size-from-dt.patch diff --git a/queue-5.10/arm64-dts-qcom-ipq6018-fix-tcsr_mutex-register-size.patch b/queue-5.10/arm64-dts-qcom-ipq6018-fix-tcsr_mutex-register-size.patch new file mode 100644 index 00000000000..a76ec7a37cf --- /dev/null +++ b/queue-5.10/arm64-dts-qcom-ipq6018-fix-tcsr_mutex-register-size.patch @@ -0,0 +1,45 @@ +From 13f63b2dc8e04e8ff485c5880838fd41b6b9a166 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Sep 2023 15:25:34 +0530 +Subject: arm64: dts: qcom: ipq6018: Fix tcsr_mutex register size + +From: Vignesh Viswanathan + +[ Upstream commit 72fc3d58b87b0d622039c6299b89024fbb7b420f ] + +IPQ6018's TCSR Mutex HW lock register has 32 locks of size 4KB each. +Total size of the TCSR Mutex registers is 128KB. + +Fix size of the tcsr_mutex hwlock register to 0x20000. + +Changes in v2: + - Drop change to remove qcom,ipq6018-tcsr-mutex compatible string + - Added Fixes and stable tags + +Cc: stable@vger.kernel.org +Fixes: 5bf635621245 ("arm64: dts: ipq6018: Add a few device nodes") +Signed-off-by: Vignesh Viswanathan +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20230905095535.1263113-2-quic_viswanat@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +index a8c26aff6f376..3677209106773 100644 +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -238,7 +238,7 @@ + + tcsr_mutex: hwlock@1905000 { + compatible = "qcom,ipq6018-tcsr-mutex", "qcom,tcsr-mutex"; +- reg = <0x0 0x01905000 0x0 0x1000>; ++ reg = <0x0 0x01905000 0x0 0x20000>; + #hwlock-cells = <1>; + }; + +-- +2.42.0 + diff --git a/queue-5.10/arm64-dts-qcom-ipq6018-switch-tcsr-mutex-to-mmio.patch b/queue-5.10/arm64-dts-qcom-ipq6018-switch-tcsr-mutex-to-mmio.patch new file mode 100644 index 00000000000..d75849ad595 --- /dev/null +++ b/queue-5.10/arm64-dts-qcom-ipq6018-switch-tcsr-mutex-to-mmio.patch @@ -0,0 +1,60 @@ +From c97754d8030c762ca96b032fefd2a904bd4e0243 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 11:20:31 +0200 +Subject: arm64: dts: qcom: ipq6018: switch TCSR mutex to MMIO + +From: Krzysztof Kozlowski + +[ Upstream commit f5e303aefc06b7508d7a490f9a2d80e4dc134c70 ] + +The TCSR mutex bindings allow device to be described only with address +space (so it uses MMIO, not syscon regmap). This seems reasonable as +TCSR mutex is actually a dedicated IO address space and it also fixes DT +schema checks: + + qcom/ipq6018-cp01-c1.dtb: hwlock: 'reg' is a required property + qcom/ipq6018-cp01-c1.dtb: hwlock: 'syscon' does not match any of the regexes: 'pinctrl-[0-9]+' + +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220909092035.223915-12-krzysztof.kozlowski@linaro.org +Stable-dep-of: 72fc3d58b87b ("arm64: dts: qcom: ipq6018: Fix tcsr_mutex register size") +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 13 ++++--------- + 1 file changed, 4 insertions(+), 9 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +index 201a3bb5511cd..a8c26aff6f376 100644 +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -129,12 +129,6 @@ + }; + }; + +- tcsr_mutex: hwlock { +- compatible = "qcom,tcsr-mutex"; +- syscon = <&tcsr_mutex_regs 0 0x80>; +- #hwlock-cells = <1>; +- }; +- + pmuv8: pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = ; + }; + +- tcsr_mutex_regs: syscon@1905000 { +- compatible = "syscon"; +- reg = <0x0 0x01905000 0x0 0x8000>; ++ tcsr_mutex: hwlock@1905000 { ++ compatible = "qcom,ipq6018-tcsr-mutex", "qcom,tcsr-mutex"; ++ reg = <0x0 0x01905000 0x0 0x1000>; ++ #hwlock-cells = <1>; + }; + + tcsr_q6: syscon@1945000 { +-- +2.42.0 + diff --git a/queue-5.10/bluetooth-add-device-0bda-887b-to-device-tables.patch b/queue-5.10/bluetooth-add-device-0bda-887b-to-device-tables.patch new file mode 100644 index 00000000000..3e2a144d876 --- /dev/null +++ b/queue-5.10/bluetooth-add-device-0bda-887b-to-device-tables.patch @@ -0,0 +1,67 @@ +From ad8336b7b8f27209c551c2a6904ba6f7b82dfff9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Mar 2023 19:52:02 -0500 +Subject: bluetooth: Add device 0bda:887b to device tables + +From: Larry Finger + +[ Upstream commit 730a1d1a93a3e30c3723f87af97a8517334b2203 ] + +This device is part of a Realtek RTW8852BE chip. + +The device table entry is as follows: + +T: Bus=03 Lev=01 Prnt=01 Port=12 Cnt=02 Dev#= 3 Spd=12 MxCh= 0 +D: Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=0bda ProdID=887b Rev= 0.00 +S: Manufacturer=Realtek +S: Product=Bluetooth Radio +S: SerialNumber=00e04c000001 +C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms +I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms +I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms +I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms +I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms +I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms + +Signed-off-by: Larry Finger +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: da06ff1f585e ("Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE") +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index fffb73e6f49d4..bb1ec0cac2b29 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -418,6 +418,8 @@ static const struct usb_device_id blacklist_table[] = { + /* Realtek 8852BE Bluetooth devices */ + { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, + + /* Realtek Bluetooth devices */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01), +-- +2.42.0 + diff --git a/queue-5.10/bluetooth-add-device-13d3-3571-to-device-tables.patch b/queue-5.10/bluetooth-add-device-13d3-3571-to-device-tables.patch new file mode 100644 index 00000000000..0afd7606059 --- /dev/null +++ b/queue-5.10/bluetooth-add-device-13d3-3571-to-device-tables.patch @@ -0,0 +1,65 @@ +From baf7f4a4bb918d5e2f6d163dd791852b1de2af97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Mar 2023 19:52:03 -0500 +Subject: bluetooth: Add device 13d3:3571 to device tables + +From: Larry Finger + +[ Upstream commit 069f534247bb6db4f8c2c2ea8e9155abf495c37e ] + +This device is part of a Realtek RTW8852BE chip. The device table is as follows: + +T: Bus=03 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 +D: Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=13d3 ProdID=3571 Rev= 0.00 +S: Manufacturer=Realtek +S: Product=Bluetooth Radio +S: SerialNumber=00e04c000001 +C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms +I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms +I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms +I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms +I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms +I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms + +Signed-off-by: Larry Finger +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: da06ff1f585e ("Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE") +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index bb1ec0cac2b29..6c225f48a26d4 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -420,6 +420,8 @@ static const struct usb_device_id blacklist_table[] = { + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, + + /* Realtek Bluetooth devices */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01), +-- +2.42.0 + diff --git a/queue-5.10/bluetooth-btusb-add-0bda-b85b-for-fn-link-rtl8852be.patch b/queue-5.10/bluetooth-btusb-add-0bda-b85b-for-fn-link-rtl8852be.patch new file mode 100644 index 00000000000..79f45cbbec0 --- /dev/null +++ b/queue-5.10/bluetooth-btusb-add-0bda-b85b-for-fn-link-rtl8852be.patch @@ -0,0 +1,75 @@ +From 3e37ba18d41eb9fa3c5f006d14447231c2fd95cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Oct 2023 19:21:17 +0800 +Subject: Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE + +From: Guan Wentao + +[ Upstream commit da06ff1f585ea784c79f80e7fab0e0c4ebb49c1c ] + +Add PID/VID 0bda:b85b for Realtek RTL8852BE USB bluetooth part. +The PID/VID was reported by the patch last year. [1] +Some SBCs like rockpi 5B A8 module contains the device. +And it`s founded in website. [2] [3] + +Here is the device tables in /sys/kernel/debug/usb/devices . + +T: Bus=07 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 +D: Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=0bda ProdID=b85b Rev= 0.00 +S: Manufacturer=Realtek +S: Product=Bluetooth Radio +S: SerialNumber=00e04c000001 +C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms +I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms +I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms +I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms +I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms +I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms + +Link: https://lore.kernel.org/all/20220420052402.19049-1-tangmeng@uniontech.com/ [1] +Link: https://forum.radxa.com/t/bluetooth-on-ubuntu/13051/4 [2] +Link: https://ubuntuforums.org/showthread.php?t=2489527 [3] + +Cc: stable@vger.kernel.org +Signed-off-by: Meng Tang +Signed-off-by: Guan Wentao +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index f1079614bfdb3..a1a8b282b99b1 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -420,6 +420,8 @@ static const struct usb_device_id blacklist_table[] = { + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3570), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK | +-- +2.42.0 + diff --git a/queue-5.10/bluetooth-btusb-add-realtek-rtl8852be-support-id-0x0.patch b/queue-5.10/bluetooth-btusb-add-realtek-rtl8852be-support-id-0x0.patch new file mode 100644 index 00000000000..22f1ffe9c61 --- /dev/null +++ b/queue-5.10/bluetooth-btusb-add-realtek-rtl8852be-support-id-0x0.patch @@ -0,0 +1,70 @@ +From 6be8ee495acc64d36028a5c831427548c30275ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 11:10:05 +0300 +Subject: Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x0cb8:0xc559 + +From: Artem Lukyanov + +[ Upstream commit 393b4916b7b5b94faf5c6a7c68df1c62d17e4f38 ] + +Add the support ID(0x0cb8, 0xc559) to usb_device_id table for +Realtek RTL8852BE. + +The device info from /sys/kernel/debug/usb/devices as below. + +T: Bus=03 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 +D: Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=0cb8 ProdID=c559 Rev= 0.00 +S: Manufacturer=Realtek +S: Product=Bluetooth Radio +S: SerialNumber=00e04c000001 +C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms +I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms +I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms +I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms +I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms +I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms + +Signed-off-by: Artem Lukyanov +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: da06ff1f585e ("Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE") +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index cc210fb790d89..fffb73e6f49d4 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -415,6 +415,10 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x13d3, 0x3586), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + ++ /* Realtek 8852BE Bluetooth devices */ ++ { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, ++ + /* Realtek Bluetooth devices */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01), + .driver_info = BTUSB_REALTEK }, +-- +2.42.0 + diff --git a/queue-5.10/bluetooth-btusb-add-rtw8852be-device-13d3-3570-to-de.patch b/queue-5.10/bluetooth-btusb-add-rtw8852be-device-13d3-3570-to-de.patch new file mode 100644 index 00000000000..8624bda7e62 --- /dev/null +++ b/queue-5.10/bluetooth-btusb-add-rtw8852be-device-13d3-3570-to-de.patch @@ -0,0 +1,68 @@ +From d4aa3cb2c4c68f8fde58c54d631760b90a10d94c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Sep 2023 16:46:55 +0530 +Subject: Bluetooth: btusb: Add RTW8852BE device 13d3:3570 to device tables + +From: Masum Reza + +[ Upstream commit 02be109d3a405dbc4d53fb4b4473d7a113548088 ] + +This device is used in TP-Link TX20E WiFi+Bluetooth adapter. + +Relevant information in /sys/kernel/debug/usb/devices +about the Bluetooth device is listed as the below. + +T: Bus=01 Lev=01 Prnt=01 Port=08 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 +D: Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=13d3 ProdID=3570 Rev= 0.00 +S: Manufacturer=Realtek +S: Product=Bluetooth Radio +S: SerialNumber=00e04c000001 +C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms +I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms +I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms +I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms +I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms +I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms + +Signed-off-by: Masum Reza +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: da06ff1f585e ("Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE") +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 6c225f48a26d4..f1079614bfdb3 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -420,6 +420,8 @@ static const struct usb_device_id blacklist_table[] = { + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x13d3, 0x3570), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + +-- +2.42.0 + diff --git a/queue-5.10/cpufreq-stats-fix-buffer-overflow-detection-in-trans.patch b/queue-5.10/cpufreq-stats-fix-buffer-overflow-detection-in-trans.patch new file mode 100644 index 00000000000..3b592790203 --- /dev/null +++ b/queue-5.10/cpufreq-stats-fix-buffer-overflow-detection-in-trans.patch @@ -0,0 +1,87 @@ +From 5c5c0250a9da09cad0e5c9cd34808b3b0d3bdf4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Oct 2023 20:30:14 +0200 +Subject: cpufreq: stats: Fix buffer overflow detection in trans_stats() + +From: Christian Marangi + +[ Upstream commit ea167a7fc2426f7685c3735e104921c1a20a6d3f ] + +Commit 3c0897c180c6 ("cpufreq: Use scnprintf() for avoiding potential +buffer overflow") switched from snprintf to the more secure scnprintf +but never updated the exit condition for PAGE_SIZE. + +As the commit say and as scnprintf document, what scnprintf returns what +is actually written not counting the '\0' end char. This results in the +case of len exceeding the size, len set to PAGE_SIZE - 1, as it can be +written at max PAGE_SIZE - 1 (as '\0' is not counted) + +Because of len is never set to PAGE_SIZE, the function never break early, +never prints the warning and never return -EFBIG. + +Fix this by changing the condition to PAGE_SIZE - 1 to correctly trigger +the error. + +Cc: 5.10+ # 5.10+ +Fixes: 3c0897c180c6 ("cpufreq: Use scnprintf() for avoiding potential buffer overflow") +Signed-off-by: Christian Marangi +[ rjw: Subject and changelog edits ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/cpufreq_stats.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c +index 6cd5c8ab5d49f..ab856dd2d5fc0 100644 +--- a/drivers/cpufreq/cpufreq_stats.c ++++ b/drivers/cpufreq/cpufreq_stats.c +@@ -131,25 +131,25 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) + len += scnprintf(buf + len, PAGE_SIZE - len, " From : To\n"); + len += scnprintf(buf + len, PAGE_SIZE - len, " : "); + for (i = 0; i < stats->state_num; i++) { +- if (len >= PAGE_SIZE) ++ if (len >= PAGE_SIZE - 1) + break; + len += scnprintf(buf + len, PAGE_SIZE - len, "%9u ", + stats->freq_table[i]); + } +- if (len >= PAGE_SIZE) +- return PAGE_SIZE; ++ if (len >= PAGE_SIZE - 1) ++ return PAGE_SIZE - 1; + + len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); + + for (i = 0; i < stats->state_num; i++) { +- if (len >= PAGE_SIZE) ++ if (len >= PAGE_SIZE - 1) + break; + + len += scnprintf(buf + len, PAGE_SIZE - len, "%9u: ", + stats->freq_table[i]); + + for (j = 0; j < stats->state_num; j++) { +- if (len >= PAGE_SIZE) ++ if (len >= PAGE_SIZE - 1) + break; + + if (pending) +@@ -159,12 +159,12 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) + + len += scnprintf(buf + len, PAGE_SIZE - len, "%9u ", count); + } +- if (len >= PAGE_SIZE) ++ if (len >= PAGE_SIZE - 1) + break; + len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); + } + +- if (len >= PAGE_SIZE) { ++ if (len >= PAGE_SIZE - 1) { + pr_warn_once("cpufreq transition table exceeds PAGE_SIZE. Disabling\n"); + return -EFBIG; + } +-- +2.42.0 + diff --git a/queue-5.10/pci-dwc-dra7xx-use-the-common-msi-irq_chip.patch b/queue-5.10/pci-dwc-dra7xx-use-the-common-msi-irq_chip.patch new file mode 100644 index 00000000000..b360386146f --- /dev/null +++ b/queue-5.10/pci-dwc-dra7xx-use-the-common-msi-irq_chip.patch @@ -0,0 +1,168 @@ +From eb79d84adcfd4f527905aa45475665fc4d33bfbe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Nov 2020 15:11:49 -0600 +Subject: PCI: dwc/dra7xx: Use the common MSI irq_chip + +From: Rob Herring + +[ Upstream commit 7f170d35f58311362e8b01b6774ca1053c0641b8 ] + +The dra7xx MSI irq_chip implementation is identical to the default DWC one. +The only difference is the interrupt handler as the MSI interrupt is muxed +with other interrupts, but that doesn't affect the irq_chip part of it. + +Link: https://lore.kernel.org/r/20201105211159.1814485-7-robh@kernel.org +Tested-by: Marek Szyprowski +Signed-off-by: Rob Herring +Signed-off-by: Lorenzo Pieralisi +Cc: Kishon Vijay Abraham I +Cc: Lorenzo Pieralisi +Cc: Bjorn Helgaas +Cc: linux-omap@vger.kernel.org +Stable-dep-of: 83a939f0fdc2 ("PCI: exynos: Don't discard .remove() callback") +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pci-dra7xx.c | 125 ------------------------ + 1 file changed, 125 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c +index a4aabc85dbb12..4d0c35a4aa598 100644 +--- a/drivers/pci/controller/dwc/pci-dra7xx.c ++++ b/drivers/pci/controller/dwc/pci-dra7xx.c +@@ -377,133 +377,8 @@ static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) + return 0; + } + +-static void dra7xx_pcie_setup_msi_msg(struct irq_data *d, struct msi_msg *msg) +-{ +- struct pcie_port *pp = irq_data_get_irq_chip_data(d); +- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +- u64 msi_target; +- +- msi_target = (u64)pp->msi_data; +- +- msg->address_lo = lower_32_bits(msi_target); +- msg->address_hi = upper_32_bits(msi_target); +- +- msg->data = d->hwirq; +- +- dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n", +- (int)d->hwirq, msg->address_hi, msg->address_lo); +-} +- +-static int dra7xx_pcie_msi_set_affinity(struct irq_data *d, +- const struct cpumask *mask, +- bool force) +-{ +- return -EINVAL; +-} +- +-static void dra7xx_pcie_bottom_mask(struct irq_data *d) +-{ +- struct pcie_port *pp = irq_data_get_irq_chip_data(d); +- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +- unsigned int res, bit, ctrl; +- unsigned long flags; +- +- raw_spin_lock_irqsave(&pp->lock, flags); +- +- ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; +- res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; +- bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; +- +- pp->irq_mask[ctrl] |= BIT(bit); +- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, +- pp->irq_mask[ctrl]); +- +- raw_spin_unlock_irqrestore(&pp->lock, flags); +-} +- +-static void dra7xx_pcie_bottom_unmask(struct irq_data *d) +-{ +- struct pcie_port *pp = irq_data_get_irq_chip_data(d); +- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +- unsigned int res, bit, ctrl; +- unsigned long flags; +- +- raw_spin_lock_irqsave(&pp->lock, flags); +- +- ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; +- res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; +- bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; +- +- pp->irq_mask[ctrl] &= ~BIT(bit); +- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, +- pp->irq_mask[ctrl]); +- +- raw_spin_unlock_irqrestore(&pp->lock, flags); +-} +- +-static void dra7xx_pcie_bottom_ack(struct irq_data *d) +-{ +- struct pcie_port *pp = irq_data_get_irq_chip_data(d); +- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +- unsigned int res, bit, ctrl; +- +- ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; +- res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; +- bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; +- +- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_STATUS + res, BIT(bit)); +-} +- +-static struct irq_chip dra7xx_pci_msi_bottom_irq_chip = { +- .name = "DRA7XX-PCI-MSI", +- .irq_ack = dra7xx_pcie_bottom_ack, +- .irq_compose_msi_msg = dra7xx_pcie_setup_msi_msg, +- .irq_set_affinity = dra7xx_pcie_msi_set_affinity, +- .irq_mask = dra7xx_pcie_bottom_mask, +- .irq_unmask = dra7xx_pcie_bottom_unmask, +-}; +- +-static int dra7xx_pcie_msi_host_init(struct pcie_port *pp) +-{ +- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +- struct device *dev = pci->dev; +- u32 ctrl, num_ctrls; +- int ret; +- +- pp->msi_irq_chip = &dra7xx_pci_msi_bottom_irq_chip; +- +- num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; +- /* Initialize IRQ Status array */ +- for (ctrl = 0; ctrl < num_ctrls; ctrl++) { +- pp->irq_mask[ctrl] = ~0; +- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + +- (ctrl * MSI_REG_CTRL_BLOCK_SIZE), +- pp->irq_mask[ctrl]); +- dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_ENABLE + +- (ctrl * MSI_REG_CTRL_BLOCK_SIZE), +- ~0); +- } +- +- ret = dw_pcie_allocate_domains(pp); +- if (ret) +- return ret; +- +- pp->msi_data = dma_map_single_attrs(dev, &pp->msi_msg, +- sizeof(pp->msi_msg), +- DMA_FROM_DEVICE, +- DMA_ATTR_SKIP_CPU_SYNC); +- ret = dma_mapping_error(dev, pp->msi_data); +- if (ret) { +- dev_err(dev, "Failed to map MSI data\n"); +- pp->msi_data = 0; +- dw_pcie_free_msi(pp); +- } +- return ret; +-} +- + static const struct dw_pcie_host_ops dra7xx_pcie_host_ops = { + .host_init = dra7xx_pcie_host_init, +- .msi_host_init = dra7xx_pcie_msi_host_init, + }; + + static void dra7xx_pcie_ep_init(struct dw_pcie_ep *ep) +-- +2.42.0 + diff --git a/queue-5.10/pci-dwc-drop-the-.set_num_vectors-host-op.patch b/queue-5.10/pci-dwc-drop-the-.set_num_vectors-host-op.patch new file mode 100644 index 00000000000..0a6ded8786f --- /dev/null +++ b/queue-5.10/pci-dwc-drop-the-.set_num_vectors-host-op.patch @@ -0,0 +1,137 @@ +From 2535a2b742bde8ebeb7e5852ae7ac39acd5a08a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Nov 2020 15:11:50 -0600 +Subject: PCI: dwc: Drop the .set_num_vectors() host op + +From: Rob Herring + +[ Upstream commit 331e9bcead5252364e52fc95efbbe7273667b07d ] + +There's no reason for the .set_num_vectors() host op. Drivers needing a +non-default value can just initialize pcie_port.num_vectors directly. + +Link: https://lore.kernel.org/r/20201105211159.1814485-8-robh@kernel.org +Tested-by: Marek Szyprowski +Signed-off-by: Rob Herring +Signed-off-by: Lorenzo Pieralisi +Acked-by: Jingoo Han +Cc: Gustavo Pimentel +Cc: Lorenzo Pieralisi +Cc: Bjorn Helgaas +Cc: Thierry Reding +Cc: Jonathan Hunter +Cc: linux-tegra@vger.kernel.org +Stable-dep-of: 83a939f0fdc2 ("PCI: exynos: Don't discard .remove() callback") +Signed-off-by: Sasha Levin +--- + .../pci/controller/dwc/pcie-designware-host.c | 19 ++++--------------- + .../pci/controller/dwc/pcie-designware-plat.c | 7 +------ + drivers/pci/controller/dwc/pcie-designware.h | 1 - + drivers/pci/controller/dwc/pcie-tegra194.c | 7 +------ + 4 files changed, 6 insertions(+), 28 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c +index d6b7eec1a25b0..32d3af7c44917 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -365,22 +365,11 @@ int dw_pcie_host_init(struct pcie_port *pp) + pci->link_gen = of_pci_get_max_link_speed(np); + + if (pci_msi_enabled()) { +- /* +- * If a specific SoC driver needs to change the +- * default number of vectors, it needs to implement +- * the set_num_vectors callback. +- */ +- if (!pp->ops->set_num_vectors) { ++ if (!pp->num_vectors) { + pp->num_vectors = MSI_DEF_NUM_VECTORS; +- } else { +- pp->ops->set_num_vectors(pp); +- +- if (pp->num_vectors > MAX_MSI_IRQS || +- pp->num_vectors == 0) { +- dev_err(dev, +- "Invalid number of vectors\n"); +- return -EINVAL; +- } ++ } else if (pp->num_vectors > MAX_MSI_IRQS) { ++ dev_err(dev, "Invalid number of vectors\n"); ++ return -EINVAL; + } + + if (!pp->ops->msi_host_init) { +diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c +index 562a05e07b1d5..13fede1d41572 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-plat.c ++++ b/drivers/pci/controller/dwc/pcie-designware-plat.c +@@ -44,14 +44,8 @@ static int dw_plat_pcie_host_init(struct pcie_port *pp) + return 0; + } + +-static void dw_plat_set_num_vectors(struct pcie_port *pp) +-{ +- pp->num_vectors = MAX_MSI_IRQS; +-} +- + static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = { + .host_init = dw_plat_pcie_host_init, +- .set_num_vectors = dw_plat_set_num_vectors, + }; + + static int dw_plat_pcie_establish_link(struct dw_pcie *pci) +@@ -128,6 +122,7 @@ static int dw_plat_add_pcie_port(struct dw_plat_pcie *dw_plat_pcie, + return pp->msi_irq; + } + ++ pp->num_vectors = MAX_MSI_IRQS; + pp->ops = &dw_plat_pcie_host_ops; + + ret = dw_pcie_host_init(pp); +diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h +index 9d2f511f13faf..82c0339c283f1 100644 +--- a/drivers/pci/controller/dwc/pcie-designware.h ++++ b/drivers/pci/controller/dwc/pcie-designware.h +@@ -174,7 +174,6 @@ enum dw_pcie_device_mode { + + struct dw_pcie_host_ops { + int (*host_init)(struct pcie_port *pp); +- void (*set_num_vectors)(struct pcie_port *pp); + int (*msi_host_init)(struct pcie_port *pp); + }; + +diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c +index 825cb65945fba..a93b5dca110ec 100644 +--- a/drivers/pci/controller/dwc/pcie-tegra194.c ++++ b/drivers/pci/controller/dwc/pcie-tegra194.c +@@ -996,11 +996,6 @@ static int tegra_pcie_dw_link_up(struct dw_pcie *pci) + return !!(val & PCI_EXP_LNKSTA_DLLLA); + } + +-static void tegra_pcie_set_msi_vec_num(struct pcie_port *pp) +-{ +- pp->num_vectors = MAX_MSI_IRQS; +-} +- + static int tegra_pcie_dw_start_link(struct dw_pcie *pci) + { + struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); +@@ -1025,7 +1020,6 @@ static const struct dw_pcie_ops tegra_dw_pcie_ops = { + + static struct dw_pcie_host_ops tegra_pcie_dw_host_ops = { + .host_init = tegra_pcie_dw_host_init, +- .set_num_vectors = tegra_pcie_set_msi_vec_num, + }; + + static void tegra_pcie_disable_phy(struct tegra_pcie_dw *pcie) +@@ -2002,6 +1996,7 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev) + pci->n_fts[1] = FTS_VAL; + + pp = &pci->pp; ++ pp->num_vectors = MAX_MSI_IRQS; + pcie->dev = &pdev->dev; + pcie->mode = (enum dw_pcie_device_mode)data->mode; + +-- +2.42.0 + diff --git a/queue-5.10/pci-dwc-exynos-rework-the-driver-to-support-exynos54.patch b/queue-5.10/pci-dwc-exynos-rework-the-driver-to-support-exynos54.patch new file mode 100644 index 00000000000..949fa6aa2a9 --- /dev/null +++ b/queue-5.10/pci-dwc-exynos-rework-the-driver-to-support-exynos54.patch @@ -0,0 +1,646 @@ +From a8f5794be913c874645a36fcd07145df3ac0eac6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Nov 2020 18:01:39 +0100 +Subject: PCI: dwc: exynos: Rework the driver to support Exynos5433 variant + +From: Jaehoon Chung + +[ Upstream commit 778f7c194b1dac351d345ce723f8747026092949 ] + +Exynos5440 SoC support has been dropped since commit 8c83315da1cf ("ARM: +dts: exynos: Remove Exynos5440"). Rework this driver to support DWC PCIe +variant found in the Exynos5433 SoCs. + +The main difference in Exynos5433 variant is lack of the MSI support +(the MSI interrupt is not even routed to the CPU). + +[mszyprow: reworked the driver to support only Exynos5433 variant, + simplified code, rebased onto current kernel code, added + regulator support, converted to the regular platform driver, + removed MSI related code, rewrote commit message, added help] + +Link: https://lore.kernel.org/r/20201113170139.29956-6-m.szyprowski@samsung.com +Signed-off-by: Jaehoon Chung +Signed-off-by: Marek Szyprowski +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Rob Herring +Acked-by: Krzysztof Kozlowski +Acked-by: Jingoo Han +Stable-dep-of: 83a939f0fdc2 ("PCI: exynos: Don't discard .remove() callback") +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/Kconfig | 9 +- + drivers/pci/controller/dwc/pci-exynos.c | 353 ++++++++++-------------- + drivers/pci/quirks.c | 1 + + 3 files changed, 147 insertions(+), 216 deletions(-) + +diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig +index bc049865f8e05..9ee1e248e7448 100644 +--- a/drivers/pci/controller/dwc/Kconfig ++++ b/drivers/pci/controller/dwc/Kconfig +@@ -83,10 +83,15 @@ config PCIE_DW_PLAT_EP + selected. + + config PCI_EXYNOS +- bool "Samsung Exynos PCIe controller" +- depends on SOC_EXYNOS5440 || COMPILE_TEST ++ tristate "Samsung Exynos PCIe controller" ++ depends on ARCH_EXYNOS || COMPILE_TEST + depends on PCI_MSI_IRQ_DOMAIN + select PCIE_DW_HOST ++ help ++ Enables support for the PCIe controller in the Samsung Exynos SoCs ++ to work in host mode. The PCI controller is based on the DesignWare ++ hardware and therefore the driver re-uses the DesignWare core ++ functions to implement the driver. + + config PCI_IMX6 + bool "Freescale i.MX6/7/8 PCIe controller" +diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c +index 5c10a5432896c..c24dab383654b 100644 +--- a/drivers/pci/controller/dwc/pci-exynos.c ++++ b/drivers/pci/controller/dwc/pci-exynos.c +@@ -2,26 +2,23 @@ + /* + * PCIe host controller driver for Samsung Exynos SoCs + * +- * Copyright (C) 2013 Samsung Electronics Co., Ltd. ++ * Copyright (C) 2013-2020 Samsung Electronics Co., Ltd. + * https://www.samsung.com + * + * Author: Jingoo Han ++ * Jaehoon Chung + */ + + #include + #include +-#include + #include + #include + #include + #include +-#include + #include + #include + #include +-#include +-#include +-#include ++#include + + #include "pcie-designware.h" + +@@ -37,102 +34,43 @@ + #define PCIE_IRQ_SPECIAL 0x008 + #define PCIE_IRQ_EN_PULSE 0x00c + #define PCIE_IRQ_EN_LEVEL 0x010 +-#define IRQ_MSI_ENABLE BIT(2) + #define PCIE_IRQ_EN_SPECIAL 0x014 +-#define PCIE_PWR_RESET 0x018 ++#define PCIE_SW_WAKE 0x018 ++#define PCIE_BUS_EN BIT(1) + #define PCIE_CORE_RESET 0x01c + #define PCIE_CORE_RESET_ENABLE BIT(0) + #define PCIE_STICKY_RESET 0x020 + #define PCIE_NONSTICKY_RESET 0x024 + #define PCIE_APP_INIT_RESET 0x028 + #define PCIE_APP_LTSSM_ENABLE 0x02c +-#define PCIE_ELBI_RDLH_LINKUP 0x064 ++#define PCIE_ELBI_RDLH_LINKUP 0x074 ++#define PCIE_ELBI_XMLH_LINKUP BIT(4) + #define PCIE_ELBI_LTSSM_ENABLE 0x1 + #define PCIE_ELBI_SLV_AWMISC 0x11c + #define PCIE_ELBI_SLV_ARMISC 0x120 + #define PCIE_ELBI_SLV_DBI_ENABLE BIT(21) + +-struct exynos_pcie_mem_res { +- void __iomem *elbi_base; /* DT 0th resource: PCIe CTRL */ +-}; +- +-struct exynos_pcie_clk_res { +- struct clk *clk; +- struct clk *bus_clk; +-}; +- + struct exynos_pcie { +- struct dw_pcie *pci; +- struct exynos_pcie_mem_res *mem_res; +- struct exynos_pcie_clk_res *clk_res; +- const struct exynos_pcie_ops *ops; +- int reset_gpio; +- ++ struct dw_pcie pci; ++ void __iomem *elbi_base; ++ struct clk *clk; ++ struct clk *bus_clk; + struct phy *phy; ++ struct regulator_bulk_data supplies[2]; + }; + +-struct exynos_pcie_ops { +- int (*get_mem_resources)(struct platform_device *pdev, +- struct exynos_pcie *ep); +- int (*get_clk_resources)(struct exynos_pcie *ep); +- int (*init_clk_resources)(struct exynos_pcie *ep); +- void (*deinit_clk_resources)(struct exynos_pcie *ep); +-}; +- +-static int exynos5440_pcie_get_mem_resources(struct platform_device *pdev, +- struct exynos_pcie *ep) +-{ +- struct dw_pcie *pci = ep->pci; +- struct device *dev = pci->dev; +- +- ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL); +- if (!ep->mem_res) +- return -ENOMEM; +- +- ep->mem_res->elbi_base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(ep->mem_res->elbi_base)) +- return PTR_ERR(ep->mem_res->elbi_base); +- +- return 0; +-} +- +-static int exynos5440_pcie_get_clk_resources(struct exynos_pcie *ep) ++static int exynos_pcie_init_clk_resources(struct exynos_pcie *ep) + { +- struct dw_pcie *pci = ep->pci; +- struct device *dev = pci->dev; +- +- ep->clk_res = devm_kzalloc(dev, sizeof(*ep->clk_res), GFP_KERNEL); +- if (!ep->clk_res) +- return -ENOMEM; +- +- ep->clk_res->clk = devm_clk_get(dev, "pcie"); +- if (IS_ERR(ep->clk_res->clk)) { +- dev_err(dev, "Failed to get pcie rc clock\n"); +- return PTR_ERR(ep->clk_res->clk); +- } +- +- ep->clk_res->bus_clk = devm_clk_get(dev, "pcie_bus"); +- if (IS_ERR(ep->clk_res->bus_clk)) { +- dev_err(dev, "Failed to get pcie bus clock\n"); +- return PTR_ERR(ep->clk_res->bus_clk); +- } +- +- return 0; +-} +- +-static int exynos5440_pcie_init_clk_resources(struct exynos_pcie *ep) +-{ +- struct dw_pcie *pci = ep->pci; +- struct device *dev = pci->dev; ++ struct device *dev = ep->pci.dev; + int ret; + +- ret = clk_prepare_enable(ep->clk_res->clk); ++ ret = clk_prepare_enable(ep->clk); + if (ret) { + dev_err(dev, "cannot enable pcie rc clock"); + return ret; + } + +- ret = clk_prepare_enable(ep->clk_res->bus_clk); ++ ret = clk_prepare_enable(ep->bus_clk); + if (ret) { + dev_err(dev, "cannot enable pcie bus clock"); + goto err_bus_clk; +@@ -141,24 +79,17 @@ static int exynos5440_pcie_init_clk_resources(struct exynos_pcie *ep) + return 0; + + err_bus_clk: +- clk_disable_unprepare(ep->clk_res->clk); ++ clk_disable_unprepare(ep->clk); + + return ret; + } + +-static void exynos5440_pcie_deinit_clk_resources(struct exynos_pcie *ep) ++static void exynos_pcie_deinit_clk_resources(struct exynos_pcie *ep) + { +- clk_disable_unprepare(ep->clk_res->bus_clk); +- clk_disable_unprepare(ep->clk_res->clk); ++ clk_disable_unprepare(ep->bus_clk); ++ clk_disable_unprepare(ep->clk); + } + +-static const struct exynos_pcie_ops exynos5440_pcie_ops = { +- .get_mem_resources = exynos5440_pcie_get_mem_resources, +- .get_clk_resources = exynos5440_pcie_get_clk_resources, +- .init_clk_resources = exynos5440_pcie_init_clk_resources, +- .deinit_clk_resources = exynos5440_pcie_deinit_clk_resources, +-}; +- + static void exynos_pcie_writel(void __iomem *base, u32 val, u32 reg) + { + writel(val, base + reg); +@@ -173,94 +104,71 @@ static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on) + { + u32 val; + +- val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_AWMISC); ++ val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_AWMISC); + if (on) + val |= PCIE_ELBI_SLV_DBI_ENABLE; + else + val &= ~PCIE_ELBI_SLV_DBI_ENABLE; +- exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_AWMISC); ++ exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_AWMISC); + } + + static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *ep, bool on) + { + u32 val; + +- val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_ARMISC); ++ val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_ARMISC); + if (on) + val |= PCIE_ELBI_SLV_DBI_ENABLE; + else + val &= ~PCIE_ELBI_SLV_DBI_ENABLE; +- exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_ARMISC); ++ exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_ARMISC); + } + + static void exynos_pcie_assert_core_reset(struct exynos_pcie *ep) + { + u32 val; + +- val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET); ++ val = exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET); + val &= ~PCIE_CORE_RESET_ENABLE; +- exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET); +- exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_PWR_RESET); +- exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_STICKY_RESET); +- exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_NONSTICKY_RESET); ++ exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET); ++ exynos_pcie_writel(ep->elbi_base, 0, PCIE_STICKY_RESET); ++ exynos_pcie_writel(ep->elbi_base, 0, PCIE_NONSTICKY_RESET); + } + + static void exynos_pcie_deassert_core_reset(struct exynos_pcie *ep) + { + u32 val; + +- val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET); ++ val = exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET); + val |= PCIE_CORE_RESET_ENABLE; + +- exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET); +- exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_STICKY_RESET); +- exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_NONSTICKY_RESET); +- exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_APP_INIT_RESET); +- exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_APP_INIT_RESET); +-} +- +-static void exynos_pcie_assert_reset(struct exynos_pcie *ep) +-{ +- struct dw_pcie *pci = ep->pci; +- struct device *dev = pci->dev; +- +- if (ep->reset_gpio >= 0) +- devm_gpio_request_one(dev, ep->reset_gpio, +- GPIOF_OUT_INIT_HIGH, "RESET"); ++ exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET); ++ exynos_pcie_writel(ep->elbi_base, 1, PCIE_STICKY_RESET); ++ exynos_pcie_writel(ep->elbi_base, 1, PCIE_NONSTICKY_RESET); ++ exynos_pcie_writel(ep->elbi_base, 1, PCIE_APP_INIT_RESET); ++ exynos_pcie_writel(ep->elbi_base, 0, PCIE_APP_INIT_RESET); + } + + static int exynos_pcie_start_link(struct dw_pcie *pci) + { + struct exynos_pcie *ep = to_exynos_pcie(pci); ++ u32 val; ++ ++ val = exynos_pcie_readl(ep->elbi_base, PCIE_SW_WAKE); ++ val &= ~PCIE_BUS_EN; ++ exynos_pcie_writel(ep->elbi_base, val, PCIE_SW_WAKE); + + /* assert LTSSM enable */ +- exynos_pcie_writel(ep->mem_res->elbi_base, PCIE_ELBI_LTSSM_ENABLE, ++ exynos_pcie_writel(ep->elbi_base, PCIE_ELBI_LTSSM_ENABLE, + PCIE_APP_LTSSM_ENABLE); +- +- /* check if the link is up or not */ +- if (!dw_pcie_wait_for_link(pci)) +- return 0; +- +- phy_power_off(ep->phy); +- return -ETIMEDOUT; ++ return 0; + } + + static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep) + { +- u32 val; +- +- val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_PULSE); +- exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_PULSE); +-} +- +-static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep) +-{ +- u32 val; ++ u32 val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_PULSE); + +- /* enable INTX interrupt */ +- val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | +- IRQ_INTC_ASSERT | IRQ_INTD_ASSERT; +- exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_PULSE); ++ exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_PULSE); + } + + static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) +@@ -271,22 +179,14 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) + return IRQ_HANDLED; + } + +-static void exynos_pcie_msi_init(struct exynos_pcie *ep) +-{ +- u32 val; +- +- /* enable MSI interrupt */ +- val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL); +- val |= IRQ_MSI_ENABLE; +- exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_LEVEL); +-} +- +-static void exynos_pcie_enable_interrupts(struct exynos_pcie *ep) ++static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep) + { +- exynos_pcie_enable_irq_pulse(ep); ++ u32 val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | ++ IRQ_INTC_ASSERT | IRQ_INTD_ASSERT; + +- if (IS_ENABLED(CONFIG_PCI_MSI)) +- exynos_pcie_msi_init(ep); ++ exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_EN_PULSE); ++ exynos_pcie_writel(ep->elbi_base, 0, PCIE_IRQ_EN_LEVEL); ++ exynos_pcie_writel(ep->elbi_base, 0, PCIE_IRQ_EN_SPECIAL); + } + + static u32 exynos_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, +@@ -345,13 +245,9 @@ static struct pci_ops exynos_pci_ops = { + static int exynos_pcie_link_up(struct dw_pcie *pci) + { + struct exynos_pcie *ep = to_exynos_pcie(pci); +- u32 val; ++ u32 val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_RDLH_LINKUP); + +- val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_RDLH_LINKUP); +- if (val == PCIE_ELBI_LTSSM_ENABLE) +- return 1; +- +- return 0; ++ return (val & PCIE_ELBI_XMLH_LINKUP); + } + + static int exynos_pcie_host_init(struct pcie_port *pp) +@@ -364,17 +260,11 @@ static int exynos_pcie_host_init(struct pcie_port *pp) + exynos_pcie_assert_core_reset(ep); + + phy_reset(ep->phy); +- +- exynos_pcie_writel(ep->mem_res->elbi_base, 1, +- PCIE_PWR_RESET); +- + phy_power_on(ep->phy); + phy_init(ep->phy); + + exynos_pcie_deassert_core_reset(ep); +- exynos_pcie_assert_reset(ep); +- +- exynos_pcie_enable_interrupts(ep); ++ exynos_pcie_enable_irq_pulse(ep); + + return 0; + } +@@ -383,26 +273,27 @@ static const struct dw_pcie_host_ops exynos_pcie_host_ops = { + .host_init = exynos_pcie_host_init, + }; + +-static int __init exynos_add_pcie_port(struct exynos_pcie *ep, ++static int exynos_add_pcie_port(struct exynos_pcie *ep, + struct platform_device *pdev) + { +- struct dw_pcie *pci = ep->pci; ++ struct dw_pcie *pci = &ep->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = &pdev->dev; + int ret; + +- pp->irq = platform_get_irq(pdev, 1); ++ pp->irq = platform_get_irq(pdev, 0); + if (pp->irq < 0) + return pp->irq; + + ret = devm_request_irq(dev, pp->irq, exynos_pcie_irq_handler, +- IRQF_SHARED, "exynos-pcie", ep); ++ IRQF_SHARED, "exynos-pcie", ep); + if (ret) { + dev_err(dev, "failed to request irq\n"); + return ret; + } + + pp->ops = &exynos_pcie_host_ops; ++ pp->msi_irq = -ENODEV; + + ret = dw_pcie_host_init(pp); + if (ret) { +@@ -420,10 +311,9 @@ static const struct dw_pcie_ops dw_pcie_ops = { + .start_link = exynos_pcie_start_link, + }; + +-static int __init exynos_pcie_probe(struct platform_device *pdev) ++static int exynos_pcie_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct dw_pcie *pci; + struct exynos_pcie *ep; + struct device_node *np = dev->of_node; + int ret; +@@ -432,43 +322,45 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) + if (!ep) + return -ENOMEM; + +- pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); +- if (!pci) +- return -ENOMEM; +- +- pci->dev = dev; +- pci->ops = &dw_pcie_ops; +- +- ep->pci = pci; +- ep->ops = (const struct exynos_pcie_ops *) +- of_device_get_match_data(dev); +- +- ep->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); ++ ep->pci.dev = dev; ++ ep->pci.ops = &dw_pcie_ops; + + ep->phy = devm_of_phy_get(dev, np, NULL); +- if (IS_ERR(ep->phy)) { +- if (PTR_ERR(ep->phy) != -ENODEV) +- return PTR_ERR(ep->phy); ++ if (IS_ERR(ep->phy)) ++ return PTR_ERR(ep->phy); + +- ep->phy = NULL; +- } ++ /* External Local Bus interface (ELBI) registers */ ++ ep->elbi_base = devm_platform_ioremap_resource_byname(pdev, "elbi"); ++ if (IS_ERR(ep->elbi_base)) ++ return PTR_ERR(ep->elbi_base); + +- if (ep->ops && ep->ops->get_mem_resources) { +- ret = ep->ops->get_mem_resources(pdev, ep); +- if (ret) +- return ret; ++ ep->clk = devm_clk_get(dev, "pcie"); ++ if (IS_ERR(ep->clk)) { ++ dev_err(dev, "Failed to get pcie rc clock\n"); ++ return PTR_ERR(ep->clk); + } + +- if (ep->ops && ep->ops->get_clk_resources && +- ep->ops->init_clk_resources) { +- ret = ep->ops->get_clk_resources(ep); +- if (ret) +- return ret; +- ret = ep->ops->init_clk_resources(ep); +- if (ret) +- return ret; ++ ep->bus_clk = devm_clk_get(dev, "pcie_bus"); ++ if (IS_ERR(ep->bus_clk)) { ++ dev_err(dev, "Failed to get pcie bus clock\n"); ++ return PTR_ERR(ep->bus_clk); + } + ++ ep->supplies[0].supply = "vdd18"; ++ ep->supplies[1].supply = "vdd10"; ++ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ep->supplies), ++ ep->supplies); ++ if (ret) ++ return ret; ++ ++ ret = exynos_pcie_init_clk_resources(ep); ++ if (ret) ++ return ret; ++ ++ ret = regulator_bulk_enable(ARRAY_SIZE(ep->supplies), ep->supplies); ++ if (ret) ++ return ret; ++ + platform_set_drvdata(pdev, ep); + + ret = exynos_add_pcie_port(ep, pdev); +@@ -479,9 +371,9 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) + + fail_probe: + phy_exit(ep->phy); ++ exynos_pcie_deinit_clk_resources(ep); ++ regulator_bulk_disable(ARRAY_SIZE(ep->supplies), ep->supplies); + +- if (ep->ops && ep->ops->deinit_clk_resources) +- ep->ops->deinit_clk_resources(ep); + return ret; + } + +@@ -489,32 +381,65 @@ static int __exit exynos_pcie_remove(struct platform_device *pdev) + { + struct exynos_pcie *ep = platform_get_drvdata(pdev); + +- if (ep->ops && ep->ops->deinit_clk_resources) +- ep->ops->deinit_clk_resources(ep); ++ dw_pcie_host_deinit(&ep->pci.pp); ++ exynos_pcie_assert_core_reset(ep); ++ phy_power_off(ep->phy); ++ phy_exit(ep->phy); ++ exynos_pcie_deinit_clk_resources(ep); ++ regulator_bulk_disable(ARRAY_SIZE(ep->supplies), ep->supplies); ++ ++ return 0; ++} ++ ++static int __maybe_unused exynos_pcie_suspend_noirq(struct device *dev) ++{ ++ struct exynos_pcie *ep = dev_get_drvdata(dev); ++ ++ exynos_pcie_assert_core_reset(ep); ++ phy_power_off(ep->phy); ++ phy_exit(ep->phy); ++ regulator_bulk_disable(ARRAY_SIZE(ep->supplies), ep->supplies); + + return 0; + } + ++static int __maybe_unused exynos_pcie_resume_noirq(struct device *dev) ++{ ++ struct exynos_pcie *ep = dev_get_drvdata(dev); ++ struct dw_pcie *pci = &ep->pci; ++ struct pcie_port *pp = &pci->pp; ++ int ret; ++ ++ ret = regulator_bulk_enable(ARRAY_SIZE(ep->supplies), ep->supplies); ++ if (ret) ++ return ret; ++ ++ /* exynos_pcie_host_init controls ep->phy */ ++ exynos_pcie_host_init(pp); ++ dw_pcie_setup_rc(pp); ++ exynos_pcie_start_link(pci); ++ return dw_pcie_wait_for_link(pci); ++} ++ ++static const struct dev_pm_ops exynos_pcie_pm_ops = { ++ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(exynos_pcie_suspend_noirq, ++ exynos_pcie_resume_noirq) ++}; ++ + static const struct of_device_id exynos_pcie_of_match[] = { +- { +- .compatible = "samsung,exynos5440-pcie", +- .data = &exynos5440_pcie_ops +- }, +- {}, ++ { .compatible = "samsung,exynos5433-pcie", }, ++ { }, + }; + + static struct platform_driver exynos_pcie_driver = { ++ .probe = exynos_pcie_probe, + .remove = __exit_p(exynos_pcie_remove), + .driver = { + .name = "exynos-pcie", + .of_match_table = exynos_pcie_of_match, ++ .pm = &exynos_pcie_pm_ops, + }, + }; +- +-/* Exynos PCIe driver does not allow module unload */ +- +-static int __init exynos_pcie_init(void) +-{ +- return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe); +-} +-subsys_initcall(exynos_pcie_init); ++module_platform_driver(exynos_pcie_driver); ++MODULE_LICENSE("GPL v2"); ++MODULE_DEVICE_TABLE(of, exynos_pcie_of_match); +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 158ff4331a141..01c2b63e3b3a1 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -2538,6 +2538,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disab + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, 0x0761, quirk_disable_all_msi); ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SAMSUNG, 0xa5e3, quirk_disable_all_msi); + + /* Disable MSI on chipsets that are known to not support it */ + static void quirk_disable_msi(struct pci_dev *dev) +-- +2.42.0 + diff --git a/queue-5.10/pci-dwc-move-dbi-dbi2-and-addr_space-resource-setup-.patch b/queue-5.10/pci-dwc-move-dbi-dbi2-and-addr_space-resource-setup-.patch new file mode 100644 index 00000000000..7a4f4b1634c --- /dev/null +++ b/queue-5.10/pci-dwc-move-dbi-dbi2-and-addr_space-resource-setup-.patch @@ -0,0 +1,707 @@ +From a5bb5f9005bc2bba67a3c1eee93921b864d23624 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Nov 2020 15:11:46 -0600 +Subject: PCI: dwc: Move "dbi", "dbi2", and "addr_space" resource setup into + common code + +From: Rob Herring + +[ Upstream commit a0fd361db8e508b8ce71c284b5ae3961759a0b3b ] + +Most DWC drivers use the common register resource names "dbi", "dbi2", and +"addr_space", so let's move their setup into the DWC common code. + +This means 'dbi_base' in particular is setup later, but it looks like no +drivers touch DBI registers before dw_pcie_host_init or dw_pcie_ep_init. + +Link: https://lore.kernel.org/r/20201105211159.1814485-4-robh@kernel.org +Tested-by: Marek Szyprowski +Signed-off-by: Rob Herring +Signed-off-by: Lorenzo Pieralisi +Acked-by: Jingoo Han +Cc: Kishon Vijay Abraham I +Cc: Lorenzo Pieralisi +Cc: Bjorn Helgaas +Cc: Murali Karicheri +Cc: Minghuan Lian +Cc: Mingkai Hu +Cc: Roy Zang +Cc: Jonathan Chocron +Cc: Jesper Nilsson +Cc: Gustavo Pimentel +Cc: Xiaowei Song +Cc: Binghui Wang +Cc: Andy Gross +Cc: Bjorn Andersson +Cc: Stanimir Varbanov +Cc: Pratyush Anand +Cc: Thierry Reding +Cc: Jonathan Hunter +Cc: Kunihiko Hayashi +Cc: Masahiro Yamada +Cc: linux-omap@vger.kernel.org +Cc: linuxppc-dev@lists.ozlabs.org +Cc: linux-arm-kernel@axis.com +Cc: linux-arm-msm@vger.kernel.org +Cc: linux-tegra@vger.kernel.org +Stable-dep-of: 83a939f0fdc2 ("PCI: exynos: Don't discard .remove() callback") +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pci-dra7xx.c | 8 ---- + drivers/pci/controller/dwc/pci-keystone.c | 29 +----------- + .../pci/controller/dwc/pci-layerscape-ep.c | 37 +-------------- + drivers/pci/controller/dwc/pcie-al.c | 9 +--- + drivers/pci/controller/dwc/pcie-artpec6.c | 43 ++---------------- + .../pci/controller/dwc/pcie-designware-ep.c | 29 ++++++++++-- + .../pci/controller/dwc/pcie-designware-host.c | 7 +++ + .../pci/controller/dwc/pcie-designware-plat.c | 45 +------------------ + drivers/pci/controller/dwc/pcie-intel-gw.c | 4 -- + drivers/pci/controller/dwc/pcie-kirin.c | 5 --- + drivers/pci/controller/dwc/pcie-qcom.c | 8 ---- + drivers/pci/controller/dwc/pcie-spear13xx.c | 11 +---- + drivers/pci/controller/dwc/pcie-tegra194.c | 22 --------- + drivers/pci/controller/dwc/pcie-uniphier-ep.c | 38 +--------------- + drivers/pci/controller/dwc/pcie-uniphier.c | 6 --- + 15 files changed, 47 insertions(+), 254 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c +index 6d012d2b1e90d..a4aabc85dbb12 100644 +--- a/drivers/pci/controller/dwc/pci-dra7xx.c ++++ b/drivers/pci/controller/dwc/pci-dra7xx.c +@@ -578,7 +578,6 @@ static int __init dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx, + { + int ret; + struct dw_pcie_ep *ep; +- struct resource *res; + struct device *dev = &pdev->dev; + struct dw_pcie *pci = dra7xx->pci; + +@@ -594,13 +593,6 @@ static int __init dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx, + if (IS_ERR(pci->dbi_base2)) + return PTR_ERR(pci->dbi_base2); + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); +- if (!res) +- return -EINVAL; +- +- ep->phys_base = res->start; +- ep->addr_size = resource_size(res); +- + ret = dw_pcie_ep_init(ep); + if (ret) { + dev_err(dev, "failed to initialize endpoint\n"); +diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c +index 5b722287aac92..5177f6d1ca592 100644 +--- a/drivers/pci/controller/dwc/pci-keystone.c ++++ b/drivers/pci/controller/dwc/pci-keystone.c +@@ -978,33 +978,6 @@ static const struct dw_pcie_ep_ops ks_pcie_am654_ep_ops = { + .get_features = &ks_pcie_am654_get_features, + }; + +-static int __init ks_pcie_add_pcie_ep(struct keystone_pcie *ks_pcie, +- struct platform_device *pdev) +-{ +- int ret; +- struct dw_pcie_ep *ep; +- struct resource *res; +- struct device *dev = &pdev->dev; +- struct dw_pcie *pci = ks_pcie->pci; +- +- ep = &pci->ep; +- +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); +- if (!res) +- return -EINVAL; +- +- ep->phys_base = res->start; +- ep->addr_size = resource_size(res); +- +- ret = dw_pcie_ep_init(ep); +- if (ret) { +- dev_err(dev, "failed to initialize endpoint\n"); +- return ret; +- } +- +- return 0; +-} +- + static void ks_pcie_disable_phy(struct keystone_pcie *ks_pcie) + { + int num_lanes = ks_pcie->num_lanes; +@@ -1314,7 +1287,7 @@ static int ks_pcie_probe(struct platform_device *pdev) + } + + pci->ep.ops = ep_ops; +- ret = ks_pcie_add_pcie_ep(ks_pcie, pdev); ++ ret = dw_pcie_ep_init(&pci->ep); + if (ret < 0) + goto err_get_sync; + break; +diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c +index 84206f265e544..4d12efdacd2f5 100644 +--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c ++++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c +@@ -18,8 +18,6 @@ + + #include "pcie-designware.h" + +-#define PCIE_DBI2_OFFSET 0x1000 /* DBI2 base address*/ +- + #define to_ls_pcie_ep(x) dev_get_drvdata((x)->dev) + + struct ls_pcie_ep_drvdata { +@@ -124,34 +122,6 @@ static const struct of_device_id ls_pcie_ep_of_match[] = { + { }, + }; + +-static int __init ls_add_pcie_ep(struct ls_pcie_ep *pcie, +- struct platform_device *pdev) +-{ +- struct dw_pcie *pci = pcie->pci; +- struct device *dev = pci->dev; +- struct dw_pcie_ep *ep; +- struct resource *res; +- int ret; +- +- ep = &pci->ep; +- ep->ops = pcie->drvdata->ops; +- +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); +- if (!res) +- return -EINVAL; +- +- ep->phys_base = res->start; +- ep->addr_size = resource_size(res); +- +- ret = dw_pcie_ep_init(ep); +- if (ret) { +- dev_err(dev, "failed to initialize endpoint\n"); +- return ret; +- } +- +- return 0; +-} +- + static int __init ls_pcie_ep_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -159,7 +129,6 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev) + struct ls_pcie_ep *pcie; + struct pci_epc_features *ls_epc; + struct resource *dbi_base; +- int ret; + + pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); + if (!pcie) +@@ -188,13 +157,11 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev) + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); + +- pci->dbi_base2 = pci->dbi_base + PCIE_DBI2_OFFSET; ++ pci->ep.ops = &ls_pcie_ep_ops; + + platform_set_drvdata(pdev, pcie); + +- ret = ls_add_pcie_ep(pcie, pdev); +- +- return ret; ++ return dw_pcie_ep_init(&pci->ep); + } + + static struct platform_driver ls_pcie_ep_driver = { +diff --git a/drivers/pci/controller/dwc/pcie-al.c b/drivers/pci/controller/dwc/pcie-al.c +index f973fbca90cf7..d06866921187b 100644 +--- a/drivers/pci/controller/dwc/pcie-al.c ++++ b/drivers/pci/controller/dwc/pcie-al.c +@@ -347,7 +347,6 @@ static int al_pcie_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct resource *controller_res; + struct resource *ecam_res; +- struct resource *dbi_res; + struct al_pcie *al_pcie; + struct dw_pcie *pci; + +@@ -365,11 +364,6 @@ static int al_pcie_probe(struct platform_device *pdev) + al_pcie->pci = pci; + al_pcie->dev = dev; + +- dbi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); +- pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_res); +- if (IS_ERR(pci->dbi_base)) +- return PTR_ERR(pci->dbi_base); +- + ecam_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); + if (!ecam_res) { + dev_err(dev, "couldn't find 'config' reg in DT\n"); +@@ -386,8 +380,7 @@ static int al_pcie_probe(struct platform_device *pdev) + return PTR_ERR(al_pcie->controller_base); + } + +- dev_dbg(dev, "From DT: dbi_base: %pR, controller_base: %pR\n", +- dbi_res, controller_res); ++ dev_dbg(dev, "From DT: controller_base: %pR\n", controller_res); + + platform_set_drvdata(pdev, al_pcie); + +diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c +index 929448e9e0bc6..52ad7909cd0c0 100644 +--- a/drivers/pci/controller/dwc/pcie-artpec6.c ++++ b/drivers/pci/controller/dwc/pcie-artpec6.c +@@ -403,38 +403,6 @@ static const struct dw_pcie_ep_ops pcie_ep_ops = { + .raise_irq = artpec6_pcie_raise_irq, + }; + +-static int artpec6_add_pcie_ep(struct artpec6_pcie *artpec6_pcie, +- struct platform_device *pdev) +-{ +- int ret; +- struct dw_pcie_ep *ep; +- struct resource *res; +- struct device *dev = &pdev->dev; +- struct dw_pcie *pci = artpec6_pcie->pci; +- +- ep = &pci->ep; +- ep->ops = &pcie_ep_ops; +- +- pci->dbi_base2 = devm_platform_ioremap_resource_byname(pdev, "dbi2"); +- if (IS_ERR(pci->dbi_base2)) +- return PTR_ERR(pci->dbi_base2); +- +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); +- if (!res) +- return -EINVAL; +- +- ep->phys_base = res->start; +- ep->addr_size = resource_size(res); +- +- ret = dw_pcie_ep_init(ep); +- if (ret) { +- dev_err(dev, "failed to initialize endpoint\n"); +- return ret; +- } +- +- return 0; +-} +- + static int artpec6_pcie_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -469,10 +437,6 @@ static int artpec6_pcie_probe(struct platform_device *pdev) + artpec6_pcie->variant = variant; + artpec6_pcie->mode = mode; + +- pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "dbi"); +- if (IS_ERR(pci->dbi_base)) +- return PTR_ERR(pci->dbi_base); +- + artpec6_pcie->phy_base = + devm_platform_ioremap_resource_byname(pdev, "phy"); + if (IS_ERR(artpec6_pcie->phy_base)) +@@ -504,9 +468,10 @@ static int artpec6_pcie_probe(struct platform_device *pdev) + val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); + val &= ~PCIECFG_DEVICE_TYPE_MASK; + artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); +- ret = artpec6_add_pcie_ep(artpec6_pcie, pdev); +- if (ret < 0) +- return ret; ++ ++ pci->ep.ops = &pcie_ep_ops; ++ ++ return dw_pcie_ep_init(&pci->ep); + break; + } + default: +diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c +index 95ed719402d75..ea1b8893d25fe 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-ep.c ++++ b/drivers/pci/controller/dwc/pcie-designware-ep.c +@@ -7,6 +7,7 @@ + */ + + #include ++#include + + #include "pcie-designware.h" + #include +@@ -676,20 +677,42 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) + int ret; + void *addr; + u8 func_no; ++ struct resource *res; + struct pci_epc *epc; + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + struct device *dev = pci->dev; ++ struct platform_device *pdev = to_platform_device(dev); + struct device_node *np = dev->of_node; + const struct pci_epc_features *epc_features; + struct dw_pcie_ep_func *ep_func; + + INIT_LIST_HEAD(&ep->func_list); + +- if (!pci->dbi_base || !pci->dbi_base2) { +- dev_err(dev, "dbi_base/dbi_base2 is not populated\n"); +- return -EINVAL; ++ if (!pci->dbi_base) { ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); ++ pci->dbi_base = devm_pci_remap_cfg_resource(dev, res); ++ if (IS_ERR(pci->dbi_base)) ++ return PTR_ERR(pci->dbi_base); ++ } ++ ++ if (!pci->dbi_base2) { ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi2"); ++ if (!res) ++ pci->dbi_base2 = pci->dbi_base + SZ_4K; ++ else { ++ pci->dbi_base2 = devm_pci_remap_cfg_resource(dev, res); ++ if (IS_ERR(pci->dbi_base2)) ++ return PTR_ERR(pci->dbi_base2); ++ } + } + ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); ++ if (!res) ++ return -EINVAL; ++ ++ ep->phys_base = res->start; ++ ep->addr_size = resource_size(res); ++ + ret = of_property_read_u32(np, "num-ib-windows", &ep->num_ib_windows); + if (ret < 0) { + dev_err(dev, "Unable to read *num-ib-windows* property\n"); +diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c +index 42d8116a4a002..d6b7eec1a25b0 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -310,6 +310,13 @@ int dw_pcie_host_init(struct pcie_port *pp) + dev_err(dev, "Missing *config* reg space\n"); + } + ++ if (!pci->dbi_base) { ++ struct resource *dbi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); ++ pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_res); ++ if (IS_ERR(pci->dbi_base)) ++ return PTR_ERR(pci->dbi_base); ++ } ++ + bridge = devm_pci_alloc_host_bridge(dev, 0); + if (!bridge) + return -ENOMEM; +diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c +index e3e300669ed56..562a05e07b1d5 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-plat.c ++++ b/drivers/pci/controller/dwc/pcie-designware-plat.c +@@ -139,43 +139,11 @@ static int dw_plat_add_pcie_port(struct dw_plat_pcie *dw_plat_pcie, + return 0; + } + +-static int dw_plat_add_pcie_ep(struct dw_plat_pcie *dw_plat_pcie, +- struct platform_device *pdev) +-{ +- int ret; +- struct dw_pcie_ep *ep; +- struct resource *res; +- struct device *dev = &pdev->dev; +- struct dw_pcie *pci = dw_plat_pcie->pci; +- +- ep = &pci->ep; +- ep->ops = &pcie_ep_ops; +- +- pci->dbi_base2 = devm_platform_ioremap_resource_byname(pdev, "dbi2"); +- if (IS_ERR(pci->dbi_base2)) +- return PTR_ERR(pci->dbi_base2); +- +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); +- if (!res) +- return -EINVAL; +- +- ep->phys_base = res->start; +- ep->addr_size = resource_size(res); +- +- ret = dw_pcie_ep_init(ep); +- if (ret) { +- dev_err(dev, "Failed to initialize endpoint\n"); +- return ret; +- } +- return 0; +-} +- + static int dw_plat_pcie_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct dw_plat_pcie *dw_plat_pcie; + struct dw_pcie *pci; +- struct resource *res; /* Resource from DT */ + int ret; + const struct of_device_id *match; + const struct dw_plat_pcie_of_data *data; +@@ -202,14 +170,6 @@ static int dw_plat_pcie_probe(struct platform_device *pdev) + dw_plat_pcie->pci = pci; + dw_plat_pcie->mode = mode; + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); +- if (!res) +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- +- pci->dbi_base = devm_ioremap_resource(dev, res); +- if (IS_ERR(pci->dbi_base)) +- return PTR_ERR(pci->dbi_base); +- + platform_set_drvdata(pdev, dw_plat_pcie); + + switch (dw_plat_pcie->mode) { +@@ -225,9 +185,8 @@ static int dw_plat_pcie_probe(struct platform_device *pdev) + if (!IS_ENABLED(CONFIG_PCIE_DW_PLAT_EP)) + return -ENODEV; + +- ret = dw_plat_add_pcie_ep(dw_plat_pcie, pdev); +- if (ret < 0) +- return ret; ++ pci->ep.ops = &pcie_ep_ops; ++ return dw_pcie_ep_init(&pci->ep); + break; + default: + dev_err(dev, "INVALID device type %d\n", dw_plat_pcie->mode); +diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c +index 5e1a284fdc538..429171c35945d 100644 +--- a/drivers/pci/controller/dwc/pcie-intel-gw.c ++++ b/drivers/pci/controller/dwc/pcie-intel-gw.c +@@ -236,10 +236,6 @@ static int intel_pcie_get_resources(struct platform_device *pdev) + struct device *dev = pci->dev; + int ret; + +- pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "dbi"); +- if (IS_ERR(pci->dbi_base)) +- return PTR_ERR(pci->dbi_base); +- + lpp->core_clk = devm_clk_get(dev, NULL); + if (IS_ERR(lpp->core_clk)) { + ret = PTR_ERR(lpp->core_clk); +diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c +index d0a6a2dee6f5b..3042a23cf09a4 100644 +--- a/drivers/pci/controller/dwc/pcie-kirin.c ++++ b/drivers/pci/controller/dwc/pcie-kirin.c +@@ -157,11 +157,6 @@ static long kirin_pcie_get_resource(struct kirin_pcie *kirin_pcie, + if (IS_ERR(kirin_pcie->phy_base)) + return PTR_ERR(kirin_pcie->phy_base); + +- kirin_pcie->pci->dbi_base = +- devm_platform_ioremap_resource_byname(pdev, "dbi"); +- if (IS_ERR(kirin_pcie->pci->dbi_base)) +- return PTR_ERR(kirin_pcie->pci->dbi_base); +- + kirin_pcie->crgctrl = + syscon_regmap_lookup_by_compatible("hisilicon,hi3660-crgctrl"); + if (IS_ERR(kirin_pcie->crgctrl)) +diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c +index c68e14271c02c..150dd6fe7ba39 100644 +--- a/drivers/pci/controller/dwc/pcie-qcom.c ++++ b/drivers/pci/controller/dwc/pcie-qcom.c +@@ -1360,7 +1360,6 @@ static const struct dw_pcie_ops dw_pcie_ops = { + static int qcom_pcie_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct resource *res; + struct pcie_port *pp; + struct dw_pcie *pci; + struct qcom_pcie *pcie; +@@ -1399,13 +1398,6 @@ static int qcom_pcie_probe(struct platform_device *pdev) + goto err_pm_runtime_put; + } + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); +- pci->dbi_base = devm_pci_remap_cfg_resource(dev, res); +- if (IS_ERR(pci->dbi_base)) { +- ret = PTR_ERR(pci->dbi_base); +- goto err_pm_runtime_put; +- } +- + pcie->elbi = devm_platform_ioremap_resource_byname(pdev, "elbi"); + if (IS_ERR(pcie->elbi)) { + ret = PTR_ERR(pcie->elbi); +diff --git a/drivers/pci/controller/dwc/pcie-spear13xx.c b/drivers/pci/controller/dwc/pcie-spear13xx.c +index e348225f651fb..1ed7e3501ff1c 100644 +--- a/drivers/pci/controller/dwc/pcie-spear13xx.c ++++ b/drivers/pci/controller/dwc/pcie-spear13xx.c +@@ -152,6 +152,8 @@ static int spear13xx_pcie_host_init(struct pcie_port *pp) + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci); + ++ spear13xx_pcie->app_base = pci->dbi_base + 0x2000; ++ + spear13xx_pcie_establish_link(spear13xx_pcie); + spear13xx_pcie_enable_interrupts(spear13xx_pcie); + +@@ -203,7 +205,6 @@ static int spear13xx_pcie_probe(struct platform_device *pdev) + struct dw_pcie *pci; + struct spear13xx_pcie *spear13xx_pcie; + struct device_node *np = dev->of_node; +- struct resource *dbi_base; + int ret; + + spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL); +@@ -242,14 +243,6 @@ static int spear13xx_pcie_probe(struct platform_device *pdev) + return ret; + } + +- dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); +- pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base); +- if (IS_ERR(pci->dbi_base)) { +- ret = PTR_ERR(pci->dbi_base); +- goto fail_clk; +- } +- spear13xx_pcie->app_base = pci->dbi_base + 0x2000; +- + if (of_property_read_bool(np, "st,pcie-is-gen1")) + pci->link_gen = 1; + +diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c +index 80c2015b49d8f..825cb65945fba 100644 +--- a/drivers/pci/controller/dwc/pcie-tegra194.c ++++ b/drivers/pci/controller/dwc/pcie-tegra194.c +@@ -1913,19 +1913,12 @@ static int tegra_pcie_config_ep(struct tegra_pcie_dw *pcie, + struct dw_pcie *pci = &pcie->pci; + struct device *dev = pcie->dev; + struct dw_pcie_ep *ep; +- struct resource *res; + char *name; + int ret; + + ep = &pci->ep; + ep->ops = &pcie_ep_ops; + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); +- if (!res) +- return -EINVAL; +- +- ep->phys_base = res->start; +- ep->addr_size = resource_size(res); + ep->page_size = SZ_64K; + + ret = gpiod_set_debounce(pcie->pex_rst_gpiod, PERST_DEBOUNCE_TIME); +@@ -1989,7 +1982,6 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct resource *atu_dma_res; + struct tegra_pcie_dw *pcie; +- struct resource *dbi_res; + struct pcie_port *pp; + struct dw_pcie *pci; + struct phy **phys; +@@ -2098,20 +2090,6 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev) + + pcie->phys = phys; + +- dbi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); +- if (!dbi_res) { +- dev_err(dev, "Failed to find \"dbi\" region\n"); +- return -ENODEV; +- } +- pcie->dbi_res = dbi_res; +- +- pci->dbi_base = devm_ioremap_resource(dev, dbi_res); +- if (IS_ERR(pci->dbi_base)) +- return PTR_ERR(pci->dbi_base); +- +- /* Tegra HW locates DBI2 at a fixed offset from DBI */ +- pci->dbi_base2 = pci->dbi_base + 0x1000; +- + atu_dma_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "atu_dma"); + if (!atu_dma_res) { +diff --git a/drivers/pci/controller/dwc/pcie-uniphier-ep.c b/drivers/pci/controller/dwc/pcie-uniphier-ep.c +index 1483559600610..69810c6b0d584 100644 +--- a/drivers/pci/controller/dwc/pcie-uniphier-ep.c ++++ b/drivers/pci/controller/dwc/pcie-uniphier-ep.c +@@ -218,35 +218,6 @@ static const struct dw_pcie_ep_ops uniphier_pcie_ep_ops = { + .get_features = uniphier_pcie_get_features, + }; + +-static int uniphier_add_pcie_ep(struct uniphier_pcie_ep_priv *priv, +- struct platform_device *pdev) +-{ +- struct dw_pcie *pci = &priv->pci; +- struct dw_pcie_ep *ep = &pci->ep; +- struct device *dev = &pdev->dev; +- struct resource *res; +- int ret; +- +- ep->ops = &uniphier_pcie_ep_ops; +- +- pci->dbi_base2 = devm_platform_ioremap_resource_byname(pdev, "dbi2"); +- if (IS_ERR(pci->dbi_base2)) +- return PTR_ERR(pci->dbi_base2); +- +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); +- if (!res) +- return -EINVAL; +- +- ep->phys_base = res->start; +- ep->addr_size = resource_size(res); +- +- ret = dw_pcie_ep_init(ep); +- if (ret) +- dev_err(dev, "Failed to initialize endpoint (%d)\n", ret); +- +- return ret; +-} +- + static int uniphier_pcie_ep_enable(struct uniphier_pcie_ep_priv *priv) + { + int ret; +@@ -300,7 +271,6 @@ static int uniphier_pcie_ep_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct uniphier_pcie_ep_priv *priv; +- struct resource *res; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +@@ -314,11 +284,6 @@ static int uniphier_pcie_ep_probe(struct platform_device *pdev) + priv->pci.dev = dev; + priv->pci.ops = &dw_pcie_ops; + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); +- priv->pci.dbi_base = devm_pci_remap_cfg_resource(dev, res); +- if (IS_ERR(priv->pci.dbi_base)) +- return PTR_ERR(priv->pci.dbi_base); +- + priv->base = devm_platform_ioremap_resource_byname(pdev, "link"); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); +@@ -352,7 +317,8 @@ static int uniphier_pcie_ep_probe(struct platform_device *pdev) + if (ret) + return ret; + +- return uniphier_add_pcie_ep(priv, pdev); ++ priv->pci.ep.ops = &uniphier_pcie_ep_ops; ++ return dw_pcie_ep_init(&priv->pci.ep); + } + + static const struct pci_epc_features uniphier_pro5_data = { +diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c +index 527ec8aeb602f..85bf170e93541 100644 +--- a/drivers/pci/controller/dwc/pcie-uniphier.c ++++ b/drivers/pci/controller/dwc/pcie-uniphier.c +@@ -394,7 +394,6 @@ static int uniphier_pcie_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct uniphier_pcie_priv *priv; +- struct resource *res; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +@@ -404,11 +403,6 @@ static int uniphier_pcie_probe(struct platform_device *pdev) + priv->pci.dev = dev; + priv->pci.ops = &dw_pcie_ops; + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); +- priv->pci.dbi_base = devm_pci_remap_cfg_resource(dev, res); +- if (IS_ERR(priv->pci.dbi_base)) +- return PTR_ERR(priv->pci.dbi_base); +- + priv->base = devm_platform_ioremap_resource_byname(pdev, "link"); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); +-- +2.42.0 + diff --git a/queue-5.10/pci-dwc-move-dw_pcie_msi_init-into-core.patch b/queue-5.10/pci-dwc-move-dw_pcie_msi_init-into-core.patch new file mode 100644 index 00000000000..33367c48e91 --- /dev/null +++ b/queue-5.10/pci-dwc-move-dw_pcie_msi_init-into-core.patch @@ -0,0 +1,309 @@ +From 991c38cf974a9c07aaa5c25b35d535adee2ed41d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Nov 2020 15:11:54 -0600 +Subject: PCI: dwc: Move dw_pcie_msi_init() into core + +From: Rob Herring + +[ Upstream commit 59fbab1ae40eb048eb2bd2385a5b981051513458 ] + +The host drivers which call dw_pcie_msi_init() are all the ones using +the built-in MSI controller, so let's move it into the common DWC code. + +Link: https://lore.kernel.org/r/20201105211159.1814485-12-robh@kernel.org +Tested-by: Marek Szyprowski +Signed-off-by: Rob Herring +Signed-off-by: Lorenzo Pieralisi +Acked-by: Jingoo Han +Cc: Kishon Vijay Abraham I +Cc: Lorenzo Pieralisi +Cc: Bjorn Helgaas +Cc: Kukjin Kim +Cc: Krzysztof Kozlowski +Cc: Richard Zhu +Cc: Lucas Stach +Cc: Shawn Guo +Cc: Sascha Hauer +Cc: Pengutronix Kernel Team +Cc: Fabio Estevam +Cc: NXP Linux Team +Cc: Yue Wang +Cc: Kevin Hilman +Cc: Neil Armstrong +Cc: Jerome Brunet +Cc: Martin Blumenstingl +Cc: Jesper Nilsson +Cc: Gustavo Pimentel +Cc: Xiaowei Song +Cc: Binghui Wang +Cc: Stanimir Varbanov +Cc: Andy Gross +Cc: Bjorn Andersson +Cc: Pratyush Anand +Cc: Thierry Reding +Cc: Jonathan Hunter +Cc: Kunihiko Hayashi +Cc: Masahiro Yamada +Cc: linux-omap@vger.kernel.org +Cc: linux-samsung-soc@vger.kernel.org +Cc: linux-amlogic@lists.infradead.org +Cc: linux-arm-kernel@axis.com +Cc: linux-arm-msm@vger.kernel.org +Cc: linux-tegra@vger.kernel.org +Stable-dep-of: 83a939f0fdc2 ("PCI: exynos: Don't discard .remove() callback") +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pci-dra7xx.c | 2 -- + drivers/pci/controller/dwc/pci-exynos.c | 4 ---- + drivers/pci/controller/dwc/pci-imx6.c | 1 - + drivers/pci/controller/dwc/pci-meson.c | 1 - + drivers/pci/controller/dwc/pcie-artpec6.c | 1 - + drivers/pci/controller/dwc/pcie-designware-host.c | 9 +++++---- + drivers/pci/controller/dwc/pcie-designware-plat.c | 1 - + drivers/pci/controller/dwc/pcie-designware.h | 10 ---------- + drivers/pci/controller/dwc/pcie-histb.c | 2 -- + drivers/pci/controller/dwc/pcie-kirin.c | 1 - + drivers/pci/controller/dwc/pcie-qcom.c | 2 -- + drivers/pci/controller/dwc/pcie-spear13xx.c | 6 +----- + drivers/pci/controller/dwc/pcie-tegra194.c | 2 -- + drivers/pci/controller/dwc/pcie-uniphier.c | 1 - + 14 files changed, 6 insertions(+), 37 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c +index 054423d9646d6..72a5a2bf933bc 100644 +--- a/drivers/pci/controller/dwc/pci-dra7xx.c ++++ b/drivers/pci/controller/dwc/pci-dra7xx.c +@@ -182,8 +182,6 @@ static int dra7xx_pcie_host_init(struct pcie_port *pp) + struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); + + dw_pcie_setup_rc(pp); +- +- dw_pcie_msi_init(pp); + dra7xx_pcie_enable_interrupts(dra7xx); + + return 0; +diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c +index 6498b615c834a..3939fe22e8a20 100644 +--- a/drivers/pci/controller/dwc/pci-exynos.c ++++ b/drivers/pci/controller/dwc/pci-exynos.c +@@ -273,12 +273,8 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) + + static void exynos_pcie_msi_init(struct exynos_pcie *ep) + { +- struct dw_pcie *pci = ep->pci; +- struct pcie_port *pp = &pci->pp; + u32 val; + +- dw_pcie_msi_init(pp); +- + /* enable MSI interrupt */ + val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL); + val |= IRQ_MSI_ENABLE; +diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c +index 8d1d2d79693d6..dbdf79ac48683 100644 +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -840,7 +840,6 @@ static int imx6_pcie_host_init(struct pcie_port *pp) + imx6_pcie_deassert_core_reset(imx6_pcie); + imx6_setup_phy_mpll(imx6_pcie); + dw_pcie_setup_rc(pp); +- dw_pcie_msi_init(pp); + + return 0; + } +diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c +index 41a3351b100b5..2df0adcf0bf22 100644 +--- a/drivers/pci/controller/dwc/pci-meson.c ++++ b/drivers/pci/controller/dwc/pci-meson.c +@@ -381,7 +381,6 @@ static int meson_pcie_host_init(struct pcie_port *pp) + meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE); + + dw_pcie_setup_rc(pp); +- dw_pcie_msi_init(pp); + + return 0; + } +diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c +index 8b3da3038ac35..7ee8f3c83f8f3 100644 +--- a/drivers/pci/controller/dwc/pcie-artpec6.c ++++ b/drivers/pci/controller/dwc/pcie-artpec6.c +@@ -329,7 +329,6 @@ static int artpec6_pcie_host_init(struct pcie_port *pp) + artpec6_pcie_deassert_core_reset(artpec6_pcie); + artpec6_pcie_wait_for_phy(artpec6_pcie); + dw_pcie_setup_rc(pp); +- dw_pcie_msi_init(pp); + + return 0; + } +diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c +index b242d7e64c204..e740cbeda2bbc 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -256,7 +256,7 @@ int dw_pcie_allocate_domains(struct pcie_port *pp) + return 0; + } + +-void dw_pcie_free_msi(struct pcie_port *pp) ++static void dw_pcie_free_msi(struct pcie_port *pp) + { + if (pp->msi_irq) { + irq_set_chained_handler(pp->msi_irq, NULL); +@@ -275,19 +275,18 @@ void dw_pcie_free_msi(struct pcie_port *pp) + } + } + +-void dw_pcie_msi_init(struct pcie_port *pp) ++static void dw_pcie_msi_init(struct pcie_port *pp) + { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + u64 msi_target = (u64)pp->msi_data; + +- if (!IS_ENABLED(CONFIG_PCI_MSI)) ++ if (!pci_msi_enabled() || !pp->has_msi_ctrl) + return; + + /* Program the msi_data */ + dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target)); + dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target)); + } +-EXPORT_SYMBOL_GPL(dw_pcie_msi_init); + + int dw_pcie_host_init(struct pcie_port *pp) + { +@@ -424,6 +423,8 @@ int dw_pcie_host_init(struct pcie_port *pp) + goto err_free_msi; + } + ++ dw_pcie_msi_init(pp); ++ + if (!dw_pcie_link_up(pci) && pci->ops->start_link) { + ret = pci->ops->start_link(pci); + if (ret) +diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c +index adebcaeb1a6c0..dec24e595c3e0 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-plat.c ++++ b/drivers/pci/controller/dwc/pcie-designware-plat.c +@@ -36,7 +36,6 @@ static const struct of_device_id dw_plat_pcie_of_match[]; + static int dw_plat_pcie_host_init(struct pcie_port *pp) + { + dw_pcie_setup_rc(pp); +- dw_pcie_msi_init(pp); + + return 0; + } +diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h +index f33dc89a93650..04c61e2e23d07 100644 +--- a/drivers/pci/controller/dwc/pcie-designware.h ++++ b/drivers/pci/controller/dwc/pcie-designware.h +@@ -365,8 +365,6 @@ static inline void dw_pcie_dbi_ro_wr_dis(struct dw_pcie *pci) + + #ifdef CONFIG_PCIE_DW_HOST + irqreturn_t dw_handle_msi_irq(struct pcie_port *pp); +-void dw_pcie_msi_init(struct pcie_port *pp); +-void dw_pcie_free_msi(struct pcie_port *pp); + void dw_pcie_setup_rc(struct pcie_port *pp); + int dw_pcie_host_init(struct pcie_port *pp); + void dw_pcie_host_deinit(struct pcie_port *pp); +@@ -379,14 +377,6 @@ static inline irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) + return IRQ_NONE; + } + +-static inline void dw_pcie_msi_init(struct pcie_port *pp) +-{ +-} +- +-static inline void dw_pcie_free_msi(struct pcie_port *pp) +-{ +-} +- + static inline void dw_pcie_setup_rc(struct pcie_port *pp) + { + } +diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c +index ece544165059b..210777c793ea0 100644 +--- a/drivers/pci/controller/dwc/pcie-histb.c ++++ b/drivers/pci/controller/dwc/pcie-histb.c +@@ -199,8 +199,6 @@ static int histb_pcie_host_init(struct pcie_port *pp) + /* setup root complex */ + dw_pcie_setup_rc(pp); + +- dw_pcie_msi_init(pp); +- + return 0; + } + +diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c +index 675b4d8392d37..f84ac1b36b2cc 100644 +--- a/drivers/pci/controller/dwc/pcie-kirin.c ++++ b/drivers/pci/controller/dwc/pcie-kirin.c +@@ -406,7 +406,6 @@ static int kirin_pcie_host_init(struct pcie_port *pp) + pp->bridge->ops = &kirin_pci_ops; + + dw_pcie_setup_rc(pp); +- dw_pcie_msi_init(pp); + + return 0; + } +diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c +index 03251e34137f3..b482264541bc2 100644 +--- a/drivers/pci/controller/dwc/pcie-qcom.c ++++ b/drivers/pci/controller/dwc/pcie-qcom.c +@@ -1273,8 +1273,6 @@ static int qcom_pcie_host_init(struct pcie_port *pp) + } + + dw_pcie_setup_rc(pp); +- dw_pcie_msi_init(pp); +- + qcom_ep_reset_deassert(pcie); + + return 0; +diff --git a/drivers/pci/controller/dwc/pcie-spear13xx.c b/drivers/pci/controller/dwc/pcie-spear13xx.c +index ebbaa06fc8ab5..31475e4493a70 100644 +--- a/drivers/pci/controller/dwc/pcie-spear13xx.c ++++ b/drivers/pci/controller/dwc/pcie-spear13xx.c +@@ -102,16 +102,12 @@ static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg) + + static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pcie) + { +- struct dw_pcie *pci = spear13xx_pcie->pci; +- struct pcie_port *pp = &pci->pp; + struct pcie_app_reg *app_reg = spear13xx_pcie->app_base; + + /* Enable MSI interrupt */ +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- dw_pcie_msi_init(pp); ++ if (IS_ENABLED(CONFIG_PCI_MSI)) + writel(readl(&app_reg->int_mask) | + MSI_CTRL_INT, &app_reg->int_mask); +- } + } + + static int spear13xx_pcie_link_up(struct dw_pcie *pci) +diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c +index 782aa3f382829..e5cd9751e6e8c 100644 +--- a/drivers/pci/controller/dwc/pcie-tegra194.c ++++ b/drivers/pci/controller/dwc/pcie-tegra194.c +@@ -767,8 +767,6 @@ static void tegra_pcie_enable_msi_interrupts(struct pcie_port *pp) + struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); + u32 val; + +- dw_pcie_msi_init(pp); +- + /* Enable MSI interrupt generation */ + val = appl_readl(pcie, APPL_INTR_EN_L0_0); + val |= APPL_INTR_EN_L0_0_SYS_MSI_INTR_EN; +diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c +index bd4bf2db9480e..83f545b326003 100644 +--- a/drivers/pci/controller/dwc/pcie-uniphier.c ++++ b/drivers/pci/controller/dwc/pcie-uniphier.c +@@ -309,7 +309,6 @@ static int uniphier_pcie_host_init(struct pcie_port *pp) + uniphier_pcie_irq_enable(priv); + + dw_pcie_setup_rc(pp); +- dw_pcie_msi_init(pp); + + return 0; + } +-- +2.42.0 + diff --git a/queue-5.10/pci-dwc-move-dw_pcie_setup_rc-to-dwc-common-code.patch b/queue-5.10/pci-dwc-move-dw_pcie_setup_rc-to-dwc-common-code.patch new file mode 100644 index 00000000000..6c2fad7e662 --- /dev/null +++ b/queue-5.10/pci-dwc-move-dw_pcie_setup_rc-to-dwc-common-code.patch @@ -0,0 +1,278 @@ +From 84fe8050a0a03887401d8a144590419e08fd6410 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Nov 2020 15:11:55 -0600 +Subject: PCI: dwc: Move dw_pcie_setup_rc() to DWC common code + +From: Rob Herring + +[ Upstream commit b9ac0f9dc8ea4b91362694e82a1e66313a6c6dc6 ] + +All RC complex drivers must call dw_pcie_setup_rc(). The ordering of the +call shouldn't be too important other than being after any RC resets. + +There's a few calls of dw_pcie_setup_rc() left as drivers implementing +suspend/resume need it. + +Link: https://lore.kernel.org/r/20201105211159.1814485-13-robh@kernel.org +Tested-by: Marek Szyprowski +Signed-off-by: Rob Herring +Signed-off-by: Lorenzo Pieralisi +Acked-by: Jingoo Han +Cc: Kishon Vijay Abraham I +Cc: Lorenzo Pieralisi +Cc: Bjorn Helgaas +Cc: Kukjin Kim +Cc: Krzysztof Kozlowski +Cc: Richard Zhu +Cc: Lucas Stach +Cc: Shawn Guo +Cc: Sascha Hauer +Cc: Pengutronix Kernel Team +Cc: Fabio Estevam +Cc: NXP Linux Team +Cc: Murali Karicheri +Cc: Minghuan Lian +Cc: Mingkai Hu +Cc: Roy Zang +Cc: Yue Wang +Cc: Kevin Hilman +Cc: Neil Armstrong +Cc: Jerome Brunet +Cc: Martin Blumenstingl +Cc: Thomas Petazzoni +Cc: Jesper Nilsson +Cc: Gustavo Pimentel +Cc: Xiaowei Song +Cc: Binghui Wang +Cc: Andy Gross +Cc: Bjorn Andersson +Cc: Stanimir Varbanov +Cc: Pratyush Anand +Cc: Kunihiko Hayashi +Cc: Masahiro Yamada +Cc: linux-omap@vger.kernel.org +Cc: linux-samsung-soc@vger.kernel.org +Cc: linuxppc-dev@lists.ozlabs.org +Cc: linux-amlogic@lists.infradead.org +Cc: linux-arm-kernel@axis.com +Cc: linux-arm-msm@vger.kernel.org +Stable-dep-of: 83a939f0fdc2 ("PCI: exynos: Don't discard .remove() callback") +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pci-dra7xx.c | 1 - + drivers/pci/controller/dwc/pci-exynos.c | 1 - + drivers/pci/controller/dwc/pci-imx6.c | 1 - + drivers/pci/controller/dwc/pci-keystone.c | 2 -- + drivers/pci/controller/dwc/pci-layerscape.c | 2 -- + drivers/pci/controller/dwc/pci-meson.c | 2 -- + drivers/pci/controller/dwc/pcie-armada8k.c | 2 -- + drivers/pci/controller/dwc/pcie-artpec6.c | 1 - + drivers/pci/controller/dwc/pcie-designware-host.c | 1 + + drivers/pci/controller/dwc/pcie-designware-plat.c | 8 -------- + drivers/pci/controller/dwc/pcie-histb.c | 3 --- + drivers/pci/controller/dwc/pcie-kirin.c | 2 -- + drivers/pci/controller/dwc/pcie-qcom.c | 1 - + drivers/pci/controller/dwc/pcie-spear13xx.c | 2 -- + drivers/pci/controller/dwc/pcie-uniphier.c | 2 -- + 15 files changed, 1 insertion(+), 30 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c +index 72a5a2bf933bc..b105af63854a3 100644 +--- a/drivers/pci/controller/dwc/pci-dra7xx.c ++++ b/drivers/pci/controller/dwc/pci-dra7xx.c +@@ -181,7 +181,6 @@ static int dra7xx_pcie_host_init(struct pcie_port *pp) + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); + +- dw_pcie_setup_rc(pp); + dra7xx_pcie_enable_interrupts(dra7xx); + + return 0; +diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c +index 3939fe22e8a20..5c10a5432896c 100644 +--- a/drivers/pci/controller/dwc/pci-exynos.c ++++ b/drivers/pci/controller/dwc/pci-exynos.c +@@ -372,7 +372,6 @@ static int exynos_pcie_host_init(struct pcie_port *pp) + phy_init(ep->phy); + + exynos_pcie_deassert_core_reset(ep); +- dw_pcie_setup_rc(pp); + exynos_pcie_assert_reset(ep); + + exynos_pcie_enable_interrupts(ep); +diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c +index dbdf79ac48683..67f06060f7a48 100644 +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -839,7 +839,6 @@ static int imx6_pcie_host_init(struct pcie_port *pp) + imx6_pcie_init_phy(imx6_pcie); + imx6_pcie_deassert_core_reset(imx6_pcie); + imx6_setup_phy_mpll(imx6_pcie); +- dw_pcie_setup_rc(pp); + + return 0; + } +diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c +index a5db966f6d20b..c3891a6b96123 100644 +--- a/drivers/pci/controller/dwc/pci-keystone.c ++++ b/drivers/pci/controller/dwc/pci-keystone.c +@@ -808,8 +808,6 @@ static int __init ks_pcie_host_init(struct pcie_port *pp) + if (ret) + return ret; + +- dw_pcie_setup_rc(pp); +- + ks_pcie_stop_link(pci); + ks_pcie_setup_rc_app_regs(ks_pcie); + writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8), +diff --git a/drivers/pci/controller/dwc/pci-layerscape.c b/drivers/pci/controller/dwc/pci-layerscape.c +index 4d280b940f1fe..5d325e8acb361 100644 +--- a/drivers/pci/controller/dwc/pci-layerscape.c ++++ b/drivers/pci/controller/dwc/pci-layerscape.c +@@ -150,8 +150,6 @@ static int ls_pcie_host_init(struct pcie_port *pp) + + ls_pcie_drop_msg_tlp(pcie); + +- dw_pcie_setup_rc(pp); +- + return 0; + } + +diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c +index 2df0adcf0bf22..04589f0decb23 100644 +--- a/drivers/pci/controller/dwc/pci-meson.c ++++ b/drivers/pci/controller/dwc/pci-meson.c +@@ -380,8 +380,6 @@ static int meson_pcie_host_init(struct pcie_port *pp) + meson_set_max_payload(mp, MAX_PAYLOAD_SIZE); + meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE); + +- dw_pcie_setup_rc(pp); +- + return 0; + } + +diff --git a/drivers/pci/controller/dwc/pcie-armada8k.c b/drivers/pci/controller/dwc/pcie-armada8k.c +index dd2926bbb9017..4e2552dcf9827 100644 +--- a/drivers/pci/controller/dwc/pcie-armada8k.c ++++ b/drivers/pci/controller/dwc/pcie-armada8k.c +@@ -171,8 +171,6 @@ static int armada8k_pcie_host_init(struct pcie_port *pp) + u32 reg; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + +- dw_pcie_setup_rc(pp); +- + if (!dw_pcie_link_up(pci)) { + /* Disable LTSSM state machine to enable configuration */ + reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG); +diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c +index 7ee8f3c83f8f3..fcba9915a6067 100644 +--- a/drivers/pci/controller/dwc/pcie-artpec6.c ++++ b/drivers/pci/controller/dwc/pcie-artpec6.c +@@ -328,7 +328,6 @@ static int artpec6_pcie_host_init(struct pcie_port *pp) + artpec6_pcie_init_phy(artpec6_pcie); + artpec6_pcie_deassert_core_reset(artpec6_pcie); + artpec6_pcie_wait_for_phy(artpec6_pcie); +- dw_pcie_setup_rc(pp); + + return 0; + } +diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c +index e740cbeda2bbc..44eccd9d956f4 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -423,6 +423,7 @@ int dw_pcie_host_init(struct pcie_port *pp) + goto err_free_msi; + } + ++ dw_pcie_setup_rc(pp); + dw_pcie_msi_init(pp); + + if (!dw_pcie_link_up(pci) && pci->ops->start_link) { +diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c +index dec24e595c3e0..9b397c807261c 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-plat.c ++++ b/drivers/pci/controller/dwc/pcie-designware-plat.c +@@ -33,15 +33,7 @@ struct dw_plat_pcie_of_data { + + static const struct of_device_id dw_plat_pcie_of_match[]; + +-static int dw_plat_pcie_host_init(struct pcie_port *pp) +-{ +- dw_pcie_setup_rc(pp); +- +- return 0; +-} +- + static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = { +- .host_init = dw_plat_pcie_host_init, + }; + + static int dw_plat_pcie_establish_link(struct dw_pcie *pci) +diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c +index 210777c793ea0..86f9d16c50d75 100644 +--- a/drivers/pci/controller/dwc/pcie-histb.c ++++ b/drivers/pci/controller/dwc/pcie-histb.c +@@ -196,9 +196,6 @@ static int histb_pcie_host_init(struct pcie_port *pp) + regval |= PCIE_WM_RC; + histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, regval); + +- /* setup root complex */ +- dw_pcie_setup_rc(pp); +- + return 0; + } + +diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c +index f84ac1b36b2cc..ac4bbdaf53245 100644 +--- a/drivers/pci/controller/dwc/pcie-kirin.c ++++ b/drivers/pci/controller/dwc/pcie-kirin.c +@@ -405,8 +405,6 @@ static int kirin_pcie_host_init(struct pcie_port *pp) + { + pp->bridge->ops = &kirin_pci_ops; + +- dw_pcie_setup_rc(pp); +- + return 0; + } + +diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c +index b482264541bc2..28608f6ef9755 100644 +--- a/drivers/pci/controller/dwc/pcie-qcom.c ++++ b/drivers/pci/controller/dwc/pcie-qcom.c +@@ -1272,7 +1272,6 @@ static int qcom_pcie_host_init(struct pcie_port *pp) + goto err_disable_phy; + } + +- dw_pcie_setup_rc(pp); + qcom_ep_reset_deassert(pcie); + + return 0; +diff --git a/drivers/pci/controller/dwc/pcie-spear13xx.c b/drivers/pci/controller/dwc/pcie-spear13xx.c +index 31475e4493a70..1a9e353bef554 100644 +--- a/drivers/pci/controller/dwc/pcie-spear13xx.c ++++ b/drivers/pci/controller/dwc/pcie-spear13xx.c +@@ -130,8 +130,6 @@ static int spear13xx_pcie_host_init(struct pcie_port *pp) + + spear13xx_pcie->app_base = pci->dbi_base + 0x2000; + +- dw_pcie_setup_rc(pp); +- + /* + * this controller support only 128 bytes read size, however its + * default value in capability register is 512 bytes. So force +diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c +index 83f545b326003..680950a202dd9 100644 +--- a/drivers/pci/controller/dwc/pcie-uniphier.c ++++ b/drivers/pci/controller/dwc/pcie-uniphier.c +@@ -308,8 +308,6 @@ static int uniphier_pcie_host_init(struct pcie_port *pp) + + uniphier_pcie_irq_enable(priv); + +- dw_pcie_setup_rc(pp); +- + return 0; + } + +-- +2.42.0 + diff --git a/queue-5.10/pci-dwc-move-link-handling-into-common-code.patch b/queue-5.10/pci-dwc-move-link-handling-into-common-code.patch new file mode 100644 index 00000000000..412739ab19c --- /dev/null +++ b/queue-5.10/pci-dwc-move-link-handling-into-common-code.patch @@ -0,0 +1,723 @@ +From 709ce1bab4115f2f008a8db0a05d14a9803e9727 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Nov 2020 15:11:53 -0600 +Subject: PCI: dwc: Move link handling into common code + +From: Rob Herring + +[ Upstream commit 886a9c1347558f0568e87fbbe7bcc3a76102bf0b ] + +All the DWC drivers do link setup and checks at roughly the same time. +Let's use the existing .start_link() hook (currently only used in EP +mode) and move the link handling to the core code. + +The behavior for a link down was inconsistent as some drivers would fail +probe in that case while others succeed. Let's standardize this to +succeed as there are usecases where devices (and the link) appear later +even without hotplug. For example, a reconfigured FPGA device. + +Link: https://lore.kernel.org/r/20201105211159.1814485-11-robh@kernel.org +Tested-by: Marek Szyprowski +Signed-off-by: Rob Herring +Signed-off-by: Lorenzo Pieralisi +Acked-by: Jingoo Han +Cc: Kishon Vijay Abraham I +Cc: Lorenzo Pieralisi +Cc: Bjorn Helgaas +Cc: Kukjin Kim +Cc: Krzysztof Kozlowski +Cc: Richard Zhu +Cc: Lucas Stach +Cc: Shawn Guo +Cc: Sascha Hauer +Cc: Pengutronix Kernel Team +Cc: Fabio Estevam +Cc: NXP Linux Team +Cc: Murali Karicheri +Cc: Yue Wang +Cc: Kevin Hilman +Cc: Neil Armstrong +Cc: Jerome Brunet +Cc: Martin Blumenstingl +Cc: Thomas Petazzoni +Cc: Jesper Nilsson +Cc: Gustavo Pimentel +Cc: Xiaowei Song +Cc: Binghui Wang +Cc: Andy Gross +Cc: Bjorn Andersson +Cc: Stanimir Varbanov +Cc: Pratyush Anand +Cc: Thierry Reding +Cc: Jonathan Hunter +Cc: Kunihiko Hayashi +Cc: Masahiro Yamada +Cc: linux-omap@vger.kernel.org +Cc: linux-samsung-soc@vger.kernel.org +Cc: linux-amlogic@lists.infradead.org +Cc: linux-arm-kernel@axis.com +Cc: linux-arm-msm@vger.kernel.org +Cc: linux-tegra@vger.kernel.org +Stable-dep-of: 83a939f0fdc2 ("PCI: exynos: Don't discard .remove() callback") +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pci-dra7xx.c | 2 - + drivers/pci/controller/dwc/pci-exynos.c | 41 +++++++---------- + drivers/pci/controller/dwc/pci-imx6.c | 9 ++-- + drivers/pci/controller/dwc/pci-keystone.c | 9 ---- + drivers/pci/controller/dwc/pci-meson.c | 24 ++++------ + drivers/pci/controller/dwc/pcie-armada8k.c | 39 +++++++--------- + drivers/pci/controller/dwc/pcie-artpec6.c | 2 - + .../pci/controller/dwc/pcie-designware-host.c | 9 ++++ + .../pci/controller/dwc/pcie-designware-plat.c | 3 -- + drivers/pci/controller/dwc/pcie-histb.c | 34 +++++++------- + drivers/pci/controller/dwc/pcie-kirin.c | 23 ++-------- + drivers/pci/controller/dwc/pcie-qcom.c | 19 ++------ + drivers/pci/controller/dwc/pcie-spear13xx.c | 46 ++++++++----------- + drivers/pci/controller/dwc/pcie-tegra194.c | 1 - + drivers/pci/controller/dwc/pcie-uniphier.c | 13 ++---- + 15 files changed, 103 insertions(+), 171 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c +index 6b75c68dddb56..054423d9646d6 100644 +--- a/drivers/pci/controller/dwc/pci-dra7xx.c ++++ b/drivers/pci/controller/dwc/pci-dra7xx.c +@@ -183,8 +183,6 @@ static int dra7xx_pcie_host_init(struct pcie_port *pp) + + dw_pcie_setup_rc(pp); + +- dra7xx_pcie_establish_link(pci); +- dw_pcie_wait_for_link(pci); + dw_pcie_msi_init(pp); + dra7xx_pcie_enable_interrupts(dra7xx); + +diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c +index 7734394953e57..6498b615c834a 100644 +--- a/drivers/pci/controller/dwc/pci-exynos.c ++++ b/drivers/pci/controller/dwc/pci-exynos.c +@@ -229,30 +229,9 @@ static void exynos_pcie_assert_reset(struct exynos_pcie *ep) + GPIOF_OUT_INIT_HIGH, "RESET"); + } + +-static int exynos_pcie_establish_link(struct exynos_pcie *ep) ++static int exynos_pcie_start_link(struct dw_pcie *pci) + { +- struct dw_pcie *pci = ep->pci; +- struct pcie_port *pp = &pci->pp; +- struct device *dev = pci->dev; +- +- if (dw_pcie_link_up(pci)) { +- dev_err(dev, "Link already up\n"); +- return 0; +- } +- +- exynos_pcie_assert_core_reset(ep); +- +- phy_reset(ep->phy); +- +- exynos_pcie_writel(ep->mem_res->elbi_base, 1, +- PCIE_PWR_RESET); +- +- phy_power_on(ep->phy); +- phy_init(ep->phy); +- +- exynos_pcie_deassert_core_reset(ep); +- dw_pcie_setup_rc(pp); +- exynos_pcie_assert_reset(ep); ++ struct exynos_pcie *ep = to_exynos_pcie(pci); + + /* assert LTSSM enable */ + exynos_pcie_writel(ep->mem_res->elbi_base, PCIE_ELBI_LTSSM_ENABLE, +@@ -386,7 +365,20 @@ static int exynos_pcie_host_init(struct pcie_port *pp) + + pp->bridge->ops = &exynos_pci_ops; + +- exynos_pcie_establish_link(ep); ++ exynos_pcie_assert_core_reset(ep); ++ ++ phy_reset(ep->phy); ++ ++ exynos_pcie_writel(ep->mem_res->elbi_base, 1, ++ PCIE_PWR_RESET); ++ ++ phy_power_on(ep->phy); ++ phy_init(ep->phy); ++ ++ exynos_pcie_deassert_core_reset(ep); ++ dw_pcie_setup_rc(pp); ++ exynos_pcie_assert_reset(ep); ++ + exynos_pcie_enable_interrupts(ep); + + return 0; +@@ -430,6 +422,7 @@ static const struct dw_pcie_ops dw_pcie_ops = { + .read_dbi = exynos_pcie_read_dbi, + .write_dbi = exynos_pcie_write_dbi, + .link_up = exynos_pcie_link_up, ++ .start_link = exynos_pcie_start_link, + }; + + static int __init exynos_pcie_probe(struct platform_device *pdev) +diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c +index 104341bfde180..8d1d2d79693d6 100644 +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -750,9 +750,9 @@ static void imx6_pcie_ltssm_enable(struct device *dev) + } + } + +-static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) ++static int imx6_pcie_start_link(struct dw_pcie *pci) + { +- struct dw_pcie *pci = imx6_pcie->pci; ++ struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci); + struct device *dev = pci->dev; + u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + u32 tmp; +@@ -840,7 +840,6 @@ static int imx6_pcie_host_init(struct pcie_port *pp) + imx6_pcie_deassert_core_reset(imx6_pcie); + imx6_setup_phy_mpll(imx6_pcie); + dw_pcie_setup_rc(pp); +- imx6_pcie_establish_link(imx6_pcie); + dw_pcie_msi_init(pp); + + return 0; +@@ -870,7 +869,7 @@ static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, + } + + static const struct dw_pcie_ops dw_pcie_ops = { +- /* No special ops needed, but pcie-designware still expects this struct */ ++ .start_link = imx6_pcie_start_link, + }; + + #ifdef CONFIG_PM_SLEEP +@@ -979,7 +978,7 @@ static int imx6_pcie_resume_noirq(struct device *dev) + imx6_pcie_deassert_core_reset(imx6_pcie); + dw_pcie_setup_rc(pp); + +- ret = imx6_pcie_establish_link(imx6_pcie); ++ ret = imx6_pcie_start_link(imx6_pcie->pci); + if (ret < 0) + dev_info(dev, "pcie link is down after resume.\n"); + +diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c +index fbd38e90bef65..a5db966f6d20b 100644 +--- a/drivers/pci/controller/dwc/pci-keystone.c ++++ b/drivers/pci/controller/dwc/pci-keystone.c +@@ -511,14 +511,8 @@ static void ks_pcie_stop_link(struct dw_pcie *pci) + static int ks_pcie_start_link(struct dw_pcie *pci) + { + struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); +- struct device *dev = pci->dev; + u32 val; + +- if (dw_pcie_link_up(pci)) { +- dev_dbg(dev, "link is already up\n"); +- return 0; +- } +- + /* Initiate Link Training */ + val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); + ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val); +@@ -834,9 +828,6 @@ static int __init ks_pcie_host_init(struct pcie_port *pp) + "Asynchronous external abort"); + #endif + +- ks_pcie_start_link(pci); +- dw_pcie_wait_for_link(pci); +- + return 0; + } + +diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c +index 10d65b3093e4a..41a3351b100b5 100644 +--- a/drivers/pci/controller/dwc/pci-meson.c ++++ b/drivers/pci/controller/dwc/pci-meson.c +@@ -231,7 +231,7 @@ static void meson_pcie_assert_reset(struct meson_pcie *mp) + gpiod_set_value_cansleep(mp->reset_gpio, 0); + } + +-static void meson_pcie_init_dw(struct meson_pcie *mp) ++static void meson_pcie_ltssm_enable(struct meson_pcie *mp) + { + u32 val; + +@@ -289,20 +289,14 @@ static void meson_set_max_rd_req_size(struct meson_pcie *mp, int size) + dw_pcie_writel_dbi(pci, offset + PCI_EXP_DEVCTL, val); + } + +-static int meson_pcie_establish_link(struct meson_pcie *mp) ++static int meson_pcie_start_link(struct dw_pcie *pci) + { +- struct dw_pcie *pci = &mp->pci; +- struct pcie_port *pp = &pci->pp; +- +- meson_pcie_init_dw(mp); +- meson_set_max_payload(mp, MAX_PAYLOAD_SIZE); +- meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE); +- +- dw_pcie_setup_rc(pp); ++ struct meson_pcie *mp = to_meson_pcie(pci); + ++ meson_pcie_ltssm_enable(mp); + meson_pcie_assert_reset(mp); + +- return dw_pcie_wait_for_link(pci); ++ return 0; + } + + static int meson_pcie_rd_own_conf(struct pci_bus *bus, u32 devfn, +@@ -380,14 +374,13 @@ static int meson_pcie_host_init(struct pcie_port *pp) + { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct meson_pcie *mp = to_meson_pcie(pci); +- int ret; + + pp->bridge->ops = &meson_pci_ops; + +- ret = meson_pcie_establish_link(mp); +- if (ret) +- return ret; ++ meson_set_max_payload(mp, MAX_PAYLOAD_SIZE); ++ meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE); + ++ dw_pcie_setup_rc(pp); + dw_pcie_msi_init(pp); + + return 0; +@@ -418,6 +411,7 @@ static int meson_add_pcie_port(struct meson_pcie *mp, + + static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = meson_pcie_link_up, ++ .start_link = meson_pcie_start_link, + }; + + static int meson_pcie_probe(struct platform_device *pdev) +diff --git a/drivers/pci/controller/dwc/pcie-armada8k.c b/drivers/pci/controller/dwc/pcie-armada8k.c +index 13901f359a415..dd2926bbb9017 100644 +--- a/drivers/pci/controller/dwc/pcie-armada8k.c ++++ b/drivers/pci/controller/dwc/pcie-armada8k.c +@@ -154,10 +154,24 @@ static int armada8k_pcie_link_up(struct dw_pcie *pci) + return 0; + } + +-static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie) ++static int armada8k_pcie_start_link(struct dw_pcie *pci) ++{ ++ u32 reg; ++ ++ /* Start LTSSM */ ++ reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG); ++ reg |= PCIE_APP_LTSSM_EN; ++ dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg); ++ ++ return 0; ++} ++ ++static int armada8k_pcie_host_init(struct pcie_port *pp) + { +- struct dw_pcie *pci = pcie->pci; + u32 reg; ++ struct dw_pcie *pci = to_dw_pcie_from_pp(pp); ++ ++ dw_pcie_setup_rc(pp); + + if (!dw_pcie_link_up(pci)) { + /* Disable LTSSM state machine to enable configuration */ +@@ -193,26 +207,6 @@ static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie) + PCIE_INT_C_ASSERT_MASK | PCIE_INT_D_ASSERT_MASK; + dw_pcie_writel_dbi(pci, PCIE_GLOBAL_INT_MASK1_REG, reg); + +- if (!dw_pcie_link_up(pci)) { +- /* Configuration done. Start LTSSM */ +- reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG); +- reg |= PCIE_APP_LTSSM_EN; +- dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg); +- } +- +- /* Wait until the link becomes active again */ +- if (dw_pcie_wait_for_link(pci)) +- dev_err(pci->dev, "Link not up after reconfiguration\n"); +-} +- +-static int armada8k_pcie_host_init(struct pcie_port *pp) +-{ +- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +- struct armada8k_pcie *pcie = to_armada8k_pcie(pci); +- +- dw_pcie_setup_rc(pp); +- armada8k_pcie_establish_link(pcie); +- + return 0; + } + +@@ -269,6 +263,7 @@ static int armada8k_add_pcie_port(struct armada8k_pcie *pcie, + + static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = armada8k_pcie_link_up, ++ .start_link = armada8k_pcie_start_link, + }; + + static int armada8k_pcie_probe(struct platform_device *pdev) +diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c +index a5239a58cee06..8b3da3038ac35 100644 +--- a/drivers/pci/controller/dwc/pcie-artpec6.c ++++ b/drivers/pci/controller/dwc/pcie-artpec6.c +@@ -329,8 +329,6 @@ static int artpec6_pcie_host_init(struct pcie_port *pp) + artpec6_pcie_deassert_core_reset(artpec6_pcie); + artpec6_pcie_wait_for_phy(artpec6_pcie); + dw_pcie_setup_rc(pp); +- artpec6_pcie_establish_link(pci); +- dw_pcie_wait_for_link(pci); + dw_pcie_msi_init(pp); + + return 0; +diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c +index d8ffac3106d9c..b242d7e64c204 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -424,6 +424,15 @@ int dw_pcie_host_init(struct pcie_port *pp) + goto err_free_msi; + } + ++ if (!dw_pcie_link_up(pci) && pci->ops->start_link) { ++ ret = pci->ops->start_link(pci); ++ if (ret) ++ goto err_free_msi; ++ } ++ ++ /* Ignore errors, the link may come up later */ ++ dw_pcie_wait_for_link(pci); ++ + bridge->sysdata = pp; + + ret = pci_host_probe(bridge); +diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c +index 3da38ac6a87a0..adebcaeb1a6c0 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-plat.c ++++ b/drivers/pci/controller/dwc/pcie-designware-plat.c +@@ -35,10 +35,7 @@ static const struct of_device_id dw_plat_pcie_of_match[]; + + static int dw_plat_pcie_host_init(struct pcie_port *pp) + { +- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +- + dw_pcie_setup_rc(pp); +- dw_pcie_wait_for_link(pci); + dw_pcie_msi_init(pp); + + return 0; +diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c +index 777e24902afbf..ece544165059b 100644 +--- a/drivers/pci/controller/dwc/pcie-histb.c ++++ b/drivers/pci/controller/dwc/pcie-histb.c +@@ -169,39 +169,36 @@ static int histb_pcie_link_up(struct dw_pcie *pci) + return 0; + } + +-static int histb_pcie_establish_link(struct pcie_port *pp) ++static int histb_pcie_start_link(struct dw_pcie *pci) + { +- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct histb_pcie *hipcie = to_histb_pcie(pci); + u32 regval; + +- if (dw_pcie_link_up(pci)) { +- dev_info(pci->dev, "Link already up\n"); +- return 0; +- } +- +- /* PCIe RC work mode */ +- regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0); +- regval &= ~PCIE_DEVICE_TYPE_MASK; +- regval |= PCIE_WM_RC; +- histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, regval); +- +- /* setup root complex */ +- dw_pcie_setup_rc(pp); +- + /* assert LTSSM enable */ + regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL7); + regval |= PCIE_APP_LTSSM_ENABLE; + histb_pcie_writel(hipcie, PCIE_SYS_CTRL7, regval); + +- return dw_pcie_wait_for_link(pci); ++ return 0; + } + + static int histb_pcie_host_init(struct pcie_port *pp) + { ++ struct dw_pcie *pci = to_dw_pcie_from_pp(pp); ++ struct histb_pcie *hipcie = to_histb_pcie(pci); ++ u32 regval; ++ + pp->bridge->ops = &histb_pci_ops; + +- histb_pcie_establish_link(pp); ++ /* PCIe RC work mode */ ++ regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0); ++ regval &= ~PCIE_DEVICE_TYPE_MASK; ++ regval |= PCIE_WM_RC; ++ histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, regval); ++ ++ /* setup root complex */ ++ dw_pcie_setup_rc(pp); ++ + dw_pcie_msi_init(pp); + + return 0; +@@ -300,6 +297,7 @@ static const struct dw_pcie_ops dw_pcie_ops = { + .read_dbi = histb_pcie_read_dbi, + .write_dbi = histb_pcie_write_dbi, + .link_up = histb_pcie_link_up, ++ .start_link = histb_pcie_start_link, + }; + + static int histb_pcie_probe(struct platform_device *pdev) +diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c +index ba03dbca7885e..675b4d8392d37 100644 +--- a/drivers/pci/controller/dwc/pcie-kirin.c ++++ b/drivers/pci/controller/dwc/pcie-kirin.c +@@ -390,32 +390,14 @@ static int kirin_pcie_link_up(struct dw_pcie *pci) + return 0; + } + +-static int kirin_pcie_establish_link(struct pcie_port *pp) ++static int kirin_pcie_start_link(struct dw_pcie *pci) + { +- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); +- struct device *dev = kirin_pcie->pci->dev; +- int count = 0; +- +- if (kirin_pcie_link_up(pci)) +- return 0; +- +- dw_pcie_setup_rc(pp); + + /* assert LTSSM enable */ + kirin_apb_ctrl_writel(kirin_pcie, PCIE_LTSSM_ENABLE_BIT, + PCIE_APP_LTSSM_ENABLE); + +- /* check if the link is up or not */ +- while (!kirin_pcie_link_up(pci)) { +- usleep_range(LINK_WAIT_MIN, LINK_WAIT_MAX); +- count++; +- if (count == 1000) { +- dev_err(dev, "Link Fail\n"); +- return -EINVAL; +- } +- } +- + return 0; + } + +@@ -423,7 +405,7 @@ static int kirin_pcie_host_init(struct pcie_port *pp) + { + pp->bridge->ops = &kirin_pci_ops; + +- kirin_pcie_establish_link(pp); ++ dw_pcie_setup_rc(pp); + dw_pcie_msi_init(pp); + + return 0; +@@ -433,6 +415,7 @@ static const struct dw_pcie_ops kirin_dw_pcie_ops = { + .read_dbi = kirin_pcie_read_dbi, + .write_dbi = kirin_pcie_write_dbi, + .link_up = kirin_pcie_link_up, ++ .start_link = kirin_pcie_start_link, + }; + + static const struct dw_pcie_host_ops kirin_pcie_host_ops = { +diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c +index 4f230f01a645e..03251e34137f3 100644 +--- a/drivers/pci/controller/dwc/pcie-qcom.c ++++ b/drivers/pci/controller/dwc/pcie-qcom.c +@@ -207,18 +207,15 @@ static void qcom_ep_reset_deassert(struct qcom_pcie *pcie) + usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); + } + +-static int qcom_pcie_establish_link(struct qcom_pcie *pcie) ++static int qcom_pcie_start_link(struct dw_pcie *pci) + { +- struct dw_pcie *pci = pcie->pci; +- +- if (dw_pcie_link_up(pci)) +- return 0; ++ struct qcom_pcie *pcie = to_qcom_pcie(pci); + + /* Enable Link Training state machine */ + if (pcie->ops->ltssm_enable) + pcie->ops->ltssm_enable(pcie); + +- return dw_pcie_wait_for_link(pci); ++ return 0; + } + + static void qcom_pcie_2_1_0_ltssm_enable(struct qcom_pcie *pcie) +@@ -1280,15 +1277,8 @@ static int qcom_pcie_host_init(struct pcie_port *pp) + + qcom_ep_reset_deassert(pcie); + +- ret = qcom_pcie_establish_link(pcie); +- if (ret) +- goto err; +- + return 0; +-err: +- qcom_ep_reset_assert(pcie); +- if (pcie->ops->post_deinit) +- pcie->ops->post_deinit(pcie); ++ + err_disable_phy: + phy_power_off(pcie->phy); + err_deinit: +@@ -1355,6 +1345,7 @@ static const struct qcom_pcie_ops ops_2_7_0 = { + + static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = qcom_pcie_link_up, ++ .start_link = qcom_pcie_start_link, + }; + + static int qcom_pcie_probe(struct platform_device *pdev) +diff --git a/drivers/pci/controller/dwc/pcie-spear13xx.c b/drivers/pci/controller/dwc/pcie-spear13xx.c +index 800c34a60a334..ebbaa06fc8ab5 100644 +--- a/drivers/pci/controller/dwc/pcie-spear13xx.c ++++ b/drivers/pci/controller/dwc/pcie-spear13xx.c +@@ -66,32 +66,10 @@ struct pcie_app_reg { + + #define to_spear13xx_pcie(x) dev_get_drvdata((x)->dev) + +-static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie) ++static int spear13xx_pcie_start_link(struct dw_pcie *pci) + { +- struct dw_pcie *pci = spear13xx_pcie->pci; +- struct pcie_port *pp = &pci->pp; ++ struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci); + struct pcie_app_reg *app_reg = spear13xx_pcie->app_base; +- u32 val; +- u32 exp_cap_off = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); +- +- if (dw_pcie_link_up(pci)) { +- dev_err(pci->dev, "link already up\n"); +- return 0; +- } +- +- dw_pcie_setup_rc(pp); +- +- /* +- * this controller support only 128 bytes read size, however its +- * default value in capability register is 512 bytes. So force +- * it to 128 here. +- */ +- val = dw_pcie_readw_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL); +- val &= ~PCI_EXP_DEVCTL_READRQ; +- dw_pcie_writew_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL, val); +- +- dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, 0x104A); +- dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, 0xCD80); + + /* enable ltssm */ + writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID) +@@ -99,7 +77,7 @@ static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie) + | ((u32)1 << REG_TRANSLATION_ENABLE), + &app_reg->app_ctrl_0); + +- return dw_pcie_wait_for_link(pci); ++ return 0; + } + + static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg) +@@ -151,10 +129,25 @@ static int spear13xx_pcie_host_init(struct pcie_port *pp) + { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci); ++ u32 exp_cap_off = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); ++ u32 val; + + spear13xx_pcie->app_base = pci->dbi_base + 0x2000; + +- spear13xx_pcie_establish_link(spear13xx_pcie); ++ dw_pcie_setup_rc(pp); ++ ++ /* ++ * this controller support only 128 bytes read size, however its ++ * default value in capability register is 512 bytes. So force ++ * it to 128 here. ++ */ ++ val = dw_pcie_readw_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL); ++ val &= ~PCI_EXP_DEVCTL_READRQ; ++ dw_pcie_writew_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL, val); ++ ++ dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, 0x104A); ++ dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, 0xCD80); ++ + spear13xx_pcie_enable_interrupts(spear13xx_pcie); + + return 0; +@@ -198,6 +191,7 @@ static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie, + + static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = spear13xx_pcie_link_up, ++ .start_link = spear13xx_pcie_start_link, + }; + + static int spear13xx_pcie_probe(struct platform_device *pdev) +diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c +index 8e67495be90f9..782aa3f382829 100644 +--- a/drivers/pci/controller/dwc/pcie-tegra194.c ++++ b/drivers/pci/controller/dwc/pcie-tegra194.c +@@ -1555,7 +1555,6 @@ static int tegra_pcie_deinit_controller(struct tegra_pcie_dw *pcie) + + static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie) + { +- struct pcie_port *pp = &pcie->pci.pp; + struct device *dev = pcie->dev; + char *name; + int ret; +diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c +index 4620561da7a3e..bd4bf2db9480e 100644 +--- a/drivers/pci/controller/dwc/pcie-uniphier.c ++++ b/drivers/pci/controller/dwc/pcie-uniphier.c +@@ -146,16 +146,13 @@ static int uniphier_pcie_link_up(struct dw_pcie *pci) + return (val & mask) == mask; + } + +-static int uniphier_pcie_establish_link(struct dw_pcie *pci) ++static int uniphier_pcie_start_link(struct dw_pcie *pci) + { + struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); + +- if (dw_pcie_link_up(pci)) +- return 0; +- + uniphier_pcie_ltssm_enable(priv, true); + +- return dw_pcie_wait_for_link(pci); ++ return 0; + } + + static void uniphier_pcie_stop_link(struct dw_pcie *pci) +@@ -312,10 +309,6 @@ static int uniphier_pcie_host_init(struct pcie_port *pp) + uniphier_pcie_irq_enable(priv); + + dw_pcie_setup_rc(pp); +- ret = uniphier_pcie_establish_link(pci); +- if (ret) +- return ret; +- + dw_pcie_msi_init(pp); + + return 0; +@@ -379,7 +372,7 @@ static int uniphier_pcie_host_enable(struct uniphier_pcie_priv *priv) + } + + static const struct dw_pcie_ops dw_pcie_ops = { +- .start_link = uniphier_pcie_establish_link, ++ .start_link = uniphier_pcie_start_link, + .stop_link = uniphier_pcie_stop_link, + .link_up = uniphier_pcie_link_up, + }; +-- +2.42.0 + diff --git a/queue-5.10/pci-dwc-move-msi-interrupt-setup-into-dwc-common-cod.patch b/queue-5.10/pci-dwc-move-msi-interrupt-setup-into-dwc-common-cod.patch new file mode 100644 index 00000000000..d1e0b615bcb --- /dev/null +++ b/queue-5.10/pci-dwc-move-msi-interrupt-setup-into-dwc-common-cod.patch @@ -0,0 +1,323 @@ +From 7dfbd819eb0f2302460066fe9ce49e4fe8c6ce05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Nov 2020 15:11:51 -0600 +Subject: PCI: dwc: Move MSI interrupt setup into DWC common code + +From: Rob Herring + +[ Upstream commit 5bcb1757e637a4f6d130f1f5106ce030516316b8 ] + +Platforms using the built-in DWC MSI controller all have a dedicated +interrupt with "msi" name or at index 0, so let's move setting up the +interrupt to the common DWC code. + +spear13xx and dra7xx are the 2 oddballs with muxed interrupts, so +we need to prevent configuring the MSI interrupt by setting msi_irq +to negative. + +Link: https://lore.kernel.org/r/20201105211159.1814485-9-robh@kernel.org +Tested-by: Marek Szyprowski +Signed-off-by: Rob Herring +Signed-off-by: Lorenzo Pieralisi +Acked-by: Jingoo Han +Cc: Lorenzo Pieralisi +Cc: Bjorn Helgaas +Cc: Kukjin Kim +Cc: Krzysztof Kozlowski +Cc: Richard Zhu +Cc: Lucas Stach +Cc: Shawn Guo +Cc: Sascha Hauer +Cc: Pengutronix Kernel Team +Cc: Fabio Estevam +Cc: NXP Linux Team +Cc: Yue Wang +Cc: Kevin Hilman +Cc: Neil Armstrong +Cc: Jerome Brunet +Cc: Martin Blumenstingl +Cc: Jesper Nilsson +Cc: Gustavo Pimentel +Cc: Xiaowei Song +Cc: Binghui Wang +Cc: Stanimir Varbanov +Cc: Andy Gross +Cc: Bjorn Andersson +Cc: Pratyush Anand +Cc: Thierry Reding +Cc: Jonathan Hunter +Cc: Kunihiko Hayashi +Cc: Masahiro Yamada +Cc: linux-samsung-soc@vger.kernel.org +Cc: linux-amlogic@lists.infradead.org +Cc: linux-arm-kernel@axis.com +Cc: linux-arm-msm@vger.kernel.org +Cc: linux-tegra@vger.kernel.org +Stable-dep-of: 83a939f0fdc2 ("PCI: exynos: Don't discard .remove() callback") +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pci-dra7xx.c | 3 +++ + drivers/pci/controller/dwc/pci-exynos.c | 6 ----- + drivers/pci/controller/dwc/pci-imx6.c | 6 ----- + drivers/pci/controller/dwc/pci-meson.c | 6 ----- + drivers/pci/controller/dwc/pcie-artpec6.c | 6 ----- + .../pci/controller/dwc/pcie-designware-host.c | 11 +++++++++- + .../pci/controller/dwc/pcie-designware-plat.c | 6 ----- + drivers/pci/controller/dwc/pcie-histb.c | 6 ----- + drivers/pci/controller/dwc/pcie-kirin.c | 22 ------------------- + drivers/pci/controller/dwc/pcie-qcom.c | 8 ------- + drivers/pci/controller/dwc/pcie-spear13xx.c | 1 + + drivers/pci/controller/dwc/pcie-tegra194.c | 8 ------- + drivers/pci/controller/dwc/pcie-uniphier.c | 6 ----- + 13 files changed, 14 insertions(+), 81 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c +index 4d0c35a4aa598..6b75c68dddb56 100644 +--- a/drivers/pci/controller/dwc/pci-dra7xx.c ++++ b/drivers/pci/controller/dwc/pci-dra7xx.c +@@ -489,6 +489,9 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, + if (pp->irq < 0) + return pp->irq; + ++ /* MSI IRQ is muxed */ ++ pp->msi_irq = -ENODEV; ++ + ret = dra7xx_pcie_init_irq_domain(pp); + if (ret < 0) + return ret; +diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c +index 242683cde04a5..7734394953e57 100644 +--- a/drivers/pci/controller/dwc/pci-exynos.c ++++ b/drivers/pci/controller/dwc/pci-exynos.c +@@ -415,12 +415,6 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *ep, + return ret; + } + +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- pp->msi_irq = platform_get_irq(pdev, 0); +- if (pp->msi_irq < 0) +- return pp->msi_irq; +- } +- + pp->ops = &exynos_pcie_host_ops; + + ret = dw_pcie_host_init(pp); +diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c +index 8117f2dad86c4..104341bfde180 100644 +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -858,12 +858,6 @@ static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, + struct device *dev = &pdev->dev; + int ret; + +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- pp->msi_irq = platform_get_irq_byname(pdev, "msi"); +- if (pp->msi_irq < 0) +- return pp->msi_irq; +- } +- + pp->ops = &imx6_pcie_host_ops; + + ret = dw_pcie_host_init(pp); +diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c +index 1913dc2c8fa08..10d65b3093e4a 100644 +--- a/drivers/pci/controller/dwc/pci-meson.c ++++ b/drivers/pci/controller/dwc/pci-meson.c +@@ -405,12 +405,6 @@ static int meson_add_pcie_port(struct meson_pcie *mp, + struct device *dev = &pdev->dev; + int ret; + +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- pp->msi_irq = platform_get_irq(pdev, 0); +- if (pp->msi_irq < 0) +- return pp->msi_irq; +- } +- + pp->ops = &meson_pcie_host_ops; + + ret = dw_pcie_host_init(pp); +diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c +index 52ad7909cd0c0..a5239a58cee06 100644 +--- a/drivers/pci/controller/dwc/pcie-artpec6.c ++++ b/drivers/pci/controller/dwc/pcie-artpec6.c +@@ -348,12 +348,6 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie, + struct device *dev = pci->dev; + int ret; + +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- pp->msi_irq = platform_get_irq_byname(pdev, "msi"); +- if (pp->msi_irq < 0) +- return pp->msi_irq; +- } +- + pp->ops = &artpec6_pcie_host_ops; + + ret = dw_pcie_host_init(pp); +diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c +index 32d3af7c44917..401890f5c8ca8 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -373,13 +373,22 @@ int dw_pcie_host_init(struct pcie_port *pp) + } + + if (!pp->ops->msi_host_init) { ++ if (!pp->msi_irq) { ++ pp->msi_irq = platform_get_irq_byname_optional(pdev, "msi"); ++ if (pp->msi_irq < 0) { ++ pp->msi_irq = platform_get_irq(pdev, 0); ++ if (pp->msi_irq < 0) ++ return pp->msi_irq; ++ } ++ } ++ + pp->msi_irq_chip = &dw_pci_msi_bottom_irq_chip; + + ret = dw_pcie_allocate_domains(pp); + if (ret) + return ret; + +- if (pp->msi_irq) ++ if (pp->msi_irq > 0) + irq_set_chained_handler_and_data(pp->msi_irq, + dw_chained_msi_isr, + pp); +diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c +index 13fede1d41572..3da38ac6a87a0 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-plat.c ++++ b/drivers/pci/controller/dwc/pcie-designware-plat.c +@@ -116,12 +116,6 @@ static int dw_plat_add_pcie_port(struct dw_plat_pcie *dw_plat_pcie, + if (pp->irq < 0) + return pp->irq; + +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- pp->msi_irq = platform_get_irq(pdev, 0); +- if (pp->msi_irq < 0) +- return pp->msi_irq; +- } +- + pp->num_vectors = MAX_MSI_IRQS; + pp->ops = &dw_plat_pcie_host_ops; + +diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c +index afc1abbe49aa9..777e24902afbf 100644 +--- a/drivers/pci/controller/dwc/pcie-histb.c ++++ b/drivers/pci/controller/dwc/pcie-histb.c +@@ -400,12 +400,6 @@ static int histb_pcie_probe(struct platform_device *pdev) + return PTR_ERR(hipcie->bus_reset); + } + +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- pp->msi_irq = platform_get_irq_byname(pdev, "msi"); +- if (pp->msi_irq < 0) +- return pp->msi_irq; +- } +- + hipcie->phy = devm_phy_get(dev, "phy"); + if (IS_ERR(hipcie->phy)) { + dev_info(dev, "no pcie-phy found\n"); +diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c +index 3042a23cf09a4..ba03dbca7885e 100644 +--- a/drivers/pci/controller/dwc/pcie-kirin.c ++++ b/drivers/pci/controller/dwc/pcie-kirin.c +@@ -439,31 +439,9 @@ static const struct dw_pcie_host_ops kirin_pcie_host_ops = { + .host_init = kirin_pcie_host_init, + }; + +-static int kirin_pcie_add_msi(struct dw_pcie *pci, +- struct platform_device *pdev) +-{ +- int irq; +- +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) +- return irq; +- +- pci->pp.msi_irq = irq; +- } +- +- return 0; +-} +- + static int kirin_add_pcie_port(struct dw_pcie *pci, + struct platform_device *pdev) + { +- int ret; +- +- ret = kirin_pcie_add_msi(pci, pdev); +- if (ret) +- return ret; +- + pci->pp.ops = &kirin_pcie_host_ops; + + return dw_pcie_host_init(&pci->pp); +diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c +index 150dd6fe7ba39..4f230f01a645e 100644 +--- a/drivers/pci/controller/dwc/pcie-qcom.c ++++ b/drivers/pci/controller/dwc/pcie-qcom.c +@@ -1416,14 +1416,6 @@ static int qcom_pcie_probe(struct platform_device *pdev) + + pp->ops = &qcom_pcie_dw_ops; + +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- pp->msi_irq = platform_get_irq_byname(pdev, "msi"); +- if (pp->msi_irq < 0) { +- ret = pp->msi_irq; +- goto err_pm_runtime_put; +- } +- } +- + ret = phy_init(pcie->phy); + if (ret) + goto err_pm_runtime_put; +diff --git a/drivers/pci/controller/dwc/pcie-spear13xx.c b/drivers/pci/controller/dwc/pcie-spear13xx.c +index 1ed7e3501ff1c..800c34a60a334 100644 +--- a/drivers/pci/controller/dwc/pcie-spear13xx.c ++++ b/drivers/pci/controller/dwc/pcie-spear13xx.c +@@ -185,6 +185,7 @@ static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie, + } + + pp->ops = &spear13xx_pcie_host_ops; ++ pp->msi_irq = -ENODEV; + + ret = dw_pcie_host_init(pp); + if (ret) { +diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c +index a93b5dca110ec..8e67495be90f9 100644 +--- a/drivers/pci/controller/dwc/pcie-tegra194.c ++++ b/drivers/pci/controller/dwc/pcie-tegra194.c +@@ -1560,14 +1560,6 @@ static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie) + char *name; + int ret; + +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- pp->msi_irq = of_irq_get_byname(dev->of_node, "msi"); +- if (!pp->msi_irq) { +- dev_err(dev, "Failed to get MSI interrupt\n"); +- return -ENODEV; +- } +- } +- + pm_runtime_enable(dev); + + ret = pm_runtime_get_sync(dev); +diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c +index 85bf170e93541..4620561da7a3e 100644 +--- a/drivers/pci/controller/dwc/pcie-uniphier.c ++++ b/drivers/pci/controller/dwc/pcie-uniphier.c +@@ -335,12 +335,6 @@ static int uniphier_add_pcie_port(struct uniphier_pcie_priv *priv, + + pp->ops = &uniphier_pcie_host_ops; + +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- pp->msi_irq = platform_get_irq_byname(pdev, "msi"); +- if (pp->msi_irq < 0) +- return pp->msi_irq; +- } +- + ret = dw_pcie_host_init(pp); + if (ret) { + dev_err(dev, "Failed to initialize host (%d)\n", ret); +-- +2.42.0 + diff --git a/queue-5.10/pci-dwc-rework-msi-initialization.patch b/queue-5.10/pci-dwc-rework-msi-initialization.patch new file mode 100644 index 00000000000..670763f78d9 --- /dev/null +++ b/queue-5.10/pci-dwc-rework-msi-initialization.patch @@ -0,0 +1,218 @@ +From f014ef788425a1aeb38511ab7536facbdd3d9342 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Nov 2020 15:11:52 -0600 +Subject: PCI: dwc: Rework MSI initialization + +From: Rob Herring + +[ Upstream commit f78f02638af5941eb45a402fa52c0edf4ac0f507 ] + +There are 3 possible MSI implementations for the DWC host. The first is +using the built-in DWC MSI controller. The 2nd is a custom MSI +controller as part of the PCI host (keystone only). The 3rd is an +external MSI controller (typically GICv3 ITS). Currently, the last 2 +are distinguished with a .msi_host_init() hook with the 3rd option using +an empty function. However we can detect the 3rd case with the presence +of 'msi-parent' or 'msi-map' properties, so let's do that instead and +remove the empty functions. + +Link: https://lore.kernel.org/r/20201105211159.1814485-10-robh@kernel.org +Tested-by: Marek Szyprowski +Signed-off-by: Rob Herring +Signed-off-by: Lorenzo Pieralisi +Acked-by: Jingoo Han +Cc: Murali Karicheri +Cc: Lorenzo Pieralisi +Cc: Bjorn Helgaas +Cc: Minghuan Lian +Cc: Mingkai Hu +Cc: Roy Zang +Cc: Gustavo Pimentel +Cc: linuxppc-dev@lists.ozlabs.org +Stable-dep-of: 83a939f0fdc2 ("PCI: exynos: Don't discard .remove() callback") +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pci-keystone.c | 9 ------- + drivers/pci/controller/dwc/pci-layerscape.c | 25 ------------------- + .../pci/controller/dwc/pcie-designware-host.c | 20 +++++++++------ + drivers/pci/controller/dwc/pcie-designware.h | 1 + + drivers/pci/controller/dwc/pcie-intel-gw.c | 9 ------- + 5 files changed, 13 insertions(+), 51 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c +index 5177f6d1ca592..fbd38e90bef65 100644 +--- a/drivers/pci/controller/dwc/pci-keystone.c ++++ b/drivers/pci/controller/dwc/pci-keystone.c +@@ -272,14 +272,6 @@ static void ks_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, + ks_pcie_app_writel(ks_pcie, IRQ_EOI, offset); + } + +-/* +- * Dummy function so that DW core doesn't configure MSI +- */ +-static int ks_pcie_am654_msi_host_init(struct pcie_port *pp) +-{ +- return 0; +-} +- + static void ks_pcie_enable_error_irq(struct keystone_pcie *ks_pcie) + { + ks_pcie_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL); +@@ -855,7 +847,6 @@ static const struct dw_pcie_host_ops ks_pcie_host_ops = { + + static const struct dw_pcie_host_ops ks_pcie_am654_host_ops = { + .host_init = ks_pcie_host_init, +- .msi_host_init = ks_pcie_am654_msi_host_init, + }; + + static irqreturn_t ks_pcie_err_irq_handler(int irq, void *priv) +diff --git a/drivers/pci/controller/dwc/pci-layerscape.c b/drivers/pci/controller/dwc/pci-layerscape.c +index f24f79a70d9a8..4d280b940f1fe 100644 +--- a/drivers/pci/controller/dwc/pci-layerscape.c ++++ b/drivers/pci/controller/dwc/pci-layerscape.c +@@ -182,37 +182,12 @@ static int ls1021_pcie_host_init(struct pcie_port *pp) + return ls_pcie_host_init(pp); + } + +-static int ls_pcie_msi_host_init(struct pcie_port *pp) +-{ +- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +- struct device *dev = pci->dev; +- struct device_node *np = dev->of_node; +- struct device_node *msi_node; +- +- /* +- * The MSI domain is set by the generic of_msi_configure(). This +- * .msi_host_init() function keeps us from doing the default MSI +- * domain setup in dw_pcie_host_init() and also enforces the +- * requirement that "msi-parent" exists. +- */ +- msi_node = of_parse_phandle(np, "msi-parent", 0); +- if (!msi_node) { +- dev_err(dev, "failed to find msi-parent\n"); +- return -EINVAL; +- } +- +- of_node_put(msi_node); +- return 0; +-} +- + static const struct dw_pcie_host_ops ls1021_pcie_host_ops = { + .host_init = ls1021_pcie_host_init, +- .msi_host_init = ls_pcie_msi_host_init, + }; + + static const struct dw_pcie_host_ops ls_pcie_host_ops = { + .host_init = ls_pcie_host_init, +- .msi_host_init = ls_pcie_msi_host_init, + }; + + static const struct dw_pcie_ops dw_ls1021_pcie_ops = { +diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c +index 401890f5c8ca8..d8ffac3106d9c 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -365,6 +365,10 @@ int dw_pcie_host_init(struct pcie_port *pp) + pci->link_gen = of_pci_get_max_link_speed(np); + + if (pci_msi_enabled()) { ++ pp->has_msi_ctrl = !(pp->ops->msi_host_init || ++ of_property_read_bool(np, "msi-parent") || ++ of_property_read_bool(np, "msi-map")); ++ + if (!pp->num_vectors) { + pp->num_vectors = MSI_DEF_NUM_VECTORS; + } else if (pp->num_vectors > MAX_MSI_IRQS) { +@@ -372,7 +376,11 @@ int dw_pcie_host_init(struct pcie_port *pp) + return -EINVAL; + } + +- if (!pp->ops->msi_host_init) { ++ if (pp->ops->msi_host_init) { ++ ret = pp->ops->msi_host_init(pp); ++ if (ret < 0) ++ return ret; ++ } else if (pp->has_msi_ctrl) { + if (!pp->msi_irq) { + pp->msi_irq = platform_get_irq_byname_optional(pdev, "msi"); + if (pp->msi_irq < 0) { +@@ -403,10 +411,6 @@ int dw_pcie_host_init(struct pcie_port *pp) + pp->msi_data = 0; + goto err_free_msi; + } +- } else { +- ret = pp->ops->msi_host_init(pp); +- if (ret < 0) +- return ret; + } + } + +@@ -427,7 +431,7 @@ int dw_pcie_host_init(struct pcie_port *pp) + return 0; + + err_free_msi: +- if (pci_msi_enabled() && !pp->ops->msi_host_init) ++ if (pp->has_msi_ctrl) + dw_pcie_free_msi(pp); + return ret; + } +@@ -437,7 +441,7 @@ void dw_pcie_host_deinit(struct pcie_port *pp) + { + pci_stop_root_bus(pp->bridge->bus); + pci_remove_root_bus(pp->bridge->bus); +- if (pci_msi_enabled() && !pp->ops->msi_host_init) ++ if (pp->has_msi_ctrl) + dw_pcie_free_msi(pp); + } + EXPORT_SYMBOL_GPL(dw_pcie_host_deinit); +@@ -548,7 +552,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp) + + dw_pcie_setup(pci); + +- if (pci_msi_enabled() && !pp->ops->msi_host_init) { ++ if (pp->has_msi_ctrl) { + num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; + + /* Initialize IRQ Status array */ +diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h +index 82c0339c283f1..f33dc89a93650 100644 +--- a/drivers/pci/controller/dwc/pcie-designware.h ++++ b/drivers/pci/controller/dwc/pcie-designware.h +@@ -178,6 +178,7 @@ struct dw_pcie_host_ops { + }; + + struct pcie_port { ++ bool has_msi_ctrl:1; + u64 cfg0_base; + void __iomem *va_cfg0_base; + u32 cfg0_size; +diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c +index 429171c35945d..5ce25944cc315 100644 +--- a/drivers/pci/controller/dwc/pcie-intel-gw.c ++++ b/drivers/pci/controller/dwc/pcie-intel-gw.c +@@ -399,14 +399,6 @@ static int intel_pcie_rc_init(struct pcie_port *pp) + return intel_pcie_host_setup(lpp); + } + +-/* +- * Dummy function so that DW core doesn't configure MSI +- */ +-static int intel_pcie_msi_init(struct pcie_port *pp) +-{ +- return 0; +-} +- + static u64 intel_pcie_cpu_addr(struct dw_pcie *pcie, u64 cpu_addr) + { + return cpu_addr + BUS_IATU_OFFSET; +@@ -418,7 +410,6 @@ static const struct dw_pcie_ops intel_pcie_ops = { + + static const struct dw_pcie_host_ops intel_pcie_dw_ops = { + .host_init = intel_pcie_rc_init, +- .msi_host_init = intel_pcie_msi_init, + }; + + static const struct intel_pcie_soc pcie_data = { +-- +2.42.0 + diff --git a/queue-5.10/pci-exynos-don-t-discard-.remove-callback.patch b/queue-5.10/pci-exynos-don-t-discard-.remove-callback.patch new file mode 100644 index 00000000000..8bd16c17b6e --- /dev/null +++ b/queue-5.10/pci-exynos-don-t-discard-.remove-callback.patch @@ -0,0 +1,60 @@ +From cfeb180401c710b50c82ea03f6a76493624afc36 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Oct 2023 19:02:51 +0200 +Subject: PCI: exynos: Don't discard .remove() callback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 83a939f0fdc208ff3639dd3d42ac9b3c35607fd2 ] + +With CONFIG_PCI_EXYNOS=y and exynos_pcie_remove() marked with __exit, the +function is discarded from the driver. In this case a bound device can +still get unbound, e.g via sysfs. Then no cleanup code is run resulting in +resource leaks or worse. + +The right thing to do is do always have the remove callback available. +This fixes the following warning by modpost: + + WARNING: modpost: drivers/pci/controller/dwc/pci-exynos: section mismatch in reference: exynos_pcie_driver+0x8 (section: .data) -> exynos_pcie_remove (section: .exit.text) + +(with ARCH=x86_64 W=1 allmodconfig). + +Fixes: 340cba6092c2 ("pci: Add PCIe driver for Samsung Exynos") +Link: https://lore.kernel.org/r/20231001170254.2506508-2-u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Signed-off-by: Bjorn Helgaas +Reviewed-by: Alim Akhtar +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pci-exynos.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c +index c24dab383654b..2696a4544f102 100644 +--- a/drivers/pci/controller/dwc/pci-exynos.c ++++ b/drivers/pci/controller/dwc/pci-exynos.c +@@ -377,7 +377,7 @@ static int exynos_pcie_probe(struct platform_device *pdev) + return ret; + } + +-static int __exit exynos_pcie_remove(struct platform_device *pdev) ++static int exynos_pcie_remove(struct platform_device *pdev) + { + struct exynos_pcie *ep = platform_get_drvdata(pdev); + +@@ -433,7 +433,7 @@ static const struct of_device_id exynos_pcie_of_match[] = { + + static struct platform_driver exynos_pcie_driver = { + .probe = exynos_pcie_probe, +- .remove = __exit_p(exynos_pcie_remove), ++ .remove = exynos_pcie_remove, + .driver = { + .name = "exynos-pcie", + .of_match_table = exynos_pcie_of_match, +-- +2.42.0 + diff --git a/queue-5.10/serial-meson-remove-redundant-initialization-of-vari.patch b/queue-5.10/serial-meson-remove-redundant-initialization-of-vari.patch new file mode 100644 index 00000000000..843321a73e9 --- /dev/null +++ b/queue-5.10/serial-meson-remove-redundant-initialization-of-vari.patch @@ -0,0 +1,48 @@ +From cf31acecb91ddeab131652ce81975d8a28f641a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Apr 2021 11:11:06 +0100 +Subject: serial: meson: remove redundant initialization of variable id + +From: Colin Ian King + +[ Upstream commit 021212f5335229ed12e3d31f9b7d30bd3bb66f7d ] + +The variable id being initialized with a value that is never read +and it is being updated later with a new value. The initialization is +redundant and can be removed. Since id is just being used in a for-loop +inside a local scope, move the declaration of id to that scope. + +Reviewed-by: Kevin Hilman +Reviewed-by: Martin Blumenstingl +Signed-off-by: Colin Ian King +Addresses-Coverity: ("Unused value") +Link: https://lore.kernel.org/r/20210426101106.9122-1-colin.king@canonical.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 2a1d728f20ed ("tty: serial: meson: fix hard LOCKUP on crtscts mode") +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/meson_uart.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c +index 91b7359b79a2f..d06653493f0ef 100644 +--- a/drivers/tty/serial/meson_uart.c ++++ b/drivers/tty/serial/meson_uart.c +@@ -729,12 +729,13 @@ static int meson_uart_probe(struct platform_device *pdev) + struct resource *res_mem, *res_irq; + struct uart_port *port; + int ret = 0; +- int id = -1; + + if (pdev->dev.of_node) + pdev->id = of_alias_get_id(pdev->dev.of_node, "serial"); + + if (pdev->id < 0) { ++ int id; ++ + for (id = AML_UART_PORT_OFFSET; id < AML_UART_PORT_NUM; id++) { + if (!meson_ports[id]) { + pdev->id = id; +-- +2.42.0 + diff --git a/queue-5.10/serial-meson-use-platform_get_irq-to-get-the-interru.patch b/queue-5.10/serial-meson-use-platform_get_irq-to-get-the-interru.patch new file mode 100644 index 00000000000..ffcda317647 --- /dev/null +++ b/queue-5.10/serial-meson-use-platform_get_irq-to-get-the-interru.patch @@ -0,0 +1,69 @@ +From c81458f574f90ebc1aaaff23f62ce684bd1b7059 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Dec 2021 14:29:10 +0000 +Subject: serial: meson: Use platform_get_irq() to get the interrupt + +From: Lad Prabhakar + +[ Upstream commit 5b68061983471470d4109bac776145245f06bc09 ] + +platform_get_resource(pdev, IORESOURCE_IRQ, ..) relies on static +allocation of IRQ resources in DT core code, this causes an issue +when using hierarchical interrupt domains using "interrupts" property +in the node as this bypasses the hierarchical setup and messes up the +irq chaining. + +In preparation for removal of static setup of IRQ resource from DT core +code use platform_get_irq(). + +Signed-off-by: Lad Prabhakar +Link: https://lore.kernel.org/r/20211224142917.6966-5-prabhakar.mahadev-lad.rj@bp.renesas.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 2a1d728f20ed ("tty: serial: meson: fix hard LOCKUP on crtscts mode") +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/meson_uart.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c +index 78bda91a6bf15..bdc394afec5be 100644 +--- a/drivers/tty/serial/meson_uart.c ++++ b/drivers/tty/serial/meson_uart.c +@@ -726,10 +726,11 @@ static int meson_uart_probe_clocks(struct platform_device *pdev, + + static int meson_uart_probe(struct platform_device *pdev) + { +- struct resource *res_mem, *res_irq; ++ struct resource *res_mem; + struct uart_port *port; + u32 fifosize = 64; /* Default is 64, 128 for EE UART_0 */ + int ret = 0; ++ int irq; + + if (pdev->dev.of_node) + pdev->id = of_alias_get_id(pdev->dev.of_node, "serial"); +@@ -752,9 +753,9 @@ static int meson_uart_probe(struct platform_device *pdev) + if (!res_mem) + return -ENODEV; + +- res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +- if (!res_irq) +- return -ENODEV; ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; + + of_property_read_u32(pdev->dev.of_node, "fifo-size", &fifosize); + +@@ -779,7 +780,7 @@ static int meson_uart_probe(struct platform_device *pdev) + port->iotype = UPIO_MEM; + port->mapbase = res_mem->start; + port->mapsize = resource_size(res_mem); +- port->irq = res_irq->start; ++ port->irq = irq; + port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MESON_CONSOLE); + port->dev = &pdev->dev; +-- +2.42.0 + diff --git a/queue-5.10/series b/queue-5.10/series index a6a77c0a9e7..c74b63c7344 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -138,3 +138,25 @@ mm-cma-use-nth_page-in-place-of-direct-struct-page-manipulation.patch mm-memory_hotplug-use-pfn-math-in-place-of-direct-struct-page-manipulation.patch mtd-cfi_cmdset_0001-byte-swap-otp-info.patch i3c-master-cdns-fix-reading-status-register.patch +serial-meson-remove-redundant-initialization-of-vari.patch +tty-serial-meson-retrieve-port-fifo-size-from-dt.patch +serial-meson-use-platform_get_irq-to-get-the-interru.patch +tty-serial-meson-fix-hard-lockup-on-crtscts-mode.patch +cpufreq-stats-fix-buffer-overflow-detection-in-trans.patch +bluetooth-btusb-add-realtek-rtl8852be-support-id-0x0.patch +bluetooth-add-device-0bda-887b-to-device-tables.patch +bluetooth-add-device-13d3-3571-to-device-tables.patch +bluetooth-btusb-add-rtw8852be-device-13d3-3570-to-de.patch +bluetooth-btusb-add-0bda-b85b-for-fn-link-rtl8852be.patch +pci-dwc-move-dbi-dbi2-and-addr_space-resource-setup-.patch +pci-dwc-dra7xx-use-the-common-msi-irq_chip.patch +pci-dwc-drop-the-.set_num_vectors-host-op.patch +pci-dwc-move-msi-interrupt-setup-into-dwc-common-cod.patch +pci-dwc-rework-msi-initialization.patch +pci-dwc-move-link-handling-into-common-code.patch +pci-dwc-move-dw_pcie_msi_init-into-core.patch +pci-dwc-move-dw_pcie_setup_rc-to-dwc-common-code.patch +pci-dwc-exynos-rework-the-driver-to-support-exynos54.patch +pci-exynos-don-t-discard-.remove-callback.patch +arm64-dts-qcom-ipq6018-switch-tcsr-mutex-to-mmio.patch +arm64-dts-qcom-ipq6018-fix-tcsr_mutex-register-size.patch diff --git a/queue-5.10/tty-serial-meson-fix-hard-lockup-on-crtscts-mode.patch b/queue-5.10/tty-serial-meson-fix-hard-lockup-on-crtscts-mode.patch new file mode 100644 index 00000000000..74402d3b89c --- /dev/null +++ b/queue-5.10/tty-serial-meson-fix-hard-lockup-on-crtscts-mode.patch @@ -0,0 +1,101 @@ +From 2bcb06935a5183deb0a4f37b09f622964de14800 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Oct 2023 11:39:26 +0000 +Subject: tty: serial: meson: fix hard LOCKUP on crtscts mode + +From: Pavel Krasavin + +[ Upstream commit 2a1d728f20edeee7f26dc307ed9df4e0d23947ab ] + +There might be hard lockup if we set crtscts mode on port without RTS/CTS configured: + +# stty -F /dev/ttyAML6 crtscts; echo 1 > /dev/ttyAML6; echo 2 > /dev/ttyAML6 +[ 95.890386] rcu: INFO: rcu_preempt detected stalls on CPUs/tasks: +[ 95.890857] rcu: 3-...0: (201 ticks this GP) idle=e33c/1/0x4000000000000000 softirq=5844/5846 fqs=4984 +[ 95.900212] rcu: (detected by 2, t=21016 jiffies, g=7753, q=296 ncpus=4) +[ 95.906972] Task dump for CPU 3: +[ 95.910178] task:bash state:R running task stack:0 pid:205 ppid:1 flags:0x00000202 +[ 95.920059] Call trace: +[ 95.922485] __switch_to+0xe4/0x168 +[ 95.925951] 0xffffff8003477508 +[ 95.974379] watchdog: Watchdog detected hard LOCKUP on cpu 3 +[ 95.974424] Modules linked in: 88x2cs(O) rtc_meson_vrtc + +Possible solution would be to not allow to setup crtscts on such port. + +Tested on S905X3 based board. + +Fixes: ff7693d079e5 ("ARM: meson: serial: add MesonX SoC on-chip uart driver") +Cc: stable@vger.kernel.org +Signed-off-by: Pavel Krasavin +Reviewed-by: Neil Armstrong +Reviewed-by: Dmitry Rokosov + +v6: stable tag added +v5: https://lore.kernel.org/lkml/OF43DA36FF.2BD3BB21-ON00258A47.005A8125-00258A47.005A9513@gdc.ru/ +added missed Reviewed-by tags, Fixes tag added according to Dmitry and Neil notes +v4: https://lore.kernel.org/lkml/OF55521400.7512350F-ON00258A47.003F7254-00258A47.0040E15C@gdc.ru/ +More correct patch subject according to Jiri's note +v3: https://lore.kernel.org/lkml/OF6CF5FFA0.CCFD0E8E-ON00258A46.00549EDF-00258A46.0054BB62@gdc.ru/ +"From:" line added to the mail +v2: https://lore.kernel.org/lkml/OF950BEF72.7F425944-ON00258A46.00488A76-00258A46.00497D44@gdc.ru/ +braces for single statement removed according to Dmitry's note +v1: https://lore.kernel.org/lkml/OF28B2B8C9.5BC0CD28-ON00258A46.0037688F-00258A46.0039155B@gdc.ru/ +Link: https://lore.kernel.org/r/OF66360032.51C36182-ON00258A48.003F656B-00258A48.0040092C@gdc.ru + +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/meson_uart.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c +index bdc394afec5be..bb66a3f06626c 100644 +--- a/drivers/tty/serial/meson_uart.c ++++ b/drivers/tty/serial/meson_uart.c +@@ -370,10 +370,14 @@ static void meson_uart_set_termios(struct uart_port *port, + else + val |= AML_UART_STOP_BIT_1SB; + +- if (cflags & CRTSCTS) +- val &= ~AML_UART_TWO_WIRE_EN; +- else ++ if (cflags & CRTSCTS) { ++ if (port->flags & UPF_HARD_FLOW) ++ val &= ~AML_UART_TWO_WIRE_EN; ++ else ++ termios->c_cflag &= ~CRTSCTS; ++ } else { + val |= AML_UART_TWO_WIRE_EN; ++ } + + writel(val, port->membase + AML_UART_CONTROL); + +@@ -731,6 +735,7 @@ static int meson_uart_probe(struct platform_device *pdev) + u32 fifosize = 64; /* Default is 64, 128 for EE UART_0 */ + int ret = 0; + int irq; ++ bool has_rtscts; + + if (pdev->dev.of_node) + pdev->id = of_alias_get_id(pdev->dev.of_node, "serial"); +@@ -758,6 +763,7 @@ static int meson_uart_probe(struct platform_device *pdev) + return irq; + + of_property_read_u32(pdev->dev.of_node, "fifo-size", &fifosize); ++ has_rtscts = of_property_read_bool(pdev->dev.of_node, "uart-has-rtscts"); + + if (meson_ports[pdev->id]) { + dev_err(&pdev->dev, "port %d already allocated\n", pdev->id); +@@ -782,6 +788,8 @@ static int meson_uart_probe(struct platform_device *pdev) + port->mapsize = resource_size(res_mem); + port->irq = irq; + port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY; ++ if (has_rtscts) ++ port->flags |= UPF_HARD_FLOW; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MESON_CONSOLE); + port->dev = &pdev->dev; + port->line = pdev->id; +-- +2.42.0 + diff --git a/queue-5.10/tty-serial-meson-retrieve-port-fifo-size-from-dt.patch b/queue-5.10/tty-serial-meson-retrieve-port-fifo-size-from-dt.patch new file mode 100644 index 00000000000..3e5ffdae230 --- /dev/null +++ b/queue-5.10/tty-serial-meson-retrieve-port-fifo-size-from-dt.patch @@ -0,0 +1,55 @@ +From 9d2cae48b9b4411bf46cf89fbcac9625931c327a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 May 2021 09:58:32 +0200 +Subject: tty: serial: meson: retrieve port FIFO size from DT + +From: Neil Armstrong + +[ Upstream commit 27d44e05d7b85d9d4cfe0a3c0663ea49752ece93 ] + +Now the DT bindings has a property to get the FIFO size for a particular port, +retrieve it and use to setup the FIFO interrupts threshold. + +Reviewed-by: Kevin Hilman +Signed-off-by: Neil Armstrong +Link: https://lore.kernel.org/r/20210518075833.3736038-3-narmstrong@baylibre.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 2a1d728f20ed ("tty: serial: meson: fix hard LOCKUP on crtscts mode") +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/meson_uart.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c +index d06653493f0ef..78bda91a6bf15 100644 +--- a/drivers/tty/serial/meson_uart.c ++++ b/drivers/tty/serial/meson_uart.c +@@ -728,6 +728,7 @@ static int meson_uart_probe(struct platform_device *pdev) + { + struct resource *res_mem, *res_irq; + struct uart_port *port; ++ u32 fifosize = 64; /* Default is 64, 128 for EE UART_0 */ + int ret = 0; + + if (pdev->dev.of_node) +@@ -755,6 +756,8 @@ static int meson_uart_probe(struct platform_device *pdev) + if (!res_irq) + return -ENODEV; + ++ of_property_read_u32(pdev->dev.of_node, "fifo-size", &fifosize); ++ + if (meson_ports[pdev->id]) { + dev_err(&pdev->dev, "port %d already allocated\n", pdev->id); + return -EBUSY; +@@ -784,7 +787,7 @@ static int meson_uart_probe(struct platform_device *pdev) + port->type = PORT_MESON; + port->x_char = 0; + port->ops = &meson_uart_ops; +- port->fifosize = 64; ++ port->fifosize = fifosize; + + meson_ports[pdev->id] = port; + platform_set_drvdata(pdev, port); +-- +2.42.0 + -- 2.47.3