From: Greg Kroah-Hartman Date: Mon, 29 Nov 2021 12:48:46 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v5.15.6~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cf3dd2daa2e71fbe698eb45dde89315c12ea979b;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: arm64-dts-marvell-armada-37xx-declare-pcie-reset-pin.patch arm64-dts-marvell-armada-37xx-set-pcie_reset_pin-to-gpio-function.patch hugetlbfs-flush-tlbs-correctly-after-huge_pmd_unshare.patch pci-aardvark-configure-pcie-resources-from-ranges-dt-property.patch pci-aardvark-don-t-touch-pcie-registers-if-no-card-connected.patch pci-aardvark-fix-a-leaked-reference-by-adding-missing-of_node_put.patch pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch pci-aardvark-fix-compilation-on-s390.patch pci-aardvark-fix-i-o-space-page-leak.patch pci-aardvark-fix-link-training.patch pci-aardvark-fix-pcie-max-payload-size-setting.patch pci-aardvark-improve-link-training.patch pci-aardvark-indicate-error-in-val-when-config-read-fails.patch pci-aardvark-introduce-an-advk_pcie_valid_device-helper.patch pci-aardvark-issue-perst-via-gpio.patch pci-aardvark-move-pcie-reset-card-code-to-advk_pcie_train_link.patch pci-aardvark-remove-pcie-outbound-window-configuration.patch pci-aardvark-replace-custom-macros-by-standard-linux-pci_regs.h-macros.patch pci-aardvark-train-link-immediately-after-enabling-training.patch pci-aardvark-update-comment-about-disabling-link-training.patch pci-aardvark-wait-for-endpoint-to-be-ready-before-training-link.patch pci-add-pci_exp_lnkctl2_tls-macros.patch pinctrl-armada-37xx-add-missing-pin-pcie1-wakeup.patch pinctrl-armada-37xx-correct-mpp-definitions.patch pinctrl-armada-37xx-correct-pwm-pins-definitions.patch s390-mm-validate-vma-in-pgste-manipulation-functions.patch tracing-check-pid-filtering-when-creating-events.patch --- diff --git a/queue-4.14/arm64-dts-marvell-armada-37xx-declare-pcie-reset-pin.patch b/queue-4.14/arm64-dts-marvell-armada-37xx-declare-pcie-reset-pin.patch new file mode 100644 index 00000000000..072bc2a3d02 --- /dev/null +++ b/queue-4.14/arm64-dts-marvell-armada-37xx-declare-pcie-reset-pin.patch @@ -0,0 +1,40 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:32 +0100 +Subject: arm64: dts: marvell: armada-37xx: declare PCIe reset pin +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Miquel Raynal" , "Gregory CLEMENT" , "Marek Behún" +Message-ID: <20211124224933.24275-24-kabel@kernel.org> + +From: Miquel Raynal + +commit a5470af981a0cc14a650af8da5186668971a4fc8 upstream. + +One pin can be muxed as PCIe endpoint card reset. + +Signed-off-by: Miquel Raynal +Signed-off-by: Gregory CLEMENT +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +@@ -239,6 +239,15 @@ + function = "mii"; + }; + ++ pcie_reset_pins: pcie-reset-pins { ++ groups = "pcie1"; ++ function = "pcie"; ++ }; ++ ++ pcie_clkreq_pins: pcie-clkreq-pins { ++ groups = "pcie1_clkreq"; ++ function = "pcie"; ++ }; + }; + + eth0: ethernet@30000 { diff --git a/queue-4.14/arm64-dts-marvell-armada-37xx-set-pcie_reset_pin-to-gpio-function.patch b/queue-4.14/arm64-dts-marvell-armada-37xx-set-pcie_reset_pin-to-gpio-function.patch new file mode 100644 index 00000000000..4046cc068df --- /dev/null +++ b/queue-4.14/arm64-dts-marvell-armada-37xx-set-pcie_reset_pin-to-gpio-function.patch @@ -0,0 +1,86 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:33 +0100 +Subject: arm64: dts: marvell: armada-37xx: Set pcie_reset_pin to gpio function +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" , "Remi Pommarel" , "Tomasz Maciej Nowak" , "Thomas Petazzoni" , "Gregory CLEMENT" , "Marek Behún" +Message-ID: <20211124224933.24275-25-kabel@kernel.org> + +From: Marek Behún + +commit 715878016984b2617f6c1f177c50039e12e7bd5b upstream. + +We found out that we are unable to control the PERST# signal via the +default pin dedicated to be PERST# pin (GPIO2[3] pin) on A3700 SOC when +this pin is in EP_PCIE1_Resetn mode. There is a register in the PCIe +register space called PERSTN_GPIO_EN (D0088004[3]), but changing the +value of this register does not change the pin output when measuring +with voltmeter. + +We do not know if this is a bug in the SOC, or if it works only when +PCIe controller is in a certain state. + +Commit f4c7d053d7f7 ("PCI: aardvark: Wait for endpoint to be ready +before training link") says that when this pin changes pinctrl mode +from EP_PCIE1_Resetn to GPIO, the PERST# signal is asserted for a brief +moment. + +So currently the situation is that on A3700 boards the PERST# signal is +asserted in U-Boot (because the code in U-Boot issues reset via this pin +via GPIO mode), and then in Linux by the obscure and undocumented +mechanism described by the above mentioned commit. + +We want to issue PERST# signal in a known way, therefore this patch +changes the pcie_reset_pin function from "pcie" to "gpio" and adds the +reset-gpios property to the PCIe node in device tree files of +EspressoBin and Armada 3720 Dev Board (Turris Mox device tree already +has this property and uDPU does not have a PCIe port). + +Signed-off-by: Marek Behún +Cc: Remi Pommarel +Tested-by: Tomasz Maciej Nowak +Acked-by: Thomas Petazzoni +Signed-off-by: Gregory CLEMENT +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/boot/dts/marvell/armada-3720-db.dts | 3 +++ + arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts | 3 +++ + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 2 +- + 3 files changed, 7 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts ++++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts +@@ -155,6 +155,9 @@ + + /* CON15(V2.0)/CON17(V1.4) : PCIe / CON15(V2.0)/CON12(V1.4) :mini-PCIe */ + &pcie0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_reset_pins &pcie_clkreq_pins>; ++ reset-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + +--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts ++++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts +@@ -82,6 +82,9 @@ + + /* J9 */ + &pcie0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_reset_pins &pcie_clkreq_pins>; ++ reset-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + +--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +@@ -241,7 +241,7 @@ + + pcie_reset_pins: pcie-reset-pins { + groups = "pcie1"; +- function = "pcie"; ++ function = "gpio"; + }; + + pcie_clkreq_pins: pcie-clkreq-pins { diff --git a/queue-4.14/hugetlbfs-flush-tlbs-correctly-after-huge_pmd_unshare.patch b/queue-4.14/hugetlbfs-flush-tlbs-correctly-after-huge_pmd_unshare.patch new file mode 100644 index 00000000000..360245bc60d --- /dev/null +++ b/queue-4.14/hugetlbfs-flush-tlbs-correctly-after-huge_pmd_unshare.patch @@ -0,0 +1,216 @@ +From a4a118f2eead1d6c49e00765de89878288d4b890 Mon Sep 17 00:00:00 2001 +From: Nadav Amit +Date: Sun, 21 Nov 2021 12:40:07 -0800 +Subject: hugetlbfs: flush TLBs correctly after huge_pmd_unshare + +From: Nadav Amit + +commit a4a118f2eead1d6c49e00765de89878288d4b890 upstream. + +When __unmap_hugepage_range() calls to huge_pmd_unshare() succeed, a TLB +flush is missing. This TLB flush must be performed before releasing the +i_mmap_rwsem, in order to prevent an unshared PMDs page from being +released and reused before the TLB flush took place. + +Arguably, a comprehensive solution would use mmu_gather interface to +batch the TLB flushes and the PMDs page release, however it is not an +easy solution: (1) try_to_unmap_one() and try_to_migrate_one() also call +huge_pmd_unshare() and they cannot use the mmu_gather interface; and (2) +deferring the release of the page reference for the PMDs page until +after i_mmap_rwsem is dropeed can confuse huge_pmd_unshare() into +thinking PMDs are shared when they are not. + +Fix __unmap_hugepage_range() by adding the missing TLB flush, and +forcing a flush when unshare is successful. + +Fixes: 24669e58477e ("hugetlb: use mmu_gather instead of a temporary linked list for accumulating pages)" # 3.6 +Signed-off-by: Nadav Amit +Reviewed-by: Mike Kravetz +Cc: Aneesh Kumar K.V +Cc: KAMEZAWA Hiroyuki +Cc: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/include/asm/tlb.h | 8 ++++++++ + arch/ia64/include/asm/tlb.h | 10 ++++++++++ + arch/s390/include/asm/tlb.h | 14 ++++++++++++++ + arch/sh/include/asm/tlb.h | 10 ++++++++++ + arch/um/include/asm/tlb.h | 12 ++++++++++++ + include/asm-generic/tlb.h | 2 ++ + mm/hugetlb.c | 19 +++++++++++++++++++ + mm/memory.c | 10 ++++++++++ + 8 files changed, 85 insertions(+) + +--- a/arch/arm/include/asm/tlb.h ++++ b/arch/arm/include/asm/tlb.h +@@ -280,6 +280,14 @@ tlb_remove_pmd_tlb_entry(struct mmu_gath + tlb_add_flush(tlb, addr); + } + ++static inline void ++tlb_flush_pmd_range(struct mmu_gather *tlb, unsigned long address, ++ unsigned long size) ++{ ++ tlb_add_flush(tlb, address); ++ tlb_add_flush(tlb, address + size - PMD_SIZE); ++} ++ + #define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr) + #define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr) + #define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp) +--- a/arch/ia64/include/asm/tlb.h ++++ b/arch/ia64/include/asm/tlb.h +@@ -269,6 +269,16 @@ __tlb_remove_tlb_entry (struct mmu_gathe + tlb->end_addr = address + PAGE_SIZE; + } + ++static inline void ++tlb_flush_pmd_range(struct mmu_gather *tlb, unsigned long address, ++ unsigned long size) ++{ ++ if (tlb->start_addr > address) ++ tlb->start_addr = address; ++ if (tlb->end_addr < address + size) ++ tlb->end_addr = address + size; ++} ++ + #define tlb_migrate_finish(mm) platform_tlb_migrate_finish(mm) + + #define tlb_start_vma(tlb, vma) do { } while (0) +--- a/arch/s390/include/asm/tlb.h ++++ b/arch/s390/include/asm/tlb.h +@@ -116,6 +116,20 @@ static inline void tlb_remove_page_size( + return tlb_remove_page(tlb, page); + } + ++static inline void tlb_flush_pmd_range(struct mmu_gather *tlb, ++ unsigned long address, unsigned long size) ++{ ++ /* ++ * the range might exceed the original range that was provided to ++ * tlb_gather_mmu(), so we need to update it despite the fact it is ++ * usually not updated. ++ */ ++ if (tlb->start > address) ++ tlb->start = address; ++ if (tlb->end < address + size) ++ tlb->end = address + size; ++} ++ + /* + * pte_free_tlb frees a pte table and clears the CRSTE for the + * page table from the tlb. +--- a/arch/sh/include/asm/tlb.h ++++ b/arch/sh/include/asm/tlb.h +@@ -127,6 +127,16 @@ static inline void tlb_remove_page_size( + return tlb_remove_page(tlb, page); + } + ++static inline void ++tlb_flush_pmd_range(struct mmu_gather *tlb, unsigned long address, ++ unsigned long size) ++{ ++ if (tlb->start > address) ++ tlb->start = address; ++ if (tlb->end < address + size) ++ tlb->end = address + size; ++} ++ + #define tlb_remove_check_page_size_change tlb_remove_check_page_size_change + static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb, + unsigned int page_size) +--- a/arch/um/include/asm/tlb.h ++++ b/arch/um/include/asm/tlb.h +@@ -130,6 +130,18 @@ static inline void tlb_remove_page_size( + return tlb_remove_page(tlb, page); + } + ++static inline void ++tlb_flush_pmd_range(struct mmu_gather *tlb, unsigned long address, ++ unsigned long size) ++{ ++ tlb->need_flush = 1; ++ ++ if (tlb->start > address) ++ tlb->start = address; ++ if (tlb->end < address + size) ++ tlb->end = address + size; ++} ++ + /** + * tlb_remove_tlb_entry - remember a pte unmapping for later tlb invalidation. + * +--- a/include/asm-generic/tlb.h ++++ b/include/asm-generic/tlb.h +@@ -117,6 +117,8 @@ void arch_tlb_gather_mmu(struct mmu_gath + void tlb_flush_mmu(struct mmu_gather *tlb); + void arch_tlb_finish_mmu(struct mmu_gather *tlb, + unsigned long start, unsigned long end, bool force); ++void tlb_flush_pmd_range(struct mmu_gather *tlb, unsigned long address, ++ unsigned long size); + extern bool __tlb_remove_page_size(struct mmu_gather *tlb, struct page *page, + int page_size); + +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -3386,6 +3386,7 @@ void __unmap_hugepage_range(struct mmu_g + unsigned long sz = huge_page_size(h); + const unsigned long mmun_start = start; /* For mmu_notifiers */ + const unsigned long mmun_end = end; /* For mmu_notifiers */ ++ bool force_flush = false; + + WARN_ON(!is_vm_hugetlb_page(vma)); + BUG_ON(start & ~huge_page_mask(h)); +@@ -3407,6 +3408,8 @@ void __unmap_hugepage_range(struct mmu_g + ptl = huge_pte_lock(h, mm, ptep); + if (huge_pmd_unshare(mm, &address, ptep)) { + spin_unlock(ptl); ++ tlb_flush_pmd_range(tlb, address & PUD_MASK, PUD_SIZE); ++ force_flush = true; + continue; + } + +@@ -3463,6 +3466,22 @@ void __unmap_hugepage_range(struct mmu_g + } + mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); + tlb_end_vma(tlb, vma); ++ ++ /* ++ * If we unshared PMDs, the TLB flush was not recorded in mmu_gather. We ++ * could defer the flush until now, since by holding i_mmap_rwsem we ++ * guaranteed that the last refernece would not be dropped. But we must ++ * do the flushing before we return, as otherwise i_mmap_rwsem will be ++ * dropped and the last reference to the shared PMDs page might be ++ * dropped as well. ++ * ++ * In theory we could defer the freeing of the PMD pages as well, but ++ * huge_pmd_unshare() relies on the exact page_count for the PMD page to ++ * detect sharing, so we cannot defer the release of the page either. ++ * Instead, do flush now. ++ */ ++ if (force_flush) ++ tlb_flush_mmu(tlb); + } + + void __unmap_hugepage_range_final(struct mmu_gather *tlb, +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -335,6 +335,16 @@ bool __tlb_remove_page_size(struct mmu_g + return false; + } + ++void tlb_flush_pmd_range(struct mmu_gather *tlb, unsigned long address, ++ unsigned long size) ++{ ++ if (tlb->page_size != 0 && tlb->page_size != PMD_SIZE) ++ tlb_flush_mmu(tlb); ++ ++ tlb->page_size = PMD_SIZE; ++ tlb->start = min(tlb->start, address); ++ tlb->end = max(tlb->end, address + size); ++} + #endif /* HAVE_GENERIC_MMU_GATHER */ + + #ifdef CONFIG_HAVE_RCU_TABLE_FREE diff --git a/queue-4.14/pci-aardvark-configure-pcie-resources-from-ranges-dt-property.patch b/queue-4.14/pci-aardvark-configure-pcie-resources-from-ranges-dt-property.patch new file mode 100644 index 00000000000..87aff6f4310 --- /dev/null +++ b/queue-4.14/pci-aardvark-configure-pcie-resources-from-ranges-dt-property.patch @@ -0,0 +1,297 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:24 +0100 +Subject: PCI: aardvark: Configure PCIe resources from 'ranges' DT property +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Lorenzo Pieralisi" , "Marek Behún" +Message-ID: <20211124224933.24275-16-kabel@kernel.org> + +From: Pali Rohár + +commit 64f160e19e9264a7f6d89c516baae1473b6f8359 upstream. + +In commit 6df6ba974a55 ("PCI: aardvark: Remove PCIe outbound window +configuration") was removed aardvark PCIe outbound window configuration and +commit description said that was recommended solution by HW designers. + +But that commit completely removed support for configuring PCIe IO +resources without removing PCIe IO 'ranges' from DTS files. After that +commit PCIe IO space started to be treated as PCIe MEM space and accessing +it just caused kernel crash. + +Moreover implementation of PCIe outbound windows prior that commit was +incorrect. It completely ignored offset between CPU address and PCIe bus +address and expected that in DTS is CPU address always same as PCIe bus +address without doing any checks. Also it completely ignored size of every +PCIe resource specified in 'ranges' DTS property and expected that every +PCIe resource has size 128 MB (also for PCIe IO range). Again without any +check. Apparently none of PCIe resource has in DTS specified size of 128 +MB. So it was completely broken and thanks to how aardvark mask works, +configuration was completely ignored. + +This patch reverts back support for PCIe outbound window configuration but +implementation is a new without issues mentioned above. PCIe outbound +window is required when DTS specify in 'ranges' property non-zero offset +between CPU and PCIe address space. To address recommendation by HW +designers as specified in commit description of 6df6ba974a55, set default +outbound parameters as PCIe MEM access without translation and therefore +for this PCIe 'ranges' it is not needed to configure PCIe outbound window. +For PCIe IO space is needed to configure aardvark PCIe outbound window. + +This patch fixes kernel crash when trying to access PCIe IO space. + +Link: https://lore.kernel.org/r/20210624215546.4015-2-pali@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Cc: stable@vger.kernel.org # 6df6ba974a55 ("PCI: aardvark: Remove PCIe outbound window configuration") +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 190 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 189 insertions(+), 1 deletion(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -107,6 +107,46 @@ + #define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C) + #define PCIE_MSI_DATA_MASK GENMASK(15, 0) + ++/* PCIe window configuration */ ++#define OB_WIN_BASE_ADDR 0x4c00 ++#define OB_WIN_BLOCK_SIZE 0x20 ++#define OB_WIN_COUNT 8 ++#define OB_WIN_REG_ADDR(win, offset) (OB_WIN_BASE_ADDR + \ ++ OB_WIN_BLOCK_SIZE * (win) + \ ++ (offset)) ++#define OB_WIN_MATCH_LS(win) OB_WIN_REG_ADDR(win, 0x00) ++#define OB_WIN_ENABLE BIT(0) ++#define OB_WIN_MATCH_MS(win) OB_WIN_REG_ADDR(win, 0x04) ++#define OB_WIN_REMAP_LS(win) OB_WIN_REG_ADDR(win, 0x08) ++#define OB_WIN_REMAP_MS(win) OB_WIN_REG_ADDR(win, 0x0c) ++#define OB_WIN_MASK_LS(win) OB_WIN_REG_ADDR(win, 0x10) ++#define OB_WIN_MASK_MS(win) OB_WIN_REG_ADDR(win, 0x14) ++#define OB_WIN_ACTIONS(win) OB_WIN_REG_ADDR(win, 0x18) ++#define OB_WIN_DEFAULT_ACTIONS (OB_WIN_ACTIONS(OB_WIN_COUNT-1) + 0x4) ++#define OB_WIN_FUNC_NUM_MASK GENMASK(31, 24) ++#define OB_WIN_FUNC_NUM_SHIFT 24 ++#define OB_WIN_FUNC_NUM_ENABLE BIT(23) ++#define OB_WIN_BUS_NUM_BITS_MASK GENMASK(22, 20) ++#define OB_WIN_BUS_NUM_BITS_SHIFT 20 ++#define OB_WIN_MSG_CODE_ENABLE BIT(22) ++#define OB_WIN_MSG_CODE_MASK GENMASK(21, 14) ++#define OB_WIN_MSG_CODE_SHIFT 14 ++#define OB_WIN_MSG_PAYLOAD_LEN BIT(12) ++#define OB_WIN_ATTR_ENABLE BIT(11) ++#define OB_WIN_ATTR_TC_MASK GENMASK(10, 8) ++#define OB_WIN_ATTR_TC_SHIFT 8 ++#define OB_WIN_ATTR_RELAXED BIT(7) ++#define OB_WIN_ATTR_NOSNOOP BIT(6) ++#define OB_WIN_ATTR_POISON BIT(5) ++#define OB_WIN_ATTR_IDO BIT(4) ++#define OB_WIN_TYPE_MASK GENMASK(3, 0) ++#define OB_WIN_TYPE_SHIFT 0 ++#define OB_WIN_TYPE_MEM 0x0 ++#define OB_WIN_TYPE_IO 0x4 ++#define OB_WIN_TYPE_CONFIG_TYPE0 0x8 ++#define OB_WIN_TYPE_CONFIG_TYPE1 0x9 ++#define OB_WIN_TYPE_MSG 0xc ++ + /* LMI registers base address and register offsets */ + #define LMI_BASE_ADDR 0x6000 + #define CFG_REG (LMI_BASE_ADDR + 0x0) +@@ -175,6 +215,13 @@ struct advk_pcie { + struct platform_device *pdev; + void __iomem *base; + struct list_head resources; ++ struct { ++ phys_addr_t match; ++ phys_addr_t remap; ++ phys_addr_t mask; ++ u32 actions; ++ } wins[OB_WIN_COUNT]; ++ u8 wins_count; + struct irq_domain *irq_domain; + struct irq_chip irq_chip; + raw_spinlock_t irq_lock; +@@ -350,9 +397,39 @@ err: + dev_err(dev, "link never came up\n"); + } + ++/* ++ * Set PCIe address window register which could be used for memory ++ * mapping. ++ */ ++static void advk_pcie_set_ob_win(struct advk_pcie *pcie, u8 win_num, ++ phys_addr_t match, phys_addr_t remap, ++ phys_addr_t mask, u32 actions) ++{ ++ advk_writel(pcie, OB_WIN_ENABLE | ++ lower_32_bits(match), OB_WIN_MATCH_LS(win_num)); ++ advk_writel(pcie, upper_32_bits(match), OB_WIN_MATCH_MS(win_num)); ++ advk_writel(pcie, lower_32_bits(remap), OB_WIN_REMAP_LS(win_num)); ++ advk_writel(pcie, upper_32_bits(remap), OB_WIN_REMAP_MS(win_num)); ++ advk_writel(pcie, lower_32_bits(mask), OB_WIN_MASK_LS(win_num)); ++ advk_writel(pcie, upper_32_bits(mask), OB_WIN_MASK_MS(win_num)); ++ advk_writel(pcie, actions, OB_WIN_ACTIONS(win_num)); ++} ++ ++static void advk_pcie_disable_ob_win(struct advk_pcie *pcie, u8 win_num) ++{ ++ advk_writel(pcie, 0, OB_WIN_MATCH_LS(win_num)); ++ advk_writel(pcie, 0, OB_WIN_MATCH_MS(win_num)); ++ advk_writel(pcie, 0, OB_WIN_REMAP_LS(win_num)); ++ advk_writel(pcie, 0, OB_WIN_REMAP_MS(win_num)); ++ advk_writel(pcie, 0, OB_WIN_MASK_LS(win_num)); ++ advk_writel(pcie, 0, OB_WIN_MASK_MS(win_num)); ++ advk_writel(pcie, 0, OB_WIN_ACTIONS(win_num)); ++} ++ + static void advk_pcie_setup_hw(struct advk_pcie *pcie) + { + u32 reg; ++ int i; + + /* Set to Direct mode */ + reg = advk_readl(pcie, CTRL_CONFIG_REG); +@@ -416,15 +493,51 @@ static void advk_pcie_setup_hw(struct ad + reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK); + advk_writel(pcie, reg, HOST_CTRL_INT_MASK_REG); + ++ /* ++ * Enable AXI address window location generation: ++ * When it is enabled, the default outbound window ++ * configurations (Default User Field: 0xD0074CFC) ++ * are used to transparent address translation for ++ * the outbound transactions. Thus, PCIe address ++ * windows are not required for transparent memory ++ * access when default outbound window configuration ++ * is set for memory access. ++ */ + reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG); + reg |= PCIE_CORE_CTRL2_OB_WIN_ENABLE; + advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG); + +- /* Bypass the address window mapping for PIO */ ++ /* ++ * Set memory access in Default User Field so it ++ * is not required to configure PCIe address for ++ * transparent memory access. ++ */ ++ advk_writel(pcie, OB_WIN_TYPE_MEM, OB_WIN_DEFAULT_ACTIONS); ++ ++ /* ++ * Bypass the address window mapping for PIO: ++ * Since PIO access already contains all required ++ * info over AXI interface by PIO registers, the ++ * address window is not required. ++ */ + reg = advk_readl(pcie, PIO_CTRL); + reg |= PIO_CTRL_ADDR_WIN_DISABLE; + advk_writel(pcie, reg, PIO_CTRL); + ++ /* ++ * Configure PCIe address windows for non-memory or ++ * non-transparent access as by default PCIe uses ++ * transparent memory access. ++ */ ++ for (i = 0; i < pcie->wins_count; i++) ++ advk_pcie_set_ob_win(pcie, i, ++ pcie->wins[i].match, pcie->wins[i].remap, ++ pcie->wins[i].mask, pcie->wins[i].actions); ++ ++ /* Disable remaining PCIe outbound windows */ ++ for (i = pcie->wins_count; i < OB_WIN_COUNT; i++) ++ advk_pcie_disable_ob_win(pcie, i); ++ + advk_pcie_train_link(pcie); + + reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); +@@ -1041,6 +1154,7 @@ static int advk_pcie_probe(struct platfo + struct resource *res; + struct pci_bus *bus, *child; + struct pci_host_bridge *bridge; ++ struct resource_entry *entry; + int ret, irq; + + bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct advk_pcie)); +@@ -1070,6 +1184,80 @@ static int advk_pcie_probe(struct platfo + return ret; + } + ++ resource_list_for_each_entry(entry, &pcie->resources) { ++ resource_size_t start = entry->res->start; ++ resource_size_t size = resource_size(entry->res); ++ unsigned long type = resource_type(entry->res); ++ u64 win_size; ++ ++ /* ++ * Aardvark hardware allows to configure also PCIe window ++ * for config type 0 and type 1 mapping, but driver uses ++ * only PIO for issuing configuration transfers which does ++ * not use PCIe window configuration. ++ */ ++ if (type != IORESOURCE_MEM && type != IORESOURCE_MEM_64 && ++ type != IORESOURCE_IO) ++ continue; ++ ++ /* ++ * Skip transparent memory resources. Default outbound access ++ * configuration is set to transparent memory access so it ++ * does not need window configuration. ++ */ ++ if ((type == IORESOURCE_MEM || type == IORESOURCE_MEM_64) && ++ entry->offset == 0) ++ continue; ++ ++ /* ++ * The n-th PCIe window is configured by tuple (match, remap, mask) ++ * and an access to address A uses this window if A matches the ++ * match with given mask. ++ * So every PCIe window size must be a power of two and every start ++ * address must be aligned to window size. Minimal size is 64 KiB ++ * because lower 16 bits of mask must be zero. Remapped address ++ * may have set only bits from the mask. ++ */ ++ while (pcie->wins_count < OB_WIN_COUNT && size > 0) { ++ /* Calculate the largest aligned window size */ ++ win_size = (1ULL << (fls64(size)-1)) | ++ (start ? (1ULL << __ffs64(start)) : 0); ++ win_size = 1ULL << __ffs64(win_size); ++ if (win_size < 0x10000) ++ break; ++ ++ dev_dbg(dev, ++ "Configuring PCIe window %d: [0x%llx-0x%llx] as %lu\n", ++ pcie->wins_count, (unsigned long long)start, ++ (unsigned long long)start + win_size, type); ++ ++ if (type == IORESOURCE_IO) { ++ pcie->wins[pcie->wins_count].actions = OB_WIN_TYPE_IO; ++ pcie->wins[pcie->wins_count].match = pci_pio_to_address(start); ++ } else { ++ pcie->wins[pcie->wins_count].actions = OB_WIN_TYPE_MEM; ++ pcie->wins[pcie->wins_count].match = start; ++ } ++ pcie->wins[pcie->wins_count].remap = start - entry->offset; ++ pcie->wins[pcie->wins_count].mask = ~(win_size - 1); ++ ++ if (pcie->wins[pcie->wins_count].remap & (win_size - 1)) ++ break; ++ ++ start += win_size; ++ size -= win_size; ++ pcie->wins_count++; ++ } ++ ++ if (size > 0) { ++ dev_err(&pcie->pdev->dev, ++ "Invalid PCIe region [0x%llx-0x%llx]\n", ++ (unsigned long long)entry->res->start, ++ (unsigned long long)entry->res->end + 1); ++ return -EINVAL; ++ } ++ } ++ + pcie->reset_gpio = devm_fwnode_get_index_gpiod_from_child(dev, "reset", + 0, + dev_fwnode(dev), diff --git a/queue-4.14/pci-aardvark-don-t-touch-pcie-registers-if-no-card-connected.patch b/queue-4.14/pci-aardvark-don-t-touch-pcie-registers-if-no-card-connected.patch new file mode 100644 index 00000000000..4a1a76a0963 --- /dev/null +++ b/queue-4.14/pci-aardvark-don-t-touch-pcie-registers-if-no-card-connected.patch @@ -0,0 +1,55 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:19 +0100 +Subject: PCI: aardvark: Don't touch PCIe registers if no card connected +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Lorenzo Pieralisi" , "Marek Behún" +Message-ID: <20211124224933.24275-11-kabel@kernel.org> + +From: Pali Rohár + +commit 70e380250c3621c55ff218cbaf2272830d9dbb1d upstream. + +When there is no PCIe card connected and advk_pcie_rd_conf() or +advk_pcie_wr_conf() is called for PCI bus which doesn't belong to emulated +root bridge, the aardvark driver throws the following error message: + + advk-pcie d0070000.pcie: config read/write timed out + +Obviously accessing PCIe registers of disconnected card is not possible. + +Extend check in advk_pcie_valid_device() function for validating +availability of PCIe bus. If PCIe link is down, then the device is marked +as Not Found and the driver does not try to access these registers. + +This is just an optimization to prevent accessing PCIe registers when card +is disconnected. Trying to access PCIe registers of disconnected card does +not cause any crash, kernel just needs to wait for a timeout. So if card +disappear immediately after checking for PCIe link (before accessing PCIe +registers), it does not cause any problems. + +Link: https://lore.kernel.org/r/20200702083036.12230-1-pali@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -598,6 +598,13 @@ static bool advk_pcie_valid_device(struc + if ((bus->number == pcie->root_bus_nr) && PCI_SLOT(devfn) != 0) + return false; + ++ /* ++ * If the link goes down after we check for link-up, nothing bad ++ * happens but the config access times out. ++ */ ++ if (bus->number != pcie->root_bus_nr && !advk_pcie_link_up(pcie)) ++ return false; ++ + return true; + } + diff --git a/queue-4.14/pci-aardvark-fix-a-leaked-reference-by-adding-missing-of_node_put.patch b/queue-4.14/pci-aardvark-fix-a-leaked-reference-by-adding-missing-of_node_put.patch new file mode 100644 index 00000000000..2d9fd29b218 --- /dev/null +++ b/queue-4.14/pci-aardvark-fix-a-leaked-reference-by-adding-missing-of_node_put.patch @@ -0,0 +1,74 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:11 +0100 +Subject: PCI: aardvark: Fix a leaked reference by adding missing of_node_put() +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Wen Yang" , "Lorenzo Pieralisi" , "Thomas Petazzoni" , "Bjorn Helgaas" , linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, "Marek Behún" +Message-ID: <20211124224933.24275-3-kabel@kernel.org> + +From: Wen Yang + +commit 3842f5166bf1ef286fe7a39f262b5c9581308366 upstream. + +The call to of_get_next_child() returns a node pointer with refcount +incremented thus it must be explicitly decremented after the last +usage. + +irq_domain_add_linear() also calls of_node_get() to increase refcount, +so irq_domain will not be affected when it is released. + +Detected by coccinelle with the following warnings: + ./drivers/pci/controller/pci-aardvark.c:826:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 798, but without a corresponding object release within this function. + +Signed-off-by: Wen Yang +Signed-off-by: Lorenzo Pieralisi +Cc: Thomas Petazzoni +Cc: Lorenzo Pieralisi +Cc: Bjorn Helgaas +Cc: linux-pci@vger.kernel.org +Cc: linux-arm-kernel@lists.infradead.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -789,6 +789,7 @@ static int advk_pcie_init_irq_domain(str + struct device_node *node = dev->of_node; + struct device_node *pcie_intc_node; + struct irq_chip *irq_chip; ++ int ret = 0; + + raw_spin_lock_init(&pcie->irq_lock); + +@@ -803,8 +804,8 @@ static int advk_pcie_init_irq_domain(str + irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-irq", + dev_name(dev)); + if (!irq_chip->name) { +- of_node_put(pcie_intc_node); +- return -ENOMEM; ++ ret = -ENOMEM; ++ goto out_put_node; + } + + irq_chip->irq_mask = advk_pcie_irq_mask; +@@ -816,11 +817,13 @@ static int advk_pcie_init_irq_domain(str + &advk_pcie_irq_domain_ops, pcie); + if (!pcie->irq_domain) { + dev_err(dev, "Failed to get a INTx IRQ domain\n"); +- of_node_put(pcie_intc_node); +- return -ENOMEM; ++ ret = -ENOMEM; ++ goto out_put_node; + } + +- return 0; ++out_put_node: ++ of_node_put(pcie_intc_node); ++ return ret; + } + + static void advk_pcie_remove_irq_domain(struct advk_pcie *pcie) diff --git a/queue-4.14/pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch b/queue-4.14/pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch new file mode 100644 index 00000000000..574e936f77d --- /dev/null +++ b/queue-4.14/pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch @@ -0,0 +1,131 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:28 +0100 +Subject: PCI: aardvark: Fix checking for link up via LTSSM state +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" , "Lorenzo Pieralisi" , "Remi Pommarel" +Message-ID: <20211124224933.24275-20-kabel@kernel.org> + +From: Pali Rohár + +commit 661c399a651c11aaf83c45cbfe0b4a1fb7bc3179 upstream. + +Current implementation of advk_pcie_link_up() is wrong as it marks also +link disabled or hot reset states as link up. + +Fix it by marking link up only to those states which are defined in PCIe +Base specification 3.0, Table 4-14: Link Status Mapped to the LTSSM. + +To simplify implementation, Define macros for every LTSSM state which +aardvark hardware can return in CFG_REG register. + +Fix also checking for link training according to the same Table 4-14. +Define a new function advk_pcie_link_training() for this purpose. + +Link: https://lore.kernel.org/r/20211005180952.6812-13-kabel@kernel.org +Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Cc: stable@vger.kernel.org +Cc: Remi Pommarel +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 71 +++++++++++++++++++++++++++++++++++++--- + 1 file changed, 67 insertions(+), 4 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -152,9 +152,50 @@ + #define CFG_REG (LMI_BASE_ADDR + 0x0) + #define LTSSM_SHIFT 24 + #define LTSSM_MASK 0x3f +-#define LTSSM_L0 0x10 + #define RC_BAR_CONFIG 0x300 + ++/* LTSSM values in CFG_REG */ ++enum { ++ LTSSM_DETECT_QUIET = 0x0, ++ LTSSM_DETECT_ACTIVE = 0x1, ++ LTSSM_POLLING_ACTIVE = 0x2, ++ LTSSM_POLLING_COMPLIANCE = 0x3, ++ LTSSM_POLLING_CONFIGURATION = 0x4, ++ LTSSM_CONFIG_LINKWIDTH_START = 0x5, ++ LTSSM_CONFIG_LINKWIDTH_ACCEPT = 0x6, ++ LTSSM_CONFIG_LANENUM_ACCEPT = 0x7, ++ LTSSM_CONFIG_LANENUM_WAIT = 0x8, ++ LTSSM_CONFIG_COMPLETE = 0x9, ++ LTSSM_CONFIG_IDLE = 0xa, ++ LTSSM_RECOVERY_RCVR_LOCK = 0xb, ++ LTSSM_RECOVERY_SPEED = 0xc, ++ LTSSM_RECOVERY_RCVR_CFG = 0xd, ++ LTSSM_RECOVERY_IDLE = 0xe, ++ LTSSM_L0 = 0x10, ++ LTSSM_RX_L0S_ENTRY = 0x11, ++ LTSSM_RX_L0S_IDLE = 0x12, ++ LTSSM_RX_L0S_FTS = 0x13, ++ LTSSM_TX_L0S_ENTRY = 0x14, ++ LTSSM_TX_L0S_IDLE = 0x15, ++ LTSSM_TX_L0S_FTS = 0x16, ++ LTSSM_L1_ENTRY = 0x17, ++ LTSSM_L1_IDLE = 0x18, ++ LTSSM_L2_IDLE = 0x19, ++ LTSSM_L2_TRANSMIT_WAKE = 0x1a, ++ LTSSM_DISABLED = 0x20, ++ LTSSM_LOOPBACK_ENTRY_MASTER = 0x21, ++ LTSSM_LOOPBACK_ACTIVE_MASTER = 0x22, ++ LTSSM_LOOPBACK_EXIT_MASTER = 0x23, ++ LTSSM_LOOPBACK_ENTRY_SLAVE = 0x24, ++ LTSSM_LOOPBACK_ACTIVE_SLAVE = 0x25, ++ LTSSM_LOOPBACK_EXIT_SLAVE = 0x26, ++ LTSSM_HOT_RESET = 0x27, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE0 = 0x28, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE1 = 0x29, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE2 = 0x2a, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE3 = 0x2b, ++}; ++ + /* PCIe core controller registers */ + #define CTRL_CORE_BASE_ADDR 0x18000 + #define CTRL_CONFIG_REG (CTRL_CORE_BASE_ADDR + 0x0) +@@ -248,13 +289,35 @@ static inline u32 advk_readl(struct advk + return readl(pcie->base + reg); + } + +-static int advk_pcie_link_up(struct advk_pcie *pcie) ++static u8 advk_pcie_ltssm_state(struct advk_pcie *pcie) + { +- u32 val, ltssm_state; ++ u32 val; ++ u8 ltssm_state; + + val = advk_readl(pcie, CFG_REG); + ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK; +- return ltssm_state >= LTSSM_L0; ++ return ltssm_state; ++} ++ ++static inline bool advk_pcie_link_up(struct advk_pcie *pcie) ++{ ++ /* check if LTSSM is in normal operation - some L* state */ ++ u8 ltssm_state = advk_pcie_ltssm_state(pcie); ++ return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED; ++} ++ ++static inline bool advk_pcie_link_training(struct advk_pcie *pcie) ++{ ++ /* ++ * According to PCIe Base specification 3.0, Table 4-14: Link ++ * Status Mapped to the LTSSM is Link Training mapped to LTSSM ++ * Configuration and Recovery states. ++ */ ++ u8 ltssm_state = advk_pcie_ltssm_state(pcie); ++ return ((ltssm_state >= LTSSM_CONFIG_LINKWIDTH_START && ++ ltssm_state < LTSSM_L0) || ++ (ltssm_state >= LTSSM_RECOVERY_EQUALIZATION_PHASE0 && ++ ltssm_state <= LTSSM_RECOVERY_EQUALIZATION_PHASE3)); + } + + static int advk_pcie_wait_for_link(struct advk_pcie *pcie) diff --git a/queue-4.14/pci-aardvark-fix-compilation-on-s390.patch b/queue-4.14/pci-aardvark-fix-compilation-on-s390.patch new file mode 100644 index 00000000000..92f32031f83 --- /dev/null +++ b/queue-4.14/pci-aardvark-fix-compilation-on-s390.patch @@ -0,0 +1,45 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:20 +0100 +Subject: PCI: aardvark: Fix compilation on s390 +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "kernel test robot" , "Lorenzo Pieralisi" , "Marek Behún" , "Marek Behún" +Message-ID: <20211124224933.24275-12-kabel@kernel.org> + +From: Pali Rohár + +commit b32c012e4b98f0126aa327be2d1f409963057643 upstream. + +Include linux/gpio/consumer.h instead of linux/gpio.h, as is said in the +latter file. + +This was reported by kernel test bot when compiling for s390. + + drivers/pci/controller/pci-aardvark.c:350:2: error: implicit declaration of function 'gpiod_set_value_cansleep' [-Werror,-Wimplicit-function-declaration] + drivers/pci/controller/pci-aardvark.c:1074:21: error: implicit declaration of function 'devm_gpiod_get_from_of_node' [-Werror,-Wimplicit-function-declaration] + drivers/pci/controller/pci-aardvark.c:1076:14: error: use of undeclared identifier 'GPIOD_OUT_LOW' + +Link: https://lore.kernel.org/r/202006211118.LxtENQfl%25lkp@intel.com +Link: https://lore.kernel.org/r/20200907111038.5811-2-pali@kernel.org +Fixes: 5169a9851daa ("PCI: aardvark: Issue PERST via GPIO") +Reported-by: kernel test robot +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -12,7 +12,7 @@ + */ + + #include +-#include ++#include + #include + #include + #include diff --git a/queue-4.14/pci-aardvark-fix-i-o-space-page-leak.patch b/queue-4.14/pci-aardvark-fix-i-o-space-page-leak.patch new file mode 100644 index 00000000000..a0583b32674 --- /dev/null +++ b/queue-4.14/pci-aardvark-fix-i-o-space-page-leak.patch @@ -0,0 +1,92 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:10 +0100 +Subject: PCI: aardvark: Fix I/O space page leak +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Sergei Shtylyov" , "Lorenzo Pieralisi" , "Bjorn Helgaas" , "Thomas Petazzoni" , "Linus Walleij" , "Marek Behún" +Message-ID: <20211124224933.24275-2-kabel@kernel.org> + +From: Sergei Shtylyov + +commit 1df3e5b3feebf29a3ecfa0c0f06f79544ca573e4 upstream. + +When testing the R-Car PCIe driver on the Condor board, if the PCIe PHY +driver was left disabled, the kernel crashed with this BUG: + + kernel BUG at lib/ioremap.c:72! + Internal error: Oops - BUG: 0 [#1] PREEMPT SMP + Modules linked in: + CPU: 0 PID: 39 Comm: kworker/0:1 Not tainted 4.17.0-dirty #1092 + Hardware name: Renesas Condor board based on r8a77980 (DT) + Workqueue: events deferred_probe_work_func + pstate: 80000005 (Nzcv daif -PAN -UAO) + pc : ioremap_page_range+0x370/0x3c8 + lr : ioremap_page_range+0x40/0x3c8 + sp : ffff000008da39e0 + x29: ffff000008da39e0 x28: 00e8000000000f07 + x27: ffff7dfffee00000 x26: 0140000000000000 + x25: ffff7dfffef00000 x24: 00000000000fe100 + x23: ffff80007b906000 x22: ffff000008ab8000 + x21: ffff000008bb1d58 x20: ffff7dfffef00000 + x19: ffff800009c30fb8 x18: 0000000000000001 + x17: 00000000000152d0 x16: 00000000014012d0 + x15: 0000000000000000 x14: 0720072007200720 + x13: 0720072007200720 x12: 0720072007200720 + x11: 0720072007300730 x10: 00000000000000ae + x9 : 0000000000000000 x8 : ffff7dffff000000 + x7 : 0000000000000000 x6 : 0000000000000100 + x5 : 0000000000000000 x4 : 000000007b906000 + x3 : ffff80007c61a880 x2 : ffff7dfffeefffff + x1 : 0000000040000000 x0 : 00e80000fe100f07 + Process kworker/0:1 (pid: 39, stack limit = 0x (ptrval)) + Call trace: + ioremap_page_range+0x370/0x3c8 + pci_remap_iospace+0x7c/0xac + pci_parse_request_of_pci_ranges+0x13c/0x190 + rcar_pcie_probe+0x4c/0xb04 + platform_drv_probe+0x50/0xbc + driver_probe_device+0x21c/0x308 + __device_attach_driver+0x98/0xc8 + bus_for_each_drv+0x54/0x94 + __device_attach+0xc4/0x12c + device_initial_probe+0x10/0x18 + bus_probe_device+0x90/0x98 + deferred_probe_work_func+0xb0/0x150 + process_one_work+0x12c/0x29c + worker_thread+0x200/0x3fc + kthread+0x108/0x134 + ret_from_fork+0x10/0x18 + Code: f9004ba2 54000080 aa0003fb 17ffff48 (d4210000) + +It turned out that pci_remap_iospace() wasn't undone when the driver's +probe failed, and since devm_phy_optional_get() returned -EPROBE_DEFER, +the probe was retried, finally causing the BUG due to trying to remap +already remapped pages. + +The Aardvark PCI controller driver has the same issue. +Replace pci_remap_iospace() with its devm_ managed version to fix the bug. + +Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Sergei Shtylyov +[lorenzo.pieralisi@arm.com: updated the commit log] +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Bjorn Helgaas +Reviewed-by: Thomas Petazzoni +Reviewed-by: Linus Walleij +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -932,7 +932,7 @@ static int advk_pcie_parse_request_of_pc + 0, 0xF8000000, 0, + lower_32_bits(res->start), + OB_PCIE_IO); +- err = pci_remap_iospace(res, iobase); ++ err = devm_pci_remap_iospace(dev, res, iobase); + if (err) { + dev_warn(dev, "error %d: failed to map resource %pR\n", + err, res); diff --git a/queue-4.14/pci-aardvark-fix-link-training.patch b/queue-4.14/pci-aardvark-fix-link-training.patch new file mode 100644 index 00000000000..4efda38b150 --- /dev/null +++ b/queue-4.14/pci-aardvark-fix-link-training.patch @@ -0,0 +1,319 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:27 +0100 +Subject: PCI: aardvark: Fix link training +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" , "Lorenzo Pieralisi" +Message-ID: <20211124224933.24275-19-kabel@kernel.org> + +From: Pali Rohár + +commit f76b36d40beee0a13aa8f6aa011df0d7cbbb8a7f upstream. + +Fix multiple link training issues in aardvark driver. The main reason of +these issues was misunderstanding of what certain registers do, since their +names and comments were misleading: before commit 96be36dbffac ("PCI: +aardvark: Replace custom macros by standard linux/pci_regs.h macros"), the +pci-aardvark.c driver used custom macros for accessing standard PCIe Root +Bridge registers, and misleading comments did not help to understand what +the code was really doing. + +After doing more tests and experiments I've come to the conclusion that the +SPEED_GEN register in aardvark sets the PCIe revision / generation +compliance and forces maximal link speed. Both GEN3 and GEN2 values set the +read-only PCI_EXP_FLAGS_VERS bits (PCIe capabilities version of Root +Bridge) to value 2, while GEN1 value sets PCI_EXP_FLAGS_VERS to 1, which +matches with PCI Express specifications revisions 3, 2 and 1 respectively. +Changing SPEED_GEN also sets the read-only bits PCI_EXP_LNKCAP_SLS and +PCI_EXP_LNKCAP2_SLS to corresponding speed. + +(Note that PCI Express rev 1 specification does not define PCI_EXP_LNKCAP2 + and PCI_EXP_LNKCTL2 registers and when SPEED_GEN is set to GEN1 (which + also sets PCI_EXP_FLAGS_VERS set to 1), lspci cannot access + PCI_EXP_LNKCAP2 and PCI_EXP_LNKCTL2 registers.) + +Changing PCIe link speed can be done via PCI_EXP_LNKCTL2_TLS bits of +PCI_EXP_LNKCTL2 register. Armada 3700 Functional Specifications says that +the default value of PCI_EXP_LNKCTL2_TLS is based on SPEED_GEN value, but +tests showed that the default value is always 8.0 GT/s, independently of +speed set by SPEED_GEN. So after setting SPEED_GEN, we must also set value +in PCI_EXP_LNKCTL2 register via PCI_EXP_LNKCTL2_TLS bits. + +Triggering PCI_EXP_LNKCTL_RL bit immediately after setting LINK_TRAINING_EN +bit actually doesn't do anything. Tests have shown that a delay is needed +after enabling LINK_TRAINING_EN bit. As triggering PCI_EXP_LNKCTL_RL +currently does nothing, remove it. + +Commit 43fc679ced18 ("PCI: aardvark: Improve link training") introduced +code which sets SPEED_GEN register based on negotiated link speed from +PCI_EXP_LNKSTA_CLS bits of PCI_EXP_LNKSTA register. This code was added to +fix detection of Compex WLE900VX (Atheros QCA9880) WiFi GEN1 PCIe cards, as +otherwise these cards were "invisible" on PCIe bus (probably because they +crashed). But apparently more people reported the same issues with these +cards also with other PCIe controllers [1] and I was able to reproduce this +issue also with other "noname" WiFi cards based on Atheros QCA9890 chip +(with the same PCI vendor/device ids as Atheros QCA9880). So this is not an +issue in aardvark but rather an issue in Atheros QCA98xx chips. Also, this +issue only exists if the kernel is compiled with PCIe ASPM support, and a +generic workaround for this is to change PCIe Bridge to 2.5 GT/s link speed +via PCI_EXP_LNKCTL2_TLS_2_5GT bits in PCI_EXP_LNKCTL2 register [2], before +triggering PCI_EXP_LNKCTL_RL bit. This workaround also works when SPEED_GEN +is set to value GEN2 (5 GT/s). So remove this hack completely in the +aardvark driver and always set SPEED_GEN to value from 'max-link-speed' DT +property. Fix for Atheros QCA98xx chips is handled separately by patch [2]. + +These two things (code for triggering PCI_EXP_LNKCTL_RL bit and changing +SPEED_GEN value) also explain why commit 6964494582f5 ("PCI: aardvark: +Train link immediately after enabling training") somehow fixed detection of +those problematic Compex cards with Atheros chips: if triggering link +retraining (via PCI_EXP_LNKCTL_RL bit) was done immediately after enabling +link training (via LINK_TRAINING_EN), it did nothing. If there was a +specific delay, aardvark HW already initialized PCIe link and therefore +triggering link retraining caused the above issue. Compex cards triggered +link down event and disappeared from the PCIe bus. + +Commit f4c7d053d7f7 ("PCI: aardvark: Wait for endpoint to be ready before +training link") added 100ms sleep before calling 'Start link training' +command and explained that it is a requirement of PCI Express +specification. But the code after this 100ms sleep was not doing 'Start +link training', rather it triggered PCI_EXP_LNKCTL_RL bit via PCIe Root +Bridge to put link into Recovery state. + +The required delay after fundamental reset is already done in function +advk_pcie_wait_for_link() which also checks whether PCIe link is up. +So after removing the code which triggers PCI_EXP_LNKCTL_RL bit on PCIe +Root Bridge, there is no need to wait 100ms again. Remove the extra +msleep() call and update comment about the delay required by the PCI +Express specification. + +According to Marvell Armada 3700 Functional Specifications, Link training +should be enabled via aardvark register LINK_TRAINING_EN after selecting +PCIe generation and x1 lane. There is no need to disable it prior resetting +card via PERST# signal. This disabling code was introduced in commit +5169a9851daa ("PCI: aardvark: Issue PERST via GPIO") as a workaround for +some Atheros cards. It turns out that this also is Atheros specific issue +and affects any PCIe controller, not only aardvark. Moreover this Atheros +issue was triggered by juggling with PCI_EXP_LNKCTL_RL, LINK_TRAINING_EN +and SPEED_GEN bits interleaved with sleeps. Now, after removing triggering +PCI_EXP_LNKCTL_RL, there is no need to explicitly disable LINK_TRAINING_EN +bit. So remove this code too. The problematic Compex cards described in +previous git commits are correctly detected in advk_pcie_train_link() +function even after applying all these changes. + +Note that with this patch, and also prior this patch, some NVMe disks which +support PCIe GEN3 with 8 GT/s speed are negotiated only at the lowest link +speed 2.5 GT/s, independently of SPEED_GEN value. After manually triggering +PCI_EXP_LNKCTL_RL bit (e.g. from userspace via setpci), these NVMe disks +change link speed to 5 GT/s when SPEED_GEN was configured to GEN2. This +issue first needs to be properly investigated. I will send a fix in the +future. + +On the other hand, some other GEN2 PCIe cards with 5 GT/s speed are +autonomously by HW autonegotiated at full 5 GT/s speed without need of any +software interaction. + +Armada 3700 Functional Specifications describes the following steps for +link training: set SPEED_GEN to GEN2, enable LINK_TRAINING_EN, poll until +link training is complete, trigger PCI_EXP_LNKCTL_RL, poll until signal +rate is 5 GT/s, poll until link training is complete, enable ASPM L0s. + +The requirement for triggering PCI_EXP_LNKCTL_RL can be explained by the +need to achieve 5 GT/s speed (as changing link speed is done by throw to +recovery state entered by PCI_EXP_LNKCTL_RL) or maybe as a part of enabling +ASPM L0s (but in this case ASPM L0s should have been enabled prior +PCI_EXP_LNKCTL_RL). + +It is unknown why the original pci-aardvark.c driver was triggering +PCI_EXP_LNKCTL_RL bit before waiting for the link to be up. This does not +align with neither PCIe base specifications nor with Armada 3700 Functional +Specification. (Note that in older versions of aardvark, this bit was +called incorrectly PCIE_CORE_LINK_TRAINING, so this may be the reason.) + +It is also unknown why Armada 3700 Functional Specification says that it is +needed to trigger PCI_EXP_LNKCTL_RL for GEN2 mode, as according to PCIe +base specification 5 GT/s speed negotiation is supposed to be entirely +autonomous, even if initial speed is 2.5 GT/s. + +[1] - https://lore.kernel.org/linux-pci/87h7l8axqp.fsf@toke.dk/ +[2] - https://lore.kernel.org/linux-pci/20210326124326.21163-1-pali@kernel.org/ + +Link: https://lore.kernel.org/r/20211005180952.6812-12-kabel@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 119 +++++++++++----------------------------- + 1 file changed, 35 insertions(+), 84 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -248,11 +248,6 @@ static inline u32 advk_readl(struct advk + return readl(pcie->base + reg); + } + +-static inline u16 advk_read16(struct advk_pcie *pcie, u64 reg) +-{ +- return advk_readl(pcie, (reg & ~0x3)) >> ((reg & 0x3) * 8); +-} +- + static int advk_pcie_link_up(struct advk_pcie *pcie) + { + u32 val, ltssm_state; +@@ -279,23 +274,9 @@ static int advk_pcie_wait_for_link(struc + + static void advk_pcie_issue_perst(struct advk_pcie *pcie) + { +- u32 reg; +- + if (!pcie->reset_gpio) + return; + +- /* +- * As required by PCI Express spec (PCI Express Base Specification, REV. +- * 4.0 PCI Express, February 19 2014, 6.6.1 Conventional Reset) a delay +- * for at least 100ms after de-asserting PERST# signal is needed before +- * link training is enabled. So ensure that link training is disabled +- * prior de-asserting PERST# signal to fulfill that PCI Express spec +- * requirement. +- */ +- reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); +- reg &= ~LINK_TRAINING_EN; +- advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); +- + /* 10ms delay is needed for some cards */ + dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n"); + gpiod_set_value_cansleep(pcie->reset_gpio, 1); +@@ -303,54 +284,47 @@ static void advk_pcie_issue_perst(struct + gpiod_set_value_cansleep(pcie->reset_gpio, 0); + } + +-static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen) ++static void advk_pcie_train_link(struct advk_pcie *pcie) + { +- int ret, neg_gen; ++ struct device *dev = &pcie->pdev->dev; + u32 reg; ++ int ret; + +- /* Setup link speed */ ++ /* ++ * Setup PCIe rev / gen compliance based on device tree property ++ * 'max-link-speed' which also forces maximal link speed. ++ */ + reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); + reg &= ~PCIE_GEN_SEL_MSK; +- if (gen == 3) ++ if (pcie->link_gen == 3) + reg |= SPEED_GEN_3; +- else if (gen == 2) ++ else if (pcie->link_gen == 2) + reg |= SPEED_GEN_2; + else + reg |= SPEED_GEN_1; + advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); + + /* +- * Enable link training. This is not needed in every call to this +- * function, just once suffices, but it does not break anything either. +- */ ++ * Set maximal link speed value also into PCIe Link Control 2 register. ++ * Armada 3700 Functional Specification says that default value is based ++ * on SPEED_GEN but tests showed that default value is always 8.0 GT/s. ++ */ ++ reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2); ++ reg &= ~PCI_EXP_LNKCTL2_TLS; ++ if (pcie->link_gen == 3) ++ reg |= PCI_EXP_LNKCTL2_TLS_8_0GT; ++ else if (pcie->link_gen == 2) ++ reg |= PCI_EXP_LNKCTL2_TLS_5_0GT; ++ else ++ reg |= PCI_EXP_LNKCTL2_TLS_2_5GT; ++ advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2); ++ ++ /* Enable link training after selecting PCIe generation */ + reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); + reg |= LINK_TRAINING_EN; + advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); + + /* +- * Start link training immediately after enabling it. +- * This solves problems for some buggy cards. +- */ +- reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL); +- reg |= PCI_EXP_LNKCTL_RL; +- advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL); +- +- ret = advk_pcie_wait_for_link(pcie); +- if (ret) +- return ret; +- +- reg = advk_read16(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKSTA); +- neg_gen = reg & PCI_EXP_LNKSTA_CLS; +- +- return neg_gen; +-} +- +-static void advk_pcie_train_link(struct advk_pcie *pcie) +-{ +- struct device *dev = &pcie->pdev->dev; +- int neg_gen = -1, gen; +- +- /* + * Reset PCIe card via PERST# signal. Some cards are not detected + * during link training when they are in some non-initial state. + */ +@@ -360,41 +334,18 @@ static void advk_pcie_train_link(struct + * PERST# signal could have been asserted by pinctrl subsystem before + * probe() callback has been called or issued explicitly by reset gpio + * function advk_pcie_issue_perst(), making the endpoint going into +- * fundamental reset. As required by PCI Express spec a delay for at +- * least 100ms after such a reset before link training is needed. +- */ +- msleep(PCI_PM_D3COLD_WAIT); +- +- /* +- * Try link training at link gen specified by device tree property +- * 'max-link-speed'. If this fails, iteratively train at lower gen. +- */ +- for (gen = pcie->link_gen; gen > 0; --gen) { +- neg_gen = advk_pcie_train_at_gen(pcie, gen); +- if (neg_gen > 0) +- break; +- } +- +- if (neg_gen < 0) +- goto err; +- +- /* +- * After successful training if negotiated gen is lower than requested, +- * train again on negotiated gen. This solves some stability issues for +- * some buggy gen1 cards. ++ * fundamental reset. As required by PCI Express spec (PCI Express ++ * Base Specification, REV. 4.0 PCI Express, February 19 2014, 6.6.1 ++ * Conventional Reset) a delay for at least 100ms after such a reset ++ * before sending a Configuration Request to the device is needed. ++ * So wait until PCIe link is up. Function advk_pcie_wait_for_link() ++ * waits for link at least 900ms. + */ +- if (neg_gen < gen) { +- gen = neg_gen; +- neg_gen = advk_pcie_train_at_gen(pcie, gen); +- } +- +- if (neg_gen == gen) { +- dev_info(dev, "link up at gen %i\n", gen); +- return; +- } +- +-err: +- dev_err(dev, "link never came up\n"); ++ ret = advk_pcie_wait_for_link(pcie); ++ if (ret < 0) ++ dev_err(dev, "link never came up\n"); ++ else ++ dev_info(dev, "link up\n"); + } + + /* diff --git a/queue-4.14/pci-aardvark-fix-pcie-max-payload-size-setting.patch b/queue-4.14/pci-aardvark-fix-pcie-max-payload-size-setting.patch new file mode 100644 index 00000000000..0111f0ff468 --- /dev/null +++ b/queue-4.14/pci-aardvark-fix-pcie-max-payload-size-setting.patch @@ -0,0 +1,51 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:25 +0100 +Subject: PCI: aardvark: Fix PCIe Max Payload Size setting +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" , "Lorenzo Pieralisi" +Message-ID: <20211124224933.24275-17-kabel@kernel.org> + +From: Pali Rohár + +commit a4e17d65dafdd3513042d8f00404c9b6068a825c upstream. + +Change PCIe Max Payload Size setting in PCIe Device Control register to 512 +bytes to align with PCIe Link Initialization sequence as defined in Marvell +Armada 3700 Functional Specification. According to the specification, +maximal Max Payload Size supported by this device is 512 bytes. + +Without this kernel prints suspicious line: + + pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 256 (was 16384, max 512) + +With this change it changes to: + + pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 256 (was 512, max 512) + +Link: https://lore.kernel.org/r/20211005180952.6812-3-kabel@kernel.org +Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Cc: stable@vger.kernel.org +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -453,8 +453,9 @@ static void advk_pcie_setup_hw(struct ad + reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL); + reg &= ~PCI_EXP_DEVCTL_RELAX_EN; + reg &= ~PCI_EXP_DEVCTL_NOSNOOP_EN; ++ reg &= ~PCI_EXP_DEVCTL_PAYLOAD; + reg &= ~PCI_EXP_DEVCTL_READRQ; +- reg |= PCI_EXP_DEVCTL_PAYLOAD; /* Set max payload size */ ++ reg |= PCI_EXP_DEVCTL_PAYLOAD_512B; + reg |= PCI_EXP_DEVCTL_READRQ_512B; + advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL); + diff --git a/queue-4.14/pci-aardvark-improve-link-training.patch b/queue-4.14/pci-aardvark-improve-link-training.patch new file mode 100644 index 00000000000..24f2dc55d1d --- /dev/null +++ b/queue-4.14/pci-aardvark-improve-link-training.patch @@ -0,0 +1,214 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:14 +0100 +Subject: PCI: aardvark: Improve link training +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" , "Tomasz Maciej Nowak" , "Lorenzo Pieralisi" , "Rob Herring" , "Thomas Petazzoni" , "Marek Behún" +Message-ID: <20211124224933.24275-6-kabel@kernel.org> + +From: Marek Behún + +commit 43fc679ced18006b12d918d7a8a4af392b7fbfe7 upstream. + +Currently the aardvark driver trains link in PCIe gen2 mode. This may +cause some buggy gen1 cards (such as Compex WLE900VX) to be unstable or +even not detected. Moreover when ASPM code tries to retrain link second +time, these cards may stop responding and link goes down. If gen1 is +used this does not happen. + +Unconditionally forcing gen1 is not a good solution since it may have +performance impact on gen2 cards. + +To overcome this, read 'max-link-speed' property (as defined in PCI +device tree bindings) and use this as max gen mode. Then iteratively try +link training at this mode or lower until successful. After successful +link training choose final controller gen based on Negotiated Link Speed +from Link Status register, which should match card speed. + +Link: https://lore.kernel.org/r/20200430080625.26070-5-pali@kernel.org +Tested-by: Tomasz Maciej Nowak +Signed-off-by: Pali Rohár +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Rob Herring +Acked-by: Thomas Petazzoni +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 114 +++++++++++++++++++++++++++++++--------- + 1 file changed, 89 insertions(+), 25 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -36,6 +36,7 @@ + #define PCIE_CORE_LINK_CTRL_STAT_REG 0xd0 + #define PCIE_CORE_LINK_L0S_ENTRY BIT(0) + #define PCIE_CORE_LINK_TRAINING BIT(5) ++#define PCIE_CORE_LINK_SPEED_SHIFT 16 + #define PCIE_CORE_LINK_WIDTH_SHIFT 20 + #define PCIE_CORE_ERR_CAPCTL_REG 0x118 + #define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX BIT(5) +@@ -212,6 +213,7 @@ struct advk_pcie { + struct mutex msi_used_lock; + u16 msi_msg; + int root_bus_nr; ++ int link_gen; + }; + + static inline void advk_writel(struct advk_pcie *pcie, u32 val, u64 reg) +@@ -235,20 +237,16 @@ static int advk_pcie_link_up(struct advk + + static int advk_pcie_wait_for_link(struct advk_pcie *pcie) + { +- struct device *dev = &pcie->pdev->dev; + int retries; + + /* check if the link is up or not */ + for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) { +- if (advk_pcie_link_up(pcie)) { +- dev_info(dev, "link up\n"); ++ if (advk_pcie_link_up(pcie)) + return 0; +- } + + usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX); + } + +- dev_err(dev, "link never came up\n"); + return -ETIMEDOUT; + } + +@@ -272,6 +270,85 @@ static void advk_pcie_set_ob_win(struct + advk_writel(pcie, match_ls | BIT(0), OB_WIN_MATCH_LS(win_num)); + } + ++static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen) ++{ ++ int ret, neg_gen; ++ u32 reg; ++ ++ /* Setup link speed */ ++ reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); ++ reg &= ~PCIE_GEN_SEL_MSK; ++ if (gen == 3) ++ reg |= SPEED_GEN_3; ++ else if (gen == 2) ++ reg |= SPEED_GEN_2; ++ else ++ reg |= SPEED_GEN_1; ++ advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); ++ ++ /* ++ * Enable link training. This is not needed in every call to this ++ * function, just once suffices, but it does not break anything either. ++ */ ++ reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); ++ reg |= LINK_TRAINING_EN; ++ advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); ++ ++ /* ++ * Start link training immediately after enabling it. ++ * This solves problems for some buggy cards. ++ */ ++ reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG); ++ reg |= PCIE_CORE_LINK_TRAINING; ++ advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG); ++ ++ ret = advk_pcie_wait_for_link(pcie); ++ if (ret) ++ return ret; ++ ++ reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG); ++ neg_gen = (reg >> PCIE_CORE_LINK_SPEED_SHIFT) & 0xf; ++ ++ return neg_gen; ++} ++ ++static void advk_pcie_train_link(struct advk_pcie *pcie) ++{ ++ struct device *dev = &pcie->pdev->dev; ++ int neg_gen = -1, gen; ++ ++ /* ++ * Try link training at link gen specified by device tree property ++ * 'max-link-speed'. If this fails, iteratively train at lower gen. ++ */ ++ for (gen = pcie->link_gen; gen > 0; --gen) { ++ neg_gen = advk_pcie_train_at_gen(pcie, gen); ++ if (neg_gen > 0) ++ break; ++ } ++ ++ if (neg_gen < 0) ++ goto err; ++ ++ /* ++ * After successful training if negotiated gen is lower than requested, ++ * train again on negotiated gen. This solves some stability issues for ++ * some buggy gen1 cards. ++ */ ++ if (neg_gen < gen) { ++ gen = neg_gen; ++ neg_gen = advk_pcie_train_at_gen(pcie, gen); ++ } ++ ++ if (neg_gen == gen) { ++ dev_info(dev, "link up at gen %i\n", gen); ++ return; ++ } ++ ++err: ++ dev_err(dev, "link never came up\n"); ++} ++ + static void advk_pcie_setup_hw(struct advk_pcie *pcie) + { + u32 reg; +@@ -312,12 +389,6 @@ static void advk_pcie_setup_hw(struct ad + PCIE_CORE_CTRL2_TD_ENABLE; + advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG); + +- /* Set GEN2 */ +- reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); +- reg &= ~PCIE_GEN_SEL_MSK; +- reg |= SPEED_GEN_2; +- advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); +- + /* Set lane X1 */ + reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); + reg &= ~LANE_CNT_MSK; +@@ -365,20 +436,7 @@ static void advk_pcie_setup_hw(struct ad + */ + msleep(PCI_PM_D3COLD_WAIT); + +- /* Enable link training */ +- reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); +- reg |= LINK_TRAINING_EN; +- advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); +- +- /* +- * Start link training immediately after enabling it. +- * This solves problems for some buggy cards. +- */ +- reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG); +- reg |= PCIE_CORE_LINK_TRAINING; +- advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG); +- +- advk_pcie_wait_for_link(pcie); ++ advk_pcie_train_link(pcie); + + reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); + reg |= PCIE_CORE_CMD_MEM_ACCESS_EN | +@@ -1017,6 +1075,12 @@ static int advk_pcie_probe(struct platfo + return ret; + } + ++ ret = of_pci_get_max_link_speed(dev->of_node); ++ if (ret <= 0 || ret > 3) ++ pcie->link_gen = 3; ++ else ++ pcie->link_gen = ret; ++ + advk_pcie_setup_hw(pcie); + + ret = advk_pcie_init_irq_domain(pcie); diff --git a/queue-4.14/pci-aardvark-indicate-error-in-val-when-config-read-fails.patch b/queue-4.14/pci-aardvark-indicate-error-in-val-when-config-read-fails.patch new file mode 100644 index 00000000000..23764a0ff09 --- /dev/null +++ b/queue-4.14/pci-aardvark-indicate-error-in-val-when-config-read-fails.patch @@ -0,0 +1,44 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:17 +0100 +Subject: PCI: aardvark: Indicate error in 'val' when config read fails +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Bjorn Helgaas" , "Lorenzo Pieralisi" , "Marek Behún" +Message-ID: <20211124224933.24275-9-kabel@kernel.org> + +From: Pali Rohár + +commit b1bd5714472cc72e14409f5659b154c765a76c65 upstream. + +Most callers of config read do not check for return value. But most of the +ones that do, checks for error indication in 'val' variable. + +This patch updates error handling in advk_pcie_rd_conf() function. If PIO +transfer fails then 'val' variable is set to 0xffffffff which indicates +failture. + +Link: https://lore.kernel.org/r/20200528162604.GA323482@bjorn-Precision-5520 +Link: https://lore.kernel.org/r/20200601130315.18895-1-pali@kernel.org +Reported-by: Bjorn Helgaas +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -631,8 +631,10 @@ static int advk_pcie_rd_conf(struct pci_ + advk_writel(pcie, 1, PIO_START); + + ret = advk_pcie_wait_pio(pcie); +- if (ret < 0) ++ if (ret < 0) { ++ *val = 0xffffffff; + return PCIBIOS_SET_FAILED; ++ } + + /* Check PIO status and get the read result */ + ret = advk_pcie_check_pio_status(pcie, val); diff --git a/queue-4.14/pci-aardvark-introduce-an-advk_pcie_valid_device-helper.patch b/queue-4.14/pci-aardvark-introduce-an-advk_pcie_valid_device-helper.patch new file mode 100644 index 00000000000..af7f9e0327f --- /dev/null +++ b/queue-4.14/pci-aardvark-introduce-an-advk_pcie_valid_device-helper.patch @@ -0,0 +1,61 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:18 +0100 +Subject: PCI: aardvark: Introduce an advk_pcie_valid_device() helper +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Thomas Petazzoni" , "Lorenzo Pieralisi" , "Marek Behún" +Message-ID: <20211124224933.24275-10-kabel@kernel.org> + +From: Thomas Petazzoni + +commit 248d4e59616c632f37f04c233eec6d5008384926 upstream. + +In other to mimic other PCIe host controller drivers, introduce an +advk_pcie_valid_device() helper, used in the configuration read/write +functions. + +Signed-off-by: Thomas Petazzoni +[lorenzo.pieralisi@arm.com: updated host->controller dir move] +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -592,6 +592,15 @@ static bool advk_pcie_pio_is_running(str + return false; + } + ++static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus, ++ int devfn) ++{ ++ if ((bus->number == pcie->root_bus_nr) && PCI_SLOT(devfn) != 0) ++ return false; ++ ++ return true; ++} ++ + static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn, + int where, int size, u32 *val) + { +@@ -599,7 +608,7 @@ static int advk_pcie_rd_conf(struct pci_ + u32 reg; + int ret; + +- if ((bus->number == pcie->root_bus_nr) && PCI_SLOT(devfn) != 0) { ++ if (!advk_pcie_valid_device(pcie, bus, devfn)) { + *val = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } +@@ -660,7 +669,7 @@ static int advk_pcie_wr_conf(struct pci_ + int offset; + int ret; + +- if ((bus->number == pcie->root_bus_nr) && PCI_SLOT(devfn) != 0) ++ if (!advk_pcie_valid_device(pcie, bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (where % size) diff --git a/queue-4.14/pci-aardvark-issue-perst-via-gpio.patch b/queue-4.14/pci-aardvark-issue-perst-via-gpio.patch new file mode 100644 index 00000000000..bf361068695 --- /dev/null +++ b/queue-4.14/pci-aardvark-issue-perst-via-gpio.patch @@ -0,0 +1,133 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:15 +0100 +Subject: PCI: aardvark: Issue PERST via GPIO +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Tomasz Maciej Nowak" , "Lorenzo Pieralisi" , "Thomas Petazzoni" , "Marek Behún" +Message-ID: <20211124224933.24275-7-kabel@kernel.org> + +From: Pali Rohár + +commit 5169a9851daaa2782a7bd2bb83d5b1bd224b2879 upstream. + +Add support for issuing PERST via GPIO specified in 'reset-gpios' +property (as described in PCI device tree bindings). + +Some buggy cards (e.g. Compex WLE900VX or WLE1216) are not detected +after reboot when PERST is not issued during driver initialization. + +If bootloader already enabled link training then issuing PERST has no +effect for some buggy cards (e.g. Compex WLE900VX) and these cards are +not detected. We therefore clear the LINK_TRAINING_EN register before. + +It was observed that Compex WLE900VX card needs to be in PERST reset +for at least 10ms if bootloader enabled link training. + +Tested on Turris MOX. + +Link: https://lore.kernel.org/r/20200430080625.26070-6-pali@kernel.org +Tested-by: Tomasz Maciej Nowak +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Acked-by: Thomas Petazzoni +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 44 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 43 insertions(+), 1 deletion(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -12,6 +12,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -20,6 +21,7 @@ + #include + #include + #include ++#include + #include + + /* PCIe core registers */ +@@ -214,6 +216,7 @@ struct advk_pcie { + u16 msi_msg; + int root_bus_nr; + int link_gen; ++ struct gpio_desc *reset_gpio; + }; + + static inline void advk_writel(struct advk_pcie *pcie, u32 val, u64 reg) +@@ -349,6 +352,25 @@ err: + dev_err(dev, "link never came up\n"); + } + ++static void advk_pcie_issue_perst(struct advk_pcie *pcie) ++{ ++ u32 reg; ++ ++ if (!pcie->reset_gpio) ++ return; ++ ++ /* PERST does not work for some cards when link training is enabled */ ++ reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); ++ reg &= ~LINK_TRAINING_EN; ++ advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); ++ ++ /* 10ms delay is needed for some cards */ ++ dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n"); ++ gpiod_set_value_cansleep(pcie->reset_gpio, 1); ++ usleep_range(10000, 11000); ++ gpiod_set_value_cansleep(pcie->reset_gpio, 0); ++} ++ + static void advk_pcie_setup_hw(struct advk_pcie *pcie) + { + u32 reg; +@@ -358,6 +380,8 @@ static void advk_pcie_setup_hw(struct ad + for (i = 0; i < 8; i++) + advk_pcie_set_ob_win(pcie, i, 0, 0, 0, 0, 0, 0, 0); + ++ advk_pcie_issue_perst(pcie); ++ + /* Set to Direct mode */ + reg = advk_readl(pcie, CTRL_CONFIG_REG); + reg &= ~(CTRL_MODE_MASK << CTRL_MODE_SHIFT); +@@ -430,7 +454,8 @@ static void advk_pcie_setup_hw(struct ad + + /* + * PERST# signal could have been asserted by pinctrl subsystem before +- * probe() callback has been called, making the endpoint going into ++ * probe() callback has been called or issued explicitly by reset gpio ++ * function advk_pcie_issue_perst(), making the endpoint going into + * fundamental reset. As required by PCI Express spec a delay for at + * least 100ms after such a reset before link training is needed. + */ +@@ -1075,6 +1100,23 @@ static int advk_pcie_probe(struct platfo + return ret; + } + ++ pcie->reset_gpio = devm_fwnode_get_index_gpiod_from_child(dev, "reset", ++ 0, ++ dev_fwnode(dev), ++ GPIOD_OUT_LOW, ++ "pcie1-reset"); ++ ret = PTR_ERR_OR_ZERO(pcie->reset_gpio); ++ if (ret) { ++ if (ret == -ENOENT) { ++ pcie->reset_gpio = NULL; ++ } else { ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get reset-gpio: %i\n", ++ ret); ++ return ret; ++ } ++ } ++ + ret = of_pci_get_max_link_speed(dev->of_node); + if (ret <= 0 || ret > 3) + pcie->link_gen = 3; diff --git a/queue-4.14/pci-aardvark-move-pcie-reset-card-code-to-advk_pcie_train_link.patch b/queue-4.14/pci-aardvark-move-pcie-reset-card-code-to-advk_pcie_train_link.patch new file mode 100644 index 00000000000..85d2b7832c5 --- /dev/null +++ b/queue-4.14/pci-aardvark-move-pcie-reset-card-code-to-advk_pcie_train_link.patch @@ -0,0 +1,133 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:21 +0100 +Subject: PCI: aardvark: Move PCIe reset card code to advk_pcie_train_link() +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" , "Lorenzo Pieralisi" , "Marek Behún" +Message-ID: <20211124224933.24275-13-kabel@kernel.org> + +From: Pali Rohár + +commit d0c6a3475b033960e85ae2bf176b14cab0a627d2 upstream. + +Move code which belongs to link training (delays and resets) into +advk_pcie_train_link() function, so everything related to link training, +including timings is at one place. + +After experiments it can be observed that link training in aardvark +hardware is very sensitive to timings and delays, so it is a good idea to +have this code at the same place as link training calls. + +This patch does not change behavior of aardvark initialization. + +Link: https://lore.kernel.org/r/20200907111038.5811-6-pali@kernel.org +Tested-by: Marek Behún +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 64 +++++++++++++++++++++------------------- + 1 file changed, 34 insertions(+), 30 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -268,6 +268,25 @@ static void advk_pcie_set_ob_win(struct + advk_writel(pcie, match_ls | BIT(0), OB_WIN_MATCH_LS(win_num)); + } + ++static void advk_pcie_issue_perst(struct advk_pcie *pcie) ++{ ++ u32 reg; ++ ++ if (!pcie->reset_gpio) ++ return; ++ ++ /* PERST does not work for some cards when link training is enabled */ ++ reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); ++ reg &= ~LINK_TRAINING_EN; ++ advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); ++ ++ /* 10ms delay is needed for some cards */ ++ dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n"); ++ gpiod_set_value_cansleep(pcie->reset_gpio, 1); ++ usleep_range(10000, 11000); ++ gpiod_set_value_cansleep(pcie->reset_gpio, 0); ++} ++ + static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen) + { + int ret, neg_gen; +@@ -316,6 +335,21 @@ static void advk_pcie_train_link(struct + int neg_gen = -1, gen; + + /* ++ * Reset PCIe card via PERST# signal. Some cards are not detected ++ * during link training when they are in some non-initial state. ++ */ ++ advk_pcie_issue_perst(pcie); ++ ++ /* ++ * PERST# signal could have been asserted by pinctrl subsystem before ++ * probe() callback has been called or issued explicitly by reset gpio ++ * function advk_pcie_issue_perst(), making the endpoint going into ++ * fundamental reset. As required by PCI Express spec a delay for at ++ * least 100ms after such a reset before link training is needed. ++ */ ++ msleep(PCI_PM_D3COLD_WAIT); ++ ++ /* + * Try link training at link gen specified by device tree property + * 'max-link-speed'. If this fails, iteratively train at lower gen. + */ +@@ -347,25 +381,6 @@ err: + dev_err(dev, "link never came up\n"); + } + +-static void advk_pcie_issue_perst(struct advk_pcie *pcie) +-{ +- u32 reg; +- +- if (!pcie->reset_gpio) +- return; +- +- /* PERST does not work for some cards when link training is enabled */ +- reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); +- reg &= ~LINK_TRAINING_EN; +- advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); +- +- /* 10ms delay is needed for some cards */ +- dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n"); +- gpiod_set_value_cansleep(pcie->reset_gpio, 1); +- usleep_range(10000, 11000); +- gpiod_set_value_cansleep(pcie->reset_gpio, 0); +-} +- + static void advk_pcie_setup_hw(struct advk_pcie *pcie) + { + u32 reg; +@@ -375,8 +390,6 @@ static void advk_pcie_setup_hw(struct ad + for (i = 0; i < 8; i++) + advk_pcie_set_ob_win(pcie, i, 0, 0, 0, 0, 0, 0, 0); + +- advk_pcie_issue_perst(pcie); +- + /* Set to Direct mode */ + reg = advk_readl(pcie, CTRL_CONFIG_REG); + reg &= ~(CTRL_MODE_MASK << CTRL_MODE_SHIFT); +@@ -448,15 +461,6 @@ static void advk_pcie_setup_hw(struct ad + reg |= PIO_CTRL_ADDR_WIN_DISABLE; + advk_writel(pcie, reg, PIO_CTRL); + +- /* +- * PERST# signal could have been asserted by pinctrl subsystem before +- * probe() callback has been called or issued explicitly by reset gpio +- * function advk_pcie_issue_perst(), making the endpoint going into +- * fundamental reset. As required by PCI Express spec a delay for at +- * least 100ms after such a reset before link training is needed. +- */ +- msleep(PCI_PM_D3COLD_WAIT); +- + advk_pcie_train_link(pcie); + + reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); diff --git a/queue-4.14/pci-aardvark-remove-pcie-outbound-window-configuration.patch b/queue-4.14/pci-aardvark-remove-pcie-outbound-window-configuration.patch new file mode 100644 index 00000000000..c09aa1ee16d --- /dev/null +++ b/queue-4.14/pci-aardvark-remove-pcie-outbound-window-configuration.patch @@ -0,0 +1,128 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:23 +0100 +Subject: PCI: aardvark: Remove PCIe outbound window configuration +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Evan Wang" , "Thomas Petazzoni" , "Lorenzo Pieralisi" , "Victor Gu" , "Nadav Haklai" , "Marek Behún" +Message-ID: <20211124224933.24275-15-kabel@kernel.org> + +From: Evan Wang + +commit 6df6ba974a55678a2c7d9a0c06eb15cde0c4b184 upstream. + +Outbound window is used to translate CPU space addresses to PCIe space +addresses when the CPU initiates PCIe transactions. + +According to the suggestion of the HW designers, the recommended +solution is to use the default outbound parameters, even though the +current outbound window setting does not cause any known functional +issue. + +This patch doesn't address any known functional issue, but aligns to +HW design guidelines, and removes code that isn't needed. + +Signed-off-by: Evan Wang +[Thomas: tweak commit log.] +Signed-off-by: Thomas Petazzoni +[lorenzo.pieralisi@arm.com: handled host->controller dir move] +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Victor Gu +Reviewed-by: Nadav Haklai +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 55 ---------------------------------------- + 1 file changed, 55 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -107,24 +107,6 @@ + #define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C) + #define PCIE_MSI_DATA_MASK GENMASK(15, 0) + +-/* PCIe window configuration */ +-#define OB_WIN_BASE_ADDR 0x4c00 +-#define OB_WIN_BLOCK_SIZE 0x20 +-#define OB_WIN_REG_ADDR(win, offset) (OB_WIN_BASE_ADDR + \ +- OB_WIN_BLOCK_SIZE * (win) + \ +- (offset)) +-#define OB_WIN_MATCH_LS(win) OB_WIN_REG_ADDR(win, 0x00) +-#define OB_WIN_MATCH_MS(win) OB_WIN_REG_ADDR(win, 0x04) +-#define OB_WIN_REMAP_LS(win) OB_WIN_REG_ADDR(win, 0x08) +-#define OB_WIN_REMAP_MS(win) OB_WIN_REG_ADDR(win, 0x0c) +-#define OB_WIN_MASK_LS(win) OB_WIN_REG_ADDR(win, 0x10) +-#define OB_WIN_MASK_MS(win) OB_WIN_REG_ADDR(win, 0x14) +-#define OB_WIN_ACTIONS(win) OB_WIN_REG_ADDR(win, 0x18) +- +-/* PCIe window types */ +-#define OB_PCIE_MEM 0x0 +-#define OB_PCIE_IO 0x4 +- + /* LMI registers base address and register offsets */ + #define LMI_BASE_ADDR 0x6000 + #define CFG_REG (LMI_BASE_ADDR + 0x0) +@@ -248,26 +230,6 @@ static int advk_pcie_wait_for_link(struc + return -ETIMEDOUT; + } + +-/* +- * Set PCIe address window register which could be used for memory +- * mapping. +- */ +-static void advk_pcie_set_ob_win(struct advk_pcie *pcie, +- u32 win_num, u32 match_ms, +- u32 match_ls, u32 mask_ms, +- u32 mask_ls, u32 remap_ms, +- u32 remap_ls, u32 action) +-{ +- advk_writel(pcie, match_ls, OB_WIN_MATCH_LS(win_num)); +- advk_writel(pcie, match_ms, OB_WIN_MATCH_MS(win_num)); +- advk_writel(pcie, mask_ms, OB_WIN_MASK_MS(win_num)); +- advk_writel(pcie, mask_ls, OB_WIN_MASK_LS(win_num)); +- advk_writel(pcie, remap_ms, OB_WIN_REMAP_MS(win_num)); +- advk_writel(pcie, remap_ls, OB_WIN_REMAP_LS(win_num)); +- advk_writel(pcie, action, OB_WIN_ACTIONS(win_num)); +- advk_writel(pcie, match_ls | BIT(0), OB_WIN_MATCH_LS(win_num)); +-} +- + static void advk_pcie_issue_perst(struct advk_pcie *pcie) + { + u32 reg; +@@ -391,11 +353,6 @@ err: + static void advk_pcie_setup_hw(struct advk_pcie *pcie) + { + u32 reg; +- int i; +- +- /* Point PCIe unit MBUS decode windows to DRAM space */ +- for (i = 0; i < 8; i++) +- advk_pcie_set_ob_win(pcie, i, 0, 0, 0, 0, 0, 0, 0); + + /* Set to Direct mode */ + reg = advk_readl(pcie, CTRL_CONFIG_REG); +@@ -1048,12 +1005,6 @@ static int advk_pcie_parse_request_of_pc + + switch (resource_type(res)) { + case IORESOURCE_IO: +- advk_pcie_set_ob_win(pcie, 1, +- upper_32_bits(res->start), +- lower_32_bits(res->start), +- 0, 0xF8000000, 0, +- lower_32_bits(res->start), +- OB_PCIE_IO); + err = devm_pci_remap_iospace(dev, res, iobase); + if (err) { + dev_warn(dev, "error %d: failed to map resource %pR\n", +@@ -1062,12 +1013,6 @@ static int advk_pcie_parse_request_of_pc + } + break; + case IORESOURCE_MEM: +- advk_pcie_set_ob_win(pcie, 0, +- upper_32_bits(res->start), +- lower_32_bits(res->start), +- 0x0, 0xF8000000, 0, +- lower_32_bits(res->start), +- (2 << 20) | OB_PCIE_MEM); + res_valid |= !(res->flags & IORESOURCE_PREFETCH); + break; + case IORESOURCE_BUS: diff --git a/queue-4.14/pci-aardvark-replace-custom-macros-by-standard-linux-pci_regs.h-macros.patch b/queue-4.14/pci-aardvark-replace-custom-macros-by-standard-linux-pci_regs.h-macros.patch new file mode 100644 index 00000000000..7ea6d5388f4 --- /dev/null +++ b/queue-4.14/pci-aardvark-replace-custom-macros-by-standard-linux-pci_regs.h-macros.patch @@ -0,0 +1,104 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:16 +0100 +Subject: PCI: aardvark: Replace custom macros by standard linux/pci_regs.h macros +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Tomasz Maciej Nowak" , "Lorenzo Pieralisi" , "Rob Herring" , "Thomas Petazzoni" , "Marek Behún" +Message-ID: <20211124224933.24275-8-kabel@kernel.org> + +From: Pali Rohár + +commit 96be36dbffacea0aa9e6ec4839583e79faa141a1 upstream. + +PCI-E capability macros are already defined in linux/pci_regs.h. +Remove their reimplementation in pcie-aardvark. + +Link: https://lore.kernel.org/r/20200430080625.26070-9-pali@kernel.org +Tested-by: Tomasz Maciej Nowak +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Rob Herring +Acked-by: Thomas Petazzoni +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 42 ++++++++++++++++++---------------------- + 1 file changed, 19 insertions(+), 23 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -29,17 +29,7 @@ + #define PCIE_CORE_CMD_IO_ACCESS_EN BIT(0) + #define PCIE_CORE_CMD_MEM_ACCESS_EN BIT(1) + #define PCIE_CORE_CMD_MEM_IO_REQ_EN BIT(2) +-#define PCIE_CORE_DEV_CTRL_STATS_REG 0xc8 +-#define PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE (0 << 4) +-#define PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT 5 +-#define PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE (0 << 11) +-#define PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT 12 +-#define PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ 0x2 +-#define PCIE_CORE_LINK_CTRL_STAT_REG 0xd0 +-#define PCIE_CORE_LINK_L0S_ENTRY BIT(0) +-#define PCIE_CORE_LINK_TRAINING BIT(5) +-#define PCIE_CORE_LINK_SPEED_SHIFT 16 +-#define PCIE_CORE_LINK_WIDTH_SHIFT 20 ++#define PCIE_CORE_PCIEXP_CAP 0xc0 + #define PCIE_CORE_ERR_CAPCTL_REG 0x118 + #define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX BIT(5) + #define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN BIT(6) +@@ -229,6 +219,11 @@ static inline u32 advk_readl(struct advk + return readl(pcie->base + reg); + } + ++static inline u16 advk_read16(struct advk_pcie *pcie, u64 reg) ++{ ++ return advk_readl(pcie, (reg & ~0x3)) >> ((reg & 0x3) * 8); ++} ++ + static int advk_pcie_link_up(struct advk_pcie *pcie) + { + u32 val, ltssm_state; +@@ -301,16 +296,16 @@ static int advk_pcie_train_at_gen(struct + * Start link training immediately after enabling it. + * This solves problems for some buggy cards. + */ +- reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG); +- reg |= PCIE_CORE_LINK_TRAINING; +- advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG); ++ reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL); ++ reg |= PCI_EXP_LNKCTL_RL; ++ advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL); + + ret = advk_pcie_wait_for_link(pcie); + if (ret) + return ret; + +- reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG); +- neg_gen = (reg >> PCIE_CORE_LINK_SPEED_SHIFT) & 0xf; ++ reg = advk_read16(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKSTA); ++ neg_gen = reg & PCI_EXP_LNKSTA_CLS; + + return neg_gen; + } +@@ -400,13 +395,14 @@ static void advk_pcie_setup_hw(struct ad + PCIE_CORE_ERR_CAPCTL_ECRC_CHCK_RCV; + advk_writel(pcie, reg, PCIE_CORE_ERR_CAPCTL_REG); + +- /* Set PCIe Device Control and Status 1 PF0 register */ +- reg = PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE | +- (7 << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) | +- PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE | +- (PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ << +- PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT); +- advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG); ++ /* Set PCIe Device Control register */ ++ reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL); ++ reg &= ~PCI_EXP_DEVCTL_RELAX_EN; ++ reg &= ~PCI_EXP_DEVCTL_NOSNOOP_EN; ++ reg &= ~PCI_EXP_DEVCTL_READRQ; ++ reg |= PCI_EXP_DEVCTL_PAYLOAD; /* Set max payload size */ ++ reg |= PCI_EXP_DEVCTL_READRQ_512B; ++ advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL); + + /* Program PCIe Control 2 to disable strict ordering */ + reg = PCIE_CORE_CTRL2_RESERVED | diff --git a/queue-4.14/pci-aardvark-train-link-immediately-after-enabling-training.patch b/queue-4.14/pci-aardvark-train-link-immediately-after-enabling-training.patch new file mode 100644 index 00000000000..5a61c358468 --- /dev/null +++ b/queue-4.14/pci-aardvark-train-link-immediately-after-enabling-training.patch @@ -0,0 +1,66 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:13 +0100 +Subject: PCI: aardvark: Train link immediately after enabling training +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Tomasz Maciej Nowak" , "Lorenzo Pieralisi" , "Rob Herring" , "Thomas Petazzoni" , "Marek Behún" +Message-ID: <20211124224933.24275-5-kabel@kernel.org> + +From: Pali Rohár + +commit 6964494582f56a3882c2c53b0edbfe99eb32b2e1 upstream. + +Adding even 100ms (PCI_PM_D3COLD_WAIT) delay between enabling link +training and starting link training causes detection issues with some +buggy cards (such as Compex WLE900VX). + +Move the code which enables link training immediately before the one +which starts link traning. + +This fixes detection issues of Compex WLE900VX card on Turris MOX after +cold boot. + +Link: https://lore.kernel.org/r/20200430080625.26070-2-pali@kernel.org +Fixes: f4c7d053d7f7 ("PCI: aardvark: Wait for endpoint to be ready...") +Tested-by: Tomasz Maciej Nowak +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Acked-by: Rob Herring +Acked-by: Thomas Petazzoni +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -324,11 +324,6 @@ static void advk_pcie_setup_hw(struct ad + reg |= LANE_COUNT_1; + advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); + +- /* Enable link training */ +- reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); +- reg |= LINK_TRAINING_EN; +- advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); +- + /* Enable MSI */ + reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG); + reg |= PCIE_CORE_CTRL2_MSI_ENABLE; +@@ -370,7 +365,15 @@ static void advk_pcie_setup_hw(struct ad + */ + msleep(PCI_PM_D3COLD_WAIT); + +- /* Start link training */ ++ /* Enable link training */ ++ reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); ++ reg |= LINK_TRAINING_EN; ++ advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); ++ ++ /* ++ * Start link training immediately after enabling it. ++ * This solves problems for some buggy cards. ++ */ + reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG); + reg |= PCIE_CORE_LINK_TRAINING; + advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG); diff --git a/queue-4.14/pci-aardvark-update-comment-about-disabling-link-training.patch b/queue-4.14/pci-aardvark-update-comment-about-disabling-link-training.patch new file mode 100644 index 00000000000..60b8ee0ff31 --- /dev/null +++ b/queue-4.14/pci-aardvark-update-comment-about-disabling-link-training.patch @@ -0,0 +1,45 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:22 +0100 +Subject: PCI: aardvark: Update comment about disabling link training +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Lorenzo Pieralisi" , "Marek Behún" +Message-ID: <20211124224933.24275-14-kabel@kernel.org> + +From: Pali Rohár + +commit 1d1cd163d0de22a4041a6f1aeabcf78f80076539 upstream. + +According to PCI Express Base Specifications (rev 4.0, 6.6.1 +"Conventional reset"), after fundamental reset a 100ms delay is needed +prior to enabling link training. + +Update comment in code to reflect this requirement. + +Link: https://lore.kernel.org/r/20201202184659.3795-1-pali@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -275,7 +275,14 @@ static void advk_pcie_issue_perst(struct + if (!pcie->reset_gpio) + return; + +- /* PERST does not work for some cards when link training is enabled */ ++ /* ++ * As required by PCI Express spec (PCI Express Base Specification, REV. ++ * 4.0 PCI Express, February 19 2014, 6.6.1 Conventional Reset) a delay ++ * for at least 100ms after de-asserting PERST# signal is needed before ++ * link training is enabled. So ensure that link training is disabled ++ * prior de-asserting PERST# signal to fulfill that PCI Express spec ++ * requirement. ++ */ + reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); + reg &= ~LINK_TRAINING_EN; + advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); diff --git a/queue-4.14/pci-aardvark-wait-for-endpoint-to-be-ready-before-training-link.patch b/queue-4.14/pci-aardvark-wait-for-endpoint-to-be-ready-before-training-link.patch new file mode 100644 index 00000000000..e835121d46d --- /dev/null +++ b/queue-4.14/pci-aardvark-wait-for-endpoint-to-be-ready-before-training-link.patch @@ -0,0 +1,58 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:12 +0100 +Subject: PCI: aardvark: Wait for endpoint to be ready before training link +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Remi Pommarel" , "Lorenzo Pieralisi" , "Thomas Petazzoni" , "Marek Behún" +Message-ID: <20211124224933.24275-4-kabel@kernel.org> + +From: Remi Pommarel + +commit f4c7d053d7f77cd5c1a1ba7c7ce085ddba13d1d7 upstream. + +When configuring pcie reset pin from gpio (e.g. initially set by +u-boot) to pcie function this pin goes low for a brief moment +asserting the PERST# signal. Thus connected device enters fundamental +reset process and link configuration can only begin after a minimal +100ms delay (see [1]). + +Because the pin configuration comes from the "default" pinctrl it is +implicitly configured before the probe callback is called: + +driver_probe_device() + really_probe() + ... + pinctrl_bind_pins() /* Here pin goes from gpio to PCIE reset + function and PERST# is asserted */ + ... + drv->probe() + +[1] "PCI Express Base Specification", REV. 4.0 + PCI Express, February 19 2014, 6.6.1 Conventional Reset + +Signed-off-by: Remi Pommarel +Signed-off-by: Lorenzo Pieralisi +Acked-by: Thomas Petazzoni +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/host/pci-aardvark.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -362,6 +362,14 @@ static void advk_pcie_setup_hw(struct ad + reg |= PIO_CTRL_ADDR_WIN_DISABLE; + advk_writel(pcie, reg, PIO_CTRL); + ++ /* ++ * PERST# signal could have been asserted by pinctrl subsystem before ++ * probe() callback has been called, making the endpoint going into ++ * fundamental reset. As required by PCI Express spec a delay for at ++ * least 100ms after such a reset before link training is needed. ++ */ ++ msleep(PCI_PM_D3COLD_WAIT); ++ + /* Start link training */ + reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG); + reg |= PCIE_CORE_LINK_TRAINING; diff --git a/queue-4.14/pci-add-pci_exp_lnkctl2_tls-macros.patch b/queue-4.14/pci-add-pci_exp_lnkctl2_tls-macros.patch new file mode 100644 index 00000000000..dd93e8508fa --- /dev/null +++ b/queue-4.14/pci-add-pci_exp_lnkctl2_tls-macros.patch @@ -0,0 +1,38 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:26 +0100 +Subject: PCI: Add PCI_EXP_LNKCTL2_TLS* macros +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Frederick Lawler" , "Bjorn Helgaas" , "Marek Behún" +Message-ID: <20211124224933.24275-18-kabel@kernel.org> + +From: Frederick Lawler + +commit c80851f6ce63a6e313f8c7b4b6eb82c67aa4497b upstream. + +The Link Control 2 register is missing macros for Target Link Speeds. Add +those in. + +Signed-off-by: Frederick Lawler +[bhelgaas: use "GT" instead of "GB"] +Signed-off-by: Bjorn Helgaas +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + include/uapi/linux/pci_regs.h | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/include/uapi/linux/pci_regs.h ++++ b/include/uapi/linux/pci_regs.h +@@ -654,6 +654,11 @@ + #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x00000008 /* Supported Speed 8.0GT/s */ + #define PCI_EXP_LNKCAP2_CROSSLINK 0x00000100 /* Crosslink supported */ + #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ ++#define PCI_EXP_LNKCTL2_TLS 0x000f ++#define PCI_EXP_LNKCTL2_TLS_2_5GT 0x0001 /* Supported Speed 2.5GT/s */ ++#define PCI_EXP_LNKCTL2_TLS_5_0GT 0x0002 /* Supported Speed 5GT/s */ ++#define PCI_EXP_LNKCTL2_TLS_8_0GT 0x0003 /* Supported Speed 8GT/s */ ++#define PCI_EXP_LNKCTL2_TLS_16_0GT 0x0004 /* Supported Speed 16GT/s */ + #define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ + #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 52 /* v2 endpoints with link end here */ + #define PCI_EXP_SLTCAP2 52 /* Slot Capabilities 2 */ diff --git a/queue-4.14/pinctrl-armada-37xx-add-missing-pin-pcie1-wakeup.patch b/queue-4.14/pinctrl-armada-37xx-add-missing-pin-pcie1-wakeup.patch new file mode 100644 index 00000000000..b656f5519b4 --- /dev/null +++ b/queue-4.14/pinctrl-armada-37xx-add-missing-pin-pcie1-wakeup.patch @@ -0,0 +1,33 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:30 +0100 +Subject: pinctrl: armada-37xx: add missing pin: PCIe1 Wakeup +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Gregory CLEMENT" , "Miquel Raynal" , "Linus Walleij" , "Marek Behún" +Message-ID: <20211124224933.24275-22-kabel@kernel.org> + +From: Gregory CLEMENT + +commit 4d98fbaacd79a82f408febb66a9c42fe42361b16 upstream. + +Declare the PCIe1 Wakeup which was initially missing. + +Signed-off-by: Gregory CLEMENT +Tested-by: Miquel Raynal +Signed-off-by: Linus Walleij +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c ++++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +@@ -185,6 +185,7 @@ static struct armada_37xx_pin_group arma + PIN_GRP_GPIO("smi", 18, 2, BIT(4), "smi"), + PIN_GRP_GPIO("pcie1", 3, 1, BIT(5), "pcie"), + PIN_GRP_GPIO("pcie1_clkreq", 4, 1, BIT(9), "pcie"), ++ PIN_GRP_GPIO("pcie1_wakeup", 5, 1, BIT(10), "pcie"), + PIN_GRP_GPIO("ptp", 20, 3, BIT(11) | BIT(12) | BIT(13), "ptp"), + PIN_GRP("ptp_clk", 21, 1, BIT(6), "ptp", "mii"), + PIN_GRP("ptp_trig", 22, 1, BIT(7), "ptp", "mii"), diff --git a/queue-4.14/pinctrl-armada-37xx-correct-mpp-definitions.patch b/queue-4.14/pinctrl-armada-37xx-correct-mpp-definitions.patch new file mode 100644 index 00000000000..78c4a0b8d5f --- /dev/null +++ b/queue-4.14/pinctrl-armada-37xx-correct-mpp-definitions.patch @@ -0,0 +1,108 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:29 +0100 +Subject: pinctrl: armada-37xx: Correct mpp definitions +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" , "Gregory CLEMENT" , "Miquel Raynal" , "Linus Walleij" , "Marek Behún" +Message-ID: <20211124224933.24275-21-kabel@kernel.org> + +From: Marek Behún + +commit 823868fceae3bac07cf5eccb128d6916e7a5ae9d upstream. + +This is a cleanup and fix of the patch by Ken Ma . + +Fix the mpp definitions according to newest revision of the +specification: + - northbridge: + fix pmic1 gpio number to 7 + fix pmic0 gpio number to 6 + - southbridge + split pcie1 group bit mask to BIT(5) and BIT(9) + fix ptp group bit mask to BIT(11) | BIT(12) | BIT(13) + add smi group with bit mask BIT(4) + +[gregory: split the pcie group in 2, as at hardware level they can be +configured separately] +Signed-off-by: Marek Behún +Signed-off-by: Gregory CLEMENT +Tested-by: Miquel Raynal +Signed-off-by: Linus Walleij +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt | 18 +++++++--- + drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 10 +++-- + 2 files changed, 19 insertions(+), 9 deletions(-) + +--- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt ++++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt +@@ -58,11 +58,11 @@ group pwm3 + - functions pwm, gpio + + group pmic1 +- - pin 17 ++ - pin 7 + - functions pmic, gpio + + group pmic0 +- - pin 16 ++ - pin 6 + - functions pmic, gpio + + group i2c2 +@@ -112,17 +112,25 @@ group usb2_drvvbus1 + - functions drvbus, gpio + + group sdio_sb +- - pins 60-64 ++ - pins 60-65 + - functions sdio, gpio + + group rgmii +- - pins 42-55 ++ - pins 42-53 + - functions mii, gpio + + group pcie1 +- - pins 39-40 ++ - pins 39 ++ - functions pcie, gpio ++ ++group pcie1_clkreq ++ - pins 40 + - functions pcie, gpio + ++group smi ++ - pins 54-55 ++ - functions smi, gpio ++ + group ptp + - pins 56-58 + - functions ptp, gpio +--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c ++++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +@@ -157,8 +157,8 @@ static struct armada_37xx_pin_group arma + PIN_GRP_GPIO("pwm1", 12, 1, BIT(4), "pwm"), + PIN_GRP_GPIO("pwm2", 13, 1, BIT(5), "pwm"), + PIN_GRP_GPIO("pwm3", 14, 1, BIT(6), "pwm"), +- PIN_GRP_GPIO("pmic1", 17, 1, BIT(7), "pmic"), +- PIN_GRP_GPIO("pmic0", 16, 1, BIT(8), "pmic"), ++ PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"), ++ PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"), + PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"), + PIN_GRP_GPIO("i2c1", 0, 2, BIT(10), "i2c"), + PIN_GRP_GPIO("spi_cs1", 17, 1, BIT(12), "spi"), +@@ -182,8 +182,10 @@ static struct armada_37xx_pin_group arma + PIN_GRP_GPIO("usb2_drvvbus1", 1, 1, BIT(1), "drvbus"), + PIN_GRP_GPIO("sdio_sb", 24, 6, BIT(2), "sdio"), + PIN_GRP_GPIO("rgmii", 6, 12, BIT(3), "mii"), +- PIN_GRP_GPIO("pcie1", 3, 2, BIT(4), "pcie"), +- PIN_GRP_GPIO("ptp", 20, 3, BIT(5), "ptp"), ++ PIN_GRP_GPIO("smi", 18, 2, BIT(4), "smi"), ++ PIN_GRP_GPIO("pcie1", 3, 1, BIT(5), "pcie"), ++ PIN_GRP_GPIO("pcie1_clkreq", 4, 1, BIT(9), "pcie"), ++ PIN_GRP_GPIO("ptp", 20, 3, BIT(11) | BIT(12) | BIT(13), "ptp"), + PIN_GRP("ptp_clk", 21, 1, BIT(6), "ptp", "mii"), + PIN_GRP("ptp_trig", 22, 1, BIT(7), "ptp", "mii"), + PIN_GRP_GPIO_3("mii_col", 23, 1, BIT(8) | BIT(14), 0, BIT(8), BIT(14), diff --git a/queue-4.14/pinctrl-armada-37xx-correct-pwm-pins-definitions.patch b/queue-4.14/pinctrl-armada-37xx-correct-pwm-pins-definitions.patch new file mode 100644 index 00000000000..9008822ee9d --- /dev/null +++ b/queue-4.14/pinctrl-armada-37xx-correct-pwm-pins-definitions.patch @@ -0,0 +1,101 @@ +From foo@baz Mon Nov 29 01:32:04 PM CET 2021 +From: "Marek Behún" +Date: Wed, 24 Nov 2021 23:49:31 +0100 +Subject: pinctrl: armada-37xx: Correct PWM pins definitions +To: Greg Kroah-Hartman , Sasha Levin +Cc: pali@kernel.org, stable@vger.kernel.org, "Marek Behún" , "Rob Herring" , "Linus Walleij" +Message-ID: <20211124224933.24275-23-kabel@kernel.org> + +From: "Marek Behún" + +commit baf8d6899b1e8906dc076ef26cc633e96a8bb0c3 upstream. + +The PWM pins on North Bridge on Armada 37xx can be configured into PWM +or GPIO functions. When in PWM function, each pin can also be configured +to drive low on 0 and tri-state on 1 (LED mode). + +The current definitions handle this by declaring two pin groups for each +pin: +- group "pwmN" with functions "pwm" and "gpio" +- group "ledN_od" ("od" for open drain) with functions "led" and "gpio" + +This is semantically incorrect. The correct definition for each pin +should be one group with three functions: "pwm", "led" and "gpio". + +Change the "pwmN" groups to support "led" function. + +Remove "ledN_od" groups. This cannot break backwards compatibility with +older device trees: no device tree uses it since there is no PWM driver +for this SOC yet. Also "ledN_od" groups are not even documented. + +Fixes: b835d6953009 ("pinctrl: armada-37xx: swap polarity on LED group") +Signed-off-by: Marek Behún +Acked-by: Rob Herring +Link: https://lore.kernel.org/r/20210719112938.27594-1-kabel@kernel.org +Signed-off-by: Linus Walleij +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt | 8 ++-- + drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 17 ++++------ + 2 files changed, 12 insertions(+), 13 deletions(-) + +--- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt ++++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt +@@ -43,19 +43,19 @@ group emmc_nb + + group pwm0 + - pin 11 (GPIO1-11) +- - functions pwm, gpio ++ - functions pwm, led, gpio + + group pwm1 + - pin 12 +- - functions pwm, gpio ++ - functions pwm, led, gpio + + group pwm2 + - pin 13 +- - functions pwm, gpio ++ - functions pwm, led, gpio + + group pwm3 + - pin 14 +- - functions pwm, gpio ++ - functions pwm, led, gpio + + group pmic1 + - pin 7 +--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c ++++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +@@ -153,10 +153,14 @@ static struct armada_37xx_pin_group arma + PIN_GRP_GPIO("jtag", 20, 5, BIT(0), "jtag"), + PIN_GRP_GPIO("sdio0", 8, 3, BIT(1), "sdio"), + PIN_GRP_GPIO("emmc_nb", 27, 9, BIT(2), "emmc"), +- PIN_GRP_GPIO("pwm0", 11, 1, BIT(3), "pwm"), +- PIN_GRP_GPIO("pwm1", 12, 1, BIT(4), "pwm"), +- PIN_GRP_GPIO("pwm2", 13, 1, BIT(5), "pwm"), +- PIN_GRP_GPIO("pwm3", 14, 1, BIT(6), "pwm"), ++ PIN_GRP_GPIO_3("pwm0", 11, 1, BIT(3) | BIT(20), 0, BIT(20), BIT(3), ++ "pwm", "led"), ++ PIN_GRP_GPIO_3("pwm1", 12, 1, BIT(4) | BIT(21), 0, BIT(21), BIT(4), ++ "pwm", "led"), ++ PIN_GRP_GPIO_3("pwm2", 13, 1, BIT(5) | BIT(22), 0, BIT(22), BIT(5), ++ "pwm", "led"), ++ PIN_GRP_GPIO_3("pwm3", 14, 1, BIT(6) | BIT(23), 0, BIT(23), BIT(6), ++ "pwm", "led"), + PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"), + PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"), + PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"), +@@ -170,11 +174,6 @@ static struct armada_37xx_pin_group arma + PIN_GRP_EXTRA("uart2", 9, 2, BIT(1) | BIT(13) | BIT(14) | BIT(19), + BIT(1) | BIT(13) | BIT(14), BIT(1) | BIT(19), + 18, 2, "gpio", "uart"), +- PIN_GRP_GPIO_2("led0_od", 11, 1, BIT(20), BIT(20), 0, "led"), +- PIN_GRP_GPIO_2("led1_od", 12, 1, BIT(21), BIT(21), 0, "led"), +- PIN_GRP_GPIO_2("led2_od", 13, 1, BIT(22), BIT(22), 0, "led"), +- PIN_GRP_GPIO_2("led3_od", 14, 1, BIT(23), BIT(23), 0, "led"), +- + }; + + static struct armada_37xx_pin_group armada_37xx_sb_groups[] = { diff --git a/queue-4.14/s390-mm-validate-vma-in-pgste-manipulation-functions.patch b/queue-4.14/s390-mm-validate-vma-in-pgste-manipulation-functions.patch new file mode 100644 index 00000000000..3a8a2bf8d5a --- /dev/null +++ b/queue-4.14/s390-mm-validate-vma-in-pgste-manipulation-functions.patch @@ -0,0 +1,86 @@ +From fe3d10024073f06f04c74b9674bd71ccc1d787cf Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Thu, 9 Sep 2021 18:22:42 +0200 +Subject: s390/mm: validate VMA in PGSTE manipulation functions + +From: David Hildenbrand + +commit fe3d10024073f06f04c74b9674bd71ccc1d787cf upstream. + +We should not walk/touch page tables outside of VMA boundaries when +holding only the mmap sem in read mode. Evil user space can modify the +VMA layout just before this function runs and e.g., trigger races with +page table removal code since commit dd2283f2605e ("mm: mmap: zap pages +with read mmap_sem in munmap"). gfn_to_hva() will only translate using +KVM memory regions, but won't validate the VMA. + +Further, we should not allocate page tables outside of VMA boundaries: if +evil user space decides to map hugetlbfs to these ranges, bad things will +happen because we suddenly have PTE or PMD page tables where we +shouldn't have them. + +Similarly, we have to check if we suddenly find a hugetlbfs VMA, before +calling get_locked_pte(). + +Fixes: 2d42f9477320 ("s390/kvm: Add PGSTE manipulation functions") +Signed-off-by: David Hildenbrand +Reviewed-by: Claudio Imbrenda +Acked-by: Heiko Carstens +Link: https://lore.kernel.org/r/20210909162248.14969-4-david@redhat.com +Signed-off-by: Christian Borntraeger +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/mm/pgtable.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/arch/s390/mm/pgtable.c ++++ b/arch/s390/mm/pgtable.c +@@ -896,6 +896,7 @@ EXPORT_SYMBOL(get_guest_storage_key); + int pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc, + unsigned long *oldpte, unsigned long *oldpgste) + { ++ struct vm_area_struct *vma; + unsigned long pgstev; + spinlock_t *ptl; + pgste_t pgste; +@@ -905,6 +906,10 @@ int pgste_perform_essa(struct mm_struct + WARN_ON_ONCE(orc > ESSA_MAX); + if (unlikely(orc > ESSA_MAX)) + return -EINVAL; ++ ++ vma = find_vma(mm, hva); ++ if (!vma || hva < vma->vm_start || is_vm_hugetlb_page(vma)) ++ return -EFAULT; + ptep = get_locked_pte(mm, hva, &ptl); + if (unlikely(!ptep)) + return -EFAULT; +@@ -997,10 +1002,14 @@ EXPORT_SYMBOL(pgste_perform_essa); + int set_pgste_bits(struct mm_struct *mm, unsigned long hva, + unsigned long bits, unsigned long value) + { ++ struct vm_area_struct *vma; + spinlock_t *ptl; + pgste_t new; + pte_t *ptep; + ++ vma = find_vma(mm, hva); ++ if (!vma || hva < vma->vm_start || is_vm_hugetlb_page(vma)) ++ return -EFAULT; + ptep = get_locked_pte(mm, hva, &ptl); + if (unlikely(!ptep)) + return -EFAULT; +@@ -1025,9 +1034,13 @@ EXPORT_SYMBOL(set_pgste_bits); + */ + int get_pgste(struct mm_struct *mm, unsigned long hva, unsigned long *pgstep) + { ++ struct vm_area_struct *vma; + spinlock_t *ptl; + pte_t *ptep; + ++ vma = find_vma(mm, hva); ++ if (!vma || hva < vma->vm_start || is_vm_hugetlb_page(vma)) ++ return -EFAULT; + ptep = get_locked_pte(mm, hva, &ptl); + if (unlikely(!ptep)) + return -EFAULT; diff --git a/queue-4.14/series b/queue-4.14/series index a6e191b4a92..0be701ddc14 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -27,3 +27,30 @@ tcp_cubic-fix-spurious-hystart-ack-train-detections-.patch mips-use-3-level-pgtable-for-64kb-page-size-on-mips_.patch net-smc-don-t-call-clcsock-shutdown-twice-when-smc-s.patch vhost-vsock-fix-incorrect-used-length-reported-to-the-guest.patch +tracing-check-pid-filtering-when-creating-events.patch +s390-mm-validate-vma-in-pgste-manipulation-functions.patch +pci-aardvark-fix-i-o-space-page-leak.patch +pci-aardvark-fix-a-leaked-reference-by-adding-missing-of_node_put.patch +pci-aardvark-wait-for-endpoint-to-be-ready-before-training-link.patch +pci-aardvark-train-link-immediately-after-enabling-training.patch +pci-aardvark-improve-link-training.patch +pci-aardvark-issue-perst-via-gpio.patch +pci-aardvark-replace-custom-macros-by-standard-linux-pci_regs.h-macros.patch +pci-aardvark-indicate-error-in-val-when-config-read-fails.patch +pci-aardvark-introduce-an-advk_pcie_valid_device-helper.patch +pci-aardvark-don-t-touch-pcie-registers-if-no-card-connected.patch +pci-aardvark-fix-compilation-on-s390.patch +pci-aardvark-move-pcie-reset-card-code-to-advk_pcie_train_link.patch +pci-aardvark-update-comment-about-disabling-link-training.patch +pci-aardvark-remove-pcie-outbound-window-configuration.patch +pci-aardvark-configure-pcie-resources-from-ranges-dt-property.patch +pci-aardvark-fix-pcie-max-payload-size-setting.patch +pci-add-pci_exp_lnkctl2_tls-macros.patch +pci-aardvark-fix-link-training.patch +pci-aardvark-fix-checking-for-link-up-via-ltssm-state.patch +pinctrl-armada-37xx-correct-mpp-definitions.patch +pinctrl-armada-37xx-add-missing-pin-pcie1-wakeup.patch +pinctrl-armada-37xx-correct-pwm-pins-definitions.patch +arm64-dts-marvell-armada-37xx-declare-pcie-reset-pin.patch +arm64-dts-marvell-armada-37xx-set-pcie_reset_pin-to-gpio-function.patch +hugetlbfs-flush-tlbs-correctly-after-huge_pmd_unshare.patch diff --git a/queue-4.14/tracing-check-pid-filtering-when-creating-events.patch b/queue-4.14/tracing-check-pid-filtering-when-creating-events.patch new file mode 100644 index 00000000000..75e783ac10d --- /dev/null +++ b/queue-4.14/tracing-check-pid-filtering-when-creating-events.patch @@ -0,0 +1,48 @@ +From 6cb206508b621a9a0a2c35b60540e399225c8243 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (VMware)" +Date: Fri, 26 Nov 2021 13:35:26 -0500 +Subject: tracing: Check pid filtering when creating events + +From: Steven Rostedt (VMware) + +commit 6cb206508b621a9a0a2c35b60540e399225c8243 upstream. + +When pid filtering is activated in an instance, all of the events trace +files for that instance has the PID_FILTER flag set. This determines +whether or not pid filtering needs to be done on the event, otherwise the +event is executed as normal. + +If pid filtering is enabled when an event is created (via a dynamic event +or modules), its flag is not updated to reflect the current state, and the +events are not filtered properly. + +Cc: stable@vger.kernel.org +Fixes: 3fdaf80f4a836 ("tracing: Implement event pid filtering") +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_events.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -2254,12 +2254,19 @@ static struct trace_event_file * + trace_create_new_event(struct trace_event_call *call, + struct trace_array *tr) + { ++ struct trace_pid_list *pid_list; + struct trace_event_file *file; + + file = kmem_cache_alloc(file_cachep, GFP_TRACE); + if (!file) + return NULL; + ++ pid_list = rcu_dereference_protected(tr->filtered_pids, ++ lockdep_is_held(&event_mutex)); ++ ++ if (pid_list) ++ file->flags |= EVENT_FILE_FL_PID_FILTER; ++ + file->event_call = call; + file->tr = tr; + atomic_set(&file->sm_ref, 0);