net/mptcp/protocol.c 977d293e23b4 ("mptcp: ensure tx skbs always have the MPTCP ext") efe686ffce01 ("mptcp: ensure tx skbs always have the MPTCP ext") same patch merged in both trees, keep net-next.
Unified · Split
| @@ -54,7 +54,7 @@ properties: · 53 unmodified lines | |||
| 54 | - const: toradex,apalis_t30 | 54 | - const: toradex,apalis_t30 |
| 55 | - const: nvidia,tegra30 | 55 | - const: nvidia,tegra30 |
| 56 | - items: | 56 | - items: |
| 57 | - const: toradex,apalis_t30-eval-v1.1 | 57 | - const: toradex,apalis_t30-v1.1-eval |
| 58 | - const: toradex,apalis_t30-eval | 58 | - const: toradex,apalis_t30-eval |
| 59 | - const: toradex,apalis_t30-v1.1 | 59 | - const: toradex,apalis_t30-v1.1 |
| 60 | - const: toradex,apalis_t30 | 60 | - const: toradex,apalis_t30 |
| @@ -9,7 +9,7 @@ function block. · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | All DISP device tree nodes must be siblings to the central MMSYS_CONFIG node. | 10 | All DISP device tree nodes must be siblings to the central MMSYS_CONFIG node. |
| 11 | For a description of the MMSYS_CONFIG binding, see | 11 | For a description of the MMSYS_CONFIG binding, see |
| 12 | Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt. | 12 | Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml. |
| 13 | 13 | ||
| 14 | DISP function blocks | 14 | DISP function blocks |
| 15 | ==================== | 15 | ==================== |
| @@ -0,0 +1,89 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/ufs/samsung,exynos-ufs.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Samsung SoC series UFS host controller Device Tree Bindings | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Alim Akhtar <alim.akhtar@samsung.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | Each Samsung UFS host controller instance should have its own node. | ||
| 14 | This binding define Samsung specific binding other then what is used | ||
| 15 | in the common ufshcd bindings | ||
| 16 | [1] Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt | ||
| 17 | |||
| 18 | properties: | ||
| 19 | |||
| 20 | compatible: | ||
| 21 | enum: | ||
| 22 | - samsung,exynos7-ufs | ||
| 23 | |||
| 24 | reg: | ||
| 25 | items: | ||
| 26 | - description: HCI register | ||
| 27 | - description: vendor specific register | ||
| 28 | - description: unipro register | ||
| 29 | - description: UFS protector register | ||
| 30 | |||
| 31 | reg-names: | ||
| 32 | items: | ||
| 33 | - const: hci | ||
| 34 | - const: vs_hci | ||
| 35 | - const: unipro | ||
| 36 | - const: ufsp | ||
| 37 | |||
| 38 | clocks: | ||
| 39 | items: | ||
| 40 | - description: ufs link core clock | ||
| 41 | - description: unipro main clock | ||
| 42 | |||
| 43 | clock-names: | ||
| 44 | items: | ||
| 45 | - const: core_clk | ||
| 46 | - const: sclk_unipro_main | ||
| 47 | |||
| 48 | interrupts: | ||
| 49 | maxItems: 1 | ||
| 50 | |||
| 51 | phys: | ||
| 52 | maxItems: 1 | ||
| 53 | |||
| 54 | phy-names: | ||
| 55 | const: ufs-phy | ||
| 56 | |||
| 57 | required: | ||
| 58 | - compatible | ||
| 59 | - reg | ||
| 60 | - interrupts | ||
| 61 | - phys | ||
| 62 | - phy-names | ||
| 63 | - clocks | ||
| 64 | - clock-names | ||
| 65 | |||
| 66 | additionalProperties: false | ||
| 67 | |||
| 68 | examples: | ||
| 69 | - | | ||
| 70 | #include <dt-bindings/interrupt-controller/arm-gic.h> | ||
| 71 | #include <dt-bindings/clock/exynos7-clk.h> | ||
| 72 | |||
| 73 | ufs: ufs@15570000 { | ||
| 74 | compatible = "samsung,exynos7-ufs"; | ||
| 75 | reg = <0x15570000 0x100>, | ||
| 76 | <0x15570100 0x100>, | ||
| 77 | <0x15571000 0x200>, | ||
| 78 | <0x15572000 0x300>; | ||
| 79 | reg-names = "hci", "vs_hci", "unipro", "ufsp"; | ||
| 80 | interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>; | ||
| 81 | clocks = <&clock_fsys1 ACLK_UFS20_LINK>, | ||
| 82 | <&clock_fsys1 SCLK_UFSUNIPRO20_USER>; | ||
| 83 | clock-names = "core_clk", "sclk_unipro_main"; | ||
| 84 | pinctrl-names = "default"; | ||
| 85 | pinctrl-0 = <&ufs_rst_n &ufs_refclk_out>; | ||
| 86 | phys = <&ufs_phy>; | ||
| 87 | phy-names = "ufs-phy"; | ||
| 88 | }; | ||
| 89 | ... | ||
| @@ -851,7 +851,7 @@ NOTES: · 850 unmodified lines | |||
| 851 | - 0x88A8 traffic will not be received unless VLAN stripping is disabled with | 851 | - 0x88A8 traffic will not be received unless VLAN stripping is disabled with |
| 852 | the following command:: | 852 | the following command:: |
| 853 | 853 | ||
| 854 | # ethool -K <ethX> rxvlan off | 854 | # ethtool -K <ethX> rxvlan off |
| 855 | 855 | ||
| 856 | - 0x88A8/0x8100 double VLANs cannot be used with 0x8100 or 0x8100/0x8100 VLANS | 856 | - 0x88A8/0x8100 double VLANs cannot be used with 0x8100 or 0x8100/0x8100 VLANS |
| 857 | configured on the same port. 0x88a8/0x8100 traffic will not be received if | 857 | configured on the same port. 0x88a8/0x8100 traffic will not be received if |
| @@ -296,7 +296,7 @@ not available. · 295 unmodified lines | |||
| 296 | Device Tree bindings and board design | 296 | Device Tree bindings and board design |
| 297 | ===================================== | 297 | ===================================== |
| 298 | 298 | ||
| 299 | This section references ``Documentation/devicetree/bindings/net/dsa/sja1105.txt`` | 299 | This section references ``Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml`` |
| 300 | and aims to showcase some potential switch caveats. | 300 | and aims to showcase some potential switch caveats. |
| 301 | 301 | ||
| 302 | RMII PHY role and out-of-band signaling | 302 | RMII PHY role and out-of-band signaling |
| @@ -2804,9 +2804,8 @@ F: arch/arm/mach-pxa/include/mach/vpac270.h · 2803 unmodified lines | |||
| 2804 | F: arch/arm/mach-pxa/vpac270.c | 2804 | F: arch/arm/mach-pxa/vpac270.c |
| 2805 | 2805 | ||
| 2806 | ARM/VT8500 ARM ARCHITECTURE | 2806 | ARM/VT8500 ARM ARCHITECTURE |
| 2807 | M: Tony Prisk <linux@prisktech.co.nz> | ||
| 2808 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 2807 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2809 | S: Maintained | 2808 | S: Orphan |
| 2810 | F: Documentation/devicetree/bindings/i2c/i2c-wmt.txt | 2809 | F: Documentation/devicetree/bindings/i2c/i2c-wmt.txt |
| 2811 | F: arch/arm/mach-vt8500/ | 2810 | F: arch/arm/mach-vt8500/ |
| 2812 | F: drivers/clocksource/timer-vt8500.c | 2811 | F: drivers/clocksource/timer-vt8500.c |
| @@ -13255,9 +13254,9 @@ F: Documentation/scsi/NinjaSCSI.rst · 10442 unmodified lines | |||
| 13255 | F: drivers/scsi/nsp32* | 13254 | F: drivers/scsi/nsp32* |
| 13256 | 13255 | ||
| 13257 | NIOS2 ARCHITECTURE | 13256 | NIOS2 ARCHITECTURE |
| 13258 | M: Ley Foon Tan <ley.foon.tan@intel.com> | 13257 | M: Dinh Nguyen <dinguyen@kernel.org> |
| 13259 | S: Maintained | 13258 | S: Maintained |
| 13260 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/lftan/nios2.git | 13259 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git |
| 13261 | F: arch/nios2/ | 13260 | F: arch/nios2/ |
| 13262 | 13261 | ||
| 13263 | NITRO ENCLAVES (NE) | 13262 | NITRO ENCLAVES (NE) |
| @@ -14342,7 +14341,8 @@ F: Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml · 1078 unmodified lines | |||
| 14342 | F: drivers/pci/controller/pci-ixp4xx.c | 14341 | F: drivers/pci/controller/pci-ixp4xx.c |
| 14343 | 14342 | ||
| 14344 | PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD) | 14343 | PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD) |
| 14345 | M: Jonathan Derrick <jonathan.derrick@intel.com> | 14344 | M: Nirmal Patel <nirmal.patel@linux.intel.com> |
| 14345 | R: Jonathan Derrick <jonathan.derrick@linux.dev> | ||
| 14346 | L: linux-pci@vger.kernel.org | 14346 | L: linux-pci@vger.kernel.org |
| 14347 | S: Supported | 14347 | S: Supported |
| 14348 | F: drivers/pci/controller/vmd.c | 14348 | F: drivers/pci/controller/vmd.c |
| @@ -16955,7 +16955,6 @@ F: drivers/misc/sgi-xp/ · 2606 unmodified lines | |||
| 16955 | 16955 | ||
| 16956 | SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS | 16956 | SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS |
| 16957 | M: Karsten Graul <kgraul@linux.ibm.com> | 16957 | M: Karsten Graul <kgraul@linux.ibm.com> |
| 16958 | M: Guvenc Gulce <guvenc@linux.ibm.com> | ||
| 16959 | L: linux-s390@vger.kernel.org | 16958 | L: linux-s390@vger.kernel.org |
| 16960 | S: Supported | 16959 | S: Supported |
| 16961 | W: http://www.ibm.com/developerworks/linux/linux390/ | 16960 | W: http://www.ibm.com/developerworks/linux/linux390/ |
| @@ -17968,10 +17967,11 @@ F: Documentation/admin-guide/svga.rst · 1006 unmodified lines | |||
| 17968 | F: arch/x86/boot/video* | 17967 | F: arch/x86/boot/video* |
| 17969 | 17968 | ||
| 17970 | SWIOTLB SUBSYSTEM | 17969 | SWIOTLB SUBSYSTEM |
| 17971 | M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 17970 | M: Christoph Hellwig <hch@infradead.org> |
| 17972 | L: iommu@lists.linux-foundation.org | 17971 | L: iommu@lists.linux-foundation.org |
| 17973 | S: Supported | 17972 | S: Supported |
| 17974 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb.git | 17973 | W: http://git.infradead.org/users/hch/dma-mapping.git |
| 17974 | T: git git://git.infradead.org/users/hch/dma-mapping.git | ||
| 17975 | F: arch/*/kernel/pci-swiotlb.c | 17975 | F: arch/*/kernel/pci-swiotlb.c |
| 17976 | F: include/linux/swiotlb.h | 17976 | F: include/linux/swiotlb.h |
| 17977 | F: kernel/dma/swiotlb.c | 17977 | F: kernel/dma/swiotlb.c |
| @@ -20474,7 +20474,6 @@ F: samples/bpf/xdpsock* · 2496 unmodified lines | |||
| 20474 | F: tools/lib/bpf/xsk* | 20474 | F: tools/lib/bpf/xsk* |
| 20475 | 20475 | ||
| 20476 | XEN BLOCK SUBSYSTEM | 20476 | XEN BLOCK SUBSYSTEM |
| 20477 | M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | ||
| 20478 | M: Roger Pau Monné <roger.pau@citrix.com> | 20477 | M: Roger Pau Monné <roger.pau@citrix.com> |
| 20479 | L: xen-devel@lists.xenproject.org (moderated for non-subscribers) | 20478 | L: xen-devel@lists.xenproject.org (moderated for non-subscribers) |
| 20480 | S: Supported | 20479 | S: Supported |
| @@ -20522,7 +20521,7 @@ S: Supported · 41 unmodified lines | |||
| 20522 | F: drivers/net/xen-netback/* | 20521 | F: drivers/net/xen-netback/* |
| 20523 | 20522 | ||
| 20524 | XEN PCI SUBSYSTEM | 20523 | XEN PCI SUBSYSTEM |
| 20525 | M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 20524 | M: Juergen Gross <jgross@suse.com> |
| 20526 | L: xen-devel@lists.xenproject.org (moderated for non-subscribers) | 20525 | L: xen-devel@lists.xenproject.org (moderated for non-subscribers) |
| 20527 | S: Supported | 20526 | S: Supported |
| 20528 | F: arch/x86/pci/*xen* | 20527 | F: arch/x86/pci/*xen* |
| @@ -20545,7 +20544,8 @@ S: Supported · 16 unmodified lines | |||
| 20545 | F: sound/xen/* | 20544 | F: sound/xen/* |
| 20546 | 20545 | ||
| 20547 | XEN SWIOTLB SUBSYSTEM | 20546 | XEN SWIOTLB SUBSYSTEM |
| 20548 | M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 20547 | M: Juergen Gross <jgross@suse.com> |
| 20548 | M: Stefano Stabellini <sstabellini@kernel.org> | ||
| 20549 | L: xen-devel@lists.xenproject.org (moderated for non-subscribers) | 20549 | L: xen-devel@lists.xenproject.org (moderated for non-subscribers) |
| 20550 | L: iommu@lists.linux-foundation.org | 20550 | L: iommu@lists.linux-foundation.org |
| 20551 | S: Supported | 20551 | S: Supported |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 5 | 2 | VERSION = 5 |
| 3 | PATCHLEVEL = 15 | 3 | PATCHLEVEL = 15 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc1 | 5 | EXTRAVERSION = -rc2 |
| 6 | NAME = Opossums on Parade | 6 | NAME = Opossums on Parade |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -20,7 +20,7 @@ config ALPHA · 19 unmodified lines | |||
| 20 | select NEED_SG_DMA_LENGTH | 20 | select NEED_SG_DMA_LENGTH |
| 21 | select VIRT_TO_BUS | 21 | select VIRT_TO_BUS |
| 22 | select GENERIC_IRQ_PROBE | 22 | select GENERIC_IRQ_PROBE |
| 23 | select GENERIC_PCI_IOMAP if PCI | 23 | select GENERIC_PCI_IOMAP |
| 24 | select AUTO_IRQ_AFFINITY if SMP | 24 | select AUTO_IRQ_AFFINITY if SMP |
| 25 | select GENERIC_IRQ_SHOW | 25 | select GENERIC_IRQ_SHOW |
| 26 | select ARCH_WANT_IPC_PARSE_VERSION | 26 | select ARCH_WANT_IPC_PARSE_VERSION |
| @@ -199,7 +199,6 @@ config ALPHA_EIGER · 172 unmodified lines | |||
| 199 | 199 | ||
| 200 | config ALPHA_JENSEN | 200 | config ALPHA_JENSEN |
| 201 | bool "Jensen" | 201 | bool "Jensen" |
| 202 | depends on BROKEN | ||
| 203 | select HAVE_EISA | 202 | select HAVE_EISA |
| 204 | help | 203 | help |
| 205 | DEC PC 150 AXP (aka Jensen): This is a very old Digital system - one | 204 | DEC PC 150 AXP (aka Jensen): This is a very old Digital system - one |
| @@ -16,3 +16,4 @@ extern void __divlu(void); · 15 unmodified lines | |||
| 16 | extern void __remlu(void); | 16 | extern void __remlu(void); |
| 17 | extern void __divqu(void); | 17 | extern void __divqu(void); |
| 18 | extern void __remqu(void); | 18 | extern void __remqu(void); |
| 19 | extern unsigned long __udiv_qrnnd(unsigned long *, unsigned long, unsigned long , unsigned long); | ||
| @@ -111,18 +111,18 @@ __EXTERN_INLINE void jensen_set_hae(unsigned long addr) · 110 unmodified lines | |||
| 111 | * convinced that I need one of the newer machines. | 111 | * convinced that I need one of the newer machines. |
| 112 | */ | 112 | */ |
| 113 | 113 | ||
| 114 | static inline unsigned int jensen_local_inb(unsigned long addr) | 114 | __EXTERN_INLINE unsigned int jensen_local_inb(unsigned long addr) |
| 115 | { | 115 | { |
| 116 | return 0xff & *(vuip)((addr << 9) + EISA_VL82C106); | 116 | return 0xff & *(vuip)((addr << 9) + EISA_VL82C106); |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static inline void jensen_local_outb(u8 b, unsigned long addr) | 119 | __EXTERN_INLINE void jensen_local_outb(u8 b, unsigned long addr) |
| 120 | { | 120 | { |
| 121 | *(vuip)((addr << 9) + EISA_VL82C106) = b; | 121 | *(vuip)((addr << 9) + EISA_VL82C106) = b; |
| 122 | mb(); | 122 | mb(); |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | static inline unsigned int jensen_bus_inb(unsigned long addr) | 125 | __EXTERN_INLINE unsigned int jensen_bus_inb(unsigned long addr) |
| 126 | { | 126 | { |
| 127 | long result; | 127 | long result; |
| 128 | 128 | ||
| @@ -131,7 +131,7 @@ static inline unsigned int jensen_bus_inb(unsigned long addr) · 2 unmodified lines | |||
| 131 | return __kernel_extbl(result, addr & 3); | 131 | return __kernel_extbl(result, addr & 3); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | static inline void jensen_bus_outb(u8 b, unsigned long addr) | 134 | __EXTERN_INLINE void jensen_bus_outb(u8 b, unsigned long addr) |
| 135 | { | 135 | { |
| 136 | jensen_set_hae(0); | 136 | jensen_set_hae(0); |
| 137 | *(vuip)((addr << 7) + EISA_IO + 0x00) = b * 0x01010101; | 137 | *(vuip)((addr << 7) + EISA_IO + 0x00) = b * 0x01010101; |
| @@ -7,6 +7,11 @@ · 6 unmodified lines | |||
| 7 | * | 7 | * |
| 8 | * Code supporting the Jensen. | 8 | * Code supporting the Jensen. |
| 9 | */ | 9 | */ |
| 10 | #define __EXTERN_INLINE | ||
| 11 | #include <asm/io.h> | ||
| 12 | #include <asm/jensen.h> | ||
| 13 | #undef __EXTERN_INLINE | ||
| 14 | |||
| 10 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 11 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 12 | #include <linux/types.h> | 17 | #include <linux/types.h> |
| @@ -17,11 +22,6 @@ · 4 unmodified lines | |||
| 17 | 22 | ||
| 18 | #include <asm/ptrace.h> | 23 | #include <asm/ptrace.h> |
| 19 | 24 | ||
| 20 | #define __EXTERN_INLINE inline | ||
| 21 | #include <asm/io.h> | ||
| 22 | #include <asm/jensen.h> | ||
| 23 | #undef __EXTERN_INLINE | ||
| 24 | |||
| 25 | #include <asm/dma.h> | 25 | #include <asm/dma.h> |
| 26 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
| 27 | #include <asm/mmu_context.h> | 27 | #include <asm/mmu_context.h> |
| @@ -14,6 +14,7 @@ ev6-$(CONFIG_ALPHA_EV6) := ev6- · 13 unmodified lines | |||
| 14 | ev67-$(CONFIG_ALPHA_EV67) := ev67- | 14 | ev67-$(CONFIG_ALPHA_EV67) := ev67- |
| 15 | 15 | ||
| 16 | lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \ | 16 | lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \ |
| 17 | udiv-qrnnd.o \ | ||
| 17 | udelay.o \ | 18 | udelay.o \ |
| 18 | $(ev6-y)memset.o \ | 19 | $(ev6-y)memset.o \ |
| 19 | $(ev6-y)memcpy.o \ | 20 | $(ev6-y)memcpy.o \ |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | |||
| 25 | # along with GCC; see the file COPYING. If not, write to the | 25 | # along with GCC; see the file COPYING. If not, write to the |
| 26 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, | 26 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
| 27 | # MA 02111-1307, USA. | 27 | # MA 02111-1307, USA. |
| 28 | #include <asm/export.h> | ||
| 28 | 29 | ||
| 29 | .set noreorder | 30 | .set noreorder |
| 30 | .set noat | 31 | .set noat |
| @@ -161,3 +162,4 @@ $Odd: · 130 unmodified lines | |||
| 161 | ret $31,($26),1 | 162 | ret $31,($26),1 |
| 162 | 163 | ||
| 163 | .end __udiv_qrnnd | 164 | .end __udiv_qrnnd |
| 165 | EXPORT_SYMBOL(__udiv_qrnnd) | ||
| @@ -7,4 +7,4 @@ ccflags-y := -w · 6 unmodified lines | |||
| 7 | 7 | ||
| 8 | obj-$(CONFIG_MATHEMU) += math-emu.o | 8 | obj-$(CONFIG_MATHEMU) += math-emu.o |
| 9 | 9 | ||
| 10 | math-emu-objs := math.o qrnnd.o | 10 | math-emu-objs := math.o |
| @@ -403,5 +403,3 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask) · 402 unmodified lines | |||
| 403 | egress: | 403 | egress: |
| 404 | return si_code; | 404 | return si_code; |
| 405 | } | 405 | } |
| 406 | |||
| 407 | EXPORT_SYMBOL(__udiv_qrnnd); | ||
| @@ -513,7 +513,7 @@ size_t sve_state_size(struct task_struct const *task) · 512 unmodified lines | |||
| 513 | void sve_alloc(struct task_struct *task) | 513 | void sve_alloc(struct task_struct *task) |
| 514 | { | 514 | { |
| 515 | if (task->thread.sve_state) { | 515 | if (task->thread.sve_state) { |
| 516 | memset(task->thread.sve_state, 0, sve_state_size(current)); | 516 | memset(task->thread.sve_state, 0, sve_state_size(task)); |
| 517 | return; | 517 | return; |
| 518 | } | 518 | } |
| 519 | 519 | ||
| @@ -18,7 +18,6 @@ · 17 unmodified lines | |||
| 18 | #include <linux/mman.h> | 18 | #include <linux/mman.h> |
| 19 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
| 20 | #include <linux/nospec.h> | 20 | #include <linux/nospec.h> |
| 21 | #include <linux/sched.h> | ||
| 22 | #include <linux/stddef.h> | 21 | #include <linux/stddef.h> |
| 23 | #include <linux/sysctl.h> | 22 | #include <linux/sysctl.h> |
| 24 | #include <linux/unistd.h> | 23 | #include <linux/unistd.h> |
| @@ -58,7 +57,7 @@ · 33 unmodified lines | |||
| 58 | 57 | ||
| 59 | #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK) | 58 | #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK) |
| 60 | #include <linux/stackprotector.h> | 59 | #include <linux/stackprotector.h> |
| 61 | unsigned long __stack_chk_guard __read_mostly; | 60 | unsigned long __stack_chk_guard __ro_after_init; |
| 62 | EXPORT_SYMBOL(__stack_chk_guard); | 61 | EXPORT_SYMBOL(__stack_chk_guard); |
| 63 | #endif | 62 | #endif |
| 64 | 63 | ||
| @@ -513,12 +513,15 @@ void ioport_unmap(void __iomem *addr) · 512 unmodified lines | |||
| 513 | } | 513 | } |
| 514 | } | 514 | } |
| 515 | 515 | ||
| 516 | #ifdef CONFIG_PCI | ||
| 516 | void pci_iounmap(struct pci_dev *dev, void __iomem * addr) | 517 | void pci_iounmap(struct pci_dev *dev, void __iomem * addr) |
| 517 | { | 518 | { |
| 518 | if (!INDIRECT_ADDR(addr)) { | 519 | if (!INDIRECT_ADDR(addr)) { |
| 519 | iounmap(addr); | 520 | iounmap(addr); |
| 520 | } | 521 | } |
| 521 | } | 522 | } |
| 523 | EXPORT_SYMBOL(pci_iounmap); | ||
| 524 | #endif | ||
| 522 | 525 | ||
| 523 | EXPORT_SYMBOL(ioread8); | 526 | EXPORT_SYMBOL(ioread8); |
| 524 | EXPORT_SYMBOL(ioread16); | 527 | EXPORT_SYMBOL(ioread16); |
| @@ -544,4 +547,3 @@ EXPORT_SYMBOL(iowrite16_rep); · 19 unmodified lines | |||
| 544 | EXPORT_SYMBOL(iowrite32_rep); | 547 | EXPORT_SYMBOL(iowrite32_rep); |
| 545 | EXPORT_SYMBOL(ioport_map); | 548 | EXPORT_SYMBOL(ioport_map); |
| 546 | EXPORT_SYMBOL(ioport_unmap); | 549 | EXPORT_SYMBOL(ioport_unmap); |
| 547 | EXPORT_SYMBOL(pci_iounmap); | ||
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | #include <asm/switch_to.h> | 18 | #include <asm/switch_to.h> |
| 19 | #include <asm/syscall.h> | 19 | #include <asm/syscall.h> |
| 20 | #include <asm/time.h> | 20 | #include <asm/time.h> |
| 21 | #include <asm/tm.h> | ||
| 21 | #include <asm/unistd.h> | 22 | #include <asm/unistd.h> |
| 22 | 23 | ||
| 23 | #if defined(CONFIG_PPC_ADV_DEBUG_REGS) && defined(CONFIG_PPC32) | 24 | #if defined(CONFIG_PPC_ADV_DEBUG_REGS) && defined(CONFIG_PPC32) |
| @@ -136,6 +137,48 @@ notrace long system_call_exception(long r3, long r4, long r5, · 112 unmodified lines | |||
| 136 | */ | 137 | */ |
| 137 | irq_soft_mask_regs_set_state(regs, IRQS_ENABLED); | 138 | irq_soft_mask_regs_set_state(regs, IRQS_ENABLED); |
| 138 | 139 | ||
| 140 | /* | ||
| 141 | * If system call is called with TM active, set _TIF_RESTOREALL to | ||
| 142 | * prevent RFSCV being used to return to userspace, because POWER9 | ||
| 143 | * TM implementation has problems with this instruction returning to | ||
| 144 | * transactional state. Final register values are not relevant because | ||
| 145 | * the transaction will be aborted upon return anyway. Or in the case | ||
| 146 | * of unsupported_scv SIGILL fault, the return state does not much | ||
| 147 | * matter because it's an edge case. | ||
| 148 | */ | ||
| 149 | if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) && | ||
| 150 | unlikely(MSR_TM_TRANSACTIONAL(regs->msr))) | ||
| 151 | current_thread_info()->flags |= _TIF_RESTOREALL; | ||
| 152 | |||
| 153 | /* | ||
| 154 | * If the system call was made with a transaction active, doom it and | ||
| 155 | * return without performing the system call. Unless it was an | ||
| 156 | * unsupported scv vector, in which case it's treated like an illegal | ||
| 157 | * instruction. | ||
| 158 | */ | ||
| 159 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
| 160 | if (unlikely(MSR_TM_TRANSACTIONAL(regs->msr)) && | ||
| 161 | !trap_is_unsupported_scv(regs)) { | ||
| 162 | /* Enable TM in the kernel, and disable EE (for scv) */ | ||
| 163 | hard_irq_disable(); | ||
| 164 | mtmsr(mfmsr() | MSR_TM); | ||
| 165 | |||
| 166 | /* tabort, this dooms the transaction, nothing else */ | ||
| 167 | asm volatile(".long 0x7c00071d | ((%0) << 16)" | ||
| 168 | :: "r"(TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT)); | ||
| 169 | |||
| 170 | /* | ||
| 171 | * Userspace will never see the return value. Execution will | ||
| 172 | * resume after the tbegin. of the aborted transaction with the | ||
| 173 | * checkpointed register state. A context switch could occur | ||
| 174 | * or signal delivered to the process before resuming the | ||
| 175 | * doomed transaction context, but that should all be handled | ||
| 176 | * as expected. | ||
| 177 | */ | ||
| 178 | return -ENOSYS; | ||
| 179 | } | ||
| 180 | #endif // CONFIG_PPC_TRANSACTIONAL_MEM | ||
| 181 | |||
| 139 | local_irq_enable(); | 182 | local_irq_enable(); |
| 140 | 183 | ||
| 141 | if (unlikely(current_thread_info()->flags & _TIF_SYSCALL_DOTRACE)) { | 184 | if (unlikely(current_thread_info()->flags & _TIF_SYSCALL_DOTRACE)) { |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | |||
| 12 | #include <asm/mmu.h> | 12 | #include <asm/mmu.h> |
| 13 | #include <asm/ppc_asm.h> | 13 | #include <asm/ppc_asm.h> |
| 14 | #include <asm/ptrace.h> | 14 | #include <asm/ptrace.h> |
| 15 | #include <asm/tm.h> | ||
| 16 | 15 | ||
| 17 | .section ".toc","aw" | 16 | .section ".toc","aw" |
| 18 | SYS_CALL_TABLE: | 17 | SYS_CALL_TABLE: |
| @@ -55,12 +54,6 @@ COMPAT_SYS_CALL_TABLE: · 36 unmodified lines | |||
| 55 | .globl system_call_vectored_\name | 54 | .globl system_call_vectored_\name |
| 56 | system_call_vectored_\name: | 55 | system_call_vectored_\name: |
| 57 | _ASM_NOKPROBE_SYMBOL(system_call_vectored_\name) | 56 | _ASM_NOKPROBE_SYMBOL(system_call_vectored_\name) |
| 58 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
| 59 | BEGIN_FTR_SECTION | ||
| 60 | extrdi. r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */ | ||
| 61 | bne tabort_syscall | ||
| 62 | END_FTR_SECTION_IFSET(CPU_FTR_TM) | ||
| 63 | #endif | ||
| 64 | SCV_INTERRUPT_TO_KERNEL | 57 | SCV_INTERRUPT_TO_KERNEL |
| 65 | mr r10,r1 | 58 | mr r10,r1 |
| 66 | ld r1,PACAKSAVE(r13) | 59 | ld r1,PACAKSAVE(r13) |
| @@ -247,12 +240,6 @@ _ASM_NOKPROBE_SYMBOL(system_call_common_real) · 180 unmodified lines | |||
| 247 | .globl system_call_common | 240 | .globl system_call_common |
| 248 | system_call_common: | 241 | system_call_common: |
| 249 | _ASM_NOKPROBE_SYMBOL(system_call_common) | 242 | _ASM_NOKPROBE_SYMBOL(system_call_common) |
| 250 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
| 251 | BEGIN_FTR_SECTION | ||
| 252 | extrdi. r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */ | ||
| 253 | bne tabort_syscall | ||
| 254 | END_FTR_SECTION_IFSET(CPU_FTR_TM) | ||
| 255 | #endif | ||
| 256 | mr r10,r1 | 243 | mr r10,r1 |
| 257 | ld r1,PACAKSAVE(r13) | 244 | ld r1,PACAKSAVE(r13) |
| 258 | std r10,0(r1) | 245 | std r10,0(r1) |
| @@ -425,34 +412,6 @@ SOFT_MASK_TABLE(.Lsyscall_rst_start, 1b) · 166 unmodified lines | |||
| 425 | RESTART_TABLE(.Lsyscall_rst_start, .Lsyscall_rst_end, syscall_restart) | 412 | RESTART_TABLE(.Lsyscall_rst_start, .Lsyscall_rst_end, syscall_restart) |
| 426 | #endif | 413 | #endif |
| 427 | 414 | ||
| 428 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
| 429 | tabort_syscall: | ||
| 430 | _ASM_NOKPROBE_SYMBOL(tabort_syscall) | ||
| 431 | /* Firstly we need to enable TM in the kernel */ | ||
| 432 | mfmsr r10 | ||
| 433 | li r9, 1 | ||
| 434 | rldimi r10, r9, MSR_TM_LG, 63-MSR_TM_LG | ||
| 435 | mtmsrd r10, 0 | ||
| 436 | |||
| 437 | /* tabort, this dooms the transaction, nothing else */ | ||
| 438 | li r9, (TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT) | ||
| 439 | TABORT(R9) | ||
| 440 | |||
| 441 | /* | ||
| 442 | * Return directly to userspace. We have corrupted user register state, | ||
| 443 | * but userspace will never see that register state. Execution will | ||
| 444 | * resume after the tbegin of the aborted transaction with the | ||
| 445 | * checkpointed register state. | ||
| 446 | */ | ||
| 447 | li r9, MSR_RI | ||
| 448 | andc r10, r10, r9 | ||
| 449 | mtmsrd r10, 1 | ||
| 450 | mtspr SPRN_SRR0, r11 | ||
| 451 | mtspr SPRN_SRR1, r12 | ||
| 452 | RFI_TO_USER | ||
| 453 | b . /* prevent speculative execution */ | ||
| 454 | #endif | ||
| 455 | |||
| 456 | /* | 415 | /* |
| 457 | * If MSR EE/RI was never enabled, IRQs not reconciled, NVGPRs not | 416 | * If MSR EE/RI was never enabled, IRQs not reconciled, NVGPRs not |
| 458 | * touched, no exit work created, then this can be used. | 417 | * touched, no exit work created, then this can be used. |
| @@ -249,6 +249,7 @@ void machine_check_queue_event(void) · 248 unmodified lines | |||
| 249 | { | 249 | { |
| 250 | int index; | 250 | int index; |
| 251 | struct machine_check_event evt; | 251 | struct machine_check_event evt; |
| 252 | unsigned long msr; | ||
| 252 | 253 | ||
| 253 | if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) | 254 | if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) |
| 254 | return; | 255 | return; |
| @@ -262,8 +263,20 @@ void machine_check_queue_event(void) · 7 unmodified lines | |||
| 262 | memcpy(&local_paca->mce_info->mce_event_queue[index], | 263 | memcpy(&local_paca->mce_info->mce_event_queue[index], |
| 263 | &evt, sizeof(evt)); | 264 | &evt, sizeof(evt)); |
| 264 | 265 | ||
| 265 | /* Queue irq work to process this event later. */ | 266 | /* |
| 266 | irq_work_queue(&mce_event_process_work); | 267 | * Queue irq work to process this event later. Before |
| 268 | * queuing the work enable translation for non radix LPAR, | ||
| 269 | * as irq_work_queue may try to access memory outside RMO | ||
| 270 | * region. | ||
| 271 | */ | ||
| 272 | if (!radix_enabled() && firmware_has_feature(FW_FEATURE_LPAR)) { | ||
| 273 | msr = mfmsr(); | ||
| 274 | mtmsr(msr | MSR_IR | MSR_DR); | ||
| 275 | irq_work_queue(&mce_event_process_work); | ||
| 276 | mtmsr(msr); | ||
| 277 | } else { | ||
| 278 | irq_work_queue(&mce_event_process_work); | ||
| 279 | } | ||
| 267 | } | 280 | } |
| 268 | 281 | ||
| 269 | void mce_common_process_ue(struct pt_regs *regs, | 282 | void mce_common_process_ue(struct pt_regs *regs, |
| @@ -2536,7 +2536,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_P9_TM_HV_ASSIST) · 2535 unmodified lines | |||
| 2536 | /* The following code handles the fake_suspend = 1 case */ | 2536 | /* The following code handles the fake_suspend = 1 case */ |
| 2537 | mflr r0 | 2537 | mflr r0 |
| 2538 | std r0, PPC_LR_STKOFF(r1) | 2538 | std r0, PPC_LR_STKOFF(r1) |
| 2539 | stdu r1, -PPC_MIN_STKFRM(r1) | 2539 | stdu r1, -TM_FRAME_SIZE(r1) |
| 2540 | 2540 | ||
| 2541 | /* Turn on TM. */ | 2541 | /* Turn on TM. */ |
| 2542 | mfmsr r8 | 2542 | mfmsr r8 |
| @@ -2551,10 +2551,42 @@ BEGIN_FTR_SECTION · 8 unmodified lines | |||
| 2551 | END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG) | 2551 | END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG) |
| 2552 | nop | 2552 | nop |
| 2553 | 2553 | ||
| 2554 | /* | ||
| 2555 | * It's possible that treclaim. may modify registers, if we have lost | ||
| 2556 | * track of fake-suspend state in the guest due to it using rfscv. | ||
| 2557 | * Save and restore registers in case this occurs. | ||
| 2558 | */ | ||
| 2559 | mfspr r3, SPRN_DSCR | ||
| 2560 | mfspr r4, SPRN_XER | ||
| 2561 | mfspr r5, SPRN_AMR | ||
| 2562 | /* SPRN_TAR would need to be saved here if the kernel ever used it */ | ||
| 2563 | mfcr r12 | ||
| 2564 | SAVE_NVGPRS(r1) | ||
| 2565 | SAVE_GPR(2, r1) | ||
| 2566 | SAVE_GPR(3, r1) | ||
| 2567 | SAVE_GPR(4, r1) | ||
| 2568 | SAVE_GPR(5, r1) | ||
| 2569 | stw r12, 8(r1) | ||
| 2570 | std r1, HSTATE_HOST_R1(r13) | ||
| 2571 | |||
| 2554 | /* We have to treclaim here because that's the only way to do S->N */ | 2572 | /* We have to treclaim here because that's the only way to do S->N */ |
| 2555 | li r3, TM_CAUSE_KVM_RESCHED | 2573 | li r3, TM_CAUSE_KVM_RESCHED |
| 2556 | TRECLAIM(R3) | 2574 | TRECLAIM(R3) |
| 2557 | 2575 | ||
| 2576 | GET_PACA(r13) | ||
| 2577 | ld r1, HSTATE_HOST_R1(r13) | ||
| 2578 | REST_GPR(2, r1) | ||
| 2579 | REST_GPR(3, r1) | ||
| 2580 | REST_GPR(4, r1) | ||
| 2581 | REST_GPR(5, r1) | ||
| 2582 | lwz r12, 8(r1) | ||
| 2583 | REST_NVGPRS(r1) | ||
| 2584 | mtspr SPRN_DSCR, r3 | ||
| 2585 | mtspr SPRN_XER, r4 | ||
| 2586 | mtspr SPRN_AMR, r5 | ||
| 2587 | mtcr r12 | ||
| 2588 | HMT_MEDIUM | ||
| 2589 | |||
| 2558 | /* | 2590 | /* |
| 2559 | * We were in fake suspend, so we are not going to save the | 2591 | * We were in fake suspend, so we are not going to save the |
| 2560 | * register state as the guest checkpointed state (since | 2592 | * register state as the guest checkpointed state (since |
| @@ -2582,7 +2614,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG) · 21 unmodified lines | |||
| 2582 | std r5, VCPU_TFHAR(r9) | 2614 | std r5, VCPU_TFHAR(r9) |
| 2583 | std r6, VCPU_TFIAR(r9) | 2615 | std r6, VCPU_TFIAR(r9) |
| 2584 | 2616 | ||
| 2585 | addi r1, r1, PPC_MIN_STKFRM | 2617 | addi r1, r1, TM_FRAME_SIZE |
| 2586 | ld r0, PPC_LR_STKOFF(r1) | 2618 | ld r0, PPC_LR_STKOFF(r1) |
| 2587 | mtlr r0 | 2619 | mtlr r0 |
| 2588 | blr | 2620 | blr |
| @@ -348,9 +348,9 @@ static int xics_host_map(struct irq_domain *domain, unsigned int virq, · 347 unmodified lines | |||
| 348 | if (xics_ics->check(xics_ics, hwirq)) | 348 | if (xics_ics->check(xics_ics, hwirq)) |
| 349 | return -EINVAL; | 349 | return -EINVAL; |
| 350 | 350 | ||
| 351 | /* No chip data for the XICS domain */ | 351 | /* Let the ICS be the chip data for the XICS domain. For ICS native */ |
| 352 | irq_domain_set_info(domain, virq, hwirq, xics_ics->chip, | 352 | irq_domain_set_info(domain, virq, hwirq, xics_ics->chip, |
| 353 | NULL, handle_fasteoi_irq, NULL, NULL); | 353 | xics_ics, handle_fasteoi_irq, NULL, NULL); |
| 354 | 354 | ||
| 355 | return 0; | 355 | return 0; |
| 356 | } | 356 | } |
| @@ -685,16 +685,6 @@ config STACK_GUARD · 684 unmodified lines | |||
| 685 | The minimum size for the stack guard should be 256 for 31 bit and | 685 | The minimum size for the stack guard should be 256 for 31 bit and |
| 686 | 512 for 64 bit. | 686 | 512 for 64 bit. |
| 687 | 687 | ||
| 688 | config WARN_DYNAMIC_STACK | ||
| 689 | def_bool n | ||
| 690 | prompt "Emit compiler warnings for function with dynamic stack usage" | ||
| 691 | help | ||
| 692 | This option enables the compiler option -mwarn-dynamicstack. If the | ||
| 693 | compiler supports this options generates warnings for functions | ||
| 694 | that dynamically allocate stack space using alloca. | ||
| 695 | |||
| 696 | Say N if you are unsure. | ||
| 697 | |||
| 698 | endmenu | 688 | endmenu |
| 699 | 689 | ||
| 700 | menu "I/O subsystem" | 690 | menu "I/O subsystem" |
| @@ -85,13 +85,6 @@ cflags-$(CONFIG_CHECK_STACK) += -mstack-guard=$(CONFIG_STACK_GUARD) · 84 unmodified lines | |||
| 85 | endif | 85 | endif |
| 86 | endif | 86 | endif |
| 87 | 87 | ||
| 88 | ifdef CONFIG_WARN_DYNAMIC_STACK | ||
| 89 | ifneq ($(call cc-option,-mwarn-dynamicstack),) | ||
| 90 | KBUILD_CFLAGS += -mwarn-dynamicstack | ||
| 91 | KBUILD_CFLAGS_DECOMPRESSOR += -mwarn-dynamicstack | ||
| 92 | endif | ||
| 93 | endif | ||
| 94 | |||
| 95 | ifdef CONFIG_EXPOLINE | 88 | ifdef CONFIG_EXPOLINE |
| 96 | ifneq ($(call cc-option,$(CC_FLAGS_MARCH) -mindirect-branch=thunk),) | 89 | ifneq ($(call cc-option,$(CC_FLAGS_MARCH) -mindirect-branch=thunk),) |
| 97 | CC_FLAGS_EXPOLINE := -mindirect-branch=thunk | 90 | CC_FLAGS_EXPOLINE := -mindirect-branch=thunk |
| @@ -10,6 +10,7 @@ CONFIG_BPF_JIT=y · 9 unmodified lines | |||
| 10 | CONFIG_BPF_JIT_ALWAYS_ON=y | 10 | CONFIG_BPF_JIT_ALWAYS_ON=y |
| 11 | CONFIG_BPF_LSM=y | 11 | CONFIG_BPF_LSM=y |
| 12 | CONFIG_PREEMPT=y | 12 | CONFIG_PREEMPT=y |
| 13 | CONFIG_SCHED_CORE=y | ||
| 13 | CONFIG_BSD_PROCESS_ACCT=y | 14 | CONFIG_BSD_PROCESS_ACCT=y |
| 14 | CONFIG_BSD_PROCESS_ACCT_V3=y | 15 | CONFIG_BSD_PROCESS_ACCT_V3=y |
| 15 | CONFIG_TASKSTATS=y | 16 | CONFIG_TASKSTATS=y |
| @@ -503,6 +504,7 @@ CONFIG_NLMON=m · 487 unmodified lines | |||
| 503 | # CONFIG_NET_VENDOR_HUAWEI is not set | 504 | # CONFIG_NET_VENDOR_HUAWEI is not set |
| 504 | # CONFIG_NET_VENDOR_INTEL is not set | 505 | # CONFIG_NET_VENDOR_INTEL is not set |
| 505 | # CONFIG_NET_VENDOR_MICROSOFT is not set | 506 | # CONFIG_NET_VENDOR_MICROSOFT is not set |
| 507 | # CONFIG_NET_VENDOR_LITEX is not set | ||
| 506 | # CONFIG_NET_VENDOR_MARVELL is not set | 508 | # CONFIG_NET_VENDOR_MARVELL is not set |
| 507 | CONFIG_MLX4_EN=m | 509 | CONFIG_MLX4_EN=m |
| 508 | CONFIG_MLX5_CORE=m | 510 | CONFIG_MLX5_CORE=m |
| @@ -661,7 +663,6 @@ CONFIG_NFSD_V3_ACL=y · 152 unmodified lines | |||
| 661 | CONFIG_NFSD_V4=y | 663 | CONFIG_NFSD_V4=y |
| 662 | CONFIG_NFSD_V4_SECURITY_LABEL=y | 664 | CONFIG_NFSD_V4_SECURITY_LABEL=y |
| 663 | CONFIG_CIFS=m | 665 | CONFIG_CIFS=m |
| 664 | CONFIG_CIFS_WEAK_PW_HASH=y | ||
| 665 | CONFIG_CIFS_UPCALL=y | 666 | CONFIG_CIFS_UPCALL=y |
| 666 | CONFIG_CIFS_XATTR=y | 667 | CONFIG_CIFS_XATTR=y |
| 667 | CONFIG_CIFS_POSIX=y | 668 | CONFIG_CIFS_POSIX=y |
| @@ -720,6 +721,8 @@ CONFIG_CRYPTO_XCBC=m · 52 unmodified lines | |||
| 720 | CONFIG_CRYPTO_VMAC=m | 721 | CONFIG_CRYPTO_VMAC=m |
| 721 | CONFIG_CRYPTO_CRC32=m | 722 | CONFIG_CRYPTO_CRC32=m |
| 722 | CONFIG_CRYPTO_BLAKE2S=m | 723 | CONFIG_CRYPTO_BLAKE2S=m |
| 724 | CONFIG_CRYPTO_MD4=m | ||
| 725 | CONFIG_CRYPTO_MD5=y | ||
| 723 | CONFIG_CRYPTO_MICHAEL_MIC=m | 726 | CONFIG_CRYPTO_MICHAEL_MIC=m |
| 724 | CONFIG_CRYPTO_RMD160=m | 727 | CONFIG_CRYPTO_RMD160=m |
| 725 | CONFIG_CRYPTO_SHA3=m | 728 | CONFIG_CRYPTO_SHA3=m |
| @@ -774,7 +777,6 @@ CONFIG_RANDOM32_SELFTEST=y · 48 unmodified lines | |||
| 774 | CONFIG_DMA_CMA=y | 777 | CONFIG_DMA_CMA=y |
| 775 | CONFIG_CMA_SIZE_MBYTES=0 | 778 | CONFIG_CMA_SIZE_MBYTES=0 |
| 776 | CONFIG_DMA_API_DEBUG=y | 779 | CONFIG_DMA_API_DEBUG=y |
| 777 | CONFIG_STRING_SELFTEST=y | ||
| 778 | CONFIG_PRINTK_TIME=y | 780 | CONFIG_PRINTK_TIME=y |
| 779 | CONFIG_DYNAMIC_DEBUG=y | 781 | CONFIG_DYNAMIC_DEBUG=y |
| 780 | CONFIG_DEBUG_INFO=y | 782 | CONFIG_DEBUG_INFO=y |
| @@ -853,12 +855,12 @@ CONFIG_FAIL_FUNCTION=y · 72 unmodified lines | |||
| 853 | CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y | 855 | CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y |
| 854 | CONFIG_LKDTM=m | 856 | CONFIG_LKDTM=m |
| 855 | CONFIG_TEST_MIN_HEAP=y | 857 | CONFIG_TEST_MIN_HEAP=y |
| 856 | CONFIG_TEST_SORT=y | ||
| 857 | CONFIG_KPROBES_SANITY_TEST=y | 858 | CONFIG_KPROBES_SANITY_TEST=y |
| 858 | CONFIG_RBTREE_TEST=y | 859 | CONFIG_RBTREE_TEST=y |
| 859 | CONFIG_INTERVAL_TREE_TEST=m | 860 | CONFIG_INTERVAL_TREE_TEST=m |
| 860 | CONFIG_PERCPU_TEST=m | 861 | CONFIG_PERCPU_TEST=m |
| 861 | CONFIG_ATOMIC64_SELFTEST=y | 862 | CONFIG_ATOMIC64_SELFTEST=y |
| 863 | CONFIG_STRING_SELFTEST=y | ||
| 862 | CONFIG_TEST_BITOPS=m | 864 | CONFIG_TEST_BITOPS=m |
| 863 | CONFIG_TEST_BPF=m | 865 | CONFIG_TEST_BPF=m |
| 864 | CONFIG_TEST_LIVEPATCH=m | 866 | CONFIG_TEST_LIVEPATCH=m |
| @@ -8,6 +8,7 @@ CONFIG_BPF_SYSCALL=y · 7 unmodified lines | |||
| 8 | CONFIG_BPF_JIT=y | 8 | CONFIG_BPF_JIT=y |
| 9 | CONFIG_BPF_JIT_ALWAYS_ON=y | 9 | CONFIG_BPF_JIT_ALWAYS_ON=y |
| 10 | CONFIG_BPF_LSM=y | 10 | CONFIG_BPF_LSM=y |
| 11 | CONFIG_SCHED_CORE=y | ||
| 11 | CONFIG_BSD_PROCESS_ACCT=y | 12 | CONFIG_BSD_PROCESS_ACCT=y |
| 12 | CONFIG_BSD_PROCESS_ACCT_V3=y | 13 | CONFIG_BSD_PROCESS_ACCT_V3=y |
| 13 | CONFIG_TASKSTATS=y | 14 | CONFIG_TASKSTATS=y |
| @@ -494,6 +495,7 @@ CONFIG_NLMON=m · 480 unmodified lines | |||
| 494 | # CONFIG_NET_VENDOR_HUAWEI is not set | 495 | # CONFIG_NET_VENDOR_HUAWEI is not set |
| 495 | # CONFIG_NET_VENDOR_INTEL is not set | 496 | # CONFIG_NET_VENDOR_INTEL is not set |
| 496 | # CONFIG_NET_VENDOR_MICROSOFT is not set | 497 | # CONFIG_NET_VENDOR_MICROSOFT is not set |
| 498 | # CONFIG_NET_VENDOR_LITEX is not set | ||
| 497 | # CONFIG_NET_VENDOR_MARVELL is not set | 499 | # CONFIG_NET_VENDOR_MARVELL is not set |
| 498 | CONFIG_MLX4_EN=m | 500 | CONFIG_MLX4_EN=m |
| 499 | CONFIG_MLX5_CORE=m | 501 | CONFIG_MLX5_CORE=m |
| @@ -648,7 +650,6 @@ CONFIG_NFSD_V3_ACL=y · 148 unmodified lines | |||
| 648 | CONFIG_NFSD_V4=y | 650 | CONFIG_NFSD_V4=y |
| 649 | CONFIG_NFSD_V4_SECURITY_LABEL=y | 651 | CONFIG_NFSD_V4_SECURITY_LABEL=y |
| 650 | CONFIG_CIFS=m | 652 | CONFIG_CIFS=m |
| 651 | CONFIG_CIFS_WEAK_PW_HASH=y | ||
| 652 | CONFIG_CIFS_UPCALL=y | 653 | CONFIG_CIFS_UPCALL=y |
| 653 | CONFIG_CIFS_XATTR=y | 654 | CONFIG_CIFS_XATTR=y |
| 654 | CONFIG_CIFS_POSIX=y | 655 | CONFIG_CIFS_POSIX=y |
| @@ -708,6 +709,8 @@ CONFIG_CRYPTO_XCBC=m · 53 unmodified lines | |||
| 708 | CONFIG_CRYPTO_VMAC=m | 709 | CONFIG_CRYPTO_VMAC=m |
| 709 | CONFIG_CRYPTO_CRC32=m | 710 | CONFIG_CRYPTO_CRC32=m |
| 710 | CONFIG_CRYPTO_BLAKE2S=m | 711 | CONFIG_CRYPTO_BLAKE2S=m |
| 712 | CONFIG_CRYPTO_MD4=m | ||
| 713 | CONFIG_CRYPTO_MD5=y | ||
| 711 | CONFIG_CRYPTO_MICHAEL_MIC=m | 714 | CONFIG_CRYPTO_MICHAEL_MIC=m |
| 712 | CONFIG_CRYPTO_RMD160=m | 715 | CONFIG_CRYPTO_RMD160=m |
| 713 | CONFIG_CRYPTO_SHA3=m | 716 | CONFIG_CRYPTO_SHA3=m |
| @@ -55,7 +55,7 @@ int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv, · 54 unmodified lines | |||
| 55 | int num_devices, const char *buf); | 55 | int num_devices, const char *buf); |
| 56 | 56 | ||
| 57 | extern int ccwgroup_set_online(struct ccwgroup_device *gdev); | 57 | extern int ccwgroup_set_online(struct ccwgroup_device *gdev); |
| 58 | extern int ccwgroup_set_offline(struct ccwgroup_device *gdev); | 58 | int ccwgroup_set_offline(struct ccwgroup_device *gdev, bool call_gdrv); |
| 59 | 59 | ||
| 60 | extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev); | 60 | extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev); |
| 61 | extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev); | 61 | extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev); |
| @@ -248,8 +248,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1) · 247 unmodified lines | |||
| 248 | 248 | ||
| 249 | #define EMIT6_PCREL(op1, op2, b1, b2, i, off, mask) \ | 249 | #define EMIT6_PCREL(op1, op2, b1, b2, i, off, mask) \ |
| 250 | ({ \ | 250 | ({ \ |
| 251 | /* Branch instruction needs 6 bytes */ \ | 251 | int rel = (addrs[(i) + (off) + 1] - jit->prg) / 2; \ |
| 252 | int rel = (addrs[(i) + (off) + 1] - (addrs[(i) + 1] - 6)) / 2;\ | ||
| 253 | _EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), (op2) | (mask));\ | 252 | _EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), (op2) | (mask));\ |
| 254 | REG_SET_SEEN(b1); \ | 253 | REG_SET_SEEN(b1); \ |
| 255 | REG_SET_SEEN(b2); \ | 254 | REG_SET_SEEN(b2); \ |
| @@ -761,10 +760,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 505 unmodified lines | |||
| 761 | EMIT4(0xb9080000, dst_reg, src_reg); | 760 | EMIT4(0xb9080000, dst_reg, src_reg); |
| 762 | break; | 761 | break; |
| 763 | case BPF_ALU | BPF_ADD | BPF_K: /* dst = (u32) dst + (u32) imm */ | 762 | case BPF_ALU | BPF_ADD | BPF_K: /* dst = (u32) dst + (u32) imm */ |
| 764 | if (!imm) | 763 | if (imm != 0) { |
| 765 | break; | 764 | /* alfi %dst,imm */ |
| 766 | /* alfi %dst,imm */ | 765 | EMIT6_IMM(0xc20b0000, dst_reg, imm); |
| 767 | EMIT6_IMM(0xc20b0000, dst_reg, imm); | 766 | } |
| 768 | EMIT_ZERO(dst_reg); | 767 | EMIT_ZERO(dst_reg); |
| 769 | break; | 768 | break; |
| 770 | case BPF_ALU64 | BPF_ADD | BPF_K: /* dst = dst + imm */ | 769 | case BPF_ALU64 | BPF_ADD | BPF_K: /* dst = dst + imm */ |
| @@ -786,17 +785,22 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 15 unmodified lines | |||
| 786 | EMIT4(0xb9090000, dst_reg, src_reg); | 785 | EMIT4(0xb9090000, dst_reg, src_reg); |
| 787 | break; | 786 | break; |
| 788 | case BPF_ALU | BPF_SUB | BPF_K: /* dst = (u32) dst - (u32) imm */ | 787 | case BPF_ALU | BPF_SUB | BPF_K: /* dst = (u32) dst - (u32) imm */ |
| 789 | if (!imm) | 788 | if (imm != 0) { |
| 790 | break; | 789 | /* alfi %dst,-imm */ |
| 791 | /* alfi %dst,-imm */ | 790 | EMIT6_IMM(0xc20b0000, dst_reg, -imm); |
| 792 | EMIT6_IMM(0xc20b0000, dst_reg, -imm); | 791 | } |
| 793 | EMIT_ZERO(dst_reg); | 792 | EMIT_ZERO(dst_reg); |
| 794 | break; | 793 | break; |
| 795 | case BPF_ALU64 | BPF_SUB | BPF_K: /* dst = dst - imm */ | 794 | case BPF_ALU64 | BPF_SUB | BPF_K: /* dst = dst - imm */ |
| 796 | if (!imm) | 795 | if (!imm) |
| 797 | break; | 796 | break; |
| 798 | /* agfi %dst,-imm */ | 797 | if (imm == -0x80000000) { |
| 799 | EMIT6_IMM(0xc2080000, dst_reg, -imm); | 798 | /* algfi %dst,0x80000000 */ |
| 799 | EMIT6_IMM(0xc20a0000, dst_reg, 0x80000000); | ||
| 800 | } else { | ||
| 801 | /* agfi %dst,-imm */ | ||
| 802 | EMIT6_IMM(0xc2080000, dst_reg, -imm); | ||
| 803 | } | ||
| 800 | break; | 804 | break; |
| 801 | /* | 805 | /* |
| 802 | * BPF_MUL | 806 | * BPF_MUL |
| @@ -811,10 +815,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 8 unmodified lines | |||
| 811 | EMIT4(0xb90c0000, dst_reg, src_reg); | 815 | EMIT4(0xb90c0000, dst_reg, src_reg); |
| 812 | break; | 816 | break; |
| 813 | case BPF_ALU | BPF_MUL | BPF_K: /* dst = (u32) dst * (u32) imm */ | 817 | case BPF_ALU | BPF_MUL | BPF_K: /* dst = (u32) dst * (u32) imm */ |
| 814 | if (imm == 1) | 818 | if (imm != 1) { |
| 815 | break; | 819 | /* msfi %r5,imm */ |
| 816 | /* msfi %r5,imm */ | 820 | EMIT6_IMM(0xc2010000, dst_reg, imm); |
| 817 | EMIT6_IMM(0xc2010000, dst_reg, imm); | 821 | } |
| 818 | EMIT_ZERO(dst_reg); | 822 | EMIT_ZERO(dst_reg); |
| 819 | break; | 823 | break; |
| 820 | case BPF_ALU64 | BPF_MUL | BPF_K: /* dst = dst * imm */ | 824 | case BPF_ALU64 | BPF_MUL | BPF_K: /* dst = dst * imm */ |
| @@ -867,6 +871,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 46 unmodified lines | |||
| 867 | if (BPF_OP(insn->code) == BPF_MOD) | 871 | if (BPF_OP(insn->code) == BPF_MOD) |
| 868 | /* lhgi %dst,0 */ | 872 | /* lhgi %dst,0 */ |
| 869 | EMIT4_IMM(0xa7090000, dst_reg, 0); | 873 | EMIT4_IMM(0xa7090000, dst_reg, 0); |
| 874 | else | ||
| 875 | EMIT_ZERO(dst_reg); | ||
| 870 | break; | 876 | break; |
| 871 | } | 877 | } |
| 872 | /* lhi %w0,0 */ | 878 | /* lhi %w0,0 */ |
| @@ -999,10 +1005,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 126 unmodified lines | |||
| 999 | EMIT4(0xb9820000, dst_reg, src_reg); | 1005 | EMIT4(0xb9820000, dst_reg, src_reg); |
| 1000 | break; | 1006 | break; |
| 1001 | case BPF_ALU | BPF_XOR | BPF_K: /* dst = (u32) dst ^ (u32) imm */ | 1007 | case BPF_ALU | BPF_XOR | BPF_K: /* dst = (u32) dst ^ (u32) imm */ |
| 1002 | if (!imm) | 1008 | if (imm != 0) { |
| 1003 | break; | 1009 | /* xilf %dst,imm */ |
| 1004 | /* xilf %dst,imm */ | 1010 | EMIT6_IMM(0xc0070000, dst_reg, imm); |
| 1005 | EMIT6_IMM(0xc0070000, dst_reg, imm); | 1011 | } |
| 1006 | EMIT_ZERO(dst_reg); | 1012 | EMIT_ZERO(dst_reg); |
| 1007 | break; | 1013 | break; |
| 1008 | case BPF_ALU64 | BPF_XOR | BPF_K: /* dst = dst ^ imm */ | 1014 | case BPF_ALU64 | BPF_XOR | BPF_K: /* dst = dst ^ imm */ |
| @@ -1033,10 +1039,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 24 unmodified lines | |||
| 1033 | EMIT6_DISP_LH(0xeb000000, 0x000d, dst_reg, dst_reg, src_reg, 0); | 1039 | EMIT6_DISP_LH(0xeb000000, 0x000d, dst_reg, dst_reg, src_reg, 0); |
| 1034 | break; | 1040 | break; |
| 1035 | case BPF_ALU | BPF_LSH | BPF_K: /* dst = (u32) dst << (u32) imm */ | 1041 | case BPF_ALU | BPF_LSH | BPF_K: /* dst = (u32) dst << (u32) imm */ |
| 1036 | if (imm == 0) | 1042 | if (imm != 0) { |
| 1037 | break; | 1043 | /* sll %dst,imm(%r0) */ |
| 1038 | /* sll %dst,imm(%r0) */ | 1044 | EMIT4_DISP(0x89000000, dst_reg, REG_0, imm); |
| 1039 | EMIT4_DISP(0x89000000, dst_reg, REG_0, imm); | 1045 | } |
| 1040 | EMIT_ZERO(dst_reg); | 1046 | EMIT_ZERO(dst_reg); |
| 1041 | break; | 1047 | break; |
| 1042 | case BPF_ALU64 | BPF_LSH | BPF_K: /* dst = dst << imm */ | 1048 | case BPF_ALU64 | BPF_LSH | BPF_K: /* dst = dst << imm */ |
| @@ -1058,10 +1064,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 15 unmodified lines | |||
| 1058 | EMIT6_DISP_LH(0xeb000000, 0x000c, dst_reg, dst_reg, src_reg, 0); | 1064 | EMIT6_DISP_LH(0xeb000000, 0x000c, dst_reg, dst_reg, src_reg, 0); |
| 1059 | break; | 1065 | break; |
| 1060 | case BPF_ALU | BPF_RSH | BPF_K: /* dst = (u32) dst >> (u32) imm */ | 1066 | case BPF_ALU | BPF_RSH | BPF_K: /* dst = (u32) dst >> (u32) imm */ |
| 1061 | if (imm == 0) | 1067 | if (imm != 0) { |
| 1062 | break; | 1068 | /* srl %dst,imm(%r0) */ |
| 1063 | /* srl %dst,imm(%r0) */ | 1069 | EMIT4_DISP(0x88000000, dst_reg, REG_0, imm); |
| 1064 | EMIT4_DISP(0x88000000, dst_reg, REG_0, imm); | 1070 | } |
| 1065 | EMIT_ZERO(dst_reg); | 1071 | EMIT_ZERO(dst_reg); |
| 1066 | break; | 1072 | break; |
| 1067 | case BPF_ALU64 | BPF_RSH | BPF_K: /* dst = dst >> imm */ | 1073 | case BPF_ALU64 | BPF_RSH | BPF_K: /* dst = dst >> imm */ |
| @@ -1083,10 +1089,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 15 unmodified lines | |||
| 1083 | EMIT6_DISP_LH(0xeb000000, 0x000a, dst_reg, dst_reg, src_reg, 0); | 1089 | EMIT6_DISP_LH(0xeb000000, 0x000a, dst_reg, dst_reg, src_reg, 0); |
| 1084 | break; | 1090 | break; |
| 1085 | case BPF_ALU | BPF_ARSH | BPF_K: /* ((s32) dst >> imm */ | 1091 | case BPF_ALU | BPF_ARSH | BPF_K: /* ((s32) dst >> imm */ |
| 1086 | if (imm == 0) | 1092 | if (imm != 0) { |
| 1087 | break; | 1093 | /* sra %dst,imm(%r0) */ |
| 1088 | /* sra %dst,imm(%r0) */ | 1094 | EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm); |
| 1089 | EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm); | 1095 | } |
| 1090 | EMIT_ZERO(dst_reg); | 1096 | EMIT_ZERO(dst_reg); |
| 1091 | break; | 1097 | break; |
| 1092 | case BPF_ALU64 | BPF_ARSH | BPF_K: /* ((s64) dst) >>= imm */ | 1098 | case BPF_ALU64 | BPF_ARSH | BPF_K: /* ((s64) dst) >>= imm */ |
| @@ -159,7 +159,7 @@ SYSCALL_DEFINE3(s390_pci_mmio_write, unsigned long, mmio_addr, · 158 unmodified lines | |||
| 159 | 159 | ||
| 160 | mmap_read_lock(current->mm); | 160 | mmap_read_lock(current->mm); |
| 161 | ret = -EINVAL; | 161 | ret = -EINVAL; |
| 162 | vma = find_vma(current->mm, mmio_addr); | 162 | vma = vma_lookup(current->mm, mmio_addr); |
| 163 | if (!vma) | 163 | if (!vma) |
| 164 | goto out_unlock_mmap; | 164 | goto out_unlock_mmap; |
| 165 | if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) | 165 | if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) |
| @@ -298,7 +298,7 @@ SYSCALL_DEFINE3(s390_pci_mmio_read, unsigned long, mmio_addr, · 132 unmodified lines | |||
| 298 | 298 | ||
| 299 | mmap_read_lock(current->mm); | 299 | mmap_read_lock(current->mm); |
| 300 | ret = -EINVAL; | 300 | ret = -EINVAL; |
| 301 | vma = find_vma(current->mm, mmio_addr); | 301 | vma = vma_lookup(current->mm, mmio_addr); |
| 302 | if (!vma) | 302 | if (!vma) |
| 303 | goto out_unlock_mmap; | 303 | goto out_unlock_mmap; |
| 304 | if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) | 304 | if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) |
| @@ -80,30 +80,30 @@ $(obj)/vmlinux.bin.xz: $(obj)/vmlinux.bin FORCE · 79 unmodified lines | |||
| 80 | $(obj)/vmlinux.bin.lzo: $(obj)/vmlinux.bin FORCE | 80 | $(obj)/vmlinux.bin.lzo: $(obj)/vmlinux.bin FORCE |
| 81 | $(call if_changed,lzo) | 81 | $(call if_changed,lzo) |
| 82 | 82 | ||
| 83 | $(obj)/uImage.bz2: $(obj)/vmlinux.bin.bz2 | 83 | $(obj)/uImage.bz2: $(obj)/vmlinux.bin.bz2 FORCE |
| 84 | $(call if_changed,uimage,bzip2) | 84 | $(call if_changed,uimage,bzip2) |
| 85 | 85 | ||
| 86 | $(obj)/uImage.gz: $(obj)/vmlinux.bin.gz | 86 | $(obj)/uImage.gz: $(obj)/vmlinux.bin.gz FORCE |
| 87 | $(call if_changed,uimage,gzip) | 87 | $(call if_changed,uimage,gzip) |
| 88 | 88 | ||
| 89 | $(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma | 89 | $(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma FORCE |
| 90 | $(call if_changed,uimage,lzma) | 90 | $(call if_changed,uimage,lzma) |
| 91 | 91 | ||
| 92 | $(obj)/uImage.xz: $(obj)/vmlinux.bin.xz | 92 | $(obj)/uImage.xz: $(obj)/vmlinux.bin.xz FORCE |
| 93 | $(call if_changed,uimage,xz) | 93 | $(call if_changed,uimage,xz) |
| 94 | 94 | ||
| 95 | $(obj)/uImage.lzo: $(obj)/vmlinux.bin.lzo | 95 | $(obj)/uImage.lzo: $(obj)/vmlinux.bin.lzo FORCE |
| 96 | $(call if_changed,uimage,lzo) | 96 | $(call if_changed,uimage,lzo) |
| 97 | 97 | ||
| 98 | $(obj)/uImage.bin: $(obj)/vmlinux.bin | 98 | $(obj)/uImage.bin: $(obj)/vmlinux.bin FORCE |
| 99 | $(call if_changed,uimage,none) | 99 | $(call if_changed,uimage,none) |
| 100 | 100 | ||
| 101 | OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec | 101 | OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec |
| 102 | $(obj)/vmlinux.srec: $(obj)/compressed/vmlinux | 102 | $(obj)/vmlinux.srec: $(obj)/compressed/vmlinux FORCE |
| 103 | $(call if_changed,objcopy) | 103 | $(call if_changed,objcopy) |
| 104 | 104 | ||
| 105 | OBJCOPYFLAGS_uImage.srec := -I binary -O srec | 105 | OBJCOPYFLAGS_uImage.srec := -I binary -O srec |
| 106 | $(obj)/uImage.srec: $(obj)/uImage | 106 | $(obj)/uImage.srec: $(obj)/uImage FORCE |
| 107 | $(call if_changed,objcopy) | 107 | $(call if_changed,objcopy) |
| 108 | 108 | ||
| 109 | $(obj)/uImage: $(obj)/uImage.$(suffix-y) | 109 | $(obj)/uImage: $(obj)/uImage.$(suffix-y) |
| @@ -356,7 +356,9 @@ err_nomem: · 355 unmodified lines | |||
| 356 | void arch_dma_free(struct device *dev, size_t size, void *cpu_addr, | 356 | void arch_dma_free(struct device *dev, size_t size, void *cpu_addr, |
| 357 | dma_addr_t dma_addr, unsigned long attrs) | 357 | dma_addr_t dma_addr, unsigned long attrs) |
| 358 | { | 358 | { |
| 359 | if (!sparc_dma_free_resource(cpu_addr, PAGE_ALIGN(size))) | 359 | size = PAGE_ALIGN(size); |
| 360 | |||
| 361 | if (!sparc_dma_free_resource(cpu_addr, size)) | ||
| 360 | return; | 362 | return; |
| 361 | 363 | ||
| 362 | dma_make_coherent(dma_addr, size); | 364 | dma_make_coherent(dma_addr, size); |
| @@ -19,8 +19,10 @@ void ioport_unmap(void __iomem *addr) · 18 unmodified lines | |||
| 19 | EXPORT_SYMBOL(ioport_map); | 19 | EXPORT_SYMBOL(ioport_map); |
| 20 | EXPORT_SYMBOL(ioport_unmap); | 20 | EXPORT_SYMBOL(ioport_unmap); |
| 21 | 21 | ||
| 22 | #ifdef CONFIG_PCI | ||
| 22 | void pci_iounmap(struct pci_dev *dev, void __iomem * addr) | 23 | void pci_iounmap(struct pci_dev *dev, void __iomem * addr) |
| 23 | { | 24 | { |
| 24 | /* nothing to do */ | 25 | /* nothing to do */ |
| 25 | } | 26 | } |
| 26 | EXPORT_SYMBOL(pci_iounmap); | 27 | EXPORT_SYMBOL(pci_iounmap); |
| 28 | #endif | ||
| @@ -339,6 +339,11 @@ config NEED_PER_CPU_PAGE_FIRST_CHUNK · 338 unmodified lines | |||
| 339 | config ARCH_HIBERNATION_POSSIBLE | 339 | config ARCH_HIBERNATION_POSSIBLE |
| 340 | def_bool y | 340 | def_bool y |
| 341 | 341 | ||
| 342 | config ARCH_NR_GPIO | ||
| 343 | int | ||
| 344 | default 1024 if X86_64 | ||
| 345 | default 512 | ||
| 346 | |||
| 342 | config ARCH_SUSPEND_POSSIBLE | 347 | config ARCH_SUSPEND_POSSIBLE |
| 343 | def_bool y | 348 | def_bool y |
| 344 | 349 | ||
| @@ -4,6 +4,12 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | tune = $(call cc-option,-mtune=$(1),$(2)) | 5 | tune = $(call cc-option,-mtune=$(1),$(2)) |
| 6 | 6 | ||
| 7 | ifdef CONFIG_CC_IS_CLANG | ||
| 8 | align := -falign-functions=0 $(call cc-option,-falign-jumps=0) $(call cc-option,-falign-loops=0) | ||
| 9 | else | ||
| 10 | align := -falign-functions=0 -falign-jumps=0 -falign-loops=0 | ||
| 11 | endif | ||
| 12 | |||
| 7 | cflags-$(CONFIG_M486SX) += -march=i486 | 13 | cflags-$(CONFIG_M486SX) += -march=i486 |
| 8 | cflags-$(CONFIG_M486) += -march=i486 | 14 | cflags-$(CONFIG_M486) += -march=i486 |
| 9 | cflags-$(CONFIG_M586) += -march=i586 | 15 | cflags-$(CONFIG_M586) += -march=i586 |
| @@ -19,11 +25,11 @@ cflags-$(CONFIG_MK6) += -march=k6 · 9 unmodified lines | |||
| 19 | # They make zero difference whatsosever to performance at this time. | 25 | # They make zero difference whatsosever to performance at this time. |
| 20 | cflags-$(CONFIG_MK7) += -march=athlon | 26 | cflags-$(CONFIG_MK7) += -march=athlon |
| 21 | cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,-march=athlon) | 27 | cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,-march=athlon) |
| 22 | cflags-$(CONFIG_MCRUSOE) += -march=i686 -falign-functions=0 -falign-jumps=0 -falign-loops=0 | 28 | cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align) |
| 23 | cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) -falign-functions=0 -falign-jumps=0 -falign-loops=0 | 29 | cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) $(align) |
| 24 | cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586) | 30 | cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586) |
| 25 | cflags-$(CONFIG_MWINCHIP3D) += $(call cc-option,-march=winchip2,-march=i586) | 31 | cflags-$(CONFIG_MWINCHIP3D) += $(call cc-option,-march=winchip2,-march=i586) |
| 26 | cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) -falign-functions=0 -falign-jumps=0 -falign-loops=0 | 32 | cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) $(align) |
| 27 | cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) | 33 | cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) |
| 28 | cflags-$(CONFIG_MVIAC7) += -march=i686 | 34 | cflags-$(CONFIG_MVIAC7) += -march=i686 |
| 29 | cflags-$(CONFIG_MCORE2) += -march=i686 $(call tune,core2) | 35 | cflags-$(CONFIG_MCORE2) += -march=i686 $(call tune,core2) |
| @@ -1253,6 +1253,9 @@ static void __mc_scan_banks(struct mce *m, struct pt_regs *regs, struct mce *fin · 1252 unmodified lines | |||
| 1253 | 1253 | ||
| 1254 | static void kill_me_now(struct callback_head *ch) | 1254 | static void kill_me_now(struct callback_head *ch) |
| 1255 | { | 1255 | { |
| 1256 | struct task_struct *p = container_of(ch, struct task_struct, mce_kill_me); | ||
| 1257 | |||
| 1258 | p->mce_count = 0; | ||
| 1256 | force_sig(SIGBUS); | 1259 | force_sig(SIGBUS); |
| 1257 | } | 1260 | } |
| 1258 | 1261 | ||
| @@ -1262,6 +1265,7 @@ static void kill_me_maybe(struct callback_head *cb) · 3 unmodified lines | |||
| 1262 | int flags = MF_ACTION_REQUIRED; | 1265 | int flags = MF_ACTION_REQUIRED; |
| 1263 | int ret; | 1266 | int ret; |
| 1264 | 1267 | ||
| 1268 | p->mce_count = 0; | ||
| 1265 | pr_err("Uncorrected hardware memory error in user-access at %llx", p->mce_addr); | 1269 | pr_err("Uncorrected hardware memory error in user-access at %llx", p->mce_addr); |
| 1266 | 1270 | ||
| 1267 | if (!p->mce_ripv) | 1271 | if (!p->mce_ripv) |
| @@ -1290,17 +1294,34 @@ static void kill_me_maybe(struct callback_head *cb) · 22 unmodified lines | |||
| 1290 | } | 1294 | } |
| 1291 | } | 1295 | } |
| 1292 | 1296 | ||
| 1293 | static void queue_task_work(struct mce *m, int kill_current_task) | 1297 | static void queue_task_work(struct mce *m, char *msg, int kill_current_task) |
| 1294 | { | 1298 | { |
| 1295 | current->mce_addr = m->addr; | 1299 | int count = ++current->mce_count; |
| 1296 | current->mce_kflags = m->kflags; | ||
| 1297 | current->mce_ripv = !!(m->mcgstatus & MCG_STATUS_RIPV); | ||
| 1298 | current->mce_whole_page = whole_page(m); | ||
| 1299 | 1300 | ||
| 1300 | if (kill_current_task) | 1301 | /* First call, save all the details */ |
| 1301 | current->mce_kill_me.func = kill_me_now; | 1302 | if (count == 1) { |
| 1302 | else | 1303 | current->mce_addr = m->addr; |
| 1303 | current->mce_kill_me.func = kill_me_maybe; | 1304 | current->mce_kflags = m->kflags; |
| 1305 | current->mce_ripv = !!(m->mcgstatus & MCG_STATUS_RIPV); | ||
| 1306 | current->mce_whole_page = whole_page(m); | ||
| 1307 | |||
| 1308 | if (kill_current_task) | ||
| 1309 | current->mce_kill_me.func = kill_me_now; | ||
| 1310 | else | ||
| 1311 | current->mce_kill_me.func = kill_me_maybe; | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | /* Ten is likely overkill. Don't expect more than two faults before task_work() */ | ||
| 1315 | if (count > 10) | ||
| 1316 | mce_panic("Too many consecutive machine checks while accessing user data", m, msg); | ||
| 1317 | |||
| 1318 | /* Second or later call, make sure page address matches the one from first call */ | ||
| 1319 | if (count > 1 && (current->mce_addr >> PAGE_SHIFT) != (m->addr >> PAGE_SHIFT)) | ||
| 1320 | mce_panic("Consecutive machine checks to different user pages", m, msg); | ||
| 1321 | |||
| 1322 | /* Do not call task_work_add() more than once */ | ||
| 1323 | if (count > 1) | ||
| 1324 | return; | ||
| 1304 | 1325 | ||
| 1305 | task_work_add(current, ¤t->mce_kill_me, TWA_RESUME); | 1326 | task_work_add(current, ¤t->mce_kill_me, TWA_RESUME); |
| 1306 | } | 1327 | } |
| @@ -1438,7 +1459,7 @@ noinstr void do_machine_check(struct pt_regs *regs) · 131 unmodified lines | |||
| 1438 | /* If this triggers there is no way to recover. Die hard. */ | 1459 | /* If this triggers there is no way to recover. Die hard. */ |
| 1439 | BUG_ON(!on_thread_stack() || !user_mode(regs)); | 1460 | BUG_ON(!on_thread_stack() || !user_mode(regs)); |
| 1440 | 1461 | ||
| 1441 | queue_task_work(&m, kill_current_task); | 1462 | queue_task_work(&m, msg, kill_current_task); |
| 1442 | 1463 | ||
| 1443 | } else { | 1464 | } else { |
| 1444 | /* | 1465 | /* |
| @@ -1456,7 +1477,7 @@ noinstr void do_machine_check(struct pt_regs *regs) · 11 unmodified lines | |||
| 1456 | } | 1477 | } |
| 1457 | 1478 | ||
| 1458 | if (m.kflags & MCE_IN_KERNEL_COPYIN) | 1479 | if (m.kflags & MCE_IN_KERNEL_COPYIN) |
| 1459 | queue_task_work(&m, kill_current_task); | 1480 | queue_task_work(&m, msg, kill_current_task); |
| 1460 | } | 1481 | } |
| 1461 | out: | 1482 | out: |
| 1462 | mce_wrmsrl(MSR_IA32_MCG_STATUS, 0); | 1483 | mce_wrmsrl(MSR_IA32_MCG_STATUS, 0); |
| @@ -1432,18 +1432,18 @@ int kern_addr_valid(unsigned long addr) · 1431 unmodified lines | |||
| 1432 | return 0; | 1432 | return 0; |
| 1433 | 1433 | ||
| 1434 | p4d = p4d_offset(pgd, addr); | 1434 | p4d = p4d_offset(pgd, addr); |
| 1435 | if (p4d_none(*p4d)) | 1435 | if (!p4d_present(*p4d)) |
| 1436 | return 0; | 1436 | return 0; |
| 1437 | 1437 | ||
| 1438 | pud = pud_offset(p4d, addr); | 1438 | pud = pud_offset(p4d, addr); |
| 1439 | if (pud_none(*pud)) | 1439 | if (!pud_present(*pud)) |
| 1440 | return 0; | 1440 | return 0; |
| 1441 | 1441 | ||
| 1442 | if (pud_large(*pud)) | 1442 | if (pud_large(*pud)) |
| 1443 | return pfn_valid(pud_pfn(*pud)); | 1443 | return pfn_valid(pud_pfn(*pud)); |
| 1444 | 1444 | ||
| 1445 | pmd = pmd_offset(pud, addr); | 1445 | pmd = pmd_offset(pud, addr); |
| 1446 | if (pmd_none(*pmd)) | 1446 | if (!pmd_present(*pmd)) |
| 1447 | return 0; | 1447 | return 0; |
| 1448 | 1448 | ||
| 1449 | if (pmd_large(*pmd)) | 1449 | if (pmd_large(*pmd)) |
| @@ -583,7 +583,12 @@ int memtype_reserve(u64 start, u64 end, enum page_cache_mode req_type, · 582 unmodified lines | |||
| 583 | int err = 0; | 583 | int err = 0; |
| 584 | 584 | ||
| 585 | start = sanitize_phys(start); | 585 | start = sanitize_phys(start); |
| 586 | end = sanitize_phys(end); | 586 | |
| 587 | /* | ||
| 588 | * The end address passed into this function is exclusive, but | ||
| 589 | * sanitize_phys() expects an inclusive address. | ||
| 590 | */ | ||
| 591 | end = sanitize_phys(end - 1) + 1; | ||
| 587 | if (start >= end) { | 592 | if (start >= end) { |
| 588 | WARN(1, "%s failed: [mem %#010Lx-%#010Lx], req %s\n", __func__, | 593 | WARN(1, "%s failed: [mem %#010Lx-%#010Lx], req %s\n", __func__, |
| 589 | start, end - 1, cattr_name(req_type)); | 594 | start, end - 1, cattr_name(req_type)); |
| @@ -1214,6 +1214,11 @@ static void __init xen_dom0_set_legacy_features(void) · 1213 unmodified lines | |||
| 1214 | x86_platform.legacy.rtc = 1; | 1214 | x86_platform.legacy.rtc = 1; |
| 1215 | } | 1215 | } |
| 1216 | 1216 | ||
| 1217 | static void __init xen_domu_set_legacy_features(void) | ||
| 1218 | { | ||
| 1219 | x86_platform.legacy.rtc = 0; | ||
| 1220 | } | ||
| 1221 | |||
| 1217 | /* First C function to be called on Xen boot */ | 1222 | /* First C function to be called on Xen boot */ |
| 1218 | asmlinkage __visible void __init xen_start_kernel(void) | 1223 | asmlinkage __visible void __init xen_start_kernel(void) |
| 1219 | { | 1224 | { |
| @@ -1359,6 +1364,8 @@ asmlinkage __visible void __init xen_start_kernel(void) · 139 unmodified lines | |||
| 1359 | add_preferred_console("xenboot", 0, NULL); | 1364 | add_preferred_console("xenboot", 0, NULL); |
| 1360 | if (pci_xen) | 1365 | if (pci_xen) |
| 1361 | x86_init.pci.arch_init = pci_xen_init; | 1366 | x86_init.pci.arch_init = pci_xen_init; |
| 1367 | x86_platform.set_legacy_features = | ||
| 1368 | xen_domu_set_legacy_features; | ||
| 1362 | } else { | 1369 | } else { |
| 1363 | const struct dom0_vga_console_info *info = | 1370 | const struct dom0_vga_console_info *info = |
| 1364 | (void *)((char *)xen_start_info + | 1371 | (void *)((char *)xen_start_info + |
| @@ -1518,14 +1518,17 @@ static inline void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, · 1517 unmodified lines | |||
| 1518 | if (pinned) { | 1518 | if (pinned) { |
| 1519 | struct page *page = pfn_to_page(pfn); | 1519 | struct page *page = pfn_to_page(pfn); |
| 1520 | 1520 | ||
| 1521 | if (static_branch_likely(&xen_struct_pages_ready)) | 1521 | pinned = false; |
| 1522 | if (static_branch_likely(&xen_struct_pages_ready)) { | ||
| 1523 | pinned = PagePinned(page); | ||
| 1522 | SetPagePinned(page); | 1524 | SetPagePinned(page); |
| 1525 | } | ||
| 1523 | 1526 | ||
| 1524 | xen_mc_batch(); | 1527 | xen_mc_batch(); |
| 1525 | 1528 | ||
| 1526 | __set_pfn_prot(pfn, PAGE_KERNEL_RO); | 1529 | __set_pfn_prot(pfn, PAGE_KERNEL_RO); |
| 1527 | 1530 | ||
| 1528 | if (level == PT_PTE && USE_SPLIT_PTE_PTLOCKS) | 1531 | if (level == PT_PTE && USE_SPLIT_PTE_PTLOCKS && !pinned) |
| 1529 | __pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); | 1532 | __pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); |
| 1530 | 1533 | ||
| 1531 | xen_mc_issue(PARAVIRT_LAZY_MMU); | 1534 | xen_mc_issue(PARAVIRT_LAZY_MMU); |
| @@ -1182,10 +1182,6 @@ int blkcg_init_queue(struct request_queue *q) · 1181 unmodified lines | |||
| 1182 | if (preloaded) | 1182 | if (preloaded) |
| 1183 | radix_tree_preload_end(); | 1183 | radix_tree_preload_end(); |
| 1184 | 1184 | ||
| 1185 | ret = blk_iolatency_init(q); | ||
| 1186 | if (ret) | ||
| 1187 | goto err_destroy_all; | ||
| 1188 | |||
| 1189 | ret = blk_ioprio_init(q); | 1185 | ret = blk_ioprio_init(q); |
| 1190 | if (ret) | 1186 | if (ret) |
| 1191 | goto err_destroy_all; | 1187 | goto err_destroy_all; |
| @@ -1194,6 +1190,12 @@ int blkcg_init_queue(struct request_queue *q) · 2 unmodified lines | |||
| 1194 | if (ret) | 1190 | if (ret) |
| 1195 | goto err_destroy_all; | 1191 | goto err_destroy_all; |
| 1196 | 1192 | ||
| 1193 | ret = blk_iolatency_init(q); | ||
| 1194 | if (ret) { | ||
| 1195 | blk_throtl_exit(q); | ||
| 1196 | goto err_destroy_all; | ||
| 1197 | } | ||
| 1198 | |||
| 1197 | return 0; | 1199 | return 0; |
| 1198 | 1200 | ||
| 1199 | err_destroy_all: | 1201 | err_destroy_all: |
| @@ -1364,10 +1366,14 @@ enomem: · 164 unmodified lines | |||
| 1364 | /* alloc failed, nothing's initialized yet, free everything */ | 1366 | /* alloc failed, nothing's initialized yet, free everything */ |
| 1365 | spin_lock_irq(&q->queue_lock); | 1367 | spin_lock_irq(&q->queue_lock); |
| 1366 | list_for_each_entry(blkg, &q->blkg_list, q_node) { | 1368 | list_for_each_entry(blkg, &q->blkg_list, q_node) { |
| 1369 | struct blkcg *blkcg = blkg->blkcg; | ||
| 1370 | |||
| 1371 | spin_lock(&blkcg->lock); | ||
| 1367 | if (blkg->pd[pol->plid]) { | 1372 | if (blkg->pd[pol->plid]) { |
| 1368 | pol->pd_free_fn(blkg->pd[pol->plid]); | 1373 | pol->pd_free_fn(blkg->pd[pol->plid]); |
| 1369 | blkg->pd[pol->plid] = NULL; | 1374 | blkg->pd[pol->plid] = NULL; |
| 1370 | } | 1375 | } |
| 1376 | spin_unlock(&blkcg->lock); | ||
| 1371 | } | 1377 | } |
| 1372 | spin_unlock_irq(&q->queue_lock); | 1378 | spin_unlock_irq(&q->queue_lock); |
| 1373 | ret = -ENOMEM; | 1379 | ret = -ENOMEM; |
| @@ -1399,12 +1405,16 @@ void blkcg_deactivate_policy(struct request_queue *q, · 25 unmodified lines | |||
| 1399 | __clear_bit(pol->plid, q->blkcg_pols); | 1405 | __clear_bit(pol->plid, q->blkcg_pols); |
| 1400 | 1406 | ||
| 1401 | list_for_each_entry(blkg, &q->blkg_list, q_node) { | 1407 | list_for_each_entry(blkg, &q->blkg_list, q_node) { |
| 1408 | struct blkcg *blkcg = blkg->blkcg; | ||
| 1409 | |||
| 1410 | spin_lock(&blkcg->lock); | ||
| 1402 | if (blkg->pd[pol->plid]) { | 1411 | if (blkg->pd[pol->plid]) { |
| 1403 | if (pol->pd_offline_fn) | 1412 | if (pol->pd_offline_fn) |
| 1404 | pol->pd_offline_fn(blkg->pd[pol->plid]); | 1413 | pol->pd_offline_fn(blkg->pd[pol->plid]); |
| 1405 | pol->pd_free_fn(blkg->pd[pol->plid]); | 1414 | pol->pd_free_fn(blkg->pd[pol->plid]); |
| 1406 | blkg->pd[pol->plid] = NULL; | 1415 | blkg->pd[pol->plid] = NULL; |
| 1407 | } | 1416 | } |
| 1417 | spin_unlock(&blkcg->lock); | ||
| 1408 | } | 1418 | } |
| 1409 | 1419 | ||
| 1410 | spin_unlock_irq(&q->queue_lock); | 1420 | spin_unlock_irq(&q->queue_lock); |
| @@ -426,8 +426,15 @@ EXPORT_SYMBOL(blk_integrity_register); · 425 unmodified lines | |||
| 426 | */ | 426 | */ |
| 427 | void blk_integrity_unregister(struct gendisk *disk) | 427 | void blk_integrity_unregister(struct gendisk *disk) |
| 428 | { | 428 | { |
| 429 | struct blk_integrity *bi = &disk->queue->integrity; | ||
| 430 | |||
| 431 | if (!bi->profile) | ||
| 432 | return; | ||
| 433 | |||
| 434 | /* ensure all bios are off the integrity workqueue */ | ||
| 435 | blk_flush_integrity(); | ||
| 429 | blk_queue_flag_clear(QUEUE_FLAG_STABLE_WRITES, disk->queue); | 436 | blk_queue_flag_clear(QUEUE_FLAG_STABLE_WRITES, disk->queue); |
| 430 | memset(&disk->queue->integrity, 0, sizeof(struct blk_integrity)); | 437 | memset(bi, 0, sizeof(*bi)); |
| 431 | } | 438 | } |
| 432 | EXPORT_SYMBOL(blk_integrity_unregister); | 439 | EXPORT_SYMBOL(blk_integrity_unregister); |
| 433 | 440 | ||
| @@ -208,7 +208,7 @@ static struct request *blk_mq_find_and_get_req(struct blk_mq_tags *tags, · 207 unmodified lines | |||
| 208 | 208 | ||
| 209 | spin_lock_irqsave(&tags->lock, flags); | 209 | spin_lock_irqsave(&tags->lock, flags); |
| 210 | rq = tags->rqs[bitnr]; | 210 | rq = tags->rqs[bitnr]; |
| 211 | if (!rq || !refcount_inc_not_zero(&rq->ref)) | 211 | if (!rq || rq->tag != bitnr || !refcount_inc_not_zero(&rq->ref)) |
| 212 | rq = NULL; | 212 | rq = NULL; |
| 213 | spin_unlock_irqrestore(&tags->lock, flags); | 213 | spin_unlock_irqrestore(&tags->lock, flags); |
| 214 | return rq; | 214 | return rq; |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/export.h> | 13 | #include <linux/export.h> |
| 14 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
| 15 | #include <linux/suspend.h> | 15 | #include <linux/suspend.h> |
| 16 | #include <linux/init.h> | ||
| 16 | 17 | ||
| 17 | #include <linux/mc146818rtc.h> | 18 | #include <linux/mc146818rtc.h> |
| 18 | 19 | ||
| @@ -165,6 +166,9 @@ void generate_pm_trace(const void *tracedata, unsigned int user) · 146 unmodified lines | |||
| 165 | const char *file = *(const char **)(tracedata + 2); | 166 | const char *file = *(const char **)(tracedata + 2); |
| 166 | unsigned int user_hash_value, file_hash_value; | 167 | unsigned int user_hash_value, file_hash_value; |
| 167 | 168 | ||
| 169 | if (!x86_platform.legacy.rtc) | ||
| 170 | return; | ||
| 171 | |||
| 168 | user_hash_value = user % USERHASH; | 172 | user_hash_value = user % USERHASH; |
| 169 | file_hash_value = hash_string(lineno, file, FILEHASH); | 173 | file_hash_value = hash_string(lineno, file, FILEHASH); |
| 170 | set_magic_time(user_hash_value, file_hash_value, dev_hash_value); | 174 | set_magic_time(user_hash_value, file_hash_value, dev_hash_value); |
| @@ -267,6 +271,9 @@ static struct notifier_block pm_trace_nb = { · 96 unmodified lines | |||
| 267 | 271 | ||
| 268 | static int __init early_resume_init(void) | 272 | static int __init early_resume_init(void) |
| 269 | { | 273 | { |
| 274 | if (!x86_platform.legacy.rtc) | ||
| 275 | return 0; | ||
| 276 | |||
| 270 | hash_value_early_read = read_magic_time(); | 277 | hash_value_early_read = read_magic_time(); |
| 271 | register_pm_notifier(&pm_trace_nb); | 278 | register_pm_notifier(&pm_trace_nb); |
| 272 | return 0; | 279 | return 0; |
| @@ -277,6 +284,9 @@ static int __init late_resume_init(void) · 4 unmodified lines | |||
| 277 | unsigned int val = hash_value_early_read; | 284 | unsigned int val = hash_value_early_read; |
| 278 | unsigned int user, file, dev; | 285 | unsigned int user, file, dev; |
| 279 | 286 | ||
| 287 | if (!x86_platform.legacy.rtc) | ||
| 288 | return 0; | ||
| 289 | |||
| 280 | user = val % USERHASH; | 290 | user = val % USERHASH; |
| 281 | val = val / USERHASH; | 291 | val = val / USERHASH; |
| 282 | file = val % FILEHASH; | 292 | file = val % FILEHASH; |
| @@ -74,8 +74,8 @@ unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *l · 73 unmodified lines | |||
| 74 | if (count) | 74 | if (count) |
| 75 | return count; | 75 | return count; |
| 76 | 76 | ||
| 77 | kobject_put(&attr_set->kobj); | ||
| 78 | mutex_destroy(&attr_set->update_lock); | 77 | mutex_destroy(&attr_set->update_lock); |
| 78 | kobject_put(&attr_set->kobj); | ||
| 79 | return 0; | 79 | return 0; |
| 80 | } | 80 | } |
| 81 | EXPORT_SYMBOL_GPL(gov_attr_set_put); | 81 | EXPORT_SYMBOL_GPL(gov_attr_set_put); |
| @@ -3205,11 +3205,15 @@ static int __init intel_pstate_init(void) · 3204 unmodified lines | |||
| 3205 | if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) | 3205 | if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) |
| 3206 | return -ENODEV; | 3206 | return -ENODEV; |
| 3207 | 3207 | ||
| 3208 | if (no_load) | ||
| 3209 | return -ENODEV; | ||
| 3210 | |||
| 3211 | id = x86_match_cpu(hwp_support_ids); | 3208 | id = x86_match_cpu(hwp_support_ids); |
| 3212 | if (id) { | 3209 | if (id) { |
| 3210 | bool hwp_forced = intel_pstate_hwp_is_enabled(); | ||
| 3211 | |||
| 3212 | if (hwp_forced) | ||
| 3213 | pr_info("HWP enabled by BIOS\n"); | ||
| 3214 | else if (no_load) | ||
| 3215 | return -ENODEV; | ||
| 3216 | |||
| 3213 | copy_cpu_funcs(&core_funcs); | 3217 | copy_cpu_funcs(&core_funcs); |
| 3214 | /* | 3218 | /* |
| 3215 | * Avoid enabling HWP for processors without EPP support, | 3219 | * Avoid enabling HWP for processors without EPP support, |
| @@ -3219,8 +3223,7 @@ static int __init intel_pstate_init(void) · 3 unmodified lines | |||
| 3219 | * If HWP is enabled already, though, there is no choice but to | 3223 | * If HWP is enabled already, though, there is no choice but to |
| 3220 | * deal with it. | 3224 | * deal with it. |
| 3221 | */ | 3225 | */ |
| 3222 | if ((!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) || | 3226 | if ((!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) || hwp_forced) { |
| 3223 | intel_pstate_hwp_is_enabled()) { | ||
| 3224 | hwp_active++; | 3227 | hwp_active++; |
| 3225 | hwp_mode_bdw = id->driver_data; | 3228 | hwp_mode_bdw = id->driver_data; |
| 3226 | intel_pstate.attr = hwp_cpufreq_attrs; | 3229 | intel_pstate.attr = hwp_cpufreq_attrs; |
| @@ -3235,7 +3238,11 @@ static int __init intel_pstate_init(void) · 8 unmodified lines | |||
| 3235 | 3238 | ||
| 3236 | goto hwp_cpu_matched; | 3239 | goto hwp_cpu_matched; |
| 3237 | } | 3240 | } |
| 3241 | pr_info("HWP not enabled\n"); | ||
| 3238 | } else { | 3242 | } else { |
| 3243 | if (no_load) | ||
| 3244 | return -ENODEV; | ||
| 3245 | |||
| 3239 | id = x86_match_cpu(intel_pstate_cpu_ids); | 3246 | id = x86_match_cpu(intel_pstate_cpu_ids); |
| 3240 | if (!id) { | 3247 | if (!id) { |
| 3241 | pr_info("CPU model not supported\n"); | 3248 | pr_info("CPU model not supported\n"); |
| @@ -3314,10 +3321,9 @@ static int __init intel_pstate_setup(char *str) · 72 unmodified lines | |||
| 3314 | else if (!strcmp(str, "passive")) | 3321 | else if (!strcmp(str, "passive")) |
| 3315 | default_driver = &intel_cpufreq; | 3322 | default_driver = &intel_cpufreq; |
| 3316 | 3323 | ||
| 3317 | if (!strcmp(str, "no_hwp")) { | 3324 | if (!strcmp(str, "no_hwp")) |
| 3318 | pr_info("HWP disabled\n"); | ||
| 3319 | no_hwp = 1; | 3325 | no_hwp = 1; |
| 3320 | } | 3326 | |
| 3321 | if (!strcmp(str, "force")) | 3327 | if (!strcmp(str, "force")) |
| 3322 | force_load = 1; | 3328 | force_load = 1; |
| 3323 | if (!strcmp(str, "hwp_only")) | 3329 | if (!strcmp(str, "hwp_only")) |
| @@ -758,7 +758,7 @@ enum amd_hw_ip_block_type { · 757 unmodified lines | |||
| 758 | MAX_HWIP | 758 | MAX_HWIP |
| 759 | }; | 759 | }; |
| 760 | 760 | ||
| 761 | #define HWIP_MAX_INSTANCE 8 | 761 | #define HWIP_MAX_INSTANCE 10 |
| 762 | 762 | ||
| 763 | struct amd_powerplay { | 763 | struct amd_powerplay { |
| 764 | void *pp_handle; | 764 | void *pp_handle; |
| @@ -192,6 +192,16 @@ void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm) · 191 unmodified lines | |||
| 192 | kgd2kfd_suspend(adev->kfd.dev, run_pm); | 192 | kgd2kfd_suspend(adev->kfd.dev, run_pm); |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | int amdgpu_amdkfd_resume_iommu(struct amdgpu_device *adev) | ||
| 196 | { | ||
| 197 | int r = 0; | ||
| 198 | |||
| 199 | if (adev->kfd.dev) | ||
| 200 | r = kgd2kfd_resume_iommu(adev->kfd.dev); | ||
| 201 | |||
| 202 | return r; | ||
| 203 | } | ||
| 204 | |||
| 195 | int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm) | 205 | int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm) |
| 196 | { | 206 | { |
| 197 | int r = 0; | 207 | int r = 0; |
| @@ -137,6 +137,7 @@ int amdgpu_amdkfd_init(void); · 136 unmodified lines | |||
| 137 | void amdgpu_amdkfd_fini(void); | 137 | void amdgpu_amdkfd_fini(void); |
| 138 | 138 | ||
| 139 | void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm); | 139 | void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm); |
| 140 | int amdgpu_amdkfd_resume_iommu(struct amdgpu_device *adev); | ||
| 140 | int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm); | 141 | int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm); |
| 141 | void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev, | 142 | void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev, |
| 142 | const void *ih_ring_entry); | 143 | const void *ih_ring_entry); |
| @@ -327,6 +328,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, · 184 unmodified lines | |||
| 327 | const struct kgd2kfd_shared_resources *gpu_resources); | 328 | const struct kgd2kfd_shared_resources *gpu_resources); |
| 328 | void kgd2kfd_device_exit(struct kfd_dev *kfd); | 329 | void kgd2kfd_device_exit(struct kfd_dev *kfd); |
| 329 | void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm); | 330 | void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm); |
| 331 | int kgd2kfd_resume_iommu(struct kfd_dev *kfd); | ||
| 330 | int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm); | 332 | int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm); |
| 331 | int kgd2kfd_pre_reset(struct kfd_dev *kfd); | 333 | int kgd2kfd_pre_reset(struct kfd_dev *kfd); |
| 332 | int kgd2kfd_post_reset(struct kfd_dev *kfd); | 334 | int kgd2kfd_post_reset(struct kfd_dev *kfd); |
| @@ -365,6 +367,11 @@ static inline void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) · 32 unmodified lines | |||
| 365 | { | 367 | { |
| 366 | } | 368 | } |
| 367 | 369 | ||
| 370 | static int __maybe_unused kgd2kfd_resume_iommu(struct kfd_dev *kfd) | ||
| 371 | { | ||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | |||
| 368 | static inline int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) | 375 | static inline int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) |
| 369 | { | 376 | { |
| 370 | return 0; | 377 | return 0; |
| @@ -1544,20 +1544,18 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) · 1543 unmodified lines | |||
| 1544 | struct dentry *ent; | 1544 | struct dentry *ent; |
| 1545 | int r, i; | 1545 | int r, i; |
| 1546 | 1546 | ||
| 1547 | |||
| 1548 | |||
| 1549 | ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev, | 1547 | ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev, |
| 1550 | &fops_ib_preempt); | 1548 | &fops_ib_preempt); |
| 1551 | if (!ent) { | 1549 | if (IS_ERR(ent)) { |
| 1552 | DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n"); | 1550 | DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n"); |
| 1553 | return -EIO; | 1551 | return PTR_ERR(ent); |
| 1554 | } | 1552 | } |
| 1555 | 1553 | ||
| 1556 | ent = debugfs_create_file("amdgpu_force_sclk", 0200, root, adev, | 1554 | ent = debugfs_create_file("amdgpu_force_sclk", 0200, root, adev, |
| 1557 | &fops_sclk_set); | 1555 | &fops_sclk_set); |
| 1558 | if (!ent) { | 1556 | if (IS_ERR(ent)) { |
| 1559 | DRM_ERROR("unable to create amdgpu_set_sclk debugsfs file\n"); | 1557 | DRM_ERROR("unable to create amdgpu_set_sclk debugsfs file\n"); |
| 1560 | return -EIO; | 1558 | return PTR_ERR(ent); |
| 1561 | } | 1559 | } |
| 1562 | 1560 | ||
| 1563 | /* Register debugfs entries for amdgpu_ttm */ | 1561 | /* Register debugfs entries for amdgpu_ttm */ |
| @@ -2394,6 +2394,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) · 2393 unmodified lines | |||
| 2394 | if (r) | 2394 | if (r) |
| 2395 | goto init_failed; | 2395 | goto init_failed; |
| 2396 | 2396 | ||
| 2397 | r = amdgpu_amdkfd_resume_iommu(adev); | ||
| 2398 | if (r) | ||
| 2399 | goto init_failed; | ||
| 2400 | |||
| 2397 | r = amdgpu_device_ip_hw_init_phase1(adev); | 2401 | r = amdgpu_device_ip_hw_init_phase1(adev); |
| 2398 | if (r) | 2402 | if (r) |
| 2399 | goto init_failed; | 2403 | goto init_failed; |
| @@ -3148,6 +3152,10 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev) · 748 unmodified lines | |||
| 3148 | { | 3152 | { |
| 3149 | int r; | 3153 | int r; |
| 3150 | 3154 | ||
| 3155 | r = amdgpu_amdkfd_resume_iommu(adev); | ||
| 3156 | if (r) | ||
| 3157 | return r; | ||
| 3158 | |||
| 3151 | r = amdgpu_device_ip_resume_phase1(adev); | 3159 | r = amdgpu_device_ip_resume_phase1(adev); |
| 3152 | if (r) | 3160 | if (r) |
| 3153 | return r; | 3161 | return r; |
| @@ -4601,6 +4609,10 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle, · 1447 unmodified lines | |||
| 4601 | dev_warn(tmp_adev->dev, "asic atom init failed!"); | 4609 | dev_warn(tmp_adev->dev, "asic atom init failed!"); |
| 4602 | } else { | 4610 | } else { |
| 4603 | dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); | 4611 | dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); |
| 4612 | r = amdgpu_amdkfd_resume_iommu(tmp_adev); | ||
| 4613 | if (r) | ||
| 4614 | goto out; | ||
| 4615 | |||
| 4604 | r = amdgpu_device_ip_resume_phase1(tmp_adev); | 4616 | r = amdgpu_device_ip_resume_phase1(tmp_adev); |
| 4605 | if (r) | 4617 | if (r) |
| 4606 | goto out; | 4618 | goto out; |
| @@ -598,7 +598,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) · 597 unmodified lines | |||
| 598 | break; | 598 | break; |
| 599 | default: | 599 | default: |
| 600 | adev->gmc.tmz_enabled = false; | 600 | adev->gmc.tmz_enabled = false; |
| 601 | dev_warn(adev->dev, | 601 | dev_info(adev->dev, |
| 602 | "Trusted Memory Zone (TMZ) feature not supported\n"); | 602 | "Trusted Memory Zone (TMZ) feature not supported\n"); |
| 603 | break; | 603 | break; |
| 604 | } | 604 | } |
| @@ -757,7 +757,7 @@ Out: · 756 unmodified lines | |||
| 757 | return res; | 757 | return res; |
| 758 | } | 758 | } |
| 759 | 759 | ||
| 760 | inline uint32_t amdgpu_ras_eeprom_max_record_count(void) | 760 | uint32_t amdgpu_ras_eeprom_max_record_count(void) |
| 761 | { | 761 | { |
| 762 | return RAS_MAX_RECORD_COUNT; | 762 | return RAS_MAX_RECORD_COUNT; |
| 763 | } | 763 | } |
| @@ -120,7 +120,7 @@ int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control, · 119 unmodified lines | |||
| 120 | int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control, | 120 | int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control, |
| 121 | struct eeprom_table_record *records, const u32 num); | 121 | struct eeprom_table_record *records, const u32 num); |
| 122 | 122 | ||
| 123 | inline uint32_t amdgpu_ras_eeprom_max_record_count(void); | 123 | uint32_t amdgpu_ras_eeprom_max_record_count(void); |
| 124 | 124 | ||
| 125 | void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control); | 125 | void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control); |
| 126 | 126 | ||
| @@ -428,8 +428,8 @@ int amdgpu_debugfs_ring_init(struct amdgpu_device *adev, · 427 unmodified lines | |||
| 428 | ent = debugfs_create_file(name, | 428 | ent = debugfs_create_file(name, |
| 429 | S_IFREG | S_IRUGO, root, | 429 | S_IFREG | S_IRUGO, root, |
| 430 | ring, &amdgpu_debugfs_ring_fops); | 430 | ring, &amdgpu_debugfs_ring_fops); |
| 431 | if (!ent) | 431 | if (IS_ERR(ent)) |
| 432 | return -ENOMEM; | 432 | return PTR_ERR(ent); |
| 433 | 433 | ||
| 434 | i_size_write(ent->d_inode, ring->ring_size + 12); | 434 | i_size_write(ent->d_inode, ring->ring_size + 12); |
| 435 | ring->ent = ent; | 435 | ring->ent = ent; |
| @@ -515,6 +515,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, · 514 unmodified lines | |||
| 515 | goto out; | 515 | goto out; |
| 516 | } | 516 | } |
| 517 | 517 | ||
| 518 | if (bo->type == ttm_bo_type_device && | ||
| 519 | new_mem->mem_type == TTM_PL_VRAM && | ||
| 520 | old_mem->mem_type != TTM_PL_VRAM) { | ||
| 521 | /* amdgpu_bo_fault_reserve_notify will re-set this if the CPU | ||
| 522 | * accesses the BO after it's moved. | ||
| 523 | */ | ||
| 524 | abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; | ||
| 525 | } | ||
| 526 | |||
| 518 | if (adev->mman.buffer_funcs_enabled) { | 527 | if (adev->mman.buffer_funcs_enabled) { |
| 519 | if (((old_mem->mem_type == TTM_PL_SYSTEM && | 528 | if (((old_mem->mem_type == TTM_PL_SYSTEM && |
| 520 | new_mem->mem_type == TTM_PL_VRAM) || | 529 | new_mem->mem_type == TTM_PL_VRAM) || |
| @@ -545,15 +554,6 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, · 24 unmodified lines | |||
| 545 | return r; | 554 | return r; |
| 546 | } | 555 | } |
| 547 | 556 | ||
| 548 | if (bo->type == ttm_bo_type_device && | ||
| 549 | new_mem->mem_type == TTM_PL_VRAM && | ||
| 550 | old_mem->mem_type != TTM_PL_VRAM) { | ||
| 551 | /* amdgpu_bo_fault_reserve_notify will re-set this if the CPU | ||
| 552 | * accesses the BO after it's moved. | ||
| 553 | */ | ||
| 554 | abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; | ||
| 555 | } | ||
| 556 | |||
| 557 | out: | 557 | out: |
| 558 | /* update statistics */ | 558 | /* update statistics */ |
| 559 | atomic64_add(bo->base.size, &adev->num_bytes_moved); | 559 | atomic64_add(bo->base.size, &adev->num_bytes_moved); |
| @@ -468,6 +468,7 @@ static const struct kfd_device_info navi10_device_info = { · 467 unmodified lines | |||
| 468 | .needs_iommu_device = false, | 468 | .needs_iommu_device = false, |
| 469 | .supports_cwsr = true, | 469 | .supports_cwsr = true, |
| 470 | .needs_pci_atomics = true, | 470 | .needs_pci_atomics = true, |
| 471 | .no_atomic_fw_version = 145, | ||
| 471 | .num_sdma_engines = 2, | 472 | .num_sdma_engines = 2, |
| 472 | .num_xgmi_sdma_engines = 0, | 473 | .num_xgmi_sdma_engines = 0, |
| 473 | .num_sdma_queues_per_engine = 8, | 474 | .num_sdma_queues_per_engine = 8, |
| @@ -487,6 +488,7 @@ static const struct kfd_device_info navi12_device_info = { · 13 unmodified lines | |||
| 487 | .needs_iommu_device = false, | 488 | .needs_iommu_device = false, |
| 488 | .supports_cwsr = true, | 489 | .supports_cwsr = true, |
| 489 | .needs_pci_atomics = true, | 490 | .needs_pci_atomics = true, |
| 491 | .no_atomic_fw_version = 145, | ||
| 490 | .num_sdma_engines = 2, | 492 | .num_sdma_engines = 2, |
| 491 | .num_xgmi_sdma_engines = 0, | 493 | .num_xgmi_sdma_engines = 0, |
| 492 | .num_sdma_queues_per_engine = 8, | 494 | .num_sdma_queues_per_engine = 8, |
| @@ -506,6 +508,7 @@ static const struct kfd_device_info navi14_device_info = { · 13 unmodified lines | |||
| 506 | .needs_iommu_device = false, | 508 | .needs_iommu_device = false, |
| 507 | .supports_cwsr = true, | 509 | .supports_cwsr = true, |
| 508 | .needs_pci_atomics = true, | 510 | .needs_pci_atomics = true, |
| 511 | .no_atomic_fw_version = 145, | ||
| 509 | .num_sdma_engines = 2, | 512 | .num_sdma_engines = 2, |
| 510 | .num_xgmi_sdma_engines = 0, | 513 | .num_xgmi_sdma_engines = 0, |
| 511 | .num_sdma_queues_per_engine = 8, | 514 | .num_sdma_queues_per_engine = 8, |
| @@ -525,6 +528,7 @@ static const struct kfd_device_info sienna_cichlid_device_info = { · 13 unmodified lines | |||
| 525 | .needs_iommu_device = false, | 528 | .needs_iommu_device = false, |
| 526 | .supports_cwsr = true, | 529 | .supports_cwsr = true, |
| 527 | .needs_pci_atomics = true, | 530 | .needs_pci_atomics = true, |
| 531 | .no_atomic_fw_version = 92, | ||
| 528 | .num_sdma_engines = 4, | 532 | .num_sdma_engines = 4, |
| 529 | .num_xgmi_sdma_engines = 0, | 533 | .num_xgmi_sdma_engines = 0, |
| 530 | .num_sdma_queues_per_engine = 8, | 534 | .num_sdma_queues_per_engine = 8, |
| @@ -544,6 +548,7 @@ static const struct kfd_device_info navy_flounder_device_info = { · 13 unmodified lines | |||
| 544 | .needs_iommu_device = false, | 548 | .needs_iommu_device = false, |
| 545 | .supports_cwsr = true, | 549 | .supports_cwsr = true, |
| 546 | .needs_pci_atomics = true, | 550 | .needs_pci_atomics = true, |
| 551 | .no_atomic_fw_version = 92, | ||
| 547 | .num_sdma_engines = 2, | 552 | .num_sdma_engines = 2, |
| 548 | .num_xgmi_sdma_engines = 0, | 553 | .num_xgmi_sdma_engines = 0, |
| 549 | .num_sdma_queues_per_engine = 8, | 554 | .num_sdma_queues_per_engine = 8, |
| @@ -562,7 +567,8 @@ static const struct kfd_device_info vangogh_device_info = { · 12 unmodified lines | |||
| 562 | .mqd_size_aligned = MQD_SIZE_ALIGNED, | 567 | .mqd_size_aligned = MQD_SIZE_ALIGNED, |
| 563 | .needs_iommu_device = false, | 568 | .needs_iommu_device = false, |
| 564 | .supports_cwsr = true, | 569 | .supports_cwsr = true, |
| 565 | .needs_pci_atomics = false, | 570 | .needs_pci_atomics = true, |
| 571 | .no_atomic_fw_version = 92, | ||
| 566 | .num_sdma_engines = 1, | 572 | .num_sdma_engines = 1, |
| 567 | .num_xgmi_sdma_engines = 0, | 573 | .num_xgmi_sdma_engines = 0, |
| 568 | .num_sdma_queues_per_engine = 2, | 574 | .num_sdma_queues_per_engine = 2, |
| @@ -582,6 +588,7 @@ static const struct kfd_device_info dimgrey_cavefish_device_info = { · 13 unmodified lines | |||
| 582 | .needs_iommu_device = false, | 588 | .needs_iommu_device = false, |
| 583 | .supports_cwsr = true, | 589 | .supports_cwsr = true, |
| 584 | .needs_pci_atomics = true, | 590 | .needs_pci_atomics = true, |
| 591 | .no_atomic_fw_version = 92, | ||
| 585 | .num_sdma_engines = 2, | 592 | .num_sdma_engines = 2, |
| 586 | .num_xgmi_sdma_engines = 0, | 593 | .num_xgmi_sdma_engines = 0, |
| 587 | .num_sdma_queues_per_engine = 8, | 594 | .num_sdma_queues_per_engine = 8, |
| @@ -601,6 +608,7 @@ static const struct kfd_device_info beige_goby_device_info = { · 13 unmodified lines | |||
| 601 | .needs_iommu_device = false, | 608 | .needs_iommu_device = false, |
| 602 | .supports_cwsr = true, | 609 | .supports_cwsr = true, |
| 603 | .needs_pci_atomics = true, | 610 | .needs_pci_atomics = true, |
| 611 | .no_atomic_fw_version = 92, | ||
| 604 | .num_sdma_engines = 1, | 612 | .num_sdma_engines = 1, |
| 605 | .num_xgmi_sdma_engines = 0, | 613 | .num_xgmi_sdma_engines = 0, |
| 606 | .num_sdma_queues_per_engine = 8, | 614 | .num_sdma_queues_per_engine = 8, |
| @@ -619,7 +627,8 @@ static const struct kfd_device_info yellow_carp_device_info = { · 12 unmodified lines | |||
| 619 | .mqd_size_aligned = MQD_SIZE_ALIGNED, | 627 | .mqd_size_aligned = MQD_SIZE_ALIGNED, |
| 620 | .needs_iommu_device = false, | 628 | .needs_iommu_device = false, |
| 621 | .supports_cwsr = true, | 629 | .supports_cwsr = true, |
| 622 | .needs_pci_atomics = false, | 630 | .needs_pci_atomics = true, |
| 631 | .no_atomic_fw_version = 92, | ||
| 623 | .num_sdma_engines = 1, | 632 | .num_sdma_engines = 1, |
| 624 | .num_xgmi_sdma_engines = 0, | 633 | .num_xgmi_sdma_engines = 0, |
| 625 | .num_sdma_queues_per_engine = 2, | 634 | .num_sdma_queues_per_engine = 2, |
| @@ -708,20 +717,6 @@ struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, · 82 unmodified lines | |||
| 708 | if (!kfd) | 717 | if (!kfd) |
| 709 | return NULL; | 718 | return NULL; |
| 710 | 719 | ||
| 711 | /* Allow BIF to recode atomics to PCIe 3.0 AtomicOps. | ||
| 712 | * 32 and 64-bit requests are possible and must be | ||
| 713 | * supported. | ||
| 714 | */ | ||
| 715 | kfd->pci_atomic_requested = amdgpu_amdkfd_have_atomics_support(kgd); | ||
| 716 | if (device_info->needs_pci_atomics && | ||
| 717 | !kfd->pci_atomic_requested) { | ||
| 718 | dev_info(kfd_device, | ||
| 719 | "skipped device %x:%x, PCI rejects atomics\n", | ||
| 720 | pdev->vendor, pdev->device); | ||
| 721 | kfree(kfd); | ||
| 722 | return NULL; | ||
| 723 | } | ||
| 724 | |||
| 725 | kfd->kgd = kgd; | 720 | kfd->kgd = kgd; |
| 726 | kfd->device_info = device_info; | 721 | kfd->device_info = device_info; |
| 727 | kfd->pdev = pdev; | 722 | kfd->pdev = pdev; |
| @@ -821,6 +816,23 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, · 93 unmodified lines | |||
| 821 | kfd->vm_info.vmid_num_kfd = kfd->vm_info.last_vmid_kfd | 816 | kfd->vm_info.vmid_num_kfd = kfd->vm_info.last_vmid_kfd |
| 822 | - kfd->vm_info.first_vmid_kfd + 1; | 817 | - kfd->vm_info.first_vmid_kfd + 1; |
| 823 | 818 | ||
| 819 | /* Allow BIF to recode atomics to PCIe 3.0 AtomicOps. | ||
| 820 | * 32 and 64-bit requests are possible and must be | ||
| 821 | * supported. | ||
| 822 | */ | ||
| 823 | kfd->pci_atomic_requested = amdgpu_amdkfd_have_atomics_support(kfd->kgd); | ||
| 824 | if (!kfd->pci_atomic_requested && | ||
| 825 | kfd->device_info->needs_pci_atomics && | ||
| 826 | (!kfd->device_info->no_atomic_fw_version || | ||
| 827 | kfd->mec_fw_version < kfd->device_info->no_atomic_fw_version)) { | ||
| 828 | dev_info(kfd_device, | ||
| 829 | "skipped device %x:%x, PCI rejects atomics %d<%d\n", | ||
| 830 | kfd->pdev->vendor, kfd->pdev->device, | ||
| 831 | kfd->mec_fw_version, | ||
| 832 | kfd->device_info->no_atomic_fw_version); | ||
| 833 | return false; | ||
| 834 | } | ||
| 835 | |||
| 824 | /* Verify module parameters regarding mapped process number*/ | 836 | /* Verify module parameters regarding mapped process number*/ |
| 825 | if ((hws_max_conc_proc < 0) | 837 | if ((hws_max_conc_proc < 0) |
| 826 | || (hws_max_conc_proc > kfd->vm_info.vmid_num_kfd)) { | 838 | || (hws_max_conc_proc > kfd->vm_info.vmid_num_kfd)) { |
| @@ -1057,17 +1069,21 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) · 230 unmodified lines | |||
| 1057 | return ret; | 1069 | return ret; |
| 1058 | } | 1070 | } |
| 1059 | 1071 | ||
| 1060 | static int kfd_resume(struct kfd_dev *kfd) | 1072 | int kgd2kfd_resume_iommu(struct kfd_dev *kfd) |
| 1061 | { | 1073 | { |
| 1062 | int err = 0; | 1074 | int err = 0; |
| 1063 | 1075 | ||
| 1064 | err = kfd_iommu_resume(kfd); | 1076 | err = kfd_iommu_resume(kfd); |
| 1065 | if (err) { | 1077 | if (err) |
| 1066 | dev_err(kfd_device, | 1078 | dev_err(kfd_device, |
| 1067 | "Failed to resume IOMMU for device %x:%x\n", | 1079 | "Failed to resume IOMMU for device %x:%x\n", |
| 1068 | kfd->pdev->vendor, kfd->pdev->device); | 1080 | kfd->pdev->vendor, kfd->pdev->device); |
| 1069 | return err; | 1081 | return err; |
| 1070 | } | 1082 | } |
| 1083 | |||
| 1084 | static int kfd_resume(struct kfd_dev *kfd) | ||
| 1085 | { | ||
| 1086 | int err = 0; | ||
| 1071 | 1087 | ||
| 1072 | err = kfd->dqm->ops.start(kfd->dqm); | 1088 | err = kfd->dqm->ops.start(kfd->dqm); |
| 1073 | if (err) { | 1089 | if (err) { |
| @@ -207,6 +207,7 @@ struct kfd_device_info { · 206 unmodified lines | |||
| 207 | bool supports_cwsr; | 207 | bool supports_cwsr; |
| 208 | bool needs_iommu_device; | 208 | bool needs_iommu_device; |
| 209 | bool needs_pci_atomics; | 209 | bool needs_pci_atomics; |
| 210 | uint32_t no_atomic_fw_version; | ||
| 210 | unsigned int num_sdma_engines; | 211 | unsigned int num_sdma_engines; |
| 211 | unsigned int num_xgmi_sdma_engines; | 212 | unsigned int num_xgmi_sdma_engines; |
| 212 | unsigned int num_sdma_queues_per_engine; | 213 | unsigned int num_sdma_queues_per_engine; |
| @@ -998,6 +998,8 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_ · 997 unmodified lines | |||
| 998 | uint32_t agp_base, agp_bot, agp_top; | 998 | uint32_t agp_base, agp_bot, agp_top; |
| 999 | PHYSICAL_ADDRESS_LOC page_table_start, page_table_end, page_table_base; | 999 | PHYSICAL_ADDRESS_LOC page_table_start, page_table_end, page_table_base; |
| 1000 | 1000 | ||
| 1001 | memset(pa_config, 0, sizeof(*pa_config)); | ||
| 1002 | |||
| 1001 | logical_addr_low = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18; | 1003 | logical_addr_low = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18; |
| 1002 | pt_base = amdgpu_gmc_pd_addr(adev->gart.bo); | 1004 | pt_base = amdgpu_gmc_pd_addr(adev->gart.bo); |
| 1003 | 1005 | ||
| @@ -6024,21 +6026,23 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) · 5020 unmodified lines | |||
| 6024 | return 0; | 6026 | return 0; |
| 6025 | 6027 | ||
| 6026 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 6028 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 6027 | work = kzalloc(sizeof(*work), GFP_ATOMIC); | 6029 | if (dm->vblank_control_workqueue) { |
| 6028 | if (!work) | 6030 | work = kzalloc(sizeof(*work), GFP_ATOMIC); |
| 6029 | return -ENOMEM; | 6031 | if (!work) |
| 6032 | return -ENOMEM; | ||
| 6030 | 6033 | ||
| 6031 | INIT_WORK(&work->work, vblank_control_worker); | 6034 | INIT_WORK(&work->work, vblank_control_worker); |
| 6032 | work->dm = dm; | 6035 | work->dm = dm; |
| 6033 | work->acrtc = acrtc; | 6036 | work->acrtc = acrtc; |
| 6034 | work->enable = enable; | 6037 | work->enable = enable; |
| 6035 | 6038 | ||
| 6036 | if (acrtc_state->stream) { | 6039 | if (acrtc_state->stream) { |
| 6037 | dc_stream_retain(acrtc_state->stream); | 6040 | dc_stream_retain(acrtc_state->stream); |
| 6038 | work->stream = acrtc_state->stream; | 6041 | work->stream = acrtc_state->stream; |
| 6039 | } | 6042 | } |
| 6040 | 6043 | ||
| 6041 | queue_work(dm->vblank_control_workqueue, &work->work); | 6044 | queue_work(dm->vblank_control_workqueue, &work->work); |
| 6045 | } | ||
| 6042 | #endif | 6046 | #endif |
| 6043 | 6047 | ||
| 6044 | return 0; | 6048 | return 0; |
| @@ -6792,14 +6796,15 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { · 747 unmodified lines | |||
| 6792 | 6796 | ||
| 6793 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 6797 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 6794 | static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, | 6798 | static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, |
| 6795 | struct dc_state *dc_state) | 6799 | struct dc_state *dc_state, |
| 6800 | struct dsc_mst_fairness_vars *vars) | ||
| 6796 | { | 6801 | { |
| 6797 | struct dc_stream_state *stream = NULL; | 6802 | struct dc_stream_state *stream = NULL; |
| 6798 | struct drm_connector *connector; | 6803 | struct drm_connector *connector; |
| 6799 | struct drm_connector_state *new_con_state; | 6804 | struct drm_connector_state *new_con_state; |
| 6800 | struct amdgpu_dm_connector *aconnector; | 6805 | struct amdgpu_dm_connector *aconnector; |
| 6801 | struct dm_connector_state *dm_conn_state; | 6806 | struct dm_connector_state *dm_conn_state; |
| 6802 | int i, j, clock, bpp; | 6807 | int i, j, clock; |
| 6803 | int vcpi, pbn_div, pbn = 0; | 6808 | int vcpi, pbn_div, pbn = 0; |
| 6804 | 6809 | ||
| 6805 | for_each_new_connector_in_state(state, connector, new_con_state, i) { | 6810 | for_each_new_connector_in_state(state, connector, new_con_state, i) { |
| @@ -6838,9 +6843,15 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, · 32 unmodified lines | |||
| 6838 | } | 6843 | } |
| 6839 | 6844 | ||
| 6840 | pbn_div = dm_mst_get_pbn_divider(stream->link); | 6845 | pbn_div = dm_mst_get_pbn_divider(stream->link); |
| 6841 | bpp = stream->timing.dsc_cfg.bits_per_pixel; | ||
| 6842 | clock = stream->timing.pix_clk_100hz / 10; | 6846 | clock = stream->timing.pix_clk_100hz / 10; |
| 6843 | pbn = drm_dp_calc_pbn_mode(clock, bpp, true); | 6847 | /* pbn is calculated by compute_mst_dsc_configs_for_state*/ |
| 6848 | for (j = 0; j < dc_state->stream_count; j++) { | ||
| 6849 | if (vars[j].aconnector == aconnector) { | ||
| 6850 | pbn = vars[j].pbn; | ||
| 6851 | break; | ||
| 6852 | } | ||
| 6853 | } | ||
| 6854 | |||
| 6844 | vcpi = drm_dp_mst_atomic_enable_dsc(state, | 6855 | vcpi = drm_dp_mst_atomic_enable_dsc(state, |
| 6845 | aconnector->port, | 6856 | aconnector->port, |
| 6846 | pbn, pbn_div, | 6857 | pbn, pbn_div, |
| @@ -7519,6 +7530,32 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, · 672 unmodified lines | |||
| 7519 | } | 7530 | } |
| 7520 | } | 7531 | } |
| 7521 | 7532 | ||
| 7533 | static void amdgpu_set_panel_orientation(struct drm_connector *connector) | ||
| 7534 | { | ||
| 7535 | struct drm_encoder *encoder; | ||
| 7536 | struct amdgpu_encoder *amdgpu_encoder; | ||
| 7537 | const struct drm_display_mode *native_mode; | ||
| 7538 | |||
| 7539 | if (connector->connector_type != DRM_MODE_CONNECTOR_eDP && | ||
| 7540 | connector->connector_type != DRM_MODE_CONNECTOR_LVDS) | ||
| 7541 | return; | ||
| 7542 | |||
| 7543 | encoder = amdgpu_dm_connector_to_encoder(connector); | ||
| 7544 | if (!encoder) | ||
| 7545 | return; | ||
| 7546 | |||
| 7547 | amdgpu_encoder = to_amdgpu_encoder(encoder); | ||
| 7548 | |||
| 7549 | native_mode = &amdgpu_encoder->native_mode; | ||
| 7550 | if (native_mode->hdisplay == 0 || native_mode->vdisplay == 0) | ||
| 7551 | return; | ||
| 7552 | |||
| 7553 | drm_connector_set_panel_orientation_with_quirk(connector, | ||
| 7554 | DRM_MODE_PANEL_ORIENTATION_UNKNOWN, | ||
| 7555 | native_mode->hdisplay, | ||
| 7556 | native_mode->vdisplay); | ||
| 7557 | } | ||
| 7558 | |||
| 7522 | static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, | 7559 | static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, |
| 7523 | struct edid *edid) | 7560 | struct edid *edid) |
| 7524 | { | 7561 | { |
| @@ -7547,6 +7584,8 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, · 22 unmodified lines | |||
| 7547 | * restored here. | 7584 | * restored here. |
| 7548 | */ | 7585 | */ |
| 7549 | amdgpu_dm_update_freesync_caps(connector, edid); | 7586 | amdgpu_dm_update_freesync_caps(connector, edid); |
| 7587 | |||
| 7588 | amdgpu_set_panel_orientation(connector); | ||
| 7550 | } else { | 7589 | } else { |
| 7551 | amdgpu_dm_connector->num_modes = 0; | 7590 | amdgpu_dm_connector->num_modes = 0; |
| 7552 | } | 7591 | } |
| @@ -8058,8 +8097,26 @@ static bool is_content_protection_different(struct drm_connector_state *state, · 505 unmodified lines | |||
| 8058 | state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED) | 8097 | state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED) |
| 8059 | state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; | 8098 | state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; |
| 8060 | 8099 | ||
| 8061 | /* Check if something is connected/enabled, otherwise we start hdcp but nothing is connected/enabled | 8100 | /* Stream removed and re-enabled |
| 8062 | * hot-plug, headless s3, dpms | 8101 | * |
| 8102 | * Can sometimes overlap with the HPD case, | ||
| 8103 | * thus set update_hdcp to false to avoid | ||
| 8104 | * setting HDCP multiple times. | ||
| 8105 | * | ||
| 8106 | * Handles: DESIRED -> DESIRED (Special case) | ||
| 8107 | */ | ||
| 8108 | if (!(old_state->crtc && old_state->crtc->enabled) && | ||
| 8109 | state->crtc && state->crtc->enabled && | ||
| 8110 | connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) { | ||
| 8111 | dm_con_state->update_hdcp = false; | ||
| 8112 | return true; | ||
| 8113 | } | ||
| 8114 | |||
| 8115 | /* Hot-plug, headless s3, dpms | ||
| 8116 | * | ||
| 8117 | * Only start HDCP if the display is connected/enabled. | ||
| 8118 | * update_hdcp flag will be set to false until the next | ||
| 8119 | * HPD comes in. | ||
| 8063 | * | 8120 | * |
| 8064 | * Handles: DESIRED -> DESIRED (Special case) | 8121 | * Handles: DESIRED -> DESIRED (Special case) |
| 8065 | */ | 8122 | */ |
| @@ -8648,7 +8705,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, · 582 unmodified lines | |||
| 8648 | * If PSR or idle optimizations are enabled then flush out | 8705 | * If PSR or idle optimizations are enabled then flush out |
| 8649 | * any pending work before hardware programming. | 8706 | * any pending work before hardware programming. |
| 8650 | */ | 8707 | */ |
| 8651 | flush_workqueue(dm->vblank_control_workqueue); | 8708 | if (dm->vblank_control_workqueue) |
| 8709 | flush_workqueue(dm->vblank_control_workqueue); | ||
| 8652 | #endif | 8710 | #endif |
| 8653 | 8711 | ||
| 8654 | bundle->stream_update.stream = acrtc_state->stream; | 8712 | bundle->stream_update.stream = acrtc_state->stream; |
| @@ -8983,7 +9041,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) · 328 unmodified lines | |||
| 8983 | /* if there mode set or reset, disable eDP PSR */ | 9041 | /* if there mode set or reset, disable eDP PSR */ |
| 8984 | if (mode_set_reset_required) { | 9042 | if (mode_set_reset_required) { |
| 8985 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 9043 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 8986 | flush_workqueue(dm->vblank_control_workqueue); | 9044 | if (dm->vblank_control_workqueue) |
| 9045 | flush_workqueue(dm->vblank_control_workqueue); | ||
| 8987 | #endif | 9046 | #endif |
| 8988 | amdgpu_dm_psr_disable_all(dm); | 9047 | amdgpu_dm_psr_disable_all(dm); |
| 8989 | } | 9048 | } |
| @@ -10243,6 +10302,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, · 1253 unmodified lines | |||
| 10243 | int ret, i; | 10302 | int ret, i; |
| 10244 | bool lock_and_validation_needed = false; | 10303 | bool lock_and_validation_needed = false; |
| 10245 | struct dm_crtc_state *dm_old_crtc_state; | 10304 | struct dm_crtc_state *dm_old_crtc_state; |
| 10305 | #if defined(CONFIG_DRM_AMD_DC_DCN) | ||
| 10306 | struct dsc_mst_fairness_vars vars[MAX_PIPES]; | ||
| 10307 | #endif | ||
| 10246 | 10308 | ||
| 10247 | trace_amdgpu_dm_atomic_check_begin(state); | 10309 | trace_amdgpu_dm_atomic_check_begin(state); |
| 10248 | 10310 | ||
| @@ -10473,10 +10535,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, · 224 unmodified lines | |||
| 10473 | goto fail; | 10535 | goto fail; |
| 10474 | 10536 | ||
| 10475 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 10537 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 10476 | if (!compute_mst_dsc_configs_for_state(state, dm_state->context)) | 10538 | if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) |
| 10477 | goto fail; | 10539 | goto fail; |
| 10478 | 10540 | ||
| 10479 | ret = dm_update_mst_vcpi_slots_for_dsc(state, dm_state->context); | 10541 | ret = dm_update_mst_vcpi_slots_for_dsc(state, dm_state->context, vars); |
| 10480 | if (ret) | 10542 | if (ret) |
| 10481 | goto fail; | 10543 | goto fail; |
| 10482 | #endif | 10544 | #endif |
| @@ -10492,7 +10554,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, · 9 unmodified lines | |||
| 10492 | goto fail; | 10554 | goto fail; |
| 10493 | status = dc_validate_global_state(dc, dm_state->context, false); | 10555 | status = dc_validate_global_state(dc, dm_state->context, false); |
| 10494 | if (status != DC_OK) { | 10556 | if (status != DC_OK) { |
| 10495 | DC_LOG_WARNING("DC global validation failure: %s (%d)", | 10557 | drm_dbg_atomic(dev, |
| 10558 | "DC global validation failure: %s (%d)", | ||
| 10496 | dc_status_to_str(status), status); | 10559 | dc_status_to_str(status), status); |
| 10497 | ret = -EINVAL; | 10560 | ret = -EINVAL; |
| 10498 | goto fail; | 10561 | goto fail; |
| @@ -518,12 +518,7 @@ struct dsc_mst_fairness_params { · 517 unmodified lines | |||
| 518 | uint32_t num_slices_h; | 518 | uint32_t num_slices_h; |
| 519 | uint32_t num_slices_v; | 519 | uint32_t num_slices_v; |
| 520 | uint32_t bpp_overwrite; | 520 | uint32_t bpp_overwrite; |
| 521 | }; | 521 | struct amdgpu_dm_connector *aconnector; |
| 522 | |||
| 523 | struct dsc_mst_fairness_vars { | ||
| 524 | int pbn; | ||
| 525 | bool dsc_enabled; | ||
| 526 | int bpp_x16; | ||
| 527 | }; | 522 | }; |
| 528 | 523 | ||
| 529 | static int kbps_to_peak_pbn(int kbps) | 524 | static int kbps_to_peak_pbn(int kbps) |
| @@ -750,12 +745,12 @@ static void try_disable_dsc(struct drm_atomic_state *state, · 220 unmodified lines | |||
| 750 | 745 | ||
| 751 | static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, | 746 | static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, |
| 752 | struct dc_state *dc_state, | 747 | struct dc_state *dc_state, |
| 753 | struct dc_link *dc_link) | 748 | struct dc_link *dc_link, |
| 749 | struct dsc_mst_fairness_vars *vars) | ||
| 754 | { | 750 | { |
| 755 | int i; | 751 | int i; |
| 756 | struct dc_stream_state *stream; | 752 | struct dc_stream_state *stream; |
| 757 | struct dsc_mst_fairness_params params[MAX_PIPES]; | 753 | struct dsc_mst_fairness_params params[MAX_PIPES]; |
| 758 | struct dsc_mst_fairness_vars vars[MAX_PIPES]; | ||
| 759 | struct amdgpu_dm_connector *aconnector; | 754 | struct amdgpu_dm_connector *aconnector; |
| 760 | int count = 0; | 755 | int count = 0; |
| 761 | bool debugfs_overwrite = false; | 756 | bool debugfs_overwrite = false; |
| @@ -776,6 +771,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, · 14 unmodified lines | |||
| 776 | params[count].timing = &stream->timing; | 771 | params[count].timing = &stream->timing; |
| 777 | params[count].sink = stream->sink; | 772 | params[count].sink = stream->sink; |
| 778 | aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; | 773 | aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; |
| 774 | params[count].aconnector = aconnector; | ||
| 779 | params[count].port = aconnector->port; | 775 | params[count].port = aconnector->port; |
| 780 | params[count].clock_force_enable = aconnector->dsc_settings.dsc_force_enable; | 776 | params[count].clock_force_enable = aconnector->dsc_settings.dsc_force_enable; |
| 781 | if (params[count].clock_force_enable == DSC_CLK_FORCE_ENABLE) | 777 | if (params[count].clock_force_enable == DSC_CLK_FORCE_ENABLE) |
| @@ -798,6 +794,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, · 16 unmodified lines | |||
| 798 | } | 794 | } |
| 799 | /* Try no compression */ | 795 | /* Try no compression */ |
| 800 | for (i = 0; i < count; i++) { | 796 | for (i = 0; i < count; i++) { |
| 797 | vars[i].aconnector = params[i].aconnector; | ||
| 801 | vars[i].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); | 798 | vars[i].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); |
| 802 | vars[i].dsc_enabled = false; | 799 | vars[i].dsc_enabled = false; |
| 803 | vars[i].bpp_x16 = 0; | 800 | vars[i].bpp_x16 = 0; |
| @@ -851,7 +848,8 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, · 47 unmodified lines | |||
| 851 | } | 848 | } |
| 852 | 849 | ||
| 853 | bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, | 850 | bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, |
| 854 | struct dc_state *dc_state) | 851 | struct dc_state *dc_state, |
| 852 | struct dsc_mst_fairness_vars *vars) | ||
| 855 | { | 853 | { |
| 856 | int i, j; | 854 | int i, j; |
| 857 | struct dc_stream_state *stream; | 855 | struct dc_stream_state *stream; |
| @@ -882,7 +880,7 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, · 24 unmodified lines | |||
| 882 | return false; | 880 | return false; |
| 883 | 881 | ||
| 884 | mutex_lock(&aconnector->mst_mgr.lock); | 882 | mutex_lock(&aconnector->mst_mgr.lock); |
| 885 | if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link)) { | 883 | if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars)) { |
| 886 | mutex_unlock(&aconnector->mst_mgr.lock); | 884 | mutex_unlock(&aconnector->mst_mgr.lock); |
| 887 | return false; | 885 | return false; |
| 888 | } | 886 | } |
| @@ -39,8 +39,17 @@ void · 38 unmodified lines | |||
| 39 | dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev); | 39 | dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev); |
| 40 | 40 | ||
| 41 | #if defined(CONFIG_DRM_AMD_DC_DCN) | 41 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 42 | |||
| 43 | struct dsc_mst_fairness_vars { | ||
| 44 | int pbn; | ||
| 45 | bool dsc_enabled; | ||
| 46 | int bpp_x16; | ||
| 47 | struct amdgpu_dm_connector *aconnector; | ||
| 48 | }; | ||
| 49 | |||
| 42 | bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, | 50 | bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, |
| 43 | struct dc_state *dc_state); | 51 | struct dc_state *dc_state, |
| 52 | struct dsc_mst_fairness_vars *vars); | ||
| 44 | #endif | 53 | #endif |
| 45 | 54 | ||
| 46 | #endif | 55 | #endif |
| @@ -62,7 +62,7 @@ inline void dc_assert_fp_enabled(void) · 61 unmodified lines | |||
| 62 | depth = *pcpu; | 62 | depth = *pcpu; |
| 63 | put_cpu_ptr(&fpu_recursion_depth); | 63 | put_cpu_ptr(&fpu_recursion_depth); |
| 64 | 64 | ||
| 65 | ASSERT(depth > 1); | 65 | ASSERT(depth >= 1); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | /** | 68 | /** |
| @@ -2586,13 +2586,21 @@ static struct abm *get_abm_from_stream_res(const struct dc_link *link) · 2585 unmodified lines | |||
| 2586 | 2586 | ||
| 2587 | int dc_link_get_backlight_level(const struct dc_link *link) | 2587 | int dc_link_get_backlight_level(const struct dc_link *link) |
| 2588 | { | 2588 | { |
| 2589 | |||
| 2590 | struct abm *abm = get_abm_from_stream_res(link); | 2589 | struct abm *abm = get_abm_from_stream_res(link); |
| 2590 | struct panel_cntl *panel_cntl = link->panel_cntl; | ||
| 2591 | struct dc *dc = link->ctx->dc; | ||
| 2592 | struct dmcu *dmcu = dc->res_pool->dmcu; | ||
| 2593 | bool fw_set_brightness = true; | ||
| 2591 | 2594 | ||
| 2592 | if (abm == NULL || abm->funcs->get_current_backlight == NULL) | 2595 | if (dmcu) |
| 2593 | return DC_ERROR_UNEXPECTED; | 2596 | fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); |
| 2594 | 2597 | ||
| 2595 | return (int) abm->funcs->get_current_backlight(abm); | 2598 | if (!fw_set_brightness && panel_cntl->funcs->get_current_backlight) |
| 2599 | return panel_cntl->funcs->get_current_backlight(panel_cntl); | ||
| 2600 | else if (abm != NULL && abm->funcs->get_current_backlight != NULL) | ||
| 2601 | return (int) abm->funcs->get_current_backlight(abm); | ||
| 2602 | else | ||
| 2603 | return DC_ERROR_UNEXPECTED; | ||
| 2596 | } | 2604 | } |
| 2597 | 2605 | ||
| 2598 | int dc_link_get_target_backlight_pwm(const struct dc_link *link) | 2606 | int dc_link_get_target_backlight_pwm(const struct dc_link *link) |
| @@ -1,4 +1,26 @@ | |||
| 1 | /* Copyright 2015 Advanced Micro Devices, Inc. */ | 1 | /* |
| 2 | * Copyright 2015 Advanced Micro Devices, Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | * | ||
| 22 | * Authors: AMD | ||
| 23 | */ | ||
| 2 | #include "dm_services.h" | 24 | #include "dm_services.h" |
| 3 | #include "dc.h" | 25 | #include "dc.h" |
| 4 | #include "dc_link_dp.h" | 26 | #include "dc_link_dp.h" |
| @@ -1840,9 +1862,13 @@ bool perform_link_training_with_retries( · 1835 unmodified lines | |||
| 1840 | dp_disable_link_phy(link, signal); | 1862 | dp_disable_link_phy(link, signal); |
| 1841 | 1863 | ||
| 1842 | /* Abort link training if failure due to sink being unplugged. */ | 1864 | /* Abort link training if failure due to sink being unplugged. */ |
| 1843 | if (status == LINK_TRAINING_ABORT) | 1865 | if (status == LINK_TRAINING_ABORT) { |
| 1844 | break; | 1866 | enum dc_connection_type type = dc_connection_none; |
| 1845 | else if (do_fallback) { | 1867 | |
| 1868 | dc_link_detect_sink(link, &type); | ||
| 1869 | if (type == dc_connection_none) | ||
| 1870 | break; | ||
| 1871 | } else if (do_fallback) { | ||
| 1846 | decide_fallback_link_setting(*link_setting, ¤t_setting, status); | 1872 | decide_fallback_link_setting(*link_setting, ¤t_setting, status); |
| 1847 | /* Fail link training if reduced link bandwidth no longer meets | 1873 | /* Fail link training if reduced link bandwidth no longer meets |
| 1848 | * stream requirements. | 1874 | * stream requirements. |
| @@ -49,7 +49,6 @@ · 48 unmodified lines | |||
| 49 | static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl) | 49 | static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl) |
| 50 | { | 50 | { |
| 51 | uint64_t current_backlight; | 51 | uint64_t current_backlight; |
| 52 | uint32_t round_result; | ||
| 53 | uint32_t bl_period, bl_int_count; | 52 | uint32_t bl_period, bl_int_count; |
| 54 | uint32_t bl_pwm, fractional_duty_cycle_en; | 53 | uint32_t bl_pwm, fractional_duty_cycle_en; |
| 55 | uint32_t bl_period_mask, bl_pwm_mask; | 54 | uint32_t bl_period_mask, bl_pwm_mask; |
| @@ -84,15 +83,6 @@ static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_c · 28 unmodified lines | |||
| 84 | current_backlight = div_u64(current_backlight, bl_period); | 83 | current_backlight = div_u64(current_backlight, bl_period); |
| 85 | current_backlight = (current_backlight + 1) >> 1; | 84 | current_backlight = (current_backlight + 1) >> 1; |
| 86 | 85 | ||
| 87 | current_backlight = (uint64_t)(current_backlight) * bl_period; | ||
| 88 | |||
| 89 | round_result = (uint32_t)(current_backlight & 0xFFFFFFFF); | ||
| 90 | |||
| 91 | round_result = (round_result >> (bl_int_count-1)) & 1; | ||
| 92 | |||
| 93 | current_backlight >>= bl_int_count; | ||
| 94 | current_backlight += round_result; | ||
| 95 | |||
| 96 | return (uint32_t)(current_backlight); | 86 | return (uint32_t)(current_backlight); |
| 97 | } | 87 | } |
| 98 | 88 | ||
| @@ -33,63 +33,47 @@ · 32 unmodified lines | |||
| 33 | #define TABLE_PMSTATUSLOG 3 // Called by Tools for Agm logging | 33 | #define TABLE_PMSTATUSLOG 3 // Called by Tools for Agm logging |
| 34 | #define TABLE_DPMCLOCKS 4 // Called by Driver; defined here, but not used, for backward compatible | 34 | #define TABLE_DPMCLOCKS 4 // Called by Driver; defined here, but not used, for backward compatible |
| 35 | #define TABLE_MOMENTARY_PM 5 // Called by Tools; defined here, but not used, for backward compatible | 35 | #define TABLE_MOMENTARY_PM 5 // Called by Tools; defined here, but not used, for backward compatible |
| 36 | #define TABLE_COUNT 6 | 36 | #define TABLE_SMU_METRICS 6 // Called by Driver |
| 37 | #define TABLE_COUNT 7 | ||
| 37 | 38 | ||
| 38 | #define NUM_DSPCLK_LEVELS 8 | 39 | typedef struct SmuMetricsTable_t { |
| 39 | #define NUM_SOCCLK_DPM_LEVELS 8 | 40 | //CPU status |
| 40 | #define NUM_DCEFCLK_DPM_LEVELS 4 | 41 | uint16_t CoreFrequency[6]; //[MHz] |
| 41 | #define NUM_FCLK_DPM_LEVELS 4 | 42 | uint32_t CorePower[6]; //[mW] |
| 42 | #define NUM_MEMCLK_DPM_LEVELS 4 | 43 | uint16_t CoreTemperature[6]; //[centi-Celsius] |
| 44 | uint16_t L3Frequency[2]; //[MHz] | ||
| 45 | uint16_t L3Temperature[2]; //[centi-Celsius] | ||
| 46 | uint16_t C0Residency[6]; //Percentage | ||
| 43 | 47 | ||
| 44 | #define NUMBER_OF_PSTATES 8 | 48 | // GFX status |
| 45 | #define NUMBER_OF_CORES 8 | 49 | uint16_t GfxclkFrequency; //[MHz] |
| 50 | uint16_t GfxTemperature; //[centi-Celsius] | ||
| 46 | 51 | ||
| 47 | typedef enum { | 52 | // SOC IP info |
| 48 | S3_TYPE_ENTRY, | 53 | uint16_t SocclkFrequency; //[MHz] |
| 49 | S5_TYPE_ENTRY, | 54 | uint16_t VclkFrequency; //[MHz] |
| 50 | } Sleep_Type_e; | 55 | uint16_t DclkFrequency; //[MHz] |
| 56 | uint16_t MemclkFrequency; //[MHz] | ||
| 51 | 57 | ||
| 52 | typedef enum { | 58 | // power, VF info for CPU/GFX telemetry rails, and then socket power total |
| 53 | GFX_OFF = 0, | 59 | uint32_t Voltage[2]; //[mV] indices: VDDCR_VDD, VDDCR_GFX |
| 54 | GFX_ON = 1, | 60 | uint32_t Current[2]; //[mA] indices: VDDCR_VDD, VDDCR_GFX |
| 55 | } GFX_Mode_e; | 61 | uint32_t Power[2]; //[mW] indices: VDDCR_VDD, VDDCR_GFX |
| 62 | uint32_t CurrentSocketPower; //[mW] | ||
| 56 | 63 | ||
| 57 | typedef enum { | 64 | uint16_t SocTemperature; //[centi-Celsius] |
| 58 | CPU_P0 = 0, | 65 | uint16_t EdgeTemperature; |
| 59 | CPU_P1, | 66 | uint16_t ThrottlerStatus; |
| 60 | CPU_P2, | 67 | uint16_t Spare; |
| 61 | CPU_P3, | ||
| 62 | CPU_P4, | ||
| 63 | CPU_P5, | ||
| 64 | CPU_P6, | ||
| 65 | CPU_P7 | ||
| 66 | } CPU_PState_e; | ||
| 67 | 68 | ||
| 68 | typedef enum { | 69 | } SmuMetricsTable_t; |
| 69 | CPU_CORE0 = 0, | ||
| 70 | CPU_CORE1, | ||
| 71 | CPU_CORE2, | ||
| 72 | CPU_CORE3, | ||
| 73 | CPU_CORE4, | ||
| 74 | CPU_CORE5, | ||
| 75 | CPU_CORE6, | ||
| 76 | CPU_CORE7 | ||
| 77 | } CORE_ID_e; | ||
| 78 | 70 | ||
| 79 | typedef enum { | 71 | typedef struct SmuMetrics_t { |
| 80 | DF_DPM0 = 0, | 72 | SmuMetricsTable_t Current; |
| 81 | DF_DPM1, | 73 | SmuMetricsTable_t Average; |
| 82 | DF_DPM2, | 74 | uint32_t SampleStartTime; |
| 83 | DF_DPM3, | 75 | uint32_t SampleStopTime; |
| 84 | DF_PState_Count | 76 | uint32_t Accnt; |
| 85 | } DF_PState_e; | 77 | } SmuMetrics_t; |
| 86 | |||
| 87 | typedef enum { | ||
| 88 | GFX_DPM0 = 0, | ||
| 89 | GFX_DPM1, | ||
| 90 | GFX_DPM2, | ||
| 91 | GFX_DPM3, | ||
| 92 | GFX_PState_Count | ||
| 93 | } GFX_PState_e; | ||
| 94 | 78 | ||
| 95 | #endif | 79 | #endif |
| @@ -226,7 +226,10 @@ · 225 unmodified lines | |||
| 226 | __SMU_DUMMY_MAP(SetUclkDpmMode), \ | 226 | __SMU_DUMMY_MAP(SetUclkDpmMode), \ |
| 227 | __SMU_DUMMY_MAP(LightSBR), \ | 227 | __SMU_DUMMY_MAP(LightSBR), \ |
| 228 | __SMU_DUMMY_MAP(GfxDriverResetRecovery), \ | 228 | __SMU_DUMMY_MAP(GfxDriverResetRecovery), \ |
| 229 | __SMU_DUMMY_MAP(BoardPowerCalibration), | 229 | __SMU_DUMMY_MAP(BoardPowerCalibration), \ |
| 230 | __SMU_DUMMY_MAP(RequestGfxclk), \ | ||
| 231 | __SMU_DUMMY_MAP(ForceGfxVid), \ | ||
| 232 | __SMU_DUMMY_MAP(UnforceGfxVid), | ||
| 230 | 233 | ||
| 231 | #undef __SMU_DUMMY_MAP | 234 | #undef __SMU_DUMMY_MAP |
| 232 | #define __SMU_DUMMY_MAP(type) SMU_MSG_##type | 235 | #define __SMU_DUMMY_MAP(type) SMU_MSG_##type |
| @@ -65,6 +65,13 @@ · 64 unmodified lines | |||
| 65 | #define PPSMC_MSG_SetDriverTableVMID 0x34 | 65 | #define PPSMC_MSG_SetDriverTableVMID 0x34 |
| 66 | #define PPSMC_MSG_SetSoftMinCclk 0x35 | 66 | #define PPSMC_MSG_SetSoftMinCclk 0x35 |
| 67 | #define PPSMC_MSG_SetSoftMaxCclk 0x36 | 67 | #define PPSMC_MSG_SetSoftMaxCclk 0x36 |
| 68 | #define PPSMC_Message_Count 0x37 | 68 | #define PPSMC_MSG_GetGfxFrequency 0x37 |
| 69 | #define PPSMC_MSG_GetGfxVid 0x38 | ||
| 70 | #define PPSMC_MSG_ForceGfxFreq 0x39 | ||
| 71 | #define PPSMC_MSG_UnForceGfxFreq 0x3A | ||
| 72 | #define PPSMC_MSG_ForceGfxVid 0x3B | ||
| 73 | #define PPSMC_MSG_UnforceGfxVid 0x3C | ||
| 74 | #define PPSMC_MSG_GetEnabledSmuFeatures 0x3D | ||
| 75 | #define PPSMC_Message_Count 0x3E | ||
| 69 | 76 | ||
| 70 | #endif | 77 | #endif |
| @@ -1404,7 +1404,7 @@ static int smu_disable_dpms(struct smu_context *smu) · 1403 unmodified lines | |||
| 1404 | */ | 1404 | */ |
| 1405 | if (smu->uploading_custom_pp_table && | 1405 | if (smu->uploading_custom_pp_table && |
| 1406 | (adev->asic_type >= CHIP_NAVI10) && | 1406 | (adev->asic_type >= CHIP_NAVI10) && |
| 1407 | (adev->asic_type <= CHIP_DIMGREY_CAVEFISH)) | 1407 | (adev->asic_type <= CHIP_BEIGE_GOBY)) |
| 1408 | return smu_disable_all_features_with_exception(smu, | 1408 | return smu_disable_all_features_with_exception(smu, |
| 1409 | true, | 1409 | true, |
| 1410 | SMU_FEATURE_COUNT); | 1410 | SMU_FEATURE_COUNT); |
| @@ -771,8 +771,12 @@ static int arcturus_print_clk_levels(struct smu_context *smu, · 770 unmodified lines | |||
| 771 | struct smu_11_0_dpm_context *dpm_context = NULL; | 771 | struct smu_11_0_dpm_context *dpm_context = NULL; |
| 772 | uint32_t gen_speed, lane_width; | 772 | uint32_t gen_speed, lane_width; |
| 773 | 773 | ||
| 774 | if (amdgpu_ras_intr_triggered()) | 774 | smu_cmn_get_sysfs_buf(&buf, &size); |
| 775 | return sysfs_emit(buf, "unavailable\n"); | 775 | |
| 776 | if (amdgpu_ras_intr_triggered()) { | ||
| 777 | size += sysfs_emit_at(buf, size, "unavailable\n"); | ||
| 778 | return size; | ||
| 779 | } | ||
| 776 | 780 | ||
| 777 | dpm_context = smu_dpm->dpm_context; | 781 | dpm_context = smu_dpm->dpm_context; |
| 778 | 782 | ||
| @@ -44,6 +44,27 @@ · 43 unmodified lines | |||
| 44 | #undef pr_info | 44 | #undef pr_info |
| 45 | #undef pr_debug | 45 | #undef pr_debug |
| 46 | 46 | ||
| 47 | /* unit: MHz */ | ||
| 48 | #define CYAN_SKILLFISH_SCLK_MIN 1000 | ||
| 49 | #define CYAN_SKILLFISH_SCLK_MAX 2000 | ||
| 50 | #define CYAN_SKILLFISH_SCLK_DEFAULT 1800 | ||
| 51 | |||
| 52 | /* unit: mV */ | ||
| 53 | #define CYAN_SKILLFISH_VDDC_MIN 700 | ||
| 54 | #define CYAN_SKILLFISH_VDDC_MAX 1129 | ||
| 55 | #define CYAN_SKILLFISH_VDDC_MAGIC 5118 // 0x13fe | ||
| 56 | |||
| 57 | static struct gfx_user_settings { | ||
| 58 | uint32_t sclk; | ||
| 59 | uint32_t vddc; | ||
| 60 | } cyan_skillfish_user_settings; | ||
| 61 | |||
| 62 | #define FEATURE_MASK(feature) (1ULL << feature) | ||
| 63 | #define SMC_DPM_FEATURE ( \ | ||
| 64 | FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \ | ||
| 65 | FEATURE_MASK(FEATURE_SOC_DPM_BIT) | \ | ||
| 66 | FEATURE_MASK(FEATURE_GFX_DPM_BIT)) | ||
| 67 | |||
| 47 | static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = { | 68 | static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = { |
| 48 | MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), | 69 | MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), |
| 49 | MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 0), | 70 | MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 0), |
| @@ -52,14 +73,473 @@ static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] · 2 unmodified lines | |||
| 52 | MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverTableDramAddrLow, 0), | 73 | MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverTableDramAddrLow, 0), |
| 53 | MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), | 74 | MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), |
| 54 | MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), | 75 | MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), |
| 76 | MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 0), | ||
| 77 | MSG_MAP(RequestGfxclk, PPSMC_MSG_RequestGfxclk, 0), | ||
| 78 | MSG_MAP(ForceGfxVid, PPSMC_MSG_ForceGfxVid, 0), | ||
| 79 | MSG_MAP(UnforceGfxVid, PPSMC_MSG_UnforceGfxVid, 0), | ||
| 80 | }; | ||
| 81 | |||
| 82 | static struct cmn2asic_mapping cyan_skillfish_table_map[SMU_TABLE_COUNT] = { | ||
| 83 | TAB_MAP_VALID(SMU_METRICS), | ||
| 55 | }; | 84 | }; |
| 56 | 85 | ||
| 86 | static int cyan_skillfish_tables_init(struct smu_context *smu) | ||
| 87 | { | ||
| 88 | struct smu_table_context *smu_table = &smu->smu_table; | ||
| 89 | struct smu_table *tables = smu_table->tables; | ||
| 90 | |||
| 91 | SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, | ||
| 92 | sizeof(SmuMetrics_t), | ||
| 93 | PAGE_SIZE, | ||
| 94 | AMDGPU_GEM_DOMAIN_VRAM); | ||
| 95 | |||
| 96 | smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); | ||
| 97 | if (!smu_table->metrics_table) | ||
| 98 | goto err0_out; | ||
| 99 | |||
| 100 | smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2); | ||
| 101 | smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); | ||
| 102 | if (!smu_table->gpu_metrics_table) | ||
| 103 | goto err1_out; | ||
| 104 | |||
| 105 | smu_table->metrics_time = 0; | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | |||
| 109 | err1_out: | ||
| 110 | smu_table->gpu_metrics_table_size = 0; | ||
| 111 | kfree(smu_table->metrics_table); | ||
| 112 | err0_out: | ||
| 113 | return -ENOMEM; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int cyan_skillfish_init_smc_tables(struct smu_context *smu) | ||
| 117 | { | ||
| 118 | int ret = 0; | ||
| 119 | |||
| 120 | ret = cyan_skillfish_tables_init(smu); | ||
| 121 | if (ret) | ||
| 122 | return ret; | ||
| 123 | |||
| 124 | return smu_v11_0_init_smc_tables(smu); | ||
| 125 | } | ||
| 126 | |||
| 127 | static int cyan_skillfish_finit_smc_tables(struct smu_context *smu) | ||
| 128 | { | ||
| 129 | struct smu_table_context *smu_table = &smu->smu_table; | ||
| 130 | |||
| 131 | kfree(smu_table->metrics_table); | ||
| 132 | smu_table->metrics_table = NULL; | ||
| 133 | |||
| 134 | kfree(smu_table->gpu_metrics_table); | ||
| 135 | smu_table->gpu_metrics_table = NULL; | ||
| 136 | smu_table->gpu_metrics_table_size = 0; | ||
| 137 | |||
| 138 | smu_table->metrics_time = 0; | ||
| 139 | |||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | |||
| 143 | static int | ||
| 144 | cyan_skillfish_get_smu_metrics_data(struct smu_context *smu, | ||
| 145 | MetricsMember_t member, | ||
| 146 | uint32_t *value) | ||
| 147 | { | ||
| 148 | struct smu_table_context *smu_table = &smu->smu_table; | ||
| 149 | SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; | ||
| 150 | int ret = 0; | ||
| 151 | |||
| 152 | mutex_lock(&smu->metrics_lock); | ||
| 153 | |||
| 154 | ret = smu_cmn_get_metrics_table_locked(smu, NULL, false); | ||
| 155 | if (ret) { | ||
| 156 | mutex_unlock(&smu->metrics_lock); | ||
| 157 | return ret; | ||
| 158 | } | ||
| 159 | |||
| 160 | switch (member) { | ||
| 161 | case METRICS_CURR_GFXCLK: | ||
| 162 | *value = metrics->Current.GfxclkFrequency; | ||
| 163 | break; | ||
| 164 | case METRICS_CURR_SOCCLK: | ||
| 165 | *value = metrics->Current.SocclkFrequency; | ||
| 166 | break; | ||
| 167 | case METRICS_CURR_VCLK: | ||
| 168 | *value = metrics->Current.VclkFrequency; | ||
| 169 | break; | ||
| 170 | case METRICS_CURR_DCLK: | ||
| 171 | *value = metrics->Current.DclkFrequency; | ||
| 172 | break; | ||
| 173 | case METRICS_CURR_UCLK: | ||
| 174 | *value = metrics->Current.MemclkFrequency; | ||
| 175 | break; | ||
| 176 | case METRICS_AVERAGE_SOCKETPOWER: | ||
| 177 | *value = (metrics->Current.CurrentSocketPower << 8) / | ||
| 178 | 1000; | ||
| 179 | break; | ||
| 180 | case METRICS_TEMPERATURE_EDGE: | ||
| 181 | *value = metrics->Current.GfxTemperature / 100 * | ||
| 182 | SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; | ||
| 183 | break; | ||
| 184 | case METRICS_TEMPERATURE_HOTSPOT: | ||
| 185 | *value = metrics->Current.SocTemperature / 100 * | ||
| 186 | SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; | ||
| 187 | break; | ||
| 188 | case METRICS_VOLTAGE_VDDSOC: | ||
| 189 | *value = metrics->Current.Voltage[0]; | ||
| 190 | break; | ||
| 191 | case METRICS_VOLTAGE_VDDGFX: | ||
| 192 | *value = metrics->Current.Voltage[1]; | ||
| 193 | break; | ||
| 194 | case METRICS_THROTTLER_STATUS: | ||
| 195 | *value = metrics->Current.ThrottlerStatus; | ||
| 196 | break; | ||
| 197 | default: | ||
| 198 | *value = UINT_MAX; | ||
| 199 | break; | ||
| 200 | } | ||
| 201 | |||
| 202 | mutex_unlock(&smu->metrics_lock); | ||
| 203 | |||
| 204 | return ret; | ||
| 205 | } | ||
| 206 | |||
| 207 | static int cyan_skillfish_read_sensor(struct smu_context *smu, | ||
| 208 | enum amd_pp_sensors sensor, | ||
| 209 | void *data, | ||
| 210 | uint32_t *size) | ||
| 211 | { | ||
| 212 | int ret = 0; | ||
| 213 | |||
| 214 | if (!data || !size) | ||
| 215 | return -EINVAL; | ||
| 216 | |||
| 217 | mutex_lock(&smu->sensor_lock); | ||
| 218 | |||
| 219 | switch (sensor) { | ||
| 220 | case AMDGPU_PP_SENSOR_GFX_SCLK: | ||
| 221 | ret = cyan_skillfish_get_smu_metrics_data(smu, | ||
| 222 | METRICS_CURR_GFXCLK, | ||
| 223 | (uint32_t *)data); | ||
| 224 | *(uint32_t *)data *= 100; | ||
| 225 | *size = 4; | ||
| 226 | break; | ||
| 227 | case AMDGPU_PP_SENSOR_GFX_MCLK: | ||
| 228 | ret = cyan_skillfish_get_smu_metrics_data(smu, | ||
| 229 | METRICS_CURR_UCLK, | ||
| 230 | (uint32_t *)data); | ||
| 231 | *(uint32_t *)data *= 100; | ||
| 232 | *size = 4; | ||
| 233 | break; | ||
| 234 | case AMDGPU_PP_SENSOR_GPU_POWER: | ||
| 235 | ret = cyan_skillfish_get_smu_metrics_data(smu, | ||
| 236 | METRICS_AVERAGE_SOCKETPOWER, | ||
| 237 | (uint32_t *)data); | ||
| 238 | *size = 4; | ||
| 239 | break; | ||
| 240 | case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: | ||
| 241 | ret = cyan_skillfish_get_smu_metrics_data(smu, | ||
| 242 | METRICS_TEMPERATURE_HOTSPOT, | ||
| 243 | (uint32_t *)data); | ||
| 244 | *size = 4; | ||
| 245 | break; | ||
| 246 | case AMDGPU_PP_SENSOR_EDGE_TEMP: | ||
| 247 | ret = cyan_skillfish_get_smu_metrics_data(smu, | ||
| 248 | METRICS_TEMPERATURE_EDGE, | ||
| 249 | (uint32_t *)data); | ||
| 250 | *size = 4; | ||
| 251 | break; | ||
| 252 | case AMDGPU_PP_SENSOR_VDDNB: | ||
| 253 | ret = cyan_skillfish_get_smu_metrics_data(smu, | ||
| 254 | METRICS_VOLTAGE_VDDSOC, | ||
| 255 | (uint32_t *)data); | ||
| 256 | *size = 4; | ||
| 257 | break; | ||
| 258 | case AMDGPU_PP_SENSOR_VDDGFX: | ||
| 259 | ret = cyan_skillfish_get_smu_metrics_data(smu, | ||
| 260 | METRICS_VOLTAGE_VDDGFX, | ||
| 261 | (uint32_t *)data); | ||
| 262 | *size = 4; | ||
| 263 | break; | ||
| 264 | default: | ||
| 265 | ret = -EOPNOTSUPP; | ||
| 266 | break; | ||
| 267 | } | ||
| 268 | |||
| 269 | mutex_unlock(&smu->sensor_lock); | ||
| 270 | |||
| 271 | return ret; | ||
| 272 | } | ||
| 273 | |||
| 274 | static int cyan_skillfish_get_current_clk_freq(struct smu_context *smu, | ||
| 275 | enum smu_clk_type clk_type, | ||
| 276 | uint32_t *value) | ||
| 277 | { | ||
| 278 | MetricsMember_t member_type; | ||
| 279 | |||
| 280 | switch (clk_type) { | ||
| 281 | case SMU_GFXCLK: | ||
| 282 | case SMU_SCLK: | ||
| 283 | member_type = METRICS_CURR_GFXCLK; | ||
| 284 | break; | ||
| 285 | case SMU_FCLK: | ||
| 286 | case SMU_MCLK: | ||
| 287 | member_type = METRICS_CURR_UCLK; | ||
| 288 | break; | ||
| 289 | case SMU_SOCCLK: | ||
| 290 | member_type = METRICS_CURR_SOCCLK; | ||
| 291 | break; | ||
| 292 | case SMU_VCLK: | ||
| 293 | member_type = METRICS_CURR_VCLK; | ||
| 294 | break; | ||
| 295 | case SMU_DCLK: | ||
| 296 | member_type = METRICS_CURR_DCLK; | ||
| 297 | break; | ||
| 298 | default: | ||
| 299 | return -EINVAL; | ||
| 300 | } | ||
| 301 | |||
| 302 | return cyan_skillfish_get_smu_metrics_data(smu, member_type, value); | ||
| 303 | } | ||
| 304 | |||
| 305 | static int cyan_skillfish_print_clk_levels(struct smu_context *smu, | ||
| 306 | enum smu_clk_type clk_type, | ||
| 307 | char *buf) | ||
| 308 | { | ||
| 309 | int ret = 0, size = 0; | ||
| 310 | uint32_t cur_value = 0; | ||
| 311 | |||
| 312 | smu_cmn_get_sysfs_buf(&buf, &size); | ||
| 313 | |||
| 314 | switch (clk_type) { | ||
| 315 | case SMU_OD_SCLK: | ||
| 316 | ret = cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, &cur_value); | ||
| 317 | if (ret) | ||
| 318 | return ret; | ||
| 319 | size += sysfs_emit_at(buf, size,"%s:\n", "OD_SCLK"); | ||
| 320 | size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); | ||
| 321 | break; | ||
| 322 | case SMU_OD_VDDC_CURVE: | ||
| 323 | ret = cyan_skillfish_get_smu_metrics_data(smu, METRICS_VOLTAGE_VDDGFX, &cur_value); | ||
| 324 | if (ret) | ||
| 325 | return ret; | ||
| 326 | size += sysfs_emit_at(buf, size,"%s:\n", "OD_VDDC"); | ||
| 327 | size += sysfs_emit_at(buf, size, "0: %umV *\n", cur_value); | ||
| 328 | break; | ||
| 329 | case SMU_OD_RANGE: | ||
| 330 | size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); | ||
| 331 | size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", | ||
| 332 | CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); | ||
| 333 | size += sysfs_emit_at(buf, size, "VDDC: %7umV %10umV\n", | ||
| 334 | CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); | ||
| 335 | break; | ||
| 336 | case SMU_GFXCLK: | ||
| 337 | case SMU_SCLK: | ||
| 338 | case SMU_FCLK: | ||
| 339 | case SMU_MCLK: | ||
| 340 | case SMU_SOCCLK: | ||
| 341 | case SMU_VCLK: | ||
| 342 | case SMU_DCLK: | ||
| 343 | ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value); | ||
| 344 | if (ret) | ||
| 345 | return ret; | ||
| 346 | size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); | ||
| 347 | break; | ||
| 348 | default: | ||
| 349 | dev_warn(smu->adev->dev, "Unsupported clock type\n"); | ||
| 350 | return ret; | ||
| 351 | } | ||
| 352 | |||
| 353 | return size; | ||
| 354 | } | ||
| 355 | |||
| 356 | static bool cyan_skillfish_is_dpm_running(struct smu_context *smu) | ||
| 357 | { | ||
| 358 | struct amdgpu_device *adev = smu->adev; | ||
| 359 | int ret = 0; | ||
| 360 | uint32_t feature_mask[2]; | ||
| 361 | uint64_t feature_enabled; | ||
| 362 | |||
| 363 | /* we need to re-init after suspend so return false */ | ||
| 364 | if (adev->in_suspend) | ||
| 365 | return false; | ||
| 366 | |||
| 367 | ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); | ||
| 368 | |||
| 369 | if (ret) | ||
| 370 | return false; | ||
| 371 | |||
| 372 | feature_enabled = (uint64_t)feature_mask[0] | | ||
| 373 | ((uint64_t)feature_mask[1] << 32); | ||
| 374 | |||
| 375 | return !!(feature_enabled & SMC_DPM_FEATURE); | ||
| 376 | } | ||
| 377 | |||
| 378 | static ssize_t cyan_skillfish_get_gpu_metrics(struct smu_context *smu, | ||
| 379 | void **table) | ||
| 380 | { | ||
| 381 | struct smu_table_context *smu_table = &smu->smu_table; | ||
| 382 | struct gpu_metrics_v2_2 *gpu_metrics = | ||
| 383 | (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; | ||
| 384 | SmuMetrics_t metrics; | ||
| 385 | int i, ret = 0; | ||
| 386 | |||
| 387 | ret = smu_cmn_get_metrics_table(smu, &metrics, true); | ||
| 388 | if (ret) | ||
| 389 | return ret; | ||
| 390 | |||
| 391 | smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2); | ||
| 392 | |||
| 393 | gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature; | ||
| 394 | gpu_metrics->temperature_soc = metrics.Current.SocTemperature; | ||
| 395 | |||
| 396 | gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower; | ||
| 397 | gpu_metrics->average_soc_power = metrics.Current.Power[0]; | ||
| 398 | gpu_metrics->average_gfx_power = metrics.Current.Power[1]; | ||
| 399 | |||
| 400 | gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency; | ||
| 401 | gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency; | ||
| 402 | gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency; | ||
| 403 | gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency; | ||
| 404 | gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency; | ||
| 405 | gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency; | ||
| 406 | |||
| 407 | gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency; | ||
| 408 | gpu_metrics->current_socclk = metrics.Current.SocclkFrequency; | ||
| 409 | gpu_metrics->current_uclk = metrics.Current.MemclkFrequency; | ||
| 410 | gpu_metrics->current_fclk = metrics.Current.MemclkFrequency; | ||
| 411 | gpu_metrics->current_vclk = metrics.Current.VclkFrequency; | ||
| 412 | gpu_metrics->current_dclk = metrics.Current.DclkFrequency; | ||
| 413 | |||
| 414 | for (i = 0; i < 6; i++) { | ||
| 415 | gpu_metrics->temperature_core[i] = metrics.Current.CoreTemperature[i]; | ||
| 416 | gpu_metrics->average_core_power[i] = metrics.Average.CorePower[i]; | ||
| 417 | gpu_metrics->current_coreclk[i] = metrics.Current.CoreFrequency[i]; | ||
| 418 | } | ||
| 419 | |||
| 420 | for (i = 0; i < 2; i++) { | ||
| 421 | gpu_metrics->temperature_l3[i] = metrics.Current.L3Temperature[i]; | ||
| 422 | gpu_metrics->current_l3clk[i] = metrics.Current.L3Frequency[i]; | ||
| 423 | } | ||
| 424 | |||
| 425 | gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus; | ||
| 426 | gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); | ||
| 427 | |||
| 428 | *table = (void *)gpu_metrics; | ||
| 429 | |||
| 430 | return sizeof(struct gpu_metrics_v2_2); | ||
| 431 | } | ||
| 432 | |||
| 433 | static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu, | ||
| 434 | enum PP_OD_DPM_TABLE_COMMAND type, | ||
| 435 | long input[], uint32_t size) | ||
| 436 | { | ||
| 437 | int ret = 0; | ||
| 438 | uint32_t vid; | ||
| 439 | |||
| 440 | switch (type) { | ||
| 441 | case PP_OD_EDIT_VDDC_CURVE: | ||
| 442 | if (size != 3 || input[0] != 0) { | ||
| 443 | dev_err(smu->adev->dev, "Invalid parameter!\n"); | ||
| 444 | return -EINVAL; | ||
| 445 | } | ||
| 446 | |||
| 447 | if (input[1] <= CYAN_SKILLFISH_SCLK_MIN || | ||
| 448 | input[1] > CYAN_SKILLFISH_SCLK_MAX) { | ||
| 449 | dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", | ||
| 450 | CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); | ||
| 451 | return -EINVAL; | ||
| 452 | } | ||
| 453 | |||
| 454 | if (input[2] <= CYAN_SKILLFISH_VDDC_MIN || | ||
| 455 | input[2] > CYAN_SKILLFISH_VDDC_MAX) { | ||
| 456 | dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", | ||
| 457 | CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); | ||
| 458 | return -EINVAL; | ||
| 459 | } | ||
| 460 | |||
| 461 | cyan_skillfish_user_settings.sclk = input[1]; | ||
| 462 | cyan_skillfish_user_settings.vddc = input[2]; | ||
| 463 | |||
| 464 | break; | ||
| 465 | case PP_OD_RESTORE_DEFAULT_TABLE: | ||
| 466 | if (size != 0) { | ||
| 467 | dev_err(smu->adev->dev, "Invalid parameter!\n"); | ||
| 468 | return -EINVAL; | ||
| 469 | } | ||
| 470 | |||
| 471 | cyan_skillfish_user_settings.sclk = CYAN_SKILLFISH_SCLK_DEFAULT; | ||
| 472 | cyan_skillfish_user_settings.vddc = CYAN_SKILLFISH_VDDC_MAGIC; | ||
| 473 | |||
| 474 | break; | ||
| 475 | case PP_OD_COMMIT_DPM_TABLE: | ||
| 476 | if (size != 0) { | ||
| 477 | dev_err(smu->adev->dev, "Invalid parameter!\n"); | ||
| 478 | return -EINVAL; | ||
| 479 | } | ||
| 480 | |||
| 481 | if (cyan_skillfish_user_settings.sclk < CYAN_SKILLFISH_SCLK_MIN || | ||
| 482 | cyan_skillfish_user_settings.sclk > CYAN_SKILLFISH_SCLK_MAX) { | ||
| 483 | dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", | ||
| 484 | CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); | ||
| 485 | return -EINVAL; | ||
| 486 | } | ||
| 487 | |||
| 488 | if ((cyan_skillfish_user_settings.vddc != CYAN_SKILLFISH_VDDC_MAGIC) && | ||
| 489 | (cyan_skillfish_user_settings.vddc < CYAN_SKILLFISH_VDDC_MIN || | ||
| 490 | cyan_skillfish_user_settings.vddc > CYAN_SKILLFISH_VDDC_MAX)) { | ||
| 491 | dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", | ||
| 492 | CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); | ||
| 493 | return -EINVAL; | ||
| 494 | } | ||
| 495 | |||
| 496 | ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestGfxclk, | ||
| 497 | cyan_skillfish_user_settings.sclk, NULL); | ||
| 498 | if (ret) { | ||
| 499 | dev_err(smu->adev->dev, "Set sclk failed!\n"); | ||
| 500 | return ret; | ||
| 501 | } | ||
| 502 | |||
| 503 | if (cyan_skillfish_user_settings.vddc == CYAN_SKILLFISH_VDDC_MAGIC) { | ||
| 504 | ret = smu_cmn_send_smc_msg(smu, SMU_MSG_UnforceGfxVid, NULL); | ||
| 505 | if (ret) { | ||
| 506 | dev_err(smu->adev->dev, "Unforce vddc failed!\n"); | ||
| 507 | return ret; | ||
| 508 | } | ||
| 509 | } else { | ||
| 510 | /* | ||
| 511 | * PMFW accepts SVI2 VID code, convert voltage to VID: | ||
| 512 | * vid = (uint32_t)((1.55 - voltage) * 160.0 + 0.00001) | ||
| 513 | */ | ||
| 514 | vid = (1550 - cyan_skillfish_user_settings.vddc) * 160 / 1000; | ||
| 515 | ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ForceGfxVid, vid, NULL); | ||
| 516 | if (ret) { | ||
| 517 | dev_err(smu->adev->dev, "Force vddc failed!\n"); | ||
| 518 | return ret; | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | break; | ||
| 523 | default: | ||
| 524 | return -EOPNOTSUPP; | ||
| 525 | } | ||
| 526 | |||
| 527 | return ret; | ||
| 528 | } | ||
| 529 | |||
| 57 | static const struct pptable_funcs cyan_skillfish_ppt_funcs = { | 530 | static const struct pptable_funcs cyan_skillfish_ppt_funcs = { |
| 58 | 531 | ||
| 59 | .check_fw_status = smu_v11_0_check_fw_status, | 532 | .check_fw_status = smu_v11_0_check_fw_status, |
| 60 | .check_fw_version = smu_v11_0_check_fw_version, | 533 | .check_fw_version = smu_v11_0_check_fw_version, |
| 61 | .init_power = smu_v11_0_init_power, | 534 | .init_power = smu_v11_0_init_power, |
| 62 | .fini_power = smu_v11_0_fini_power, | 535 | .fini_power = smu_v11_0_fini_power, |
| 536 | .init_smc_tables = cyan_skillfish_init_smc_tables, | ||
| 537 | .fini_smc_tables = cyan_skillfish_finit_smc_tables, | ||
| 538 | .read_sensor = cyan_skillfish_read_sensor, | ||
| 539 | .print_clk_levels = cyan_skillfish_print_clk_levels, | ||
| 540 | .is_dpm_running = cyan_skillfish_is_dpm_running, | ||
| 541 | .get_gpu_metrics = cyan_skillfish_get_gpu_metrics, | ||
| 542 | .od_edit_dpm_table = cyan_skillfish_od_edit_dpm_table, | ||
| 63 | .register_irq_handler = smu_v11_0_register_irq_handler, | 543 | .register_irq_handler = smu_v11_0_register_irq_handler, |
| 64 | .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, | 544 | .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, |
| 65 | .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, | 545 | .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, |
| @@ -72,5 +552,6 @@ void cyan_skillfish_set_ppt_funcs(struct smu_context *smu) · 6 unmodified lines | |||
| 72 | { | 552 | { |
| 73 | smu->ppt_funcs = &cyan_skillfish_ppt_funcs; | 553 | smu->ppt_funcs = &cyan_skillfish_ppt_funcs; |
| 74 | smu->message_map = cyan_skillfish_message_map; | 554 | smu->message_map = cyan_skillfish_message_map; |
| 555 | smu->table_map = cyan_skillfish_table_map; | ||
| 75 | smu->is_apu = true; | 556 | smu->is_apu = true; |
| 76 | } | 557 | } |
| @@ -1279,6 +1279,8 @@ static int navi10_print_clk_levels(struct smu_context *smu, · 1278 unmodified lines | |||
| 1279 | struct smu_11_0_overdrive_table *od_settings = smu->od_settings; | 1279 | struct smu_11_0_overdrive_table *od_settings = smu->od_settings; |
| 1280 | uint32_t min_value, max_value; | 1280 | uint32_t min_value, max_value; |
| 1281 | 1281 | ||
| 1282 | smu_cmn_get_sysfs_buf(&buf, &size); | ||
| 1283 | |||
| 1282 | switch (clk_type) { | 1284 | switch (clk_type) { |
| 1283 | case SMU_GFXCLK: | 1285 | case SMU_GFXCLK: |
| 1284 | case SMU_SCLK: | 1286 | case SMU_SCLK: |
| @@ -1392,7 +1394,7 @@ static int navi10_print_clk_levels(struct smu_context *smu, · 107 unmodified lines | |||
| 1392 | case SMU_OD_RANGE: | 1394 | case SMU_OD_RANGE: |
| 1393 | if (!smu->od_enabled || !od_table || !od_settings) | 1395 | if (!smu->od_enabled || !od_table || !od_settings) |
| 1394 | break; | 1396 | break; |
| 1395 | size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); | 1397 | size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); |
| 1396 | 1398 | ||
| 1397 | if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) { | 1399 | if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) { |
| 1398 | navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN, | 1400 | navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN, |
| @@ -2272,7 +2274,27 @@ static int navi10_baco_enter(struct smu_context *smu) · 873 unmodified lines | |||
| 2272 | { | 2274 | { |
| 2273 | struct amdgpu_device *adev = smu->adev; | 2275 | struct amdgpu_device *adev = smu->adev; |
| 2274 | 2276 | ||
| 2275 | if (adev->in_runpm) | 2277 | /* |
| 2278 | * This aims the case below: | ||
| 2279 | * amdgpu driver loaded -> runpm suspend kicked -> sound driver loaded | ||
| 2280 | * | ||
| 2281 | * For NAVI10 and later ASICs, we rely on PMFW to handle the runpm. To | ||
| 2282 | * make that possible, PMFW needs to acknowledge the dstate transition | ||
| 2283 | * process for both gfx(function 0) and audio(function 1) function of | ||
| 2284 | * the ASIC. | ||
| 2285 | * | ||
| 2286 | * The PCI device's initial runpm status is RUNPM_SUSPENDED. So as the | ||
| 2287 | * device representing the audio function of the ASIC. And that means | ||
| 2288 | * even if the sound driver(snd_hda_intel) was not loaded yet, it's still | ||
| 2289 | * possible runpm suspend kicked on the ASIC. However without the dstate | ||
| 2290 | * transition notification from audio function, pmfw cannot handle the | ||
| 2291 | * BACO in/exit correctly. And that will cause driver hang on runpm | ||
| 2292 | * resuming. | ||
| 2293 | * | ||
| 2294 | * To address this, we revert to legacy message way(driver masters the | ||
| 2295 | * timing for BACO in/exit) on sound driver missing. | ||
| 2296 | */ | ||
| 2297 | if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) | ||
| 2276 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); | 2298 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); |
| 2277 | else | 2299 | else |
| 2278 | return smu_v11_0_baco_enter(smu); | 2300 | return smu_v11_0_baco_enter(smu); |
| @@ -2282,7 +2304,7 @@ static int navi10_baco_exit(struct smu_context *smu) · 3 unmodified lines | |||
| 2282 | { | 2304 | { |
| 2283 | struct amdgpu_device *adev = smu->adev; | 2305 | struct amdgpu_device *adev = smu->adev; |
| 2284 | 2306 | ||
| 2285 | if (adev->in_runpm) { | 2307 | if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) { |
| 2286 | /* Wait for PMFW handling for the Dstate change */ | 2308 | /* Wait for PMFW handling for the Dstate change */ |
| 2287 | msleep(10); | 2309 | msleep(10); |
| 2288 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); | 2310 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); |
| @@ -1058,6 +1058,8 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu, · 1057 unmodified lines | |||
| 1058 | uint32_t min_value, max_value; | 1058 | uint32_t min_value, max_value; |
| 1059 | uint32_t smu_version; | 1059 | uint32_t smu_version; |
| 1060 | 1060 | ||
| 1061 | smu_cmn_get_sysfs_buf(&buf, &size); | ||
| 1062 | |||
| 1061 | switch (clk_type) { | 1063 | switch (clk_type) { |
| 1062 | case SMU_GFXCLK: | 1064 | case SMU_GFXCLK: |
| 1063 | case SMU_SCLK: | 1065 | case SMU_SCLK: |
| @@ -1180,7 +1182,7 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu, · 116 unmodified lines | |||
| 1180 | if (!smu->od_enabled || !od_table || !od_settings) | 1182 | if (!smu->od_enabled || !od_table || !od_settings) |
| 1181 | break; | 1183 | break; |
| 1182 | 1184 | ||
| 1183 | size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); | 1185 | size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); |
| 1184 | 1186 | ||
| 1185 | if (sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_GFXCLK_LIMITS)) { | 1187 | if (sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_GFXCLK_LIMITS)) { |
| 1186 | sienna_cichlid_get_od_setting_range(od_settings, SMU_11_0_7_ODSETTING_GFXCLKFMIN, | 1188 | sienna_cichlid_get_od_setting_range(od_settings, SMU_11_0_7_ODSETTING_GFXCLKFMIN, |
| @@ -2187,7 +2189,7 @@ static int sienna_cichlid_baco_enter(struct smu_context *smu) · 1000 unmodified lines | |||
| 2187 | { | 2189 | { |
| 2188 | struct amdgpu_device *adev = smu->adev; | 2190 | struct amdgpu_device *adev = smu->adev; |
| 2189 | 2191 | ||
| 2190 | if (adev->in_runpm) | 2192 | if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) |
| 2191 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); | 2193 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); |
| 2192 | else | 2194 | else |
| 2193 | return smu_v11_0_baco_enter(smu); | 2195 | return smu_v11_0_baco_enter(smu); |
| @@ -2197,7 +2199,7 @@ static int sienna_cichlid_baco_exit(struct smu_context *smu) · 3 unmodified lines | |||
| 2197 | { | 2199 | { |
| 2198 | struct amdgpu_device *adev = smu->adev; | 2200 | struct amdgpu_device *adev = smu->adev; |
| 2199 | 2201 | ||
| 2200 | if (adev->in_runpm) { | 2202 | if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) { |
| 2201 | /* Wait for PMFW handling for the Dstate change */ | 2203 | /* Wait for PMFW handling for the Dstate change */ |
| 2202 | msleep(10); | 2204 | msleep(10); |
| 2203 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); | 2205 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); |
| @@ -589,10 +589,12 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu, · 588 unmodified lines | |||
| 589 | if (ret) | 589 | if (ret) |
| 590 | return ret; | 590 | return ret; |
| 591 | 591 | ||
| 592 | smu_cmn_get_sysfs_buf(&buf, &size); | ||
| 593 | |||
| 592 | switch (clk_type) { | 594 | switch (clk_type) { |
| 593 | case SMU_OD_SCLK: | 595 | case SMU_OD_SCLK: |
| 594 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { | 596 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { |
| 595 | size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); | 597 | size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK"); |
| 596 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", | 598 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", |
| 597 | (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); | 599 | (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); |
| 598 | size += sysfs_emit_at(buf, size, "1: %10uMhz\n", | 600 | size += sysfs_emit_at(buf, size, "1: %10uMhz\n", |
| @@ -601,7 +603,7 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu, · 2 unmodified lines | |||
| 601 | break; | 603 | break; |
| 602 | case SMU_OD_CCLK: | 604 | case SMU_OD_CCLK: |
| 603 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { | 605 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { |
| 604 | size = sysfs_emit(buf, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select); | 606 | size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select); |
| 605 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", | 607 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", |
| 606 | (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq); | 608 | (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq); |
| 607 | size += sysfs_emit_at(buf, size, "1: %10uMhz\n", | 609 | size += sysfs_emit_at(buf, size, "1: %10uMhz\n", |
| @@ -610,7 +612,7 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu, · 2 unmodified lines | |||
| 610 | break; | 612 | break; |
| 611 | case SMU_OD_RANGE: | 613 | case SMU_OD_RANGE: |
| 612 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { | 614 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { |
| 613 | size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); | 615 | size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); |
| 614 | size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", | 616 | size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", |
| 615 | smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); | 617 | smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); |
| 616 | size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n", | 618 | size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n", |
| @@ -688,10 +690,12 @@ static int vangogh_print_clk_levels(struct smu_context *smu, · 71 unmodified lines | |||
| 688 | if (ret) | 690 | if (ret) |
| 689 | return ret; | 691 | return ret; |
| 690 | 692 | ||
| 693 | smu_cmn_get_sysfs_buf(&buf, &size); | ||
| 694 | |||
| 691 | switch (clk_type) { | 695 | switch (clk_type) { |
| 692 | case SMU_OD_SCLK: | 696 | case SMU_OD_SCLK: |
| 693 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { | 697 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { |
| 694 | size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); | 698 | size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK"); |
| 695 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", | 699 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", |
| 696 | (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); | 700 | (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); |
| 697 | size += sysfs_emit_at(buf, size, "1: %10uMhz\n", | 701 | size += sysfs_emit_at(buf, size, "1: %10uMhz\n", |
| @@ -700,7 +704,7 @@ static int vangogh_print_clk_levels(struct smu_context *smu, · 2 unmodified lines | |||
| 700 | break; | 704 | break; |
| 701 | case SMU_OD_CCLK: | 705 | case SMU_OD_CCLK: |
| 702 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { | 706 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { |
| 703 | size = sysfs_emit(buf, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select); | 707 | size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select); |
| 704 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", | 708 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", |
| 705 | (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq); | 709 | (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq); |
| 706 | size += sysfs_emit_at(buf, size, "1: %10uMhz\n", | 710 | size += sysfs_emit_at(buf, size, "1: %10uMhz\n", |
| @@ -709,7 +713,7 @@ static int vangogh_print_clk_levels(struct smu_context *smu, · 2 unmodified lines | |||
| 709 | break; | 713 | break; |
| 710 | case SMU_OD_RANGE: | 714 | case SMU_OD_RANGE: |
| 711 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { | 715 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { |
| 712 | size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); | 716 | size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); |
| 713 | size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", | 717 | size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", |
| 714 | smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); | 718 | smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); |
| 715 | size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n", | 719 | size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n", |
| @@ -497,6 +497,8 @@ static int renoir_print_clk_levels(struct smu_context *smu, · 496 unmodified lines | |||
| 497 | if (ret) | 497 | if (ret) |
| 498 | return ret; | 498 | return ret; |
| 499 | 499 | ||
| 500 | smu_cmn_get_sysfs_buf(&buf, &size); | ||
| 501 | |||
| 500 | switch (clk_type) { | 502 | switch (clk_type) { |
| 501 | case SMU_OD_RANGE: | 503 | case SMU_OD_RANGE: |
| 502 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { | 504 | if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { |
| @@ -733,15 +733,19 @@ static int aldebaran_print_clk_levels(struct smu_context *smu, · 732 unmodified lines | |||
| 733 | uint32_t freq_values[3] = {0}; | 733 | uint32_t freq_values[3] = {0}; |
| 734 | uint32_t min_clk, max_clk; | 734 | uint32_t min_clk, max_clk; |
| 735 | 735 | ||
| 736 | if (amdgpu_ras_intr_triggered()) | 736 | smu_cmn_get_sysfs_buf(&buf, &size); |
| 737 | return sysfs_emit(buf, "unavailable\n"); | 737 | |
| 738 | if (amdgpu_ras_intr_triggered()) { | ||
| 739 | size += sysfs_emit_at(buf, size, "unavailable\n"); | ||
| 740 | return size; | ||
| 741 | } | ||
| 738 | 742 | ||
| 739 | dpm_context = smu_dpm->dpm_context; | 743 | dpm_context = smu_dpm->dpm_context; |
| 740 | 744 | ||
| 741 | switch (type) { | 745 | switch (type) { |
| 742 | 746 | ||
| 743 | case SMU_OD_SCLK: | 747 | case SMU_OD_SCLK: |
| 744 | size = sysfs_emit(buf, "%s:\n", "GFXCLK"); | 748 | size += sysfs_emit_at(buf, size, "%s:\n", "GFXCLK"); |
| 745 | fallthrough; | 749 | fallthrough; |
| 746 | case SMU_SCLK: | 750 | case SMU_SCLK: |
| 747 | ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now); | 751 | ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now); |
| @@ -795,7 +799,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu, · 47 unmodified lines | |||
| 795 | break; | 799 | break; |
| 796 | 800 | ||
| 797 | case SMU_OD_MCLK: | 801 | case SMU_OD_MCLK: |
| 798 | size = sysfs_emit(buf, "%s:\n", "MCLK"); | 802 | size += sysfs_emit_at(buf, size, "%s:\n", "MCLK"); |
| 799 | fallthrough; | 803 | fallthrough; |
| 800 | case SMU_MCLK: | 804 | case SMU_MCLK: |
| 801 | ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_UCLK, &now); | 805 | ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_UCLK, &now); |
| @@ -1052,16 +1052,18 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu, · 1051 unmodified lines | |||
| 1052 | int i, size = 0, ret = 0; | 1052 | int i, size = 0, ret = 0; |
| 1053 | uint32_t cur_value = 0, value = 0, count = 0; | 1053 | uint32_t cur_value = 0, value = 0, count = 0; |
| 1054 | 1054 | ||
| 1055 | smu_cmn_get_sysfs_buf(&buf, &size); | ||
| 1056 | |||
| 1055 | switch (clk_type) { | 1057 | switch (clk_type) { |
| 1056 | case SMU_OD_SCLK: | 1058 | case SMU_OD_SCLK: |
| 1057 | size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); | 1059 | size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK"); |
| 1058 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", | 1060 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", |
| 1059 | (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); | 1061 | (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); |
| 1060 | size += sysfs_emit_at(buf, size, "1: %10uMhz\n", | 1062 | size += sysfs_emit_at(buf, size, "1: %10uMhz\n", |
| 1061 | (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); | 1063 | (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); |
| 1062 | break; | 1064 | break; |
| 1063 | case SMU_OD_RANGE: | 1065 | case SMU_OD_RANGE: |
| 1064 | size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); | 1066 | size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); |
| 1065 | size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", | 1067 | size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", |
| 1066 | smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); | 1068 | smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); |
| 1067 | break; | 1069 | break; |
| @@ -1053,3 +1053,24 @@ int smu_cmn_set_mp1_state(struct smu_context *smu, · 1052 unmodified lines | |||
| 1053 | 1053 | ||
| 1054 | return ret; | 1054 | return ret; |
| 1055 | } | 1055 | } |
| 1056 | |||
| 1057 | bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev) | ||
| 1058 | { | ||
| 1059 | struct pci_dev *p = NULL; | ||
| 1060 | bool snd_driver_loaded; | ||
| 1061 | |||
| 1062 | /* | ||
| 1063 | * If the ASIC comes with no audio function, we always assume | ||
| 1064 | * it is "enabled". | ||
| 1065 | */ | ||
| 1066 | p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus), | ||
| 1067 | adev->pdev->bus->number, 1); | ||
| 1068 | if (!p) | ||
| 1069 | return true; | ||
| 1070 | |||
| 1071 | snd_driver_loaded = pci_is_enabled(p) ? true : false; | ||
| 1072 | |||
| 1073 | pci_dev_put(p); | ||
| 1074 | |||
| 1075 | return snd_driver_loaded; | ||
| 1076 | } | ||
| @@ -110,5 +110,20 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev); · 109 unmodified lines | |||
| 110 | int smu_cmn_set_mp1_state(struct smu_context *smu, | 110 | int smu_cmn_set_mp1_state(struct smu_context *smu, |
| 111 | enum pp_mp1_state mp1_state); | 111 | enum pp_mp1_state mp1_state); |
| 112 | 112 | ||
| 113 | /* | ||
| 114 | * Helper function to make sysfs_emit_at() happy. Align buf to | ||
| 115 | * the current page boundary and record the offset. | ||
| 116 | */ | ||
| 117 | static inline void smu_cmn_get_sysfs_buf(char **buf, int *offset) | ||
| 118 | { | ||
| 119 | if (!*buf || !offset) | ||
| 120 | return; | ||
| 121 | |||
| 122 | *offset = offset_in_page(*buf); | ||
| 123 | *buf -= *offset; | ||
| 124 | } | ||
| 125 | |||
| 126 | bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev); | ||
| 127 | |||
| 113 | #endif | 128 | #endif |
| 114 | #endif | 129 | #endif |
| @@ -397,8 +397,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state, · 396 unmodified lines | |||
| 397 | if (switch_mmu_context) { | 397 | if (switch_mmu_context) { |
| 398 | struct etnaviv_iommu_context *old_context = gpu->mmu_context; | 398 | struct etnaviv_iommu_context *old_context = gpu->mmu_context; |
| 399 | 399 | ||
| 400 | etnaviv_iommu_context_get(mmu_context); | 400 | gpu->mmu_context = etnaviv_iommu_context_get(mmu_context); |
| 401 | gpu->mmu_context = mmu_context; | ||
| 402 | etnaviv_iommu_context_put(old_context); | 401 | etnaviv_iommu_context_put(old_context); |
| 403 | } | 402 | } |
| 404 | 403 | ||
| @@ -294,8 +294,7 @@ struct etnaviv_vram_mapping *etnaviv_gem_mapping_get( · 293 unmodified lines | |||
| 294 | list_del(&mapping->obj_node); | 294 | list_del(&mapping->obj_node); |
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | etnaviv_iommu_context_get(mmu_context); | 297 | mapping->context = etnaviv_iommu_context_get(mmu_context); |
| 298 | mapping->context = mmu_context; | ||
| 299 | mapping->use = 1; | 298 | mapping->use = 1; |
| 300 | 299 | ||
| 301 | ret = etnaviv_iommu_map_gem(mmu_context, etnaviv_obj, | 300 | ret = etnaviv_iommu_map_gem(mmu_context, etnaviv_obj, |
| @@ -532,8 +532,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, · 531 unmodified lines | |||
| 532 | goto err_submit_objects; | 532 | goto err_submit_objects; |
| 533 | 533 | ||
| 534 | submit->ctx = file->driver_priv; | 534 | submit->ctx = file->driver_priv; |
| 535 | etnaviv_iommu_context_get(submit->ctx->mmu); | 535 | submit->mmu_context = etnaviv_iommu_context_get(submit->ctx->mmu); |
| 536 | submit->mmu_context = submit->ctx->mmu; | ||
| 537 | submit->exec_state = args->exec_state; | 536 | submit->exec_state = args->exec_state; |
| 538 | submit->flags = args->flags; | 537 | submit->flags = args->flags; |
| 539 | 538 | ||
| @@ -569,6 +569,12 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu) · 568 unmodified lines | |||
| 569 | /* We rely on the GPU running, so program the clock */ | 569 | /* We rely on the GPU running, so program the clock */ |
| 570 | etnaviv_gpu_update_clock(gpu); | 570 | etnaviv_gpu_update_clock(gpu); |
| 571 | 571 | ||
| 572 | gpu->fe_running = false; | ||
| 573 | gpu->exec_state = -1; | ||
| 574 | if (gpu->mmu_context) | ||
| 575 | etnaviv_iommu_context_put(gpu->mmu_context); | ||
| 576 | gpu->mmu_context = NULL; | ||
| 577 | |||
| 572 | return 0; | 578 | return 0; |
| 573 | } | 579 | } |
| 574 | 580 | ||
| @@ -637,19 +643,23 @@ void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch) · 62 unmodified lines | |||
| 637 | VIVS_MMUv2_SEC_COMMAND_CONTROL_ENABLE | | 643 | VIVS_MMUv2_SEC_COMMAND_CONTROL_ENABLE | |
| 638 | VIVS_MMUv2_SEC_COMMAND_CONTROL_PREFETCH(prefetch)); | 644 | VIVS_MMUv2_SEC_COMMAND_CONTROL_PREFETCH(prefetch)); |
| 639 | } | 645 | } |
| 646 | |||
| 647 | gpu->fe_running = true; | ||
| 640 | } | 648 | } |
| 641 | 649 | ||
| 642 | static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu) | 650 | static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu, |
| 651 | struct etnaviv_iommu_context *context) | ||
| 643 | { | 652 | { |
| 644 | u32 address = etnaviv_cmdbuf_get_va(&gpu->buffer, | ||
| 645 | &gpu->mmu_context->cmdbuf_mapping); | ||
| 646 | u16 prefetch; | 653 | u16 prefetch; |
| 654 | u32 address; | ||
| 647 | 655 | ||
| 648 | /* setup the MMU */ | 656 | /* setup the MMU */ |
| 649 | etnaviv_iommu_restore(gpu, gpu->mmu_context); | 657 | etnaviv_iommu_restore(gpu, context); |
| 650 | 658 | ||
| 651 | /* Start command processor */ | 659 | /* Start command processor */ |
| 652 | prefetch = etnaviv_buffer_init(gpu); | 660 | prefetch = etnaviv_buffer_init(gpu); |
| 661 | address = etnaviv_cmdbuf_get_va(&gpu->buffer, | ||
| 662 | &gpu->mmu_context->cmdbuf_mapping); | ||
| 653 | 663 | ||
| 654 | etnaviv_gpu_start_fe(gpu, address, prefetch); | 664 | etnaviv_gpu_start_fe(gpu, address, prefetch); |
| 655 | } | 665 | } |
| @@ -832,7 +842,6 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) · 176 unmodified lines | |||
| 832 | /* Now program the hardware */ | 842 | /* Now program the hardware */ |
| 833 | mutex_lock(&gpu->lock); | 843 | mutex_lock(&gpu->lock); |
| 834 | etnaviv_gpu_hw_init(gpu); | 844 | etnaviv_gpu_hw_init(gpu); |
| 835 | gpu->exec_state = -1; | ||
| 836 | mutex_unlock(&gpu->lock); | 845 | mutex_unlock(&gpu->lock); |
| 837 | 846 | ||
| 838 | pm_runtime_mark_last_busy(gpu->dev); | 847 | pm_runtime_mark_last_busy(gpu->dev); |
| @@ -1057,8 +1066,6 @@ void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu) · 218 unmodified lines | |||
| 1057 | spin_unlock(&gpu->event_spinlock); | 1066 | spin_unlock(&gpu->event_spinlock); |
| 1058 | 1067 | ||
| 1059 | etnaviv_gpu_hw_init(gpu); | 1068 | etnaviv_gpu_hw_init(gpu); |
| 1060 | gpu->exec_state = -1; | ||
| 1061 | gpu->mmu_context = NULL; | ||
| 1062 | 1069 | ||
| 1063 | mutex_unlock(&gpu->lock); | 1070 | mutex_unlock(&gpu->lock); |
| 1064 | pm_runtime_mark_last_busy(gpu->dev); | 1071 | pm_runtime_mark_last_busy(gpu->dev); |
| @@ -1370,14 +1377,12 @@ struct dma_fence *etnaviv_gpu_submit(struct etnaviv_gem_submit *submit) · 305 unmodified lines | |||
| 1370 | goto out_unlock; | 1377 | goto out_unlock; |
| 1371 | } | 1378 | } |
| 1372 | 1379 | ||
| 1373 | if (!gpu->mmu_context) { | 1380 | if (!gpu->fe_running) |
| 1374 | etnaviv_iommu_context_get(submit->mmu_context); | 1381 | etnaviv_gpu_start_fe_idleloop(gpu, submit->mmu_context); |
| 1375 | gpu->mmu_context = submit->mmu_context; | 1382 | |
| 1376 | etnaviv_gpu_start_fe_idleloop(gpu); | 1383 | if (submit->prev_mmu_context) |
| 1377 | } else { | 1384 | etnaviv_iommu_context_put(submit->prev_mmu_context); |
| 1378 | etnaviv_iommu_context_get(gpu->mmu_context); | 1385 | submit->prev_mmu_context = etnaviv_iommu_context_get(gpu->mmu_context); |
| 1379 | submit->prev_mmu_context = gpu->mmu_context; | ||
| 1380 | } | ||
| 1381 | 1386 | ||
| 1382 | if (submit->nr_pmrs) { | 1387 | if (submit->nr_pmrs) { |
| 1383 | gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre; | 1388 | gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre; |
| @@ -1579,7 +1584,7 @@ int etnaviv_gpu_wait_idle(struct etnaviv_gpu *gpu, unsigned int timeout_ms) · 195 unmodified lines | |||
| 1579 | 1584 | ||
| 1580 | static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu) | 1585 | static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu) |
| 1581 | { | 1586 | { |
| 1582 | if (gpu->initialized && gpu->mmu_context) { | 1587 | if (gpu->initialized && gpu->fe_running) { |
| 1583 | /* Replace the last WAIT with END */ | 1588 | /* Replace the last WAIT with END */ |
| 1584 | mutex_lock(&gpu->lock); | 1589 | mutex_lock(&gpu->lock); |
| 1585 | etnaviv_buffer_end(gpu); | 1590 | etnaviv_buffer_end(gpu); |
| @@ -1592,8 +1597,7 @@ static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu) · 6 unmodified lines | |||
| 1592 | */ | 1597 | */ |
| 1593 | etnaviv_gpu_wait_idle(gpu, 100); | 1598 | etnaviv_gpu_wait_idle(gpu, 100); |
| 1594 | 1599 | ||
| 1595 | etnaviv_iommu_context_put(gpu->mmu_context); | 1600 | gpu->fe_running = false; |
| 1596 | gpu->mmu_context = NULL; | ||
| 1597 | } | 1601 | } |
| 1598 | 1602 | ||
| 1599 | gpu->exec_state = -1; | 1603 | gpu->exec_state = -1; |
| @@ -1741,6 +1745,9 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master, · 141 unmodified lines | |||
| 1741 | etnaviv_gpu_hw_suspend(gpu); | 1745 | etnaviv_gpu_hw_suspend(gpu); |
| 1742 | #endif | 1746 | #endif |
| 1743 | 1747 | ||
| 1748 | if (gpu->mmu_context) | ||
| 1749 | etnaviv_iommu_context_put(gpu->mmu_context); | ||
| 1750 | |||
| 1744 | if (gpu->initialized) { | 1751 | if (gpu->initialized) { |
| 1745 | etnaviv_cmdbuf_free(&gpu->buffer); | 1752 | etnaviv_cmdbuf_free(&gpu->buffer); |
| 1746 | etnaviv_iommu_global_fini(gpu); | 1753 | etnaviv_iommu_global_fini(gpu); |
| @@ -101,6 +101,7 @@ struct etnaviv_gpu { · 100 unmodified lines | |||
| 101 | struct workqueue_struct *wq; | 101 | struct workqueue_struct *wq; |
| 102 | struct drm_gpu_scheduler sched; | 102 | struct drm_gpu_scheduler sched; |
| 103 | bool initialized; | 103 | bool initialized; |
| 104 | bool fe_running; | ||
| 104 | 105 | ||
| 105 | /* 'ring'-buffer: */ | 106 | /* 'ring'-buffer: */ |
| 106 | struct etnaviv_cmdbuf buffer; | 107 | struct etnaviv_cmdbuf buffer; |
| @@ -92,6 +92,10 @@ static void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu, · 91 unmodified lines | |||
| 92 | struct etnaviv_iommuv1_context *v1_context = to_v1_context(context); | 92 | struct etnaviv_iommuv1_context *v1_context = to_v1_context(context); |
| 93 | u32 pgtable; | 93 | u32 pgtable; |
| 94 | 94 | ||
| 95 | if (gpu->mmu_context) | ||
| 96 | etnaviv_iommu_context_put(gpu->mmu_context); | ||
| 97 | gpu->mmu_context = etnaviv_iommu_context_get(context); | ||
| 98 | |||
| 95 | /* set base addresses */ | 99 | /* set base addresses */ |
| 96 | gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_RA, context->global->memory_base); | 100 | gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_RA, context->global->memory_base); |
| 97 | gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_FE, context->global->memory_base); | 101 | gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_FE, context->global->memory_base); |
| @@ -172,6 +172,10 @@ static void etnaviv_iommuv2_restore_nonsec(struct etnaviv_gpu *gpu, · 171 unmodified lines | |||
| 172 | if (gpu_read(gpu, VIVS_MMUv2_CONTROL) & VIVS_MMUv2_CONTROL_ENABLE) | 172 | if (gpu_read(gpu, VIVS_MMUv2_CONTROL) & VIVS_MMUv2_CONTROL_ENABLE) |
| 173 | return; | 173 | return; |
| 174 | 174 | ||
| 175 | if (gpu->mmu_context) | ||
| 176 | etnaviv_iommu_context_put(gpu->mmu_context); | ||
| 177 | gpu->mmu_context = etnaviv_iommu_context_get(context); | ||
| 178 | |||
| 175 | prefetch = etnaviv_buffer_config_mmuv2(gpu, | 179 | prefetch = etnaviv_buffer_config_mmuv2(gpu, |
| 176 | (u32)v2_context->mtlb_dma, | 180 | (u32)v2_context->mtlb_dma, |
| 177 | (u32)context->global->bad_page_dma); | 181 | (u32)context->global->bad_page_dma); |
| @@ -192,6 +196,10 @@ static void etnaviv_iommuv2_restore_sec(struct etnaviv_gpu *gpu, · 14 unmodified lines | |||
| 192 | if (gpu_read(gpu, VIVS_MMUv2_SEC_CONTROL) & VIVS_MMUv2_SEC_CONTROL_ENABLE) | 196 | if (gpu_read(gpu, VIVS_MMUv2_SEC_CONTROL) & VIVS_MMUv2_SEC_CONTROL_ENABLE) |
| 193 | return; | 197 | return; |
| 194 | 198 | ||
| 199 | if (gpu->mmu_context) | ||
| 200 | etnaviv_iommu_context_put(gpu->mmu_context); | ||
| 201 | gpu->mmu_context = etnaviv_iommu_context_get(context); | ||
| 202 | |||
| 195 | gpu_write(gpu, VIVS_MMUv2_PTA_ADDRESS_LOW, | 203 | gpu_write(gpu, VIVS_MMUv2_PTA_ADDRESS_LOW, |
| 196 | lower_32_bits(context->global->v2.pta_dma)); | 204 | lower_32_bits(context->global->v2.pta_dma)); |
| 197 | gpu_write(gpu, VIVS_MMUv2_PTA_ADDRESS_HIGH, | 205 | gpu_write(gpu, VIVS_MMUv2_PTA_ADDRESS_HIGH, |
| @@ -199,6 +199,7 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context, · 198 unmodified lines | |||
| 199 | */ | 199 | */ |
| 200 | list_for_each_entry_safe(m, n, &list, scan_node) { | 200 | list_for_each_entry_safe(m, n, &list, scan_node) { |
| 201 | etnaviv_iommu_remove_mapping(context, m); | 201 | etnaviv_iommu_remove_mapping(context, m); |
| 202 | etnaviv_iommu_context_put(m->context); | ||
| 202 | m->context = NULL; | 203 | m->context = NULL; |
| 203 | list_del_init(&m->mmu_node); | 204 | list_del_init(&m->mmu_node); |
| 204 | list_del_init(&m->scan_node); | 205 | list_del_init(&m->scan_node); |
| @@ -105,9 +105,11 @@ void etnaviv_iommu_dump(struct etnaviv_iommu_context *ctx, void *buf); · 104 unmodified lines | |||
| 105 | struct etnaviv_iommu_context * | 105 | struct etnaviv_iommu_context * |
| 106 | etnaviv_iommu_context_init(struct etnaviv_iommu_global *global, | 106 | etnaviv_iommu_context_init(struct etnaviv_iommu_global *global, |
| 107 | struct etnaviv_cmdbuf_suballoc *suballoc); | 107 | struct etnaviv_cmdbuf_suballoc *suballoc); |
| 108 | static inline void etnaviv_iommu_context_get(struct etnaviv_iommu_context *ctx) | 108 | static inline struct etnaviv_iommu_context * |
| 109 | etnaviv_iommu_context_get(struct etnaviv_iommu_context *ctx) | ||
| 109 | { | 110 | { |
| 110 | kref_get(&ctx->refcount); | 111 | kref_get(&ctx->refcount); |
| 112 | return ctx; | ||
| 111 | } | 113 | } |
| 112 | void etnaviv_iommu_context_put(struct etnaviv_iommu_context *ctx); | 114 | void etnaviv_iommu_context_put(struct etnaviv_iommu_context *ctx); |
| 113 | void etnaviv_iommu_restore(struct etnaviv_gpu *gpu, | 115 | void etnaviv_iommu_restore(struct etnaviv_gpu *gpu, |
| @@ -19,7 +19,6 @@ subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers) · 18 unmodified lines | |||
| 19 | subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable) | 19 | subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable) |
| 20 | # clang warnings | 20 | # clang warnings |
| 21 | subdir-ccflags-y += $(call cc-disable-warning, sign-compare) | 21 | subdir-ccflags-y += $(call cc-disable-warning, sign-compare) |
| 22 | subdir-ccflags-y += $(call cc-disable-warning, sometimes-uninitialized) | ||
| 23 | subdir-ccflags-y += $(call cc-disable-warning, initializer-overrides) | 22 | subdir-ccflags-y += $(call cc-disable-warning, initializer-overrides) |
| 24 | subdir-ccflags-y += $(call cc-disable-warning, frame-address) | 23 | subdir-ccflags-y += $(call cc-disable-warning, frame-address) |
| 25 | subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror | 24 | subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror |
| @@ -2445,11 +2445,14 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) · 2444 unmodified lines | |||
| 2445 | */ | 2445 | */ |
| 2446 | if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, | 2446 | if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, |
| 2447 | intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) == | 2447 | intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) == |
| 2448 | sizeof(intel_dp->edp_dpcd)) | 2448 | sizeof(intel_dp->edp_dpcd)) { |
| 2449 | drm_dbg_kms(&dev_priv->drm, "eDP DPCD: %*ph\n", | 2449 | drm_dbg_kms(&dev_priv->drm, "eDP DPCD: %*ph\n", |
| 2450 | (int)sizeof(intel_dp->edp_dpcd), | 2450 | (int)sizeof(intel_dp->edp_dpcd), |
| 2451 | intel_dp->edp_dpcd); | 2451 | intel_dp->edp_dpcd); |
| 2452 | 2452 | ||
| 2453 | intel_dp->use_max_params = intel_dp->edp_dpcd[0] < DP_EDP_14; | ||
| 2454 | } | ||
| 2455 | |||
| 2453 | /* | 2456 | /* |
| 2454 | * This has to be called after intel_dp->edp_dpcd is filled, PSR checks | 2457 | * This has to be called after intel_dp->edp_dpcd is filled, PSR checks |
| 2455 | * for SET_POWER_CAPABLE bit in intel_dp->edp_dpcd[1] | 2458 | * for SET_POWER_CAPABLE bit in intel_dp->edp_dpcd[1] |
| @@ -848,7 +848,7 @@ intel_dp_link_train_all_phys(struct intel_dp *intel_dp, · 847 unmodified lines | |||
| 848 | } | 848 | } |
| 849 | 849 | ||
| 850 | if (ret) | 850 | if (ret) |
| 851 | intel_dp_link_train_phy(intel_dp, crtc_state, DP_PHY_DPRX); | 851 | ret = intel_dp_link_train_phy(intel_dp, crtc_state, DP_PHY_DPRX); |
| 852 | 852 | ||
| 853 | if (intel_dp->set_idle_link_train) | 853 | if (intel_dp->set_idle_link_train) |
| 854 | intel_dp->set_idle_link_train(intel_dp, crtc_state); | 854 | intel_dp->set_idle_link_train(intel_dp, crtc_state); |
| @@ -986,6 +986,9 @@ void i915_gem_context_release(struct kref *ref) · 985 unmodified lines | |||
| 986 | trace_i915_context_free(ctx); | 986 | trace_i915_context_free(ctx); |
| 987 | GEM_BUG_ON(!i915_gem_context_is_closed(ctx)); | 987 | GEM_BUG_ON(!i915_gem_context_is_closed(ctx)); |
| 988 | 988 | ||
| 989 | if (ctx->syncobj) | ||
| 990 | drm_syncobj_put(ctx->syncobj); | ||
| 991 | |||
| 989 | mutex_destroy(&ctx->engines_mutex); | 992 | mutex_destroy(&ctx->engines_mutex); |
| 990 | mutex_destroy(&ctx->lut_mutex); | 993 | mutex_destroy(&ctx->lut_mutex); |
| 991 | 994 | ||
| @@ -1205,9 +1208,6 @@ static void context_close(struct i915_gem_context *ctx) · 213 unmodified lines | |||
| 1205 | if (vm) | 1208 | if (vm) |
| 1206 | i915_vm_close(vm); | 1209 | i915_vm_close(vm); |
| 1207 | 1210 | ||
| 1208 | if (ctx->syncobj) | ||
| 1209 | drm_syncobj_put(ctx->syncobj); | ||
| 1210 | |||
| 1211 | ctx->file_priv = ERR_PTR(-EBADF); | 1211 | ctx->file_priv = ERR_PTR(-EBADF); |
| 1212 | 1212 | ||
| 1213 | /* | 1213 | /* |
| @@ -59,13 +59,13 @@ static int igt_dmabuf_import_self(void *arg) · 58 unmodified lines | |||
| 59 | err = PTR_ERR(import); | 59 | err = PTR_ERR(import); |
| 60 | goto out_dmabuf; | 60 | goto out_dmabuf; |
| 61 | } | 61 | } |
| 62 | import_obj = to_intel_bo(import); | ||
| 62 | 63 | ||
| 63 | if (import != &obj->base) { | 64 | if (import != &obj->base) { |
| 64 | pr_err("i915_gem_prime_import created a new object!\n"); | 65 | pr_err("i915_gem_prime_import created a new object!\n"); |
| 65 | err = -EINVAL; | 66 | err = -EINVAL; |
| 66 | goto out_import; | 67 | goto out_import; |
| 67 | } | 68 | } |
| 68 | import_obj = to_intel_bo(import); | ||
| 69 | 69 | ||
| 70 | i915_gem_object_lock(import_obj, NULL); | 70 | i915_gem_object_lock(import_obj, NULL); |
| 71 | err = __i915_gem_object_get_pages(import_obj); | 71 | err = __i915_gem_object_get_pages(import_obj); |
| @@ -128,6 +128,8 @@ static int igt_dmabuf_import_same_driver_lmem(void *arg) · 56 unmodified lines | |||
| 128 | pr_err("i915_gem_prime_import failed with the wrong err=%ld\n", | 128 | pr_err("i915_gem_prime_import failed with the wrong err=%ld\n", |
| 129 | PTR_ERR(import)); | 129 | PTR_ERR(import)); |
| 130 | err = PTR_ERR(import); | 130 | err = PTR_ERR(import); |
| 131 | } else { | ||
| 132 | err = 0; | ||
| 131 | } | 133 | } |
| 132 | 134 | ||
| 133 | dma_buf_put(dmabuf); | 135 | dma_buf_put(dmabuf); |
| @@ -176,6 +178,7 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915, · 42 unmodified lines | |||
| 176 | err = PTR_ERR(import); | 178 | err = PTR_ERR(import); |
| 177 | goto out_dmabuf; | 179 | goto out_dmabuf; |
| 178 | } | 180 | } |
| 181 | import_obj = to_intel_bo(import); | ||
| 179 | 182 | ||
| 180 | if (import == &obj->base) { | 183 | if (import == &obj->base) { |
| 181 | pr_err("i915_gem_prime_import reused gem object!\n"); | 184 | pr_err("i915_gem_prime_import reused gem object!\n"); |
| @@ -183,8 +186,6 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915, · 1 unmodified line | |||
| 183 | goto out_import; | 186 | goto out_import; |
| 184 | } | 187 | } |
| 185 | 188 | ||
| 186 | import_obj = to_intel_bo(import); | ||
| 187 | |||
| 188 | i915_gem_object_lock(import_obj, NULL); | 189 | i915_gem_object_lock(import_obj, NULL); |
| 189 | err = __i915_gem_object_get_pages(import_obj); | 190 | err = __i915_gem_object_get_pages(import_obj); |
| 190 | if (err) { | 191 | if (err) { |
| @@ -581,6 +581,20 @@ static enum i915_mmap_type default_mapping(struct drm_i915_private *i915) · 580 unmodified lines | |||
| 581 | return I915_MMAP_TYPE_GTT; | 581 | return I915_MMAP_TYPE_GTT; |
| 582 | } | 582 | } |
| 583 | 583 | ||
| 584 | static struct drm_i915_gem_object * | ||
| 585 | create_sys_or_internal(struct drm_i915_private *i915, | ||
| 586 | unsigned long size) | ||
| 587 | { | ||
| 588 | if (HAS_LMEM(i915)) { | ||
| 589 | struct intel_memory_region *sys_region = | ||
| 590 | i915->mm.regions[INTEL_REGION_SMEM]; | ||
| 591 | |||
| 592 | return __i915_gem_object_create_user(i915, size, &sys_region, 1); | ||
| 593 | } | ||
| 594 | |||
| 595 | return i915_gem_object_create_internal(i915, size); | ||
| 596 | } | ||
| 597 | |||
| 584 | static bool assert_mmap_offset(struct drm_i915_private *i915, | 598 | static bool assert_mmap_offset(struct drm_i915_private *i915, |
| 585 | unsigned long size, | 599 | unsigned long size, |
| 586 | int expected) | 600 | int expected) |
| @@ -589,7 +603,7 @@ static bool assert_mmap_offset(struct drm_i915_private *i915, · 2 unmodified lines | |||
| 589 | u64 offset; | 603 | u64 offset; |
| 590 | int ret; | 604 | int ret; |
| 591 | 605 | ||
| 592 | obj = i915_gem_object_create_internal(i915, size); | 606 | obj = create_sys_or_internal(i915, size); |
| 593 | if (IS_ERR(obj)) | 607 | if (IS_ERR(obj)) |
| 594 | return expected && expected == PTR_ERR(obj); | 608 | return expected && expected == PTR_ERR(obj); |
| 595 | 609 | ||
| @@ -633,6 +647,7 @@ static int igt_mmap_offset_exhaustion(void *arg) · 37 unmodified lines | |||
| 633 | struct drm_mm_node *hole, *next; | 647 | struct drm_mm_node *hole, *next; |
| 634 | int loop, err = 0; | 648 | int loop, err = 0; |
| 635 | u64 offset; | 649 | u64 offset; |
| 650 | int enospc = HAS_LMEM(i915) ? -ENXIO : -ENOSPC; | ||
| 636 | 651 | ||
| 637 | /* Disable background reaper */ | 652 | /* Disable background reaper */ |
| 638 | disable_retire_worker(i915); | 653 | disable_retire_worker(i915); |
| @@ -683,14 +698,14 @@ static int igt_mmap_offset_exhaustion(void *arg) · 44 unmodified lines | |||
| 683 | } | 698 | } |
| 684 | 699 | ||
| 685 | /* Too large */ | 700 | /* Too large */ |
| 686 | if (!assert_mmap_offset(i915, 2 * PAGE_SIZE, -ENOSPC)) { | 701 | if (!assert_mmap_offset(i915, 2 * PAGE_SIZE, enospc)) { |
| 687 | pr_err("Unexpectedly succeeded in inserting too large object into single page hole\n"); | 702 | pr_err("Unexpectedly succeeded in inserting too large object into single page hole\n"); |
| 688 | err = -EINVAL; | 703 | err = -EINVAL; |
| 689 | goto out; | 704 | goto out; |
| 690 | } | 705 | } |
| 691 | 706 | ||
| 692 | /* Fill the hole, further allocation attempts should then fail */ | 707 | /* Fill the hole, further allocation attempts should then fail */ |
| 693 | obj = i915_gem_object_create_internal(i915, PAGE_SIZE); | 708 | obj = create_sys_or_internal(i915, PAGE_SIZE); |
| 694 | if (IS_ERR(obj)) { | 709 | if (IS_ERR(obj)) { |
| 695 | err = PTR_ERR(obj); | 710 | err = PTR_ERR(obj); |
| 696 | pr_err("Unable to create object for reclaimed hole\n"); | 711 | pr_err("Unable to create object for reclaimed hole\n"); |
| @@ -703,7 +718,7 @@ static int igt_mmap_offset_exhaustion(void *arg) · 6 unmodified lines | |||
| 703 | goto err_obj; | 718 | goto err_obj; |
| 704 | } | 719 | } |
| 705 | 720 | ||
| 706 | if (!assert_mmap_offset(i915, PAGE_SIZE, -ENOSPC)) { | 721 | if (!assert_mmap_offset(i915, PAGE_SIZE, enospc)) { |
| 707 | pr_err("Unexpectedly succeeded in inserting object into no holes!\n"); | 722 | pr_err("Unexpectedly succeeded in inserting object into no holes!\n"); |
| 708 | err = -EINVAL; | 723 | err = -EINVAL; |
| 709 | goto err_obj; | 724 | goto err_obj; |
| @@ -839,10 +854,9 @@ static int wc_check(struct drm_i915_gem_object *obj) · 129 unmodified lines | |||
| 839 | 854 | ||
| 840 | static bool can_mmap(struct drm_i915_gem_object *obj, enum i915_mmap_type type) | 855 | static bool can_mmap(struct drm_i915_gem_object *obj, enum i915_mmap_type type) |
| 841 | { | 856 | { |
| 842 | struct drm_i915_private *i915 = to_i915(obj->base.dev); | ||
| 843 | bool no_map; | 857 | bool no_map; |
| 844 | 858 | ||
| 845 | if (HAS_LMEM(i915)) | 859 | if (obj->ops->mmap_offset) |
| 846 | return type == I915_MMAP_TYPE_FIXED; | 860 | return type == I915_MMAP_TYPE_FIXED; |
| 847 | else if (type == I915_MMAP_TYPE_FIXED) | 861 | else if (type == I915_MMAP_TYPE_FIXED) |
| 848 | return false; | 862 | return false; |
| @@ -1973,8 +1973,14 @@ u32 intel_rps_read_actual_frequency(struct intel_rps *rps) · 1972 unmodified lines | |||
| 1973 | u32 intel_rps_read_punit_req(struct intel_rps *rps) | 1973 | u32 intel_rps_read_punit_req(struct intel_rps *rps) |
| 1974 | { | 1974 | { |
| 1975 | struct intel_uncore *uncore = rps_to_uncore(rps); | 1975 | struct intel_uncore *uncore = rps_to_uncore(rps); |
| 1976 | struct intel_runtime_pm *rpm = rps_to_uncore(rps)->rpm; | ||
| 1977 | intel_wakeref_t wakeref; | ||
| 1978 | u32 freq = 0; | ||
| 1976 | 1979 | ||
| 1977 | return intel_uncore_read(uncore, GEN6_RPNSWREQ); | 1980 | with_intel_runtime_pm_if_in_use(rpm, wakeref) |
| 1981 | freq = intel_uncore_read(uncore, GEN6_RPNSWREQ); | ||
| 1982 | |||
| 1983 | return freq; | ||
| 1978 | } | 1984 | } |
| 1979 | 1985 | ||
| 1980 | static u32 intel_rps_get_req(u32 pureq) | 1986 | static u32 intel_rps_get_req(u32 pureq) |
| @@ -172,11 +172,6 @@ void intel_uc_driver_remove(struct intel_uc *uc) · 171 unmodified lines | |||
| 172 | __uc_free_load_err_log(uc); | 172 | __uc_free_load_err_log(uc); |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | static inline bool guc_communication_enabled(struct intel_guc *guc) | ||
| 176 | { | ||
| 177 | return intel_guc_ct_enabled(&guc->ct); | ||
| 178 | } | ||
| 179 | |||
| 180 | /* | 175 | /* |
| 181 | * Events triggered while CT buffers are disabled are logged in the SCRATCH_15 | 176 | * Events triggered while CT buffers are disabled are logged in the SCRATCH_15 |
| 182 | * register using the same bits used in the CT message payload. Since our | 177 | * register using the same bits used in the CT message payload. Since our |
| @@ -210,7 +205,7 @@ static void guc_get_mmio_msg(struct intel_guc *guc) · 27 unmodified lines | |||
| 210 | static void guc_handle_mmio_msg(struct intel_guc *guc) | 205 | static void guc_handle_mmio_msg(struct intel_guc *guc) |
| 211 | { | 206 | { |
| 212 | /* we need communication to be enabled to reply to GuC */ | 207 | /* we need communication to be enabled to reply to GuC */ |
| 213 | GEM_BUG_ON(!guc_communication_enabled(guc)); | 208 | GEM_BUG_ON(!intel_guc_ct_enabled(&guc->ct)); |
| 214 | 209 | ||
| 215 | spin_lock_irq(&guc->irq_lock); | 210 | spin_lock_irq(&guc->irq_lock); |
| 216 | if (guc->mmio_msg) { | 211 | if (guc->mmio_msg) { |
| @@ -226,7 +221,7 @@ static int guc_enable_communication(struct intel_guc *guc) · 9 unmodified lines | |||
| 226 | struct drm_i915_private *i915 = gt->i915; | 221 | struct drm_i915_private *i915 = gt->i915; |
| 227 | int ret; | 222 | int ret; |
| 228 | 223 | ||
| 229 | GEM_BUG_ON(guc_communication_enabled(guc)); | 224 | GEM_BUG_ON(intel_guc_ct_enabled(&guc->ct)); |
| 230 | 225 | ||
| 231 | ret = i915_inject_probe_error(i915, -ENXIO); | 226 | ret = i915_inject_probe_error(i915, -ENXIO); |
| 232 | if (ret) | 227 | if (ret) |
| @@ -662,7 +657,7 @@ static int __uc_resume(struct intel_uc *uc, bool enable_communication) · 429 unmodified lines | |||
| 662 | return 0; | 657 | return 0; |
| 663 | 658 | ||
| 664 | /* Make sure we enable communication if and only if it's disabled */ | 659 | /* Make sure we enable communication if and only if it's disabled */ |
| 665 | GEM_BUG_ON(enable_communication == guc_communication_enabled(guc)); | 660 | GEM_BUG_ON(enable_communication == intel_guc_ct_enabled(&guc->ct)); |
| 666 | 661 | ||
| 667 | if (enable_communication) | 662 | if (enable_communication) |
| 668 | guc_enable_communication(guc); | 663 | guc_enable_communication(guc); |
| @@ -57,7 +57,7 @@ nvkm_control_mthd_pstate_info(struct nvkm_control *ctrl, void *data, u32 size) · 56 unmodified lines | |||
| 57 | args->v0.count = 0; | 57 | args->v0.count = 0; |
| 58 | args->v0.ustate_ac = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE; | 58 | args->v0.ustate_ac = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE; |
| 59 | args->v0.ustate_dc = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE; | 59 | args->v0.ustate_dc = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE; |
| 60 | args->v0.pwrsrc = -ENOSYS; | 60 | args->v0.pwrsrc = -ENODEV; |
| 61 | args->v0.pstate = NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN; | 61 | args->v0.pstate = NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| @@ -119,7 +119,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) · 118 unmodified lines | |||
| 119 | #endif | 119 | #endif |
| 120 | 120 | ||
| 121 | if (pci_find_capability(pdev, PCI_CAP_ID_AGP)) | 121 | if (pci_find_capability(pdev, PCI_CAP_ID_AGP)) |
| 122 | rdev->agp = radeon_agp_head_init(rdev->ddev); | 122 | rdev->agp = radeon_agp_head_init(dev); |
| 123 | if (rdev->agp) { | 123 | if (rdev->agp) { |
| 124 | rdev->agp->agp_mtrr = arch_phys_wc_add( | 124 | rdev->agp->agp_mtrr = arch_phys_wc_add( |
| 125 | rdev->agp->agp_info.aper_base, | 125 | rdev->agp->agp_info.aper_base, |
| @@ -167,8 +167,6 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) · 166 unmodified lines | |||
| 167 | struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); | 167 | struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); |
| 168 | bool connected = false; | 168 | bool connected = false; |
| 169 | 169 | ||
| 170 | WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); | ||
| 171 | |||
| 172 | if (vc4_hdmi->hpd_gpio && | 170 | if (vc4_hdmi->hpd_gpio && |
| 173 | gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) { | 171 | gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) { |
| 174 | connected = true; | 172 | connected = true; |
| @@ -189,12 +187,10 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) · 14 unmodified lines | |||
| 189 | } | 187 | } |
| 190 | } | 188 | } |
| 191 | 189 | ||
| 192 | pm_runtime_put(&vc4_hdmi->pdev->dev); | ||
| 193 | return connector_status_connected; | 190 | return connector_status_connected; |
| 194 | } | 191 | } |
| 195 | 192 | ||
| 196 | cec_phys_addr_invalidate(vc4_hdmi->cec_adap); | 193 | cec_phys_addr_invalidate(vc4_hdmi->cec_adap); |
| 197 | pm_runtime_put(&vc4_hdmi->pdev->dev); | ||
| 198 | return connector_status_disconnected; | 194 | return connector_status_disconnected; |
| 199 | } | 195 | } |
| 200 | 196 | ||
| @@ -436,7 +432,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) · 235 unmodified lines | |||
| 436 | struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); | 432 | struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); |
| 437 | struct drm_connector *connector = &vc4_hdmi->connector; | 433 | struct drm_connector *connector = &vc4_hdmi->connector; |
| 438 | struct drm_connector_state *cstate = connector->state; | 434 | struct drm_connector_state *cstate = connector->state; |
| 439 | struct drm_crtc *crtc = cstate->crtc; | 435 | struct drm_crtc *crtc = encoder->crtc; |
| 440 | const struct drm_display_mode *mode = &crtc->state->adjusted_mode; | 436 | const struct drm_display_mode *mode = &crtc->state->adjusted_mode; |
| 441 | union hdmi_infoframe frame; | 437 | union hdmi_infoframe frame; |
| 442 | int ret; | 438 | int ret; |
| @@ -541,11 +537,8 @@ static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder, · 98 unmodified lines | |||
| 541 | 537 | ||
| 542 | static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) | 538 | static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) |
| 543 | { | 539 | { |
| 540 | struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; | ||
| 544 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); | 541 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); |
| 545 | struct drm_connector *connector = &vc4_hdmi->connector; | ||
| 546 | struct drm_connector_state *cstate = connector->state; | ||
| 547 | struct drm_crtc *crtc = cstate->crtc; | ||
| 548 | struct drm_display_mode *mode = &crtc->state->adjusted_mode; | ||
| 549 | 542 | ||
| 550 | if (!vc4_hdmi_supports_scrambling(encoder, mode)) | 543 | if (!vc4_hdmi_supports_scrambling(encoder, mode)) |
| 551 | return; | 544 | return; |
| @@ -566,18 +559,17 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) · 14 unmodified lines | |||
| 566 | static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) | 559 | static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) |
| 567 | { | 560 | { |
| 568 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); | 561 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); |
| 569 | struct drm_connector *connector = &vc4_hdmi->connector; | 562 | struct drm_crtc *crtc = encoder->crtc; |
| 570 | struct drm_connector_state *cstate = connector->state; | ||
| 571 | 563 | ||
| 572 | /* | 564 | /* |
| 573 | * At boot, connector->state will be NULL. Since we don't know the | 565 | * At boot, encoder->crtc will be NULL. Since we don't know the |
| 574 | * state of the scrambler and in order to avoid any | 566 | * state of the scrambler and in order to avoid any |
| 575 | * inconsistency, let's disable it all the time. | 567 | * inconsistency, let's disable it all the time. |
| 576 | */ | 568 | */ |
| 577 | if (cstate && !vc4_hdmi_supports_scrambling(encoder, &cstate->crtc->mode)) | 569 | if (crtc && !vc4_hdmi_supports_scrambling(encoder, &crtc->mode)) |
| 578 | return; | 570 | return; |
| 579 | 571 | ||
| 580 | if (cstate && !vc4_hdmi_mode_needs_scrambling(&cstate->crtc->mode)) | 572 | if (crtc && !vc4_hdmi_mode_needs_scrambling(&crtc->mode)) |
| 581 | return; | 573 | return; |
| 582 | 574 | ||
| 583 | if (delayed_work_pending(&vc4_hdmi->scrambling_work)) | 575 | if (delayed_work_pending(&vc4_hdmi->scrambling_work)) |
| @@ -635,6 +627,7 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, · 51 unmodified lines | |||
| 635 | vc4_hdmi->variant->phy_disable(vc4_hdmi); | 627 | vc4_hdmi->variant->phy_disable(vc4_hdmi); |
| 636 | 628 | ||
| 637 | clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); | 629 | clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); |
| 630 | clk_disable_unprepare(vc4_hdmi->hsm_clock); | ||
| 638 | clk_disable_unprepare(vc4_hdmi->pixel_clock); | 631 | clk_disable_unprepare(vc4_hdmi->pixel_clock); |
| 639 | 632 | ||
| 640 | ret = pm_runtime_put(&vc4_hdmi->pdev->dev); | 633 | ret = pm_runtime_put(&vc4_hdmi->pdev->dev); |
| @@ -898,9 +891,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 257 unmodified lines | |||
| 898 | vc4_hdmi_encoder_get_connector_state(encoder, state); | 891 | vc4_hdmi_encoder_get_connector_state(encoder, state); |
| 899 | struct vc4_hdmi_connector_state *vc4_conn_state = | 892 | struct vc4_hdmi_connector_state *vc4_conn_state = |
| 900 | conn_state_to_vc4_hdmi_conn_state(conn_state); | 893 | conn_state_to_vc4_hdmi_conn_state(conn_state); |
| 901 | struct drm_crtc_state *crtc_state = | 894 | struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; |
| 902 | drm_atomic_get_new_crtc_state(state, conn_state->crtc); | ||
| 903 | struct drm_display_mode *mode = &crtc_state->adjusted_mode; | ||
| 904 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); | 895 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); |
| 905 | unsigned long bvb_rate, pixel_rate, hsm_rate; | 896 | unsigned long bvb_rate, pixel_rate, hsm_rate; |
| 906 | int ret; | 897 | int ret; |
| @@ -947,6 +938,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 40 unmodified lines | |||
| 947 | return; | 938 | return; |
| 948 | } | 939 | } |
| 949 | 940 | ||
| 941 | ret = clk_prepare_enable(vc4_hdmi->hsm_clock); | ||
| 942 | if (ret) { | ||
| 943 | DRM_ERROR("Failed to turn on HSM clock: %d\n", ret); | ||
| 944 | clk_disable_unprepare(vc4_hdmi->pixel_clock); | ||
| 945 | return; | ||
| 946 | } | ||
| 947 | |||
| 950 | vc4_hdmi_cec_update_clk_div(vc4_hdmi); | 948 | vc4_hdmi_cec_update_clk_div(vc4_hdmi); |
| 951 | 949 | ||
| 952 | if (pixel_rate > 297000000) | 950 | if (pixel_rate > 297000000) |
| @@ -959,6 +957,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 6 unmodified lines | |||
| 959 | ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate); | 957 | ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate); |
| 960 | if (ret) { | 958 | if (ret) { |
| 961 | DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret); | 959 | DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret); |
| 960 | clk_disable_unprepare(vc4_hdmi->hsm_clock); | ||
| 962 | clk_disable_unprepare(vc4_hdmi->pixel_clock); | 961 | clk_disable_unprepare(vc4_hdmi->pixel_clock); |
| 963 | return; | 962 | return; |
| 964 | } | 963 | } |
| @@ -966,6 +965,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 1 unmodified line | |||
| 966 | ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); | 965 | ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); |
| 967 | if (ret) { | 966 | if (ret) { |
| 968 | DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret); | 967 | DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret); |
| 968 | clk_disable_unprepare(vc4_hdmi->hsm_clock); | ||
| 969 | clk_disable_unprepare(vc4_hdmi->pixel_clock); | 969 | clk_disable_unprepare(vc4_hdmi->pixel_clock); |
| 970 | return; | 970 | return; |
| 971 | } | 971 | } |
| @@ -985,11 +985,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 13 unmodified lines | |||
| 985 | static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, | 985 | static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, |
| 986 | struct drm_atomic_state *state) | 986 | struct drm_atomic_state *state) |
| 987 | { | 987 | { |
| 988 | struct drm_connector_state *conn_state = | 988 | struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; |
| 989 | vc4_hdmi_encoder_get_connector_state(encoder, state); | ||
| 990 | struct drm_crtc_state *crtc_state = | ||
| 991 | drm_atomic_get_new_crtc_state(state, conn_state->crtc); | ||
| 992 | struct drm_display_mode *mode = &crtc_state->adjusted_mode; | ||
| 993 | struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); | 989 | struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); |
| 994 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); | 990 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); |
| 995 | 991 | ||
| @@ -1012,11 +1008,7 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, · 16 unmodified lines | |||
| 1012 | static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, | 1008 | static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, |
| 1013 | struct drm_atomic_state *state) | 1009 | struct drm_atomic_state *state) |
| 1014 | { | 1010 | { |
| 1015 | struct drm_connector_state *conn_state = | 1011 | struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; |
| 1016 | vc4_hdmi_encoder_get_connector_state(encoder, state); | ||
| 1017 | struct drm_crtc_state *crtc_state = | ||
| 1018 | drm_atomic_get_new_crtc_state(state, conn_state->crtc); | ||
| 1019 | struct drm_display_mode *mode = &crtc_state->adjusted_mode; | ||
| 1020 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); | 1012 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); |
| 1021 | struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); | 1013 | struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); |
| 1022 | bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; | 1014 | bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; |
| @@ -1204,8 +1196,8 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi, · 181 unmodified lines | |||
| 1204 | 1196 | ||
| 1205 | static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate) | 1197 | static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate) |
| 1206 | { | 1198 | { |
| 1207 | struct drm_connector *connector = &vc4_hdmi->connector; | 1199 | struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; |
| 1208 | struct drm_crtc *crtc = connector->state->crtc; | 1200 | struct drm_crtc *crtc = encoder->crtc; |
| 1209 | const struct drm_display_mode *mode = &crtc->state->adjusted_mode; | 1201 | const struct drm_display_mode *mode = &crtc->state->adjusted_mode; |
| 1210 | u32 n, cts; | 1202 | u32 n, cts; |
| 1211 | u64 tmp; | 1203 | u64 tmp; |
| @@ -1238,13 +1230,13 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai) · 26 unmodified lines | |||
| 1238 | static int vc4_hdmi_audio_startup(struct device *dev, void *data) | 1230 | static int vc4_hdmi_audio_startup(struct device *dev, void *data) |
| 1239 | { | 1231 | { |
| 1240 | struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); | 1232 | struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); |
| 1241 | struct drm_connector *connector = &vc4_hdmi->connector; | 1233 | struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; |
| 1242 | 1234 | ||
| 1243 | /* | 1235 | /* |
| 1244 | * If the HDMI encoder hasn't probed, or the encoder is | 1236 | * If the HDMI encoder hasn't probed, or the encoder is |
| 1245 | * currently in DVI mode, treat the codec dai as missing. | 1237 | * currently in DVI mode, treat the codec dai as missing. |
| 1246 | */ | 1238 | */ |
| 1247 | if (!connector->state || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & | 1239 | if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & |
| 1248 | VC4_HDMI_RAM_PACKET_ENABLE)) | 1240 | VC4_HDMI_RAM_PACKET_ENABLE)) |
| 1249 | return -ENODEV; | 1241 | return -ENODEV; |
| 1250 | 1242 | ||
| @@ -2114,29 +2106,6 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) · 863 unmodified lines | |||
| 2114 | return 0; | 2106 | return 0; |
| 2115 | } | 2107 | } |
| 2116 | 2108 | ||
| 2117 | #ifdef CONFIG_PM | ||
| 2118 | static int vc4_hdmi_runtime_suspend(struct device *dev) | ||
| 2119 | { | ||
| 2120 | struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); | ||
| 2121 | |||
| 2122 | clk_disable_unprepare(vc4_hdmi->hsm_clock); | ||
| 2123 | |||
| 2124 | return 0; | ||
| 2125 | } | ||
| 2126 | |||
| 2127 | static int vc4_hdmi_runtime_resume(struct device *dev) | ||
| 2128 | { | ||
| 2129 | struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); | ||
| 2130 | int ret; | ||
| 2131 | |||
| 2132 | ret = clk_prepare_enable(vc4_hdmi->hsm_clock); | ||
| 2133 | if (ret) | ||
| 2134 | return ret; | ||
| 2135 | |||
| 2136 | return 0; | ||
| 2137 | } | ||
| 2138 | #endif | ||
| 2139 | |||
| 2140 | static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) | 2109 | static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) |
| 2141 | { | 2110 | { |
| 2142 | const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); | 2111 | const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); |
| @@ -2391,18 +2360,11 @@ static const struct of_device_id vc4_hdmi_dt_match[] = { · 248 unmodified lines | |||
| 2391 | {} | 2360 | {} |
| 2392 | }; | 2361 | }; |
| 2393 | 2362 | ||
| 2394 | static const struct dev_pm_ops vc4_hdmi_pm_ops = { | ||
| 2395 | SET_RUNTIME_PM_OPS(vc4_hdmi_runtime_suspend, | ||
| 2396 | vc4_hdmi_runtime_resume, | ||
| 2397 | NULL) | ||
| 2398 | }; | ||
| 2399 | |||
| 2400 | struct platform_driver vc4_hdmi_driver = { | 2363 | struct platform_driver vc4_hdmi_driver = { |
| 2401 | .probe = vc4_hdmi_dev_probe, | 2364 | .probe = vc4_hdmi_dev_probe, |
| 2402 | .remove = vc4_hdmi_dev_remove, | 2365 | .remove = vc4_hdmi_dev_remove, |
| 2403 | .driver = { | 2366 | .driver = { |
| 2404 | .name = "vc4_hdmi", | 2367 | .name = "vc4_hdmi", |
| 2405 | .of_match_table = vc4_hdmi_dt_match, | 2368 | .of_match_table = vc4_hdmi_dt_match, |
| 2406 | .pm = &vc4_hdmi_pm_ops, | ||
| 2407 | }, | 2369 | }, |
| 2408 | }; | 2370 | }; |
| @@ -351,9 +351,25 @@ static int b53_mdio_probe(struct mdio_device *mdiodev) · 350 unmodified lines | |||
| 351 | static void b53_mdio_remove(struct mdio_device *mdiodev) | 351 | static void b53_mdio_remove(struct mdio_device *mdiodev) |
| 352 | { | 352 | { |
| 353 | struct b53_device *dev = dev_get_drvdata(&mdiodev->dev); | 353 | struct b53_device *dev = dev_get_drvdata(&mdiodev->dev); |
| 354 | struct dsa_switch *ds = dev->ds; | ||
| 355 | 354 | ||
| 356 | dsa_unregister_switch(ds); | 355 | if (!dev) |
| 356 | return; | ||
| 357 | |||
| 358 | b53_switch_remove(dev); | ||
| 359 | |||
| 360 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 361 | } | ||
| 362 | |||
| 363 | static void b53_mdio_shutdown(struct mdio_device *mdiodev) | ||
| 364 | { | ||
| 365 | struct b53_device *dev = dev_get_drvdata(&mdiodev->dev); | ||
| 366 | |||
| 367 | if (!dev) | ||
| 368 | return; | ||
| 369 | |||
| 370 | b53_switch_shutdown(dev); | ||
| 371 | |||
| 372 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 357 | } | 373 | } |
| 358 | 374 | ||
| 359 | static const struct of_device_id b53_of_match[] = { | 375 | static const struct of_device_id b53_of_match[] = { |
| @@ -373,6 +389,7 @@ MODULE_DEVICE_TABLE(of, b53_of_match); · 13 unmodified lines | |||
| 373 | static struct mdio_driver b53_mdio_driver = { | 389 | static struct mdio_driver b53_mdio_driver = { |
| 374 | .probe = b53_mdio_probe, | 390 | .probe = b53_mdio_probe, |
| 375 | .remove = b53_mdio_remove, | 391 | .remove = b53_mdio_remove, |
| 392 | .shutdown = b53_mdio_shutdown, | ||
| 376 | .mdiodrv.driver = { | 393 | .mdiodrv.driver = { |
| 377 | .name = "bcm53xx", | 394 | .name = "bcm53xx", |
| 378 | .of_match_table = b53_of_match, | 395 | .of_match_table = b53_of_match, |
| @@ -316,9 +316,21 @@ static int b53_mmap_remove(struct platform_device *pdev) · 315 unmodified lines | |||
| 316 | if (dev) | 316 | if (dev) |
| 317 | b53_switch_remove(dev); | 317 | b53_switch_remove(dev); |
| 318 | 318 | ||
| 319 | platform_set_drvdata(pdev, NULL); | ||
| 320 | |||
| 319 | return 0; | 321 | return 0; |
| 320 | } | 322 | } |
| 321 | 323 | ||
| 324 | static void b53_mmap_shutdown(struct platform_device *pdev) | ||
| 325 | { | ||
| 326 | struct b53_device *dev = platform_get_drvdata(pdev); | ||
| 327 | |||
| 328 | if (dev) | ||
| 329 | b53_switch_shutdown(dev); | ||
| 330 | |||
| 331 | platform_set_drvdata(pdev, NULL); | ||
| 332 | } | ||
| 333 | |||
| 322 | static const struct of_device_id b53_mmap_of_table[] = { | 334 | static const struct of_device_id b53_mmap_of_table[] = { |
| 323 | { .compatible = "brcm,bcm3384-switch" }, | 335 | { .compatible = "brcm,bcm3384-switch" }, |
| 324 | { .compatible = "brcm,bcm6328-switch" }, | 336 | { .compatible = "brcm,bcm6328-switch" }, |
| @@ -331,6 +343,7 @@ MODULE_DEVICE_TABLE(of, b53_mmap_of_table); · 6 unmodified lines | |||
| 331 | static struct platform_driver b53_mmap_driver = { | 343 | static struct platform_driver b53_mmap_driver = { |
| 332 | .probe = b53_mmap_probe, | 344 | .probe = b53_mmap_probe, |
| 333 | .remove = b53_mmap_remove, | 345 | .remove = b53_mmap_remove, |
| 346 | .shutdown = b53_mmap_shutdown, | ||
| 334 | .driver = { | 347 | .driver = { |
| 335 | .name = "b53-switch", | 348 | .name = "b53-switch", |
| 336 | .of_match_table = b53_mmap_of_table, | 349 | .of_match_table = b53_mmap_of_table, |
| @@ -227,6 +227,11 @@ static inline void b53_switch_remove(struct b53_device *dev) · 226 unmodified lines | |||
| 227 | dsa_unregister_switch(dev->ds); | 227 | dsa_unregister_switch(dev->ds); |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | static inline void b53_switch_shutdown(struct b53_device *dev) | ||
| 231 | { | ||
| 232 | dsa_switch_shutdown(dev->ds); | ||
| 233 | } | ||
| 234 | |||
| 230 | #define b53_build_op(type_op_size, val_type) \ | 235 | #define b53_build_op(type_op_size, val_type) \ |
| 231 | static inline int b53_##type_op_size(struct b53_device *dev, u8 page, \ | 236 | static inline int b53_##type_op_size(struct b53_device *dev, u8 page, \ |
| 232 | u8 reg, val_type val) \ | 237 | u8 reg, val_type val) \ |
| @@ -321,9 +321,21 @@ static int b53_spi_remove(struct spi_device *spi) · 320 unmodified lines | |||
| 321 | if (dev) | 321 | if (dev) |
| 322 | b53_switch_remove(dev); | 322 | b53_switch_remove(dev); |
| 323 | 323 | ||
| 324 | spi_set_drvdata(spi, NULL); | ||
| 325 | |||
| 324 | return 0; | 326 | return 0; |
| 325 | } | 327 | } |
| 326 | 328 | ||
| 329 | static void b53_spi_shutdown(struct spi_device *spi) | ||
| 330 | { | ||
| 331 | struct b53_device *dev = spi_get_drvdata(spi); | ||
| 332 | |||
| 333 | if (dev) | ||
| 334 | b53_switch_shutdown(dev); | ||
| 335 | |||
| 336 | spi_set_drvdata(spi, NULL); | ||
| 337 | } | ||
| 338 | |||
| 327 | static const struct of_device_id b53_spi_of_match[] = { | 339 | static const struct of_device_id b53_spi_of_match[] = { |
| 328 | { .compatible = "brcm,bcm5325" }, | 340 | { .compatible = "brcm,bcm5325" }, |
| 329 | { .compatible = "brcm,bcm5365" }, | 341 | { .compatible = "brcm,bcm5365" }, |
| @@ -344,6 +356,7 @@ static struct spi_driver b53_spi_driver = { · 14 unmodified lines | |||
| 344 | }, | 356 | }, |
| 345 | .probe = b53_spi_probe, | 357 | .probe = b53_spi_probe, |
| 346 | .remove = b53_spi_remove, | 358 | .remove = b53_spi_remove, |
| 359 | .shutdown = b53_spi_shutdown, | ||
| 347 | }; | 360 | }; |
| 348 | 361 | ||
| 349 | module_spi_driver(b53_spi_driver); | 362 | module_spi_driver(b53_spi_driver); |
| @@ -629,17 +629,34 @@ static int b53_srab_probe(struct platform_device *pdev) · 628 unmodified lines | |||
| 629 | static int b53_srab_remove(struct platform_device *pdev) | 629 | static int b53_srab_remove(struct platform_device *pdev) |
| 630 | { | 630 | { |
| 631 | struct b53_device *dev = platform_get_drvdata(pdev); | 631 | struct b53_device *dev = platform_get_drvdata(pdev); |
| 632 | struct b53_srab_priv *priv = dev->priv; | ||
| 633 | 632 | ||
| 634 | b53_srab_intr_set(priv, false); | 633 | if (!dev) |
| 634 | return 0; | ||
| 635 | |||
| 636 | b53_srab_intr_set(dev->priv, false); | ||
| 635 | b53_switch_remove(dev); | 637 | b53_switch_remove(dev); |
| 636 | 638 | ||
| 639 | platform_set_drvdata(pdev, NULL); | ||
| 640 | |||
| 637 | return 0; | 641 | return 0; |
| 638 | } | 642 | } |
| 639 | 643 | ||
| 644 | static void b53_srab_shutdown(struct platform_device *pdev) | ||
| 645 | { | ||
| 646 | struct b53_device *dev = platform_get_drvdata(pdev); | ||
| 647 | |||
| 648 | if (!dev) | ||
| 649 | return; | ||
| 650 | |||
| 651 | b53_switch_shutdown(dev); | ||
| 652 | |||
| 653 | platform_set_drvdata(pdev, NULL); | ||
| 654 | } | ||
| 655 | |||
| 640 | static struct platform_driver b53_srab_driver = { | 656 | static struct platform_driver b53_srab_driver = { |
| 641 | .probe = b53_srab_probe, | 657 | .probe = b53_srab_probe, |
| 642 | .remove = b53_srab_remove, | 658 | .remove = b53_srab_remove, |
| 659 | .shutdown = b53_srab_shutdown, | ||
| 643 | .driver = { | 660 | .driver = { |
| 644 | .name = "b53-srab-switch", | 661 | .name = "b53-srab-switch", |
| 645 | .of_match_table = b53_srab_of_match, | 662 | .of_match_table = b53_srab_of_match, |
| @@ -68,7 +68,7 @@ static unsigned int bcm_sf2_num_active_ports(struct dsa_switch *ds) · 67 unmodified lines | |||
| 68 | struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); | 68 | struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); |
| 69 | unsigned int port, count = 0; | 69 | unsigned int port, count = 0; |
| 70 | 70 | ||
| 71 | for (port = 0; port < ARRAY_SIZE(priv->port_sts); port++) { | 71 | for (port = 0; port < ds->num_ports; port++) { |
| 72 | if (dsa_is_cpu_port(ds, port)) | 72 | if (dsa_is_cpu_port(ds, port)) |
| 73 | continue; | 73 | continue; |
| 74 | if (priv->port_sts[port].enabled) | 74 | if (priv->port_sts[port].enabled) |
| @@ -1514,6 +1514,9 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev) · 1439 unmodified lines | |||
| 1514 | { | 1514 | { |
| 1515 | struct bcm_sf2_priv *priv = platform_get_drvdata(pdev); | 1515 | struct bcm_sf2_priv *priv = platform_get_drvdata(pdev); |
| 1516 | 1516 | ||
| 1517 | if (!priv) | ||
| 1518 | return 0; | ||
| 1519 | |||
| 1517 | priv->wol_ports_mask = 0; | 1520 | priv->wol_ports_mask = 0; |
| 1518 | /* Disable interrupts */ | 1521 | /* Disable interrupts */ |
| 1519 | bcm_sf2_intr_disable(priv); | 1522 | bcm_sf2_intr_disable(priv); |
| @@ -1525,6 +1528,8 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev) · 5 unmodified lines | |||
| 1525 | if (priv->type == BCM7278_DEVICE_ID) | 1528 | if (priv->type == BCM7278_DEVICE_ID) |
| 1526 | reset_control_assert(priv->rcdev); | 1529 | reset_control_assert(priv->rcdev); |
| 1527 | 1530 | ||
| 1531 | platform_set_drvdata(pdev, NULL); | ||
| 1532 | |||
| 1528 | return 0; | 1533 | return 0; |
| 1529 | } | 1534 | } |
| 1530 | 1535 | ||
| @@ -1532,6 +1537,9 @@ static void bcm_sf2_sw_shutdown(struct platform_device *pdev) · 1 unmodified line | |||
| 1532 | { | 1537 | { |
| 1533 | struct bcm_sf2_priv *priv = platform_get_drvdata(pdev); | 1538 | struct bcm_sf2_priv *priv = platform_get_drvdata(pdev); |
| 1534 | 1539 | ||
| 1540 | if (!priv) | ||
| 1541 | return; | ||
| 1542 | |||
| 1535 | /* For a kernel about to be kexec'd we want to keep the GPHY on for a | 1543 | /* For a kernel about to be kexec'd we want to keep the GPHY on for a |
| 1536 | * successful MDIO bus scan to occur. If we did turn off the GPHY | 1544 | * successful MDIO bus scan to occur. If we did turn off the GPHY |
| 1537 | * before (e.g: port_disable), this will also power it back on. | 1545 | * before (e.g: port_disable), this will also power it back on. |
| @@ -1540,6 +1548,10 @@ static void bcm_sf2_sw_shutdown(struct platform_device *pdev) · 2 unmodified lines | |||
| 1540 | */ | 1548 | */ |
| 1541 | if (priv->hw_params.num_gphy == 1) | 1549 | if (priv->hw_params.num_gphy == 1) |
| 1542 | bcm_sf2_gphy_enable_set(priv->dev->ds, true); | 1550 | bcm_sf2_gphy_enable_set(priv->dev->ds, true); |
| 1551 | |||
| 1552 | dsa_switch_shutdown(priv->dev->ds); | ||
| 1553 | |||
| 1554 | platform_set_drvdata(pdev, NULL); | ||
| 1543 | } | 1555 | } |
| 1544 | 1556 | ||
| 1545 | #ifdef CONFIG_PM_SLEEP | 1557 | #ifdef CONFIG_PM_SLEEP |
| @@ -340,10 +340,29 @@ static int dsa_loop_drv_probe(struct mdio_device *mdiodev) · 339 unmodified lines | |||
| 340 | static void dsa_loop_drv_remove(struct mdio_device *mdiodev) | 340 | static void dsa_loop_drv_remove(struct mdio_device *mdiodev) |
| 341 | { | 341 | { |
| 342 | struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); | 342 | struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); |
| 343 | struct dsa_loop_priv *ps = ds->priv; | 343 | struct dsa_loop_priv *ps; |
| 344 | |||
| 345 | if (!ds) | ||
| 346 | return; | ||
| 347 | |||
| 348 | ps = ds->priv; | ||
| 344 | 349 | ||
| 345 | dsa_unregister_switch(ds); | 350 | dsa_unregister_switch(ds); |
| 346 | dev_put(ps->netdev); | 351 | dev_put(ps->netdev); |
| 352 | |||
| 353 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 354 | } | ||
| 355 | |||
| 356 | static void dsa_loop_drv_shutdown(struct mdio_device *mdiodev) | ||
| 357 | { | ||
| 358 | struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); | ||
| 359 | |||
| 360 | if (!ds) | ||
| 361 | return; | ||
| 362 | |||
| 363 | dsa_switch_shutdown(ds); | ||
| 364 | |||
| 365 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 347 | } | 366 | } |
| 348 | 367 | ||
| 349 | static struct mdio_driver dsa_loop_drv = { | 368 | static struct mdio_driver dsa_loop_drv = { |
| @@ -352,6 +371,7 @@ static struct mdio_driver dsa_loop_drv = { · 2 unmodified lines | |||
| 352 | }, | 371 | }, |
| 353 | .probe = dsa_loop_drv_probe, | 372 | .probe = dsa_loop_drv_probe, |
| 354 | .remove = dsa_loop_drv_remove, | 373 | .remove = dsa_loop_drv_remove, |
| 374 | .shutdown = dsa_loop_drv_shutdown, | ||
| 355 | }; | 375 | }; |
| 356 | 376 | ||
| 357 | #define NUM_FIXED_PHYS (DSA_LOOP_NUM_PORTS - 2) | 377 | #define NUM_FIXED_PHYS (DSA_LOOP_NUM_PORTS - 2) |
| @@ -1916,6 +1916,9 @@ static int hellcreek_remove(struct platform_device *pdev) · 1915 unmodified lines | |||
| 1916 | { | 1916 | { |
| 1917 | struct hellcreek *hellcreek = platform_get_drvdata(pdev); | 1917 | struct hellcreek *hellcreek = platform_get_drvdata(pdev); |
| 1918 | 1918 | ||
| 1919 | if (!hellcreek) | ||
| 1920 | return 0; | ||
| 1921 | |||
| 1919 | hellcreek_hwtstamp_free(hellcreek); | 1922 | hellcreek_hwtstamp_free(hellcreek); |
| 1920 | hellcreek_ptp_free(hellcreek); | 1923 | hellcreek_ptp_free(hellcreek); |
| 1921 | dsa_unregister_switch(hellcreek->ds); | 1924 | dsa_unregister_switch(hellcreek->ds); |
| @@ -1924,6 +1927,18 @@ static int hellcreek_remove(struct platform_device *pdev) · 2 unmodified lines | |||
| 1924 | return 0; | 1927 | return 0; |
| 1925 | } | 1928 | } |
| 1926 | 1929 | ||
| 1930 | static void hellcreek_shutdown(struct platform_device *pdev) | ||
| 1931 | { | ||
| 1932 | struct hellcreek *hellcreek = platform_get_drvdata(pdev); | ||
| 1933 | |||
| 1934 | if (!hellcreek) | ||
| 1935 | return; | ||
| 1936 | |||
| 1937 | dsa_switch_shutdown(hellcreek->ds); | ||
| 1938 | |||
| 1939 | platform_set_drvdata(pdev, NULL); | ||
| 1940 | } | ||
| 1941 | |||
| 1927 | static const struct hellcreek_platform_data de1soc_r1_pdata = { | 1942 | static const struct hellcreek_platform_data de1soc_r1_pdata = { |
| 1928 | .name = "r4c30", | 1943 | .name = "r4c30", |
| 1929 | .num_ports = 4, | 1944 | .num_ports = 4, |
| @@ -1946,6 +1961,7 @@ MODULE_DEVICE_TABLE(of, hellcreek_of_match); · 16 unmodified lines | |||
| 1946 | static struct platform_driver hellcreek_driver = { | 1961 | static struct platform_driver hellcreek_driver = { |
| 1947 | .probe = hellcreek_probe, | 1962 | .probe = hellcreek_probe, |
| 1948 | .remove = hellcreek_remove, | 1963 | .remove = hellcreek_remove, |
| 1964 | .shutdown = hellcreek_shutdown, | ||
| 1949 | .driver = { | 1965 | .driver = { |
| 1950 | .name = "hellcreek", | 1966 | .name = "hellcreek", |
| 1951 | .of_match_table = hellcreek_of_match, | 1967 | .of_match_table = hellcreek_of_match, |
| @@ -1379,6 +1379,12 @@ int lan9303_remove(struct lan9303 *chip) · 1378 unmodified lines | |||
| 1379 | } | 1379 | } |
| 1380 | EXPORT_SYMBOL(lan9303_remove); | 1380 | EXPORT_SYMBOL(lan9303_remove); |
| 1381 | 1381 | ||
| 1382 | void lan9303_shutdown(struct lan9303 *chip) | ||
| 1383 | { | ||
| 1384 | dsa_switch_shutdown(chip->ds); | ||
| 1385 | } | ||
| 1386 | EXPORT_SYMBOL(lan9303_shutdown); | ||
| 1387 | |||
| 1382 | MODULE_AUTHOR("Juergen Borleis <kernel@pengutronix.de>"); | 1388 | MODULE_AUTHOR("Juergen Borleis <kernel@pengutronix.de>"); |
| 1383 | MODULE_DESCRIPTION("Core driver for SMSC/Microchip LAN9303 three port ethernet switch"); | 1389 | MODULE_DESCRIPTION("Core driver for SMSC/Microchip LAN9303 three port ethernet switch"); |
| 1384 | MODULE_LICENSE("GPL v2"); | 1390 | MODULE_LICENSE("GPL v2"); |
| @@ -10,3 +10,4 @@ extern const struct lan9303_phy_ops lan9303_indirect_phy_ops; · 9 unmodified lines | |||
| 10 | 10 | ||
| 11 | int lan9303_probe(struct lan9303 *chip, struct device_node *np); | 11 | int lan9303_probe(struct lan9303 *chip, struct device_node *np); |
| 12 | int lan9303_remove(struct lan9303 *chip); | 12 | int lan9303_remove(struct lan9303 *chip); |
| 13 | void lan9303_shutdown(struct lan9303 *chip); | ||
| @@ -67,13 +67,28 @@ static int lan9303_i2c_probe(struct i2c_client *client, · 66 unmodified lines | |||
| 67 | 67 | ||
| 68 | static int lan9303_i2c_remove(struct i2c_client *client) | 68 | static int lan9303_i2c_remove(struct i2c_client *client) |
| 69 | { | 69 | { |
| 70 | struct lan9303_i2c *sw_dev; | 70 | struct lan9303_i2c *sw_dev = i2c_get_clientdata(client); |
| 71 | 71 | ||
| 72 | sw_dev = i2c_get_clientdata(client); | ||
| 73 | if (!sw_dev) | 72 | if (!sw_dev) |
| 74 | return -ENODEV; | 73 | return 0; |
| 74 | |||
| 75 | lan9303_remove(&sw_dev->chip); | ||
| 76 | |||
| 77 | i2c_set_clientdata(client, NULL); | ||
| 78 | |||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | static void lan9303_i2c_shutdown(struct i2c_client *client) | ||
| 83 | { | ||
| 84 | struct lan9303_i2c *sw_dev = i2c_get_clientdata(client); | ||
| 85 | |||
| 86 | if (!sw_dev) | ||
| 87 | return; | ||
| 88 | |||
| 89 | lan9303_shutdown(&sw_dev->chip); | ||
| 75 | 90 | ||
| 76 | return lan9303_remove(&sw_dev->chip); | 91 | i2c_set_clientdata(client, NULL); |
| 77 | } | 92 | } |
| 78 | 93 | ||
| 79 | /*-------------------------------------------------------------------------*/ | 94 | /*-------------------------------------------------------------------------*/ |
| @@ -97,6 +112,7 @@ static struct i2c_driver lan9303_i2c_driver = { · 17 unmodified lines | |||
| 97 | }, | 112 | }, |
| 98 | .probe = lan9303_i2c_probe, | 113 | .probe = lan9303_i2c_probe, |
| 99 | .remove = lan9303_i2c_remove, | 114 | .remove = lan9303_i2c_remove, |
| 115 | .shutdown = lan9303_i2c_shutdown, | ||
| 100 | .id_table = lan9303_i2c_id, | 116 | .id_table = lan9303_i2c_id, |
| 101 | }; | 117 | }; |
| 102 | module_i2c_driver(lan9303_i2c_driver); | 118 | module_i2c_driver(lan9303_i2c_driver); |
| @@ -138,6 +138,20 @@ static void lan9303_mdio_remove(struct mdio_device *mdiodev) · 137 unmodified lines | |||
| 138 | return; | 138 | return; |
| 139 | 139 | ||
| 140 | lan9303_remove(&sw_dev->chip); | 140 | lan9303_remove(&sw_dev->chip); |
| 141 | |||
| 142 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 143 | } | ||
| 144 | |||
| 145 | static void lan9303_mdio_shutdown(struct mdio_device *mdiodev) | ||
| 146 | { | ||
| 147 | struct lan9303_mdio *sw_dev = dev_get_drvdata(&mdiodev->dev); | ||
| 148 | |||
| 149 | if (!sw_dev) | ||
| 150 | return; | ||
| 151 | |||
| 152 | lan9303_shutdown(&sw_dev->chip); | ||
| 153 | |||
| 154 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 141 | } | 155 | } |
| 142 | 156 | ||
| 143 | /*-------------------------------------------------------------------------*/ | 157 | /*-------------------------------------------------------------------------*/ |
| @@ -155,6 +169,7 @@ static struct mdio_driver lan9303_mdio_driver = { · 11 unmodified lines | |||
| 155 | }, | 169 | }, |
| 156 | .probe = lan9303_mdio_probe, | 170 | .probe = lan9303_mdio_probe, |
| 157 | .remove = lan9303_mdio_remove, | 171 | .remove = lan9303_mdio_remove, |
| 172 | .shutdown = lan9303_mdio_shutdown, | ||
| 158 | }; | 173 | }; |
| 159 | mdio_module_driver(lan9303_mdio_driver); | 174 | mdio_module_driver(lan9303_mdio_driver); |
| 160 | 175 | ||
| @@ -2184,6 +2184,9 @@ static int gswip_remove(struct platform_device *pdev) · 2183 unmodified lines | |||
| 2184 | struct gswip_priv *priv = platform_get_drvdata(pdev); | 2184 | struct gswip_priv *priv = platform_get_drvdata(pdev); |
| 2185 | int i; | 2185 | int i; |
| 2186 | 2186 | ||
| 2187 | if (!priv) | ||
| 2188 | return 0; | ||
| 2189 | |||
| 2187 | /* disable the switch */ | 2190 | /* disable the switch */ |
| 2188 | gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB); | 2191 | gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB); |
| 2189 | 2192 | ||
| @@ -2197,9 +2200,23 @@ static int gswip_remove(struct platform_device *pdev) · 7 unmodified lines | |||
| 2197 | for (i = 0; i < priv->num_gphy_fw; i++) | 2200 | for (i = 0; i < priv->num_gphy_fw; i++) |
| 2198 | gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]); | 2201 | gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]); |
| 2199 | 2202 | ||
| 2203 | platform_set_drvdata(pdev, NULL); | ||
| 2204 | |||
| 2200 | return 0; | 2205 | return 0; |
| 2201 | } | 2206 | } |
| 2202 | 2207 | ||
| 2208 | static void gswip_shutdown(struct platform_device *pdev) | ||
| 2209 | { | ||
| 2210 | struct gswip_priv *priv = platform_get_drvdata(pdev); | ||
| 2211 | |||
| 2212 | if (!priv) | ||
| 2213 | return; | ||
| 2214 | |||
| 2215 | dsa_switch_shutdown(priv->ds); | ||
| 2216 | |||
| 2217 | platform_set_drvdata(pdev, NULL); | ||
| 2218 | } | ||
| 2219 | |||
| 2203 | static const struct gswip_hw_info gswip_xrx200 = { | 2220 | static const struct gswip_hw_info gswip_xrx200 = { |
| 2204 | .max_ports = 7, | 2221 | .max_ports = 7, |
| 2205 | .cpu_port = 6, | 2222 | .cpu_port = 6, |
| @@ -2223,6 +2240,7 @@ MODULE_DEVICE_TABLE(of, gswip_of_match); · 17 unmodified lines | |||
| 2223 | static struct platform_driver gswip_driver = { | 2240 | static struct platform_driver gswip_driver = { |
| 2224 | .probe = gswip_probe, | 2241 | .probe = gswip_probe, |
| 2225 | .remove = gswip_remove, | 2242 | .remove = gswip_remove, |
| 2243 | .shutdown = gswip_shutdown, | ||
| 2226 | .driver = { | 2244 | .driver = { |
| 2227 | .name = "gswip", | 2245 | .name = "gswip", |
| 2228 | .of_match_table = gswip_of_match, | 2246 | .of_match_table = gswip_of_match, |
| @@ -94,6 +94,8 @@ static int ksz8795_spi_remove(struct spi_device *spi) · 93 unmodified lines | |||
| 94 | if (dev) | 94 | if (dev) |
| 95 | ksz_switch_remove(dev); | 95 | ksz_switch_remove(dev); |
| 96 | 96 | ||
| 97 | spi_set_drvdata(spi, NULL); | ||
| 98 | |||
| 97 | return 0; | 99 | return 0; |
| 98 | } | 100 | } |
| 99 | 101 | ||
| @@ -101,8 +103,15 @@ static void ksz8795_spi_shutdown(struct spi_device *spi) · 1 unmodified line | |||
| 101 | { | 103 | { |
| 102 | struct ksz_device *dev = spi_get_drvdata(spi); | 104 | struct ksz_device *dev = spi_get_drvdata(spi); |
| 103 | 105 | ||
| 104 | if (dev && dev->dev_ops->shutdown) | 106 | if (!dev) |
| 107 | return; | ||
| 108 | |||
| 109 | if (dev->dev_ops->shutdown) | ||
| 105 | dev->dev_ops->shutdown(dev); | 110 | dev->dev_ops->shutdown(dev); |
| 111 | |||
| 112 | dsa_switch_shutdown(dev->ds); | ||
| 113 | |||
| 114 | spi_set_drvdata(spi, NULL); | ||
| 106 | } | 115 | } |
| 107 | 116 | ||
| 108 | static const struct of_device_id ksz8795_dt_ids[] = { | 117 | static const struct of_device_id ksz8795_dt_ids[] = { |
| @@ -191,6 +191,18 @@ static void ksz8863_smi_remove(struct mdio_device *mdiodev) · 190 unmodified lines | |||
| 191 | 191 | ||
| 192 | if (dev) | 192 | if (dev) |
| 193 | ksz_switch_remove(dev); | 193 | ksz_switch_remove(dev); |
| 194 | |||
| 195 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 196 | } | ||
| 197 | |||
| 198 | static void ksz8863_smi_shutdown(struct mdio_device *mdiodev) | ||
| 199 | { | ||
| 200 | struct ksz_device *dev = dev_get_drvdata(&mdiodev->dev); | ||
| 201 | |||
| 202 | if (dev) | ||
| 203 | dsa_switch_shutdown(dev->ds); | ||
| 204 | |||
| 205 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 194 | } | 206 | } |
| 195 | 207 | ||
| 196 | static const struct of_device_id ksz8863_dt_ids[] = { | 208 | static const struct of_device_id ksz8863_dt_ids[] = { |
| @@ -203,6 +215,7 @@ MODULE_DEVICE_TABLE(of, ksz8863_dt_ids); · 6 unmodified lines | |||
| 203 | static struct mdio_driver ksz8863_driver = { | 215 | static struct mdio_driver ksz8863_driver = { |
| 204 | .probe = ksz8863_smi_probe, | 216 | .probe = ksz8863_smi_probe, |
| 205 | .remove = ksz8863_smi_remove, | 217 | .remove = ksz8863_smi_remove, |
| 218 | .shutdown = ksz8863_smi_shutdown, | ||
| 206 | .mdiodrv.driver = { | 219 | .mdiodrv.driver = { |
| 207 | .name = "ksz8863-switch", | 220 | .name = "ksz8863-switch", |
| 208 | .of_match_table = ksz8863_dt_ids, | 221 | .of_match_table = ksz8863_dt_ids, |
| @@ -56,7 +56,10 @@ static int ksz9477_i2c_remove(struct i2c_client *i2c) · 55 unmodified lines | |||
| 56 | { | 56 | { |
| 57 | struct ksz_device *dev = i2c_get_clientdata(i2c); | 57 | struct ksz_device *dev = i2c_get_clientdata(i2c); |
| 58 | 58 | ||
| 59 | ksz_switch_remove(dev); | 59 | if (dev) |
| 60 | ksz_switch_remove(dev); | ||
| 61 | |||
| 62 | i2c_set_clientdata(i2c, NULL); | ||
| 60 | 63 | ||
| 61 | return 0; | 64 | return 0; |
| 62 | } | 65 | } |
| @@ -65,8 +68,15 @@ static void ksz9477_i2c_shutdown(struct i2c_client *i2c) · 2 unmodified lines | |||
| 65 | { | 68 | { |
| 66 | struct ksz_device *dev = i2c_get_clientdata(i2c); | 69 | struct ksz_device *dev = i2c_get_clientdata(i2c); |
| 67 | 70 | ||
| 68 | if (dev && dev->dev_ops->shutdown) | 71 | if (!dev) |
| 72 | return; | ||
| 73 | |||
| 74 | if (dev->dev_ops->shutdown) | ||
| 69 | dev->dev_ops->shutdown(dev); | 75 | dev->dev_ops->shutdown(dev); |
| 76 | |||
| 77 | dsa_switch_shutdown(dev->ds); | ||
| 78 | |||
| 79 | i2c_set_clientdata(i2c, NULL); | ||
| 70 | } | 80 | } |
| 71 | 81 | ||
| 72 | static const struct i2c_device_id ksz9477_i2c_id[] = { | 82 | static const struct i2c_device_id ksz9477_i2c_id[] = { |
| @@ -72,6 +72,8 @@ static int ksz9477_spi_remove(struct spi_device *spi) · 71 unmodified lines | |||
| 72 | if (dev) | 72 | if (dev) |
| 73 | ksz_switch_remove(dev); | 73 | ksz_switch_remove(dev); |
| 74 | 74 | ||
| 75 | spi_set_drvdata(spi, NULL); | ||
| 76 | |||
| 75 | return 0; | 77 | return 0; |
| 76 | } | 78 | } |
| 77 | 79 | ||
| @@ -79,8 +81,10 @@ static void ksz9477_spi_shutdown(struct spi_device *spi) · 1 unmodified line | |||
| 79 | { | 81 | { |
| 80 | struct ksz_device *dev = spi_get_drvdata(spi); | 82 | struct ksz_device *dev = spi_get_drvdata(spi); |
| 81 | 83 | ||
| 82 | if (dev && dev->dev_ops->shutdown) | 84 | if (dev) |
| 83 | dev->dev_ops->shutdown(dev); | 85 | dsa_switch_shutdown(dev->ds); |
| 86 | |||
| 87 | spi_set_drvdata(spi, NULL); | ||
| 84 | } | 88 | } |
| 85 | 89 | ||
| 86 | static const struct of_device_id ksz9477_dt_ids[] = { | 90 | static const struct of_device_id ksz9477_dt_ids[] = { |
| @@ -3286,6 +3286,9 @@ mt7530_remove(struct mdio_device *mdiodev) · 3285 unmodified lines | |||
| 3286 | struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); | 3286 | struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); |
| 3287 | int ret = 0; | 3287 | int ret = 0; |
| 3288 | 3288 | ||
| 3289 | if (!priv) | ||
| 3290 | return; | ||
| 3291 | |||
| 3289 | ret = regulator_disable(priv->core_pwr); | 3292 | ret = regulator_disable(priv->core_pwr); |
| 3290 | if (ret < 0) | 3293 | if (ret < 0) |
| 3291 | dev_err(priv->dev, | 3294 | dev_err(priv->dev, |
| @@ -3301,11 +3304,26 @@ mt7530_remove(struct mdio_device *mdiodev) · 9 unmodified lines | |||
| 3301 | 3304 | ||
| 3302 | dsa_unregister_switch(priv->ds); | 3305 | dsa_unregister_switch(priv->ds); |
| 3303 | mutex_destroy(&priv->reg_mutex); | 3306 | mutex_destroy(&priv->reg_mutex); |
| 3307 | |||
| 3308 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 3309 | } | ||
| 3310 | |||
| 3311 | static void mt7530_shutdown(struct mdio_device *mdiodev) | ||
| 3312 | { | ||
| 3313 | struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); | ||
| 3314 | |||
| 3315 | if (!priv) | ||
| 3316 | return; | ||
| 3317 | |||
| 3318 | dsa_switch_shutdown(priv->ds); | ||
| 3319 | |||
| 3320 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 3304 | } | 3321 | } |
| 3305 | 3322 | ||
| 3306 | static struct mdio_driver mt7530_mdio_driver = { | 3323 | static struct mdio_driver mt7530_mdio_driver = { |
| 3307 | .probe = mt7530_probe, | 3324 | .probe = mt7530_probe, |
| 3308 | .remove = mt7530_remove, | 3325 | .remove = mt7530_remove, |
| 3326 | .shutdown = mt7530_shutdown, | ||
| 3309 | .mdiodrv.driver = { | 3327 | .mdiodrv.driver = { |
| 3310 | .name = "mt7530", | 3328 | .name = "mt7530", |
| 3311 | .of_match_table = mt7530_of_match, | 3329 | .of_match_table = mt7530_of_match, |
| @@ -290,7 +290,24 @@ static void mv88e6060_remove(struct mdio_device *mdiodev) · 289 unmodified lines | |||
| 290 | { | 290 | { |
| 291 | struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); | 291 | struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); |
| 292 | 292 | ||
| 293 | if (!ds) | ||
| 294 | return; | ||
| 295 | |||
| 293 | dsa_unregister_switch(ds); | 296 | dsa_unregister_switch(ds); |
| 297 | |||
| 298 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 299 | } | ||
| 300 | |||
| 301 | static void mv88e6060_shutdown(struct mdio_device *mdiodev) | ||
| 302 | { | ||
| 303 | struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); | ||
| 304 | |||
| 305 | if (!ds) | ||
| 306 | return; | ||
| 307 | |||
| 308 | dsa_switch_shutdown(ds); | ||
| 309 | |||
| 310 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 294 | } | 311 | } |
| 295 | 312 | ||
| 296 | static const struct of_device_id mv88e6060_of_match[] = { | 313 | static const struct of_device_id mv88e6060_of_match[] = { |
| @@ -303,6 +320,7 @@ static const struct of_device_id mv88e6060_of_match[] = { · 6 unmodified lines | |||
| 303 | static struct mdio_driver mv88e6060_driver = { | 320 | static struct mdio_driver mv88e6060_driver = { |
| 304 | .probe = mv88e6060_probe, | 321 | .probe = mv88e6060_probe, |
| 305 | .remove = mv88e6060_remove, | 322 | .remove = mv88e6060_remove, |
| 323 | .shutdown = mv88e6060_shutdown, | ||
| 306 | .mdiodrv.driver = { | 324 | .mdiodrv.driver = { |
| 307 | .name = "mv88e6060", | 325 | .name = "mv88e6060", |
| 308 | .of_match_table = mv88e6060_of_match, | 326 | .of_match_table = mv88e6060_of_match, |
| @@ -3071,7 +3071,7 @@ static void mv88e6xxx_teardown(struct dsa_switch *ds) · 3070 unmodified lines | |||
| 3071 | { | 3071 | { |
| 3072 | mv88e6xxx_teardown_devlink_params(ds); | 3072 | mv88e6xxx_teardown_devlink_params(ds); |
| 3073 | dsa_devlink_resources_unregister(ds); | 3073 | dsa_devlink_resources_unregister(ds); |
| 3074 | mv88e6xxx_teardown_devlink_regions(ds); | 3074 | mv88e6xxx_teardown_devlink_regions_global(ds); |
| 3075 | } | 3075 | } |
| 3076 | 3076 | ||
| 3077 | static int mv88e6xxx_setup(struct dsa_switch *ds) | 3077 | static int mv88e6xxx_setup(struct dsa_switch *ds) |
| @@ -3215,7 +3215,7 @@ unlock: · 137 unmodified lines | |||
| 3215 | if (err) | 3215 | if (err) |
| 3216 | goto out_resources; | 3216 | goto out_resources; |
| 3217 | 3217 | ||
| 3218 | err = mv88e6xxx_setup_devlink_regions(ds); | 3218 | err = mv88e6xxx_setup_devlink_regions_global(ds); |
| 3219 | if (err) | 3219 | if (err) |
| 3220 | goto out_params; | 3220 | goto out_params; |
| 3221 | 3221 | ||
| @@ -3229,6 +3229,16 @@ out_resources: · 7 unmodified lines | |||
| 3229 | return err; | 3229 | return err; |
| 3230 | } | 3230 | } |
| 3231 | 3231 | ||
| 3232 | static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port) | ||
| 3233 | { | ||
| 3234 | return mv88e6xxx_setup_devlink_regions_port(ds, port); | ||
| 3235 | } | ||
| 3236 | |||
| 3237 | static void mv88e6xxx_port_teardown(struct dsa_switch *ds, int port) | ||
| 3238 | { | ||
| 3239 | mv88e6xxx_teardown_devlink_regions_port(ds, port); | ||
| 3240 | } | ||
| 3241 | |||
| 3232 | /* prod_id for switch families which do not have a PHY model number */ | 3242 | /* prod_id for switch families which do not have a PHY model number */ |
| 3233 | static const u16 family_prod_id_table[] = { | 3243 | static const u16 family_prod_id_table[] = { |
| 3234 | [MV88E6XXX_FAMILY_6341] = MV88E6XXX_PORT_SWITCH_ID_PROD_6341, | 3244 | [MV88E6XXX_FAMILY_6341] = MV88E6XXX_PORT_SWITCH_ID_PROD_6341, |
| @@ -6116,6 +6126,8 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { · 2881 unmodified lines | |||
| 6116 | .change_tag_protocol = mv88e6xxx_change_tag_protocol, | 6126 | .change_tag_protocol = mv88e6xxx_change_tag_protocol, |
| 6117 | .setup = mv88e6xxx_setup, | 6127 | .setup = mv88e6xxx_setup, |
| 6118 | .teardown = mv88e6xxx_teardown, | 6128 | .teardown = mv88e6xxx_teardown, |
| 6129 | .port_setup = mv88e6xxx_port_setup, | ||
| 6130 | .port_teardown = mv88e6xxx_port_teardown, | ||
| 6119 | .phylink_validate = mv88e6xxx_validate, | 6131 | .phylink_validate = mv88e6xxx_validate, |
| 6120 | .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state, | 6132 | .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state, |
| 6121 | .phylink_mac_config = mv88e6xxx_mac_config, | 6133 | .phylink_mac_config = mv88e6xxx_mac_config, |
| @@ -6389,7 +6401,12 @@ out: · 267 unmodified lines | |||
| 6389 | static void mv88e6xxx_remove(struct mdio_device *mdiodev) | 6401 | static void mv88e6xxx_remove(struct mdio_device *mdiodev) |
| 6390 | { | 6402 | { |
| 6391 | struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); | 6403 | struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); |
| 6392 | struct mv88e6xxx_chip *chip = ds->priv; | 6404 | struct mv88e6xxx_chip *chip; |
| 6405 | |||
| 6406 | if (!ds) | ||
| 6407 | return; | ||
| 6408 | |||
| 6409 | chip = ds->priv; | ||
| 6393 | 6410 | ||
| 6394 | if (chip->info->ptp_support) { | 6411 | if (chip->info->ptp_support) { |
| 6395 | mv88e6xxx_hwtstamp_free(chip); | 6412 | mv88e6xxx_hwtstamp_free(chip); |
| @@ -6410,6 +6427,20 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev) · 14 unmodified lines | |||
| 6410 | mv88e6xxx_g1_irq_free(chip); | 6427 | mv88e6xxx_g1_irq_free(chip); |
| 6411 | else | 6428 | else |
| 6412 | mv88e6xxx_irq_poll_free(chip); | 6429 | mv88e6xxx_irq_poll_free(chip); |
| 6430 | |||
| 6431 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 6432 | } | ||
| 6433 | |||
| 6434 | static void mv88e6xxx_shutdown(struct mdio_device *mdiodev) | ||
| 6435 | { | ||
| 6436 | struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); | ||
| 6437 | |||
| 6438 | if (!ds) | ||
| 6439 | return; | ||
| 6440 | |||
| 6441 | dsa_switch_shutdown(ds); | ||
| 6442 | |||
| 6443 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 6413 | } | 6444 | } |
| 6414 | 6445 | ||
| 6415 | static const struct of_device_id mv88e6xxx_of_match[] = { | 6446 | static const struct of_device_id mv88e6xxx_of_match[] = { |
| @@ -6433,6 +6464,7 @@ MODULE_DEVICE_TABLE(of, mv88e6xxx_of_match); · 17 unmodified lines | |||
| 6433 | static struct mdio_driver mv88e6xxx_driver = { | 6464 | static struct mdio_driver mv88e6xxx_driver = { |
| 6434 | .probe = mv88e6xxx_probe, | 6465 | .probe = mv88e6xxx_probe, |
| 6435 | .remove = mv88e6xxx_remove, | 6466 | .remove = mv88e6xxx_remove, |
| 6467 | .shutdown = mv88e6xxx_shutdown, | ||
| 6436 | .mdiodrv.driver = { | 6468 | .mdiodrv.driver = { |
| 6437 | .name = "mv88e6085", | 6469 | .name = "mv88e6085", |
| 6438 | .of_match_table = mv88e6xxx_of_match, | 6470 | .of_match_table = mv88e6xxx_of_match, |
| @@ -647,26 +647,25 @@ static struct mv88e6xxx_region mv88e6xxx_regions[] = { · 646 unmodified lines | |||
| 647 | }, | 647 | }, |
| 648 | }; | 648 | }; |
| 649 | 649 | ||
| 650 | static void | 650 | void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds) |
| 651 | mv88e6xxx_teardown_devlink_regions_global(struct mv88e6xxx_chip *chip) | ||
| 652 | { | 651 | { |
| 652 | struct mv88e6xxx_chip *chip = ds->priv; | ||
| 653 | int i; | 653 | int i; |
| 654 | 654 | ||
| 655 | for (i = 0; i < ARRAY_SIZE(mv88e6xxx_regions); i++) | 655 | for (i = 0; i < ARRAY_SIZE(mv88e6xxx_regions); i++) |
| 656 | dsa_devlink_region_destroy(chip->regions[i]); | 656 | dsa_devlink_region_destroy(chip->regions[i]); |
| 657 | } | 657 | } |
| 658 | 658 | ||
| 659 | static void | 659 | void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port) |
| 660 | mv88e6xxx_teardown_devlink_regions_port(struct mv88e6xxx_chip *chip, | ||
| 661 | int port) | ||
| 662 | { | 660 | { |
| 661 | struct mv88e6xxx_chip *chip = ds->priv; | ||
| 662 | |||
| 663 | dsa_devlink_region_destroy(chip->ports[port].region); | 663 | dsa_devlink_region_destroy(chip->ports[port].region); |
| 664 | } | 664 | } |
| 665 | 665 | ||
| 666 | static int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, | 666 | int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, int port) |
| 667 | struct mv88e6xxx_chip *chip, | ||
| 668 | int port) | ||
| 669 | { | 667 | { |
| 668 | struct mv88e6xxx_chip *chip = ds->priv; | ||
| 670 | struct devlink_region *region; | 669 | struct devlink_region *region; |
| 671 | 670 | ||
| 672 | region = dsa_devlink_port_region_create(ds, | 671 | region = dsa_devlink_port_region_create(ds, |
| @@ -681,40 +680,10 @@ static int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, · 8 unmodified lines | |||
| 681 | return 0; | 680 | return 0; |
| 682 | } | 681 | } |
| 683 | 682 | ||
| 684 | static void | 683 | int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds) |
| 685 | mv88e6xxx_teardown_devlink_regions_ports(struct mv88e6xxx_chip *chip) | ||
| 686 | { | ||
| 687 | int port; | ||
| 688 | |||
| 689 | for (port = 0; port < mv88e6xxx_num_ports(chip); port++) | ||
| 690 | mv88e6xxx_teardown_devlink_regions_port(chip, port); | ||
| 691 | } | ||
| 692 | |||
| 693 | static int mv88e6xxx_setup_devlink_regions_ports(struct dsa_switch *ds, | ||
| 694 | struct mv88e6xxx_chip *chip) | ||
| 695 | { | ||
| 696 | int port; | ||
| 697 | int err; | ||
| 698 | |||
| 699 | for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { | ||
| 700 | err = mv88e6xxx_setup_devlink_regions_port(ds, chip, port); | ||
| 701 | if (err) | ||
| 702 | goto out; | ||
| 703 | } | ||
| 704 | |||
| 705 | return 0; | ||
| 706 | |||
| 707 | out: | ||
| 708 | while (port-- > 0) | ||
| 709 | mv88e6xxx_teardown_devlink_regions_port(chip, port); | ||
| 710 | |||
| 711 | return err; | ||
| 712 | } | ||
| 713 | |||
| 714 | static int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds, | ||
| 715 | struct mv88e6xxx_chip *chip) | ||
| 716 | { | 684 | { |
| 717 | bool (*cond)(struct mv88e6xxx_chip *chip); | 685 | bool (*cond)(struct mv88e6xxx_chip *chip); |
| 686 | struct mv88e6xxx_chip *chip = ds->priv; | ||
| 718 | struct devlink_region_ops *ops; | 687 | struct devlink_region_ops *ops; |
| 719 | struct devlink_region *region; | 688 | struct devlink_region *region; |
| 720 | u64 size; | 689 | u64 size; |
| @@ -753,30 +722,6 @@ out: · 32 unmodified lines | |||
| 753 | return PTR_ERR(region); | 722 | return PTR_ERR(region); |
| 754 | } | 723 | } |
| 755 | 724 | ||
| 756 | int mv88e6xxx_setup_devlink_regions(struct dsa_switch *ds) | ||
| 757 | { | ||
| 758 | struct mv88e6xxx_chip *chip = ds->priv; | ||
| 759 | int err; | ||
| 760 | |||
| 761 | err = mv88e6xxx_setup_devlink_regions_global(ds, chip); | ||
| 762 | if (err) | ||
| 763 | return err; | ||
| 764 | |||
| 765 | err = mv88e6xxx_setup_devlink_regions_ports(ds, chip); | ||
| 766 | if (err) | ||
| 767 | mv88e6xxx_teardown_devlink_regions_global(chip); | ||
| 768 | |||
| 769 | return err; | ||
| 770 | } | ||
| 771 | |||
| 772 | void mv88e6xxx_teardown_devlink_regions(struct dsa_switch *ds) | ||
| 773 | { | ||
| 774 | struct mv88e6xxx_chip *chip = ds->priv; | ||
| 775 | |||
| 776 | mv88e6xxx_teardown_devlink_regions_ports(chip); | ||
| 777 | mv88e6xxx_teardown_devlink_regions_global(chip); | ||
| 778 | } | ||
| 779 | |||
| 780 | int mv88e6xxx_devlink_info_get(struct dsa_switch *ds, | 725 | int mv88e6xxx_devlink_info_get(struct dsa_switch *ds, |
| 781 | struct devlink_info_req *req, | 726 | struct devlink_info_req *req, |
| 782 | struct netlink_ext_ack *extack) | 727 | struct netlink_ext_ack *extack) |
| @@ -12,8 +12,10 @@ int mv88e6xxx_devlink_param_get(struct dsa_switch *ds, u32 id, · 11 unmodified lines | |||
| 12 | struct devlink_param_gset_ctx *ctx); | 12 | struct devlink_param_gset_ctx *ctx); |
| 13 | int mv88e6xxx_devlink_param_set(struct dsa_switch *ds, u32 id, | 13 | int mv88e6xxx_devlink_param_set(struct dsa_switch *ds, u32 id, |
| 14 | struct devlink_param_gset_ctx *ctx); | 14 | struct devlink_param_gset_ctx *ctx); |
| 15 | int mv88e6xxx_setup_devlink_regions(struct dsa_switch *ds); | 15 | int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds); |
| 16 | void mv88e6xxx_teardown_devlink_regions(struct dsa_switch *ds); | 16 | void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds); |
| 17 | int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, int port); | ||
| 18 | void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port); | ||
| 17 | 19 | ||
| 18 | int mv88e6xxx_devlink_info_get(struct dsa_switch *ds, | 20 | int mv88e6xxx_devlink_info_get(struct dsa_switch *ds, |
| 19 | struct devlink_info_req *req, | 21 | struct devlink_info_req *req, |
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* Copyright 2019-2021 NXP Semiconductors | 2 | /* Copyright 2019-2021 NXP |
| 3 | * | 3 | * |
| 4 | * This is an umbrella module for all network switches that are | 4 | * This is an umbrella module for all network switches that are |
| 5 | * register-compatible with Ocelot and that perform I/O to their host CPU | 5 | * register-compatible with Ocelot and that perform I/O to their host CPU |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | /* Copyright 2019 NXP Semiconductors | 2 | /* Copyright 2019 NXP |
| 3 | */ | 3 | */ |
| 4 | #ifndef _MSCC_FELIX_H | 4 | #ifndef _MSCC_FELIX_H |
| 5 | #define _MSCC_FELIX_H | 5 | #define _MSCC_FELIX_H |
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: (GPL-2.0 OR MIT) | 1 | // SPDX-License-Identifier: (GPL-2.0 OR MIT) |
| 2 | /* Copyright 2017 Microsemi Corporation | 2 | /* Copyright 2017 Microsemi Corporation |
| 3 | * Copyright 2018-2019 NXP Semiconductors | 3 | * Copyright 2018-2019 NXP |
| 4 | */ | 4 | */ |
| 5 | #include <linux/fsl/enetc_mdio.h> | 5 | #include <linux/fsl/enetc_mdio.h> |
| 6 | #include <soc/mscc/ocelot_qsys.h> | 6 | #include <soc/mscc/ocelot_qsys.h> |
| @@ -1472,9 +1472,10 @@ err_pci_enable: · 1465 unmodified lines | |||
| 1472 | 1472 | ||
| 1473 | static void felix_pci_remove(struct pci_dev *pdev) | 1473 | static void felix_pci_remove(struct pci_dev *pdev) |
| 1474 | { | 1474 | { |
| 1475 | struct felix *felix; | 1475 | struct felix *felix = pci_get_drvdata(pdev); |
| 1476 | 1476 | ||
| 1477 | felix = pci_get_drvdata(pdev); | 1477 | if (!felix) |
| 1478 | return; | ||
| 1478 | 1479 | ||
| 1479 | dsa_unregister_switch(felix->ds); | 1480 | dsa_unregister_switch(felix->ds); |
| 1480 | 1481 | ||
| @@ -1482,6 +1483,20 @@ static void felix_pci_remove(struct pci_dev *pdev) · 1 unmodified line | |||
| 1482 | kfree(felix); | 1483 | kfree(felix); |
| 1483 | 1484 | ||
| 1484 | pci_disable_device(pdev); | 1485 | pci_disable_device(pdev); |
| 1486 | |||
| 1487 | pci_set_drvdata(pdev, NULL); | ||
| 1488 | } | ||
| 1489 | |||
| 1490 | static void felix_pci_shutdown(struct pci_dev *pdev) | ||
| 1491 | { | ||
| 1492 | struct felix *felix = pci_get_drvdata(pdev); | ||
| 1493 | |||
| 1494 | if (!felix) | ||
| 1495 | return; | ||
| 1496 | |||
| 1497 | dsa_switch_shutdown(felix->ds); | ||
| 1498 | |||
| 1499 | pci_set_drvdata(pdev, NULL); | ||
| 1485 | } | 1500 | } |
| 1486 | 1501 | ||
| 1487 | static struct pci_device_id felix_ids[] = { | 1502 | static struct pci_device_id felix_ids[] = { |
| @@ -1498,6 +1513,7 @@ static struct pci_driver felix_vsc9959_pci_driver = { · 10 unmodified lines | |||
| 1498 | .id_table = felix_ids, | 1513 | .id_table = felix_ids, |
| 1499 | .probe = felix_pci_probe, | 1514 | .probe = felix_pci_probe, |
| 1500 | .remove = felix_pci_remove, | 1515 | .remove = felix_pci_remove, |
| 1516 | .shutdown = felix_pci_shutdown, | ||
| 1501 | }; | 1517 | }; |
| 1502 | module_pci_driver(felix_vsc9959_pci_driver); | 1518 | module_pci_driver(felix_vsc9959_pci_driver); |
| 1503 | 1519 | ||
| @@ -1245,18 +1245,33 @@ err_alloc_felix: · 1244 unmodified lines | |||
| 1245 | 1245 | ||
| 1246 | static int seville_remove(struct platform_device *pdev) | 1246 | static int seville_remove(struct platform_device *pdev) |
| 1247 | { | 1247 | { |
| 1248 | struct felix *felix; | 1248 | struct felix *felix = platform_get_drvdata(pdev); |
| 1249 | 1249 | ||
| 1250 | felix = platform_get_drvdata(pdev); | 1250 | if (!felix) |
| 1251 | return 0; | ||
| 1251 | 1252 | ||
| 1252 | dsa_unregister_switch(felix->ds); | 1253 | dsa_unregister_switch(felix->ds); |
| 1253 | 1254 | ||
| 1254 | kfree(felix->ds); | 1255 | kfree(felix->ds); |
| 1255 | kfree(felix); | 1256 | kfree(felix); |
| 1256 | 1257 | ||
| 1258 | platform_set_drvdata(pdev, NULL); | ||
| 1259 | |||
| 1257 | return 0; | 1260 | return 0; |
| 1258 | } | 1261 | } |
| 1259 | 1262 | ||
| 1263 | static void seville_shutdown(struct platform_device *pdev) | ||
| 1264 | { | ||
| 1265 | struct felix *felix = platform_get_drvdata(pdev); | ||
| 1266 | |||
| 1267 | if (!felix) | ||
| 1268 | return; | ||
| 1269 | |||
| 1270 | dsa_switch_shutdown(felix->ds); | ||
| 1271 | |||
| 1272 | platform_set_drvdata(pdev, NULL); | ||
| 1273 | } | ||
| 1274 | |||
| 1260 | static const struct of_device_id seville_of_match[] = { | 1275 | static const struct of_device_id seville_of_match[] = { |
| 1261 | { .compatible = "mscc,vsc9953-switch" }, | 1276 | { .compatible = "mscc,vsc9953-switch" }, |
| 1262 | { }, | 1277 | { }, |
| @@ -1266,6 +1281,7 @@ MODULE_DEVICE_TABLE(of, seville_of_match); · 3 unmodified lines | |||
| 1266 | static struct platform_driver seville_vsc9953_driver = { | 1281 | static struct platform_driver seville_vsc9953_driver = { |
| 1267 | .probe = seville_probe, | 1282 | .probe = seville_probe, |
| 1268 | .remove = seville_remove, | 1283 | .remove = seville_remove, |
| 1284 | .shutdown = seville_shutdown, | ||
| 1269 | .driver = { | 1285 | .driver = { |
| 1270 | .name = "mscc_seville", | 1286 | .name = "mscc_seville", |
| 1271 | .of_match_table = of_match_ptr(seville_of_match), | 1287 | .of_match_table = of_match_ptr(seville_of_match), |
| @@ -1083,6 +1083,9 @@ static void ar9331_sw_remove(struct mdio_device *mdiodev) · 1082 unmodified lines | |||
| 1083 | struct ar9331_sw_priv *priv = dev_get_drvdata(&mdiodev->dev); | 1083 | struct ar9331_sw_priv *priv = dev_get_drvdata(&mdiodev->dev); |
| 1084 | unsigned int i; | 1084 | unsigned int i; |
| 1085 | 1085 | ||
| 1086 | if (!priv) | ||
| 1087 | return; | ||
| 1088 | |||
| 1086 | for (i = 0; i < ARRAY_SIZE(priv->port); i++) { | 1089 | for (i = 0; i < ARRAY_SIZE(priv->port); i++) { |
| 1087 | struct ar9331_sw_port *port = &priv->port[i]; | 1090 | struct ar9331_sw_port *port = &priv->port[i]; |
| 1088 | 1091 | ||
| @@ -1094,6 +1097,20 @@ static void ar9331_sw_remove(struct mdio_device *mdiodev) · 5 unmodified lines | |||
| 1094 | dsa_unregister_switch(&priv->ds); | 1097 | dsa_unregister_switch(&priv->ds); |
| 1095 | 1098 | ||
| 1096 | reset_control_assert(priv->sw_reset); | 1099 | reset_control_assert(priv->sw_reset); |
| 1100 | |||
| 1101 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | static void ar9331_sw_shutdown(struct mdio_device *mdiodev) | ||
| 1105 | { | ||
| 1106 | struct ar9331_sw_priv *priv = dev_get_drvdata(&mdiodev->dev); | ||
| 1107 | |||
| 1108 | if (!priv) | ||
| 1109 | return; | ||
| 1110 | |||
| 1111 | dsa_switch_shutdown(&priv->ds); | ||
| 1112 | |||
| 1113 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 1097 | } | 1114 | } |
| 1098 | 1115 | ||
| 1099 | static const struct of_device_id ar9331_sw_of_match[] = { | 1116 | static const struct of_device_id ar9331_sw_of_match[] = { |
| @@ -1104,6 +1121,7 @@ static const struct of_device_id ar9331_sw_of_match[] = { · 4 unmodified lines | |||
| 1104 | static struct mdio_driver ar9331_sw_mdio_driver = { | 1121 | static struct mdio_driver ar9331_sw_mdio_driver = { |
| 1105 | .probe = ar9331_sw_probe, | 1122 | .probe = ar9331_sw_probe, |
| 1106 | .remove = ar9331_sw_remove, | 1123 | .remove = ar9331_sw_remove, |
| 1124 | .shutdown = ar9331_sw_shutdown, | ||
| 1107 | .mdiodrv.driver = { | 1125 | .mdiodrv.driver = { |
| 1108 | .name = AR9331_SW_NAME, | 1126 | .name = AR9331_SW_NAME, |
| 1109 | .of_match_table = ar9331_sw_of_match, | 1127 | .of_match_table = ar9331_sw_of_match, |
| @@ -1880,10 +1880,27 @@ qca8k_sw_remove(struct mdio_device *mdiodev) · 1879 unmodified lines | |||
| 1880 | struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev); | 1880 | struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev); |
| 1881 | int i; | 1881 | int i; |
| 1882 | 1882 | ||
| 1883 | if (!priv) | ||
| 1884 | return; | ||
| 1885 | |||
| 1883 | for (i = 0; i < QCA8K_NUM_PORTS; i++) | 1886 | for (i = 0; i < QCA8K_NUM_PORTS; i++) |
| 1884 | qca8k_port_set_status(priv, i, 0); | 1887 | qca8k_port_set_status(priv, i, 0); |
| 1885 | 1888 | ||
| 1886 | dsa_unregister_switch(priv->ds); | 1889 | dsa_unregister_switch(priv->ds); |
| 1890 | |||
| 1891 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 1892 | } | ||
| 1893 | |||
| 1894 | static void qca8k_sw_shutdown(struct mdio_device *mdiodev) | ||
| 1895 | { | ||
| 1896 | struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev); | ||
| 1897 | |||
| 1898 | if (!priv) | ||
| 1899 | return; | ||
| 1900 | |||
| 1901 | dsa_switch_shutdown(priv->ds); | ||
| 1902 | |||
| 1903 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 1887 | } | 1904 | } |
| 1888 | 1905 | ||
| 1889 | #ifdef CONFIG_PM_SLEEP | 1906 | #ifdef CONFIG_PM_SLEEP |
| @@ -1940,6 +1957,7 @@ static const struct of_device_id qca8k_of_match[] = { · 50 unmodified lines | |||
| 1940 | static struct mdio_driver qca8kmdio_driver = { | 1957 | static struct mdio_driver qca8kmdio_driver = { |
| 1941 | .probe = qca8k_sw_probe, | 1958 | .probe = qca8k_sw_probe, |
| 1942 | .remove = qca8k_sw_remove, | 1959 | .remove = qca8k_sw_remove, |
| 1960 | .shutdown = qca8k_sw_shutdown, | ||
| 1943 | .mdiodrv.driver = { | 1961 | .mdiodrv.driver = { |
| 1944 | .name = "qca8k", | 1962 | .name = "qca8k", |
| 1945 | .of_match_table = qca8k_of_match, | 1963 | .of_match_table = qca8k_of_match, |
| @@ -368,7 +368,7 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi) · 367 unmodified lines | |||
| 368 | smi->slave_mii_bus->parent = smi->dev; | 368 | smi->slave_mii_bus->parent = smi->dev; |
| 369 | smi->ds->slave_mii_bus = smi->slave_mii_bus; | 369 | smi->ds->slave_mii_bus = smi->slave_mii_bus; |
| 370 | 370 | ||
| 371 | ret = of_mdiobus_register(smi->slave_mii_bus, mdio_np); | 371 | ret = devm_of_mdiobus_register(smi->dev, smi->slave_mii_bus, mdio_np); |
| 372 | if (ret) { | 372 | if (ret) { |
| 373 | dev_err(smi->dev, "unable to register MDIO bus %s\n", | 373 | dev_err(smi->dev, "unable to register MDIO bus %s\n", |
| 374 | smi->slave_mii_bus->id); | 374 | smi->slave_mii_bus->id); |
| @@ -464,16 +464,33 @@ static int realtek_smi_probe(struct platform_device *pdev) · 89 unmodified lines | |||
| 464 | 464 | ||
| 465 | static int realtek_smi_remove(struct platform_device *pdev) | 465 | static int realtek_smi_remove(struct platform_device *pdev) |
| 466 | { | 466 | { |
| 467 | struct realtek_smi *smi = dev_get_drvdata(&pdev->dev); | 467 | struct realtek_smi *smi = platform_get_drvdata(pdev); |
| 468 | |||
| 469 | if (!smi) | ||
| 470 | return 0; | ||
| 468 | 471 | ||
| 469 | dsa_unregister_switch(smi->ds); | 472 | dsa_unregister_switch(smi->ds); |
| 470 | if (smi->slave_mii_bus) | 473 | if (smi->slave_mii_bus) |
| 471 | of_node_put(smi->slave_mii_bus->dev.of_node); | 474 | of_node_put(smi->slave_mii_bus->dev.of_node); |
| 472 | gpiod_set_value(smi->reset, 1); | 475 | gpiod_set_value(smi->reset, 1); |
| 473 | 476 | ||
| 477 | platform_set_drvdata(pdev, NULL); | ||
| 478 | |||
| 474 | return 0; | 479 | return 0; |
| 475 | } | 480 | } |
| 476 | 481 | ||
| 482 | static void realtek_smi_shutdown(struct platform_device *pdev) | ||
| 483 | { | ||
| 484 | struct realtek_smi *smi = platform_get_drvdata(pdev); | ||
| 485 | |||
| 486 | if (!smi) | ||
| 487 | return; | ||
| 488 | |||
| 489 | dsa_switch_shutdown(smi->ds); | ||
| 490 | |||
| 491 | platform_set_drvdata(pdev, NULL); | ||
| 492 | } | ||
| 493 | |||
| 477 | static const struct of_device_id realtek_smi_of_match[] = { | 494 | static const struct of_device_id realtek_smi_of_match[] = { |
| 478 | { | 495 | { |
| 479 | .compatible = "realtek,rtl8366rb", | 496 | .compatible = "realtek,rtl8366rb", |
| @@ -495,6 +512,7 @@ static struct platform_driver realtek_smi_driver = { · 15 unmodified lines | |||
| 495 | }, | 512 | }, |
| 496 | .probe = realtek_smi_probe, | 513 | .probe = realtek_smi_probe, |
| 497 | .remove = realtek_smi_remove, | 514 | .remove = realtek_smi_remove, |
| 515 | .shutdown = realtek_smi_shutdown, | ||
| 498 | }; | 516 | }; |
| 499 | module_platform_driver(realtek_smi_driver); | 517 | module_platform_driver(realtek_smi_driver); |
| 500 | 518 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: BSD-3-Clause | 1 | // SPDX-License-Identifier: BSD-3-Clause |
| 2 | /* Copyright (c) 2016-2018, NXP Semiconductors | 2 | /* Copyright 2016-2018 NXP |
| 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> | 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 4 | */ | 4 | */ |
| 5 | #include <linux/packing.h> | 5 | #include <linux/packing.h> |
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> | 2 | /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 3 | * Copyright 2020 NXP Semiconductors | 3 | * Copyright 2020 NXP |
| 4 | */ | 4 | */ |
| 5 | #include "sja1105.h" | 5 | #include "sja1105.h" |
| 6 | 6 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* Copyright 2020, NXP Semiconductors | 2 | /* Copyright 2020 NXP |
| 3 | */ | 3 | */ |
| 4 | #include "sja1105.h" | 4 | #include "sja1105.h" |
| 5 | #include "sja1105_vl.h" | 5 | #include "sja1105_vl.h" |
| @@ -3340,13 +3340,29 @@ static int sja1105_probe(struct spi_device *spi) · 3339 unmodified lines | |||
| 3340 | static int sja1105_remove(struct spi_device *spi) | 3340 | static int sja1105_remove(struct spi_device *spi) |
| 3341 | { | 3341 | { |
| 3342 | struct sja1105_private *priv = spi_get_drvdata(spi); | 3342 | struct sja1105_private *priv = spi_get_drvdata(spi); |
| 3343 | struct dsa_switch *ds = priv->ds; | ||
| 3344 | 3343 | ||
| 3345 | dsa_unregister_switch(ds); | 3344 | if (!priv) |
| 3345 | return 0; | ||
| 3346 | |||
| 3347 | dsa_unregister_switch(priv->ds); | ||
| 3348 | |||
| 3349 | spi_set_drvdata(spi, NULL); | ||
| 3346 | 3350 | ||
| 3347 | return 0; | 3351 | return 0; |
| 3348 | } | 3352 | } |
| 3349 | 3353 | ||
| 3354 | static void sja1105_shutdown(struct spi_device *spi) | ||
| 3355 | { | ||
| 3356 | struct sja1105_private *priv = spi_get_drvdata(spi); | ||
| 3357 | |||
| 3358 | if (!priv) | ||
| 3359 | return; | ||
| 3360 | |||
| 3361 | dsa_switch_shutdown(priv->ds); | ||
| 3362 | |||
| 3363 | spi_set_drvdata(spi, NULL); | ||
| 3364 | } | ||
| 3365 | |||
| 3350 | static const struct of_device_id sja1105_dt_ids[] = { | 3366 | static const struct of_device_id sja1105_dt_ids[] = { |
| 3351 | { .compatible = "nxp,sja1105e", .data = &sja1105e_info }, | 3367 | { .compatible = "nxp,sja1105e", .data = &sja1105e_info }, |
| 3352 | { .compatible = "nxp,sja1105t", .data = &sja1105t_info }, | 3368 | { .compatible = "nxp,sja1105t", .data = &sja1105t_info }, |
| @@ -3370,6 +3386,7 @@ static struct spi_driver sja1105_driver = { · 17 unmodified lines | |||
| 3370 | }, | 3386 | }, |
| 3371 | .probe = sja1105_probe, | 3387 | .probe = sja1105_probe, |
| 3372 | .remove = sja1105_remove, | 3388 | .remove = sja1105_remove, |
| 3389 | .shutdown = sja1105_shutdown, | ||
| 3373 | }; | 3390 | }; |
| 3374 | 3391 | ||
| 3375 | module_spi_driver(sja1105_driver); | 3392 | module_spi_driver(sja1105_driver); |
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* Copyright 2021, NXP Semiconductors | 2 | /* Copyright 2021 NXP |
| 3 | */ | 3 | */ |
| 4 | #include <linux/pcs/pcs-xpcs.h> | 4 | #include <linux/pcs/pcs-xpcs.h> |
| 5 | #include <linux/of_mdio.h> | 5 | #include <linux/of_mdio.h> |
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: BSD-3-Clause | 1 | // SPDX-License-Identifier: BSD-3-Clause |
| 2 | /* Copyright (c) 2016-2018, NXP Semiconductors | 2 | /* Copyright 2016-2018 NXP |
| 3 | * Copyright (c) 2018, Sensor-Technik Wiedemann GmbH | 3 | * Copyright (c) 2018, Sensor-Technik Wiedemann GmbH |
| 4 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> | 4 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 5 | */ | 5 | */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: BSD-3-Clause | 1 | // SPDX-License-Identifier: BSD-3-Clause |
| 2 | /* Copyright (c) 2016-2018, NXP Semiconductors | 2 | /* Copyright 2016-2018 NXP |
| 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> | 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 4 | */ | 4 | */ |
| 5 | #include "sja1105_static_config.h" | 5 | #include "sja1105_static_config.h" |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: BSD-3-Clause */ | 1 | /* SPDX-License-Identifier: BSD-3-Clause */ |
| 2 | /* Copyright (c) 2016-2018, NXP Semiconductors | 2 | /* Copyright 2016-2018 NXP |
| 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> | 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 4 | */ | 4 | */ |
| 5 | #ifndef _SJA1105_STATIC_CONFIG_H | 5 | #ifndef _SJA1105_STATIC_CONFIG_H |
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* Copyright 2020, NXP Semiconductors | 2 | /* Copyright 2020 NXP |
| 3 | */ | 3 | */ |
| 4 | #include <net/tc_act/tc_gate.h> | 4 | #include <net/tc_act/tc_gate.h> |
| 5 | #include <linux/dsa/8021q.h> | 5 | #include <linux/dsa/8021q.h> |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | /* Copyright 2020, NXP Semiconductors | 2 | /* Copyright 2020 NXP |
| 3 | */ | 3 | */ |
| 4 | #ifndef _SJA1105_VL_H | 4 | #ifndef _SJA1105_VL_H |
| 5 | #define _SJA1105_VL_H | 5 | #define _SJA1105_VL_H |
| @@ -1225,6 +1225,12 @@ int vsc73xx_remove(struct vsc73xx *vsc) · 1224 unmodified lines | |||
| 1225 | } | 1225 | } |
| 1226 | EXPORT_SYMBOL(vsc73xx_remove); | 1226 | EXPORT_SYMBOL(vsc73xx_remove); |
| 1227 | 1227 | ||
| 1228 | void vsc73xx_shutdown(struct vsc73xx *vsc) | ||
| 1229 | { | ||
| 1230 | dsa_switch_shutdown(vsc->ds); | ||
| 1231 | } | ||
| 1232 | EXPORT_SYMBOL(vsc73xx_shutdown); | ||
| 1233 | |||
| 1228 | MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); | 1234 | MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); |
| 1229 | MODULE_DESCRIPTION("Vitesse VSC7385/7388/7395/7398 driver"); | 1235 | MODULE_DESCRIPTION("Vitesse VSC7385/7388/7395/7398 driver"); |
| 1230 | MODULE_LICENSE("GPL v2"); | 1236 | MODULE_LICENSE("GPL v2"); |
| @@ -116,7 +116,26 @@ static int vsc73xx_platform_remove(struct platform_device *pdev) · 115 unmodified lines | |||
| 116 | { | 116 | { |
| 117 | struct vsc73xx_platform *vsc_platform = platform_get_drvdata(pdev); | 117 | struct vsc73xx_platform *vsc_platform = platform_get_drvdata(pdev); |
| 118 | 118 | ||
| 119 | return vsc73xx_remove(&vsc_platform->vsc); | 119 | if (!vsc_platform) |
| 120 | return 0; | ||
| 121 | |||
| 122 | vsc73xx_remove(&vsc_platform->vsc); | ||
| 123 | |||
| 124 | platform_set_drvdata(pdev, NULL); | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static void vsc73xx_platform_shutdown(struct platform_device *pdev) | ||
| 130 | { | ||
| 131 | struct vsc73xx_platform *vsc_platform = platform_get_drvdata(pdev); | ||
| 132 | |||
| 133 | if (!vsc_platform) | ||
| 134 | return; | ||
| 135 | |||
| 136 | vsc73xx_shutdown(&vsc_platform->vsc); | ||
| 137 | |||
| 138 | platform_set_drvdata(pdev, NULL); | ||
| 120 | } | 139 | } |
| 121 | 140 | ||
| 122 | static const struct vsc73xx_ops vsc73xx_platform_ops = { | 141 | static const struct vsc73xx_ops vsc73xx_platform_ops = { |
| @@ -144,6 +163,7 @@ MODULE_DEVICE_TABLE(of, vsc73xx_of_match); · 21 unmodified lines | |||
| 144 | static struct platform_driver vsc73xx_platform_driver = { | 163 | static struct platform_driver vsc73xx_platform_driver = { |
| 145 | .probe = vsc73xx_platform_probe, | 164 | .probe = vsc73xx_platform_probe, |
| 146 | .remove = vsc73xx_platform_remove, | 165 | .remove = vsc73xx_platform_remove, |
| 166 | .shutdown = vsc73xx_platform_shutdown, | ||
| 147 | .driver = { | 167 | .driver = { |
| 148 | .name = "vsc73xx-platform", | 168 | .name = "vsc73xx-platform", |
| 149 | .of_match_table = vsc73xx_of_match, | 169 | .of_match_table = vsc73xx_of_match, |
| @@ -163,7 +163,26 @@ static int vsc73xx_spi_remove(struct spi_device *spi) · 162 unmodified lines | |||
| 163 | { | 163 | { |
| 164 | struct vsc73xx_spi *vsc_spi = spi_get_drvdata(spi); | 164 | struct vsc73xx_spi *vsc_spi = spi_get_drvdata(spi); |
| 165 | 165 | ||
| 166 | return vsc73xx_remove(&vsc_spi->vsc); | 166 | if (!vsc_spi) |
| 167 | return 0; | ||
| 168 | |||
| 169 | vsc73xx_remove(&vsc_spi->vsc); | ||
| 170 | |||
| 171 | spi_set_drvdata(spi, NULL); | ||
| 172 | |||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | |||
| 176 | static void vsc73xx_spi_shutdown(struct spi_device *spi) | ||
| 177 | { | ||
| 178 | struct vsc73xx_spi *vsc_spi = spi_get_drvdata(spi); | ||
| 179 | |||
| 180 | if (!vsc_spi) | ||
| 181 | return; | ||
| 182 | |||
| 183 | vsc73xx_shutdown(&vsc_spi->vsc); | ||
| 184 | |||
| 185 | spi_set_drvdata(spi, NULL); | ||
| 167 | } | 186 | } |
| 168 | 187 | ||
| 169 | static const struct vsc73xx_ops vsc73xx_spi_ops = { | 188 | static const struct vsc73xx_ops vsc73xx_spi_ops = { |
| @@ -191,6 +210,7 @@ MODULE_DEVICE_TABLE(of, vsc73xx_of_match); · 21 unmodified lines | |||
| 191 | static struct spi_driver vsc73xx_spi_driver = { | 210 | static struct spi_driver vsc73xx_spi_driver = { |
| 192 | .probe = vsc73xx_spi_probe, | 211 | .probe = vsc73xx_spi_probe, |
| 193 | .remove = vsc73xx_spi_remove, | 212 | .remove = vsc73xx_spi_remove, |
| 213 | .shutdown = vsc73xx_spi_shutdown, | ||
| 194 | .driver = { | 214 | .driver = { |
| 195 | .name = "vsc73xx-spi", | 215 | .name = "vsc73xx-spi", |
| 196 | .of_match_table = vsc73xx_of_match, | 216 | .of_match_table = vsc73xx_of_match, |
| @@ -27,3 +27,4 @@ struct vsc73xx_ops { · 26 unmodified lines | |||
| 27 | int vsc73xx_is_addr_valid(u8 block, u8 subblock); | 27 | int vsc73xx_is_addr_valid(u8 block, u8 subblock); |
| 28 | int vsc73xx_probe(struct vsc73xx *vsc); | 28 | int vsc73xx_probe(struct vsc73xx *vsc); |
| 29 | int vsc73xx_remove(struct vsc73xx *vsc); | 29 | int vsc73xx_remove(struct vsc73xx *vsc); |
| 30 | void vsc73xx_shutdown(struct vsc73xx *vsc); | ||
| @@ -822,6 +822,12 @@ void xrs700x_switch_remove(struct xrs700x *priv) · 821 unmodified lines | |||
| 822 | } | 822 | } |
| 823 | EXPORT_SYMBOL(xrs700x_switch_remove); | 823 | EXPORT_SYMBOL(xrs700x_switch_remove); |
| 824 | 824 | ||
| 825 | void xrs700x_switch_shutdown(struct xrs700x *priv) | ||
| 826 | { | ||
| 827 | dsa_switch_shutdown(priv->ds); | ||
| 828 | } | ||
| 829 | EXPORT_SYMBOL(xrs700x_switch_shutdown); | ||
| 830 | |||
| 825 | MODULE_AUTHOR("George McCollister <george.mccollister@gmail.com>"); | 831 | MODULE_AUTHOR("George McCollister <george.mccollister@gmail.com>"); |
| 826 | MODULE_DESCRIPTION("Arrow SpeedChips XRS700x DSA driver"); | 832 | MODULE_DESCRIPTION("Arrow SpeedChips XRS700x DSA driver"); |
| 827 | MODULE_LICENSE("GPL v2"); | 833 | MODULE_LICENSE("GPL v2"); |
| @@ -40,3 +40,4 @@ struct xrs700x { · 39 unmodified lines | |||
| 40 | struct xrs700x *xrs700x_switch_alloc(struct device *base, void *devpriv); | 40 | struct xrs700x *xrs700x_switch_alloc(struct device *base, void *devpriv); |
| 41 | int xrs700x_switch_register(struct xrs700x *priv); | 41 | int xrs700x_switch_register(struct xrs700x *priv); |
| 42 | void xrs700x_switch_remove(struct xrs700x *priv); | 42 | void xrs700x_switch_remove(struct xrs700x *priv); |
| 43 | void xrs700x_switch_shutdown(struct xrs700x *priv); | ||
| @@ -109,11 +109,28 @@ static int xrs700x_i2c_remove(struct i2c_client *i2c) · 108 unmodified lines | |||
| 109 | { | 109 | { |
| 110 | struct xrs700x *priv = i2c_get_clientdata(i2c); | 110 | struct xrs700x *priv = i2c_get_clientdata(i2c); |
| 111 | 111 | ||
| 112 | if (!priv) | ||
| 113 | return 0; | ||
| 114 | |||
| 112 | xrs700x_switch_remove(priv); | 115 | xrs700x_switch_remove(priv); |
| 113 | 116 | ||
| 117 | i2c_set_clientdata(i2c, NULL); | ||
| 118 | |||
| 114 | return 0; | 119 | return 0; |
| 115 | } | 120 | } |
| 116 | 121 | ||
| 122 | static void xrs700x_i2c_shutdown(struct i2c_client *i2c) | ||
| 123 | { | ||
| 124 | struct xrs700x *priv = i2c_get_clientdata(i2c); | ||
| 125 | |||
| 126 | if (!priv) | ||
| 127 | return; | ||
| 128 | |||
| 129 | xrs700x_switch_shutdown(priv); | ||
| 130 | |||
| 131 | i2c_set_clientdata(i2c, NULL); | ||
| 132 | } | ||
| 133 | |||
| 117 | static const struct i2c_device_id xrs700x_i2c_id[] = { | 134 | static const struct i2c_device_id xrs700x_i2c_id[] = { |
| 118 | { "xrs700x-switch", 0 }, | 135 | { "xrs700x-switch", 0 }, |
| 119 | {}, | 136 | {}, |
| @@ -137,6 +154,7 @@ static struct i2c_driver xrs700x_i2c_driver = { · 17 unmodified lines | |||
| 137 | }, | 154 | }, |
| 138 | .probe = xrs700x_i2c_probe, | 155 | .probe = xrs700x_i2c_probe, |
| 139 | .remove = xrs700x_i2c_remove, | 156 | .remove = xrs700x_i2c_remove, |
| 157 | .shutdown = xrs700x_i2c_shutdown, | ||
| 140 | .id_table = xrs700x_i2c_id, | 158 | .id_table = xrs700x_i2c_id, |
| 141 | }; | 159 | }; |
| 142 | 160 | ||
| @@ -136,7 +136,24 @@ static void xrs700x_mdio_remove(struct mdio_device *mdiodev) · 135 unmodified lines | |||
| 136 | { | 136 | { |
| 137 | struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev); | 137 | struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev); |
| 138 | 138 | ||
| 139 | if (!priv) | ||
| 140 | return; | ||
| 141 | |||
| 139 | xrs700x_switch_remove(priv); | 142 | xrs700x_switch_remove(priv); |
| 143 | |||
| 144 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 145 | } | ||
| 146 | |||
| 147 | static void xrs700x_mdio_shutdown(struct mdio_device *mdiodev) | ||
| 148 | { | ||
| 149 | struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev); | ||
| 150 | |||
| 151 | if (!priv) | ||
| 152 | return; | ||
| 153 | |||
| 154 | xrs700x_switch_shutdown(priv); | ||
| 155 | |||
| 156 | dev_set_drvdata(&mdiodev->dev, NULL); | ||
| 140 | } | 157 | } |
| 141 | 158 | ||
| 142 | static const struct of_device_id __maybe_unused xrs700x_mdio_dt_ids[] = { | 159 | static const struct of_device_id __maybe_unused xrs700x_mdio_dt_ids[] = { |
| @@ -155,6 +172,7 @@ static struct mdio_driver xrs700x_mdio_driver = { · 12 unmodified lines | |||
| 155 | }, | 172 | }, |
| 156 | .probe = xrs700x_mdio_probe, | 173 | .probe = xrs700x_mdio_probe, |
| 157 | .remove = xrs700x_mdio_remove, | 174 | .remove = xrs700x_mdio_remove, |
| 175 | .shutdown = xrs700x_mdio_shutdown, | ||
| 158 | }; | 176 | }; |
| 159 | 177 | ||
| 160 | mdio_module_driver(xrs700x_mdio_driver); | 178 | mdio_module_driver(xrs700x_mdio_driver); |
| @@ -413,13 +413,13 @@ static int atl_resume_common(struct device *dev, bool deep) · 412 unmodified lines | |||
| 413 | if (deep) { | 413 | if (deep) { |
| 414 | /* Reinitialize Nic/Vecs objects */ | 414 | /* Reinitialize Nic/Vecs objects */ |
| 415 | aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol); | 415 | aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol); |
| 416 | } | ||
| 416 | 417 | ||
| 418 | if (netif_running(nic->ndev)) { | ||
| 417 | ret = aq_nic_init(nic); | 419 | ret = aq_nic_init(nic); |
| 418 | if (ret) | 420 | if (ret) |
| 419 | goto err_exit; | 421 | goto err_exit; |
| 420 | } | ||
| 421 | 422 | ||
| 422 | if (netif_running(nic->ndev)) { | ||
| 423 | ret = aq_nic_start(nic); | 423 | ret = aq_nic_start(nic); |
| 424 | if (ret) | 424 | if (ret) |
| 425 | goto err_exit; | 425 | goto err_exit; |
| @@ -129,6 +129,8 @@ static int bgmac_probe(struct bcma_device *core) · 128 unmodified lines | |||
| 129 | bcma_set_drvdata(core, bgmac); | 129 | bcma_set_drvdata(core, bgmac); |
| 130 | 130 | ||
| 131 | err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr); | 131 | err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr); |
| 132 | if (err == -EPROBE_DEFER) | ||
| 133 | return err; | ||
| 132 | 134 | ||
| 133 | /* If no MAC address assigned via device tree, check SPROM */ | 135 | /* If no MAC address assigned via device tree, check SPROM */ |
| 134 | if (err) { | 136 | if (err) { |
| @@ -391,7 +391,7 @@ static bool bnxt_txr_netif_try_stop_queue(struct bnxt *bp, · 390 unmodified lines | |||
| 391 | * netif_tx_queue_stopped(). | 391 | * netif_tx_queue_stopped(). |
| 392 | */ | 392 | */ |
| 393 | smp_mb(); | 393 | smp_mb(); |
| 394 | if (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh) { | 394 | if (bnxt_tx_avail(bp, txr) >= bp->tx_wake_thresh) { |
| 395 | netif_tx_wake_queue(txq); | 395 | netif_tx_wake_queue(txq); |
| 396 | return false; | 396 | return false; |
| 397 | } | 397 | } |
| @@ -764,7 +764,7 @@ next_tx_int: · 366 unmodified lines | |||
| 764 | smp_mb(); | 764 | smp_mb(); |
| 765 | 765 | ||
| 766 | if (unlikely(netif_tx_queue_stopped(txq)) && | 766 | if (unlikely(netif_tx_queue_stopped(txq)) && |
| 767 | bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh && | 767 | bnxt_tx_avail(bp, txr) >= bp->tx_wake_thresh && |
| 768 | READ_ONCE(txr->dev_state) != BNXT_DEV_STATE_CLOSING) | 768 | READ_ONCE(txr->dev_state) != BNXT_DEV_STATE_CLOSING) |
| 769 | netif_tx_wake_queue(txq); | 769 | netif_tx_wake_queue(txq); |
| 770 | } | 770 | } |
| @@ -2416,7 +2416,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, · 1645 unmodified lines | |||
| 2416 | if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) { | 2416 | if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) { |
| 2417 | tx_pkts++; | 2417 | tx_pkts++; |
| 2418 | /* return full budget so NAPI will complete. */ | 2418 | /* return full budget so NAPI will complete. */ |
| 2419 | if (unlikely(tx_pkts > bp->tx_wake_thresh)) { | 2419 | if (unlikely(tx_pkts >= bp->tx_wake_thresh)) { |
| 2420 | rx_pkts = budget; | 2420 | rx_pkts = budget; |
| 2421 | raw_cons = NEXT_RAW_CMP(raw_cons); | 2421 | raw_cons = NEXT_RAW_CMP(raw_cons); |
| 2422 | if (budget) | 2422 | if (budget) |
| @@ -3640,7 +3640,7 @@ static int bnxt_init_tx_rings(struct bnxt *bp) · 1217 unmodified lines | |||
| 3640 | u16 i; | 3640 | u16 i; |
| 3641 | 3641 | ||
| 3642 | bp->tx_wake_thresh = max_t(int, bp->tx_ring_size / 2, | 3642 | bp->tx_wake_thresh = max_t(int, bp->tx_ring_size / 2, |
| 3643 | MAX_SKB_FRAGS + 1); | 3643 | BNXT_MIN_TX_DESC_CNT); |
| 3644 | 3644 | ||
| 3645 | for (i = 0; i < bp->tx_nr_rings; i++) { | 3645 | for (i = 0; i < bp->tx_nr_rings; i++) { |
| 3646 | struct bnxt_tx_ring_info *txr = &bp->tx_ring[i]; | 3646 | struct bnxt_tx_ring_info *txr = &bp->tx_ring[i]; |
| @@ -629,6 +629,11 @@ struct nqe_cn { · 628 unmodified lines | |||
| 629 | #define BNXT_MAX_RX_JUM_DESC_CNT (RX_DESC_CNT * MAX_RX_AGG_PAGES - 1) | 629 | #define BNXT_MAX_RX_JUM_DESC_CNT (RX_DESC_CNT * MAX_RX_AGG_PAGES - 1) |
| 630 | #define BNXT_MAX_TX_DESC_CNT (TX_DESC_CNT * MAX_TX_PAGES - 1) | 630 | #define BNXT_MAX_TX_DESC_CNT (TX_DESC_CNT * MAX_TX_PAGES - 1) |
| 631 | 631 | ||
| 632 | /* Minimum TX BDs for a TX packet with MAX_SKB_FRAGS + 1. We need one extra | ||
| 633 | * BD because the first TX BD is always a long BD. | ||
| 634 | */ | ||
| 635 | #define BNXT_MIN_TX_DESC_CNT (MAX_SKB_FRAGS + 2) | ||
| 636 | |||
| 632 | #define RX_RING(x) (((x) & ~(RX_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4)) | 637 | #define RX_RING(x) (((x) & ~(RX_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4)) |
| 633 | #define RX_IDX(x) ((x) & (RX_DESC_CNT - 1)) | 638 | #define RX_IDX(x) ((x) & (RX_DESC_CNT - 1)) |
| 634 | 639 | ||
| @@ -798,7 +798,7 @@ static int bnxt_set_ringparam(struct net_device *dev, · 797 unmodified lines | |||
| 798 | 798 | ||
| 799 | if ((ering->rx_pending > BNXT_MAX_RX_DESC_CNT) || | 799 | if ((ering->rx_pending > BNXT_MAX_RX_DESC_CNT) || |
| 800 | (ering->tx_pending > BNXT_MAX_TX_DESC_CNT) || | 800 | (ering->tx_pending > BNXT_MAX_TX_DESC_CNT) || |
| 801 | (ering->tx_pending <= MAX_SKB_FRAGS)) | 801 | (ering->tx_pending < BNXT_MIN_TX_DESC_CNT)) |
| 802 | return -EINVAL; | 802 | return -EINVAL; |
| 803 | 803 | ||
| 804 | if (netif_running(dev)) | 804 | if (netif_running(dev)) |
| @@ -419,7 +419,7 @@ static void enetc_rx_dim_work(struct work_struct *w) · 418 unmodified lines | |||
| 419 | 419 | ||
| 420 | static void enetc_rx_net_dim(struct enetc_int_vector *v) | 420 | static void enetc_rx_net_dim(struct enetc_int_vector *v) |
| 421 | { | 421 | { |
| 422 | struct dim_sample dim_sample; | 422 | struct dim_sample dim_sample = {}; |
| 423 | 423 | ||
| 424 | v->comp_cnt++; | 424 | v->comp_cnt++; |
| 425 | 425 | ||
| @@ -1879,7 +1879,6 @@ static void enetc_clear_bdrs(struct enetc_ndev_priv *priv) · 1453 unmodified lines | |||
| 1879 | static int enetc_setup_irqs(struct enetc_ndev_priv *priv) | 1879 | static int enetc_setup_irqs(struct enetc_ndev_priv *priv) |
| 1880 | { | 1880 | { |
| 1881 | struct pci_dev *pdev = priv->si->pdev; | 1881 | struct pci_dev *pdev = priv->si->pdev; |
| 1882 | cpumask_t cpu_mask; | ||
| 1883 | int i, j, err; | 1882 | int i, j, err; |
| 1884 | 1883 | ||
| 1885 | for (i = 0; i < priv->bdr_int_num; i++) { | 1884 | for (i = 0; i < priv->bdr_int_num; i++) { |
| @@ -1908,9 +1907,7 @@ static int enetc_setup_irqs(struct enetc_ndev_priv *priv) · 22 unmodified lines | |||
| 1908 | 1907 | ||
| 1909 | enetc_wr(hw, ENETC_SIMSITRV(idx), entry); | 1908 | enetc_wr(hw, ENETC_SIMSITRV(idx), entry); |
| 1910 | } | 1909 | } |
| 1911 | cpumask_clear(&cpu_mask); | 1910 | irq_set_affinity_hint(irq, get_cpu_mask(i % num_online_cpus())); |
| 1912 | cpumask_set_cpu(i % num_online_cpus(), &cpu_mask); | ||
| 1913 | irq_set_affinity_hint(irq, &cpu_mask); | ||
| 1914 | } | 1911 | } |
| 1915 | 1912 | ||
| 1916 | return 0; | 1913 | return 0; |
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) | 1 | // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
| 2 | /* Copyright 2021 NXP Semiconductors | 2 | /* Copyright 2021 NXP |
| 3 | * | 3 | * |
| 4 | * The Integrated Endpoint Register Block (IERB) is configured by pre-boot | 4 | * The Integrated Endpoint Register Block (IERB) is configured by pre-boot |
| 5 | * software and is supposed to be to ENETC what a NVRAM is to a 'real' PCIe | 5 | * software and is supposed to be to ENETC what a NVRAM is to a 'real' PCIe |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ | 1 | /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ |
| 2 | /* Copyright 2021 NXP Semiconductors */ | 2 | /* Copyright 2021 NXP */ |
| 3 | 3 | ||
| 4 | #include <linux/pci.h> | 4 | #include <linux/pci.h> |
| 5 | #include <linux/platform_device.h> | 5 | #include <linux/platform_device.h> |
| @@ -4176,5 +4176,4 @@ static struct platform_driver fec_driver = { · 4175 unmodified lines | |||
| 4176 | 4176 | ||
| 4177 | module_platform_driver(fec_driver); | 4177 | module_platform_driver(fec_driver); |
| 4178 | 4178 | ||
| 4179 | MODULE_ALIAS("platform:"DRIVER_NAME); | ||
| 4180 | MODULE_LICENSE("GPL"); | 4179 | MODULE_LICENSE("GPL"); |
| @@ -2445,12 +2445,12 @@ static void hclge_handle_over_8bd_err(struct hclge_dev *hdev, · 2444 unmodified lines | |||
| 2445 | return; | 2445 | return; |
| 2446 | } | 2446 | } |
| 2447 | 2447 | ||
| 2448 | dev_err(dev, "PPU_PF_ABNORMAL_INT_ST over_8bd_no_fe found, vf_id(%u), queue_id(%u)\n", | 2448 | dev_err(dev, "PPU_PF_ABNORMAL_INT_ST over_8bd_no_fe found, vport(%u), queue_id(%u)\n", |
| 2449 | vf_id, q_id); | 2449 | vf_id, q_id); |
| 2450 | 2450 | ||
| 2451 | if (vf_id) { | 2451 | if (vf_id) { |
| 2452 | if (vf_id >= hdev->num_alloc_vport) { | 2452 | if (vf_id >= hdev->num_alloc_vport) { |
| 2453 | dev_err(dev, "invalid vf id(%u)\n", vf_id); | 2453 | dev_err(dev, "invalid vport(%u)\n", vf_id); |
| 2454 | return; | 2454 | return; |
| 2455 | } | 2455 | } |
| 2456 | 2456 | ||
| @@ -2463,8 +2463,8 @@ static void hclge_handle_over_8bd_err(struct hclge_dev *hdev, · 6 unmodified lines | |||
| 2463 | 2463 | ||
| 2464 | ret = hclge_inform_reset_assert_to_vf(&hdev->vport[vf_id]); | 2464 | ret = hclge_inform_reset_assert_to_vf(&hdev->vport[vf_id]); |
| 2465 | if (ret) | 2465 | if (ret) |
| 2466 | dev_err(dev, "inform reset to vf(%u) failed %d!\n", | 2466 | dev_err(dev, "inform reset to vport(%u) failed %d!\n", |
| 2467 | hdev->vport->vport_id, ret); | 2467 | vf_id, ret); |
| 2468 | } else { | 2468 | } else { |
| 2469 | set_bit(HNAE3_FUNC_RESET, reset_requests); | 2469 | set_bit(HNAE3_FUNC_RESET, reset_requests); |
| 2470 | } | 2470 | } |
| @@ -3667,7 +3667,8 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset) · 3666 unmodified lines | |||
| 3667 | if (ret) { | 3667 | if (ret) { |
| 3668 | dev_err(&hdev->pdev->dev, | 3668 | dev_err(&hdev->pdev->dev, |
| 3669 | "set vf(%u) rst failed %d!\n", | 3669 | "set vf(%u) rst failed %d!\n", |
| 3670 | vport->vport_id, ret); | 3670 | vport->vport_id - HCLGE_VF_VPORT_START_NUM, |
| 3671 | ret); | ||
| 3671 | return ret; | 3672 | return ret; |
| 3672 | } | 3673 | } |
| 3673 | 3674 | ||
| @@ -3682,7 +3683,8 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset) · 8 unmodified lines | |||
| 3682 | if (ret) | 3683 | if (ret) |
| 3683 | dev_warn(&hdev->pdev->dev, | 3684 | dev_warn(&hdev->pdev->dev, |
| 3684 | "inform reset to vf(%u) failed %d!\n", | 3685 | "inform reset to vf(%u) failed %d!\n", |
| 3685 | vport->vport_id, ret); | 3686 | vport->vport_id - HCLGE_VF_VPORT_START_NUM, |
| 3687 | ret); | ||
| 3686 | } | 3688 | } |
| 3687 | 3689 | ||
| 3688 | return 0; | 3690 | return 0; |
| @@ -4747,6 +4749,24 @@ static int hclge_get_rss(struct hnae3_handle *handle, u32 *indir, · 1058 unmodified lines | |||
| 4747 | return 0; | 4749 | return 0; |
| 4748 | } | 4750 | } |
| 4749 | 4751 | ||
| 4752 | static int hclge_parse_rss_hfunc(struct hclge_vport *vport, const u8 hfunc, | ||
| 4753 | u8 *hash_algo) | ||
| 4754 | { | ||
| 4755 | switch (hfunc) { | ||
| 4756 | case ETH_RSS_HASH_TOP: | ||
| 4757 | *hash_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ; | ||
| 4758 | return 0; | ||
| 4759 | case ETH_RSS_HASH_XOR: | ||
| 4760 | *hash_algo = HCLGE_RSS_HASH_ALGO_SIMPLE; | ||
| 4761 | return 0; | ||
| 4762 | case ETH_RSS_HASH_NO_CHANGE: | ||
| 4763 | *hash_algo = vport->rss_algo; | ||
| 4764 | return 0; | ||
| 4765 | default: | ||
| 4766 | return -EINVAL; | ||
| 4767 | } | ||
| 4768 | } | ||
| 4769 | |||
| 4750 | static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir, | 4770 | static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir, |
| 4751 | const u8 *key, const u8 hfunc) | 4771 | const u8 *key, const u8 hfunc) |
| 4752 | { | 4772 | { |
| @@ -4756,30 +4776,27 @@ static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir, · 3 unmodified lines | |||
| 4756 | u8 hash_algo; | 4776 | u8 hash_algo; |
| 4757 | int ret, i; | 4777 | int ret, i; |
| 4758 | 4778 | ||
| 4779 | ret = hclge_parse_rss_hfunc(vport, hfunc, &hash_algo); | ||
| 4780 | if (ret) { | ||
| 4781 | dev_err(&hdev->pdev->dev, "invalid hfunc type %u\n", hfunc); | ||
| 4782 | return ret; | ||
| 4783 | } | ||
| 4784 | |||
| 4759 | /* Set the RSS Hash Key if specififed by the user */ | 4785 | /* Set the RSS Hash Key if specififed by the user */ |
| 4760 | if (key) { | 4786 | if (key) { |
| 4761 | switch (hfunc) { | ||
| 4762 | case ETH_RSS_HASH_TOP: | ||
| 4763 | hash_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ; | ||
| 4764 | break; | ||
| 4765 | case ETH_RSS_HASH_XOR: | ||
| 4766 | hash_algo = HCLGE_RSS_HASH_ALGO_SIMPLE; | ||
| 4767 | break; | ||
| 4768 | case ETH_RSS_HASH_NO_CHANGE: | ||
| 4769 | hash_algo = vport->rss_algo; | ||
| 4770 | break; | ||
| 4771 | default: | ||
| 4772 | return -EINVAL; | ||
| 4773 | } | ||
| 4774 | |||
| 4775 | ret = hclge_set_rss_algo_key(hdev, hash_algo, key); | 4787 | ret = hclge_set_rss_algo_key(hdev, hash_algo, key); |
| 4776 | if (ret) | 4788 | if (ret) |
| 4777 | return ret; | 4789 | return ret; |
| 4778 | 4790 | ||
| 4779 | /* Update the shadow RSS key with user specified qids */ | 4791 | /* Update the shadow RSS key with user specified qids */ |
| 4780 | memcpy(vport->rss_hash_key, key, HCLGE_RSS_KEY_SIZE); | 4792 | memcpy(vport->rss_hash_key, key, HCLGE_RSS_KEY_SIZE); |
| 4781 | vport->rss_algo = hash_algo; | 4793 | } else { |
| 4794 | ret = hclge_set_rss_algo_key(hdev, hash_algo, | ||
| 4795 | vport->rss_hash_key); | ||
| 4796 | if (ret) | ||
| 4797 | return ret; | ||
| 4782 | } | 4798 | } |
| 4799 | vport->rss_algo = hash_algo; | ||
| 4783 | 4800 | ||
| 4784 | /* Update the shadow RSS table with user specified qids */ | 4801 | /* Update the shadow RSS table with user specified qids */ |
| 4785 | for (i = 0; i < ae_dev->dev_specs.rss_ind_tbl_size; i++) | 4802 | for (i = 0; i < ae_dev->dev_specs.rss_ind_tbl_size; i++) |
| @@ -6633,10 +6650,13 @@ static int hclge_fd_parse_ring_cookie(struct hclge_dev *hdev, u64 ring_cookie, · 1847 unmodified lines | |||
| 6633 | u8 vf = ethtool_get_flow_spec_ring_vf(ring_cookie); | 6650 | u8 vf = ethtool_get_flow_spec_ring_vf(ring_cookie); |
| 6634 | u16 tqps; | 6651 | u16 tqps; |
| 6635 | 6652 | ||
| 6653 | /* To keep consistent with user's configuration, minus 1 when | ||
| 6654 | * printing 'vf', because vf id from ethtool is added 1 for vf. | ||
| 6655 | */ | ||
| 6636 | if (vf > hdev->num_req_vfs) { | 6656 | if (vf > hdev->num_req_vfs) { |
| 6637 | dev_err(&hdev->pdev->dev, | 6657 | dev_err(&hdev->pdev->dev, |
| 6638 | "Error: vf id (%u) > max vf num (%u)\n", | 6658 | "Error: vf id (%u) should be less than %u\n", |
| 6639 | vf, hdev->num_req_vfs); | 6659 | vf - 1, hdev->num_req_vfs); |
| 6640 | return -EINVAL; | 6660 | return -EINVAL; |
| 6641 | } | 6661 | } |
| 6642 | 6662 | ||
| @@ -9825,6 +9845,9 @@ static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto, · 3182 unmodified lines | |||
| 9825 | if (is_kill && !vlan_id) | 9845 | if (is_kill && !vlan_id) |
| 9826 | return 0; | 9846 | return 0; |
| 9827 | 9847 | ||
| 9848 | if (vlan_id >= VLAN_N_VID) | ||
| 9849 | return -EINVAL; | ||
| 9850 | |||
| 9828 | ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id); | 9851 | ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id); |
| 9829 | if (ret) { | 9852 | if (ret) { |
| 9830 | dev_err(&hdev->pdev->dev, | 9853 | dev_err(&hdev->pdev->dev, |
| @@ -10731,7 +10754,8 @@ static int hclge_reset_tqp_cmd_send(struct hclge_dev *hdev, u16 queue_id, · 900 unmodified lines | |||
| 10731 | return 0; | 10754 | return 0; |
| 10732 | } | 10755 | } |
| 10733 | 10756 | ||
| 10734 | static int hclge_get_reset_status(struct hclge_dev *hdev, u16 queue_id) | 10757 | static int hclge_get_reset_status(struct hclge_dev *hdev, u16 queue_id, |
| 10758 | u8 *reset_status) | ||
| 10735 | { | 10759 | { |
| 10736 | struct hclge_reset_tqp_queue_cmd *req; | 10760 | struct hclge_reset_tqp_queue_cmd *req; |
| 10737 | struct hclge_desc desc; | 10761 | struct hclge_desc desc; |
| @@ -10749,7 +10773,9 @@ static int hclge_get_reset_status(struct hclge_dev *hdev, u16 queue_id) · 11 unmodified lines | |||
| 10749 | return ret; | 10773 | return ret; |
| 10750 | } | 10774 | } |
| 10751 | 10775 | ||
| 10752 | return hnae3_get_bit(req->ready_to_reset, HCLGE_TQP_RESET_B); | 10776 | *reset_status = hnae3_get_bit(req->ready_to_reset, HCLGE_TQP_RESET_B); |
| 10777 | |||
| 10778 | return 0; | ||
| 10753 | } | 10779 | } |
| 10754 | 10780 | ||
| 10755 | u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id) | 10781 | u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id) |
| @@ -10768,7 +10794,7 @@ static int hclge_reset_tqp_cmd(struct hnae3_handle *handle) · 12 unmodified lines | |||
| 10768 | struct hclge_vport *vport = hclge_get_vport(handle); | 10794 | struct hclge_vport *vport = hclge_get_vport(handle); |
| 10769 | struct hclge_dev *hdev = vport->back; | 10795 | struct hclge_dev *hdev = vport->back; |
| 10770 | u16 reset_try_times = 0; | 10796 | u16 reset_try_times = 0; |
| 10771 | int reset_status; | 10797 | u8 reset_status; |
| 10772 | u16 queue_gid; | 10798 | u16 queue_gid; |
| 10773 | int ret; | 10799 | int ret; |
| 10774 | u16 i; | 10800 | u16 i; |
| @@ -10784,7 +10810,11 @@ static int hclge_reset_tqp_cmd(struct hnae3_handle *handle) · 9 unmodified lines | |||
| 10784 | } | 10810 | } |
| 10785 | 10811 | ||
| 10786 | while (reset_try_times++ < HCLGE_TQP_RESET_TRY_TIMES) { | 10812 | while (reset_try_times++ < HCLGE_TQP_RESET_TRY_TIMES) { |
| 10787 | reset_status = hclge_get_reset_status(hdev, queue_gid); | 10813 | ret = hclge_get_reset_status(hdev, queue_gid, |
| 10814 | &reset_status); | ||
| 10815 | if (ret) | ||
| 10816 | return ret; | ||
| 10817 | |||
| 10788 | if (reset_status) | 10818 | if (reset_status) |
| 10789 | break; | 10819 | break; |
| 10790 | 10820 | ||
| @@ -11477,11 +11507,11 @@ static void hclge_clear_resetting_state(struct hclge_dev *hdev) · 686 unmodified lines | |||
| 11477 | struct hclge_vport *vport = &hdev->vport[i]; | 11507 | struct hclge_vport *vport = &hdev->vport[i]; |
| 11478 | int ret; | 11508 | int ret; |
| 11479 | 11509 | ||
| 11480 | /* Send cmd to clear VF's FUNC_RST_ING */ | 11510 | /* Send cmd to clear vport's FUNC_RST_ING */ |
| 11481 | ret = hclge_set_vf_rst(hdev, vport->vport_id, false); | 11511 | ret = hclge_set_vf_rst(hdev, vport->vport_id, false); |
| 11482 | if (ret) | 11512 | if (ret) |
| 11483 | dev_warn(&hdev->pdev->dev, | 11513 | dev_warn(&hdev->pdev->dev, |
| 11484 | "clear vf(%u) rst failed %d!\n", | 11514 | "clear vport(%u) rst failed %d!\n", |
| 11485 | vport->vport_id, ret); | 11515 | vport->vport_id, ret); |
| 11486 | } | 11516 | } |
| 11487 | } | 11517 | } |
| @@ -566,7 +566,7 @@ static int hclge_reset_vf(struct hclge_vport *vport) · 565 unmodified lines | |||
| 566 | struct hclge_dev *hdev = vport->back; | 566 | struct hclge_dev *hdev = vport->back; |
| 567 | 567 | ||
| 568 | dev_warn(&hdev->pdev->dev, "PF received VF reset request from VF %u!", | 568 | dev_warn(&hdev->pdev->dev, "PF received VF reset request from VF %u!", |
| 569 | vport->vport_id); | 569 | vport->vport_id - HCLGE_VF_VPORT_START_NUM); |
| 570 | 570 | ||
| 571 | return hclge_func_reset_cmd(hdev, vport->vport_id); | 571 | return hclge_func_reset_cmd(hdev, vport->vport_id); |
| 572 | } | 572 | } |
| @@ -590,9 +590,17 @@ static void hclge_get_queue_id_in_pf(struct hclge_vport *vport, · 17 unmodified lines | |||
| 590 | struct hclge_mbx_vf_to_pf_cmd *mbx_req, | 590 | struct hclge_mbx_vf_to_pf_cmd *mbx_req, |
| 591 | struct hclge_respond_to_vf_msg *resp_msg) | 591 | struct hclge_respond_to_vf_msg *resp_msg) |
| 592 | { | 592 | { |
| 593 | struct hnae3_handle *handle = &vport->nic; | ||
| 594 | struct hclge_dev *hdev = vport->back; | ||
| 593 | u16 queue_id, qid_in_pf; | 595 | u16 queue_id, qid_in_pf; |
| 594 | 596 | ||
| 595 | memcpy(&queue_id, mbx_req->msg.data, sizeof(queue_id)); | 597 | memcpy(&queue_id, mbx_req->msg.data, sizeof(queue_id)); |
| 598 | if (queue_id >= handle->kinfo.num_tqps) { | ||
| 599 | dev_err(&hdev->pdev->dev, "Invalid queue id(%u) from VF %u\n", | ||
| 600 | queue_id, mbx_req->mbx_src_vfid); | ||
| 601 | return; | ||
| 602 | } | ||
| 603 | |||
| 596 | qid_in_pf = hclge_covert_handle_qid_global(&vport->nic, queue_id); | 604 | qid_in_pf = hclge_covert_handle_qid_global(&vport->nic, queue_id); |
| 597 | memcpy(resp_msg->data, &qid_in_pf, sizeof(qid_in_pf)); | 605 | memcpy(resp_msg->data, &qid_in_pf, sizeof(qid_in_pf)); |
| 598 | resp_msg->len = sizeof(qid_in_pf); | 606 | resp_msg->len = sizeof(qid_in_pf); |
| @@ -581,7 +581,7 @@ int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate) · 580 unmodified lines | |||
| 581 | ret = hclge_cmd_send(&hdev->hw, &desc, 1); | 581 | ret = hclge_cmd_send(&hdev->hw, &desc, 1); |
| 582 | if (ret) { | 582 | if (ret) { |
| 583 | dev_err(&hdev->pdev->dev, | 583 | dev_err(&hdev->pdev->dev, |
| 584 | "vf%u, qs%u failed to set tx_rate:%d, ret=%d\n", | 584 | "vport%u, qs%u failed to set tx_rate:%d, ret=%d\n", |
| 585 | vport->vport_id, shap_cfg_cmd->qs_id, | 585 | vport->vport_id, shap_cfg_cmd->qs_id, |
| 586 | max_tx_rate, ret); | 586 | max_tx_rate, ret); |
| 587 | return ret; | 587 | return ret; |
| @@ -816,40 +816,56 @@ static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key, · 815 unmodified lines | |||
| 816 | return 0; | 816 | return 0; |
| 817 | } | 817 | } |
| 818 | 818 | ||
| 819 | static int hclgevf_parse_rss_hfunc(struct hclgevf_dev *hdev, const u8 hfunc, | ||
| 820 | u8 *hash_algo) | ||
| 821 | { | ||
| 822 | switch (hfunc) { | ||
| 823 | case ETH_RSS_HASH_TOP: | ||
| 824 | *hash_algo = HCLGEVF_RSS_HASH_ALGO_TOEPLITZ; | ||
| 825 | return 0; | ||
| 826 | case ETH_RSS_HASH_XOR: | ||
| 827 | *hash_algo = HCLGEVF_RSS_HASH_ALGO_SIMPLE; | ||
| 828 | return 0; | ||
| 829 | case ETH_RSS_HASH_NO_CHANGE: | ||
| 830 | *hash_algo = hdev->rss_cfg.hash_algo; | ||
| 831 | return 0; | ||
| 832 | default: | ||
| 833 | return -EINVAL; | ||
| 834 | } | ||
| 835 | } | ||
| 836 | |||
| 819 | static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir, | 837 | static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir, |
| 820 | const u8 *key, const u8 hfunc) | 838 | const u8 *key, const u8 hfunc) |
| 821 | { | 839 | { |
| 822 | struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); | 840 | struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); |
| 823 | struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; | 841 | struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; |
| 842 | u8 hash_algo; | ||
| 824 | int ret, i; | 843 | int ret, i; |
| 825 | 844 | ||
| 826 | if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { | 845 | if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { |
| 846 | ret = hclgevf_parse_rss_hfunc(hdev, hfunc, &hash_algo); | ||
| 847 | if (ret) | ||
| 848 | return ret; | ||
| 849 | |||
| 827 | /* Set the RSS Hash Key if specififed by the user */ | 850 | /* Set the RSS Hash Key if specififed by the user */ |
| 828 | if (key) { | 851 | if (key) { |
| 829 | switch (hfunc) { | 852 | ret = hclgevf_set_rss_algo_key(hdev, hash_algo, key); |
| 830 | case ETH_RSS_HASH_TOP: | 853 | if (ret) { |
| 831 | rss_cfg->hash_algo = | 854 | dev_err(&hdev->pdev->dev, |
| 832 | HCLGEVF_RSS_HASH_ALGO_TOEPLITZ; | 855 | "invalid hfunc type %u\n", hfunc); |
| 833 | break; | ||
| 834 | case ETH_RSS_HASH_XOR: | ||
| 835 | rss_cfg->hash_algo = | ||
| 836 | HCLGEVF_RSS_HASH_ALGO_SIMPLE; | ||
| 837 | break; | ||
| 838 | case ETH_RSS_HASH_NO_CHANGE: | ||
| 839 | break; | ||
| 840 | default: | ||
| 841 | return -EINVAL; | ||
| 842 | } | ||
| 843 | |||
| 844 | ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo, | ||
| 845 | key); | ||
| 846 | if (ret) | ||
| 847 | return ret; | 856 | return ret; |
| 857 | } | ||
| 848 | 858 | ||
| 849 | /* Update the shadow RSS key with user specified qids */ | 859 | /* Update the shadow RSS key with user specified qids */ |
| 850 | memcpy(rss_cfg->rss_hash_key, key, | 860 | memcpy(rss_cfg->rss_hash_key, key, |
| 851 | HCLGEVF_RSS_KEY_SIZE); | 861 | HCLGEVF_RSS_KEY_SIZE); |
| 862 | } else { | ||
| 863 | ret = hclgevf_set_rss_algo_key(hdev, hash_algo, | ||
| 864 | rss_cfg->rss_hash_key); | ||
| 865 | if (ret) | ||
| 866 | return ret; | ||
| 852 | } | 867 | } |
| 868 | rss_cfg->hash_algo = hash_algo; | ||
| 853 | } | 869 | } |
| 854 | 870 | ||
| 855 | /* update the shadow RSS table with user specified qids */ | 871 | /* update the shadow RSS table with user specified qids */ |
| @@ -335,6 +335,7 @@ config IGC · 334 unmodified lines | |||
| 335 | tristate "Intel(R) Ethernet Controller I225-LM/I225-V support" | 335 | tristate "Intel(R) Ethernet Controller I225-LM/I225-V support" |
| 336 | default n | 336 | default n |
| 337 | depends on PCI | 337 | depends on PCI |
| 338 | depends on PTP_1588_CLOCK_OPTIONAL | ||
| 338 | help | 339 | help |
| 339 | This driver supports Intel(R) Ethernet Controller I225-LM/I225-V | 340 | This driver supports Intel(R) Ethernet Controller I225-LM/I225-V |
| 340 | family of adapters. | 341 | family of adapters. |
| @@ -186,6 +186,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f) · 185 unmodified lines | |||
| 186 | int hash; | 186 | int hash; |
| 187 | int i; | 187 | int i; |
| 188 | 188 | ||
| 189 | if (rhashtable_lookup(ð->flow_table, &f->cookie, mtk_flow_ht_params)) | ||
| 190 | return -EEXIST; | ||
| 191 | |||
| 189 | if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) { | 192 | if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) { |
| 190 | struct flow_match_meta match; | 193 | struct flow_match_meta match; |
| 191 | 194 | ||
| @@ -372,6 +372,9 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb, · 371 unmodified lines | |||
| 372 | int nhoff = skb_network_offset(skb); | 372 | int nhoff = skb_network_offset(skb); |
| 373 | int ret = 0; | 373 | int ret = 0; |
| 374 | 374 | ||
| 375 | if (skb->encapsulation) | ||
| 376 | return -EPROTONOSUPPORT; | ||
| 377 | |||
| 375 | if (skb->protocol != htons(ETH_P_IP)) | 378 | if (skb->protocol != htons(ETH_P_IP)) |
| 376 | return -EPROTONOSUPPORT; | 379 | return -EPROTONOSUPPORT; |
| 377 | 380 | ||
| @@ -1269,7 +1272,6 @@ static void mlx4_en_do_set_rx_mode(struct work_struct *work) · 891 unmodified lines | |||
| 1269 | if (!netif_carrier_ok(dev)) { | 1272 | if (!netif_carrier_ok(dev)) { |
| 1270 | if (!mlx4_en_QUERY_PORT(mdev, priv->port)) { | 1273 | if (!mlx4_en_QUERY_PORT(mdev, priv->port)) { |
| 1271 | if (priv->port_state.link_state) { | 1274 | if (priv->port_state.link_state) { |
| 1272 | priv->last_link_state = MLX4_DEV_EVENT_PORT_UP; | ||
| 1273 | netif_carrier_on(dev); | 1275 | netif_carrier_on(dev); |
| 1274 | en_dbg(LINK, priv, "Link Up\n"); | 1276 | en_dbg(LINK, priv, "Link Up\n"); |
| 1275 | } | 1277 | } |
| @@ -1557,26 +1559,36 @@ static void mlx4_en_service_task(struct work_struct *work) · 281 unmodified lines | |||
| 1557 | mutex_unlock(&mdev->state_lock); | 1559 | mutex_unlock(&mdev->state_lock); |
| 1558 | } | 1560 | } |
| 1559 | 1561 | ||
| 1560 | static void mlx4_en_linkstate(struct work_struct *work) | 1562 | static void mlx4_en_linkstate(struct mlx4_en_priv *priv) |
| 1563 | { | ||
| 1564 | struct mlx4_en_port_state *port_state = &priv->port_state; | ||
| 1565 | struct mlx4_en_dev *mdev = priv->mdev; | ||
| 1566 | struct net_device *dev = priv->dev; | ||
| 1567 | bool up; | ||
| 1568 | |||
| 1569 | if (mlx4_en_QUERY_PORT(mdev, priv->port)) | ||
| 1570 | port_state->link_state = MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN; | ||
| 1571 | |||
| 1572 | up = port_state->link_state == MLX4_PORT_STATE_DEV_EVENT_PORT_UP; | ||
| 1573 | if (up == netif_carrier_ok(dev)) | ||
| 1574 | netif_carrier_event(dev); | ||
| 1575 | if (!up) { | ||
| 1576 | en_info(priv, "Link Down\n"); | ||
| 1577 | netif_carrier_off(dev); | ||
| 1578 | } else { | ||
| 1579 | en_info(priv, "Link Up\n"); | ||
| 1580 | netif_carrier_on(dev); | ||
| 1581 | } | ||
| 1582 | } | ||
| 1583 | |||
| 1584 | static void mlx4_en_linkstate_work(struct work_struct *work) | ||
| 1561 | { | 1585 | { |
| 1562 | struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, | 1586 | struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, |
| 1563 | linkstate_task); | 1587 | linkstate_task); |
| 1564 | struct mlx4_en_dev *mdev = priv->mdev; | 1588 | struct mlx4_en_dev *mdev = priv->mdev; |
| 1565 | int linkstate = priv->link_state; | ||
| 1566 | 1589 | ||
| 1567 | mutex_lock(&mdev->state_lock); | 1590 | mutex_lock(&mdev->state_lock); |
| 1568 | /* If observable port state changed set carrier state and | 1591 | mlx4_en_linkstate(priv); |
| 1569 | * report to system log */ | ||
| 1570 | if (priv->last_link_state != linkstate) { | ||
| 1571 | if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) { | ||
| 1572 | en_info(priv, "Link Down\n"); | ||
| 1573 | netif_carrier_off(priv->dev); | ||
| 1574 | } else { | ||
| 1575 | en_info(priv, "Link Up\n"); | ||
| 1576 | netif_carrier_on(priv->dev); | ||
| 1577 | } | ||
| 1578 | } | ||
| 1579 | priv->last_link_state = linkstate; | ||
| 1580 | mutex_unlock(&mdev->state_lock); | 1592 | mutex_unlock(&mdev->state_lock); |
| 1581 | } | 1593 | } |
| 1582 | 1594 | ||
| @@ -2079,9 +2091,11 @@ static int mlx4_en_open(struct net_device *dev) · 496 unmodified lines | |||
| 2079 | mlx4_en_clear_stats(dev); | 2091 | mlx4_en_clear_stats(dev); |
| 2080 | 2092 | ||
| 2081 | err = mlx4_en_start_port(dev); | 2093 | err = mlx4_en_start_port(dev); |
| 2082 | if (err) | 2094 | if (err) { |
| 2083 | en_err(priv, "Failed starting port:%d\n", priv->port); | 2095 | en_err(priv, "Failed starting port:%d\n", priv->port); |
| 2084 | 2096 | goto out; | |
| 2097 | } | ||
| 2098 | mlx4_en_linkstate(priv); | ||
| 2085 | out: | 2099 | out: |
| 2086 | mutex_unlock(&mdev->state_lock); | 2100 | mutex_unlock(&mdev->state_lock); |
| 2087 | return err; | 2101 | return err; |
| @@ -3168,7 +3182,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, · 1080 unmodified lines | |||
| 3168 | spin_lock_init(&priv->stats_lock); | 3182 | spin_lock_init(&priv->stats_lock); |
| 3169 | INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode); | 3183 | INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode); |
| 3170 | INIT_WORK(&priv->restart_task, mlx4_en_restart); | 3184 | INIT_WORK(&priv->restart_task, mlx4_en_restart); |
| 3171 | INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); | 3185 | INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate_work); |
| 3172 | INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); | 3186 | INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); |
| 3173 | INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task); | 3187 | INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task); |
| 3174 | #ifdef CONFIG_RFS_ACCEL | 3188 | #ifdef CONFIG_RFS_ACCEL |
| @@ -552,7 +552,6 @@ struct mlx4_en_priv { · 551 unmodified lines | |||
| 552 | 552 | ||
| 553 | struct mlx4_hwq_resources res; | 553 | struct mlx4_hwq_resources res; |
| 554 | int link_state; | 554 | int link_state; |
| 555 | int last_link_state; | ||
| 556 | bool port_up; | 555 | bool port_up; |
| 557 | int port; | 556 | int port; |
| 558 | int registered; | 557 | int registered; |
| @@ -563,16 +563,6 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port, · 562 unmodified lines | |||
| 563 | ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA | | 563 | ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA | |
| 564 | DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG); | 564 | DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG); |
| 565 | 565 | ||
| 566 | /* Take MAC, Port, Phy (intern) and PCS (SGMII/Serdes) clock out of | ||
| 567 | * reset | ||
| 568 | */ | ||
| 569 | ocelot_port_writel(ocelot_port, DEV_CLOCK_CFG_LINK_SPEED(speed), | ||
| 570 | DEV_CLOCK_CFG); | ||
| 571 | |||
| 572 | /* No PFC */ | ||
| 573 | ocelot_write_gix(ocelot, ANA_PFC_PFC_CFG_FC_LINK_SPEED(speed), | ||
| 574 | ANA_PFC_PFC_CFG, port); | ||
| 575 | |||
| 576 | /* Core: Enable port for frame transfer */ | 566 | /* Core: Enable port for frame transfer */ |
| 577 | ocelot_fields_write(ocelot, port, | 567 | ocelot_fields_write(ocelot, port, |
| 578 | QSYS_SWITCH_PORT_MODE_PORT_ENA, 1); | 568 | QSYS_SWITCH_PORT_MODE_PORT_ENA, 1); |
| @@ -1303,14 +1293,19 @@ static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond, · 724 unmodified lines | |||
| 1303 | return mask; | 1293 | return mask; |
| 1304 | } | 1294 | } |
| 1305 | 1295 | ||
| 1306 | static u32 ocelot_get_bridge_fwd_mask(struct ocelot *ocelot, | 1296 | static u32 ocelot_get_bridge_fwd_mask(struct ocelot *ocelot, int src_port, |
| 1307 | struct net_device *bridge) | 1297 | struct net_device *bridge) |
| 1308 | { | 1298 | { |
| 1299 | struct ocelot_port *ocelot_port = ocelot->ports[src_port]; | ||
| 1309 | u32 mask = 0; | 1300 | u32 mask = 0; |
| 1310 | int port; | 1301 | int port; |
| 1311 | 1302 | ||
| 1303 | if (!ocelot_port || ocelot_port->bridge != bridge || | ||
| 1304 | ocelot_port->stp_state != BR_STATE_FORWARDING) | ||
| 1305 | return 0; | ||
| 1306 | |||
| 1312 | for (port = 0; port < ocelot->num_phys_ports; port++) { | 1307 | for (port = 0; port < ocelot->num_phys_ports; port++) { |
| 1313 | struct ocelot_port *ocelot_port = ocelot->ports[port]; | 1308 | ocelot_port = ocelot->ports[port]; |
| 1314 | 1309 | ||
| 1315 | if (!ocelot_port) | 1310 | if (!ocelot_port) |
| 1316 | continue; | 1311 | continue; |
| @@ -1376,7 +1371,7 @@ void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot) · 59 unmodified lines | |||
| 1376 | struct net_device *bridge = ocelot_port->bridge; | 1371 | struct net_device *bridge = ocelot_port->bridge; |
| 1377 | struct net_device *bond = ocelot_port->bond; | 1372 | struct net_device *bond = ocelot_port->bond; |
| 1378 | 1373 | ||
| 1379 | mask = ocelot_get_bridge_fwd_mask(ocelot, bridge); | 1374 | mask = ocelot_get_bridge_fwd_mask(ocelot, port, bridge); |
| 1380 | mask |= cpu_fwd_mask; | 1375 | mask |= cpu_fwd_mask; |
| 1381 | mask &= ~BIT(port); | 1376 | mask &= ~BIT(port); |
| 1382 | if (bond) { | 1377 | if (bond) { |
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: (GPL-2.0 OR MIT) | 1 | // SPDX-License-Identifier: (GPL-2.0 OR MIT) |
| 2 | /* Copyright 2020-2021 NXP Semiconductors | 2 | /* Copyright 2020-2021 NXP |
| 3 | */ | 3 | */ |
| 4 | #include <net/devlink.h> | 4 | #include <net/devlink.h> |
| 5 | #include "ocelot.h" | 5 | #include "ocelot.h" |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | /* Microsemi Ocelot Switch driver | 2 | /* Microsemi Ocelot Switch driver |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2017, 2019 Microsemi Corporation | 4 | * Copyright (c) 2017, 2019 Microsemi Corporation |
| 5 | * Copyright 2020-2021 NXP Semiconductors | 5 | * Copyright 2020-2021 NXP |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include <linux/if_bridge.h> | 8 | #include <linux/if_bridge.h> |
| @@ -5,7 +5,7 @@ · 4 unmodified lines | |||
| 5 | * mscc_ocelot_switch_lib. | 5 | * mscc_ocelot_switch_lib. |
| 6 | * | 6 | * |
| 7 | * Copyright (c) 2017, 2019 Microsemi Corporation | 7 | * Copyright (c) 2017, 2019 Microsemi Corporation |
| 8 | * Copyright 2020-2021 NXP Semiconductors | 8 | * Copyright 2020-2021 NXP |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/if_bridge.h> | 11 | #include <linux/if_bridge.h> |
| @@ -1297,6 +1297,14 @@ qed_iwarp_wait_cid_map_cleared(struct qed_hwfn *p_hwfn, struct qed_bmap *bmap) · 1296 unmodified lines | |||
| 1297 | prev_weight = weight; | 1297 | prev_weight = weight; |
| 1298 | 1298 | ||
| 1299 | while (weight) { | 1299 | while (weight) { |
| 1300 | /* If the HW device is during recovery, all resources are | ||
| 1301 | * immediately reset without receiving a per-cid indication | ||
| 1302 | * from HW. In this case we don't expect the cid_map to be | ||
| 1303 | * cleared. | ||
| 1304 | */ | ||
| 1305 | if (p_hwfn->cdev->recov_in_prog) | ||
| 1306 | return 0; | ||
| 1307 | |||
| 1300 | msleep(QED_IWARP_MAX_CID_CLEAN_TIME); | 1308 | msleep(QED_IWARP_MAX_CID_CLEAN_TIME); |
| 1301 | 1309 | ||
| 1302 | weight = bitmap_weight(bmap->bitmap, bmap->max_count); | 1310 | weight = bitmap_weight(bmap->bitmap, bmap->max_count); |
| @@ -77,6 +77,14 @@ void qed_roce_stop(struct qed_hwfn *p_hwfn) · 76 unmodified lines | |||
| 77 | * Beyond the added delay we clear the bitmap anyway. | 77 | * Beyond the added delay we clear the bitmap anyway. |
| 78 | */ | 78 | */ |
| 79 | while (bitmap_weight(rcid_map->bitmap, rcid_map->max_count)) { | 79 | while (bitmap_weight(rcid_map->bitmap, rcid_map->max_count)) { |
| 80 | /* If the HW device is during recovery, all resources are | ||
| 81 | * immediately reset without receiving a per-cid indication | ||
| 82 | * from HW. In this case we don't expect the cid bitmap to be | ||
| 83 | * cleared. | ||
| 84 | */ | ||
| 85 | if (p_hwfn->cdev->recov_in_prog) | ||
| 86 | return; | ||
| 87 | |||
| 80 | msleep(100); | 88 | msleep(100); |
| 81 | if (wait_count++ > 20) { | 89 | if (wait_count++ > 20) { |
| 82 | DP_NOTICE(p_hwfn, "cid bitmap wait timed out\n"); | 90 | DP_NOTICE(p_hwfn, "cid bitmap wait timed out\n"); |
| @@ -973,7 +973,7 @@ static inline void tx_on(struct scc_priv *priv) · 972 unmodified lines | |||
| 973 | flags = claim_dma_lock(); | 973 | flags = claim_dma_lock(); |
| 974 | set_dma_mode(priv->param.dma, DMA_MODE_WRITE); | 974 | set_dma_mode(priv->param.dma, DMA_MODE_WRITE); |
| 975 | set_dma_addr(priv->param.dma, | 975 | set_dma_addr(priv->param.dma, |
| 976 | (int) priv->tx_buf[priv->tx_tail] + n); | 976 | virt_to_bus(priv->tx_buf[priv->tx_tail]) + n); |
| 977 | set_dma_count(priv->param.dma, | 977 | set_dma_count(priv->param.dma, |
| 978 | priv->tx_len[priv->tx_tail] - n); | 978 | priv->tx_len[priv->tx_tail] - n); |
| 979 | release_dma_lock(flags); | 979 | release_dma_lock(flags); |
| @@ -1020,7 +1020,7 @@ static inline void rx_on(struct scc_priv *priv) · 40 unmodified lines | |||
| 1020 | flags = claim_dma_lock(); | 1020 | flags = claim_dma_lock(); |
| 1021 | set_dma_mode(priv->param.dma, DMA_MODE_READ); | 1021 | set_dma_mode(priv->param.dma, DMA_MODE_READ); |
| 1022 | set_dma_addr(priv->param.dma, | 1022 | set_dma_addr(priv->param.dma, |
| 1023 | (int) priv->rx_buf[priv->rx_head]); | 1023 | virt_to_bus(priv->rx_buf[priv->rx_head])); |
| 1024 | set_dma_count(priv->param.dma, BUF_SIZE); | 1024 | set_dma_count(priv->param.dma, BUF_SIZE); |
| 1025 | release_dma_lock(flags); | 1025 | release_dma_lock(flags); |
| 1026 | enable_dma(priv->param.dma); | 1026 | enable_dma(priv->param.dma); |
| @@ -1233,7 +1233,7 @@ static void special_condition(struct scc_priv *priv, int rc) · 206 unmodified lines | |||
| 1233 | if (priv->param.dma >= 0) { | 1233 | if (priv->param.dma >= 0) { |
| 1234 | flags = claim_dma_lock(); | 1234 | flags = claim_dma_lock(); |
| 1235 | set_dma_addr(priv->param.dma, | 1235 | set_dma_addr(priv->param.dma, |
| 1236 | (int) priv->rx_buf[priv->rx_head]); | 1236 | virt_to_bus(priv->rx_buf[priv->rx_head])); |
| 1237 | set_dma_count(priv->param.dma, BUF_SIZE); | 1237 | set_dma_count(priv->param.dma, BUF_SIZE); |
| 1238 | release_dma_lock(flags); | 1238 | release_dma_lock(flags); |
| 1239 | } else { | 1239 | } else { |
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* Copyright 2021 NXP Semiconductors | 2 | /* Copyright 2021 NXP |
| 3 | */ | 3 | */ |
| 4 | #include <linux/pcs/pcs-xpcs.h> | 4 | #include <linux/pcs/pcs-xpcs.h> |
| 5 | #include "pcs-xpcs.h" | 5 | #include "pcs-xpcs.h" |
| @@ -179,6 +179,16 @@ static int mdio_remove(struct device *dev) · 178 unmodified lines | |||
| 179 | return 0; | 179 | return 0; |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | static void mdio_shutdown(struct device *dev) | ||
| 183 | { | ||
| 184 | struct mdio_device *mdiodev = to_mdio_device(dev); | ||
| 185 | struct device_driver *drv = mdiodev->dev.driver; | ||
| 186 | struct mdio_driver *mdiodrv = to_mdio_driver(drv); | ||
| 187 | |||
| 188 | if (mdiodrv->shutdown) | ||
| 189 | mdiodrv->shutdown(mdiodev); | ||
| 190 | } | ||
| 191 | |||
| 182 | /** | 192 | /** |
| 183 | * mdio_driver_register - register an mdio_driver with the MDIO layer | 193 | * mdio_driver_register - register an mdio_driver with the MDIO layer |
| 184 | * @drv: new mdio_driver to register | 194 | * @drv: new mdio_driver to register |
| @@ -193,6 +203,7 @@ int mdio_driver_register(struct mdio_driver *drv) · 8 unmodified lines | |||
| 193 | mdiodrv->driver.bus = &mdio_bus_type; | 203 | mdiodrv->driver.bus = &mdio_bus_type; |
| 194 | mdiodrv->driver.probe = mdio_probe; | 204 | mdiodrv->driver.probe = mdio_probe; |
| 195 | mdiodrv->driver.remove = mdio_remove; | 205 | mdiodrv->driver.remove = mdio_remove; |
| 206 | mdiodrv->driver.shutdown = mdio_shutdown; | ||
| 196 | 207 | ||
| 197 | retval = driver_register(&mdiodrv->driver); | 208 | retval = driver_register(&mdiodrv->driver); |
| 198 | if (retval) { | 209 | if (retval) { |
| @@ -2719,14 +2719,14 @@ struct hso_device *hso_create_mux_serial_device(struct usb_interface *interface, · 2718 unmodified lines | |||
| 2719 | 2719 | ||
| 2720 | serial = kzalloc(sizeof(*serial), GFP_KERNEL); | 2720 | serial = kzalloc(sizeof(*serial), GFP_KERNEL); |
| 2721 | if (!serial) | 2721 | if (!serial) |
| 2722 | goto exit; | 2722 | goto err_free_dev; |
| 2723 | 2723 | ||
| 2724 | hso_dev->port_data.dev_serial = serial; | 2724 | hso_dev->port_data.dev_serial = serial; |
| 2725 | serial->parent = hso_dev; | 2725 | serial->parent = hso_dev; |
| 2726 | 2726 | ||
| 2727 | if (hso_serial_common_create | 2727 | if (hso_serial_common_create |
| 2728 | (serial, 1, CTRL_URB_RX_SIZE, CTRL_URB_TX_SIZE)) | 2728 | (serial, 1, CTRL_URB_RX_SIZE, CTRL_URB_TX_SIZE)) |
| 2729 | goto exit; | 2729 | goto err_free_serial; |
| 2730 | 2730 | ||
| 2731 | serial->tx_data_length--; | 2731 | serial->tx_data_length--; |
| 2732 | serial->write_data = hso_mux_serial_write_data; | 2732 | serial->write_data = hso_mux_serial_write_data; |
| @@ -2742,11 +2742,9 @@ struct hso_device *hso_create_mux_serial_device(struct usb_interface *interface, · 9 unmodified lines | |||
| 2742 | /* done, return it */ | 2742 | /* done, return it */ |
| 2743 | return hso_dev; | 2743 | return hso_dev; |
| 2744 | 2744 | ||
| 2745 | exit: | 2745 | err_free_serial: |
| 2746 | if (serial) { | 2746 | kfree(serial); |
| 2747 | tty_unregister_device(tty_drv, serial->minor); | 2747 | err_free_dev: |
| 2748 | kfree(serial); | ||
| 2749 | } | ||
| 2750 | kfree(hso_dev); | 2748 | kfree(hso_dev); |
| 2751 | return NULL; | 2749 | return NULL; |
| 2752 | 2750 | ||
| @@ -425,6 +425,10 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, · 424 unmodified lines | |||
| 425 | 425 | ||
| 426 | skb_reserve(skb, p - buf); | 426 | skb_reserve(skb, p - buf); |
| 427 | skb_put(skb, len); | 427 | skb_put(skb, len); |
| 428 | |||
| 429 | page = (struct page *)page->private; | ||
| 430 | if (page) | ||
| 431 | give_pages(rq, page); | ||
| 428 | goto ok; | 432 | goto ok; |
| 429 | } | 433 | } |
| 430 | 434 | ||
| @@ -4756,12 +4756,12 @@ static void __net_exit vxlan_exit_batch_net(struct list_head *net_list) · 4755 unmodified lines | |||
| 4756 | LIST_HEAD(list); | 4756 | LIST_HEAD(list); |
| 4757 | unsigned int h; | 4757 | unsigned int h; |
| 4758 | 4758 | ||
| 4759 | rtnl_lock(); | ||
| 4760 | list_for_each_entry(net, net_list, exit_list) { | 4759 | list_for_each_entry(net, net_list, exit_list) { |
| 4761 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); | 4760 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); |
| 4762 | 4761 | ||
| 4763 | unregister_nexthop_notifier(net, &vn->nexthop_notifier_block); | 4762 | unregister_nexthop_notifier(net, &vn->nexthop_notifier_block); |
| 4764 | } | 4763 | } |
| 4764 | rtnl_lock(); | ||
| 4765 | list_for_each_entry(net, net_list, exit_list) | 4765 | list_for_each_entry(net, net_list, exit_list) |
| 4766 | vxlan_destroy_tunnels(net, &list); | 4766 | vxlan_destroy_tunnels(net, &list); |
| 4767 | 4767 | ||
| @@ -499,7 +499,7 @@ check_frags: · 498 unmodified lines | |||
| 499 | * the header's copy failed, and they are | 499 | * the header's copy failed, and they are |
| 500 | * sharing a slot, send an error | 500 | * sharing a slot, send an error |
| 501 | */ | 501 | */ |
| 502 | if (i == 0 && sharedslot) | 502 | if (i == 0 && !first_shinfo && sharedslot) |
| 503 | xenvif_idx_release(queue, pending_idx, | 503 | xenvif_idx_release(queue, pending_idx, |
| 504 | XEN_NETIF_RSP_ERROR); | 504 | XEN_NETIF_RSP_ERROR); |
| 505 | else | 505 | else |
| @@ -278,6 +278,7 @@ static int st_nci_spi_remove(struct spi_device *dev) · 277 unmodified lines | |||
| 278 | 278 | ||
| 279 | static struct spi_device_id st_nci_spi_id_table[] = { | 279 | static struct spi_device_id st_nci_spi_id_table[] = { |
| 280 | {ST_NCI_SPI_DRIVER_NAME, 0}, | 280 | {ST_NCI_SPI_DRIVER_NAME, 0}, |
| 281 | {"st21nfcb-spi", 0}, | ||
| 281 | {} | 282 | {} |
| 282 | }; | 283 | }; |
| 283 | MODULE_DEVICE_TABLE(spi, st_nci_spi_id_table); | 284 | MODULE_DEVICE_TABLE(spi, st_nci_spi_id_table); |
| @@ -3524,7 +3524,9 @@ static struct nvme_ns_head *nvme_find_ns_head(struct nvme_subsystem *subsys, · 3523 unmodified lines | |||
| 3524 | lockdep_assert_held(&subsys->lock); | 3524 | lockdep_assert_held(&subsys->lock); |
| 3525 | 3525 | ||
| 3526 | list_for_each_entry(h, &subsys->nsheads, entry) { | 3526 | list_for_each_entry(h, &subsys->nsheads, entry) { |
| 3527 | if (h->ns_id == nsid && nvme_tryget_ns_head(h)) | 3527 | if (h->ns_id != nsid) |
| 3528 | continue; | ||
| 3529 | if (!list_empty(&h->list) && nvme_tryget_ns_head(h)) | ||
| 3528 | return h; | 3530 | return h; |
| 3529 | } | 3531 | } |
| 3530 | 3532 | ||
| @@ -3843,6 +3845,10 @@ static void nvme_ns_remove(struct nvme_ns *ns) · 312 unmodified lines | |||
| 3843 | 3845 | ||
| 3844 | mutex_lock(&ns->ctrl->subsys->lock); | 3846 | mutex_lock(&ns->ctrl->subsys->lock); |
| 3845 | list_del_rcu(&ns->siblings); | 3847 | list_del_rcu(&ns->siblings); |
| 3848 | if (list_empty(&ns->head->list)) { | ||
| 3849 | list_del_init(&ns->head->entry); | ||
| 3850 | last_path = true; | ||
| 3851 | } | ||
| 3846 | mutex_unlock(&ns->ctrl->subsys->lock); | 3852 | mutex_unlock(&ns->ctrl->subsys->lock); |
| 3847 | 3853 | ||
| 3848 | /* guarantee not available in head->list */ | 3854 | /* guarantee not available in head->list */ |
| @@ -3856,20 +3862,11 @@ static void nvme_ns_remove(struct nvme_ns *ns) · 7 unmodified lines | |||
| 3856 | nvme_cdev_del(&ns->cdev, &ns->cdev_device); | 3862 | nvme_cdev_del(&ns->cdev, &ns->cdev_device); |
| 3857 | del_gendisk(ns->disk); | 3863 | del_gendisk(ns->disk); |
| 3858 | blk_cleanup_queue(ns->queue); | 3864 | blk_cleanup_queue(ns->queue); |
| 3859 | if (blk_get_integrity(ns->disk)) | ||
| 3860 | blk_integrity_unregister(ns->disk); | ||
| 3861 | 3865 | ||
| 3862 | down_write(&ns->ctrl->namespaces_rwsem); | 3866 | down_write(&ns->ctrl->namespaces_rwsem); |
| 3863 | list_del_init(&ns->list); | 3867 | list_del_init(&ns->list); |
| 3864 | up_write(&ns->ctrl->namespaces_rwsem); | 3868 | up_write(&ns->ctrl->namespaces_rwsem); |
| 3865 | 3869 | ||
| 3866 | /* Synchronize with nvme_init_ns_head() */ | ||
| 3867 | mutex_lock(&ns->head->subsys->lock); | ||
| 3868 | if (list_empty(&ns->head->list)) { | ||
| 3869 | list_del_init(&ns->head->entry); | ||
| 3870 | last_path = true; | ||
| 3871 | } | ||
| 3872 | mutex_unlock(&ns->head->subsys->lock); | ||
| 3873 | if (last_path) | 3870 | if (last_path) |
| 3874 | nvme_mpath_shutdown_disk(ns->head); | 3871 | nvme_mpath_shutdown_disk(ns->head); |
| 3875 | nvme_put_ns(ns); | 3872 | nvme_put_ns(ns); |
| @@ -600,14 +600,17 @@ static int nvme_update_ana_state(struct nvme_ctrl *ctrl, · 599 unmodified lines | |||
| 600 | 600 | ||
| 601 | down_read(&ctrl->namespaces_rwsem); | 601 | down_read(&ctrl->namespaces_rwsem); |
| 602 | list_for_each_entry(ns, &ctrl->namespaces, list) { | 602 | list_for_each_entry(ns, &ctrl->namespaces, list) { |
| 603 | unsigned nsid = le32_to_cpu(desc->nsids[n]); | 603 | unsigned nsid; |
| 604 | 604 | again: | |
| 605 | nsid = le32_to_cpu(desc->nsids[n]); | ||
| 605 | if (ns->head->ns_id < nsid) | 606 | if (ns->head->ns_id < nsid) |
| 606 | continue; | 607 | continue; |
| 607 | if (ns->head->ns_id == nsid) | 608 | if (ns->head->ns_id == nsid) |
| 608 | nvme_update_ns_ana_state(desc, ns); | 609 | nvme_update_ns_ana_state(desc, ns); |
| 609 | if (++n == nr_nsids) | 610 | if (++n == nr_nsids) |
| 610 | break; | 611 | break; |
| 612 | if (ns->head->ns_id > nsid) | ||
| 613 | goto again; | ||
| 611 | } | 614 | } |
| 612 | up_read(&ctrl->namespaces_rwsem); | 615 | up_read(&ctrl->namespaces_rwsem); |
| 613 | return 0; | 616 | return 0; |
| @@ -656,8 +656,8 @@ static void nvme_rdma_free_queue(struct nvme_rdma_queue *queue) · 655 unmodified lines | |||
| 656 | if (!test_and_clear_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags)) | 656 | if (!test_and_clear_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags)) |
| 657 | return; | 657 | return; |
| 658 | 658 | ||
| 659 | nvme_rdma_destroy_queue_ib(queue); | ||
| 660 | rdma_destroy_id(queue->cm_id); | 659 | rdma_destroy_id(queue->cm_id); |
| 660 | nvme_rdma_destroy_queue_ib(queue); | ||
| 661 | mutex_destroy(&queue->queue_lock); | 661 | mutex_destroy(&queue->queue_lock); |
| 662 | } | 662 | } |
| 663 | 663 | ||
| @@ -1815,14 +1815,10 @@ static int nvme_rdma_conn_established(struct nvme_rdma_queue *queue) · 1151 unmodified lines | |||
| 1815 | for (i = 0; i < queue->queue_size; i++) { | 1815 | for (i = 0; i < queue->queue_size; i++) { |
| 1816 | ret = nvme_rdma_post_recv(queue, &queue->rsp_ring[i]); | 1816 | ret = nvme_rdma_post_recv(queue, &queue->rsp_ring[i]); |
| 1817 | if (ret) | 1817 | if (ret) |
| 1818 | goto out_destroy_queue_ib; | 1818 | return ret; |
| 1819 | } | 1819 | } |
| 1820 | 1820 | ||
| 1821 | return 0; | 1821 | return 0; |
| 1822 | |||
| 1823 | out_destroy_queue_ib: | ||
| 1824 | nvme_rdma_destroy_queue_ib(queue); | ||
| 1825 | return ret; | ||
| 1826 | } | 1822 | } |
| 1827 | 1823 | ||
| 1828 | static int nvme_rdma_conn_rejected(struct nvme_rdma_queue *queue, | 1824 | static int nvme_rdma_conn_rejected(struct nvme_rdma_queue *queue, |
| @@ -1916,14 +1912,10 @@ static int nvme_rdma_route_resolved(struct nvme_rdma_queue *queue) · 87 unmodified lines | |||
| 1916 | if (ret) { | 1912 | if (ret) { |
| 1917 | dev_err(ctrl->ctrl.device, | 1913 | dev_err(ctrl->ctrl.device, |
| 1918 | "rdma_connect_locked failed (%d).\n", ret); | 1914 | "rdma_connect_locked failed (%d).\n", ret); |
| 1919 | goto out_destroy_queue_ib; | 1915 | return ret; |
| 1920 | } | 1916 | } |
| 1921 | 1917 | ||
| 1922 | return 0; | 1918 | return 0; |
| 1923 | |||
| 1924 | out_destroy_queue_ib: | ||
| 1925 | nvme_rdma_destroy_queue_ib(queue); | ||
| 1926 | return ret; | ||
| 1927 | } | 1919 | } |
| 1928 | 1920 | ||
| 1929 | static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id, | 1921 | static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id, |
| @@ -1954,8 +1946,6 @@ static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id, · 24 unmodified lines | |||
| 1954 | case RDMA_CM_EVENT_ROUTE_ERROR: | 1946 | case RDMA_CM_EVENT_ROUTE_ERROR: |
| 1955 | case RDMA_CM_EVENT_CONNECT_ERROR: | 1947 | case RDMA_CM_EVENT_CONNECT_ERROR: |
| 1956 | case RDMA_CM_EVENT_UNREACHABLE: | 1948 | case RDMA_CM_EVENT_UNREACHABLE: |
| 1957 | nvme_rdma_destroy_queue_ib(queue); | ||
| 1958 | fallthrough; | ||
| 1959 | case RDMA_CM_EVENT_ADDR_ERROR: | 1949 | case RDMA_CM_EVENT_ADDR_ERROR: |
| 1960 | dev_dbg(queue->ctrl->ctrl.device, | 1950 | dev_dbg(queue->ctrl->ctrl.device, |
| 1961 | "CM error event %d\n", ev->event); | 1951 | "CM error event %d\n", ev->event); |
| @@ -274,6 +274,12 @@ static inline void nvme_tcp_send_all(struct nvme_tcp_queue *queue) · 273 unmodified lines | |||
| 274 | } while (ret > 0); | 274 | } while (ret > 0); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | static inline bool nvme_tcp_queue_more(struct nvme_tcp_queue *queue) | ||
| 278 | { | ||
| 279 | return !list_empty(&queue->send_list) || | ||
| 280 | !llist_empty(&queue->req_list) || queue->more_requests; | ||
| 281 | } | ||
| 282 | |||
| 277 | static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req, | 283 | static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req, |
| 278 | bool sync, bool last) | 284 | bool sync, bool last) |
| 279 | { | 285 | { |
| @@ -294,9 +300,10 @@ static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req, · 14 unmodified lines | |||
| 294 | nvme_tcp_send_all(queue); | 300 | nvme_tcp_send_all(queue); |
| 295 | queue->more_requests = false; | 301 | queue->more_requests = false; |
| 296 | mutex_unlock(&queue->send_mutex); | 302 | mutex_unlock(&queue->send_mutex); |
| 297 | } else if (last) { | ||
| 298 | queue_work_on(queue->io_cpu, nvme_tcp_wq, &queue->io_work); | ||
| 299 | } | 303 | } |
| 304 | |||
| 305 | if (last && nvme_tcp_queue_more(queue)) | ||
| 306 | queue_work_on(queue->io_cpu, nvme_tcp_wq, &queue->io_work); | ||
| 300 | } | 307 | } |
| 301 | 308 | ||
| 302 | static void nvme_tcp_process_req_list(struct nvme_tcp_queue *queue) | 309 | static void nvme_tcp_process_req_list(struct nvme_tcp_queue *queue) |
| @@ -906,12 +913,6 @@ done: · 603 unmodified lines | |||
| 906 | read_unlock_bh(&sk->sk_callback_lock); | 913 | read_unlock_bh(&sk->sk_callback_lock); |
| 907 | } | 914 | } |
| 908 | 915 | ||
| 909 | static inline bool nvme_tcp_queue_more(struct nvme_tcp_queue *queue) | ||
| 910 | { | ||
| 911 | return !list_empty(&queue->send_list) || | ||
| 912 | !llist_empty(&queue->req_list) || queue->more_requests; | ||
| 913 | } | ||
| 914 | |||
| 915 | static inline void nvme_tcp_done_send_req(struct nvme_tcp_queue *queue) | 916 | static inline void nvme_tcp_done_send_req(struct nvme_tcp_queue *queue) |
| 916 | { | 917 | { |
| 917 | queue->request = NULL; | 918 | queue->request = NULL; |
| @@ -1145,8 +1146,7 @@ static void nvme_tcp_io_work(struct work_struct *w) · 227 unmodified lines | |||
| 1145 | pending = true; | 1146 | pending = true; |
| 1146 | else if (unlikely(result < 0)) | 1147 | else if (unlikely(result < 0)) |
| 1147 | break; | 1148 | break; |
| 1148 | } else | 1149 | } |
| 1149 | pending = !llist_empty(&queue->req_list); | ||
| 1150 | 1150 | ||
| 1151 | result = nvme_tcp_try_recv(queue); | 1151 | result = nvme_tcp_try_recv(queue); |
| 1152 | if (result > 0) | 1152 | if (result > 0) |
| @@ -1067,7 +1067,7 @@ static ssize_t nvmet_subsys_attr_serial_show(struct config_item *item, · 1066 unmodified lines | |||
| 1067 | { | 1067 | { |
| 1068 | struct nvmet_subsys *subsys = to_subsys(item); | 1068 | struct nvmet_subsys *subsys = to_subsys(item); |
| 1069 | 1069 | ||
| 1070 | return snprintf(page, PAGE_SIZE, "%*s\n", | 1070 | return snprintf(page, PAGE_SIZE, "%.*s\n", |
| 1071 | NVMET_SN_MAX_SIZE, subsys->serial); | 1071 | NVMET_SN_MAX_SIZE, subsys->serial); |
| 1072 | } | 1072 | } |
| 1073 | 1073 | ||
| @@ -85,7 +85,11 @@ of_dma_set_restricted_buffer(struct device *dev, struct device_node *np) · 84 unmodified lines | |||
| 85 | break; | 85 | break; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | if (i != count && of_reserved_mem_device_init_by_idx(dev, of_node, i)) | 88 | /* |
| 89 | * Attempt to initialize a restricted-dma-pool region if one was found. | ||
| 90 | * Note that count can hold a negative error code. | ||
| 91 | */ | ||
| 92 | if (i < count && of_reserved_mem_device_init_by_idx(dev, of_node, i)) | ||
| 89 | dev_warn(dev, "failed to initialise \"restricted-dma-pool\" memory node\n"); | 93 | dev_warn(dev, "failed to initialise \"restricted-dma-pool\" memory node\n"); |
| 90 | } | 94 | } |
| 91 | 95 | ||
| @@ -1291,7 +1291,6 @@ DEFINE_SIMPLE_PROP(pwms, "pwms", "#pwm-cells") · 1290 unmodified lines | |||
| 1291 | DEFINE_SIMPLE_PROP(resets, "resets", "#reset-cells") | 1291 | DEFINE_SIMPLE_PROP(resets, "resets", "#reset-cells") |
| 1292 | DEFINE_SIMPLE_PROP(leds, "leds", NULL) | 1292 | DEFINE_SIMPLE_PROP(leds, "leds", NULL) |
| 1293 | DEFINE_SIMPLE_PROP(backlight, "backlight", NULL) | 1293 | DEFINE_SIMPLE_PROP(backlight, "backlight", NULL) |
| 1294 | DEFINE_SIMPLE_PROP(phy_handle, "phy-handle", NULL) | ||
| 1295 | DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) | 1294 | DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) |
| 1296 | DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") | 1295 | DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") |
| 1297 | 1296 | ||
| @@ -1380,7 +1379,6 @@ static const struct supplier_bindings of_supplier_bindings[] = { · 82 unmodified lines | |||
| 1380 | { .parse_prop = parse_resets, }, | 1379 | { .parse_prop = parse_resets, }, |
| 1381 | { .parse_prop = parse_leds, }, | 1380 | { .parse_prop = parse_leds, }, |
| 1382 | { .parse_prop = parse_backlight, }, | 1381 | { .parse_prop = parse_backlight, }, |
| 1383 | { .parse_prop = parse_phy_handle, }, | ||
| 1384 | { .parse_prop = parse_gpio_compat, }, | 1382 | { .parse_prop = parse_gpio_compat, }, |
| 1385 | { .parse_prop = parse_interrupts, }, | 1383 | { .parse_prop = parse_interrupts, }, |
| 1386 | { .parse_prop = parse_regulators, }, | 1384 | { .parse_prop = parse_regulators, }, |
| @@ -937,7 +937,7 @@ static struct acpi_device *acpi_pci_find_companion(struct device *dev); · 936 unmodified lines | |||
| 937 | 937 | ||
| 938 | void pci_set_acpi_fwnode(struct pci_dev *dev) | 938 | void pci_set_acpi_fwnode(struct pci_dev *dev) |
| 939 | { | 939 | { |
| 940 | if (!ACPI_COMPANION(&dev->dev) && !pci_dev_is_added(dev)) | 940 | if (!dev_fwnode(&dev->dev) && !pci_dev_is_added(dev)) |
| 941 | ACPI_COMPANION_SET(&dev->dev, | 941 | ACPI_COMPANION_SET(&dev->dev, |
| 942 | acpi_pci_find_companion(&dev->dev)); | 942 | acpi_pci_find_companion(&dev->dev)); |
| 943 | } | 943 | } |
| @@ -5435,7 +5435,7 @@ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, · 5434 unmodified lines | |||
| 5435 | PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, quirk_gpu_hda); | 5435 | PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, quirk_gpu_hda); |
| 5436 | 5436 | ||
| 5437 | /* | 5437 | /* |
| 5438 | * Create device link for NVIDIA GPU with integrated USB xHCI Host | 5438 | * Create device link for GPUs with integrated USB xHCI Host |
| 5439 | * controller to VGA. | 5439 | * controller to VGA. |
| 5440 | */ | 5440 | */ |
| 5441 | static void quirk_gpu_usb(struct pci_dev *usb) | 5441 | static void quirk_gpu_usb(struct pci_dev *usb) |
| @@ -5444,9 +5444,11 @@ static void quirk_gpu_usb(struct pci_dev *usb) · 2 unmodified lines | |||
| 5444 | } | 5444 | } |
| 5445 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, | 5445 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, |
| 5446 | PCI_CLASS_SERIAL_USB, 8, quirk_gpu_usb); | 5446 | PCI_CLASS_SERIAL_USB, 8, quirk_gpu_usb); |
| 5447 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID, | ||
| 5448 | PCI_CLASS_SERIAL_USB, 8, quirk_gpu_usb); | ||
| 5447 | 5449 | ||
| 5448 | /* | 5450 | /* |
| 5449 | * Create device link for NVIDIA GPU with integrated Type-C UCSI controller | 5451 | * Create device link for GPUs with integrated Type-C UCSI controller |
| 5450 | * to VGA. Currently there is no class code defined for UCSI device over PCI | 5452 | * to VGA. Currently there is no class code defined for UCSI device over PCI |
| 5451 | * so using UNKNOWN class for now and it will be updated when UCSI | 5453 | * so using UNKNOWN class for now and it will be updated when UCSI |
| 5452 | * over PCI gets a class code. | 5454 | * over PCI gets a class code. |
| @@ -5459,6 +5461,9 @@ static void quirk_gpu_usb_typec_ucsi(struct pci_dev *ucsi) · 6 unmodified lines | |||
| 5459 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, | 5461 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, |
| 5460 | PCI_CLASS_SERIAL_UNKNOWN, 8, | 5462 | PCI_CLASS_SERIAL_UNKNOWN, 8, |
| 5461 | quirk_gpu_usb_typec_ucsi); | 5463 | quirk_gpu_usb_typec_ucsi); |
| 5464 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID, | ||
| 5465 | PCI_CLASS_SERIAL_UNKNOWN, 8, | ||
| 5466 | quirk_gpu_usb_typec_ucsi); | ||
| 5462 | 5467 | ||
| 5463 | /* | 5468 | /* |
| 5464 | * Enable the NVIDIA GPU integrated HDA controller if the BIOS left it | 5469 | * Enable the NVIDIA GPU integrated HDA controller if the BIOS left it |
| @@ -99,6 +99,24 @@ error: · 98 unmodified lines | |||
| 99 | return off ?: PCI_VPD_SZ_INVALID; | 99 | return off ?: PCI_VPD_SZ_INVALID; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static bool pci_vpd_available(struct pci_dev *dev) | ||
| 103 | { | ||
| 104 | struct pci_vpd *vpd = &dev->vpd; | ||
| 105 | |||
| 106 | if (!vpd->cap) | ||
| 107 | return false; | ||
| 108 | |||
| 109 | if (vpd->len == 0) { | ||
| 110 | vpd->len = pci_vpd_size(dev); | ||
| 111 | if (vpd->len == PCI_VPD_SZ_INVALID) { | ||
| 112 | vpd->cap = 0; | ||
| 113 | return false; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | return true; | ||
| 118 | } | ||
| 119 | |||
| 102 | /* | 120 | /* |
| 103 | * Wait for last operation to complete. | 121 | * Wait for last operation to complete. |
| 104 | * This code has to spin since there is no other notification from the PCI | 122 | * This code has to spin since there is no other notification from the PCI |
| @@ -145,7 +163,7 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count, · 40 unmodified lines | |||
| 145 | loff_t end = pos + count; | 163 | loff_t end = pos + count; |
| 146 | u8 *buf = arg; | 164 | u8 *buf = arg; |
| 147 | 165 | ||
| 148 | if (!vpd->cap) | 166 | if (!pci_vpd_available(dev)) |
| 149 | return -ENODEV; | 167 | return -ENODEV; |
| 150 | 168 | ||
| 151 | if (pos < 0) | 169 | if (pos < 0) |
| @@ -206,7 +224,7 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count, · 54 unmodified lines | |||
| 206 | loff_t end = pos + count; | 224 | loff_t end = pos + count; |
| 207 | int ret = 0; | 225 | int ret = 0; |
| 208 | 226 | ||
| 209 | if (!vpd->cap) | 227 | if (!pci_vpd_available(dev)) |
| 210 | return -ENODEV; | 228 | return -ENODEV; |
| 211 | 229 | ||
| 212 | if (pos < 0 || (pos & 3) || (count & 3)) | 230 | if (pos < 0 || (pos & 3) || (count & 3)) |
| @@ -242,14 +260,11 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count, · 29 unmodified lines | |||
| 242 | 260 | ||
| 243 | void pci_vpd_init(struct pci_dev *dev) | 261 | void pci_vpd_init(struct pci_dev *dev) |
| 244 | { | 262 | { |
| 263 | if (dev->vpd.len == PCI_VPD_SZ_INVALID) | ||
| 264 | return; | ||
| 265 | |||
| 245 | dev->vpd.cap = pci_find_capability(dev, PCI_CAP_ID_VPD); | 266 | dev->vpd.cap = pci_find_capability(dev, PCI_CAP_ID_VPD); |
| 246 | mutex_init(&dev->vpd.lock); | 267 | mutex_init(&dev->vpd.lock); |
| 247 | |||
| 248 | if (!dev->vpd.len) | ||
| 249 | dev->vpd.len = pci_vpd_size(dev); | ||
| 250 | |||
| 251 | if (dev->vpd.len == PCI_VPD_SZ_INVALID) | ||
| 252 | dev->vpd.cap = 0; | ||
| 253 | } | 268 | } |
| 254 | 269 | ||
| 255 | static ssize_t vpd_read(struct file *filp, struct kobject *kobj, | 270 | static ssize_t vpd_read(struct file *filp, struct kobject *kobj, |
| @@ -294,13 +309,14 @@ const struct attribute_group pci_dev_vpd_attr_group = { · 38 unmodified lines | |||
| 294 | 309 | ||
| 295 | void *pci_vpd_alloc(struct pci_dev *dev, unsigned int *size) | 310 | void *pci_vpd_alloc(struct pci_dev *dev, unsigned int *size) |
| 296 | { | 311 | { |
| 297 | unsigned int len = dev->vpd.len; | 312 | unsigned int len; |
| 298 | void *buf; | 313 | void *buf; |
| 299 | int cnt; | 314 | int cnt; |
| 300 | 315 | ||
| 301 | if (!dev->vpd.cap) | 316 | if (!pci_vpd_available(dev)) |
| 302 | return ERR_PTR(-ENODEV); | 317 | return ERR_PTR(-ENODEV); |
| 303 | 318 | ||
| 319 | len = dev->vpd.len; | ||
| 304 | buf = kmalloc(len, GFP_KERNEL); | 320 | buf = kmalloc(len, GFP_KERNEL); |
| 305 | if (!buf) | 321 | if (!buf) |
| 306 | return ERR_PTR(-ENOMEM); | 322 | return ERR_PTR(-ENOMEM); |
| @@ -71,7 +71,7 @@ · 70 unmodified lines | |||
| 71 | #define AMD_CPU_ID_YC 0x14B5 | 71 | #define AMD_CPU_ID_YC 0x14B5 |
| 72 | 72 | ||
| 73 | #define PMC_MSG_DELAY_MIN_US 100 | 73 | #define PMC_MSG_DELAY_MIN_US 100 |
| 74 | #define RESPONSE_REGISTER_LOOP_MAX 200 | 74 | #define RESPONSE_REGISTER_LOOP_MAX 20000 |
| 75 | 75 | ||
| 76 | #define SOC_SUBSYSTEM_IP_MAX 12 | 76 | #define SOC_SUBSYSTEM_IP_MAX 12 |
| 77 | #define DELAY_MIN_US 2000 | 77 | #define DELAY_MIN_US 2000 |
| @@ -166,8 +166,7 @@ config DELL_WMI · 165 unmodified lines | |||
| 166 | 166 | ||
| 167 | config DELL_WMI_PRIVACY | 167 | config DELL_WMI_PRIVACY |
| 168 | bool "Dell WMI Hardware Privacy Support" | 168 | bool "Dell WMI Hardware Privacy Support" |
| 169 | depends on DELL_WMI | 169 | depends on LEDS_TRIGGER_AUDIO = y || DELL_WMI = LEDS_TRIGGER_AUDIO |
| 170 | depends on LEDS_TRIGGER_AUDIO | ||
| 171 | help | 170 | help |
| 172 | This option adds integration with the "Dell Hardware Privacy" | 171 | This option adds integration with the "Dell Hardware Privacy" |
| 173 | feature of Dell laptops to the dell-wmi driver. | 172 | feature of Dell laptops to the dell-wmi driver. |
| @@ -144,6 +144,7 @@ static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = { · 143 unmodified lines | |||
| 144 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"), | 144 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"), |
| 145 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE V2"), | 145 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE V2"), |
| 146 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 GAMING X V2"), | 146 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 GAMING X V2"), |
| 147 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550I AORUS PRO AX"), | ||
| 147 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M AORUS PRO-P"), | 148 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M AORUS PRO-P"), |
| 148 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M DS3H"), | 149 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M DS3H"), |
| 149 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z390 I AORUS PRO WIFI-CF"), | 150 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z390 I AORUS PRO WIFI-CF"), |
| @@ -118,12 +118,30 @@ static const struct dmi_system_id dmi_vgbs_allow_list[] = { · 117 unmodified lines | |||
| 118 | { } | 118 | { } |
| 119 | }; | 119 | }; |
| 120 | 120 | ||
| 121 | /* | ||
| 122 | * Some devices, even non convertible ones, can send incorrect SW_TABLET_MODE | ||
| 123 | * reports. Accept such reports only from devices in this list. | ||
| 124 | */ | ||
| 125 | static const struct dmi_system_id dmi_auto_add_switch[] = { | ||
| 126 | { | ||
| 127 | .matches = { | ||
| 128 | DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "31" /* Convertible */), | ||
| 129 | }, | ||
| 130 | }, | ||
| 131 | { | ||
| 132 | .matches = { | ||
| 133 | DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "32" /* Detachable */), | ||
| 134 | }, | ||
| 135 | }, | ||
| 136 | {} /* Array terminator */ | ||
| 137 | }; | ||
| 138 | |||
| 121 | struct intel_hid_priv { | 139 | struct intel_hid_priv { |
| 122 | struct input_dev *input_dev; | 140 | struct input_dev *input_dev; |
| 123 | struct input_dev *array; | 141 | struct input_dev *array; |
| 124 | struct input_dev *switches; | 142 | struct input_dev *switches; |
| 125 | bool wakeup_mode; | 143 | bool wakeup_mode; |
| 126 | bool dual_accel; | 144 | bool auto_add_switch; |
| 127 | }; | 145 | }; |
| 128 | 146 | ||
| 129 | #define HID_EVENT_FILTER_UUID "eeec56b3-4442-408f-a792-4edd4d758054" | 147 | #define HID_EVENT_FILTER_UUID "eeec56b3-4442-408f-a792-4edd4d758054" |
| @@ -452,10 +470,8 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) · 322 unmodified lines | |||
| 452 | * Some convertible have unreliable VGBS return which could cause incorrect | 470 | * Some convertible have unreliable VGBS return which could cause incorrect |
| 453 | * SW_TABLET_MODE report, in these cases we enable support when receiving | 471 | * SW_TABLET_MODE report, in these cases we enable support when receiving |
| 454 | * the first event instead of during driver setup. | 472 | * the first event instead of during driver setup. |
| 455 | * | ||
| 456 | * See dual_accel_detect.h for more info on the dual_accel check. | ||
| 457 | */ | 473 | */ |
| 458 | if (!priv->switches && !priv->dual_accel && (event == 0xcc || event == 0xcd)) { | 474 | if (!priv->switches && priv->auto_add_switch && (event == 0xcc || event == 0xcd)) { |
| 459 | dev_info(&device->dev, "switch event received, enable switches supports\n"); | 475 | dev_info(&device->dev, "switch event received, enable switches supports\n"); |
| 460 | err = intel_hid_switches_setup(device); | 476 | err = intel_hid_switches_setup(device); |
| 461 | if (err) | 477 | if (err) |
| @@ -596,7 +612,8 @@ static int intel_hid_probe(struct platform_device *device) · 134 unmodified lines | |||
| 596 | return -ENOMEM; | 612 | return -ENOMEM; |
| 597 | dev_set_drvdata(&device->dev, priv); | 613 | dev_set_drvdata(&device->dev, priv); |
| 598 | 614 | ||
| 599 | priv->dual_accel = dual_accel_detect(); | 615 | /* See dual_accel_detect.h for more info on the dual_accel check. */ |
| 616 | priv->auto_add_switch = dmi_check_system(dmi_auto_add_switch) && !dual_accel_detect(); | ||
| 600 | 617 | ||
| 601 | err = intel_hid_input_setup(device); | 618 | err = intel_hid_input_setup(device); |
| 602 | if (err) { | 619 | if (err) { |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | |||
| 8 | * which provide mailbox interface for power management usage. | 8 | * which provide mailbox interface for power management usage. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/acpi.h> | ||
| 12 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
| 13 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
| 14 | #include <linux/device.h> | 13 | #include <linux/device.h> |
| @@ -319,7 +318,7 @@ static struct platform_driver intel_punit_ipc_driver = { · 304 unmodified lines | |||
| 319 | .remove = intel_punit_ipc_remove, | 318 | .remove = intel_punit_ipc_remove, |
| 320 | .driver = { | 319 | .driver = { |
| 321 | .name = "intel_punit_ipc", | 320 | .name = "intel_punit_ipc", |
| 322 | .acpi_match_table = ACPI_PTR(punit_ipc_acpi_ids), | 321 | .acpi_match_table = punit_ipc_acpi_ids, |
| 323 | }, | 322 | }, |
| 324 | }; | 323 | }; |
| 325 | 324 | ||
| @@ -655,7 +655,7 @@ static int acpi_add(struct acpi_device *device) · 654 unmodified lines | |||
| 655 | goto out_platform_registered; | 655 | goto out_platform_registered; |
| 656 | } | 656 | } |
| 657 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | 657 | product = dmi_get_system_info(DMI_PRODUCT_NAME); |
| 658 | if (strlen(product) > 4) | 658 | if (product && strlen(product) > 4) |
| 659 | switch (product[4]) { | 659 | switch (product[4]) { |
| 660 | case '5': | 660 | case '5': |
| 661 | case '6': | 661 | case '6': |
| @@ -100,10 +100,10 @@ static const struct ts_dmi_data chuwi_hi10_air_data = { · 99 unmodified lines | |||
| 100 | }; | 100 | }; |
| 101 | 101 | ||
| 102 | static const struct property_entry chuwi_hi10_plus_props[] = { | 102 | static const struct property_entry chuwi_hi10_plus_props[] = { |
| 103 | PROPERTY_ENTRY_U32("touchscreen-min-x", 0), | 103 | PROPERTY_ENTRY_U32("touchscreen-min-x", 12), |
| 104 | PROPERTY_ENTRY_U32("touchscreen-min-y", 5), | 104 | PROPERTY_ENTRY_U32("touchscreen-min-y", 10), |
| 105 | PROPERTY_ENTRY_U32("touchscreen-size-x", 1914), | 105 | PROPERTY_ENTRY_U32("touchscreen-size-x", 1908), |
| 106 | PROPERTY_ENTRY_U32("touchscreen-size-y", 1283), | 106 | PROPERTY_ENTRY_U32("touchscreen-size-y", 1270), |
| 107 | PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi10plus.fw"), | 107 | PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi10plus.fw"), |
| 108 | PROPERTY_ENTRY_U32("silead,max-fingers", 10), | 108 | PROPERTY_ENTRY_U32("silead,max-fingers", 10), |
| 109 | PROPERTY_ENTRY_BOOL("silead,home-button"), | 109 | PROPERTY_ENTRY_BOOL("silead,home-button"), |
| @@ -111,6 +111,15 @@ static const struct property_entry chuwi_hi10_plus_props[] = { · 1 unmodified line | |||
| 111 | }; | 111 | }; |
| 112 | 112 | ||
| 113 | static const struct ts_dmi_data chuwi_hi10_plus_data = { | 113 | static const struct ts_dmi_data chuwi_hi10_plus_data = { |
| 114 | .embedded_fw = { | ||
| 115 | .name = "silead/gsl1680-chuwi-hi10plus.fw", | ||
| 116 | .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }, | ||
| 117 | .length = 34056, | ||
| 118 | .sha256 = { 0xfd, 0x0a, 0x08, 0x08, 0x3c, 0xa6, 0x34, 0x4e, | ||
| 119 | 0x2c, 0x49, 0x9c, 0xcd, 0x7d, 0x44, 0x9d, 0x38, | ||
| 120 | 0x10, 0x68, 0xb5, 0xbd, 0xb7, 0x2a, 0x63, 0xb5, | ||
| 121 | 0x67, 0x0b, 0x96, 0xbd, 0x89, 0x67, 0x85, 0x09 }, | ||
| 122 | }, | ||
| 114 | .acpi_name = "MSSL0017:00", | 123 | .acpi_name = "MSSL0017:00", |
| 115 | .properties = chuwi_hi10_plus_props, | 124 | .properties = chuwi_hi10_plus_props, |
| 116 | }; | 125 | }; |
| @@ -141,6 +150,33 @@ static const struct ts_dmi_data chuwi_hi10_pro_data = { · 24 unmodified lines | |||
| 141 | .properties = chuwi_hi10_pro_props, | 150 | .properties = chuwi_hi10_pro_props, |
| 142 | }; | 151 | }; |
| 143 | 152 | ||
| 153 | static const struct property_entry chuwi_hibook_props[] = { | ||
| 154 | PROPERTY_ENTRY_U32("touchscreen-min-x", 30), | ||
| 155 | PROPERTY_ENTRY_U32("touchscreen-min-y", 4), | ||
| 156 | PROPERTY_ENTRY_U32("touchscreen-size-x", 1892), | ||
| 157 | PROPERTY_ENTRY_U32("touchscreen-size-y", 1276), | ||
| 158 | PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), | ||
| 159 | PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), | ||
| 160 | PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hibook.fw"), | ||
| 161 | PROPERTY_ENTRY_U32("silead,max-fingers", 10), | ||
| 162 | PROPERTY_ENTRY_BOOL("silead,home-button"), | ||
| 163 | { } | ||
| 164 | }; | ||
| 165 | |||
| 166 | static const struct ts_dmi_data chuwi_hibook_data = { | ||
| 167 | .embedded_fw = { | ||
| 168 | .name = "silead/gsl1680-chuwi-hibook.fw", | ||
| 169 | .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }, | ||
| 170 | .length = 40392, | ||
| 171 | .sha256 = { 0xf7, 0xc0, 0xe8, 0x5a, 0x6c, 0xf2, 0xeb, 0x8d, | ||
| 172 | 0x12, 0xc4, 0x45, 0xbf, 0x55, 0x13, 0x4c, 0x1a, | ||
| 173 | 0x13, 0x04, 0x31, 0x08, 0x65, 0x73, 0xf7, 0xa8, | ||
| 174 | 0x1b, 0x7d, 0x59, 0xc9, 0xe6, 0x97, 0xf7, 0x38 }, | ||
| 175 | }, | ||
| 176 | .acpi_name = "MSSL0017:00", | ||
| 177 | .properties = chuwi_hibook_props, | ||
| 178 | }; | ||
| 179 | |||
| 144 | static const struct property_entry chuwi_vi8_props[] = { | 180 | static const struct property_entry chuwi_vi8_props[] = { |
| 145 | PROPERTY_ENTRY_U32("touchscreen-min-x", 4), | 181 | PROPERTY_ENTRY_U32("touchscreen-min-x", 4), |
| 146 | PROPERTY_ENTRY_U32("touchscreen-min-y", 6), | 182 | PROPERTY_ENTRY_U32("touchscreen-min-y", 6), |
| @@ -979,6 +1015,16 @@ const struct dmi_system_id touchscreen_dmi_table[] = { · 832 unmodified lines | |||
| 979 | DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), | 1015 | DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), |
| 980 | }, | 1016 | }, |
| 981 | }, | 1017 | }, |
| 1018 | { | ||
| 1019 | /* Chuwi HiBook (CWI514) */ | ||
| 1020 | .driver_data = (void *)&chuwi_hibook_data, | ||
| 1021 | .matches = { | ||
| 1022 | DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), | ||
| 1023 | DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), | ||
| 1024 | /* Above matches are too generic, add bios-date match */ | ||
| 1025 | DMI_MATCH(DMI_BIOS_DATE, "05/07/2016"), | ||
| 1026 | }, | ||
| 1027 | }, | ||
| 982 | { | 1028 | { |
| 983 | /* Chuwi Vi8 (CWI506) */ | 1029 | /* Chuwi Vi8 (CWI506) */ |
| 984 | .driver_data = (void *)&chuwi_vi8_data, | 1030 | .driver_data = (void *)&chuwi_vi8_data, |
| @@ -174,6 +174,7 @@ config PTP_1588_CLOCK_OCP · 173 unmodified lines | |||
| 174 | depends on I2C && MTD | 174 | depends on I2C && MTD |
| 175 | depends on SERIAL_8250 | 175 | depends on SERIAL_8250 |
| 176 | depends on !S390 | 176 | depends on !S390 |
| 177 | depends on COMMON_CLK | ||
| 177 | select NET_DEVLINK | 178 | select NET_DEVLINK |
| 178 | help | 179 | help |
| 179 | This driver adds support for an OpenCompute time card. | 180 | This driver adds support for an OpenCompute time card. |
| @@ -269,5 +269,3 @@ module_exit(max14577_regulator_exit); · 268 unmodified lines | |||
| 269 | MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>"); | 269 | MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>"); |
| 270 | MODULE_DESCRIPTION("Maxim 14577/77836 regulator driver"); | 270 | MODULE_DESCRIPTION("Maxim 14577/77836 regulator driver"); |
| 271 | MODULE_LICENSE("GPL"); | 271 | MODULE_LICENSE("GPL"); |
| 272 | MODULE_ALIAS("platform:max14577-regulator"); | ||
| 273 | MODULE_ALIAS("platform:max77836-regulator"); | ||
| @@ -991,7 +991,7 @@ static const struct rpmh_vreg_init_data pm8009_1_vreg_data[] = { · 990 unmodified lines | |||
| 991 | RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"), | 991 | RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"), |
| 992 | RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6"), | 992 | RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6"), |
| 993 | RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l5-l6"), | 993 | RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l5-l6"), |
| 994 | RPMH_VREG("ldo7", "ldo%s6", &pmic5_pldo_lv, "vdd-l7"), | 994 | RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo_lv, "vdd-l7"), |
| 995 | {} | 995 | {} |
| 996 | }; | 996 | }; |
| 997 | 997 | ||
| @@ -45,13 +45,14 @@ static void __init sclp_early_facilities_detect(void) · 44 unmodified lines | |||
| 45 | sclp.has_gisaf = !!(sccb->fac118 & 0x08); | 45 | sclp.has_gisaf = !!(sccb->fac118 & 0x08); |
| 46 | sclp.has_hvs = !!(sccb->fac119 & 0x80); | 46 | sclp.has_hvs = !!(sccb->fac119 & 0x80); |
| 47 | sclp.has_kss = !!(sccb->fac98 & 0x01); | 47 | sclp.has_kss = !!(sccb->fac98 & 0x01); |
| 48 | sclp.has_sipl = !!(sccb->cbl & 0x4000); | ||
| 49 | if (sccb->fac85 & 0x02) | 48 | if (sccb->fac85 & 0x02) |
| 50 | S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; | 49 | S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; |
| 51 | if (sccb->fac91 & 0x40) | 50 | if (sccb->fac91 & 0x40) |
| 52 | S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_GUEST; | 51 | S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_GUEST; |
| 53 | if (sccb->cpuoff > 134) | 52 | if (sccb->cpuoff > 134) |
| 54 | sclp.has_diag318 = !!(sccb->byte_134 & 0x80); | 53 | sclp.has_diag318 = !!(sccb->byte_134 & 0x80); |
| 54 | if (sccb->cpuoff > 137) | ||
| 55 | sclp.has_sipl = !!(sccb->cbl & 0x4000); | ||
| 55 | sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; | 56 | sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; |
| 56 | sclp.rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; | 57 | sclp.rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; |
| 57 | sclp.rzm <<= 20; | 58 | sclp.rzm <<= 20; |
| @@ -77,12 +77,13 @@ EXPORT_SYMBOL(ccwgroup_set_online); · 76 unmodified lines | |||
| 77 | /** | 77 | /** |
| 78 | * ccwgroup_set_offline() - disable a ccwgroup device | 78 | * ccwgroup_set_offline() - disable a ccwgroup device |
| 79 | * @gdev: target ccwgroup device | 79 | * @gdev: target ccwgroup device |
| 80 | * @call_gdrv: Call the registered gdrv set_offline function | ||
| 80 | * | 81 | * |
| 81 | * This function attempts to put the ccwgroup device into the offline state. | 82 | * This function attempts to put the ccwgroup device into the offline state. |
| 82 | * Returns: | 83 | * Returns: |
| 83 | * %0 on success and a negative error value on failure. | 84 | * %0 on success and a negative error value on failure. |
| 84 | */ | 85 | */ |
| 85 | int ccwgroup_set_offline(struct ccwgroup_device *gdev) | 86 | int ccwgroup_set_offline(struct ccwgroup_device *gdev, bool call_gdrv) |
| 86 | { | 87 | { |
| 87 | struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); | 88 | struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); |
| 88 | int ret = -EINVAL; | 89 | int ret = -EINVAL; |
| @@ -91,11 +92,16 @@ int ccwgroup_set_offline(struct ccwgroup_device *gdev) · 2 unmodified lines | |||
| 91 | return -EAGAIN; | 92 | return -EAGAIN; |
| 92 | if (gdev->state == CCWGROUP_OFFLINE) | 93 | if (gdev->state == CCWGROUP_OFFLINE) |
| 93 | goto out; | 94 | goto out; |
| 95 | if (!call_gdrv) { | ||
| 96 | ret = 0; | ||
| 97 | goto offline; | ||
| 98 | } | ||
| 94 | if (gdrv->set_offline) | 99 | if (gdrv->set_offline) |
| 95 | ret = gdrv->set_offline(gdev); | 100 | ret = gdrv->set_offline(gdev); |
| 96 | if (ret) | 101 | if (ret) |
| 97 | goto out; | 102 | goto out; |
| 98 | 103 | ||
| 104 | offline: | ||
| 99 | gdev->state = CCWGROUP_OFFLINE; | 105 | gdev->state = CCWGROUP_OFFLINE; |
| 100 | out: | 106 | out: |
| 101 | atomic_set(&gdev->onoff, 0); | 107 | atomic_set(&gdev->onoff, 0); |
| @@ -124,7 +130,7 @@ static ssize_t ccwgroup_online_store(struct device *dev, · 22 unmodified lines | |||
| 124 | if (value == 1) | 130 | if (value == 1) |
| 125 | ret = ccwgroup_set_online(gdev); | 131 | ret = ccwgroup_set_online(gdev); |
| 126 | else if (value == 0) | 132 | else if (value == 0) |
| 127 | ret = ccwgroup_set_offline(gdev); | 133 | ret = ccwgroup_set_offline(gdev, true); |
| 128 | else | 134 | else |
| 129 | ret = -EINVAL; | 135 | ret = -EINVAL; |
| 130 | out: | 136 | out: |
| @@ -213,7 +213,6 @@ static inline int ap_fetch_qci_info(struct ap_config_info *info) · 212 unmodified lines | |||
| 213 | * ap_init_qci_info(): Allocate and query qci config info. | 213 | * ap_init_qci_info(): Allocate and query qci config info. |
| 214 | * Does also update the static variables ap_max_domain_id | 214 | * Does also update the static variables ap_max_domain_id |
| 215 | * and ap_max_adapter_id if this info is available. | 215 | * and ap_max_adapter_id if this info is available. |
| 216 | |||
| 217 | */ | 216 | */ |
| 218 | static void __init ap_init_qci_info(void) | 217 | static void __init ap_init_qci_info(void) |
| 219 | { | 218 | { |
| @@ -439,6 +438,7 @@ static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused) · 219 unmodified lines | |||
| 439 | /** | 438 | /** |
| 440 | * ap_interrupt_handler() - Schedule ap_tasklet on interrupt | 439 | * ap_interrupt_handler() - Schedule ap_tasklet on interrupt |
| 441 | * @airq: pointer to adapter interrupt descriptor | 440 | * @airq: pointer to adapter interrupt descriptor |
| 441 | * @floating: ignored | ||
| 442 | */ | 442 | */ |
| 443 | static void ap_interrupt_handler(struct airq_struct *airq, bool floating) | 443 | static void ap_interrupt_handler(struct airq_struct *airq, bool floating) |
| 444 | { | 444 | { |
| @@ -1786,6 +1786,7 @@ static inline void ap_scan_adapter(int ap) · 1341 unmodified lines | |||
| 1786 | /** | 1786 | /** |
| 1787 | * ap_scan_bus(): Scan the AP bus for new devices | 1787 | * ap_scan_bus(): Scan the AP bus for new devices |
| 1788 | * Runs periodically, workqueue timer (ap_config_time) | 1788 | * Runs periodically, workqueue timer (ap_config_time) |
| 1789 | * @unused: Unused pointer. | ||
| 1789 | */ | 1790 | */ |
| 1790 | static void ap_scan_bus(struct work_struct *unused) | 1791 | static void ap_scan_bus(struct work_struct *unused) |
| 1791 | { | 1792 | { |
| @@ -20,7 +20,7 @@ static void __ap_flush_queue(struct ap_queue *aq); · 19 unmodified lines | |||
| 20 | 20 | ||
| 21 | /** | 21 | /** |
| 22 | * ap_queue_enable_irq(): Enable interrupt support on this AP queue. | 22 | * ap_queue_enable_irq(): Enable interrupt support on this AP queue. |
| 23 | * @qid: The AP queue number | 23 | * @aq: The AP queue |
| 24 | * @ind: the notification indicator byte | 24 | * @ind: the notification indicator byte |
| 25 | * | 25 | * |
| 26 | * Enables interruption on AP queue via ap_aqic(). Based on the return | 26 | * Enables interruption on AP queue via ap_aqic(). Based on the return |
| @@ -311,7 +311,7 @@ static enum ap_sm_wait ap_sm_read_write(struct ap_queue *aq) · 284 unmodified lines | |||
| 311 | 311 | ||
| 312 | /** | 312 | /** |
| 313 | * ap_sm_reset(): Reset an AP queue. | 313 | * ap_sm_reset(): Reset an AP queue. |
| 314 | * @qid: The AP queue number | 314 | * @aq: The AP queue |
| 315 | * | 315 | * |
| 316 | * Submit the Reset command to an AP queue. | 316 | * Submit the Reset command to an AP queue. |
| 317 | */ | 317 | */ |
| @@ -858,7 +858,6 @@ struct qeth_card { · 857 unmodified lines | |||
| 858 | struct napi_struct napi; | 858 | struct napi_struct napi; |
| 859 | struct qeth_rx rx; | 859 | struct qeth_rx rx; |
| 860 | struct delayed_work buffer_reclaim_work; | 860 | struct delayed_work buffer_reclaim_work; |
| 861 | struct work_struct close_dev_work; | ||
| 862 | }; | 861 | }; |
| 863 | 862 | ||
| 864 | static inline bool qeth_card_hw_is_reachable(struct qeth_card *card) | 863 | static inline bool qeth_card_hw_is_reachable(struct qeth_card *card) |
| @@ -70,15 +70,6 @@ static void qeth_issue_next_read_cb(struct qeth_card *card, · 69 unmodified lines | |||
| 70 | static int qeth_qdio_establish(struct qeth_card *); | 70 | static int qeth_qdio_establish(struct qeth_card *); |
| 71 | static void qeth_free_qdio_queues(struct qeth_card *card); | 71 | static void qeth_free_qdio_queues(struct qeth_card *card); |
| 72 | 72 | ||
| 73 | static void qeth_close_dev_handler(struct work_struct *work) | ||
| 74 | { | ||
| 75 | struct qeth_card *card; | ||
| 76 | |||
| 77 | card = container_of(work, struct qeth_card, close_dev_work); | ||
| 78 | QETH_CARD_TEXT(card, 2, "cldevhdl"); | ||
| 79 | ccwgroup_set_offline(card->gdev); | ||
| 80 | } | ||
| 81 | |||
| 82 | static const char *qeth_get_cardname(struct qeth_card *card) | 73 | static const char *qeth_get_cardname(struct qeth_card *card) |
| 83 | { | 74 | { |
| 84 | if (IS_VM_NIC(card)) { | 75 | if (IS_VM_NIC(card)) { |
| @@ -202,6 +193,9 @@ static void qeth_clear_working_pool_list(struct qeth_card *card) · 117 unmodified lines | |||
| 202 | &card->qdio.in_buf_pool.entry_list, list) | 193 | &card->qdio.in_buf_pool.entry_list, list) |
| 203 | list_del(&pool_entry->list); | 194 | list_del(&pool_entry->list); |
| 204 | 195 | ||
| 196 | if (!queue) | ||
| 197 | return; | ||
| 198 | |||
| 205 | for (i = 0; i < ARRAY_SIZE(queue->bufs); i++) | 199 | for (i = 0; i < ARRAY_SIZE(queue->bufs); i++) |
| 206 | queue->bufs[i].pool_entry = NULL; | 200 | queue->bufs[i].pool_entry = NULL; |
| 207 | } | 201 | } |
| @@ -792,10 +786,12 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, · 584 unmodified lines | |||
| 792 | case IPA_CMD_STOPLAN: | 786 | case IPA_CMD_STOPLAN: |
| 793 | if (cmd->hdr.return_code == IPA_RC_VEPA_TO_VEB_TRANSITION) { | 787 | if (cmd->hdr.return_code == IPA_RC_VEPA_TO_VEB_TRANSITION) { |
| 794 | dev_err(&card->gdev->dev, | 788 | dev_err(&card->gdev->dev, |
| 795 | "Interface %s is down because the adjacent port is no longer in reflective relay mode\n", | 789 | "Adjacent port of interface %s is no longer in reflective relay mode, trigger recovery\n", |
| 796 | netdev_name(card->dev)); | 790 | netdev_name(card->dev)); |
| 797 | schedule_work(&card->close_dev_work); | 791 | /* Set offline, then probably fail to set online: */ |
| 792 | qeth_schedule_recovery(card); | ||
| 798 | } else { | 793 | } else { |
| 794 | /* stay online for subsequent STARTLAN */ | ||
| 799 | dev_warn(&card->gdev->dev, | 795 | dev_warn(&card->gdev->dev, |
| 800 | "The link for interface %s on CHPID 0x%X failed\n", | 796 | "The link for interface %s on CHPID 0x%X failed\n", |
| 801 | netdev_name(card->dev), card->info.chpid); | 797 | netdev_name(card->dev), card->info.chpid); |
| @@ -1537,7 +1533,6 @@ static void qeth_setup_card(struct qeth_card *card) · 735 unmodified lines | |||
| 1537 | INIT_LIST_HEAD(&card->ipato.entries); | 1533 | INIT_LIST_HEAD(&card->ipato.entries); |
| 1538 | qeth_init_qdio_info(card); | 1534 | qeth_init_qdio_info(card); |
| 1539 | INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work); | 1535 | INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work); |
| 1540 | INIT_WORK(&card->close_dev_work, qeth_close_dev_handler); | ||
| 1541 | hash_init(card->rx_mode_addrs); | 1536 | hash_init(card->rx_mode_addrs); |
| 1542 | hash_init(card->local_addrs4); | 1537 | hash_init(card->local_addrs4); |
| 1543 | hash_init(card->local_addrs6); | 1538 | hash_init(card->local_addrs6); |
| @@ -5519,7 +5514,8 @@ static int qeth_do_reset(void *data) · 3975 unmodified lines | |||
| 5519 | dev_info(&card->gdev->dev, | 5514 | dev_info(&card->gdev->dev, |
| 5520 | "Device successfully recovered!\n"); | 5515 | "Device successfully recovered!\n"); |
| 5521 | } else { | 5516 | } else { |
| 5522 | ccwgroup_set_offline(card->gdev); | 5517 | qeth_set_offline(card, disc, true); |
| 5518 | ccwgroup_set_offline(card->gdev, false); | ||
| 5523 | dev_warn(&card->gdev->dev, | 5519 | dev_warn(&card->gdev->dev, |
| 5524 | "The qeth device driver failed to recover an error on the device\n"); | 5520 | "The qeth device driver failed to recover an error on the device\n"); |
| 5525 | } | 5521 | } |
| @@ -2307,7 +2307,6 @@ static void qeth_l2_remove_device(struct ccwgroup_device *gdev) · 2306 unmodified lines | |||
| 2307 | if (gdev->state == CCWGROUP_ONLINE) | 2307 | if (gdev->state == CCWGROUP_ONLINE) |
| 2308 | qeth_set_offline(card, card->discipline, false); | 2308 | qeth_set_offline(card, card->discipline, false); |
| 2309 | 2309 | ||
| 2310 | cancel_work_sync(&card->close_dev_work); | ||
| 2311 | if (card->dev->reg_state == NETREG_REGISTERED) { | 2310 | if (card->dev->reg_state == NETREG_REGISTERED) { |
| 2312 | priv = netdev_priv(card->dev); | 2311 | priv = netdev_priv(card->dev); |
| 2313 | if (priv->brport_features & BR_LEARNING_SYNC) { | 2312 | if (priv->brport_features & BR_LEARNING_SYNC) { |
| @@ -1969,7 +1969,6 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) · 1968 unmodified lines | |||
| 1969 | if (cgdev->state == CCWGROUP_ONLINE) | 1969 | if (cgdev->state == CCWGROUP_ONLINE) |
| 1970 | qeth_set_offline(card, card->discipline, false); | 1970 | qeth_set_offline(card, card->discipline, false); |
| 1971 | 1971 | ||
| 1972 | cancel_work_sync(&card->close_dev_work); | ||
| 1973 | if (card->dev->reg_state == NETREG_REGISTERED) | 1972 | if (card->dev->reg_state == NETREG_REGISTERED) |
| 1974 | unregister_netdev(card->dev); | 1973 | unregister_netdev(card->dev); |
| 1975 | 1974 | ||
| @@ -600,6 +600,12 @@ static int rockchip_spi_transfer_one( · 599 unmodified lines | |||
| 600 | int ret; | 600 | int ret; |
| 601 | bool use_dma; | 601 | bool use_dma; |
| 602 | 602 | ||
| 603 | /* Zero length transfers won't trigger an interrupt on completion */ | ||
| 604 | if (!xfer->len) { | ||
| 605 | spi_finalize_current_transfer(ctlr); | ||
| 606 | return 1; | ||
| 607 | } | ||
| 608 | |||
| 603 | WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && | 609 | WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && |
| 604 | (readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY)); | 610 | (readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY)); |
| 605 | 611 | ||
| @@ -204,9 +204,6 @@ struct tegra_slink_data { · 203 unmodified lines | |||
| 204 | struct dma_async_tx_descriptor *tx_dma_desc; | 204 | struct dma_async_tx_descriptor *tx_dma_desc; |
| 205 | }; | 205 | }; |
| 206 | 206 | ||
| 207 | static int tegra_slink_runtime_suspend(struct device *dev); | ||
| 208 | static int tegra_slink_runtime_resume(struct device *dev); | ||
| 209 | |||
| 210 | static inline u32 tegra_slink_readl(struct tegra_slink_data *tspi, | 207 | static inline u32 tegra_slink_readl(struct tegra_slink_data *tspi, |
| 211 | unsigned long reg) | 208 | unsigned long reg) |
| 212 | { | 209 | { |
| @@ -1185,6 +1182,7 @@ static int tegra_slink_resume(struct device *dev) · 972 unmodified lines | |||
| 1185 | } | 1182 | } |
| 1186 | #endif | 1183 | #endif |
| 1187 | 1184 | ||
| 1185 | #ifdef CONFIG_PM | ||
| 1188 | static int tegra_slink_runtime_suspend(struct device *dev) | 1186 | static int tegra_slink_runtime_suspend(struct device *dev) |
| 1189 | { | 1187 | { |
| 1190 | struct spi_master *master = dev_get_drvdata(dev); | 1188 | struct spi_master *master = dev_get_drvdata(dev); |
| @@ -1210,6 +1208,7 @@ static int tegra_slink_runtime_resume(struct device *dev) · 19 unmodified lines | |||
| 1210 | } | 1208 | } |
| 1211 | return 0; | 1209 | return 0; |
| 1212 | } | 1210 | } |
| 1211 | #endif /* CONFIG_PM */ | ||
| 1213 | 1212 | ||
| 1214 | static const struct dev_pm_ops slink_pm_ops = { | 1213 | static const struct dev_pm_ops slink_pm_ops = { |
| 1215 | SET_RUNTIME_PM_OPS(tegra_slink_runtime_suspend, | 1214 | SET_RUNTIME_PM_OPS(tegra_slink_runtime_suspend, |
| @@ -58,10 +58,6 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf) · 57 unmodified lines | |||
| 58 | const struct spi_device *spi = to_spi_device(dev); | 58 | const struct spi_device *spi = to_spi_device(dev); |
| 59 | int len; | 59 | int len; |
| 60 | 60 | ||
| 61 | len = of_device_modalias(dev, buf, PAGE_SIZE); | ||
| 62 | if (len != -ENODEV) | ||
| 63 | return len; | ||
| 64 | |||
| 65 | len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); | 61 | len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); |
| 66 | if (len != -ENODEV) | 62 | if (len != -ENODEV) |
| 67 | return len; | 63 | return len; |
| @@ -367,10 +363,6 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) · 299 unmodified lines | |||
| 367 | const struct spi_device *spi = to_spi_device(dev); | 363 | const struct spi_device *spi = to_spi_device(dev); |
| 368 | int rc; | 364 | int rc; |
| 369 | 365 | ||
| 370 | rc = of_device_uevent_modalias(dev, env); | ||
| 371 | if (rc != -ENODEV) | ||
| 372 | return rc; | ||
| 373 | |||
| 374 | rc = acpi_device_uevent_modalias(dev, env); | 366 | rc = acpi_device_uevent_modalias(dev, env); |
| 375 | if (rc != -ENODEV) | 367 | if (rc != -ENODEV) |
| 376 | return rc; | 368 | return rc; |
| @@ -582,7 +582,9 @@ config FB_HP300 · 581 unmodified lines | |||
| 582 | 582 | ||
| 583 | config FB_TGA | 583 | config FB_TGA |
| 584 | tristate "TGA/SFB+ framebuffer support" | 584 | tristate "TGA/SFB+ framebuffer support" |
| 585 | depends on FB && (ALPHA || TC) | 585 | depends on FB |
| 586 | depends on PCI || TC | ||
| 587 | depends on ALPHA || TC | ||
| 586 | select FB_CFB_FILLRECT | 588 | select FB_CFB_FILLRECT |
| 587 | select FB_CFB_COPYAREA | 589 | select FB_CFB_COPYAREA |
| 588 | select FB_CFB_IMAGEBLIT | 590 | select FB_CFB_IMAGEBLIT |
| @@ -214,7 +214,7 @@ config XEN_PVCALLS_FRONTEND · 213 unmodified lines | |||
| 214 | implements them. | 214 | implements them. |
| 215 | 215 | ||
| 216 | config XEN_PVCALLS_BACKEND | 216 | config XEN_PVCALLS_BACKEND |
| 217 | bool "XEN PV Calls backend driver" | 217 | tristate "XEN PV Calls backend driver" |
| 218 | depends on INET && XEN && XEN_BACKEND | 218 | depends on INET && XEN && XEN_BACKEND |
| 219 | help | 219 | help |
| 220 | Experimental backend for the Xen PV Calls protocol | 220 | Experimental backend for the Xen PV Calls protocol |
| @@ -43,6 +43,8 @@ · 42 unmodified lines | |||
| 43 | #include <linux/sched.h> | 43 | #include <linux/sched.h> |
| 44 | #include <linux/cred.h> | 44 | #include <linux/cred.h> |
| 45 | #include <linux/errno.h> | 45 | #include <linux/errno.h> |
| 46 | #include <linux/freezer.h> | ||
| 47 | #include <linux/kthread.h> | ||
| 46 | #include <linux/mm.h> | 48 | #include <linux/mm.h> |
| 47 | #include <linux/memblock.h> | 49 | #include <linux/memblock.h> |
| 48 | #include <linux/pagemap.h> | 50 | #include <linux/pagemap.h> |
| @@ -115,7 +117,7 @@ static struct ctl_table xen_root[] = { · 66 unmodified lines | |||
| 115 | #define EXTENT_ORDER (fls(XEN_PFN_PER_PAGE) - 1) | 117 | #define EXTENT_ORDER (fls(XEN_PFN_PER_PAGE) - 1) |
| 116 | 118 | ||
| 117 | /* | 119 | /* |
| 118 | * balloon_process() state: | 120 | * balloon_thread() state: |
| 119 | * | 121 | * |
| 120 | * BP_DONE: done or nothing to do, | 122 | * BP_DONE: done or nothing to do, |
| 121 | * BP_WAIT: wait to be rescheduled, | 123 | * BP_WAIT: wait to be rescheduled, |
| @@ -130,6 +132,8 @@ enum bp_state { · 8 unmodified lines | |||
| 130 | BP_ECANCELED | 132 | BP_ECANCELED |
| 131 | }; | 133 | }; |
| 132 | 134 | ||
| 135 | /* Main waiting point for xen-balloon thread. */ | ||
| 136 | static DECLARE_WAIT_QUEUE_HEAD(balloon_thread_wq); | ||
| 133 | 137 | ||
| 134 | static DEFINE_MUTEX(balloon_mutex); | 138 | static DEFINE_MUTEX(balloon_mutex); |
| 135 | 139 | ||
| @@ -144,10 +148,6 @@ static xen_pfn_t frame_list[PAGE_SIZE / sizeof(xen_pfn_t)]; · 8 unmodified lines | |||
| 144 | static LIST_HEAD(ballooned_pages); | 148 | static LIST_HEAD(ballooned_pages); |
| 145 | static DECLARE_WAIT_QUEUE_HEAD(balloon_wq); | 149 | static DECLARE_WAIT_QUEUE_HEAD(balloon_wq); |
| 146 | 150 | ||
| 147 | /* Main work function, always executed in process context. */ | ||
| 148 | static void balloon_process(struct work_struct *work); | ||
| 149 | static DECLARE_DELAYED_WORK(balloon_worker, balloon_process); | ||
| 150 | |||
| 151 | /* When ballooning out (allocating memory to return to Xen) we don't really | 151 | /* When ballooning out (allocating memory to return to Xen) we don't really |
| 152 | want the kernel to try too hard since that can trigger the oom killer. */ | 152 | want the kernel to try too hard since that can trigger the oom killer. */ |
| 153 | #define GFP_BALLOON \ | 153 | #define GFP_BALLOON \ |
| @@ -366,7 +366,7 @@ static void xen_online_page(struct page *page, unsigned int order) · 212 unmodified lines | |||
| 366 | static int xen_memory_notifier(struct notifier_block *nb, unsigned long val, void *v) | 366 | static int xen_memory_notifier(struct notifier_block *nb, unsigned long val, void *v) |
| 367 | { | 367 | { |
| 368 | if (val == MEM_ONLINE) | 368 | if (val == MEM_ONLINE) |
| 369 | schedule_delayed_work(&balloon_worker, 0); | 369 | wake_up(&balloon_thread_wq); |
| 370 | 370 | ||
| 371 | return NOTIFY_OK; | 371 | return NOTIFY_OK; |
| 372 | } | 372 | } |
| @@ -491,18 +491,43 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) · 118 unmodified lines | |||
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | /* | 493 | /* |
| 494 | * As this is a work item it is guaranteed to run as a single instance only. | 494 | * Stop waiting if either state is not BP_EAGAIN and ballooning action is |
| 495 | * needed, or if the credit has changed while state is BP_EAGAIN. | ||
| 496 | */ | ||
| 497 | static bool balloon_thread_cond(enum bp_state state, long credit) | ||
| 498 | { | ||
| 499 | if (state != BP_EAGAIN) | ||
| 500 | credit = 0; | ||
| 501 | |||
| 502 | return current_credit() != credit || kthread_should_stop(); | ||
| 503 | } | ||
| 504 | |||
| 505 | /* | ||
| 506 | * As this is a kthread it is guaranteed to run as a single instance only. | ||
| 495 | * We may of course race updates of the target counts (which are protected | 507 | * We may of course race updates of the target counts (which are protected |
| 496 | * by the balloon lock), or with changes to the Xen hard limit, but we will | 508 | * by the balloon lock), or with changes to the Xen hard limit, but we will |
| 497 | * recover from these in time. | 509 | * recover from these in time. |
| 498 | */ | 510 | */ |
| 499 | static void balloon_process(struct work_struct *work) | 511 | static int balloon_thread(void *unused) |
| 500 | { | 512 | { |
| 501 | enum bp_state state = BP_DONE; | 513 | enum bp_state state = BP_DONE; |
| 502 | long credit; | 514 | long credit; |
| 515 | unsigned long timeout; | ||
| 516 | |||
| 517 | set_freezable(); | ||
| 518 | for (;;) { | ||
| 519 | if (state == BP_EAGAIN) | ||
| 520 | timeout = balloon_stats.schedule_delay * HZ; | ||
| 521 | else | ||
| 522 | timeout = 3600 * HZ; | ||
| 523 | credit = current_credit(); | ||
| 503 | 524 | ||
| 525 | wait_event_interruptible_timeout(balloon_thread_wq, | ||
| 526 | balloon_thread_cond(state, credit), timeout); | ||
| 527 | |||
| 528 | if (kthread_should_stop()) | ||
| 529 | return 0; | ||
| 504 | 530 | ||
| 505 | do { | ||
| 506 | mutex_lock(&balloon_mutex); | 531 | mutex_lock(&balloon_mutex); |
| 507 | 532 | ||
| 508 | credit = current_credit(); | 533 | credit = current_credit(); |
| @@ -529,12 +554,7 @@ static void balloon_process(struct work_struct *work) · 20 unmodified lines | |||
| 529 | mutex_unlock(&balloon_mutex); | 554 | mutex_unlock(&balloon_mutex); |
| 530 | 555 | ||
| 531 | cond_resched(); | 556 | cond_resched(); |
| 532 | 557 | } | |
| 533 | } while (credit && state == BP_DONE); | ||
| 534 | |||
| 535 | /* Schedule more work if there is some still to be done. */ | ||
| 536 | if (state == BP_EAGAIN) | ||
| 537 | schedule_delayed_work(&balloon_worker, balloon_stats.schedule_delay * HZ); | ||
| 538 | } | 558 | } |
| 539 | 559 | ||
| 540 | /* Resets the Xen limit, sets new target, and kicks off processing. */ | 560 | /* Resets the Xen limit, sets new target, and kicks off processing. */ |
| @@ -542,7 +562,7 @@ void balloon_set_new_target(unsigned long target) · 1 unmodified line | |||
| 542 | { | 562 | { |
| 543 | /* No need for lock. Not read-modify-write updates. */ | 563 | /* No need for lock. Not read-modify-write updates. */ |
| 544 | balloon_stats.target_pages = target; | 564 | balloon_stats.target_pages = target; |
| 545 | schedule_delayed_work(&balloon_worker, 0); | 565 | wake_up(&balloon_thread_wq); |
| 546 | } | 566 | } |
| 547 | EXPORT_SYMBOL_GPL(balloon_set_new_target); | 567 | EXPORT_SYMBOL_GPL(balloon_set_new_target); |
| 548 | 568 | ||
| @@ -647,7 +667,7 @@ void free_xenballooned_pages(int nr_pages, struct page **pages) · 98 unmodified lines | |||
| 647 | 667 | ||
| 648 | /* The balloon may be too large now. Shrink it if needed. */ | 668 | /* The balloon may be too large now. Shrink it if needed. */ |
| 649 | if (current_credit()) | 669 | if (current_credit()) |
| 650 | schedule_delayed_work(&balloon_worker, 0); | 670 | wake_up(&balloon_thread_wq); |
| 651 | 671 | ||
| 652 | mutex_unlock(&balloon_mutex); | 672 | mutex_unlock(&balloon_mutex); |
| 653 | } | 673 | } |
| @@ -679,6 +699,8 @@ static void __init balloon_add_region(unsigned long start_pfn, · 25 unmodified lines | |||
| 679 | 699 | ||
| 680 | static int __init balloon_init(void) | 700 | static int __init balloon_init(void) |
| 681 | { | 701 | { |
| 702 | struct task_struct *task; | ||
| 703 | |||
| 682 | if (!xen_domain()) | 704 | if (!xen_domain()) |
| 683 | return -ENODEV; | 705 | return -ENODEV; |
| 684 | 706 | ||
| @@ -722,6 +744,12 @@ static int __init balloon_init(void) · 37 unmodified lines | |||
| 722 | } | 744 | } |
| 723 | #endif | 745 | #endif |
| 724 | 746 | ||
| 747 | task = kthread_run(balloon_thread, NULL, "xen-balloon"); | ||
| 748 | if (IS_ERR(task)) { | ||
| 749 | pr_err("xen-balloon thread could not be started, ballooning will not work!\n"); | ||
| 750 | return PTR_ERR(task); | ||
| 751 | } | ||
| 752 | |||
| 725 | /* Init the xen-balloon driver. */ | 753 | /* Init the xen-balloon driver. */ |
| 726 | xen_balloon_init(); | 754 | xen_balloon_init(); |
| 727 | 755 | ||
| @@ -106,27 +106,26 @@ static int is_xen_swiotlb_buffer(struct device *dev, dma_addr_t dma_addr) · 105 unmodified lines | |||
| 106 | 106 | ||
| 107 | static int xen_swiotlb_fixup(void *buf, unsigned long nslabs) | 107 | static int xen_swiotlb_fixup(void *buf, unsigned long nslabs) |
| 108 | { | 108 | { |
| 109 | int i, rc; | 109 | int rc; |
| 110 | int dma_bits; | 110 | unsigned int order = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT); |
| 111 | unsigned int i, dma_bits = order + PAGE_SHIFT; | ||
| 111 | dma_addr_t dma_handle; | 112 | dma_addr_t dma_handle; |
| 112 | phys_addr_t p = virt_to_phys(buf); | 113 | phys_addr_t p = virt_to_phys(buf); |
| 113 | 114 | ||
| 114 | dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT; | 115 | BUILD_BUG_ON(IO_TLB_SEGSIZE & (IO_TLB_SEGSIZE - 1)); |
| 116 | BUG_ON(nslabs % IO_TLB_SEGSIZE); | ||
| 115 | 117 | ||
| 116 | i = 0; | 118 | i = 0; |
| 117 | do { | 119 | do { |
| 118 | int slabs = min(nslabs - i, (unsigned long)IO_TLB_SEGSIZE); | ||
| 119 | |||
| 120 | do { | 120 | do { |
| 121 | rc = xen_create_contiguous_region( | 121 | rc = xen_create_contiguous_region( |
| 122 | p + (i << IO_TLB_SHIFT), | 122 | p + (i << IO_TLB_SHIFT), order, |
| 123 | get_order(slabs << IO_TLB_SHIFT), | ||
| 124 | dma_bits, &dma_handle); | 123 | dma_bits, &dma_handle); |
| 125 | } while (rc && dma_bits++ < MAX_DMA_BITS); | 124 | } while (rc && dma_bits++ < MAX_DMA_BITS); |
| 126 | if (rc) | 125 | if (rc) |
| 127 | return rc; | 126 | return rc; |
| 128 | 127 | ||
| 129 | i += slabs; | 128 | i += IO_TLB_SEGSIZE; |
| 130 | } while (i < nslabs); | 129 | } while (i < nslabs); |
| 131 | return 0; | 130 | return 0; |
| 132 | } | 131 | } |
| @@ -153,9 +152,7 @@ static const char *xen_swiotlb_error(enum xen_swiotlb_err err) · 20 unmodified lines | |||
| 153 | return ""; | 152 | return ""; |
| 154 | } | 153 | } |
| 155 | 154 | ||
| 156 | #define DEFAULT_NSLABS ALIGN(SZ_64M >> IO_TLB_SHIFT, IO_TLB_SEGSIZE) | 155 | int xen_swiotlb_init(void) |
| 157 | |||
| 158 | int __ref xen_swiotlb_init(void) | ||
| 159 | { | 156 | { |
| 160 | enum xen_swiotlb_err m_ret = XEN_SWIOTLB_UNKNOWN; | 157 | enum xen_swiotlb_err m_ret = XEN_SWIOTLB_UNKNOWN; |
| 161 | unsigned long bytes = swiotlb_size_or_default(); | 158 | unsigned long bytes = swiotlb_size_or_default(); |
| @@ -185,7 +182,7 @@ retry: · 23 unmodified lines | |||
| 185 | order--; | 182 | order--; |
| 186 | } | 183 | } |
| 187 | if (!start) | 184 | if (!start) |
| 188 | goto error; | 185 | goto exit; |
| 189 | if (order != get_order(bytes)) { | 186 | if (order != get_order(bytes)) { |
| 190 | pr_warn("Warning: only able to allocate %ld MB for software IO TLB\n", | 187 | pr_warn("Warning: only able to allocate %ld MB for software IO TLB\n", |
| 191 | (PAGE_SIZE << order) >> 20); | 188 | (PAGE_SIZE << order) >> 20); |
| @@ -208,15 +205,15 @@ retry: · 16 unmodified lines | |||
| 208 | swiotlb_set_max_segment(PAGE_SIZE); | 205 | swiotlb_set_max_segment(PAGE_SIZE); |
| 209 | return 0; | 206 | return 0; |
| 210 | error: | 207 | error: |
| 211 | if (repeat--) { | 208 | if (nslabs > 1024 && repeat--) { |
| 212 | /* Min is 2MB */ | 209 | /* Min is 2MB */ |
| 213 | nslabs = max(1024UL, (nslabs >> 1)); | 210 | nslabs = max(1024UL, ALIGN(nslabs >> 1, IO_TLB_SEGSIZE)); |
| 214 | pr_info("Lowering to %luMB\n", | 211 | bytes = nslabs << IO_TLB_SHIFT; |
| 215 | (nslabs << IO_TLB_SHIFT) >> 20); | 212 | pr_info("Lowering to %luMB\n", bytes >> 20); |
| 216 | goto retry; | 213 | goto retry; |
| 217 | } | 214 | } |
| 215 | exit: | ||
| 218 | pr_err("%s (rc:%d)\n", xen_swiotlb_error(m_ret), rc); | 216 | pr_err("%s (rc:%d)\n", xen_swiotlb_error(m_ret), rc); |
| 219 | free_pages((unsigned long)start, order); | ||
| 220 | return rc; | 217 | return rc; |
| 221 | } | 218 | } |
| 222 | 219 | ||
| @@ -244,9 +241,9 @@ retry: · 21 unmodified lines | |||
| 244 | rc = xen_swiotlb_fixup(start, nslabs); | 241 | rc = xen_swiotlb_fixup(start, nslabs); |
| 245 | if (rc) { | 242 | if (rc) { |
| 246 | memblock_free(__pa(start), PAGE_ALIGN(bytes)); | 243 | memblock_free(__pa(start), PAGE_ALIGN(bytes)); |
| 247 | if (repeat--) { | 244 | if (nslabs > 1024 && repeat--) { |
| 248 | /* Min is 2MB */ | 245 | /* Min is 2MB */ |
| 249 | nslabs = max(1024UL, (nslabs >> 1)); | 246 | nslabs = max(1024UL, ALIGN(nslabs >> 1, IO_TLB_SEGSIZE)); |
| 250 | bytes = nslabs << IO_TLB_SHIFT; | 247 | bytes = nslabs << IO_TLB_SHIFT; |
| 251 | pr_info("Lowering to %luMB\n", bytes >> 20); | 248 | pr_info("Lowering to %luMB\n", bytes >> 20); |
| 252 | goto retry; | 249 | goto retry; |
| @@ -254,7 +251,7 @@ retry: · 1 unmodified line | |||
| 254 | panic("%s (rc:%d)", xen_swiotlb_error(XEN_SWIOTLB_EFIXUP), rc); | 251 | panic("%s (rc:%d)", xen_swiotlb_error(XEN_SWIOTLB_EFIXUP), rc); |
| 255 | } | 252 | } |
| 256 | 253 | ||
| 257 | if (swiotlb_init_with_tbl(start, nslabs, false)) | 254 | if (swiotlb_init_with_tbl(start, nslabs, true)) |
| 258 | panic("Cannot allocate SWIOTLB buffer"); | 255 | panic("Cannot allocate SWIOTLB buffer"); |
| 259 | swiotlb_set_max_segment(PAGE_SIZE); | 256 | swiotlb_set_max_segment(PAGE_SIZE); |
| 260 | } | 257 | } |
| @@ -20,6 +20,37 @@ · 19 unmodified lines | |||
| 20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
| 21 | #include "internal.h" | 21 | #include "internal.h" |
| 22 | 22 | ||
| 23 | /* | ||
| 24 | * Handle invalidation of an mmap'd file. We invalidate all the PTEs referring | ||
| 25 | * to the pages in this file's pagecache, forcing the kernel to go through | ||
| 26 | * ->fault() or ->page_mkwrite() - at which point we can handle invalidation | ||
| 27 | * more fully. | ||
| 28 | */ | ||
| 29 | void afs_invalidate_mmap_work(struct work_struct *work) | ||
| 30 | { | ||
| 31 | struct afs_vnode *vnode = container_of(work, struct afs_vnode, cb_work); | ||
| 32 | |||
| 33 | unmap_mapping_pages(vnode->vfs_inode.i_mapping, 0, 0, false); | ||
| 34 | } | ||
| 35 | |||
| 36 | void afs_server_init_callback_work(struct work_struct *work) | ||
| 37 | { | ||
| 38 | struct afs_server *server = container_of(work, struct afs_server, initcb_work); | ||
| 39 | struct afs_vnode *vnode; | ||
| 40 | struct afs_cell *cell = server->cell; | ||
| 41 | |||
| 42 | down_read(&cell->fs_open_mmaps_lock); | ||
| 43 | |||
| 44 | list_for_each_entry(vnode, &cell->fs_open_mmaps, cb_mmap_link) { | ||
| 45 | if (vnode->cb_server == server) { | ||
| 46 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | ||
| 47 | queue_work(system_unbound_wq, &vnode->cb_work); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | up_read(&cell->fs_open_mmaps_lock); | ||
| 52 | } | ||
| 53 | |||
| 23 | /* | 54 | /* |
| 24 | * Allow the fileserver to request callback state (re-)initialisation. | 55 | * Allow the fileserver to request callback state (re-)initialisation. |
| 25 | * Unfortunately, UUIDs are not guaranteed unique. | 56 | * Unfortunately, UUIDs are not guaranteed unique. |
| @@ -29,8 +60,11 @@ void afs_init_callback_state(struct afs_server *server) · 3 unmodified lines | |||
| 29 | rcu_read_lock(); | 60 | rcu_read_lock(); |
| 30 | do { | 61 | do { |
| 31 | server->cb_s_break++; | 62 | server->cb_s_break++; |
| 32 | server = rcu_dereference(server->uuid_next); | 63 | atomic_inc(&server->cell->fs_s_break); |
| 33 | } while (0); | 64 | if (!list_empty(&server->cell->fs_open_mmaps)) |
| 65 | queue_work(system_unbound_wq, &server->initcb_work); | ||
| 66 | |||
| 67 | } while ((server = rcu_dereference(server->uuid_next))); | ||
| 34 | rcu_read_unlock(); | 68 | rcu_read_unlock(); |
| 35 | } | 69 | } |
| 36 | 70 | ||
| @@ -44,11 +78,17 @@ void __afs_break_callback(struct afs_vnode *vnode, enum afs_cb_break_reason reas · 7 unmodified lines | |||
| 44 | clear_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); | 78 | clear_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); |
| 45 | if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { | 79 | if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { |
| 46 | vnode->cb_break++; | 80 | vnode->cb_break++; |
| 81 | vnode->cb_v_break = vnode->volume->cb_v_break; | ||
| 47 | afs_clear_permits(vnode); | 82 | afs_clear_permits(vnode); |
| 48 | 83 | ||
| 49 | if (vnode->lock_state == AFS_VNODE_LOCK_WAITING_FOR_CB) | 84 | if (vnode->lock_state == AFS_VNODE_LOCK_WAITING_FOR_CB) |
| 50 | afs_lock_may_be_available(vnode); | 85 | afs_lock_may_be_available(vnode); |
| 51 | 86 | ||
| 87 | if (reason != afs_cb_break_for_deleted && | ||
| 88 | vnode->status.type == AFS_FTYPE_FILE && | ||
| 89 | atomic_read(&vnode->cb_nr_mmap)) | ||
| 90 | queue_work(system_unbound_wq, &vnode->cb_work); | ||
| 91 | |||
| 52 | trace_afs_cb_break(&vnode->fid, vnode->cb_break, reason, true); | 92 | trace_afs_cb_break(&vnode->fid, vnode->cb_break, reason, true); |
| 53 | } else { | 93 | } else { |
| 54 | trace_afs_cb_break(&vnode->fid, vnode->cb_break, reason, false); | 94 | trace_afs_cb_break(&vnode->fid, vnode->cb_break, reason, false); |
| @@ -166,6 +166,8 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net, · 165 unmodified lines | |||
| 166 | seqlock_init(&cell->volume_lock); | 166 | seqlock_init(&cell->volume_lock); |
| 167 | cell->fs_servers = RB_ROOT; | 167 | cell->fs_servers = RB_ROOT; |
| 168 | seqlock_init(&cell->fs_lock); | 168 | seqlock_init(&cell->fs_lock); |
| 169 | INIT_LIST_HEAD(&cell->fs_open_mmaps); | ||
| 170 | init_rwsem(&cell->fs_open_mmaps_lock); | ||
| 169 | rwlock_init(&cell->vl_servers_lock); | 171 | rwlock_init(&cell->vl_servers_lock); |
| 170 | cell->flags = (1 << AFS_CELL_FL_CHECK_ALIAS); | 172 | cell->flags = (1 << AFS_CELL_FL_CHECK_ALIAS); |
| 171 | 173 | ||
| @@ -1077,9 +1077,9 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, · 1076 unmodified lines | |||
| 1077 | */ | 1077 | */ |
| 1078 | static int afs_d_revalidate_rcu(struct dentry *dentry) | 1078 | static int afs_d_revalidate_rcu(struct dentry *dentry) |
| 1079 | { | 1079 | { |
| 1080 | struct afs_vnode *dvnode, *vnode; | 1080 | struct afs_vnode *dvnode; |
| 1081 | struct dentry *parent; | 1081 | struct dentry *parent; |
| 1082 | struct inode *dir, *inode; | 1082 | struct inode *dir; |
| 1083 | long dir_version, de_version; | 1083 | long dir_version, de_version; |
| 1084 | 1084 | ||
| 1085 | _enter("%p", dentry); | 1085 | _enter("%p", dentry); |
| @@ -1109,18 +1109,6 @@ static int afs_d_revalidate_rcu(struct dentry *dentry) · 23 unmodified lines | |||
| 1109 | return -ECHILD; | 1109 | return -ECHILD; |
| 1110 | } | 1110 | } |
| 1111 | 1111 | ||
| 1112 | /* Check to see if the vnode referred to by the dentry still | ||
| 1113 | * has a callback. | ||
| 1114 | */ | ||
| 1115 | if (d_really_is_positive(dentry)) { | ||
| 1116 | inode = d_inode_rcu(dentry); | ||
| 1117 | if (inode) { | ||
| 1118 | vnode = AFS_FS_I(inode); | ||
| 1119 | if (!afs_check_validity(vnode)) | ||
| 1120 | return -ECHILD; | ||
| 1121 | } | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | return 1; /* Still valid */ | 1112 | return 1; /* Still valid */ |
| 1125 | } | 1113 | } |
| 1126 | 1114 | ||
| @@ -1156,17 +1144,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) · 29 unmodified lines | |||
| 1156 | if (IS_ERR(key)) | 1144 | if (IS_ERR(key)) |
| 1157 | key = NULL; | 1145 | key = NULL; |
| 1158 | 1146 | ||
| 1159 | if (d_really_is_positive(dentry)) { | 1147 | /* Hold the parent dentry so we can peer at it */ |
| 1160 | inode = d_inode(dentry); | ||
| 1161 | if (inode) { | ||
| 1162 | vnode = AFS_FS_I(inode); | ||
| 1163 | afs_validate(vnode, key); | ||
| 1164 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) | ||
| 1165 | goto out_bad; | ||
| 1166 | } | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | /* lock down the parent dentry so we can peer at it */ | ||
| 1170 | parent = dget_parent(dentry); | 1148 | parent = dget_parent(dentry); |
| 1171 | dir = AFS_FS_I(d_inode(parent)); | 1149 | dir = AFS_FS_I(d_inode(parent)); |
| 1172 | 1150 | ||
| @@ -1175,7 +1153,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) · 2 unmodified lines | |||
| 1175 | 1153 | ||
| 1176 | if (test_bit(AFS_VNODE_DELETED, &dir->flags)) { | 1154 | if (test_bit(AFS_VNODE_DELETED, &dir->flags)) { |
| 1177 | _debug("%pd: parent dir deleted", dentry); | 1155 | _debug("%pd: parent dir deleted", dentry); |
| 1178 | goto out_bad_parent; | 1156 | goto not_found; |
| 1179 | } | 1157 | } |
| 1180 | 1158 | ||
| 1181 | /* We only need to invalidate a dentry if the server's copy changed | 1159 | /* We only need to invalidate a dentry if the server's copy changed |
| @@ -1201,12 +1179,12 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) · 19 unmodified lines | |||
| 1201 | case 0: | 1179 | case 0: |
| 1202 | /* the filename maps to something */ | 1180 | /* the filename maps to something */ |
| 1203 | if (d_really_is_negative(dentry)) | 1181 | if (d_really_is_negative(dentry)) |
| 1204 | goto out_bad_parent; | 1182 | goto not_found; |
| 1205 | inode = d_inode(dentry); | 1183 | inode = d_inode(dentry); |
| 1206 | if (is_bad_inode(inode)) { | 1184 | if (is_bad_inode(inode)) { |
| 1207 | printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n", | 1185 | printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n", |
| 1208 | dentry); | 1186 | dentry); |
| 1209 | goto out_bad_parent; | 1187 | goto not_found; |
| 1210 | } | 1188 | } |
| 1211 | 1189 | ||
| 1212 | vnode = AFS_FS_I(inode); | 1190 | vnode = AFS_FS_I(inode); |
| @@ -1228,9 +1206,6 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) · 15 unmodified lines | |||
| 1228 | dentry, fid.unique, | 1206 | dentry, fid.unique, |
| 1229 | vnode->fid.unique, | 1207 | vnode->fid.unique, |
| 1230 | vnode->vfs_inode.i_generation); | 1208 | vnode->vfs_inode.i_generation); |
| 1231 | write_seqlock(&vnode->cb_lock); | ||
| 1232 | set_bit(AFS_VNODE_DELETED, &vnode->flags); | ||
| 1233 | write_sequnlock(&vnode->cb_lock); | ||
| 1234 | goto not_found; | 1209 | goto not_found; |
| 1235 | } | 1210 | } |
| 1236 | goto out_valid; | 1211 | goto out_valid; |
| @@ -1245,7 +1220,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) · 8 unmodified lines | |||
| 1245 | default: | 1220 | default: |
| 1246 | _debug("failed to iterate dir %pd: %d", | 1221 | _debug("failed to iterate dir %pd: %d", |
| 1247 | parent, ret); | 1222 | parent, ret); |
| 1248 | goto out_bad_parent; | 1223 | goto not_found; |
| 1249 | } | 1224 | } |
| 1250 | 1225 | ||
| 1251 | out_valid: | 1226 | out_valid: |
| @@ -1256,16 +1231,9 @@ out_valid_noupdate: · 4 unmodified lines | |||
| 1256 | _leave(" = 1 [valid]"); | 1231 | _leave(" = 1 [valid]"); |
| 1257 | return 1; | 1232 | return 1; |
| 1258 | 1233 | ||
| 1259 | /* the dirent, if it exists, now points to a different vnode */ | ||
| 1260 | not_found: | 1234 | not_found: |
| 1261 | spin_lock(&dentry->d_lock); | ||
| 1262 | dentry->d_flags |= DCACHE_NFSFS_RENAMED; | ||
| 1263 | spin_unlock(&dentry->d_lock); | ||
| 1264 | |||
| 1265 | out_bad_parent: | ||
| 1266 | _debug("dropping dentry %pd2", dentry); | 1235 | _debug("dropping dentry %pd2", dentry); |
| 1267 | dput(parent); | 1236 | dput(parent); |
| 1268 | out_bad: | ||
| 1269 | key_put(key); | 1237 | key_put(key); |
| 1270 | 1238 | ||
| 1271 | _leave(" = 0 [bad]"); | 1239 | _leave(" = 0 [bad]"); |
| @@ -1792,6 +1760,10 @@ static int afs_link(struct dentry *from, struct inode *dir, · 520 unmodified lines | |||
| 1792 | goto error; | 1760 | goto error; |
| 1793 | } | 1761 | } |
| 1794 | 1762 | ||
| 1763 | ret = afs_validate(vnode, op->key); | ||
| 1764 | if (ret < 0) | ||
| 1765 | goto error_op; | ||
| 1766 | |||
| 1795 | afs_op_set_vnode(op, 0, dvnode); | 1767 | afs_op_set_vnode(op, 0, dvnode); |
| 1796 | afs_op_set_vnode(op, 1, vnode); | 1768 | afs_op_set_vnode(op, 1, vnode); |
| 1797 | op->file[0].dv_delta = 1; | 1769 | op->file[0].dv_delta = 1; |
| @@ -1805,6 +1777,8 @@ static int afs_link(struct dentry *from, struct inode *dir, · 7 unmodified lines | |||
| 1805 | op->create.reason = afs_edit_dir_for_link; | 1777 | op->create.reason = afs_edit_dir_for_link; |
| 1806 | return afs_do_sync_operation(op); | 1778 | return afs_do_sync_operation(op); |
| 1807 | 1779 | ||
| 1780 | error_op: | ||
| 1781 | afs_put_operation(op); | ||
| 1808 | error: | 1782 | error: |
| 1809 | d_drop(dentry); | 1783 | d_drop(dentry); |
| 1810 | _leave(" = %d", ret); | 1784 | _leave(" = %d", ret); |
| @@ -1989,6 +1963,11 @@ static int afs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, · 178 unmodified lines | |||
| 1989 | if (IS_ERR(op)) | 1963 | if (IS_ERR(op)) |
| 1990 | return PTR_ERR(op); | 1964 | return PTR_ERR(op); |
| 1991 | 1965 | ||
| 1966 | ret = afs_validate(vnode, op->key); | ||
| 1967 | op->error = ret; | ||
| 1968 | if (ret < 0) | ||
| 1969 | goto error; | ||
| 1970 | |||
| 1992 | afs_op_set_vnode(op, 0, orig_dvnode); | 1971 | afs_op_set_vnode(op, 0, orig_dvnode); |
| 1993 | afs_op_set_vnode(op, 1, new_dvnode); /* May be same as orig_dvnode */ | 1972 | afs_op_set_vnode(op, 1, new_dvnode); /* May be same as orig_dvnode */ |
| 1994 | op->file[0].dv_delta = 1; | 1973 | op->file[0].dv_delta = 1; |
| @@ -263,7 +263,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode, · 262 unmodified lines | |||
| 263 | if (b == nr_blocks) { | 263 | if (b == nr_blocks) { |
| 264 | _debug("init %u", b); | 264 | _debug("init %u", b); |
| 265 | afs_edit_init_block(meta, block, b); | 265 | afs_edit_init_block(meta, block, b); |
| 266 | i_size_write(&vnode->vfs_inode, (b + 1) * AFS_DIR_BLOCK_SIZE); | 266 | afs_set_i_size(vnode, (b + 1) * AFS_DIR_BLOCK_SIZE); |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | /* Only lower dir pages have a counter in the header. */ | 269 | /* Only lower dir pages have a counter in the header. */ |
| @@ -296,7 +296,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode, · 26 unmodified lines | |||
| 296 | new_directory: | 296 | new_directory: |
| 297 | afs_edit_init_block(meta, meta, 0); | 297 | afs_edit_init_block(meta, meta, 0); |
| 298 | i_size = AFS_DIR_BLOCK_SIZE; | 298 | i_size = AFS_DIR_BLOCK_SIZE; |
| 299 | i_size_write(&vnode->vfs_inode, i_size); | 299 | afs_set_i_size(vnode, i_size); |
| 300 | slot = AFS_DIR_RESV_BLOCKS0; | 300 | slot = AFS_DIR_RESV_BLOCKS0; |
| 301 | page = page0; | 301 | page = page0; |
| 302 | block = meta; | 302 | block = meta; |
| @@ -24,12 +24,16 @@ static void afs_invalidatepage(struct page *page, unsigned int offset, · 23 unmodified lines | |||
| 24 | static int afs_releasepage(struct page *page, gfp_t gfp_flags); | 24 | static int afs_releasepage(struct page *page, gfp_t gfp_flags); |
| 25 | 25 | ||
| 26 | static void afs_readahead(struct readahead_control *ractl); | 26 | static void afs_readahead(struct readahead_control *ractl); |
| 27 | static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter); | ||
| 28 | static void afs_vm_open(struct vm_area_struct *area); | ||
| 29 | static void afs_vm_close(struct vm_area_struct *area); | ||
| 30 | static vm_fault_t afs_vm_map_pages(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff); | ||
| 27 | 31 | ||
| 28 | const struct file_operations afs_file_operations = { | 32 | const struct file_operations afs_file_operations = { |
| 29 | .open = afs_open, | 33 | .open = afs_open, |
| 30 | .release = afs_release, | 34 | .release = afs_release, |
| 31 | .llseek = generic_file_llseek, | 35 | .llseek = generic_file_llseek, |
| 32 | .read_iter = generic_file_read_iter, | 36 | .read_iter = afs_file_read_iter, |
| 33 | .write_iter = afs_file_write, | 37 | .write_iter = afs_file_write, |
| 34 | .mmap = afs_file_mmap, | 38 | .mmap = afs_file_mmap, |
| 35 | .splice_read = generic_file_splice_read, | 39 | .splice_read = generic_file_splice_read, |
| @@ -59,8 +63,10 @@ const struct address_space_operations afs_fs_aops = { · 23 unmodified lines | |||
| 59 | }; | 63 | }; |
| 60 | 64 | ||
| 61 | static const struct vm_operations_struct afs_vm_ops = { | 65 | static const struct vm_operations_struct afs_vm_ops = { |
| 66 | .open = afs_vm_open, | ||
| 67 | .close = afs_vm_close, | ||
| 62 | .fault = filemap_fault, | 68 | .fault = filemap_fault, |
| 63 | .map_pages = filemap_map_pages, | 69 | .map_pages = afs_vm_map_pages, |
| 64 | .page_mkwrite = afs_page_mkwrite, | 70 | .page_mkwrite = afs_page_mkwrite, |
| 65 | }; | 71 | }; |
| 66 | 72 | ||
| @@ -295,7 +301,7 @@ static void afs_req_issue_op(struct netfs_read_subrequest *subreq) · 228 unmodified lines | |||
| 295 | fsreq->subreq = subreq; | 301 | fsreq->subreq = subreq; |
| 296 | fsreq->pos = subreq->start + subreq->transferred; | 302 | fsreq->pos = subreq->start + subreq->transferred; |
| 297 | fsreq->len = subreq->len - subreq->transferred; | 303 | fsreq->len = subreq->len - subreq->transferred; |
| 298 | fsreq->key = subreq->rreq->netfs_priv; | 304 | fsreq->key = key_get(subreq->rreq->netfs_priv); |
| 299 | fsreq->vnode = vnode; | 305 | fsreq->vnode = vnode; |
| 300 | fsreq->iter = &fsreq->def_iter; | 306 | fsreq->iter = &fsreq->def_iter; |
| 301 | 307 | ||
| @@ -304,6 +310,7 @@ static void afs_req_issue_op(struct netfs_read_subrequest *subreq) · 2 unmodified lines | |||
| 304 | fsreq->pos, fsreq->len); | 310 | fsreq->pos, fsreq->len); |
| 305 | 311 | ||
| 306 | afs_fetch_data(fsreq->vnode, fsreq); | 312 | afs_fetch_data(fsreq->vnode, fsreq); |
| 313 | afs_put_read(fsreq); | ||
| 307 | } | 314 | } |
| 308 | 315 | ||
| 309 | static int afs_symlink_readpage(struct page *page) | 316 | static int afs_symlink_readpage(struct page *page) |
| @@ -490,15 +497,88 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags) · 180 unmodified lines | |||
| 490 | return 1; | 497 | return 1; |
| 491 | } | 498 | } |
| 492 | 499 | ||
| 500 | static void afs_add_open_mmap(struct afs_vnode *vnode) | ||
| 501 | { | ||
| 502 | if (atomic_inc_return(&vnode->cb_nr_mmap) == 1) { | ||
| 503 | down_write(&vnode->volume->cell->fs_open_mmaps_lock); | ||
| 504 | |||
| 505 | list_add_tail(&vnode->cb_mmap_link, | ||
| 506 | &vnode->volume->cell->fs_open_mmaps); | ||
| 507 | |||
| 508 | up_write(&vnode->volume->cell->fs_open_mmaps_lock); | ||
| 509 | } | ||
| 510 | } | ||
| 511 | |||
| 512 | static void afs_drop_open_mmap(struct afs_vnode *vnode) | ||
| 513 | { | ||
| 514 | if (!atomic_dec_and_test(&vnode->cb_nr_mmap)) | ||
| 515 | return; | ||
| 516 | |||
| 517 | down_write(&vnode->volume->cell->fs_open_mmaps_lock); | ||
| 518 | |||
| 519 | if (atomic_read(&vnode->cb_nr_mmap) == 0) | ||
| 520 | list_del_init(&vnode->cb_mmap_link); | ||
| 521 | |||
| 522 | up_write(&vnode->volume->cell->fs_open_mmaps_lock); | ||
| 523 | flush_work(&vnode->cb_work); | ||
| 524 | } | ||
| 525 | |||
| 493 | /* | 526 | /* |
| 494 | * Handle setting up a memory mapping on an AFS file. | 527 | * Handle setting up a memory mapping on an AFS file. |
| 495 | */ | 528 | */ |
| 496 | static int afs_file_mmap(struct file *file, struct vm_area_struct *vma) | 529 | static int afs_file_mmap(struct file *file, struct vm_area_struct *vma) |
| 497 | { | 530 | { |
| 531 | struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); | ||
| 498 | int ret; | 532 | int ret; |
| 499 | 533 | ||
| 534 | afs_add_open_mmap(vnode); | ||
| 535 | |||
| 500 | ret = generic_file_mmap(file, vma); | 536 | ret = generic_file_mmap(file, vma); |
| 501 | if (ret == 0) | 537 | if (ret == 0) |
| 502 | vma->vm_ops = &afs_vm_ops; | 538 | vma->vm_ops = &afs_vm_ops; |
| 539 | else | ||
| 540 | afs_drop_open_mmap(vnode); | ||
| 503 | return ret; | 541 | return ret; |
| 504 | } | 542 | } |
| 543 | |||
| 544 | static void afs_vm_open(struct vm_area_struct *vma) | ||
| 545 | { | ||
| 546 | afs_add_open_mmap(AFS_FS_I(file_inode(vma->vm_file))); | ||
| 547 | } | ||
| 548 | |||
| 549 | static void afs_vm_close(struct vm_area_struct *vma) | ||
| 550 | { | ||
| 551 | afs_drop_open_mmap(AFS_FS_I(file_inode(vma->vm_file))); | ||
| 552 | } | ||
| 553 | |||
| 554 | static vm_fault_t afs_vm_map_pages(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff) | ||
| 555 | { | ||
| 556 | struct afs_vnode *vnode = AFS_FS_I(file_inode(vmf->vma->vm_file)); | ||
| 557 | struct afs_file *af = vmf->vma->vm_file->private_data; | ||
| 558 | |||
| 559 | switch (afs_validate(vnode, af->key)) { | ||
| 560 | case 0: | ||
| 561 | return filemap_map_pages(vmf, start_pgoff, end_pgoff); | ||
| 562 | case -ENOMEM: | ||
| 563 | return VM_FAULT_OOM; | ||
| 564 | case -EINTR: | ||
| 565 | case -ERESTARTSYS: | ||
| 566 | return VM_FAULT_RETRY; | ||
| 567 | case -ESTALE: | ||
| 568 | default: | ||
| 569 | return VM_FAULT_SIGBUS; | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 573 | static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) | ||
| 574 | { | ||
| 575 | struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp)); | ||
| 576 | struct afs_file *af = iocb->ki_filp->private_data; | ||
| 577 | int ret; | ||
| 578 | |||
| 579 | ret = afs_validate(vnode, af->key); | ||
| 580 | if (ret < 0) | ||
| 581 | return ret; | ||
| 582 | |||
| 583 | return generic_file_read_iter(iocb, iter); | ||
| 584 | } | ||
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
| 10 | #include "afs_fs.h" | 10 | #include "afs_fs.h" |
| 11 | #include "internal.h" | 11 | #include "internal.h" |
| 12 | #include "protocol_afs.h" | ||
| 12 | #include "protocol_yfs.h" | 13 | #include "protocol_yfs.h" |
| 13 | 14 | ||
| 14 | static unsigned int afs_fs_probe_fast_poll_interval = 30 * HZ; | 15 | static unsigned int afs_fs_probe_fast_poll_interval = 30 * HZ; |
| @@ -102,7 +103,7 @@ void afs_fileserver_probe_result(struct afs_call *call) · 87 unmodified lines | |||
| 102 | struct afs_addr_list *alist = call->alist; | 103 | struct afs_addr_list *alist = call->alist; |
| 103 | struct afs_server *server = call->server; | 104 | struct afs_server *server = call->server; |
| 104 | unsigned int index = call->addr_ix; | 105 | unsigned int index = call->addr_ix; |
| 105 | unsigned int rtt_us = 0; | 106 | unsigned int rtt_us = 0, cap0; |
| 106 | int ret = call->error; | 107 | int ret = call->error; |
| 107 | 108 | ||
| 108 | _enter("%pU,%u", &server->uuid, index); | 109 | _enter("%pU,%u", &server->uuid, index); |
| @@ -159,6 +160,11 @@ responded: · 50 unmodified lines | |||
| 159 | clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags); | 160 | clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags); |
| 160 | alist->addrs[index].srx_service = call->service_id; | 161 | alist->addrs[index].srx_service = call->service_id; |
| 161 | } | 162 | } |
| 163 | cap0 = ntohl(call->tmp); | ||
| 164 | if (cap0 & AFS3_VICED_CAPABILITY_64BITFILES) | ||
| 165 | set_bit(AFS_SERVER_FL_HAS_FS64, &server->flags); | ||
| 166 | else | ||
| 167 | clear_bit(AFS_SERVER_FL_HAS_FS64, &server->flags); | ||
| 162 | } | 168 | } |
| 163 | 169 | ||
| 164 | if (rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us) && | 170 | if (rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us) && |
| @@ -456,9 +456,7 @@ void afs_fs_fetch_data(struct afs_operation *op) · 455 unmodified lines | |||
| 456 | struct afs_read *req = op->fetch.req; | 456 | struct afs_read *req = op->fetch.req; |
| 457 | __be32 *bp; | 457 | __be32 *bp; |
| 458 | 458 | ||
| 459 | if (upper_32_bits(req->pos) || | 459 | if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags)) |
| 460 | upper_32_bits(req->len) || | ||
| 461 | upper_32_bits(req->pos + req->len)) | ||
| 462 | return afs_fs_fetch_data64(op); | 460 | return afs_fs_fetch_data64(op); |
| 463 | 461 | ||
| 464 | _enter(""); | 462 | _enter(""); |
| @@ -1113,9 +1111,7 @@ void afs_fs_store_data(struct afs_operation *op) · 648 unmodified lines | |||
| 1113 | (unsigned long long)op->store.pos, | 1111 | (unsigned long long)op->store.pos, |
| 1114 | (unsigned long long)op->store.i_size); | 1112 | (unsigned long long)op->store.i_size); |
| 1115 | 1113 | ||
| 1116 | if (upper_32_bits(op->store.pos) || | 1114 | if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags)) |
| 1117 | upper_32_bits(op->store.size) || | ||
| 1118 | upper_32_bits(op->store.i_size)) | ||
| 1119 | return afs_fs_store_data64(op); | 1115 | return afs_fs_store_data64(op); |
| 1120 | 1116 | ||
| 1121 | call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData, | 1117 | call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData, |
| @@ -1229,7 +1225,7 @@ static void afs_fs_setattr_size(struct afs_operation *op) · 107 unmodified lines | |||
| 1229 | key_serial(op->key), vp->fid.vid, vp->fid.vnode); | 1225 | key_serial(op->key), vp->fid.vid, vp->fid.vnode); |
| 1230 | 1226 | ||
| 1231 | ASSERT(attr->ia_valid & ATTR_SIZE); | 1227 | ASSERT(attr->ia_valid & ATTR_SIZE); |
| 1232 | if (upper_32_bits(attr->ia_size)) | 1228 | if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags)) |
| 1233 | return afs_fs_setattr_size64(op); | 1229 | return afs_fs_setattr_size64(op); |
| 1234 | 1230 | ||
| 1235 | call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData_as_Status, | 1231 | call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData_as_Status, |
| @@ -1657,20 +1653,33 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call) · 421 unmodified lines | |||
| 1657 | return ret; | 1653 | return ret; |
| 1658 | 1654 | ||
| 1659 | count = ntohl(call->tmp); | 1655 | count = ntohl(call->tmp); |
| 1660 | |||
| 1661 | call->count = count; | 1656 | call->count = count; |
| 1662 | call->count2 = count; | 1657 | call->count2 = count; |
| 1663 | afs_extract_discard(call, count * sizeof(__be32)); | 1658 | if (count == 0) { |
| 1659 | call->unmarshall = 4; | ||
| 1660 | call->tmp = 0; | ||
| 1661 | break; | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | /* Extract the first word of the capabilities to call->tmp */ | ||
| 1665 | afs_extract_to_tmp(call); | ||
| 1664 | call->unmarshall++; | 1666 | call->unmarshall++; |
| 1665 | fallthrough; | 1667 | fallthrough; |
| 1666 | 1668 | ||
| 1667 | /* Extract capabilities words */ | ||
| 1668 | case 2: | 1669 | case 2: |
| 1669 | ret = afs_extract_data(call, false); | 1670 | ret = afs_extract_data(call, false); |
| 1670 | if (ret < 0) | 1671 | if (ret < 0) |
| 1671 | return ret; | 1672 | return ret; |
| 1672 | 1673 | ||
| 1673 | /* TODO: Examine capabilities */ | 1674 | afs_extract_discard(call, (count - 1) * sizeof(__be32)); |
| 1675 | call->unmarshall++; | ||
| 1676 | fallthrough; | ||
| 1677 | |||
| 1678 | /* Extract remaining capabilities words */ | ||
| 1679 | case 3: | ||
| 1680 | ret = afs_extract_data(call, false); | ||
| 1681 | if (ret < 0) | ||
| 1682 | return ret; | ||
| 1674 | 1683 | ||
| 1675 | call->unmarshall++; | 1684 | call->unmarshall++; |
| 1676 | break; | 1685 | break; |
| @@ -53,16 +53,6 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren · 52 unmodified lines | |||
| 53 | dump_stack(); | 53 | dump_stack(); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | /* | ||
| 57 | * Set the file size and block count. Estimate the number of 512 bytes blocks | ||
| 58 | * used, rounded up to nearest 1K for consistency with other AFS clients. | ||
| 59 | */ | ||
| 60 | static void afs_set_i_size(struct afs_vnode *vnode, u64 size) | ||
| 61 | { | ||
| 62 | i_size_write(&vnode->vfs_inode, size); | ||
| 63 | vnode->vfs_inode.i_blocks = ((size + 1023) >> 10) << 1; | ||
| 64 | } | ||
| 65 | |||
| 66 | /* | 56 | /* |
| 67 | * Initialise an inode from the vnode status. | 57 | * Initialise an inode from the vnode status. |
| 68 | */ | 58 | */ |
| @@ -587,22 +577,32 @@ static void afs_zap_data(struct afs_vnode *vnode) · 518 unmodified lines | |||
| 587 | } | 577 | } |
| 588 | 578 | ||
| 589 | /* | 579 | /* |
| 590 | * Get the server reinit counter for a vnode's current server. | 580 | * Check to see if we have a server currently serving this volume and that it |
| 581 | * hasn't been reinitialised or dropped from the list. | ||
| 591 | */ | 582 | */ |
| 592 | static bool afs_get_s_break_rcu(struct afs_vnode *vnode, unsigned int *_s_break) | 583 | static bool afs_check_server_good(struct afs_vnode *vnode) |
| 593 | { | 584 | { |
| 594 | struct afs_server_list *slist = rcu_dereference(vnode->volume->servers); | 585 | struct afs_server_list *slist; |
| 595 | struct afs_server *server; | 586 | struct afs_server *server; |
| 587 | bool good; | ||
| 596 | int i; | 588 | int i; |
| 597 | 589 | ||
| 590 | if (vnode->cb_fs_s_break == atomic_read(&vnode->volume->cell->fs_s_break)) | ||
| 591 | return true; | ||
| 592 | |||
| 593 | rcu_read_lock(); | ||
| 594 | |||
| 595 | slist = rcu_dereference(vnode->volume->servers); | ||
| 598 | for (i = 0; i < slist->nr_servers; i++) { | 596 | for (i = 0; i < slist->nr_servers; i++) { |
| 599 | server = slist->servers[i].server; | 597 | server = slist->servers[i].server; |
| 600 | if (server == vnode->cb_server) { | 598 | if (server == vnode->cb_server) { |
| 601 | *_s_break = READ_ONCE(server->cb_s_break); | 599 | good = (vnode->cb_s_break == server->cb_s_break); |
| 602 | return true; | 600 | rcu_read_unlock(); |
| 601 | return good; | ||
| 603 | } | 602 | } |
| 604 | } | 603 | } |
| 605 | 604 | ||
| 605 | rcu_read_unlock(); | ||
| 606 | return false; | 606 | return false; |
| 607 | } | 607 | } |
| 608 | 608 | ||
| @@ -611,57 +611,46 @@ static bool afs_get_s_break_rcu(struct afs_vnode *vnode, unsigned int *_s_break) · 2 unmodified lines | |||
| 611 | */ | 611 | */ |
| 612 | bool afs_check_validity(struct afs_vnode *vnode) | 612 | bool afs_check_validity(struct afs_vnode *vnode) |
| 613 | { | 613 | { |
| 614 | struct afs_volume *volume = vnode->volume; | ||
| 615 | enum afs_cb_break_reason need_clear = afs_cb_break_no_break; | 614 | enum afs_cb_break_reason need_clear = afs_cb_break_no_break; |
| 616 | time64_t now = ktime_get_real_seconds(); | 615 | time64_t now = ktime_get_real_seconds(); |
| 617 | bool valid; | 616 | unsigned int cb_break; |
| 618 | unsigned int cb_break, cb_s_break, cb_v_break; | ||
| 619 | int seq = 0; | 617 | int seq = 0; |
| 620 | 618 | ||
| 621 | do { | 619 | do { |
| 622 | read_seqbegin_or_lock(&vnode->cb_lock, &seq); | 620 | read_seqbegin_or_lock(&vnode->cb_lock, &seq); |
| 623 | cb_v_break = READ_ONCE(volume->cb_v_break); | ||
| 624 | cb_break = vnode->cb_break; | 621 | cb_break = vnode->cb_break; |
| 625 | 622 | ||
| 626 | if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags) && | 623 | if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { |
| 627 | afs_get_s_break_rcu(vnode, &cb_s_break)) { | 624 | if (vnode->cb_v_break != vnode->volume->cb_v_break) |
| 628 | if (vnode->cb_s_break != cb_s_break || | 625 | need_clear = afs_cb_break_for_v_break; |
| 629 | vnode->cb_v_break != cb_v_break) { | 626 | else if (!afs_check_server_good(vnode)) |
| 630 | vnode->cb_s_break = cb_s_break; | 627 | need_clear = afs_cb_break_for_s_reinit; |
| 631 | vnode->cb_v_break = cb_v_break; | 628 | else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) |
| 632 | need_clear = afs_cb_break_for_vsbreak; | ||
| 633 | valid = false; | ||
| 634 | } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) { | ||
| 635 | need_clear = afs_cb_break_for_zap; | 629 | need_clear = afs_cb_break_for_zap; |
| 636 | valid = false; | 630 | else if (vnode->cb_expires_at - 10 <= now) |
| 637 | } else if (vnode->cb_expires_at - 10 <= now) { | ||
| 638 | need_clear = afs_cb_break_for_lapsed; | 631 | need_clear = afs_cb_break_for_lapsed; |
| 639 | valid = false; | ||
| 640 | } else { | ||
| 641 | valid = true; | ||
| 642 | } | ||
| 643 | } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { | 632 | } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { |
| 644 | valid = true; | 633 | ; |
| 645 | } else { | 634 | } else { |
| 646 | vnode->cb_v_break = cb_v_break; | 635 | need_clear = afs_cb_break_no_promise; |
| 647 | valid = false; | ||
| 648 | } | 636 | } |
| 649 | 637 | ||
| 650 | } while (need_seqretry(&vnode->cb_lock, seq)); | 638 | } while (need_seqretry(&vnode->cb_lock, seq)); |
| 651 | 639 | ||
| 652 | done_seqretry(&vnode->cb_lock, seq); | 640 | done_seqretry(&vnode->cb_lock, seq); |
| 653 | 641 | ||
| 654 | if (need_clear != afs_cb_break_no_break) { | 642 | if (need_clear == afs_cb_break_no_break) |
| 655 | write_seqlock(&vnode->cb_lock); | 643 | return true; |
| 656 | if (cb_break == vnode->cb_break) | ||
| 657 | __afs_break_callback(vnode, need_clear); | ||
| 658 | else | ||
| 659 | trace_afs_cb_miss(&vnode->fid, need_clear); | ||
| 660 | write_sequnlock(&vnode->cb_lock); | ||
| 661 | valid = false; | ||
| 662 | } | ||
| 663 | 644 | ||
| 664 | return valid; | 645 | write_seqlock(&vnode->cb_lock); |
| 646 | if (need_clear == afs_cb_break_no_promise) | ||
| 647 | vnode->cb_v_break = vnode->volume->cb_v_break; | ||
| 648 | else if (cb_break == vnode->cb_break) | ||
| 649 | __afs_break_callback(vnode, need_clear); | ||
| 650 | else | ||
| 651 | trace_afs_cb_miss(&vnode->fid, need_clear); | ||
| 652 | write_sequnlock(&vnode->cb_lock); | ||
| 653 | return false; | ||
| 665 | } | 654 | } |
| 666 | 655 | ||
| 667 | /* | 656 | /* |
| @@ -675,21 +664,20 @@ bool afs_check_validity(struct afs_vnode *vnode) · 7 unmodified lines | |||
| 675 | */ | 664 | */ |
| 676 | int afs_validate(struct afs_vnode *vnode, struct key *key) | 665 | int afs_validate(struct afs_vnode *vnode, struct key *key) |
| 677 | { | 666 | { |
| 678 | bool valid; | ||
| 679 | int ret; | 667 | int ret; |
| 680 | 668 | ||
| 681 | _enter("{v={%llx:%llu} fl=%lx},%x", | 669 | _enter("{v={%llx:%llu} fl=%lx},%x", |
| 682 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, | 670 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, |
| 683 | key_serial(key)); | 671 | key_serial(key)); |
| 684 | 672 | ||
| 685 | rcu_read_lock(); | 673 | if (unlikely(test_bit(AFS_VNODE_DELETED, &vnode->flags))) { |
| 686 | valid = afs_check_validity(vnode); | 674 | if (vnode->vfs_inode.i_nlink) |
| 687 | rcu_read_unlock(); | 675 | clear_nlink(&vnode->vfs_inode); |
| 688 | 676 | goto valid; | |
| 689 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) | 677 | } |
| 690 | clear_nlink(&vnode->vfs_inode); | ||
| 691 | 678 | ||
| 692 | if (valid) | 679 | if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags) && |
| 680 | afs_check_validity(vnode)) | ||
| 693 | goto valid; | 681 | goto valid; |
| 694 | 682 | ||
| 695 | down_write(&vnode->validate_lock); | 683 | down_write(&vnode->validate_lock); |
| @@ -390,6 +390,9 @@ struct afs_cell { · 389 unmodified lines | |||
| 390 | /* Active fileserver interaction state. */ | 390 | /* Active fileserver interaction state. */ |
| 391 | struct rb_root fs_servers; /* afs_server (by server UUID) */ | 391 | struct rb_root fs_servers; /* afs_server (by server UUID) */ |
| 392 | seqlock_t fs_lock; /* For fs_servers */ | 392 | seqlock_t fs_lock; /* For fs_servers */ |
| 393 | struct rw_semaphore fs_open_mmaps_lock; | ||
| 394 | struct list_head fs_open_mmaps; /* List of vnodes that are mmapped */ | ||
| 395 | atomic_t fs_s_break; /* Counter of CB.InitCallBackState messages */ | ||
| 393 | 396 | ||
| 394 | /* VL server list. */ | 397 | /* VL server list. */ |
| 395 | rwlock_t vl_servers_lock; /* Lock on vl_servers */ | 398 | rwlock_t vl_servers_lock; /* Lock on vl_servers */ |
| @@ -503,6 +506,7 @@ struct afs_server { · 107 unmodified lines | |||
| 503 | struct hlist_node addr4_link; /* Link in net->fs_addresses4 */ | 506 | struct hlist_node addr4_link; /* Link in net->fs_addresses4 */ |
| 504 | struct hlist_node addr6_link; /* Link in net->fs_addresses6 */ | 507 | struct hlist_node addr6_link; /* Link in net->fs_addresses6 */ |
| 505 | struct hlist_node proc_link; /* Link in net->fs_proc */ | 508 | struct hlist_node proc_link; /* Link in net->fs_proc */ |
| 509 | struct work_struct initcb_work; /* Work for CB.InitCallBackState* */ | ||
| 506 | struct afs_server *gc_next; /* Next server in manager's list */ | 510 | struct afs_server *gc_next; /* Next server in manager's list */ |
| 507 | time64_t unuse_time; /* Time at which last unused */ | 511 | time64_t unuse_time; /* Time at which last unused */ |
| 508 | unsigned long flags; | 512 | unsigned long flags; |
| @@ -516,6 +520,7 @@ struct afs_server { · 7 unmodified lines | |||
| 516 | #define AFS_SERVER_FL_IS_YFS 16 /* Server is YFS not AFS */ | 520 | #define AFS_SERVER_FL_IS_YFS 16 /* Server is YFS not AFS */ |
| 517 | #define AFS_SERVER_FL_NO_IBULK 17 /* Fileserver doesn't support FS.InlineBulkStatus */ | 521 | #define AFS_SERVER_FL_NO_IBULK 17 /* Fileserver doesn't support FS.InlineBulkStatus */ |
| 518 | #define AFS_SERVER_FL_NO_RM2 18 /* Fileserver doesn't support YFS.RemoveFile2 */ | 522 | #define AFS_SERVER_FL_NO_RM2 18 /* Fileserver doesn't support YFS.RemoveFile2 */ |
| 523 | #define AFS_SERVER_FL_HAS_FS64 19 /* Fileserver supports FS.{Fetch,Store}Data64 */ | ||
| 519 | atomic_t ref; /* Object refcount */ | 524 | atomic_t ref; /* Object refcount */ |
| 520 | atomic_t active; /* Active user count */ | 525 | atomic_t active; /* Active user count */ |
| 521 | u32 addr_version; /* Address list version */ | 526 | u32 addr_version; /* Address list version */ |
| @@ -657,7 +662,11 @@ struct afs_vnode { · 135 unmodified lines | |||
| 657 | afs_lock_type_t lock_type : 8; | 662 | afs_lock_type_t lock_type : 8; |
| 658 | 663 | ||
| 659 | /* outstanding callback notification on this file */ | 664 | /* outstanding callback notification on this file */ |
| 665 | struct work_struct cb_work; /* Work for mmap'd files */ | ||
| 666 | struct list_head cb_mmap_link; /* Link in cell->fs_open_mmaps */ | ||
| 660 | void *cb_server; /* Server with callback/filelock */ | 667 | void *cb_server; /* Server with callback/filelock */ |
| 668 | atomic_t cb_nr_mmap; /* Number of mmaps */ | ||
| 669 | unsigned int cb_fs_s_break; /* Mass server break counter (cell->fs_s_break) */ | ||
| 661 | unsigned int cb_s_break; /* Mass break counter on ->server */ | 670 | unsigned int cb_s_break; /* Mass break counter on ->server */ |
| 662 | unsigned int cb_v_break; /* Mass break counter on ->volume */ | 671 | unsigned int cb_v_break; /* Mass break counter on ->volume */ |
| 663 | unsigned int cb_break; /* Break counter on vnode */ | 672 | unsigned int cb_break; /* Break counter on vnode */ |
| @@ -965,6 +974,8 @@ extern struct fscache_cookie_def afs_vnode_cache_index_def; · 301 unmodified lines | |||
| 965 | /* | 974 | /* |
| 966 | * callback.c | 975 | * callback.c |
| 967 | */ | 976 | */ |
| 977 | extern void afs_invalidate_mmap_work(struct work_struct *); | ||
| 978 | extern void afs_server_init_callback_work(struct work_struct *work); | ||
| 968 | extern void afs_init_callback_state(struct afs_server *); | 979 | extern void afs_init_callback_state(struct afs_server *); |
| 969 | extern void __afs_break_callback(struct afs_vnode *, enum afs_cb_break_reason); | 980 | extern void __afs_break_callback(struct afs_vnode *, enum afs_cb_break_reason); |
| 970 | extern void afs_break_callback(struct afs_vnode *, enum afs_cb_break_reason); | 981 | extern void afs_break_callback(struct afs_vnode *, enum afs_cb_break_reason); |
| @@ -1585,6 +1596,16 @@ static inline void afs_update_dentry_version(struct afs_operation *op, · 614 unmodified lines | |||
| 1585 | (void *)(unsigned long)dir_vp->scb.status.data_version; | 1596 | (void *)(unsigned long)dir_vp->scb.status.data_version; |
| 1586 | } | 1597 | } |
| 1587 | 1598 | ||
| 1599 | /* | ||
| 1600 | * Set the file size and block count. Estimate the number of 512 bytes blocks | ||
| 1601 | * used, rounded up to nearest 1K for consistency with other AFS clients. | ||
| 1602 | */ | ||
| 1603 | static inline void afs_set_i_size(struct afs_vnode *vnode, u64 size) | ||
| 1604 | { | ||
| 1605 | i_size_write(&vnode->vfs_inode, size); | ||
| 1606 | vnode->vfs_inode.i_blocks = ((size + 1023) >> 10) << 1; | ||
| 1607 | } | ||
| 1608 | |||
| 1588 | /* | 1609 | /* |
| 1589 | * Check for a conflicting operation on a directory that we just unlinked from. | 1610 | * Check for a conflicting operation on a directory that we just unlinked from. |
| 1590 | * If someone managed to sneak a link or an unlink in on the file we just | 1611 | * If someone managed to sneak a link or an unlink in on the file we just |
| @@ -0,0 +1,15 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||
| 2 | /* AFS protocol bits | ||
| 3 | * | ||
| 4 | * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. | ||
| 5 | * Written by David Howells (dhowells@redhat.com) | ||
| 6 | */ | ||
| 7 | |||
| 8 | |||
| 9 | #define AFSCAPABILITIESMAX 196 /* Maximum number of words in a capability set */ | ||
| 10 | |||
| 11 | /* AFS3 Fileserver capabilities word 0 */ | ||
| 12 | #define AFS3_VICED_CAPABILITY_ERRORTRANS 0x0001 /* Uses UAE errors */ | ||
| 13 | #define AFS3_VICED_CAPABILITY_64BITFILES 0x0002 /* FetchData64 & StoreData64 supported */ | ||
| 14 | #define AFS3_VICED_CAPABILITY_WRITELOCKACL 0x0004 /* Can lock a file even without lock perm */ | ||
| 15 | #define AFS3_VICED_CAPABILITY_SANEACLS 0x0008 /* ACLs reviewed for sanity - don't use */ | ||
| @@ -168,3 +168,9 @@ enum yfs_lock_type { · 167 unmodified lines | |||
| 168 | yfs_LockMandatoryWrite = 0x101, | 168 | yfs_LockMandatoryWrite = 0x101, |
| 169 | yfs_LockMandatoryExtend = 0x102, | 169 | yfs_LockMandatoryExtend = 0x102, |
| 170 | }; | 170 | }; |
| 171 | |||
| 172 | /* RXYFS Viced Capability Flags */ | ||
| 173 | #define YFS_VICED_CAPABILITY_ERRORTRANS 0x0001 /* Deprecated v0.195 */ | ||
| 174 | #define YFS_VICED_CAPABILITY_64BITFILES 0x0002 /* Deprecated v0.195 */ | ||
| 175 | #define YFS_VICED_CAPABILITY_WRITELOCKACL 0x0004 /* Can lock a file even without lock perm */ | ||
| 176 | #define YFS_VICED_CAPABILITY_SANEACLS 0x0008 /* Deprecated v0.195 */ | ||
| @@ -374,6 +374,7 @@ selected_server: · 373 unmodified lines | |||
| 374 | if (vnode->cb_server != server) { | 374 | if (vnode->cb_server != server) { |
| 375 | vnode->cb_server = server; | 375 | vnode->cb_server = server; |
| 376 | vnode->cb_s_break = server->cb_s_break; | 376 | vnode->cb_s_break = server->cb_s_break; |
| 377 | vnode->cb_fs_s_break = atomic_read(&server->cell->fs_s_break); | ||
| 377 | vnode->cb_v_break = vnode->volume->cb_v_break; | 378 | vnode->cb_v_break = vnode->volume->cb_v_break; |
| 378 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | 379 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); |
| 379 | } | 380 | } |
| @@ -235,6 +235,7 @@ static struct afs_server *afs_alloc_server(struct afs_cell *cell, · 234 unmodified lines | |||
| 235 | server->addr_version = alist->version; | 235 | server->addr_version = alist->version; |
| 236 | server->uuid = *uuid; | 236 | server->uuid = *uuid; |
| 237 | rwlock_init(&server->fs_lock); | 237 | rwlock_init(&server->fs_lock); |
| 238 | INIT_WORK(&server->initcb_work, afs_server_init_callback_work); | ||
| 238 | init_waitqueue_head(&server->probe_wq); | 239 | init_waitqueue_head(&server->probe_wq); |
| 239 | INIT_LIST_HEAD(&server->probe_link); | 240 | INIT_LIST_HEAD(&server->probe_link); |
| 240 | spin_lock_init(&server->probe_lock); | 241 | spin_lock_init(&server->probe_lock); |
| @@ -467,6 +468,7 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server) · 226 unmodified lines | |||
| 467 | if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags)) | 468 | if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags)) |
| 468 | afs_give_up_callbacks(net, server); | 469 | afs_give_up_callbacks(net, server); |
| 469 | 470 | ||
| 471 | flush_work(&server->initcb_work); | ||
| 470 | afs_put_server(net, server, afs_server_trace_destroy); | 472 | afs_put_server(net, server, afs_server_trace_destroy); |
| 471 | } | 473 | } |
| 472 | 474 | ||
| @@ -698,6 +698,7 @@ static struct inode *afs_alloc_inode(struct super_block *sb) · 697 unmodified lines | |||
| 698 | vnode->lock_state = AFS_VNODE_LOCK_NONE; | 698 | vnode->lock_state = AFS_VNODE_LOCK_NONE; |
| 699 | 699 | ||
| 700 | init_rwsem(&vnode->rmdir_lock); | 700 | init_rwsem(&vnode->rmdir_lock); |
| 701 | INIT_WORK(&vnode->cb_work, afs_invalidate_mmap_work); | ||
| 701 | 702 | ||
| 702 | _leave(" = %p", &vnode->vfs_inode); | 703 | _leave(" = %p", &vnode->vfs_inode); |
| 703 | return &vnode->vfs_inode; | 704 | return &vnode->vfs_inode; |
| @@ -137,7 +137,7 @@ int afs_write_end(struct file *file, struct address_space *mapping, · 136 unmodified lines | |||
| 137 | write_seqlock(&vnode->cb_lock); | 137 | write_seqlock(&vnode->cb_lock); |
| 138 | i_size = i_size_read(&vnode->vfs_inode); | 138 | i_size = i_size_read(&vnode->vfs_inode); |
| 139 | if (maybe_i_size > i_size) | 139 | if (maybe_i_size > i_size) |
| 140 | i_size_write(&vnode->vfs_inode, maybe_i_size); | 140 | afs_set_i_size(vnode, maybe_i_size); |
| 141 | write_sequnlock(&vnode->cb_lock); | 141 | write_sequnlock(&vnode->cb_lock); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| @@ -471,13 +471,18 @@ static void afs_extend_writeback(struct address_space *mapping, · 327 unmodified lines | |||
| 471 | } | 471 | } |
| 472 | 472 | ||
| 473 | /* Has the page moved or been split? */ | 473 | /* Has the page moved or been split? */ |
| 474 | if (unlikely(page != xas_reload(&xas))) | 474 | if (unlikely(page != xas_reload(&xas))) { |
| 475 | put_page(page); | ||
| 475 | break; | 476 | break; |
| 477 | } | ||
| 476 | 478 | ||
| 477 | if (!trylock_page(page)) | 479 | if (!trylock_page(page)) { |
| 480 | put_page(page); | ||
| 478 | break; | 481 | break; |
| 482 | } | ||
| 479 | if (!PageDirty(page) || PageWriteback(page)) { | 483 | if (!PageDirty(page) || PageWriteback(page)) { |
| 480 | unlock_page(page); | 484 | unlock_page(page); |
| 485 | put_page(page); | ||
| 481 | break; | 486 | break; |
| 482 | } | 487 | } |
| 483 | 488 | ||
| @@ -487,6 +492,7 @@ static void afs_extend_writeback(struct address_space *mapping, · 3 unmodified lines | |||
| 487 | t = afs_page_dirty_to(page, priv); | 492 | t = afs_page_dirty_to(page, priv); |
| 488 | if (f != 0 && !new_content) { | 493 | if (f != 0 && !new_content) { |
| 489 | unlock_page(page); | 494 | unlock_page(page); |
| 495 | put_page(page); | ||
| 490 | break; | 496 | break; |
| 491 | } | 497 | } |
| 492 | 498 | ||
| @@ -801,6 +807,7 @@ int afs_writepages(struct address_space *mapping, · 308 unmodified lines | |||
| 801 | ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from) | 807 | ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from) |
| 802 | { | 808 | { |
| 803 | struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp)); | 809 | struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp)); |
| 810 | struct afs_file *af = iocb->ki_filp->private_data; | ||
| 804 | ssize_t result; | 811 | ssize_t result; |
| 805 | size_t count = iov_iter_count(from); | 812 | size_t count = iov_iter_count(from); |
| 806 | 813 | ||
| @@ -816,6 +823,10 @@ ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from) · 9 unmodified lines | |||
| 816 | if (!count) | 823 | if (!count) |
| 817 | return 0; | 824 | return 0; |
| 818 | 825 | ||
| 826 | result = afs_validate(vnode, af->key); | ||
| 827 | if (result < 0) | ||
| 828 | return result; | ||
| 829 | |||
| 819 | result = generic_file_write_iter(iocb, from); | 830 | result = generic_file_write_iter(iocb, from); |
| 820 | 831 | ||
| 821 | _leave(" = %zd", result); | 832 | _leave(" = %zd", result); |
| @@ -829,13 +840,18 @@ ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from) · 7 unmodified lines | |||
| 829 | */ | 840 | */ |
| 830 | int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync) | 841 | int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
| 831 | { | 842 | { |
| 832 | struct inode *inode = file_inode(file); | 843 | struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); |
| 833 | struct afs_vnode *vnode = AFS_FS_I(inode); | 844 | struct afs_file *af = file->private_data; |
| 845 | int ret; | ||
| 834 | 846 | ||
| 835 | _enter("{%llx:%llu},{n=%pD},%d", | 847 | _enter("{%llx:%llu},{n=%pD},%d", |
| 836 | vnode->fid.vid, vnode->fid.vnode, file, | 848 | vnode->fid.vid, vnode->fid.vnode, file, |
| 837 | datasync); | 849 | datasync); |
| 838 | 850 | ||
| 851 | ret = afs_validate(vnode, af->key); | ||
| 852 | if (ret < 0) | ||
| 853 | return ret; | ||
| 854 | |||
| 839 | return file_write_and_wait_range(file, start, end); | 855 | return file_write_and_wait_range(file, start, end); |
| 840 | } | 856 | } |
| 841 | 857 | ||
| @@ -849,11 +865,14 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf) · 7 unmodified lines | |||
| 849 | struct file *file = vmf->vma->vm_file; | 865 | struct file *file = vmf->vma->vm_file; |
| 850 | struct inode *inode = file_inode(file); | 866 | struct inode *inode = file_inode(file); |
| 851 | struct afs_vnode *vnode = AFS_FS_I(inode); | 867 | struct afs_vnode *vnode = AFS_FS_I(inode); |
| 868 | struct afs_file *af = file->private_data; | ||
| 852 | unsigned long priv; | 869 | unsigned long priv; |
| 853 | vm_fault_t ret = VM_FAULT_RETRY; | 870 | vm_fault_t ret = VM_FAULT_RETRY; |
| 854 | 871 | ||
| 855 | _enter("{{%llx:%llu}},{%lx}", vnode->fid.vid, vnode->fid.vnode, page->index); | 872 | _enter("{{%llx:%llu}},{%lx}", vnode->fid.vid, vnode->fid.vnode, page->index); |
| 856 | 873 | ||
| 874 | afs_validate(vnode, af->key); | ||
| 875 | |||
| 857 | sb_start_pagefault(inode->i_sb); | 876 | sb_start_pagefault(inode->i_sb); |
| 858 | 877 | ||
| 859 | /* Wait for the page to be written to the cache before we allow it to | 878 | /* Wait for the page to be written to the cache before we allow it to |
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cache.c - CIFS filesystem cache index structure definitions | 3 | * CIFS filesystem cache index structure definitions |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2010 Novell, Inc. | 5 | * Copyright (c) 2010 Novell, Inc. |
| 6 | * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> | 6 | * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs_debug.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2000,2005 | 4 | * Copyright (C) International Business Machines Corp., 2000,2005 |
| 6 | * | 5 | * |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifs_fs_sb.h | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2002,2004 | 4 | * Copyright (c) International Business Machines Corp., 2002,2004 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifs_ioctl.h | ||
| 4 | * | 3 | * |
| 5 | * Structure definitions for io control for cifs/smb3 | 4 | * Structure definitions for io control for cifs/smb3 |
| 6 | * | 5 | * |
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifs_spnego.c -- SPNEGO upcall management for CIFS | 3 | * SPNEGO upcall management for CIFS |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2007 Red Hat, Inc. | 5 | * Copyright (c) 2007 Red Hat, Inc. |
| 6 | * Author(s): Jeff Layton (jlayton@redhat.com) | 6 | * Author(s): Jeff Layton (jlayton@redhat.com) |
| @@ -1,6 +1,6 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifs_spnego.h -- SPNEGO upcall management for CIFS | 3 | * SPNEGO upcall management for CIFS |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2007 Red Hat, Inc. | 5 | * Copyright (c) 2007 Red Hat, Inc. |
| 6 | * Author(s): Jeff Layton (jlayton@redhat.com) | 6 | * Author(s): Jeff Layton (jlayton@redhat.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifs_unicode.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2000,2009 | 4 | * Copyright (c) International Business Machines Corp., 2000,2009 |
| 6 | * Modified by Steve French (sfrench@us.ibm.com) | 5 | * Modified by Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifsacl.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2007,2008 | 4 | * Copyright (C) International Business Machines Corp., 2007,2008 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifsacl.h | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2007 | 4 | * Copyright (c) International Business Machines Corp., 2007 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifsencrypt.c | ||
| 4 | * | 3 | * |
| 5 | * Encryption and hashing operations relating to NTLM, NTLMv2. See MS-NLMP | 4 | * Encryption and hashing operations relating to NTLM, NTLMv2. See MS-NLMP |
| 6 | * for more detailed information | 5 | * for more detailed information |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifsfs.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002,2008 | 4 | * Copyright (C) International Business Machines Corp., 2002,2008 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifsfs.h | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2002, 2007 | 4 | * Copyright (c) International Business Machines Corp., 2002, 2007 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifsglob.h | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002,2008 | 4 | * Copyright (C) International Business Machines Corp., 2002,2008 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1400,6 +1399,7 @@ struct cifsInodeInfo { · 1393 unmodified lines | |||
| 1400 | #define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */ | 1399 | #define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */ |
| 1401 | #define CIFS_INO_LOCK (5) /* lock bit for synchronization */ | 1400 | #define CIFS_INO_LOCK (5) /* lock bit for synchronization */ |
| 1402 | #define CIFS_INO_MODIFIED_ATTR (6) /* Indicate change in mtime/ctime */ | 1401 | #define CIFS_INO_MODIFIED_ATTR (6) /* Indicate change in mtime/ctime */ |
| 1402 | #define CIFS_INO_CLOSE_ON_LOCK (7) /* Not to defer the close when lock is set */ | ||
| 1403 | unsigned long flags; | 1403 | unsigned long flags; |
| 1404 | spinlock_t writers_lock; | 1404 | spinlock_t writers_lock; |
| 1405 | unsigned int writers; /* Number of writers on this inode */ | 1405 | unsigned int writers; /* Number of writers on this inode */ |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifspdu.h | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2002,2009 | 4 | * Copyright (c) International Business Machines Corp., 2002,2009 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifsproto.h | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2002,2008 | 4 | * Copyright (c) International Business Machines Corp., 2002,2008 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -268,6 +267,9 @@ extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode); · 261 unmodified lines | |||
| 268 | 267 | ||
| 269 | extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon); | 268 | extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon); |
| 270 | 269 | ||
| 270 | extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon, | ||
| 271 | const char *path); | ||
| 272 | |||
| 271 | extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx); | 273 | extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx); |
| 272 | extern void cifs_put_tcp_session(struct TCP_Server_Info *server, | 274 | extern void cifs_put_tcp_session(struct TCP_Server_Info *server, |
| 273 | int from_reconnect); | 275 | int from_reconnect); |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/cifssmb.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002,2010 | 4 | * Copyright (C) International Business Machines Corp., 2002,2010 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/connect.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002,2011 | 4 | * Copyright (C) International Business Machines Corp., 2002,2011 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1090,7 +1089,7 @@ next_pdu: · 1083 unmodified lines | |||
| 1090 | module_put_and_exit(0); | 1089 | module_put_and_exit(0); |
| 1091 | } | 1090 | } |
| 1092 | 1091 | ||
| 1093 | /** | 1092 | /* |
| 1094 | * Returns true if srcaddr isn't specified and rhs isn't specified, or | 1093 | * Returns true if srcaddr isn't specified and rhs isn't specified, or |
| 1095 | * if srcaddr is specified and matches the IP address of the rhs argument | 1094 | * if srcaddr is specified and matches the IP address of the rhs argument |
| 1096 | */ | 1095 | */ |
| @@ -1550,6 +1549,9 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx) · 453 unmodified lines | |||
| 1550 | 1549 | ||
| 1551 | /** | 1550 | /** |
| 1552 | * cifs_setup_ipc - helper to setup the IPC tcon for the session | 1551 | * cifs_setup_ipc - helper to setup the IPC tcon for the session |
| 1552 | * @ses: smb session to issue the request on | ||
| 1553 | * @ctx: the superblock configuration context to use for building the | ||
| 1554 | * new tree connection for the IPC (interprocess communication RPC) | ||
| 1553 | * | 1555 | * |
| 1554 | * A new IPC connection is made and stored in the session | 1556 | * A new IPC connection is made and stored in the session |
| 1555 | * tcon_ipc. The IPC tcon has the same lifetime as the session. | 1557 | * tcon_ipc. The IPC tcon has the same lifetime as the session. |
| @@ -1605,6 +1607,7 @@ out: · 49 unmodified lines | |||
| 1605 | 1607 | ||
| 1606 | /** | 1608 | /** |
| 1607 | * cifs_free_ipc - helper to release the session IPC tcon | 1609 | * cifs_free_ipc - helper to release the session IPC tcon |
| 1610 | * @ses: smb session to unmount the IPC from | ||
| 1608 | * | 1611 | * |
| 1609 | * Needs to be called everytime a session is destroyed. | 1612 | * Needs to be called everytime a session is destroyed. |
| 1610 | * | 1613 | * |
| @@ -1855,6 +1858,8 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx __attribute__((unused)), · 244 unmodified lines | |||
| 1855 | 1858 | ||
| 1856 | /** | 1859 | /** |
| 1857 | * cifs_get_smb_ses - get a session matching @ctx data from @server | 1860 | * cifs_get_smb_ses - get a session matching @ctx data from @server |
| 1861 | * @server: server to setup the session to | ||
| 1862 | * @ctx: superblock configuration context to use to setup the session | ||
| 1858 | * | 1863 | * |
| 1859 | * This function assumes it is being called from cifs_mount() where we | 1864 | * This function assumes it is being called from cifs_mount() where we |
| 1860 | * already got a server reference (server refcount +1). See | 1865 | * already got a server reference (server refcount +1). See |
| @@ -2065,6 +2070,8 @@ cifs_put_tcon(struct cifs_tcon *tcon) · 204 unmodified lines | |||
| 2065 | 2070 | ||
| 2066 | /** | 2071 | /** |
| 2067 | * cifs_get_tcon - get a tcon matching @ctx data from @ses | 2072 | * cifs_get_tcon - get a tcon matching @ctx data from @ses |
| 2073 | * @ses: smb session to issue the request on | ||
| 2074 | * @ctx: the superblock configuration context to use for building the | ||
| 2068 | * | 2075 | * |
| 2069 | * - tcon refcount is the number of mount points using the tcon. | 2076 | * - tcon refcount is the number of mount points using the tcon. |
| 2070 | * - ses refcount is the number of tcon using the session. | 2077 | * - ses refcount is the number of tcon using the session. |
| @@ -3030,7 +3037,7 @@ build_unc_path_to_root(const struct smb3_fs_context *ctx, · 959 unmodified lines | |||
| 3030 | return full_path; | 3037 | return full_path; |
| 3031 | } | 3038 | } |
| 3032 | 3039 | ||
| 3033 | /** | 3040 | /* |
| 3034 | * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb | 3041 | * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb |
| 3035 | * | 3042 | * |
| 3036 | * If a referral is found, cifs_sb->ctx->mount_options will be (re-)allocated | 3043 | * If a referral is found, cifs_sb->ctx->mount_options will be (re-)allocated |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/dir.c | ||
| 4 | * | 3 | * |
| 5 | * vfs operations that deal with dentries | 4 | * vfs operations that deal with dentries |
| 6 | * | 5 | * |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/dns_resolve.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) 2007 Igor Mammedov | 4 | * Copyright (c) 2007 Igor Mammedov |
| 6 | * Author(s): Igor Mammedov (niallain@gmail.com) | 5 | * Author(s): Igor Mammedov (niallain@gmail.com) |
| @@ -1,7 +1,7 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/dns_resolve.h -- DNS Resolver upcall management for CIFS DFS | 3 | * DNS Resolver upcall management for CIFS DFS |
| 4 | * Handles host name to IP address resolution | 4 | * Handles host name to IP address resolution |
| 5 | * | 5 | * |
| 6 | * Copyright (c) International Business Machines Corp., 2008 | 6 | * Copyright (c) International Business Machines Corp., 2008 |
| 7 | * Author(s): Steve French (sfrench@us.ibm.com) | 7 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/export.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2007 | 4 | * Copyright (C) International Business Machines Corp., 2007 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/file.c | ||
| 4 | * | 3 | * |
| 5 | * vfs operations that deal with files | 4 | * vfs operations that deal with files |
| 6 | * | 5 | * |
| @@ -883,6 +882,7 @@ int cifs_close(struct inode *inode, struct file *file) · 876 unmodified lines | |||
| 883 | dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL); | 882 | dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL); |
| 884 | if ((cinode->oplock == CIFS_CACHE_RHW_FLG) && | 883 | if ((cinode->oplock == CIFS_CACHE_RHW_FLG) && |
| 885 | cinode->lease_granted && | 884 | cinode->lease_granted && |
| 885 | !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) && | ||
| 886 | dclose) { | 886 | dclose) { |
| 887 | if (test_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) { | 887 | if (test_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) { |
| 888 | inode->i_ctime = inode->i_mtime = current_time(inode); | 888 | inode->i_ctime = inode->i_mtime = current_time(inode); |
| @@ -1865,6 +1865,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) · 976 unmodified lines | |||
| 1865 | cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag, | 1865 | cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag, |
| 1866 | tcon->ses->server); | 1866 | tcon->ses->server); |
| 1867 | cifs_sb = CIFS_FILE_SB(file); | 1867 | cifs_sb = CIFS_FILE_SB(file); |
| 1868 | set_bit(CIFS_INO_CLOSE_ON_LOCK, &CIFS_I(d_inode(cfile->dentry))->flags); | ||
| 1868 | 1869 | ||
| 1869 | if (cap_unix(tcon->ses) && | 1870 | if (cap_unix(tcon->ses) && |
| 1870 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && | 1871 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && |
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/fscache.c - CIFS filesystem cache interface | 3 | * CIFS filesystem cache interface |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2010 Novell, Inc. | 5 | * Copyright (c) 2010 Novell, Inc. |
| 6 | * Author(s): Suresh Jayaraman <sjayaraman@suse.de> | 6 | * Author(s): Suresh Jayaraman <sjayaraman@suse.de> |
| @@ -1,6 +1,6 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/fscache.h - CIFS filesystem cache interface definitions | 3 | * CIFS filesystem cache interface definitions |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2010 Novell, Inc. | 5 | * Copyright (c) 2010 Novell, Inc. |
| 6 | * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> | 6 | * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/inode.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002,2010 | 4 | * Copyright (C) International Business Machines Corp., 2002,2010 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1625,7 +1624,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) · 1618 unmodified lines | |||
| 1625 | goto unlink_out; | 1624 | goto unlink_out; |
| 1626 | } | 1625 | } |
| 1627 | 1626 | ||
| 1628 | cifs_close_deferred_file(CIFS_I(inode)); | 1627 | cifs_close_deferred_file_under_dentry(tcon, full_path); |
| 1629 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 1628 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
| 1630 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 1629 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
| 1631 | rc = CIFSPOSIXDelFile(xid, tcon, full_path, | 1630 | rc = CIFSPOSIXDelFile(xid, tcon, full_path, |
| @@ -2114,9 +2113,9 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir, · 482 unmodified lines | |||
| 2114 | goto cifs_rename_exit; | 2113 | goto cifs_rename_exit; |
| 2115 | } | 2114 | } |
| 2116 | 2115 | ||
| 2117 | cifs_close_deferred_file(CIFS_I(d_inode(source_dentry))); | 2116 | cifs_close_deferred_file_under_dentry(tcon, from_name); |
| 2118 | if (d_inode(target_dentry) != NULL) | 2117 | if (d_inode(target_dentry) != NULL) |
| 2119 | cifs_close_deferred_file(CIFS_I(d_inode(target_dentry))); | 2118 | cifs_close_deferred_file_under_dentry(tcon, to_name); |
| 2120 | 2119 | ||
| 2121 | rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry, | 2120 | rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry, |
| 2122 | to_name); | 2121 | to_name); |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/ioctl.c | ||
| 4 | * | 3 | * |
| 5 | * vfs operations that deal with io control | 4 | * vfs operations that deal with io control |
| 6 | * | 5 | * |
| @@ -359,7 +358,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) · 352 unmodified lines | |||
| 359 | if (pSMBFile == NULL) | 358 | if (pSMBFile == NULL) |
| 360 | break; | 359 | break; |
| 361 | tcon = tlink_tcon(pSMBFile->tlink); | 360 | tcon = tlink_tcon(pSMBFile->tlink); |
| 362 | caps = le64_to_cpu(tcon->fsUnixInfo.Capability); | 361 | /* caps = le64_to_cpu(tcon->fsUnixInfo.Capability); */ |
| 363 | 362 | ||
| 364 | if (get_user(ExtAttrBits, (int __user *)arg)) { | 363 | if (get_user(ExtAttrBits, (int __user *)arg)) { |
| 365 | rc = -EFAULT; | 364 | rc = -EFAULT; |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/link.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002,2008 | 4 | * Copyright (C) International Business Machines Corp., 2002,2008 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/misc.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002,2008 | 4 | * Copyright (C) International Business Machines Corp., 2002,2008 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -736,7 +735,7 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode) · 729 unmodified lines | |||
| 736 | if (cancel_delayed_work(&cfile->deferred)) { | 735 | if (cancel_delayed_work(&cfile->deferred)) { |
| 737 | tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); | 736 | tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); |
| 738 | if (tmp_list == NULL) | 737 | if (tmp_list == NULL) |
| 739 | continue; | 738 | break; |
| 740 | tmp_list->cfile = cfile; | 739 | tmp_list->cfile = cfile; |
| 741 | list_add_tail(&tmp_list->list, &file_head); | 740 | list_add_tail(&tmp_list->list, &file_head); |
| 742 | } | 741 | } |
| @@ -767,7 +766,7 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon) · 24 unmodified lines | |||
| 767 | if (cancel_delayed_work(&cfile->deferred)) { | 766 | if (cancel_delayed_work(&cfile->deferred)) { |
| 768 | tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); | 767 | tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); |
| 769 | if (tmp_list == NULL) | 768 | if (tmp_list == NULL) |
| 770 | continue; | 769 | break; |
| 771 | tmp_list->cfile = cfile; | 770 | tmp_list->cfile = cfile; |
| 772 | list_add_tail(&tmp_list->list, &file_head); | 771 | list_add_tail(&tmp_list->list, &file_head); |
| 773 | } | 772 | } |
| @@ -781,6 +780,43 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon) · 7 unmodified lines | |||
| 781 | kfree(tmp_list); | 780 | kfree(tmp_list); |
| 782 | } | 781 | } |
| 783 | } | 782 | } |
| 783 | void | ||
| 784 | cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path) | ||
| 785 | { | ||
| 786 | struct cifsFileInfo *cfile; | ||
| 787 | struct list_head *tmp; | ||
| 788 | struct file_list *tmp_list, *tmp_next_list; | ||
| 789 | struct list_head file_head; | ||
| 790 | void *page; | ||
| 791 | const char *full_path; | ||
| 792 | |||
| 793 | INIT_LIST_HEAD(&file_head); | ||
| 794 | page = alloc_dentry_path(); | ||
| 795 | spin_lock(&tcon->open_file_lock); | ||
| 796 | list_for_each(tmp, &tcon->openFileList) { | ||
| 797 | cfile = list_entry(tmp, struct cifsFileInfo, tlist); | ||
| 798 | full_path = build_path_from_dentry(cfile->dentry, page); | ||
| 799 | if (strstr(full_path, path)) { | ||
| 800 | if (delayed_work_pending(&cfile->deferred)) { | ||
| 801 | if (cancel_delayed_work(&cfile->deferred)) { | ||
| 802 | tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); | ||
| 803 | if (tmp_list == NULL) | ||
| 804 | break; | ||
| 805 | tmp_list->cfile = cfile; | ||
| 806 | list_add_tail(&tmp_list->list, &file_head); | ||
| 807 | } | ||
| 808 | } | ||
| 809 | } | ||
| 810 | } | ||
| 811 | spin_unlock(&tcon->open_file_lock); | ||
| 812 | |||
| 813 | list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) { | ||
| 814 | _cifsFileInfo_put(tmp_list->cfile, true, false); | ||
| 815 | list_del(&tmp_list->list); | ||
| 816 | kfree(tmp_list); | ||
| 817 | } | ||
| 818 | free_dentry_path(page); | ||
| 819 | } | ||
| 784 | 820 | ||
| 785 | /* parses DFS refferal V3 structure | 821 | /* parses DFS refferal V3 structure |
| 786 | * caller is responsible for freeing target_nodes | 822 | * caller is responsible for freeing target_nodes |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/netmisc.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2002,2008 | 4 | * Copyright (c) International Business Machines Corp., 2002,2008 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/ntlmssp.h | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2002,2007 | 4 | * Copyright (c) International Business Machines Corp., 2002,2007 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/readdir.c | ||
| 4 | * | 3 | * |
| 5 | * Directory search handling | 4 | * Directory search handling |
| 6 | * | 5 | * |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/rfc1002pdu.h | ||
| 4 | * | 3 | * |
| 5 | * Protocol Data Unit definitions for RFC 1001/1002 support | 4 | * Protocol Data Unit definitions for RFC 1001/1002 support |
| 6 | * | 5 | * |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/sess.c | ||
| 4 | * | 3 | * |
| 5 | * SMB/CIFS session setup handling routines | 4 | * SMB/CIFS session setup handling routines |
| 6 | * | 5 | * |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/smb2file.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002, 2011 | 4 | * Copyright (C) International Business Machines Corp., 2002, 2011 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com), | 5 | * Author(s): Steve French (sfrench@us.ibm.com), |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/smb2glob.h | ||
| 4 | * | 3 | * |
| 5 | * Definitions for various global variables and structures | 4 | * Definitions for various global variables and structures |
| 6 | * | 5 | * |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/smb2inode.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002, 2011 | 4 | * Copyright (C) International Business Machines Corp., 2002, 2011 |
| 6 | * Etersoft, 2012 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/smb2misc.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002,2011 | 4 | * Copyright (C) International Business Machines Corp., 2002,2011 |
| 6 | * Etersoft, 2012 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/smb2pdu.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2009, 2013 | 4 | * Copyright (C) International Business Machines Corp., 2009, 2013 |
| 6 | * Etersoft, 2012 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/smb2pdu.h | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2009, 2013 | 4 | * Copyright (c) International Business Machines Corp., 2009, 2013 |
| 6 | * Etersoft, 2012 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/smb2proto.h | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2002, 2011 | 4 | * Copyright (c) International Business Machines Corp., 2002, 2011 |
| 6 | * Etersoft, 2012 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/smb2status.h | ||
| 4 | * | 3 | * |
| 5 | * SMB2 Status code (network error) definitions | 4 | * SMB2 Status code (network error) definitions |
| 6 | * Definitions are from MS-ERREF | 5 | * Definitions are from MS-ERREF |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/smb2transport.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002, 2011 | 4 | * Copyright (C) International Business Machines Corp., 2002, 2011 |
| 6 | * Etersoft, 2012 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1 */ | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/smberr.h | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2002,2004 | 4 | * Copyright (c) International Business Machines Corp., 2002,2004 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/transport.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (C) International Business Machines Corp., 2002,2008 | 4 | * Copyright (C) International Business Machines Corp., 2002,2008 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/winucase.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) Jeffrey Layton <jlayton@redhat.com>, 2013 | 4 | * Copyright (c) Jeffrey Layton <jlayton@redhat.com>, 2013 |
| 6 | * | 5 | * |
| @@ -1,6 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: LGPL-2.1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/xattr.c | ||
| 4 | * | 3 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2003, 2007 | 4 | * Copyright (c) International Business Machines Corp., 2003, 2007 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <linux/rculist_nulls.h> | 14 | #include <linux/rculist_nulls.h> |
| 15 | #include <linux/cpu.h> | 15 | #include <linux/cpu.h> |
| 16 | #include <linux/tracehook.h> | 16 | #include <linux/tracehook.h> |
| 17 | #include <uapi/linux/io_uring.h> | ||
| 17 | 18 | ||
| 18 | #include "io-wq.h" | 19 | #include "io-wq.h" |
| 19 | 20 | ||
| @@ -176,7 +177,6 @@ static void io_worker_ref_put(struct io_wq *wq) · 156 unmodified lines | |||
| 176 | static void io_worker_exit(struct io_worker *worker) | 177 | static void io_worker_exit(struct io_worker *worker) |
| 177 | { | 178 | { |
| 178 | struct io_wqe *wqe = worker->wqe; | 179 | struct io_wqe *wqe = worker->wqe; |
| 179 | struct io_wqe_acct *acct = io_wqe_get_acct(worker); | ||
| 180 | 180 | ||
| 181 | if (refcount_dec_and_test(&worker->ref)) | 181 | if (refcount_dec_and_test(&worker->ref)) |
| 182 | complete(&worker->ref_done); | 182 | complete(&worker->ref_done); |
| @@ -186,7 +186,6 @@ static void io_worker_exit(struct io_worker *worker) · 3 unmodified lines | |||
| 186 | if (worker->flags & IO_WORKER_F_FREE) | 186 | if (worker->flags & IO_WORKER_F_FREE) |
| 187 | hlist_nulls_del_rcu(&worker->nulls_node); | 187 | hlist_nulls_del_rcu(&worker->nulls_node); |
| 188 | list_del_rcu(&worker->all_list); | 188 | list_del_rcu(&worker->all_list); |
| 189 | acct->nr_workers--; | ||
| 190 | preempt_disable(); | 189 | preempt_disable(); |
| 191 | io_wqe_dec_running(worker); | 190 | io_wqe_dec_running(worker); |
| 192 | worker->flags = 0; | 191 | worker->flags = 0; |
| @@ -246,8 +245,6 @@ static bool io_wqe_activate_free_worker(struct io_wqe *wqe, · 53 unmodified lines | |||
| 246 | */ | 245 | */ |
| 247 | static bool io_wqe_create_worker(struct io_wqe *wqe, struct io_wqe_acct *acct) | 246 | static bool io_wqe_create_worker(struct io_wqe *wqe, struct io_wqe_acct *acct) |
| 248 | { | 247 | { |
| 249 | bool do_create = false; | ||
| 250 | |||
| 251 | /* | 248 | /* |
| 252 | * Most likely an attempt to queue unbounded work on an io_wq that | 249 | * Most likely an attempt to queue unbounded work on an io_wq that |
| 253 | * wasn't setup with any unbounded workers. | 250 | * wasn't setup with any unbounded workers. |
| @@ -256,18 +253,15 @@ static bool io_wqe_create_worker(struct io_wqe *wqe, struct io_wqe_acct *acct) · 2 unmodified lines | |||
| 256 | pr_warn_once("io-wq is not configured for unbound workers"); | 253 | pr_warn_once("io-wq is not configured for unbound workers"); |
| 257 | 254 | ||
| 258 | raw_spin_lock(&wqe->lock); | 255 | raw_spin_lock(&wqe->lock); |
| 259 | if (acct->nr_workers < acct->max_workers) { | 256 | if (acct->nr_workers == acct->max_workers) { |
| 260 | acct->nr_workers++; | 257 | raw_spin_unlock(&wqe->lock); |
| 261 | do_create = true; | 258 | return true; |
| 262 | } | 259 | } |
| 260 | acct->nr_workers++; | ||
| 263 | raw_spin_unlock(&wqe->lock); | 261 | raw_spin_unlock(&wqe->lock); |
| 264 | if (do_create) { | 262 | atomic_inc(&acct->nr_running); |
| 265 | atomic_inc(&acct->nr_running); | 263 | atomic_inc(&wqe->wq->worker_refs); |
| 266 | atomic_inc(&wqe->wq->worker_refs); | 264 | return create_io_worker(wqe->wq, wqe, acct->index); |
| 267 | return create_io_worker(wqe->wq, wqe, acct->index); | ||
| 268 | } | ||
| 269 | |||
| 270 | return true; | ||
| 271 | } | 265 | } |
| 272 | 266 | ||
| 273 | static void io_wqe_inc_running(struct io_worker *worker) | 267 | static void io_wqe_inc_running(struct io_worker *worker) |
| @@ -574,6 +568,7 @@ loop: · 300 unmodified lines | |||
| 574 | } | 568 | } |
| 575 | /* timed out, exit unless we're the last worker */ | 569 | /* timed out, exit unless we're the last worker */ |
| 576 | if (last_timeout && acct->nr_workers > 1) { | 570 | if (last_timeout && acct->nr_workers > 1) { |
| 571 | acct->nr_workers--; | ||
| 577 | raw_spin_unlock(&wqe->lock); | 572 | raw_spin_unlock(&wqe->lock); |
| 578 | __set_current_state(TASK_RUNNING); | 573 | __set_current_state(TASK_RUNNING); |
| 579 | break; | 574 | break; |
| @@ -1287,6 +1282,10 @@ int io_wq_max_workers(struct io_wq *wq, int *new_count) · 707 unmodified lines | |||
| 1287 | { | 1282 | { |
| 1288 | int i, node, prev = 0; | 1283 | int i, node, prev = 0; |
| 1289 | 1284 | ||
| 1285 | BUILD_BUG_ON((int) IO_WQ_ACCT_BOUND != (int) IO_WQ_BOUND); | ||
| 1286 | BUILD_BUG_ON((int) IO_WQ_ACCT_UNBOUND != (int) IO_WQ_UNBOUND); | ||
| 1287 | BUILD_BUG_ON((int) IO_WQ_ACCT_NR != 2); | ||
| 1288 | |||
| 1290 | for (i = 0; i < 2; i++) { | 1289 | for (i = 0; i < 2; i++) { |
| 1291 | if (new_count[i] > task_rlimit(current, RLIMIT_NPROC)) | 1290 | if (new_count[i] > task_rlimit(current, RLIMIT_NPROC)) |
| 1292 | new_count[i] = task_rlimit(current, RLIMIT_NPROC); | 1291 | new_count[i] = task_rlimit(current, RLIMIT_NPROC); |
| @@ -712,6 +712,7 @@ struct io_async_rw { · 711 unmodified lines | |||
| 712 | struct iovec fast_iov[UIO_FASTIOV]; | 712 | struct iovec fast_iov[UIO_FASTIOV]; |
| 713 | const struct iovec *free_iovec; | 713 | const struct iovec *free_iovec; |
| 714 | struct iov_iter iter; | 714 | struct iov_iter iter; |
| 715 | struct iov_iter_state iter_state; | ||
| 715 | size_t bytes_done; | 716 | size_t bytes_done; |
| 716 | struct wait_page_queue wpq; | 717 | struct wait_page_queue wpq; |
| 717 | }; | 718 | }; |
| @@ -735,7 +736,6 @@ enum { · 17 unmodified lines | |||
| 735 | REQ_F_BUFFER_SELECTED_BIT, | 736 | REQ_F_BUFFER_SELECTED_BIT, |
| 736 | REQ_F_COMPLETE_INLINE_BIT, | 737 | REQ_F_COMPLETE_INLINE_BIT, |
| 737 | REQ_F_REISSUE_BIT, | 738 | REQ_F_REISSUE_BIT, |
| 738 | REQ_F_DONT_REISSUE_BIT, | ||
| 739 | REQ_F_CREDS_BIT, | 739 | REQ_F_CREDS_BIT, |
| 740 | REQ_F_REFCOUNT_BIT, | 740 | REQ_F_REFCOUNT_BIT, |
| 741 | REQ_F_ARM_LTIMEOUT_BIT, | 741 | REQ_F_ARM_LTIMEOUT_BIT, |
| @@ -782,8 +782,6 @@ enum { · 40 unmodified lines | |||
| 782 | REQ_F_COMPLETE_INLINE = BIT(REQ_F_COMPLETE_INLINE_BIT), | 782 | REQ_F_COMPLETE_INLINE = BIT(REQ_F_COMPLETE_INLINE_BIT), |
| 783 | /* caller should reissue async */ | 783 | /* caller should reissue async */ |
| 784 | REQ_F_REISSUE = BIT(REQ_F_REISSUE_BIT), | 784 | REQ_F_REISSUE = BIT(REQ_F_REISSUE_BIT), |
| 785 | /* don't attempt request reissue, see io_rw_reissue() */ | ||
| 786 | REQ_F_DONT_REISSUE = BIT(REQ_F_DONT_REISSUE_BIT), | ||
| 787 | /* supports async reads */ | 785 | /* supports async reads */ |
| 788 | REQ_F_NOWAIT_READ = BIT(REQ_F_NOWAIT_READ_BIT), | 786 | REQ_F_NOWAIT_READ = BIT(REQ_F_NOWAIT_READ_BIT), |
| 789 | /* supports async writes */ | 787 | /* supports async writes */ |
| @@ -2444,13 +2442,6 @@ static void io_iopoll_complete(struct io_ring_ctx *ctx, unsigned int *nr_events, · 1654 unmodified lines | |||
| 2444 | req = list_first_entry(done, struct io_kiocb, inflight_entry); | 2442 | req = list_first_entry(done, struct io_kiocb, inflight_entry); |
| 2445 | list_del(&req->inflight_entry); | 2443 | list_del(&req->inflight_entry); |
| 2446 | 2444 | ||
| 2447 | if (READ_ONCE(req->result) == -EAGAIN && | ||
| 2448 | !(req->flags & REQ_F_DONT_REISSUE)) { | ||
| 2449 | req->iopoll_completed = 0; | ||
| 2450 | io_req_task_queue_reissue(req); | ||
| 2451 | continue; | ||
| 2452 | } | ||
| 2453 | |||
| 2454 | __io_cqring_fill_event(ctx, req->user_data, req->result, | 2445 | __io_cqring_fill_event(ctx, req->user_data, req->result, |
| 2455 | io_put_rw_kbuf(req)); | 2446 | io_put_rw_kbuf(req)); |
| 2456 | (*nr_events)++; | 2447 | (*nr_events)++; |
| @@ -2613,8 +2604,7 @@ static bool io_resubmit_prep(struct io_kiocb *req) · 156 unmodified lines | |||
| 2613 | 2604 | ||
| 2614 | if (!rw) | 2605 | if (!rw) |
| 2615 | return !io_req_prep_async(req); | 2606 | return !io_req_prep_async(req); |
| 2616 | /* may have left rw->iter inconsistent on -EIOCBQUEUED */ | 2607 | iov_iter_restore(&rw->iter, &rw->iter_state); |
| 2617 | iov_iter_revert(&rw->iter, req->result - iov_iter_count(&rw->iter)); | ||
| 2618 | return true; | 2608 | return true; |
| 2619 | } | 2609 | } |
| 2620 | 2610 | ||
| @@ -2714,10 +2704,9 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res, long res2) · 93 unmodified lines | |||
| 2714 | if (kiocb->ki_flags & IOCB_WRITE) | 2704 | if (kiocb->ki_flags & IOCB_WRITE) |
| 2715 | kiocb_end_write(req); | 2705 | kiocb_end_write(req); |
| 2716 | if (unlikely(res != req->result)) { | 2706 | if (unlikely(res != req->result)) { |
| 2717 | if (!(res == -EAGAIN && io_rw_should_reissue(req) && | 2707 | if (res == -EAGAIN && io_rw_should_reissue(req)) { |
| 2718 | io_resubmit_prep(req))) { | 2708 | req->flags |= REQ_F_REISSUE; |
| 2719 | req_set_fail(req); | 2709 | return; |
| 2720 | req->flags |= REQ_F_DONT_REISSUE; | ||
| 2721 | } | 2710 | } |
| 2722 | } | 2711 | } |
| 2723 | 2712 | ||
| @@ -2843,7 +2832,8 @@ static bool io_file_supports_nowait(struct io_kiocb *req, int rw) · 119 unmodified lines | |||
| 2843 | return __io_file_supports_nowait(req->file, rw); | 2832 | return __io_file_supports_nowait(req->file, rw); |
| 2844 | } | 2833 | } |
| 2845 | 2834 | ||
| 2846 | static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe) | 2835 | static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe, |
| 2836 | int rw) | ||
| 2847 | { | 2837 | { |
| 2848 | struct io_ring_ctx *ctx = req->ctx; | 2838 | struct io_ring_ctx *ctx = req->ctx; |
| 2849 | struct kiocb *kiocb = &req->rw.kiocb; | 2839 | struct kiocb *kiocb = &req->rw.kiocb; |
| @@ -2865,8 +2855,13 @@ static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 15 unmodified lines | |||
| 2865 | if (unlikely(ret)) | 2855 | if (unlikely(ret)) |
| 2866 | return ret; | 2856 | return ret; |
| 2867 | 2857 | ||
| 2868 | /* don't allow async punt for O_NONBLOCK or RWF_NOWAIT */ | 2858 | /* |
| 2869 | if ((kiocb->ki_flags & IOCB_NOWAIT) || (file->f_flags & O_NONBLOCK)) | 2859 | * If the file is marked O_NONBLOCK, still allow retry for it if it |
| 2860 | * supports async. Otherwise it's impossible to use O_NONBLOCK files | ||
| 2861 | * reliably. If not, or it IOCB_NOWAIT is set, don't retry. | ||
| 2862 | */ | ||
| 2863 | if ((kiocb->ki_flags & IOCB_NOWAIT) || | ||
| 2864 | ((file->f_flags & O_NONBLOCK) && !io_file_supports_nowait(req, rw))) | ||
| 2870 | req->flags |= REQ_F_NOWAIT; | 2865 | req->flags |= REQ_F_NOWAIT; |
| 2871 | 2866 | ||
| 2872 | ioprio = READ_ONCE(sqe->ioprio); | 2867 | ioprio = READ_ONCE(sqe->ioprio); |
| @@ -2931,7 +2926,6 @@ static void kiocb_done(struct kiocb *kiocb, ssize_t ret, · 58 unmodified lines | |||
| 2931 | { | 2926 | { |
| 2932 | struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw.kiocb); | 2927 | struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw.kiocb); |
| 2933 | struct io_async_rw *io = req->async_data; | 2928 | struct io_async_rw *io = req->async_data; |
| 2934 | bool check_reissue = kiocb->ki_complete == io_complete_rw; | ||
| 2935 | 2929 | ||
| 2936 | /* add previously done IO, if any */ | 2930 | /* add previously done IO, if any */ |
| 2937 | if (io && io->bytes_done > 0) { | 2931 | if (io && io->bytes_done > 0) { |
| @@ -2943,19 +2937,27 @@ static void kiocb_done(struct kiocb *kiocb, ssize_t ret, · 5 unmodified lines | |||
| 2943 | 2937 | ||
| 2944 | if (req->flags & REQ_F_CUR_POS) | 2938 | if (req->flags & REQ_F_CUR_POS) |
| 2945 | req->file->f_pos = kiocb->ki_pos; | 2939 | req->file->f_pos = kiocb->ki_pos; |
| 2946 | if (ret >= 0 && check_reissue) | 2940 | if (ret >= 0 && (kiocb->ki_complete == io_complete_rw)) |
| 2947 | __io_complete_rw(req, ret, 0, issue_flags); | 2941 | __io_complete_rw(req, ret, 0, issue_flags); |
| 2948 | else | 2942 | else |
| 2949 | io_rw_done(kiocb, ret); | 2943 | io_rw_done(kiocb, ret); |
| 2950 | 2944 | ||
| 2951 | if (check_reissue && (req->flags & REQ_F_REISSUE)) { | 2945 | if (req->flags & REQ_F_REISSUE) { |
| 2952 | req->flags &= ~REQ_F_REISSUE; | 2946 | req->flags &= ~REQ_F_REISSUE; |
| 2953 | if (io_resubmit_prep(req)) { | 2947 | if (io_resubmit_prep(req)) { |
| 2954 | io_req_task_queue_reissue(req); | 2948 | io_req_task_queue_reissue(req); |
| 2955 | } else { | 2949 | } else { |
| 2950 | unsigned int cflags = io_put_rw_kbuf(req); | ||
| 2951 | struct io_ring_ctx *ctx = req->ctx; | ||
| 2952 | |||
| 2956 | req_set_fail(req); | 2953 | req_set_fail(req); |
| 2957 | __io_req_complete(req, issue_flags, ret, | 2954 | if (issue_flags & IO_URING_F_NONBLOCK) { |
| 2958 | io_put_rw_kbuf(req)); | 2955 | mutex_lock(&ctx->uring_lock); |
| 2956 | __io_req_complete(req, issue_flags, ret, cflags); | ||
| 2957 | mutex_unlock(&ctx->uring_lock); | ||
| 2958 | } else { | ||
| 2959 | __io_req_complete(req, issue_flags, ret, cflags); | ||
| 2960 | } | ||
| 2959 | } | 2961 | } |
| 2960 | } | 2962 | } |
| 2961 | } | 2963 | } |
| @@ -3263,12 +3265,15 @@ static ssize_t loop_rw_iter(int rw, struct io_kiocb *req, struct iov_iter *iter) · 301 unmodified lines | |||
| 3263 | ret = nr; | 3265 | ret = nr; |
| 3264 | break; | 3266 | break; |
| 3265 | } | 3267 | } |
| 3268 | if (!iov_iter_is_bvec(iter)) { | ||
| 3269 | iov_iter_advance(iter, nr); | ||
| 3270 | } else { | ||
| 3271 | req->rw.len -= nr; | ||
| 3272 | req->rw.addr += nr; | ||
| 3273 | } | ||
| 3266 | ret += nr; | 3274 | ret += nr; |
| 3267 | if (nr != iovec.iov_len) | 3275 | if (nr != iovec.iov_len) |
| 3268 | break; | 3276 | break; |
| 3269 | req->rw.len -= nr; | ||
| 3270 | req->rw.addr += nr; | ||
| 3271 | iov_iter_advance(iter, nr); | ||
| 3272 | } | 3277 | } |
| 3273 | 3278 | ||
| 3274 | return ret; | 3279 | return ret; |
| @@ -3315,12 +3320,17 @@ static int io_setup_async_rw(struct io_kiocb *req, const struct iovec *iovec, · 40 unmodified lines | |||
| 3315 | if (!force && !io_op_defs[req->opcode].needs_async_setup) | 3320 | if (!force && !io_op_defs[req->opcode].needs_async_setup) |
| 3316 | return 0; | 3321 | return 0; |
| 3317 | if (!req->async_data) { | 3322 | if (!req->async_data) { |
| 3323 | struct io_async_rw *iorw; | ||
| 3324 | |||
| 3318 | if (io_alloc_async_data(req)) { | 3325 | if (io_alloc_async_data(req)) { |
| 3319 | kfree(iovec); | 3326 | kfree(iovec); |
| 3320 | return -ENOMEM; | 3327 | return -ENOMEM; |
| 3321 | } | 3328 | } |
| 3322 | 3329 | ||
| 3323 | io_req_map_rw(req, iovec, fast_iov, iter); | 3330 | io_req_map_rw(req, iovec, fast_iov, iter); |
| 3331 | iorw = req->async_data; | ||
| 3332 | /* we've copied and mapped the iter, ensure state is saved */ | ||
| 3333 | iov_iter_save_state(&iorw->iter, &iorw->iter_state); | ||
| 3324 | } | 3334 | } |
| 3325 | return 0; | 3335 | return 0; |
| 3326 | } | 3336 | } |
| @@ -3339,6 +3349,7 @@ static inline int io_rw_prep_async(struct io_kiocb *req, int rw) · 12 unmodified lines | |||
| 3339 | iorw->free_iovec = iov; | 3349 | iorw->free_iovec = iov; |
| 3340 | if (iov) | 3350 | if (iov) |
| 3341 | req->flags |= REQ_F_NEED_CLEANUP; | 3351 | req->flags |= REQ_F_NEED_CLEANUP; |
| 3352 | iov_iter_save_state(&iorw->iter, &iorw->iter_state); | ||
| 3342 | return 0; | 3353 | return 0; |
| 3343 | } | 3354 | } |
| 3344 | 3355 | ||
| @@ -3346,7 +3357,7 @@ static int io_read_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 1 unmodified line | |||
| 3346 | { | 3357 | { |
| 3347 | if (unlikely(!(req->file->f_mode & FMODE_READ))) | 3358 | if (unlikely(!(req->file->f_mode & FMODE_READ))) |
| 3348 | return -EBADF; | 3359 | return -EBADF; |
| 3349 | return io_prep_rw(req, sqe); | 3360 | return io_prep_rw(req, sqe, READ); |
| 3350 | } | 3361 | } |
| 3351 | 3362 | ||
| 3352 | /* | 3363 | /* |
| @@ -3442,19 +3453,28 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags) · 89 unmodified lines | |||
| 3442 | struct kiocb *kiocb = &req->rw.kiocb; | 3453 | struct kiocb *kiocb = &req->rw.kiocb; |
| 3443 | struct iov_iter __iter, *iter = &__iter; | 3454 | struct iov_iter __iter, *iter = &__iter; |
| 3444 | struct io_async_rw *rw = req->async_data; | 3455 | struct io_async_rw *rw = req->async_data; |
| 3445 | ssize_t io_size, ret, ret2; | ||
| 3446 | bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; | 3456 | bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; |
| 3457 | struct iov_iter_state __state, *state; | ||
| 3458 | ssize_t ret, ret2; | ||
| 3447 | 3459 | ||
| 3448 | if (rw) { | 3460 | if (rw) { |
| 3449 | iter = &rw->iter; | 3461 | iter = &rw->iter; |
| 3462 | state = &rw->iter_state; | ||
| 3463 | /* | ||
| 3464 | * We come here from an earlier attempt, restore our state to | ||
| 3465 | * match in case it doesn't. It's cheap enough that we don't | ||
| 3466 | * need to make this conditional. | ||
| 3467 | */ | ||
| 3468 | iov_iter_restore(iter, state); | ||
| 3450 | iovec = NULL; | 3469 | iovec = NULL; |
| 3451 | } else { | 3470 | } else { |
| 3452 | ret = io_import_iovec(READ, req, &iovec, iter, !force_nonblock); | 3471 | ret = io_import_iovec(READ, req, &iovec, iter, !force_nonblock); |
| 3453 | if (ret < 0) | 3472 | if (ret < 0) |
| 3454 | return ret; | 3473 | return ret; |
| 3474 | state = &__state; | ||
| 3475 | iov_iter_save_state(iter, state); | ||
| 3455 | } | 3476 | } |
| 3456 | io_size = iov_iter_count(iter); | 3477 | req->result = iov_iter_count(iter); |
| 3457 | req->result = io_size; | ||
| 3458 | 3478 | ||
| 3459 | /* Ensure we clear previously set non-block flag */ | 3479 | /* Ensure we clear previously set non-block flag */ |
| 3460 | if (!force_nonblock) | 3480 | if (!force_nonblock) |
| @@ -3468,7 +3488,7 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags) · 7 unmodified lines | |||
| 3468 | return ret ?: -EAGAIN; | 3488 | return ret ?: -EAGAIN; |
| 3469 | } | 3489 | } |
| 3470 | 3490 | ||
| 3471 | ret = rw_verify_area(READ, req->file, io_kiocb_ppos(kiocb), io_size); | 3491 | ret = rw_verify_area(READ, req->file, io_kiocb_ppos(kiocb), req->result); |
| 3472 | if (unlikely(ret)) { | 3492 | if (unlikely(ret)) { |
| 3473 | kfree(iovec); | 3493 | kfree(iovec); |
| 3474 | return ret; | 3494 | return ret; |
| @@ -3484,30 +3504,49 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags) · 9 unmodified lines | |||
| 3484 | /* no retry on NONBLOCK nor RWF_NOWAIT */ | 3504 | /* no retry on NONBLOCK nor RWF_NOWAIT */ |
| 3485 | if (req->flags & REQ_F_NOWAIT) | 3505 | if (req->flags & REQ_F_NOWAIT) |
| 3486 | goto done; | 3506 | goto done; |
| 3487 | /* some cases will consume bytes even on error returns */ | ||
| 3488 | iov_iter_reexpand(iter, iter->count + iter->truncated); | ||
| 3489 | iov_iter_revert(iter, io_size - iov_iter_count(iter)); | ||
| 3490 | ret = 0; | 3507 | ret = 0; |
| 3491 | } else if (ret == -EIOCBQUEUED) { | 3508 | } else if (ret == -EIOCBQUEUED) { |
| 3492 | goto out_free; | 3509 | goto out_free; |
| 3493 | } else if (ret <= 0 || ret == io_size || !force_nonblock || | 3510 | } else if (ret <= 0 || ret == req->result || !force_nonblock || |
| 3494 | (req->flags & REQ_F_NOWAIT) || !need_read_all(req)) { | 3511 | (req->flags & REQ_F_NOWAIT) || !need_read_all(req)) { |
| 3495 | /* read all, failed, already did sync or don't want to retry */ | 3512 | /* read all, failed, already did sync or don't want to retry */ |
| 3496 | goto done; | 3513 | goto done; |
| 3497 | } | 3514 | } |
| 3498 | 3515 | ||
| 3516 | /* | ||
| 3517 | * Don't depend on the iter state matching what was consumed, or being | ||
| 3518 | * untouched in case of error. Restore it and we'll advance it | ||
| 3519 | * manually if we need to. | ||
| 3520 | */ | ||
| 3521 | iov_iter_restore(iter, state); | ||
| 3522 | |||
| 3499 | ret2 = io_setup_async_rw(req, iovec, inline_vecs, iter, true); | 3523 | ret2 = io_setup_async_rw(req, iovec, inline_vecs, iter, true); |
| 3500 | if (ret2) | 3524 | if (ret2) |
| 3501 | return ret2; | 3525 | return ret2; |
| 3502 | 3526 | ||
| 3503 | iovec = NULL; | 3527 | iovec = NULL; |
| 3504 | rw = req->async_data; | 3528 | rw = req->async_data; |
| 3505 | /* now use our persistent iterator, if we aren't already */ | 3529 | /* |
| 3506 | iter = &rw->iter; | 3530 | * Now use our persistent iterator and state, if we aren't already. |
| 3531 | * We've restored and mapped the iter to match. | ||
| 3532 | */ | ||
| 3533 | if (iter != &rw->iter) { | ||
| 3534 | iter = &rw->iter; | ||
| 3535 | state = &rw->iter_state; | ||
| 3536 | } | ||
| 3507 | 3537 | ||
| 3508 | do { | 3538 | do { |
| 3509 | io_size -= ret; | 3539 | /* |
| 3540 | * We end up here because of a partial read, either from | ||
| 3541 | * above or inside this loop. Advance the iter by the bytes | ||
| 3542 | * that were consumed. | ||
| 3543 | */ | ||
| 3544 | iov_iter_advance(iter, ret); | ||
| 3545 | if (!iov_iter_count(iter)) | ||
| 3546 | break; | ||
| 3510 | rw->bytes_done += ret; | 3547 | rw->bytes_done += ret; |
| 3548 | iov_iter_save_state(iter, state); | ||
| 3549 | |||
| 3511 | /* if we can retry, do so with the callbacks armed */ | 3550 | /* if we can retry, do so with the callbacks armed */ |
| 3512 | if (!io_rw_should_retry(req)) { | 3551 | if (!io_rw_should_retry(req)) { |
| 3513 | kiocb->ki_flags &= ~IOCB_WAITQ; | 3552 | kiocb->ki_flags &= ~IOCB_WAITQ; |
| @@ -3525,7 +3564,8 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags) · 11 unmodified lines | |||
| 3525 | return 0; | 3564 | return 0; |
| 3526 | /* we got some bytes, but not all. retry. */ | 3565 | /* we got some bytes, but not all. retry. */ |
| 3527 | kiocb->ki_flags &= ~IOCB_WAITQ; | 3566 | kiocb->ki_flags &= ~IOCB_WAITQ; |
| 3528 | } while (ret > 0 && ret < io_size); | 3567 | iov_iter_restore(iter, state); |
| 3568 | } while (ret > 0); | ||
| 3529 | done: | 3569 | done: |
| 3530 | kiocb_done(kiocb, ret, issue_flags); | 3570 | kiocb_done(kiocb, ret, issue_flags); |
| 3531 | out_free: | 3571 | out_free: |
| @@ -3539,7 +3579,7 @@ static int io_write_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 7 unmodified lines | |||
| 3539 | { | 3579 | { |
| 3540 | if (unlikely(!(req->file->f_mode & FMODE_WRITE))) | 3580 | if (unlikely(!(req->file->f_mode & FMODE_WRITE))) |
| 3541 | return -EBADF; | 3581 | return -EBADF; |
| 3542 | return io_prep_rw(req, sqe); | 3582 | return io_prep_rw(req, sqe, WRITE); |
| 3543 | } | 3583 | } |
| 3544 | 3584 | ||
| 3545 | static int io_write(struct io_kiocb *req, unsigned int issue_flags) | 3585 | static int io_write(struct io_kiocb *req, unsigned int issue_flags) |
| @@ -3548,19 +3588,24 @@ static int io_write(struct io_kiocb *req, unsigned int issue_flags) · 2 unmodified lines | |||
| 3548 | struct kiocb *kiocb = &req->rw.kiocb; | 3588 | struct kiocb *kiocb = &req->rw.kiocb; |
| 3549 | struct iov_iter __iter, *iter = &__iter; | 3589 | struct iov_iter __iter, *iter = &__iter; |
| 3550 | struct io_async_rw *rw = req->async_data; | 3590 | struct io_async_rw *rw = req->async_data; |
| 3551 | ssize_t ret, ret2, io_size; | ||
| 3552 | bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; | 3591 | bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; |
| 3592 | struct iov_iter_state __state, *state; | ||
| 3593 | ssize_t ret, ret2; | ||
| 3553 | 3594 | ||
| 3554 | if (rw) { | 3595 | if (rw) { |
| 3555 | iter = &rw->iter; | 3596 | iter = &rw->iter; |
| 3597 | state = &rw->iter_state; | ||
| 3598 | iov_iter_restore(iter, state); | ||
| 3556 | iovec = NULL; | 3599 | iovec = NULL; |
| 3557 | } else { | 3600 | } else { |
| 3558 | ret = io_import_iovec(WRITE, req, &iovec, iter, !force_nonblock); | 3601 | ret = io_import_iovec(WRITE, req, &iovec, iter, !force_nonblock); |
| 3559 | if (ret < 0) | 3602 | if (ret < 0) |
| 3560 | return ret; | 3603 | return ret; |
| 3604 | state = &__state; | ||
| 3605 | iov_iter_save_state(iter, state); | ||
| 3561 | } | 3606 | } |
| 3562 | io_size = iov_iter_count(iter); | 3607 | req->result = iov_iter_count(iter); |
| 3563 | req->result = io_size; | 3608 | ret2 = 0; |
| 3564 | 3609 | ||
| 3565 | /* Ensure we clear previously set non-block flag */ | 3610 | /* Ensure we clear previously set non-block flag */ |
| 3566 | if (!force_nonblock) | 3611 | if (!force_nonblock) |
| @@ -3577,7 +3622,7 @@ static int io_write(struct io_kiocb *req, unsigned int issue_flags) · 10 unmodified lines | |||
| 3577 | (req->flags & REQ_F_ISREG)) | 3622 | (req->flags & REQ_F_ISREG)) |
| 3578 | goto copy_iov; | 3623 | goto copy_iov; |
| 3579 | 3624 | ||
| 3580 | ret = rw_verify_area(WRITE, req->file, io_kiocb_ppos(kiocb), io_size); | 3625 | ret = rw_verify_area(WRITE, req->file, io_kiocb_ppos(kiocb), req->result); |
| 3581 | if (unlikely(ret)) | 3626 | if (unlikely(ret)) |
| 3582 | goto out_free; | 3627 | goto out_free; |
| 3583 | 3628 | ||
| @@ -3624,9 +3669,9 @@ done: · 40 unmodified lines | |||
| 3624 | kiocb_done(kiocb, ret2, issue_flags); | 3669 | kiocb_done(kiocb, ret2, issue_flags); |
| 3625 | } else { | 3670 | } else { |
| 3626 | copy_iov: | 3671 | copy_iov: |
| 3627 | /* some cases will consume bytes even on error returns */ | 3672 | iov_iter_restore(iter, state); |
| 3628 | iov_iter_reexpand(iter, iter->count + iter->truncated); | 3673 | if (ret2 > 0) |
| 3629 | iov_iter_revert(iter, io_size - iov_iter_count(iter)); | 3674 | iov_iter_advance(iter, ret2); |
| 3630 | ret = io_setup_async_rw(req, iovec, inline_vecs, iter, false); | 3675 | ret = io_setup_async_rw(req, iovec, inline_vecs, iter, false); |
| 3631 | return ret ?: -EAGAIN; | 3676 | return ret ?: -EAGAIN; |
| 3632 | } | 3677 | } |
| @@ -7515,6 +7560,14 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, · 3882 unmodified lines | |||
| 7515 | break; | 7560 | break; |
| 7516 | } while (1); | 7561 | } while (1); |
| 7517 | 7562 | ||
| 7563 | if (uts) { | ||
| 7564 | struct timespec64 ts; | ||
| 7565 | |||
| 7566 | if (get_timespec64(&ts, uts)) | ||
| 7567 | return -EFAULT; | ||
| 7568 | timeout = timespec64_to_jiffies(&ts); | ||
| 7569 | } | ||
| 7570 | |||
| 7518 | if (sig) { | 7571 | if (sig) { |
| 7519 | #ifdef CONFIG_COMPAT | 7572 | #ifdef CONFIG_COMPAT |
| 7520 | if (in_compat_syscall()) | 7573 | if (in_compat_syscall()) |
| @@ -7528,14 +7581,6 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, · 7 unmodified lines | |||
| 7528 | return ret; | 7581 | return ret; |
| 7529 | } | 7582 | } |
| 7530 | 7583 | ||
| 7531 | if (uts) { | ||
| 7532 | struct timespec64 ts; | ||
| 7533 | |||
| 7534 | if (get_timespec64(&ts, uts)) | ||
| 7535 | return -EFAULT; | ||
| 7536 | timeout = timespec64_to_jiffies(&ts); | ||
| 7537 | } | ||
| 7538 | |||
| 7539 | init_waitqueue_func_entry(&iowq.wq, io_wake_function); | 7584 | init_waitqueue_func_entry(&iowq.wq, io_wake_function); |
| 7540 | iowq.wq.private = current; | 7585 | iowq.wq.private = current; |
| 7541 | INIT_LIST_HEAD(&iowq.wq.entry); | 7586 | INIT_LIST_HEAD(&iowq.wq.entry); |
| @@ -8284,11 +8329,27 @@ static int io_sqe_file_register(struct io_ring_ctx *ctx, struct file *file, · 742 unmodified lines | |||
| 8284 | #endif | 8329 | #endif |
| 8285 | } | 8330 | } |
| 8286 | 8331 | ||
| 8332 | static int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx, | ||
| 8333 | struct io_rsrc_node *node, void *rsrc) | ||
| 8334 | { | ||
| 8335 | struct io_rsrc_put *prsrc; | ||
| 8336 | |||
| 8337 | prsrc = kzalloc(sizeof(*prsrc), GFP_KERNEL); | ||
| 8338 | if (!prsrc) | ||
| 8339 | return -ENOMEM; | ||
| 8340 | |||
| 8341 | prsrc->tag = *io_get_tag_slot(data, idx); | ||
| 8342 | prsrc->rsrc = rsrc; | ||
| 8343 | list_add(&prsrc->list, &node->rsrc_list); | ||
| 8344 | return 0; | ||
| 8345 | } | ||
| 8346 | |||
| 8287 | static int io_install_fixed_file(struct io_kiocb *req, struct file *file, | 8347 | static int io_install_fixed_file(struct io_kiocb *req, struct file *file, |
| 8288 | unsigned int issue_flags, u32 slot_index) | 8348 | unsigned int issue_flags, u32 slot_index) |
| 8289 | { | 8349 | { |
| 8290 | struct io_ring_ctx *ctx = req->ctx; | 8350 | struct io_ring_ctx *ctx = req->ctx; |
| 8291 | bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; | 8351 | bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; |
| 8352 | bool needs_switch = false; | ||
| 8292 | struct io_fixed_file *file_slot; | 8353 | struct io_fixed_file *file_slot; |
| 8293 | int ret = -EBADF; | 8354 | int ret = -EBADF; |
| 8294 | 8355 | ||
| @@ -8304,9 +8365,22 @@ static int io_install_fixed_file(struct io_kiocb *req, struct file *file, · 9 unmodified lines | |||
| 8304 | 8365 | ||
| 8305 | slot_index = array_index_nospec(slot_index, ctx->nr_user_files); | 8366 | slot_index = array_index_nospec(slot_index, ctx->nr_user_files); |
| 8306 | file_slot = io_fixed_file_slot(&ctx->file_table, slot_index); | 8367 | file_slot = io_fixed_file_slot(&ctx->file_table, slot_index); |
| 8307 | ret = -EBADF; | 8368 | |
| 8308 | if (file_slot->file_ptr) | 8369 | if (file_slot->file_ptr) { |
| 8309 | goto err; | 8370 | struct file *old_file; |
| 8371 | |||
| 8372 | ret = io_rsrc_node_switch_start(ctx); | ||
| 8373 | if (ret) | ||
| 8374 | goto err; | ||
| 8375 | |||
| 8376 | old_file = (struct file *)(file_slot->file_ptr & FFS_MASK); | ||
| 8377 | ret = io_queue_rsrc_removal(ctx->file_data, slot_index, | ||
| 8378 | ctx->rsrc_node, old_file); | ||
| 8379 | if (ret) | ||
| 8380 | goto err; | ||
| 8381 | file_slot->file_ptr = 0; | ||
| 8382 | needs_switch = true; | ||
| 8383 | } | ||
| 8310 | 8384 | ||
| 8311 | *io_get_tag_slot(ctx->file_data, slot_index) = 0; | 8385 | *io_get_tag_slot(ctx->file_data, slot_index) = 0; |
| 8312 | io_fixed_file_set(file_slot, file); | 8386 | io_fixed_file_set(file_slot, file); |
| @@ -8318,27 +8392,14 @@ static int io_install_fixed_file(struct io_kiocb *req, struct file *file, · 5 unmodified lines | |||
| 8318 | 8392 | ||
| 8319 | ret = 0; | 8393 | ret = 0; |
| 8320 | err: | 8394 | err: |
| 8395 | if (needs_switch) | ||
| 8396 | io_rsrc_node_switch(ctx, ctx->file_data); | ||
| 8321 | io_ring_submit_unlock(ctx, !force_nonblock); | 8397 | io_ring_submit_unlock(ctx, !force_nonblock); |
| 8322 | if (ret) | 8398 | if (ret) |
| 8323 | fput(file); | 8399 | fput(file); |
| 8324 | return ret; | 8400 | return ret; |
| 8325 | } | 8401 | } |
| 8326 | 8402 | ||
| 8327 | static int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx, | ||
| 8328 | struct io_rsrc_node *node, void *rsrc) | ||
| 8329 | { | ||
| 8330 | struct io_rsrc_put *prsrc; | ||
| 8331 | |||
| 8332 | prsrc = kzalloc(sizeof(*prsrc), GFP_KERNEL); | ||
| 8333 | if (!prsrc) | ||
| 8334 | return -ENOMEM; | ||
| 8335 | |||
| 8336 | prsrc->tag = *io_get_tag_slot(data, idx); | ||
| 8337 | prsrc->rsrc = rsrc; | ||
| 8338 | list_add(&prsrc->list, &node->rsrc_list); | ||
| 8339 | return 0; | ||
| 8340 | } | ||
| 8341 | |||
| 8342 | static int __io_sqe_files_update(struct io_ring_ctx *ctx, | 8403 | static int __io_sqe_files_update(struct io_ring_ctx *ctx, |
| 8343 | struct io_uring_rsrc_update2 *up, | 8404 | struct io_uring_rsrc_update2 *up, |
| 8344 | unsigned nr_args) | 8405 | unsigned nr_args) |
| @@ -10560,10 +10621,12 @@ static int io_register_iowq_max_workers(struct io_ring_ctx *ctx, · 2215 unmodified lines | |||
| 10560 | * ordering. Fine to drop uring_lock here, we hold | 10621 | * ordering. Fine to drop uring_lock here, we hold |
| 10561 | * a ref to the ctx. | 10622 | * a ref to the ctx. |
| 10562 | */ | 10623 | */ |
| 10624 | refcount_inc(&sqd->refs); | ||
| 10563 | mutex_unlock(&ctx->uring_lock); | 10625 | mutex_unlock(&ctx->uring_lock); |
| 10564 | mutex_lock(&sqd->lock); | 10626 | mutex_lock(&sqd->lock); |
| 10565 | mutex_lock(&ctx->uring_lock); | 10627 | mutex_lock(&ctx->uring_lock); |
| 10566 | tctx = sqd->thread->io_uring; | 10628 | if (sqd->thread) |
| 10629 | tctx = sqd->thread->io_uring; | ||
| 10567 | } | 10630 | } |
| 10568 | } else { | 10631 | } else { |
| 10569 | tctx = current->io_uring; | 10632 | tctx = current->io_uring; |
| @@ -10577,16 +10640,20 @@ static int io_register_iowq_max_workers(struct io_ring_ctx *ctx, · 7 unmodified lines | |||
| 10577 | if (ret) | 10640 | if (ret) |
| 10578 | goto err; | 10641 | goto err; |
| 10579 | 10642 | ||
| 10580 | if (sqd) | 10643 | if (sqd) { |
| 10581 | mutex_unlock(&sqd->lock); | 10644 | mutex_unlock(&sqd->lock); |
| 10645 | io_put_sq_data(sqd); | ||
| 10646 | } | ||
| 10582 | 10647 | ||
| 10583 | if (copy_to_user(arg, new_count, sizeof(new_count))) | 10648 | if (copy_to_user(arg, new_count, sizeof(new_count))) |
| 10584 | return -EFAULT; | 10649 | return -EFAULT; |
| 10585 | 10650 | ||
| 10586 | return 0; | 10651 | return 0; |
| 10587 | err: | 10652 | err: |
| 10588 | if (sqd) | 10653 | if (sqd) { |
| 10589 | mutex_unlock(&sqd->lock); | 10654 | mutex_unlock(&sqd->lock); |
| 10655 | io_put_sq_data(sqd); | ||
| 10656 | } | ||
| 10590 | return ret; | 10657 | return ret; |
| 10591 | } | 10658 | } |
| 10592 | 10659 | ||
| @@ -191,19 +191,77 @@ int get_nlink(struct kstat *st) · 190 unmodified lines | |||
| 191 | return nlink; | 191 | return nlink; |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | void ksmbd_conv_path_to_unix(char *path) | 194 | char *ksmbd_conv_path_to_unix(char *path) |
| 195 | { | 195 | { |
| 196 | size_t path_len, remain_path_len, out_path_len; | ||
| 197 | char *out_path, *out_next; | ||
| 198 | int i, pre_dotdot_cnt = 0, slash_cnt = 0; | ||
| 199 | bool is_last; | ||
| 200 | |||
| 196 | strreplace(path, '\\', '/'); | 201 | strreplace(path, '\\', '/'); |
| 197 | } | 202 | path_len = strlen(path); |
| 203 | remain_path_len = path_len; | ||
| 204 | if (path_len == 0) | ||
| 205 | return ERR_PTR(-EINVAL); | ||
| 198 | 206 | ||
| 199 | void ksmbd_strip_last_slash(char *path) | 207 | out_path = kzalloc(path_len + 2, GFP_KERNEL); |
| 200 | { | 208 | if (!out_path) |
| 201 | int len = strlen(path); | 209 | return ERR_PTR(-ENOMEM); |
| 210 | out_path_len = 0; | ||
| 211 | out_next = out_path; | ||
| 212 | |||
| 213 | do { | ||
| 214 | char *name = path + path_len - remain_path_len; | ||
| 215 | char *next = strchrnul(name, '/'); | ||
| 216 | size_t name_len = next - name; | ||
| 217 | |||
| 218 | is_last = !next[0]; | ||
| 219 | if (name_len == 2 && name[0] == '.' && name[1] == '.') { | ||
| 220 | pre_dotdot_cnt++; | ||
| 221 | /* handle the case that path ends with "/.." */ | ||
| 222 | if (is_last) | ||
| 223 | goto follow_dotdot; | ||
| 224 | } else { | ||
| 225 | if (pre_dotdot_cnt) { | ||
| 226 | follow_dotdot: | ||
| 227 | slash_cnt = 0; | ||
| 228 | for (i = out_path_len - 1; i >= 0; i--) { | ||
| 229 | if (out_path[i] == '/' && | ||
| 230 | ++slash_cnt == pre_dotdot_cnt + 1) | ||
| 231 | break; | ||
| 232 | } | ||
| 233 | |||
| 234 | if (i < 0 && | ||
| 235 | slash_cnt != pre_dotdot_cnt) { | ||
| 236 | kfree(out_path); | ||
| 237 | return ERR_PTR(-EINVAL); | ||
| 238 | } | ||
| 239 | |||
| 240 | out_next = &out_path[i+1]; | ||
| 241 | *out_next = '\0'; | ||
| 242 | out_path_len = i + 1; | ||
| 202 | 243 | ||
| 203 | while (len && path[len - 1] == '/') { | 244 | } |
| 204 | path[len - 1] = '\0'; | 245 | |
| 205 | len--; | 246 | if (name_len != 0 && |
| 206 | } | 247 | !(name_len == 1 && name[0] == '.') && |
| 248 | !(name_len == 2 && name[0] == '.' && name[1] == '.')) { | ||
| 249 | next[0] = '\0'; | ||
| 250 | sprintf(out_next, "%s/", name); | ||
| 251 | out_next += name_len + 1; | ||
| 252 | out_path_len += name_len + 1; | ||
| 253 | next[0] = '/'; | ||
| 254 | } | ||
| 255 | pre_dotdot_cnt = 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | remain_path_len -= name_len + 1; | ||
| 259 | } while (!is_last); | ||
| 260 | |||
| 261 | if (out_path_len > 0) | ||
| 262 | out_path[out_path_len-1] = '\0'; | ||
| 263 | path[path_len] = '\0'; | ||
| 264 | return out_path; | ||
| 207 | } | 265 | } |
| 208 | 266 | ||
| 209 | void ksmbd_conv_path_to_windows(char *path) | 267 | void ksmbd_conv_path_to_windows(char *path) |
| @@ -16,8 +16,7 @@ int ksmbd_validate_filename(char *filename); · 15 unmodified lines | |||
| 16 | int parse_stream_name(char *filename, char **stream_name, int *s_type); | 16 | int parse_stream_name(char *filename, char **stream_name, int *s_type); |
| 17 | char *convert_to_nt_pathname(char *filename, char *sharepath); | 17 | char *convert_to_nt_pathname(char *filename, char *sharepath); |
| 18 | int get_nlink(struct kstat *st); | 18 | int get_nlink(struct kstat *st); |
| 19 | void ksmbd_conv_path_to_unix(char *path); | 19 | char *ksmbd_conv_path_to_unix(char *path); |
| 20 | void ksmbd_strip_last_slash(char *path); | ||
| 21 | void ksmbd_conv_path_to_windows(char *path); | 20 | void ksmbd_conv_path_to_windows(char *path); |
| 22 | char *ksmbd_extract_sharename(char *treename); | 21 | char *ksmbd_extract_sharename(char *treename); |
| 23 | char *convert_to_unix_name(struct ksmbd_share_config *share, char *name); | 22 | char *convert_to_unix_name(struct ksmbd_share_config *share, char *name); |
| @@ -634,7 +634,7 @@ static char * · 633 unmodified lines | |||
| 634 | smb2_get_name(struct ksmbd_share_config *share, const char *src, | 634 | smb2_get_name(struct ksmbd_share_config *share, const char *src, |
| 635 | const int maxlen, struct nls_table *local_nls) | 635 | const int maxlen, struct nls_table *local_nls) |
| 636 | { | 636 | { |
| 637 | char *name, *unixname; | 637 | char *name, *norm_name, *unixname; |
| 638 | 638 | ||
| 639 | name = smb_strndup_from_utf16(src, maxlen, 1, local_nls); | 639 | name = smb_strndup_from_utf16(src, maxlen, 1, local_nls); |
| 640 | if (IS_ERR(name)) { | 640 | if (IS_ERR(name)) { |
| @@ -643,11 +643,15 @@ smb2_get_name(struct ksmbd_share_config *share, const char *src, · 2 unmodified lines | |||
| 643 | } | 643 | } |
| 644 | 644 | ||
| 645 | /* change it to absolute unix name */ | 645 | /* change it to absolute unix name */ |
| 646 | ksmbd_conv_path_to_unix(name); | 646 | norm_name = ksmbd_conv_path_to_unix(name); |
| 647 | ksmbd_strip_last_slash(name); | 647 | if (IS_ERR(norm_name)) { |
| 648 | 648 | kfree(name); | |
| 649 | unixname = convert_to_unix_name(share, name); | 649 | return norm_name; |
| 650 | } | ||
| 650 | kfree(name); | 651 | kfree(name); |
| 652 | |||
| 653 | unixname = convert_to_unix_name(share, norm_name); | ||
| 654 | kfree(norm_name); | ||
| 651 | if (!unixname) { | 655 | if (!unixname) { |
| 652 | pr_err("can not convert absolute name\n"); | 656 | pr_err("can not convert absolute name\n"); |
| 653 | return ERR_PTR(-ENOMEM); | 657 | return ERR_PTR(-ENOMEM); |
| @@ -4041,6 +4045,10 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp, · 3387 unmodified lines | |||
| 4041 | path = &fp->filp->f_path; | 4045 | path = &fp->filp->f_path; |
| 4042 | /* single EA entry is requested with given user.* name */ | 4046 | /* single EA entry is requested with given user.* name */ |
| 4043 | if (req->InputBufferLength) { | 4047 | if (req->InputBufferLength) { |
| 4048 | if (le32_to_cpu(req->InputBufferLength) < | ||
| 4049 | sizeof(struct smb2_ea_info_req)) | ||
| 4050 | return -EINVAL; | ||
| 4051 | |||
| 4044 | ea_req = (struct smb2_ea_info_req *)req->Buffer; | 4052 | ea_req = (struct smb2_ea_info_req *)req->Buffer; |
| 4045 | } else { | 4053 | } else { |
| 4046 | /* need to send all EAs, if no specific EA is requested*/ | 4054 | /* need to send all EAs, if no specific EA is requested*/ |
| @@ -20,7 +20,6 @@ · 19 unmodified lines | |||
| 20 | #define SUBMOD_NAME "smb_direct" | 20 | #define SUBMOD_NAME "smb_direct" |
| 21 | 21 | ||
| 22 | #include <linux/kthread.h> | 22 | #include <linux/kthread.h> |
| 23 | #include <linux/rwlock.h> | ||
| 24 | #include <linux/list.h> | 23 | #include <linux/list.h> |
| 25 | #include <linux/mempool.h> | 24 | #include <linux/mempool.h> |
| 26 | #include <linux/highmem.h> | 25 | #include <linux/highmem.h> |
| @@ -134,18 +134,9 @@ svcxdr_decode_owner(struct xdr_stream *xdr, struct xdr_netobj *obj) · 133 unmodified lines | |||
| 134 | static inline bool | 134 | static inline bool |
| 135 | svcxdr_encode_owner(struct xdr_stream *xdr, const struct xdr_netobj *obj) | 135 | svcxdr_encode_owner(struct xdr_stream *xdr, const struct xdr_netobj *obj) |
| 136 | { | 136 | { |
| 137 | unsigned int quadlen = XDR_QUADLEN(obj->len); | 137 | if (obj->len > XDR_MAX_NETOBJ) |
| 138 | __be32 *p; | ||
| 139 | |||
| 140 | if (xdr_stream_encode_u32(xdr, obj->len) < 0) | ||
| 141 | return false; | ||
| 142 | p = xdr_reserve_space(xdr, obj->len); | ||
| 143 | if (!p) | ||
| 144 | return false; | 138 | return false; |
| 145 | p[quadlen - 1] = 0; /* XDR pad */ | 139 | return xdr_stream_encode_opaque(xdr, obj->data, obj->len) > 0; |
| 146 | memcpy(p, obj->data, obj->len); | ||
| 147 | |||
| 148 | return true; | ||
| 149 | } | 140 | } |
| 150 | 141 | ||
| 151 | #endif /* _LOCKD_SVCXDR_H_ */ | 142 | #endif /* _LOCKD_SVCXDR_H_ */ |
| @@ -3570,7 +3570,7 @@ static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_s · 3569 unmodified lines | |||
| 3570 | } | 3570 | } |
| 3571 | 3571 | ||
| 3572 | static __be32 nfsd4_match_existing_connection(struct svc_rqst *rqst, | 3572 | static __be32 nfsd4_match_existing_connection(struct svc_rqst *rqst, |
| 3573 | struct nfsd4_session *session, u32 req) | 3573 | struct nfsd4_session *session, u32 req, struct nfsd4_conn **conn) |
| 3574 | { | 3574 | { |
| 3575 | struct nfs4_client *clp = session->se_client; | 3575 | struct nfs4_client *clp = session->se_client; |
| 3576 | struct svc_xprt *xpt = rqst->rq_xprt; | 3576 | struct svc_xprt *xpt = rqst->rq_xprt; |
| @@ -3593,6 +3593,8 @@ static __be32 nfsd4_match_existing_connection(struct svc_rqst *rqst, · 16 unmodified lines | |||
| 3593 | else | 3593 | else |
| 3594 | status = nfserr_inval; | 3594 | status = nfserr_inval; |
| 3595 | spin_unlock(&clp->cl_lock); | 3595 | spin_unlock(&clp->cl_lock); |
| 3596 | if (status == nfs_ok && conn) | ||
| 3597 | *conn = c; | ||
| 3596 | return status; | 3598 | return status; |
| 3597 | } | 3599 | } |
| 3598 | 3600 | ||
| @@ -3617,8 +3619,16 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp, · 18 unmodified lines | |||
| 3617 | status = nfserr_wrong_cred; | 3619 | status = nfserr_wrong_cred; |
| 3618 | if (!nfsd4_mach_creds_match(session->se_client, rqstp)) | 3620 | if (!nfsd4_mach_creds_match(session->se_client, rqstp)) |
| 3619 | goto out; | 3621 | goto out; |
| 3620 | status = nfsd4_match_existing_connection(rqstp, session, bcts->dir); | 3622 | status = nfsd4_match_existing_connection(rqstp, session, |
| 3621 | if (status == nfs_ok || status == nfserr_inval) | 3623 | bcts->dir, &conn); |
| 3624 | if (status == nfs_ok) { | ||
| 3625 | if (bcts->dir == NFS4_CDFC4_FORE_OR_BOTH || | ||
| 3626 | bcts->dir == NFS4_CDFC4_BACK) | ||
| 3627 | conn->cn_flags |= NFS4_CDFC4_BACK; | ||
| 3628 | nfsd4_probe_callback(session->se_client); | ||
| 3629 | goto out; | ||
| 3630 | } | ||
| 3631 | if (status == nfserr_inval) | ||
| 3622 | goto out; | 3632 | goto out; |
| 3623 | status = nfsd4_map_bcts_dir(&bcts->dir); | 3633 | status = nfsd4_map_bcts_dir(&bcts->dir); |
| 3624 | if (status) | 3634 | if (status) |
| @@ -20,12 +20,33 @@ · 19 unmodified lines | |||
| 20 | * depending on the status field in the last byte. The | 20 | * depending on the status field in the last byte. The |
| 21 | * first byte is where the name start either way, and a | 21 | * first byte is where the name start either way, and a |
| 22 | * zero means it's empty. | 22 | * zero means it's empty. |
| 23 | * | ||
| 24 | * Also, due to a bug in gcc, we don't want to use the | ||
| 25 | * real (differently sized) name arrays in the inode and | ||
| 26 | * link entries, but always the 'de_name[]' one in the | ||
| 27 | * fake struct entry. | ||
| 28 | * | ||
| 29 | * See | ||
| 30 | * | ||
| 31 | * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578#c6 | ||
| 32 | * | ||
| 33 | * for details, but basically gcc will take the size of the | ||
| 34 | * 'name' array from one of the used union entries randomly. | ||
| 35 | * | ||
| 36 | * This use of 'de_name[]' (48 bytes) avoids the false positive | ||
| 37 | * warnings that would happen if gcc decides to use 'inode.di_name' | ||
| 38 | * (16 bytes) even when the pointer and size were to come from | ||
| 39 | * 'link.dl_name' (48 bytes). | ||
| 40 | * | ||
| 41 | * In all cases the actual name pointer itself is the same, it's | ||
| 42 | * only the gcc internal 'what is the size of this field' logic | ||
| 43 | * that can get confused. | ||
| 23 | */ | 44 | */ |
| 24 | union qnx4_directory_entry { | 45 | union qnx4_directory_entry { |
| 25 | struct { | 46 | struct { |
| 26 | char de_name; | 47 | const char de_name[48]; |
| 27 | char de_pad[62]; | 48 | u8 de_pad[15]; |
| 28 | char de_status; | 49 | u8 de_status; |
| 29 | }; | 50 | }; |
| 30 | struct qnx4_inode_entry inode; | 51 | struct qnx4_inode_entry inode; |
| 31 | struct qnx4_link_info link; | 52 | struct qnx4_link_info link; |
| @@ -53,29 +74,26 @@ static int qnx4_readdir(struct file *file, struct dir_context *ctx) · 21 unmodified lines | |||
| 53 | ix = (ctx->pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK; | 74 | ix = (ctx->pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK; |
| 54 | for (; ix < QNX4_INODES_PER_BLOCK; ix++, ctx->pos += QNX4_DIR_ENTRY_SIZE) { | 75 | for (; ix < QNX4_INODES_PER_BLOCK; ix++, ctx->pos += QNX4_DIR_ENTRY_SIZE) { |
| 55 | union qnx4_directory_entry *de; | 76 | union qnx4_directory_entry *de; |
| 56 | const char *name; | ||
| 57 | 77 | ||
| 58 | offset = ix * QNX4_DIR_ENTRY_SIZE; | 78 | offset = ix * QNX4_DIR_ENTRY_SIZE; |
| 59 | de = (union qnx4_directory_entry *) (bh->b_data + offset); | 79 | de = (union qnx4_directory_entry *) (bh->b_data + offset); |
| 60 | 80 | ||
| 61 | if (!de->de_name) | 81 | if (!de->de_name[0]) |
| 62 | continue; | 82 | continue; |
| 63 | if (!(de->de_status & (QNX4_FILE_USED|QNX4_FILE_LINK))) | 83 | if (!(de->de_status & (QNX4_FILE_USED|QNX4_FILE_LINK))) |
| 64 | continue; | 84 | continue; |
| 65 | if (!(de->de_status & QNX4_FILE_LINK)) { | 85 | if (!(de->de_status & QNX4_FILE_LINK)) { |
| 66 | size = sizeof(de->inode.di_fname); | 86 | size = sizeof(de->inode.di_fname); |
| 67 | name = de->inode.di_fname; | ||
| 68 | ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1; | 87 | ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1; |
| 69 | } else { | 88 | } else { |
| 70 | size = sizeof(de->link.dl_fname); | 89 | size = sizeof(de->link.dl_fname); |
| 71 | name = de->link.dl_fname; | ||
| 72 | ino = ( le32_to_cpu(de->link.dl_inode_blk) - 1 ) * | 90 | ino = ( le32_to_cpu(de->link.dl_inode_blk) - 1 ) * |
| 73 | QNX4_INODES_PER_BLOCK + | 91 | QNX4_INODES_PER_BLOCK + |
| 74 | de->link.dl_inode_ndx; | 92 | de->link.dl_inode_ndx; |
| 75 | } | 93 | } |
| 76 | size = strnlen(name, size); | 94 | size = strnlen(de->de_name, size); |
| 77 | QNX4DEBUG((KERN_INFO "qnx4_readdir:%.*s\n", size, name)); | 95 | QNX4DEBUG((KERN_INFO "qnx4_readdir:%.*s\n", size, name)); |
| 78 | if (!dir_emit(ctx, name, size, ino, DT_UNKNOWN)) { | 96 | if (!dir_emit(ctx, de->de_name, size, ino, DT_UNKNOWN)) { |
| 79 | brelse(bh); | 97 | brelse(bh); |
| 80 | return 0; | 98 | return 0; |
| 81 | } | 99 | } |
| @@ -1,6 +1,6 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
| 2 | /* | 2 | /* |
| 3 | * fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions | 3 | * SMB, CIFS, SMB2 FSCTL definitions |
| 4 | * | 4 | * |
| 5 | * Copyright (c) International Business Machines Corp., 2002,2013 | 5 | * Copyright (c) International Business Machines Corp., 2002,2013 |
| 6 | * Author(s): Steve French (sfrench@us.ibm.com) | 6 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1023,16 +1023,7 @@ static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) · 1022 unmodified lines | |||
| 1023 | port &= IO_SPACE_LIMIT; | 1023 | port &= IO_SPACE_LIMIT; |
| 1024 | return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port; | 1024 | return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port; |
| 1025 | } | 1025 | } |
| 1026 | #define __pci_ioport_unmap __pci_ioport_unmap | 1026 | #define ARCH_HAS_GENERIC_IOPORT_MAP |
| 1027 | static inline void __pci_ioport_unmap(void __iomem *p) | ||
| 1028 | { | ||
| 1029 | uintptr_t start = (uintptr_t) PCI_IOBASE; | ||
| 1030 | uintptr_t addr = (uintptr_t) p; | ||
| 1031 | |||
| 1032 | if (addr >= start && addr < start + IO_SPACE_LIMIT) | ||
| 1033 | return; | ||
| 1034 | iounmap(p); | ||
| 1035 | } | ||
| 1036 | #endif | 1027 | #endif |
| 1037 | 1028 | ||
| 1038 | #ifndef ioport_unmap | 1029 | #ifndef ioport_unmap |
| @@ -1048,21 +1039,10 @@ extern void ioport_unmap(void __iomem *p); · 9 unmodified lines | |||
| 1048 | #endif /* CONFIG_HAS_IOPORT_MAP */ | 1039 | #endif /* CONFIG_HAS_IOPORT_MAP */ |
| 1049 | 1040 | ||
| 1050 | #ifndef CONFIG_GENERIC_IOMAP | 1041 | #ifndef CONFIG_GENERIC_IOMAP |
| 1051 | struct pci_dev; | ||
| 1052 | extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); | ||
| 1053 | |||
| 1054 | #ifndef __pci_ioport_unmap | ||
| 1055 | static inline void __pci_ioport_unmap(void __iomem *p) {} | ||
| 1056 | #endif | ||
| 1057 | |||
| 1058 | #ifndef pci_iounmap | 1042 | #ifndef pci_iounmap |
| 1059 | #define pci_iounmap pci_iounmap | 1043 | #define ARCH_WANTS_GENERIC_PCI_IOUNMAP |
| 1060 | static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p) | 1044 | #endif |
| 1061 | { | ||
| 1062 | __pci_ioport_unmap(p); | ||
| 1063 | } | ||
| 1064 | #endif | 1045 | #endif |
| 1065 | #endif /* CONFIG_GENERIC_IOMAP */ | ||
| 1066 | 1046 | ||
| 1067 | #ifndef xlate_dev_mem_ptr | 1047 | #ifndef xlate_dev_mem_ptr |
| 1068 | #define xlate_dev_mem_ptr xlate_dev_mem_ptr | 1048 | #define xlate_dev_mem_ptr xlate_dev_mem_ptr |
| @@ -110,16 +110,6 @@ static inline void __iomem *ioremap_np(phys_addr_t offset, size_t size) · 109 unmodified lines | |||
| 110 | } | 110 | } |
| 111 | #endif | 111 | #endif |
| 112 | 112 | ||
| 113 | #ifdef CONFIG_PCI | ||
| 114 | /* Destroy a virtual mapping cookie for a PCI BAR (memory or IO) */ | ||
| 115 | struct pci_dev; | ||
| 116 | extern void pci_iounmap(struct pci_dev *dev, void __iomem *); | ||
| 117 | #elif defined(CONFIG_GENERIC_IOMAP) | ||
| 118 | struct pci_dev; | ||
| 119 | static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) | ||
| 120 | { } | ||
| 121 | #endif | ||
| 122 | |||
| 123 | #include <asm-generic/pci_iomap.h> | 113 | #include <asm-generic/pci_iomap.h> |
| 124 | 114 | ||
| 125 | #endif | 115 | #endif |
| @@ -18,6 +18,7 @@ extern void __iomem *pci_iomap_range(struct pci_dev *dev, int bar, · 17 unmodified lines | |||
| 18 | extern void __iomem *pci_iomap_wc_range(struct pci_dev *dev, int bar, | 18 | extern void __iomem *pci_iomap_wc_range(struct pci_dev *dev, int bar, |
| 19 | unsigned long offset, | 19 | unsigned long offset, |
| 20 | unsigned long maxlen); | 20 | unsigned long maxlen); |
| 21 | extern void pci_iounmap(struct pci_dev *dev, void __iomem *); | ||
| 21 | /* Create a virtual mapping cookie for a port on a given PCI device. | 22 | /* Create a virtual mapping cookie for a port on a given PCI device. |
| 22 | * Do not call this directly, it exists to make it easier for architectures | 23 | * Do not call this directly, it exists to make it easier for architectures |
| 23 | * to override */ | 24 | * to override */ |
| @@ -50,6 +51,8 @@ static inline void __iomem *pci_iomap_wc_range(struct pci_dev *dev, int bar, · 26 unmodified lines | |||
| 50 | { | 51 | { |
| 51 | return NULL; | 52 | return NULL; |
| 52 | } | 53 | } |
| 54 | static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) | ||
| 55 | { } | ||
| 53 | #endif | 56 | #endif |
| 54 | 57 | ||
| 55 | #endif /* __ASM_GENERIC_PCI_IOMAP_H */ | 58 | #endif /* __ASM_GENERIC_PCI_IOMAP_H */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 | 1 | /* SPDX-License-Identifier: GPL-2.0 |
| 2 | * Copyright 2019-2021 NXP Semiconductors | 2 | * Copyright 2019-2021 NXP |
| 3 | */ | 3 | */ |
| 4 | 4 | ||
| 5 | #ifndef _NET_DSA_TAG_OCELOT_H | 5 | #ifndef _NET_DSA_TAG_OCELOT_H |
| @@ -80,6 +80,9 @@ struct mdio_driver { · 79 unmodified lines | |||
| 80 | 80 | ||
| 81 | /* Clears up any memory if needed */ | 81 | /* Clears up any memory if needed */ |
| 82 | void (*remove)(struct mdio_device *mdiodev); | 82 | void (*remove)(struct mdio_device *mdiodev); |
| 83 | |||
| 84 | /* Quiesces the device on system shutdown, turns off interrupts etc */ | ||
| 85 | void (*shutdown)(struct mdio_device *mdiodev); | ||
| 83 | }; | 86 | }; |
| 84 | 87 | ||
| 85 | static inline struct mdio_driver * | 88 | static inline struct mdio_driver * |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: BSD-3-Clause | 1 | /* SPDX-License-Identifier: BSD-3-Clause |
| 2 | * Copyright (c) 2016-2018, NXP Semiconductors | 2 | * Copyright 2016-2018 NXP |
| 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> | 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 4 | */ | 4 | */ |
| 5 | #ifndef _LINUX_PACKING_H | 5 | #ifndef _LINUX_PACKING_H |
| @@ -1471,6 +1471,7 @@ struct task_struct { · 1470 unmodified lines | |||
| 1471 | mce_whole_page : 1, | 1471 | mce_whole_page : 1, |
| 1472 | __mce_reserved : 62; | 1472 | __mce_reserved : 62; |
| 1473 | struct callback_head mce_kill_me; | 1473 | struct callback_head mce_kill_me; |
| 1474 | int mce_count; | ||
| 1474 | #endif | 1475 | #endif |
| 1475 | 1476 | ||
| 1476 | #ifdef CONFIG_KRETPROBES | 1477 | #ifdef CONFIG_KRETPROBES |
| @@ -27,6 +27,12 @@ enum iter_type { · 26 unmodified lines | |||
| 27 | ITER_DISCARD, | 27 | ITER_DISCARD, |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | struct iov_iter_state { | ||
| 31 | size_t iov_offset; | ||
| 32 | size_t count; | ||
| 33 | unsigned long nr_segs; | ||
| 34 | }; | ||
| 35 | |||
| 30 | struct iov_iter { | 36 | struct iov_iter { |
| 31 | u8 iter_type; | 37 | u8 iter_type; |
| 32 | bool data_source; | 38 | bool data_source; |
| @@ -47,7 +53,6 @@ struct iov_iter { · 14 unmodified lines | |||
| 47 | }; | 53 | }; |
| 48 | loff_t xarray_start; | 54 | loff_t xarray_start; |
| 49 | }; | 55 | }; |
| 50 | size_t truncated; | ||
| 51 | }; | 56 | }; |
| 52 | 57 | ||
| 53 | static inline enum iter_type iov_iter_type(const struct iov_iter *i) | 58 | static inline enum iter_type iov_iter_type(const struct iov_iter *i) |
| @@ -55,6 +60,14 @@ static inline enum iter_type iov_iter_type(const struct iov_iter *i) · 1 unmodified line | |||
| 55 | return i->iter_type; | 60 | return i->iter_type; |
| 56 | } | 61 | } |
| 57 | 62 | ||
| 63 | static inline void iov_iter_save_state(struct iov_iter *iter, | ||
| 64 | struct iov_iter_state *state) | ||
| 65 | { | ||
| 66 | state->iov_offset = iter->iov_offset; | ||
| 67 | state->count = iter->count; | ||
| 68 | state->nr_segs = iter->nr_segs; | ||
| 69 | } | ||
| 70 | |||
| 58 | static inline bool iter_is_iovec(const struct iov_iter *i) | 71 | static inline bool iter_is_iovec(const struct iov_iter *i) |
| 59 | { | 72 | { |
| 60 | return iov_iter_type(i) == ITER_IOVEC; | 73 | return iov_iter_type(i) == ITER_IOVEC; |
| @@ -233,6 +246,7 @@ ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages, · 172 unmodified lines | |||
| 233 | ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages, | 246 | ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages, |
| 234 | size_t maxsize, size_t *start); | 247 | size_t maxsize, size_t *start); |
| 235 | int iov_iter_npages(const struct iov_iter *i, int maxpages); | 248 | int iov_iter_npages(const struct iov_iter *i, int maxpages); |
| 249 | void iov_iter_restore(struct iov_iter *i, struct iov_iter_state *state); | ||
| 236 | 250 | ||
| 237 | const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags); | 251 | const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags); |
| 238 | 252 | ||
| @@ -255,10 +269,8 @@ static inline void iov_iter_truncate(struct iov_iter *i, u64 count) · 16 unmodified lines | |||
| 255 | * conversion in assignement is by definition greater than all | 269 | * conversion in assignement is by definition greater than all |
| 256 | * values of size_t, including old i->count. | 270 | * values of size_t, including old i->count. |
| 257 | */ | 271 | */ |
| 258 | if (i->count > count) { | 272 | if (i->count > count) |
| 259 | i->truncated += i->count - count; | ||
| 260 | i->count = count; | 273 | i->count = count; |
| 261 | } | ||
| 262 | } | 274 | } |
| 263 | 275 | ||
| 264 | /* | 276 | /* |
| @@ -267,7 +279,6 @@ static inline void iov_iter_truncate(struct iov_iter *i, u64 count) · 2 unmodified lines | |||
| 267 | */ | 279 | */ |
| 268 | static inline void iov_iter_reexpand(struct iov_iter *i, size_t count) | 280 | static inline void iov_iter_reexpand(struct iov_iter *i, size_t count) |
| 269 | { | 281 | { |
| 270 | i->truncated -= count - i->count; | ||
| 271 | i->count = count; | 282 | i->count = count; |
| 272 | } | 283 | } |
| 273 | 284 | ||
| @@ -585,8 +585,16 @@ struct dsa_switch_ops { · 584 unmodified lines | |||
| 585 | int (*change_tag_protocol)(struct dsa_switch *ds, int port, | 585 | int (*change_tag_protocol)(struct dsa_switch *ds, int port, |
| 586 | enum dsa_tag_protocol proto); | 586 | enum dsa_tag_protocol proto); |
| 587 | 587 | ||
| 588 | /* Optional switch-wide initialization and destruction methods */ | ||
| 588 | int (*setup)(struct dsa_switch *ds); | 589 | int (*setup)(struct dsa_switch *ds); |
| 589 | void (*teardown)(struct dsa_switch *ds); | 590 | void (*teardown)(struct dsa_switch *ds); |
| 591 | |||
| 592 | /* Per-port initialization and destruction methods. Mandatory if the | ||
| 593 | * driver registers devlink port regions, optional otherwise. | ||
| 594 | */ | ||
| 595 | int (*port_setup)(struct dsa_switch *ds, int port); | ||
| 596 | void (*port_teardown)(struct dsa_switch *ds, int port); | ||
| 597 | |||
| 590 | u32 (*get_phy_flags)(struct dsa_switch *ds, int port); | 598 | u32 (*get_phy_flags)(struct dsa_switch *ds, int port); |
| 591 | 599 | ||
| 592 | /* | 600 | /* |
| @@ -1046,6 +1054,7 @@ static inline int dsa_ndo_eth_ioctl(struct net_device *dev, struct ifreq *ifr, · 453 unmodified lines | |||
| 1046 | 1054 | ||
| 1047 | void dsa_unregister_switch(struct dsa_switch *ds); | 1055 | void dsa_unregister_switch(struct dsa_switch *ds); |
| 1048 | int dsa_register_switch(struct dsa_switch *ds); | 1056 | int dsa_register_switch(struct dsa_switch *ds); |
| 1057 | void dsa_switch_shutdown(struct dsa_switch *ds); | ||
| 1049 | struct dsa_switch *dsa_switch_find(int tree_index, int sw_index); | 1058 | struct dsa_switch *dsa_switch_find(int tree_index, int sw_index); |
| 1050 | #ifdef CONFIG_PM_SLEEP | 1059 | #ifdef CONFIG_PM_SLEEP |
| 1051 | int dsa_switch_suspend(struct dsa_switch *ds); | 1060 | int dsa_switch_suspend(struct dsa_switch *ds); |
| @@ -1628,6 +1628,7 @@ static inline void unlock_sock_fast(struct sock *sk, bool slow) · 1627 unmodified lines | |||
| 1628 | release_sock(sk); | 1628 | release_sock(sk); |
| 1629 | __release(&sk->sk_lock.slock); | 1629 | __release(&sk->sk_lock.slock); |
| 1630 | } else { | 1630 | } else { |
| 1631 | mutex_release(&sk->sk_lock.dep_map, _RET_IP_); | ||
| 1631 | spin_unlock_bh(&sk->sk_lock.slock); | 1632 | spin_unlock_bh(&sk->sk_lock.slock); |
| 1632 | } | 1633 | } |
| 1633 | } | 1634 | } |
| @@ -306,11 +306,13 @@ enum afs_flock_operation { · 305 unmodified lines | |||
| 306 | 306 | ||
| 307 | enum afs_cb_break_reason { | 307 | enum afs_cb_break_reason { |
| 308 | afs_cb_break_no_break, | 308 | afs_cb_break_no_break, |
| 309 | afs_cb_break_no_promise, | ||
| 309 | afs_cb_break_for_callback, | 310 | afs_cb_break_for_callback, |
| 310 | afs_cb_break_for_deleted, | 311 | afs_cb_break_for_deleted, |
| 311 | afs_cb_break_for_lapsed, | 312 | afs_cb_break_for_lapsed, |
| 313 | afs_cb_break_for_s_reinit, | ||
| 312 | afs_cb_break_for_unlink, | 314 | afs_cb_break_for_unlink, |
| 313 | afs_cb_break_for_vsbreak, | 315 | afs_cb_break_for_v_break, |
| 314 | afs_cb_break_for_volume_callback, | 316 | afs_cb_break_for_volume_callback, |
| 315 | afs_cb_break_for_zap, | 317 | afs_cb_break_for_zap, |
| 316 | }; | 318 | }; |
| @@ -602,11 +604,13 @@ enum afs_cb_break_reason { · 285 unmodified lines | |||
| 602 | 604 | ||
| 603 | #define afs_cb_break_reasons \ | 605 | #define afs_cb_break_reasons \ |
| 604 | EM(afs_cb_break_no_break, "no-break") \ | 606 | EM(afs_cb_break_no_break, "no-break") \ |
| 607 | EM(afs_cb_break_no_promise, "no-promise") \ | ||
| 605 | EM(afs_cb_break_for_callback, "break-cb") \ | 608 | EM(afs_cb_break_for_callback, "break-cb") \ |
| 606 | EM(afs_cb_break_for_deleted, "break-del") \ | 609 | EM(afs_cb_break_for_deleted, "break-del") \ |
| 607 | EM(afs_cb_break_for_lapsed, "break-lapsed") \ | 610 | EM(afs_cb_break_for_lapsed, "break-lapsed") \ |
| 611 | EM(afs_cb_break_for_s_reinit, "s-reinit") \ | ||
| 608 | EM(afs_cb_break_for_unlink, "break-unlink") \ | 612 | EM(afs_cb_break_for_unlink, "break-unlink") \ |
| 609 | EM(afs_cb_break_for_vsbreak, "break-vs") \ | 613 | EM(afs_cb_break_for_v_break, "break-v") \ |
| 610 | EM(afs_cb_break_for_volume_callback, "break-v-cb") \ | 614 | EM(afs_cb_break_for_volume_callback, "break-v-cb") \ |
| 611 | E_(afs_cb_break_for_zap, "break-zap") | 615 | E_(afs_cb_break_for_zap, "break-zap") |
| 612 | 616 | ||
| @@ -1,6 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */ | 1 | /* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */ |
| 2 | /* | 2 | /* |
| 3 | * include/uapi/linux/cifs/cifs_mount.h | ||
| 4 | * | 3 | * |
| 5 | * Author(s): Scott Lovenberg (scott.lovenberg@gmail.com) | 4 | * Author(s): Scott Lovenberg (scott.lovenberg@gmail.com) |
| 6 | * | 5 | * |
| @@ -317,13 +317,19 @@ enum { · 316 unmodified lines | |||
| 317 | IORING_REGISTER_IOWQ_AFF = 17, | 317 | IORING_REGISTER_IOWQ_AFF = 17, |
| 318 | IORING_UNREGISTER_IOWQ_AFF = 18, | 318 | IORING_UNREGISTER_IOWQ_AFF = 18, |
| 319 | 319 | ||
| 320 | /* set/get max number of workers */ | 320 | /* set/get max number of io-wq workers */ |
| 321 | IORING_REGISTER_IOWQ_MAX_WORKERS = 19, | 321 | IORING_REGISTER_IOWQ_MAX_WORKERS = 19, |
| 322 | 322 | ||
| 323 | /* this goes last */ | 323 | /* this goes last */ |
| 324 | IORING_REGISTER_LAST | 324 | IORING_REGISTER_LAST |
| 325 | }; | 325 | }; |
| 326 | 326 | ||
| 327 | /* io-wq worker categories */ | ||
| 328 | enum { | ||
| 329 | IO_WQ_BOUND, | ||
| 330 | IO_WQ_UNBOUND, | ||
| 331 | }; | ||
| 332 | |||
| 327 | /* deprecated, see struct io_uring_rsrc_update */ | 333 | /* deprecated, see struct io_uring_rsrc_update */ |
| 328 | struct io_uring_files_update { | 334 | struct io_uring_files_update { |
| 329 | __u32 offset; | 335 | __u32 offset; |
| @@ -1242,7 +1242,7 @@ trace_initcall_start_cb(void *data, initcall_t fn) · 1241 unmodified lines | |||
| 1242 | { | 1242 | { |
| 1243 | ktime_t *calltime = (ktime_t *)data; | 1243 | ktime_t *calltime = (ktime_t *)data; |
| 1244 | 1244 | ||
| 1245 | printk(KERN_DEBUG "calling %pS @ %i irqs_disabled() %d\n", fn, task_pid_nr(current), irqs_disabled()); | 1245 | printk(KERN_DEBUG "calling %pS @ %i\n", fn, task_pid_nr(current)); |
| 1246 | *calltime = ktime_get(); | 1246 | *calltime = ktime_get(); |
| 1247 | } | 1247 | } |
| 1248 | 1248 | ||
| @@ -1256,8 +1256,8 @@ trace_initcall_finish_cb(void *data, initcall_t fn, int ret) · 7 unmodified lines | |||
| 1256 | rettime = ktime_get(); | 1256 | rettime = ktime_get(); |
| 1257 | delta = ktime_sub(rettime, *calltime); | 1257 | delta = ktime_sub(rettime, *calltime); |
| 1258 | duration = (unsigned long long) ktime_to_ns(delta) >> 10; | 1258 | duration = (unsigned long long) ktime_to_ns(delta) >> 10; |
| 1259 | printk(KERN_DEBUG "initcall %pS returned %d after %lld usecs, irqs_disabled() %d\n", | 1259 | printk(KERN_DEBUG "initcall %pS returned %d after %lld usecs\n", |
| 1260 | fn, ret, duration, irqs_disabled()); | 1260 | fn, ret, duration); |
| 1261 | } | 1261 | } |
| 1262 | 1262 | ||
| 1263 | static ktime_t initcall_calltime; | 1263 | static ktime_t initcall_calltime; |
| @@ -567,7 +567,8 @@ static void add_dma_entry(struct dma_debug_entry *entry) · 566 unmodified lines | |||
| 567 | pr_err("cacheline tracking ENOMEM, dma-debug disabled\n"); | 567 | pr_err("cacheline tracking ENOMEM, dma-debug disabled\n"); |
| 568 | global_disable = true; | 568 | global_disable = true; |
| 569 | } else if (rc == -EEXIST) { | 569 | } else if (rc == -EEXIST) { |
| 570 | pr_err("cacheline tracking EEXIST, overlapping mappings aren't supported\n"); | 570 | err_printk(entry->dev, entry, |
| 571 | "cacheline tracking EEXIST, overlapping mappings aren't supported\n"); | ||
| 571 | } | 572 | } |
| 572 | } | 573 | } |
| 573 | 574 | ||
| @@ -206,7 +206,8 @@ static int __dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, · 205 unmodified lines | |||
| 206 | /** | 206 | /** |
| 207 | * dma_map_sg_attrs - Map the given buffer for DMA | 207 | * dma_map_sg_attrs - Map the given buffer for DMA |
| 208 | * @dev: The device for which to perform the DMA operation | 208 | * @dev: The device for which to perform the DMA operation |
| 209 | * @sg: The sg_table object describing the buffer | 209 | * @sg: The sg_table object describing the buffer |
| 210 | * @nents: Number of entries to map | ||
| 210 | * @dir: DMA direction | 211 | * @dir: DMA direction |
| 211 | * @attrs: Optional DMA attributes for the map operation | 212 | * @attrs: Optional DMA attributes for the map operation |
| 212 | * | 213 | * |
| @@ -10193,7 +10193,7 @@ static void perf_event_addr_filters_apply(struct perf_event *event) · 10192 unmodified lines | |||
| 10193 | return; | 10193 | return; |
| 10194 | 10194 | ||
| 10195 | if (ifh->nr_file_filters) { | 10195 | if (ifh->nr_file_filters) { |
| 10196 | mm = get_task_mm(event->ctx->task); | 10196 | mm = get_task_mm(task); |
| 10197 | if (!mm) | 10197 | if (!mm) |
| 10198 | goto restart; | 10198 | goto restart; |
| 10199 | 10199 | ||
| @@ -41,6 +41,12 @@ · 40 unmodified lines | |||
| 41 | * The risk of writer starvation is there, but the pathological use cases | 41 | * The risk of writer starvation is there, but the pathological use cases |
| 42 | * which trigger it are not necessarily the typical RT workloads. | 42 | * which trigger it are not necessarily the typical RT workloads. |
| 43 | * | 43 | * |
| 44 | * Fast-path orderings: | ||
| 45 | * The lock/unlock of readers can run in fast paths: lock and unlock are only | ||
| 46 | * atomic ops, and there is no inner lock to provide ACQUIRE and RELEASE | ||
| 47 | * semantics of rwbase_rt. Atomic ops should thus provide _acquire() | ||
| 48 | * and _release() (or stronger). | ||
| 49 | * | ||
| 44 | * Common code shared between RT rw_semaphore and rwlock | 50 | * Common code shared between RT rw_semaphore and rwlock |
| 45 | */ | 51 | */ |
| 46 | 52 | ||
| @@ -53,6 +59,7 @@ static __always_inline int rwbase_read_trylock(struct rwbase_rt *rwb) · 6 unmodified lines | |||
| 53 | * set. | 59 | * set. |
| 54 | */ | 60 | */ |
| 55 | for (r = atomic_read(&rwb->readers); r < 0;) { | 61 | for (r = atomic_read(&rwb->readers); r < 0;) { |
| 62 | /* Fully-ordered if cmpxchg() succeeds, provides ACQUIRE */ | ||
| 56 | if (likely(atomic_try_cmpxchg(&rwb->readers, &r, r + 1))) | 63 | if (likely(atomic_try_cmpxchg(&rwb->readers, &r, r + 1))) |
| 57 | return 1; | 64 | return 1; |
| 58 | } | 65 | } |
| @@ -162,6 +169,8 @@ static __always_inline void rwbase_read_unlock(struct rwbase_rt *rwb, · 103 unmodified lines | |||
| 162 | /* | 169 | /* |
| 163 | * rwb->readers can only hit 0 when a writer is waiting for the | 170 | * rwb->readers can only hit 0 when a writer is waiting for the |
| 164 | * active readers to leave the critical section. | 171 | * active readers to leave the critical section. |
| 172 | * | ||
| 173 | * dec_and_test() is fully ordered, provides RELEASE. | ||
| 165 | */ | 174 | */ |
| 166 | if (unlikely(atomic_dec_and_test(&rwb->readers))) | 175 | if (unlikely(atomic_dec_and_test(&rwb->readers))) |
| 167 | __rwbase_read_unlock(rwb, state); | 176 | __rwbase_read_unlock(rwb, state); |
| @@ -172,7 +181,11 @@ static inline void __rwbase_write_unlock(struct rwbase_rt *rwb, int bias, · 4 unmodified lines | |||
| 172 | { | 181 | { |
| 173 | struct rt_mutex_base *rtm = &rwb->rtmutex; | 182 | struct rt_mutex_base *rtm = &rwb->rtmutex; |
| 174 | 183 | ||
| 175 | atomic_add(READER_BIAS - bias, &rwb->readers); | 184 | /* |
| 185 | * _release() is needed in case that reader is in fast path, pairing | ||
| 186 | * with atomic_try_cmpxchg() in rwbase_read_trylock(), provides RELEASE | ||
| 187 | */ | ||
| 188 | (void)atomic_add_return_release(READER_BIAS - bias, &rwb->readers); | ||
| 176 | raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); | 189 | raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); |
| 177 | rwbase_rtmutex_unlock(rtm); | 190 | rwbase_rtmutex_unlock(rtm); |
| 178 | } | 191 | } |
| @@ -196,6 +209,23 @@ static inline void rwbase_write_downgrade(struct rwbase_rt *rwb) · 17 unmodified lines | |||
| 196 | __rwbase_write_unlock(rwb, WRITER_BIAS - 1, flags); | 209 | __rwbase_write_unlock(rwb, WRITER_BIAS - 1, flags); |
| 197 | } | 210 | } |
| 198 | 211 | ||
| 212 | static inline bool __rwbase_write_trylock(struct rwbase_rt *rwb) | ||
| 213 | { | ||
| 214 | /* Can do without CAS because we're serialized by wait_lock. */ | ||
| 215 | lockdep_assert_held(&rwb->rtmutex.wait_lock); | ||
| 216 | |||
| 217 | /* | ||
| 218 | * _acquire is needed in case the reader is in the fast path, pairing | ||
| 219 | * with rwbase_read_unlock(), provides ACQUIRE. | ||
| 220 | */ | ||
| 221 | if (!atomic_read_acquire(&rwb->readers)) { | ||
| 222 | atomic_set(&rwb->readers, WRITER_BIAS); | ||
| 223 | return 1; | ||
| 224 | } | ||
| 225 | |||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 199 | static int __sched rwbase_write_lock(struct rwbase_rt *rwb, | 229 | static int __sched rwbase_write_lock(struct rwbase_rt *rwb, |
| 200 | unsigned int state) | 230 | unsigned int state) |
| 201 | { | 231 | { |
| @@ -210,34 +240,30 @@ static int __sched rwbase_write_lock(struct rwbase_rt *rwb, · 8 unmodified lines | |||
| 210 | atomic_sub(READER_BIAS, &rwb->readers); | 240 | atomic_sub(READER_BIAS, &rwb->readers); |
| 211 | 241 | ||
| 212 | raw_spin_lock_irqsave(&rtm->wait_lock, flags); | 242 | raw_spin_lock_irqsave(&rtm->wait_lock, flags); |
| 213 | /* | 243 | if (__rwbase_write_trylock(rwb)) |
| 214 | * set_current_state() for rw_semaphore | 244 | goto out_unlock; |
| 215 | * current_save_and_set_rtlock_wait_state() for rwlock | ||
| 216 | */ | ||
| 217 | rwbase_set_and_save_current_state(state); | ||
| 218 | 245 | ||
| 219 | /* Block until all readers have left the critical section. */ | 246 | rwbase_set_and_save_current_state(state); |
| 220 | for (; atomic_read(&rwb->readers);) { | 247 | for (;;) { |
| 221 | /* Optimized out for rwlocks */ | 248 | /* Optimized out for rwlocks */ |
| 222 | if (rwbase_signal_pending_state(state, current)) { | 249 | if (rwbase_signal_pending_state(state, current)) { |
| 223 | __set_current_state(TASK_RUNNING); | 250 | rwbase_restore_current_state(); |
| 224 | __rwbase_write_unlock(rwb, 0, flags); | 251 | __rwbase_write_unlock(rwb, 0, flags); |
| 225 | return -EINTR; | 252 | return -EINTR; |
| 226 | } | 253 | } |
| 254 | |||
| 255 | if (__rwbase_write_trylock(rwb)) | ||
| 256 | break; | ||
| 257 | |||
| 227 | raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); | 258 | raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); |
| 259 | rwbase_schedule(); | ||
| 260 | raw_spin_lock_irqsave(&rtm->wait_lock, flags); | ||
| 228 | 261 | ||
| 229 | /* | ||
| 230 | * Schedule and wait for the readers to leave the critical | ||
| 231 | * section. The last reader leaving it wakes the waiter. | ||
| 232 | */ | ||
| 233 | if (atomic_read(&rwb->readers) != 0) | ||
| 234 | rwbase_schedule(); | ||
| 235 | set_current_state(state); | 262 | set_current_state(state); |
| 236 | raw_spin_lock_irqsave(&rtm->wait_lock, flags); | ||
| 237 | } | 263 | } |
| 238 | |||
| 239 | atomic_set(&rwb->readers, WRITER_BIAS); | ||
| 240 | rwbase_restore_current_state(); | 264 | rwbase_restore_current_state(); |
| 265 | |||
| 266 | out_unlock: | ||
| 241 | raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); | 267 | raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); |
| 242 | return 0; | 268 | return 0; |
| 243 | } | 269 | } |
| @@ -253,8 +279,7 @@ static inline int rwbase_write_trylock(struct rwbase_rt *rwb) · 9 unmodified lines | |||
| 253 | atomic_sub(READER_BIAS, &rwb->readers); | 279 | atomic_sub(READER_BIAS, &rwb->readers); |
| 254 | 280 | ||
| 255 | raw_spin_lock_irqsave(&rtm->wait_lock, flags); | 281 | raw_spin_lock_irqsave(&rtm->wait_lock, flags); |
| 256 | if (!atomic_read(&rwb->readers)) { | 282 | if (__rwbase_write_trylock(rwb)) { |
| 257 | atomic_set(&rwb->readers, WRITER_BIAS); | ||
| 258 | raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); | 283 | raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); |
| 259 | return 1; | 284 | return 1; |
| 260 | } | 285 | } |
| @@ -1972,3 +1972,39 @@ int import_single_range(int rw, void __user *buf, size_t len, · 1971 unmodified lines | |||
| 1972 | return 0; | 1972 | return 0; |
| 1973 | } | 1973 | } |
| 1974 | EXPORT_SYMBOL(import_single_range); | 1974 | EXPORT_SYMBOL(import_single_range); |
| 1975 | |||
| 1976 | /** | ||
| 1977 | * iov_iter_restore() - Restore a &struct iov_iter to the same state as when | ||
| 1978 | * iov_iter_save_state() was called. | ||
| 1979 | * | ||
| 1980 | * @i: &struct iov_iter to restore | ||
| 1981 | * @state: state to restore from | ||
| 1982 | * | ||
| 1983 | * Used after iov_iter_save_state() to bring restore @i, if operations may | ||
| 1984 | * have advanced it. | ||
| 1985 | * | ||
| 1986 | * Note: only works on ITER_IOVEC, ITER_BVEC, and ITER_KVEC | ||
| 1987 | */ | ||
| 1988 | void iov_iter_restore(struct iov_iter *i, struct iov_iter_state *state) | ||
| 1989 | { | ||
| 1990 | if (WARN_ON_ONCE(!iov_iter_is_bvec(i) && !iter_is_iovec(i)) && | ||
| 1991 | !iov_iter_is_kvec(i)) | ||
| 1992 | return; | ||
| 1993 | i->iov_offset = state->iov_offset; | ||
| 1994 | i->count = state->count; | ||
| 1995 | /* | ||
| 1996 | * For the *vec iters, nr_segs + iov is constant - if we increment | ||
| 1997 | * the vec, then we also decrement the nr_segs count. Hence we don't | ||
| 1998 | * need to track both of these, just one is enough and we can deduct | ||
| 1999 | * the other from that. ITER_KVEC and ITER_IOVEC are the same struct | ||
| 2000 | * size, so we can just increment the iov pointer as they are unionzed. | ||
| 2001 | * ITER_BVEC _may_ be the same size on some archs, but on others it is | ||
| 2002 | * not. Be safe and handle it separately. | ||
| 2003 | */ | ||
| 2004 | BUILD_BUG_ON(sizeof(struct iovec) != sizeof(struct kvec)); | ||
| 2005 | if (iov_iter_is_bvec(i)) | ||
| 2006 | i->bvec -= state->nr_segs - i->nr_segs; | ||
| 2007 | else | ||
| 2008 | i->iov -= state->nr_segs - i->nr_segs; | ||
| 2009 | i->nr_segs = state->nr_segs; | ||
| 2010 | } | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 | 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
| 2 | /* Copyright (c) 2016-2018, NXP Semiconductors | 2 | /* Copyright 2016-2018 NXP |
| 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> | 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 4 | */ | 4 | */ |
| 5 | #include <linux/packing.h> | 5 | #include <linux/packing.h> |
| @@ -134,4 +134,47 @@ void __iomem *pci_iomap_wc(struct pci_dev *dev, int bar, unsigned long maxlen) · 133 unmodified lines | |||
| 134 | return pci_iomap_wc_range(dev, bar, 0, maxlen); | 134 | return pci_iomap_wc_range(dev, bar, 0, maxlen); |
| 135 | } | 135 | } |
| 136 | EXPORT_SYMBOL_GPL(pci_iomap_wc); | 136 | EXPORT_SYMBOL_GPL(pci_iomap_wc); |
| 137 | |||
| 138 | /* | ||
| 139 | * pci_iounmap() somewhat illogically comes from lib/iomap.c for the | ||
| 140 | * CONFIG_GENERIC_IOMAP case, because that's the code that knows about | ||
| 141 | * the different IOMAP ranges. | ||
| 142 | * | ||
| 143 | * But if the architecture does not use the generic iomap code, and if | ||
| 144 | * it has _not_ defined it's own private pci_iounmap function, we define | ||
| 145 | * it here. | ||
| 146 | * | ||
| 147 | * NOTE! This default implementation assumes that if the architecture | ||
| 148 | * support ioport mapping (HAS_IOPORT_MAP), the ioport mapping will | ||
| 149 | * be fixed to the range [ PCI_IOBASE, PCI_IOBASE+IO_SPACE_LIMIT [, | ||
| 150 | * and does not need unmapping with 'ioport_unmap()'. | ||
| 151 | * | ||
| 152 | * If you have different rules for your architecture, you need to | ||
| 153 | * implement your own pci_iounmap() that knows the rules for where | ||
| 154 | * and how IO vs MEM get mapped. | ||
| 155 | * | ||
| 156 | * This code is odd, and the ARCH_HAS/ARCH_WANTS #define logic comes | ||
| 157 | * from legacy <asm-generic/io.h> header file behavior. In particular, | ||
| 158 | * it would seem to make sense to do the iounmap(p) for the non-IO-space | ||
| 159 | * case here regardless, but that's not what the old header file code | ||
| 160 | * did. Probably incorrectly, but this is meant to be bug-for-bug | ||
| 161 | * compatible. | ||
| 162 | */ | ||
| 163 | #if defined(ARCH_WANTS_GENERIC_PCI_IOUNMAP) | ||
| 164 | |||
| 165 | void pci_iounmap(struct pci_dev *dev, void __iomem *p) | ||
| 166 | { | ||
| 167 | #ifdef ARCH_HAS_GENERIC_IOPORT_MAP | ||
| 168 | uintptr_t start = (uintptr_t) PCI_IOBASE; | ||
| 169 | uintptr_t addr = (uintptr_t) p; | ||
| 170 | |||
| 171 | if (addr >= start && addr < start + IO_SPACE_LIMIT) | ||
| 172 | return; | ||
| 173 | iounmap(p); | ||
| 174 | #endif | ||
| 175 | } | ||
| 176 | EXPORT_SYMBOL(pci_iounmap); | ||
| 177 | |||
| 178 | #endif /* ARCH_WANTS_GENERIC_PCI_IOUNMAP */ | ||
| 179 | |||
| 137 | #endif /* CONFIG_PCI */ | 180 | #endif /* CONFIG_PCI */ |
| @@ -106,9 +106,6 @@ static bool do_memsw_account(void) · 105 unmodified lines | |||
| 106 | /* memcg and lruvec stats flushing */ | 106 | /* memcg and lruvec stats flushing */ |
| 107 | static void flush_memcg_stats_dwork(struct work_struct *w); | 107 | static void flush_memcg_stats_dwork(struct work_struct *w); |
| 108 | static DECLARE_DEFERRABLE_WORK(stats_flush_dwork, flush_memcg_stats_dwork); | 108 | static DECLARE_DEFERRABLE_WORK(stats_flush_dwork, flush_memcg_stats_dwork); |
| 109 | static void flush_memcg_stats_work(struct work_struct *w); | ||
| 110 | static DECLARE_WORK(stats_flush_work, flush_memcg_stats_work); | ||
| 111 | static DEFINE_PER_CPU(unsigned int, stats_flush_threshold); | ||
| 112 | static DEFINE_SPINLOCK(stats_flush_lock); | 109 | static DEFINE_SPINLOCK(stats_flush_lock); |
| 113 | 110 | ||
| 114 | #define THRESHOLDS_EVENTS_TARGET 128 | 111 | #define THRESHOLDS_EVENTS_TARGET 128 |
| @@ -682,8 +679,6 @@ void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, · 567 unmodified lines | |||
| 682 | 679 | ||
| 683 | /* Update lruvec */ | 680 | /* Update lruvec */ |
| 684 | __this_cpu_add(pn->lruvec_stats_percpu->state[idx], val); | 681 | __this_cpu_add(pn->lruvec_stats_percpu->state[idx], val); |
| 685 | if (!(__this_cpu_inc_return(stats_flush_threshold) % MEMCG_CHARGE_BATCH)) | ||
| 686 | queue_work(system_unbound_wq, &stats_flush_work); | ||
| 687 | } | 682 | } |
| 688 | 683 | ||
| 689 | /** | 684 | /** |
| @@ -5361,11 +5356,6 @@ static void flush_memcg_stats_dwork(struct work_struct *w) · 4671 unmodified lines | |||
| 5361 | queue_delayed_work(system_unbound_wq, &stats_flush_dwork, 2UL*HZ); | 5356 | queue_delayed_work(system_unbound_wq, &stats_flush_dwork, 2UL*HZ); |
| 5362 | } | 5357 | } |
| 5363 | 5358 | ||
| 5364 | static void flush_memcg_stats_work(struct work_struct *w) | ||
| 5365 | { | ||
| 5366 | mem_cgroup_flush_stats(); | ||
| 5367 | } | ||
| 5368 | |||
| 5369 | static void mem_cgroup_css_rstat_flush(struct cgroup_subsys_state *css, int cpu) | 5359 | static void mem_cgroup_css_rstat_flush(struct cgroup_subsys_state *css, int cpu) |
| 5370 | { | 5360 | { |
| 5371 | struct mem_cgroup *memcg = mem_cgroup_from_css(css); | 5361 | struct mem_cgroup *memcg = mem_cgroup_from_css(css); |
| @@ -3403,6 +3403,7 @@ void unmap_mapping_pages(struct address_space *mapping, pgoff_t start, · 3402 unmodified lines | |||
| 3403 | unmap_mapping_range_tree(&mapping->i_mmap, &details); | 3403 | unmap_mapping_range_tree(&mapping->i_mmap, &details); |
| 3404 | i_mmap_unlock_write(mapping); | 3404 | i_mmap_unlock_write(mapping); |
| 3405 | } | 3405 | } |
| 3406 | EXPORT_SYMBOL_GPL(unmap_mapping_pages); | ||
| 3406 | 3407 | ||
| 3407 | /** | 3408 | /** |
| 3408 | * unmap_mapping_range - unmap the portion of all mmaps in the specified | 3409 | * unmap_mapping_range - unmap the portion of all mmaps in the specified |
| @@ -352,6 +352,7 @@ void workingset_refault(struct page *page, void *shadow) · 351 unmodified lines | |||
| 352 | 352 | ||
| 353 | inc_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + file); | 353 | inc_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + file); |
| 354 | 354 | ||
| 355 | mem_cgroup_flush_stats(); | ||
| 355 | /* | 356 | /* |
| 356 | * Compare the distance to the existing workingset size. We | 357 | * Compare the distance to the existing workingset size. We |
| 357 | * don't activate pages that couldn't stay resident even if | 358 | * don't activate pages that couldn't stay resident even if |
| @@ -6925,12 +6925,16 @@ EXPORT_SYMBOL(napi_disable); · 6924 unmodified lines | |||
| 6925 | */ | 6925 | */ |
| 6926 | void napi_enable(struct napi_struct *n) | 6926 | void napi_enable(struct napi_struct *n) |
| 6927 | { | 6927 | { |
| 6928 | BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); | 6928 | unsigned long val, new; |
| 6929 | smp_mb__before_atomic(); | 6929 | |
| 6930 | clear_bit(NAPI_STATE_SCHED, &n->state); | 6930 | do { |
| 6931 | clear_bit(NAPI_STATE_NPSVC, &n->state); | 6931 | val = READ_ONCE(n->state); |
| 6932 | if (n->dev->threaded && n->thread) | 6932 | BUG_ON(!test_bit(NAPI_STATE_SCHED, &val)); |
| 6933 | set_bit(NAPI_STATE_THREADED, &n->state); | 6933 | |
| 6934 | new = val & ~(NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC); | ||
| 6935 | if (n->dev->threaded && n->thread) | ||
| 6936 | new |= NAPIF_STATE_THREADED; | ||
| 6937 | } while (cmpxchg(&n->state, val, new) != val); | ||
| 6934 | } | 6938 | } |
| 6935 | EXPORT_SYMBOL(napi_enable); | 6939 | EXPORT_SYMBOL(napi_enable); |
| 6936 | 6940 | ||
| @@ -3179,17 +3179,15 @@ EXPORT_SYMBOL(sock_init_data); · 3178 unmodified lines | |||
| 3179 | 3179 | ||
| 3180 | void lock_sock_nested(struct sock *sk, int subclass) | 3180 | void lock_sock_nested(struct sock *sk, int subclass) |
| 3181 | { | 3181 | { |
| 3182 | /* The sk_lock has mutex_lock() semantics here. */ | ||
| 3183 | mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_); | ||
| 3184 | |||
| 3182 | might_sleep(); | 3185 | might_sleep(); |
| 3183 | spin_lock_bh(&sk->sk_lock.slock); | 3186 | spin_lock_bh(&sk->sk_lock.slock); |
| 3184 | if (sk->sk_lock.owned) | 3187 | if (sk->sk_lock.owned) |
| 3185 | __lock_sock(sk); | 3188 | __lock_sock(sk); |
| 3186 | sk->sk_lock.owned = 1; | 3189 | sk->sk_lock.owned = 1; |
| 3187 | spin_unlock(&sk->sk_lock.slock); | 3190 | spin_unlock_bh(&sk->sk_lock.slock); |
| 3188 | /* | ||
| 3189 | * The sk_lock has mutex_lock() semantics here: | ||
| 3190 | */ | ||
| 3191 | mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_); | ||
| 3192 | local_bh_enable(); | ||
| 3193 | } | 3191 | } |
| 3194 | EXPORT_SYMBOL(lock_sock_nested); | 3192 | EXPORT_SYMBOL(lock_sock_nested); |
| 3195 | 3193 | ||
| @@ -3227,24 +3225,35 @@ EXPORT_SYMBOL(release_sock); · 31 unmodified lines | |||
| 3227 | */ | 3225 | */ |
| 3228 | bool lock_sock_fast(struct sock *sk) __acquires(&sk->sk_lock.slock) | 3226 | bool lock_sock_fast(struct sock *sk) __acquires(&sk->sk_lock.slock) |
| 3229 | { | 3227 | { |
| 3228 | /* The sk_lock has mutex_lock() semantics here. */ | ||
| 3229 | mutex_acquire(&sk->sk_lock.dep_map, 0, 0, _RET_IP_); | ||
| 3230 | |||
| 3230 | might_sleep(); | 3231 | might_sleep(); |
| 3231 | spin_lock_bh(&sk->sk_lock.slock); | 3232 | spin_lock_bh(&sk->sk_lock.slock); |
| 3232 | 3233 | ||
| 3233 | if (!sk->sk_lock.owned) | 3234 | if (!sk->sk_lock.owned) { |
| 3234 | /* | 3235 | /* |
| 3235 | * Note : We must disable BH | 3236 | * Fast path return with bottom halves disabled and |
| 3237 | * sock::sk_lock.slock held. | ||
| 3238 | * | ||
| 3239 | * The 'mutex' is not contended and holding | ||
| 3240 | * sock::sk_lock.slock prevents all other lockers to | ||
| 3241 | * proceed so the corresponding unlock_sock_fast() can | ||
| 3242 | * avoid the slow path of release_sock() completely and | ||
| 3243 | * just release slock. | ||
| 3244 | * | ||
| 3245 | * From a semantical POV this is equivalent to 'acquiring' | ||
| 3246 | * the 'mutex', hence the corresponding lockdep | ||
| 3247 | * mutex_release() has to happen in the fast path of | ||
| 3248 | * unlock_sock_fast(). | ||
| 3236 | */ | 3249 | */ |
| 3237 | return false; | 3250 | return false; |
| 3251 | } | ||
| 3238 | 3252 | ||
| 3239 | __lock_sock(sk); | 3253 | __lock_sock(sk); |
| 3240 | sk->sk_lock.owned = 1; | 3254 | sk->sk_lock.owned = 1; |
| 3241 | spin_unlock(&sk->sk_lock.slock); | ||
| 3242 | /* | ||
| 3243 | * The sk_lock has mutex_lock() semantics here: | ||
| 3244 | */ | ||
| 3245 | mutex_acquire(&sk->sk_lock.dep_map, 0, 0, _RET_IP_); | ||
| 3246 | __acquire(&sk->sk_lock.slock); | 3255 | __acquire(&sk->sk_lock.slock); |
| 3247 | local_bh_enable(); | 3256 | spin_unlock_bh(&sk->sk_lock.slock); |
| 3248 | return true; | 3257 | return true; |
| 3249 | } | 3258 | } |
| 3250 | EXPORT_SYMBOL(lock_sock_fast); | 3259 | EXPORT_SYMBOL(lock_sock_fast); |
| @@ -429,6 +429,7 @@ static int dsa_port_setup(struct dsa_port *dp) · 428 unmodified lines | |||
| 429 | { | 429 | { |
| 430 | struct devlink_port *dlp = &dp->devlink_port; | 430 | struct devlink_port *dlp = &dp->devlink_port; |
| 431 | bool dsa_port_link_registered = false; | 431 | bool dsa_port_link_registered = false; |
| 432 | struct dsa_switch *ds = dp->ds; | ||
| 432 | bool dsa_port_enabled = false; | 433 | bool dsa_port_enabled = false; |
| 433 | int err = 0; | 434 | int err = 0; |
| 434 | 435 | ||
| @@ -438,6 +439,12 @@ static int dsa_port_setup(struct dsa_port *dp) · 3 unmodified lines | |||
| 438 | INIT_LIST_HEAD(&dp->fdbs); | 439 | INIT_LIST_HEAD(&dp->fdbs); |
| 439 | INIT_LIST_HEAD(&dp->mdbs); | 440 | INIT_LIST_HEAD(&dp->mdbs); |
| 440 | 441 | ||
| 442 | if (ds->ops->port_setup) { | ||
| 443 | err = ds->ops->port_setup(ds, dp->index); | ||
| 444 | if (err) | ||
| 445 | return err; | ||
| 446 | } | ||
| 447 | |||
| 441 | switch (dp->type) { | 448 | switch (dp->type) { |
| 442 | case DSA_PORT_TYPE_UNUSED: | 449 | case DSA_PORT_TYPE_UNUSED: |
| 443 | dsa_port_disable(dp); | 450 | dsa_port_disable(dp); |
| @@ -480,8 +487,11 @@ static int dsa_port_setup(struct dsa_port *dp) · 36 unmodified lines | |||
| 480 | dsa_port_disable(dp); | 487 | dsa_port_disable(dp); |
| 481 | if (err && dsa_port_link_registered) | 488 | if (err && dsa_port_link_registered) |
| 482 | dsa_port_link_unregister_of(dp); | 489 | dsa_port_link_unregister_of(dp); |
| 483 | if (err) | 490 | if (err) { |
| 491 | if (ds->ops->port_teardown) | ||
| 492 | ds->ops->port_teardown(ds, dp->index); | ||
| 484 | return err; | 493 | return err; |
| 494 | } | ||
| 485 | 495 | ||
| 486 | dp->setup = true; | 496 | dp->setup = true; |
| 487 | 497 | ||
| @@ -533,11 +543,15 @@ static int dsa_port_devlink_setup(struct dsa_port *dp) · 45 unmodified lines | |||
| 533 | static void dsa_port_teardown(struct dsa_port *dp) | 543 | static void dsa_port_teardown(struct dsa_port *dp) |
| 534 | { | 544 | { |
| 535 | struct devlink_port *dlp = &dp->devlink_port; | 545 | struct devlink_port *dlp = &dp->devlink_port; |
| 546 | struct dsa_switch *ds = dp->ds; | ||
| 536 | struct dsa_mac_addr *a, *tmp; | 547 | struct dsa_mac_addr *a, *tmp; |
| 537 | 548 | ||
| 538 | if (!dp->setup) | 549 | if (!dp->setup) |
| 539 | return; | 550 | return; |
| 540 | 551 | ||
| 552 | if (ds->ops->port_teardown) | ||
| 553 | ds->ops->port_teardown(ds, dp->index); | ||
| 554 | |||
| 541 | devlink_port_type_clear(dlp); | 555 | devlink_port_type_clear(dlp); |
| 542 | 556 | ||
| 543 | switch (dp->type) { | 557 | switch (dp->type) { |
| @@ -581,6 +595,36 @@ static void dsa_port_devlink_teardown(struct dsa_port *dp) · 37 unmodified lines | |||
| 581 | dp->devlink_port_setup = false; | 595 | dp->devlink_port_setup = false; |
| 582 | } | 596 | } |
| 583 | 597 | ||
| 598 | /* Destroy the current devlink port, and create a new one which has the UNUSED | ||
| 599 | * flavour. At this point, any call to ds->ops->port_setup has been already | ||
| 600 | * balanced out by a call to ds->ops->port_teardown, so we know that any | ||
| 601 | * devlink port regions the driver had are now unregistered. We then call its | ||
| 602 | * ds->ops->port_setup again, in order for the driver to re-create them on the | ||
| 603 | * new devlink port. | ||
| 604 | */ | ||
| 605 | static int dsa_port_reinit_as_unused(struct dsa_port *dp) | ||
| 606 | { | ||
| 607 | struct dsa_switch *ds = dp->ds; | ||
| 608 | int err; | ||
| 609 | |||
| 610 | dsa_port_devlink_teardown(dp); | ||
| 611 | dp->type = DSA_PORT_TYPE_UNUSED; | ||
| 612 | err = dsa_port_devlink_setup(dp); | ||
| 613 | if (err) | ||
| 614 | return err; | ||
| 615 | |||
| 616 | if (ds->ops->port_setup) { | ||
| 617 | /* On error, leave the devlink port registered, | ||
| 618 | * dsa_switch_teardown will clean it up later. | ||
| 619 | */ | ||
| 620 | err = ds->ops->port_setup(ds, dp->index); | ||
| 621 | if (err) | ||
| 622 | return err; | ||
| 623 | } | ||
| 624 | |||
| 625 | return 0; | ||
| 626 | } | ||
| 627 | |||
| 584 | static int dsa_devlink_info_get(struct devlink *dl, | 628 | static int dsa_devlink_info_get(struct devlink *dl, |
| 585 | struct devlink_info_req *req, | 629 | struct devlink_info_req *req, |
| 586 | struct netlink_ext_ack *extack) | 630 | struct netlink_ext_ack *extack) |
| @@ -833,7 +877,7 @@ static int dsa_switch_setup(struct dsa_switch *ds) · 246 unmodified lines | |||
| 833 | devlink_params_publish(ds->devlink); | 877 | devlink_params_publish(ds->devlink); |
| 834 | 878 | ||
| 835 | if (!ds->slave_mii_bus && ds->ops->phy_read) { | 879 | if (!ds->slave_mii_bus && ds->ops->phy_read) { |
| 836 | ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev); | 880 | ds->slave_mii_bus = mdiobus_alloc(); |
| 837 | if (!ds->slave_mii_bus) { | 881 | if (!ds->slave_mii_bus) { |
| 838 | err = -ENOMEM; | 882 | err = -ENOMEM; |
| 839 | goto teardown; | 883 | goto teardown; |
| @@ -843,13 +887,16 @@ static int dsa_switch_setup(struct dsa_switch *ds) · 3 unmodified lines | |||
| 843 | 887 | ||
| 844 | err = mdiobus_register(ds->slave_mii_bus); | 888 | err = mdiobus_register(ds->slave_mii_bus); |
| 845 | if (err < 0) | 889 | if (err < 0) |
| 846 | goto teardown; | 890 | goto free_slave_mii_bus; |
| 847 | } | 891 | } |
| 848 | 892 | ||
| 849 | ds->setup = true; | 893 | ds->setup = true; |
| 850 | 894 | ||
| 851 | return 0; | 895 | return 0; |
| 852 | 896 | ||
| 897 | free_slave_mii_bus: | ||
| 898 | if (ds->slave_mii_bus && ds->ops->phy_read) | ||
| 899 | mdiobus_free(ds->slave_mii_bus); | ||
| 853 | teardown: | 900 | teardown: |
| 854 | if (ds->ops->teardown) | 901 | if (ds->ops->teardown) |
| 855 | ds->ops->teardown(ds); | 902 | ds->ops->teardown(ds); |
| @@ -872,8 +919,11 @@ static void dsa_switch_teardown(struct dsa_switch *ds) · 16 unmodified lines | |||
| 872 | if (!ds->setup) | 919 | if (!ds->setup) |
| 873 | return; | 920 | return; |
| 874 | 921 | ||
| 875 | if (ds->slave_mii_bus && ds->ops->phy_read) | 922 | if (ds->slave_mii_bus && ds->ops->phy_read) { |
| 876 | mdiobus_unregister(ds->slave_mii_bus); | 923 | mdiobus_unregister(ds->slave_mii_bus); |
| 924 | mdiobus_free(ds->slave_mii_bus); | ||
| 925 | ds->slave_mii_bus = NULL; | ||
| 926 | } | ||
| 877 | 927 | ||
| 878 | dsa_switch_unregister_notifier(ds); | 928 | dsa_switch_unregister_notifier(ds); |
| 879 | 929 | ||
| @@ -933,12 +983,9 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst) · 53 unmodified lines | |||
| 933 | list_for_each_entry(dp, &dst->ports, list) { | 983 | list_for_each_entry(dp, &dst->ports, list) { |
| 934 | err = dsa_port_setup(dp); | 984 | err = dsa_port_setup(dp); |
| 935 | if (err) { | 985 | if (err) { |
| 936 | dsa_port_devlink_teardown(dp); | 986 | err = dsa_port_reinit_as_unused(dp); |
| 937 | dp->type = DSA_PORT_TYPE_UNUSED; | ||
| 938 | err = dsa_port_devlink_setup(dp); | ||
| 939 | if (err) | 987 | if (err) |
| 940 | goto teardown; | 988 | goto teardown; |
| 941 | continue; | ||
| 942 | } | 989 | } |
| 943 | } | 990 | } |
| 944 | 991 | ||
| @@ -1043,6 +1090,7 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) · 98 unmodified lines | |||
| 1043 | teardown_master: | 1090 | teardown_master: |
| 1044 | dsa_tree_teardown_master(dst); | 1091 | dsa_tree_teardown_master(dst); |
| 1045 | teardown_switches: | 1092 | teardown_switches: |
| 1093 | dsa_tree_teardown_ports(dst); | ||
| 1046 | dsa_tree_teardown_switches(dst); | 1094 | dsa_tree_teardown_switches(dst); |
| 1047 | teardown_cpu_ports: | 1095 | teardown_cpu_ports: |
| 1048 | dsa_tree_teardown_cpu_ports(dst); | 1096 | dsa_tree_teardown_cpu_ports(dst); |
| @@ -1557,3 +1605,53 @@ void dsa_unregister_switch(struct dsa_switch *ds) · 508 unmodified lines | |||
| 1557 | mutex_unlock(&dsa2_mutex); | 1605 | mutex_unlock(&dsa2_mutex); |
| 1558 | } | 1606 | } |
| 1559 | EXPORT_SYMBOL_GPL(dsa_unregister_switch); | 1607 | EXPORT_SYMBOL_GPL(dsa_unregister_switch); |
| 1608 | |||
| 1609 | /* If the DSA master chooses to unregister its net_device on .shutdown, DSA is | ||
| 1610 | * blocking that operation from completion, due to the dev_hold taken inside | ||
| 1611 | * netdev_upper_dev_link. Unlink the DSA slave interfaces from being uppers of | ||
| 1612 | * the DSA master, so that the system can reboot successfully. | ||
| 1613 | */ | ||
| 1614 | void dsa_switch_shutdown(struct dsa_switch *ds) | ||
| 1615 | { | ||
| 1616 | struct net_device *master, *slave_dev; | ||
| 1617 | LIST_HEAD(unregister_list); | ||
| 1618 | struct dsa_port *dp; | ||
| 1619 | |||
| 1620 | mutex_lock(&dsa2_mutex); | ||
| 1621 | rtnl_lock(); | ||
| 1622 | |||
| 1623 | list_for_each_entry(dp, &ds->dst->ports, list) { | ||
| 1624 | if (dp->ds != ds) | ||
| 1625 | continue; | ||
| 1626 | |||
| 1627 | if (!dsa_port_is_user(dp)) | ||
| 1628 | continue; | ||
| 1629 | |||
| 1630 | master = dp->cpu_dp->master; | ||
| 1631 | slave_dev = dp->slave; | ||
| 1632 | |||
| 1633 | netdev_upper_dev_unlink(master, slave_dev); | ||
| 1634 | /* Just unlinking ourselves as uppers of the master is not | ||
| 1635 | * sufficient. When the master net device unregisters, that will | ||
| 1636 | * also call dev_close, which we will catch as NETDEV_GOING_DOWN | ||
| 1637 | * and trigger a dev_close on our own devices (dsa_slave_close). | ||
| 1638 | * In turn, that will call dev_mc_unsync on the master's net | ||
| 1639 | * device. If the master is also a DSA switch port, this will | ||
| 1640 | * trigger dsa_slave_set_rx_mode which will call dev_mc_sync on | ||
| 1641 | * its own master. Lockdep will complain about the fact that | ||
| 1642 | * all cascaded masters have the same dsa_master_addr_list_lock_key, | ||
| 1643 | * which it normally would not do if the cascaded masters would | ||
| 1644 | * be in a proper upper/lower relationship, which we've just | ||
| 1645 | * destroyed. | ||
| 1646 | * To suppress the lockdep warnings, let's actually unregister | ||
| 1647 | * the DSA slave interfaces too, to avoid the nonsensical | ||
| 1648 | * multicast address list synchronization on shutdown. | ||
| 1649 | */ | ||
| 1650 | unregister_netdevice_queue(slave_dev, &unregister_list); | ||
| 1651 | } | ||
| 1652 | unregister_netdevice_many(&unregister_list); | ||
| 1653 | |||
| 1654 | rtnl_unlock(); | ||
| 1655 | mutex_unlock(&dsa2_mutex); | ||
| 1656 | } | ||
| 1657 | EXPORT_SYMBOL_GPL(dsa_switch_shutdown); | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* Copyright 2019 NXP Semiconductors | 2 | /* Copyright 2019 NXP |
| 3 | */ | 3 | */ |
| 4 | #include <linux/dsa/ocelot.h> | 4 | #include <linux/dsa/ocelot.h> |
| 5 | #include <soc/mscc/ocelot.h> | 5 | #include <soc/mscc/ocelot.h> |
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* Copyright 2020-2021 NXP Semiconductors | 2 | /* Copyright 2020-2021 NXP |
| 3 | * | 3 | * |
| 4 | * An implementation of the software-defined tag_8021q.c tagger format, which | 4 | * An implementation of the software-defined tag_8021q.c tagger format, which |
| 5 | * also preserves full functionality under a vlan_filtering bridge. It does | 5 | * also preserves full functionality under a vlan_filtering bridge. It does |
| @@ -1982,6 +1982,8 @@ static int replace_nexthop_grp(struct net *net, struct nexthop *old, · 1981 unmodified lines | |||
| 1982 | rcu_assign_pointer(old->nh_grp, newg); | 1982 | rcu_assign_pointer(old->nh_grp, newg); |
| 1983 | 1983 | ||
| 1984 | if (newg->resilient) { | 1984 | if (newg->resilient) { |
| 1985 | /* Make sure concurrent readers are not using 'oldg' anymore. */ | ||
| 1986 | synchronize_net(); | ||
| 1985 | rcu_assign_pointer(oldg->res_table, tmp_table); | 1987 | rcu_assign_pointer(oldg->res_table, tmp_table); |
| 1986 | rcu_assign_pointer(oldg->spare->res_table, tmp_table); | 1988 | rcu_assign_pointer(oldg->spare->res_table, tmp_table); |
| 1987 | } | 1989 | } |
| @@ -3565,6 +3567,7 @@ static struct notifier_block nh_netdev_notifier = { · 1577 unmodified lines | |||
| 3565 | }; | 3567 | }; |
| 3566 | 3568 | ||
| 3567 | static int nexthops_dump(struct net *net, struct notifier_block *nb, | 3569 | static int nexthops_dump(struct net *net, struct notifier_block *nb, |
| 3570 | enum nexthop_event_type event_type, | ||
| 3568 | struct netlink_ext_ack *extack) | 3571 | struct netlink_ext_ack *extack) |
| 3569 | { | 3572 | { |
| 3570 | struct rb_root *root = &net->nexthop.rb_root; | 3573 | struct rb_root *root = &net->nexthop.rb_root; |
| @@ -3575,8 +3578,7 @@ static int nexthops_dump(struct net *net, struct notifier_block *nb, · 4 unmodified lines | |||
| 3575 | struct nexthop *nh; | 3578 | struct nexthop *nh; |
| 3576 | 3579 | ||
| 3577 | nh = rb_entry(node, struct nexthop, rb_node); | 3580 | nh = rb_entry(node, struct nexthop, rb_node); |
| 3578 | err = call_nexthop_notifier(nb, net, NEXTHOP_EVENT_REPLACE, nh, | 3581 | err = call_nexthop_notifier(nb, net, event_type, nh, extack); |
| 3579 | extack); | ||
| 3580 | if (err) | 3582 | if (err) |
| 3581 | break; | 3583 | break; |
| 3582 | } | 3584 | } |
| @@ -3590,7 +3592,7 @@ int register_nexthop_notifier(struct net *net, struct notifier_block *nb, · 7 unmodified lines | |||
| 3590 | int err; | 3592 | int err; |
| 3591 | 3593 | ||
| 3592 | rtnl_lock(); | 3594 | rtnl_lock(); |
| 3593 | err = nexthops_dump(net, nb, extack); | 3595 | err = nexthops_dump(net, nb, NEXTHOP_EVENT_REPLACE, extack); |
| 3594 | if (err) | 3596 | if (err) |
| 3595 | goto unlock; | 3597 | goto unlock; |
| 3596 | err = blocking_notifier_chain_register(&net->nexthop.notifier_chain, | 3598 | err = blocking_notifier_chain_register(&net->nexthop.notifier_chain, |
| @@ -3603,8 +3605,17 @@ EXPORT_SYMBOL(register_nexthop_notifier); · 6 unmodified lines | |||
| 3603 | 3605 | ||
| 3604 | int unregister_nexthop_notifier(struct net *net, struct notifier_block *nb) | 3606 | int unregister_nexthop_notifier(struct net *net, struct notifier_block *nb) |
| 3605 | { | 3607 | { |
| 3606 | return blocking_notifier_chain_unregister(&net->nexthop.notifier_chain, | 3608 | int err; |
| 3607 | nb); | 3609 | |
| 3610 | rtnl_lock(); | ||
| 3611 | err = blocking_notifier_chain_unregister(&net->nexthop.notifier_chain, | ||
| 3612 | nb); | ||
| 3613 | if (err) | ||
| 3614 | goto unlock; | ||
| 3615 | nexthops_dump(net, nb, NEXTHOP_EVENT_DEL, NULL); | ||
| 3616 | unlock: | ||
| 3617 | rtnl_unlock(); | ||
| 3618 | return err; | ||
| 3608 | } | 3619 | } |
| 3609 | EXPORT_SYMBOL(unregister_nexthop_notifier); | 3620 | EXPORT_SYMBOL(unregister_nexthop_notifier); |
| 3610 | 3621 | ||
| @@ -510,7 +510,8 @@ static int smc_clc_prfx_set(struct socket *clcsock, · 509 unmodified lines | |||
| 510 | goto out_rel; | 510 | goto out_rel; |
| 511 | } | 511 | } |
| 512 | /* get address to which the internal TCP socket is bound */ | 512 | /* get address to which the internal TCP socket is bound */ |
| 513 | kernel_getsockname(clcsock, (struct sockaddr *)&addrs); | 513 | if (kernel_getsockname(clcsock, (struct sockaddr *)&addrs) < 0) |
| 514 | goto out_rel; | ||
| 514 | /* analyze IP specific data of net_device belonging to TCP socket */ | 515 | /* analyze IP specific data of net_device belonging to TCP socket */ |
| 515 | addr6 = (struct sockaddr_in6 *)&addrs; | 516 | addr6 = (struct sockaddr_in6 *)&addrs; |
| 516 | rcu_read_lock(); | 517 | rcu_read_lock(); |
| @@ -1468,7 +1468,9 @@ static void smc_conn_abort_work(struct work_struct *work) · 1467 unmodified lines | |||
| 1468 | abort_work); | 1468 | abort_work); |
| 1469 | struct smc_sock *smc = container_of(conn, struct smc_sock, conn); | 1469 | struct smc_sock *smc = container_of(conn, struct smc_sock, conn); |
| 1470 | 1470 | ||
| 1471 | lock_sock(&smc->sk); | ||
| 1471 | smc_conn_kill(conn, true); | 1472 | smc_conn_kill(conn, true); |
| 1473 | release_sock(&smc->sk); | ||
| 1472 | sock_put(&smc->sk); /* sock_hold done by schedulers of abort_work */ | 1474 | sock_put(&smc->sk); /* sock_hold done by schedulers of abort_work */ |
| 1473 | } | 1475 | } |
| 1474 | 1476 | ||
| @@ -29,7 +29,12 @@ CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE)) · 28 unmodified lines | |||
| 29 | else | 29 | else |
| 30 | CLANG_FLAGS += -fintegrated-as | 30 | CLANG_FLAGS += -fintegrated-as |
| 31 | endif | 31 | endif |
| 32 | # By default, clang only warns when it encounters an unknown warning flag or | ||
| 33 | # certain optimization flags it knows it has not implemented. | ||
| 34 | # Make it behave more like gcc by erroring when these flags are encountered | ||
| 35 | # so they can be implemented or wrapped in cc-option. | ||
| 32 | CLANG_FLAGS += -Werror=unknown-warning-option | 36 | CLANG_FLAGS += -Werror=unknown-warning-option |
| 37 | CLANG_FLAGS += -Werror=ignored-optimization-argument | ||
| 33 | KBUILD_CFLAGS += $(CLANG_FLAGS) | 38 | KBUILD_CFLAGS += $(CLANG_FLAGS) |
| 34 | KBUILD_AFLAGS += $(CLANG_FLAGS) | 39 | KBUILD_AFLAGS += $(CLANG_FLAGS) |
| 35 | export CLANG_FLAGS | 40 | export CLANG_FLAGS |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | |||
| 13 | # Stage 2 is handled by this file and does the following | 13 | # Stage 2 is handled by this file and does the following |
| 14 | # 1) Find all modules listed in modules.order | 14 | # 1) Find all modules listed in modules.order |
| 15 | # 2) modpost is then used to | 15 | # 2) modpost is then used to |
| 16 | # 3) create one <module>.mod.c file pr. module | 16 | # 3) create one <module>.mod.c file per module |
| 17 | # 4) create one Module.symvers file with CRC for all exported symbols | 17 | # 4) create one Module.symvers file with CRC for all exported symbols |
| 18 | 18 | ||
| 19 | # Step 3 is used to place certain information in the module's ELF | 19 | # Step 3 is used to place certain information in the module's ELF |
| @@ -34,7 +34,6 @@ REGEX_SOURCE_SYMBOL = re.compile(SOURCE_SYMBOL) · 33 unmodified lines | |||
| 34 | REGEX_KCONFIG_DEF = re.compile(DEF) | 34 | REGEX_KCONFIG_DEF = re.compile(DEF) |
| 35 | REGEX_KCONFIG_EXPR = re.compile(EXPR) | 35 | REGEX_KCONFIG_EXPR = re.compile(EXPR) |
| 36 | REGEX_KCONFIG_STMT = re.compile(STMT) | 36 | REGEX_KCONFIG_STMT = re.compile(STMT) |
| 37 | REGEX_KCONFIG_HELP = re.compile(r"^\s+help\s*$") | ||
| 38 | REGEX_FILTER_SYMBOLS = re.compile(r"[A-Za-z0-9]$") | 37 | REGEX_FILTER_SYMBOLS = re.compile(r"[A-Za-z0-9]$") |
| 39 | REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+") | 38 | REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+") |
| 40 | REGEX_QUOTES = re.compile("(\"(.*?)\")") | 39 | REGEX_QUOTES = re.compile("(\"(.*?)\")") |
| @@ -102,6 +101,9 @@ def parse_options(): · 61 unmodified lines | |||
| 102 | "continue.") | 101 | "continue.") |
| 103 | 102 | ||
| 104 | if args.commit: | 103 | if args.commit: |
| 104 | if args.commit.startswith('HEAD'): | ||
| 105 | sys.exit("The --commit option can't use the HEAD ref") | ||
| 106 | |||
| 105 | args.find = False | 107 | args.find = False |
| 106 | 108 | ||
| 107 | if args.ignore: | 109 | if args.ignore: |
| @@ -432,7 +434,6 @@ def parse_kconfig_file(kfile): · 324 unmodified lines | |||
| 432 | lines = [] | 434 | lines = [] |
| 433 | defined = [] | 435 | defined = [] |
| 434 | references = [] | 436 | references = [] |
| 435 | skip = False | ||
| 436 | 437 | ||
| 437 | if not os.path.exists(kfile): | 438 | if not os.path.exists(kfile): |
| 438 | return defined, references | 439 | return defined, references |
| @@ -448,12 +449,6 @@ def parse_kconfig_file(kfile): · 9 unmodified lines | |||
| 448 | if REGEX_KCONFIG_DEF.match(line): | 449 | if REGEX_KCONFIG_DEF.match(line): |
| 449 | symbol_def = REGEX_KCONFIG_DEF.findall(line) | 450 | symbol_def = REGEX_KCONFIG_DEF.findall(line) |
| 450 | defined.append(symbol_def[0]) | 451 | defined.append(symbol_def[0]) |
| 451 | skip = False | ||
| 452 | elif REGEX_KCONFIG_HELP.match(line): | ||
| 453 | skip = True | ||
| 454 | elif skip: | ||
| 455 | # ignore content of help messages | ||
| 456 | pass | ||
| 457 | elif REGEX_KCONFIG_STMT.match(line): | 452 | elif REGEX_KCONFIG_STMT.match(line): |
| 458 | line = REGEX_QUOTES.sub("", line) | 453 | line = REGEX_QUOTES.sub("", line) |
| 459 | symbols = get_symbols_in_line(line) | 454 | symbols = get_symbols_in_line(line) |
| @@ -13,6 +13,7 @@ import logging · 12 unmodified lines | |||
| 13 | import os | 13 | import os |
| 14 | import re | 14 | import re |
| 15 | import subprocess | 15 | import subprocess |
| 16 | import sys | ||
| 16 | 17 | ||
| 17 | _DEFAULT_OUTPUT = 'compile_commands.json' | 18 | _DEFAULT_OUTPUT = 'compile_commands.json' |
| 18 | _DEFAULT_LOG_LEVEL = 'WARNING' | 19 | _DEFAULT_LOG_LEVEL = 'WARNING' |
| @@ -43,7 +43,7 @@ void perf_evsel__delete(struct perf_evsel *evsel) · 42 unmodified lines | |||
| 43 | free(evsel); | 43 | free(evsel); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | #define FD(e, x, y) (*(int *) xyarray__entry(e->fd, x, y)) | 46 | #define FD(e, x, y) ((int *) xyarray__entry(e->fd, x, y)) |
| 47 | #define MMAP(e, x, y) (e->mmap ? ((struct perf_mmap *) xyarray__entry(e->mmap, x, y)) : NULL) | 47 | #define MMAP(e, x, y) (e->mmap ? ((struct perf_mmap *) xyarray__entry(e->mmap, x, y)) : NULL) |
| 48 | 48 | ||
| 49 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | 49 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) |
| @@ -54,7 +54,10 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) · 4 unmodified lines | |||
| 54 | int cpu, thread; | 54 | int cpu, thread; |
| 55 | for (cpu = 0; cpu < ncpus; cpu++) { | 55 | for (cpu = 0; cpu < ncpus; cpu++) { |
| 56 | for (thread = 0; thread < nthreads; thread++) { | 56 | for (thread = 0; thread < nthreads; thread++) { |
| 57 | FD(evsel, cpu, thread) = -1; | 57 | int *fd = FD(evsel, cpu, thread); |
| 58 | |||
| 59 | if (fd) | ||
| 60 | *fd = -1; | ||
| 58 | } | 61 | } |
| 59 | } | 62 | } |
| 60 | } | 63 | } |
| @@ -80,7 +83,7 @@ sys_perf_event_open(struct perf_event_attr *attr, · 19 unmodified lines | |||
| 80 | static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread, int *group_fd) | 83 | static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread, int *group_fd) |
| 81 | { | 84 | { |
| 82 | struct perf_evsel *leader = evsel->leader; | 85 | struct perf_evsel *leader = evsel->leader; |
| 83 | int fd; | 86 | int *fd; |
| 84 | 87 | ||
| 85 | if (evsel == leader) { | 88 | if (evsel == leader) { |
| 86 | *group_fd = -1; | 89 | *group_fd = -1; |
| @@ -95,10 +98,10 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread, int *grou · 8 unmodified lines | |||
| 95 | return -ENOTCONN; | 98 | return -ENOTCONN; |
| 96 | 99 | ||
| 97 | fd = FD(leader, cpu, thread); | 100 | fd = FD(leader, cpu, thread); |
| 98 | if (fd == -1) | 101 | if (fd == NULL || *fd == -1) |
| 99 | return -EBADF; | 102 | return -EBADF; |
| 100 | 103 | ||
| 101 | *group_fd = fd; | 104 | *group_fd = *fd; |
| 102 | 105 | ||
| 103 | return 0; | 106 | return 0; |
| 104 | } | 107 | } |
| @@ -138,7 +141,11 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, · 33 unmodified lines | |||
| 138 | 141 | ||
| 139 | for (cpu = 0; cpu < cpus->nr; cpu++) { | 142 | for (cpu = 0; cpu < cpus->nr; cpu++) { |
| 140 | for (thread = 0; thread < threads->nr; thread++) { | 143 | for (thread = 0; thread < threads->nr; thread++) { |
| 141 | int fd, group_fd; | 144 | int fd, group_fd, *evsel_fd; |
| 145 | |||
| 146 | evsel_fd = FD(evsel, cpu, thread); | ||
| 147 | if (evsel_fd == NULL) | ||
| 148 | return -EINVAL; | ||
| 142 | 149 | ||
| 143 | err = get_group_fd(evsel, cpu, thread, &group_fd); | 150 | err = get_group_fd(evsel, cpu, thread, &group_fd); |
| 144 | if (err < 0) | 151 | if (err < 0) |
| @@ -151,7 +158,7 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, · 6 unmodified lines | |||
| 151 | if (fd < 0) | 158 | if (fd < 0) |
| 152 | return -errno; | 159 | return -errno; |
| 153 | 160 | ||
| 154 | FD(evsel, cpu, thread) = fd; | 161 | *evsel_fd = fd; |
| 155 | } | 162 | } |
| 156 | } | 163 | } |
| 157 | 164 | ||
| @@ -163,9 +170,12 @@ static void perf_evsel__close_fd_cpu(struct perf_evsel *evsel, int cpu) · 5 unmodified lines | |||
| 163 | int thread; | 170 | int thread; |
| 164 | 171 | ||
| 165 | for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) { | 172 | for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) { |
| 166 | if (FD(evsel, cpu, thread) >= 0) | 173 | int *fd = FD(evsel, cpu, thread); |
| 167 | close(FD(evsel, cpu, thread)); | 174 | |
| 168 | FD(evsel, cpu, thread) = -1; | 175 | if (fd && *fd >= 0) { |
| 176 | close(*fd); | ||
| 177 | *fd = -1; | ||
| 178 | } | ||
| 169 | } | 179 | } |
| 170 | } | 180 | } |
| 171 | 181 | ||
| @@ -209,13 +219,12 @@ void perf_evsel__munmap(struct perf_evsel *evsel) · 37 unmodified lines | |||
| 209 | 219 | ||
| 210 | for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) { | 220 | for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) { |
| 211 | for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { | 221 | for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { |
| 212 | int fd = FD(evsel, cpu, thread); | 222 | int *fd = FD(evsel, cpu, thread); |
| 213 | struct perf_mmap *map = MMAP(evsel, cpu, thread); | ||
| 214 | 223 | ||
| 215 | if (fd < 0) | 224 | if (fd == NULL || *fd < 0) |
| 216 | continue; | 225 | continue; |
| 217 | 226 | ||
| 218 | perf_mmap__munmap(map); | 227 | perf_mmap__munmap(MMAP(evsel, cpu, thread)); |
| 219 | } | 228 | } |
| 220 | } | 229 | } |
| 221 | 230 | ||
| @@ -239,15 +248,16 @@ int perf_evsel__mmap(struct perf_evsel *evsel, int pages) · 17 unmodified lines | |||
| 239 | 248 | ||
| 240 | for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) { | 249 | for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) { |
| 241 | for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { | 250 | for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { |
| 242 | int fd = FD(evsel, cpu, thread); | 251 | int *fd = FD(evsel, cpu, thread); |
| 243 | struct perf_mmap *map = MMAP(evsel, cpu, thread); | 252 | struct perf_mmap *map; |
| 244 | 253 | ||
| 245 | if (fd < 0) | 254 | if (fd == NULL || *fd < 0) |
| 246 | continue; | 255 | continue; |
| 247 | 256 | ||
| 257 | map = MMAP(evsel, cpu, thread); | ||
| 248 | perf_mmap__init(map, NULL, false, NULL); | 258 | perf_mmap__init(map, NULL, false, NULL); |
| 249 | 259 | ||
| 250 | ret = perf_mmap__mmap(map, &mp, fd, cpu); | 260 | ret = perf_mmap__mmap(map, &mp, *fd, cpu); |
| 251 | if (ret) { | 261 | if (ret) { |
| 252 | perf_evsel__munmap(evsel); | 262 | perf_evsel__munmap(evsel); |
| 253 | return ret; | 263 | return ret; |
| @@ -260,7 +270,9 @@ int perf_evsel__mmap(struct perf_evsel *evsel, int pages) · 6 unmodified lines | |||
| 260 | 270 | ||
| 261 | void *perf_evsel__mmap_base(struct perf_evsel *evsel, int cpu, int thread) | 271 | void *perf_evsel__mmap_base(struct perf_evsel *evsel, int cpu, int thread) |
| 262 | { | 272 | { |
| 263 | if (FD(evsel, cpu, thread) < 0 || MMAP(evsel, cpu, thread) == NULL) | 273 | int *fd = FD(evsel, cpu, thread); |
| 274 | |||
| 275 | if (fd == NULL || *fd < 0 || MMAP(evsel, cpu, thread) == NULL) | ||
| 264 | return NULL; | 276 | return NULL; |
| 265 | 277 | ||
| 266 | return MMAP(evsel, cpu, thread)->base; | 278 | return MMAP(evsel, cpu, thread)->base; |
| @@ -295,17 +307,18 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, · 28 unmodified lines | |||
| 295 | struct perf_counts_values *count) | 307 | struct perf_counts_values *count) |
| 296 | { | 308 | { |
| 297 | size_t size = perf_evsel__read_size(evsel); | 309 | size_t size = perf_evsel__read_size(evsel); |
| 310 | int *fd = FD(evsel, cpu, thread); | ||
| 298 | 311 | ||
| 299 | memset(count, 0, sizeof(*count)); | 312 | memset(count, 0, sizeof(*count)); |
| 300 | 313 | ||
| 301 | if (FD(evsel, cpu, thread) < 0) | 314 | if (fd == NULL || *fd < 0) |
| 302 | return -EINVAL; | 315 | return -EINVAL; |
| 303 | 316 | ||
| 304 | if (MMAP(evsel, cpu, thread) && | 317 | if (MMAP(evsel, cpu, thread) && |
| 305 | !perf_mmap__read_self(MMAP(evsel, cpu, thread), count)) | 318 | !perf_mmap__read_self(MMAP(evsel, cpu, thread), count)) |
| 306 | return 0; | 319 | return 0; |
| 307 | 320 | ||
| 308 | if (readn(FD(evsel, cpu, thread), count->values, size) <= 0) | 321 | if (readn(*fd, count->values, size) <= 0) |
| 309 | return -errno; | 322 | return -errno; |
| 310 | 323 | ||
| 311 | return 0; | 324 | return 0; |
| @@ -318,8 +331,13 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, · 6 unmodified lines | |||
| 318 | int thread; | 331 | int thread; |
| 319 | 332 | ||
| 320 | for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { | 333 | for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { |
| 321 | int fd = FD(evsel, cpu, thread), | 334 | int err; |
| 322 | err = ioctl(fd, ioc, arg); | 335 | int *fd = FD(evsel, cpu, thread); |
| 336 | |||
| 337 | if (fd == NULL || *fd < 0) | ||
| 338 | return -1; | ||
| 339 | |||
| 340 | err = ioctl(*fd, ioc, arg); | ||
| 323 | 341 | ||
| 324 | if (err) | 342 | if (err) |
| 325 | return err; | 343 | return err; |
| @@ -368,16 +368,6 @@ static inline int output_type(unsigned int type) · 367 unmodified lines | |||
| 368 | return OUTPUT_TYPE_OTHER; | 368 | return OUTPUT_TYPE_OTHER; |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | static inline unsigned int attr_type(unsigned int type) | ||
| 372 | { | ||
| 373 | switch (type) { | ||
| 374 | case OUTPUT_TYPE_SYNTH: | ||
| 375 | return PERF_TYPE_SYNTH; | ||
| 376 | default: | ||
| 377 | return type; | ||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 381 | static bool output_set_by_user(void) | 371 | static bool output_set_by_user(void) |
| 382 | { | 372 | { |
| 383 | int j; | 373 | int j; |
| @@ -556,6 +546,18 @@ static void set_print_ip_opts(struct perf_event_attr *attr) · 172 unmodified lines | |||
| 556 | output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE; | 546 | output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE; |
| 557 | } | 547 | } |
| 558 | 548 | ||
| 549 | static struct evsel *find_first_output_type(struct evlist *evlist, | ||
| 550 | unsigned int type) | ||
| 551 | { | ||
| 552 | struct evsel *evsel; | ||
| 553 | |||
| 554 | evlist__for_each_entry(evlist, evsel) { | ||
| 555 | if (output_type(evsel->core.attr.type) == (int)type) | ||
| 556 | return evsel; | ||
| 557 | } | ||
| 558 | return NULL; | ||
| 559 | } | ||
| 560 | |||
| 559 | /* | 561 | /* |
| 560 | * verify all user requested events exist and the samples | 562 | * verify all user requested events exist and the samples |
| 561 | * have the expected data | 563 | * have the expected data |
| @@ -567,7 +569,7 @@ static int perf_session__check_output_opt(struct perf_session *session) · 5 unmodified lines | |||
| 567 | struct evsel *evsel; | 569 | struct evsel *evsel; |
| 568 | 570 | ||
| 569 | for (j = 0; j < OUTPUT_TYPE_MAX; ++j) { | 571 | for (j = 0; j < OUTPUT_TYPE_MAX; ++j) { |
| 570 | evsel = perf_session__find_first_evtype(session, attr_type(j)); | 572 | evsel = find_first_output_type(session->evlist, j); |
| 571 | 573 | ||
| 572 | /* | 574 | /* |
| 573 | * even if fields is set to 0 (ie., show nothing) event must | 575 | * even if fields is set to 0 (ie., show nothing) event must |
| @@ -757,25 +757,40 @@ void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, · 756 unmodified lines | |||
| 757 | } | 757 | } |
| 758 | 758 | ||
| 759 | void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column, | 759 | void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column, |
| 760 | unsigned int row, bool arrow_down) | 760 | unsigned int row, int diff, bool arrow_down) |
| 761 | { | 761 | { |
| 762 | unsigned int end_row; | 762 | int end_row; |
| 763 | 763 | ||
| 764 | if (row >= browser->top_idx) | 764 | if (diff <= 0) |
| 765 | end_row = row - browser->top_idx; | ||
| 766 | else | ||
| 767 | return; | 765 | return; |
| 768 | 766 | ||
| 769 | SLsmg_set_char_set(1); | 767 | SLsmg_set_char_set(1); |
| 770 | 768 | ||
| 771 | if (arrow_down) { | 769 | if (arrow_down) { |
| 770 | if (row + diff <= browser->top_idx) | ||
| 771 | return; | ||
| 772 | |||
| 773 | end_row = row + diff - browser->top_idx; | ||
| 772 | ui_browser__gotorc(browser, end_row, column - 1); | 774 | ui_browser__gotorc(browser, end_row, column - 1); |
| 773 | SLsmg_write_char(SLSMG_ULCORN_CHAR); | ||
| 774 | ui_browser__gotorc(browser, end_row, column); | ||
| 775 | SLsmg_draw_hline(2); | ||
| 776 | ui_browser__gotorc(browser, end_row + 1, column - 1); | ||
| 777 | SLsmg_write_char(SLSMG_LTEE_CHAR); | 775 | SLsmg_write_char(SLSMG_LTEE_CHAR); |
| 776 | |||
| 777 | while (--end_row >= 0 && end_row > (int)(row - browser->top_idx)) { | ||
| 778 | ui_browser__gotorc(browser, end_row, column - 1); | ||
| 779 | SLsmg_draw_vline(1); | ||
| 780 | } | ||
| 781 | |||
| 782 | end_row = (int)(row - browser->top_idx); | ||
| 783 | if (end_row >= 0) { | ||
| 784 | ui_browser__gotorc(browser, end_row, column - 1); | ||
| 785 | SLsmg_write_char(SLSMG_ULCORN_CHAR); | ||
| 786 | ui_browser__gotorc(browser, end_row, column); | ||
| 787 | SLsmg_draw_hline(2); | ||
| 788 | } | ||
| 778 | } else { | 789 | } else { |
| 790 | if (row < browser->top_idx) | ||
| 791 | return; | ||
| 792 | |||
| 793 | end_row = row - browser->top_idx; | ||
| 779 | ui_browser__gotorc(browser, end_row, column - 1); | 794 | ui_browser__gotorc(browser, end_row, column - 1); |
| 780 | SLsmg_write_char(SLSMG_LTEE_CHAR); | 795 | SLsmg_write_char(SLSMG_LTEE_CHAR); |
| 781 | ui_browser__gotorc(browser, end_row, column); | 796 | ui_browser__gotorc(browser, end_row, column); |
| @@ -51,7 +51,7 @@ void ui_browser__write_graph(struct ui_browser *browser, int graph); · 50 unmodified lines | |||
| 51 | void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, | 51 | void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, |
| 52 | u64 start, u64 end); | 52 | u64 start, u64 end); |
| 53 | void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column, | 53 | void ui_browser__mark_fused(struct ui_browser *browser, unsigned int column, |
| 54 | unsigned int row, bool arrow_down); | 54 | unsigned int row, int diff, bool arrow_down); |
| 55 | void __ui_browser__show_title(struct ui_browser *browser, const char *title); | 55 | void __ui_browser__show_title(struct ui_browser *browser, const char *title); |
| 56 | void ui_browser__show_title(struct ui_browser *browser, const char *title); | 56 | void ui_browser__show_title(struct ui_browser *browser, const char *title); |
| 57 | int ui_browser__show(struct ui_browser *browser, const char *title, | 57 | int ui_browser__show(struct ui_browser *browser, const char *title, |
| @@ -125,13 +125,20 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int · 124 unmodified lines | |||
| 125 | ab->selection = al; | 125 | ab->selection = al; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) | 128 | static int is_fused(struct annotate_browser *ab, struct disasm_line *cursor) |
| 129 | { | 129 | { |
| 130 | struct disasm_line *pos = list_prev_entry(cursor, al.node); | 130 | struct disasm_line *pos = list_prev_entry(cursor, al.node); |
| 131 | const char *name; | 131 | const char *name; |
| 132 | int diff = 1; | ||
| 133 | |||
| 134 | while (pos && pos->al.offset == -1) { | ||
| 135 | pos = list_prev_entry(pos, al.node); | ||
| 136 | if (!ab->opts->hide_src_code) | ||
| 137 | diff++; | ||
| 138 | } | ||
| 132 | 139 | ||
| 133 | if (!pos) | 140 | if (!pos) |
| 134 | return false; | 141 | return 0; |
| 135 | 142 | ||
| 136 | if (ins__is_lock(&pos->ins)) | 143 | if (ins__is_lock(&pos->ins)) |
| 137 | name = pos->ops.locked.ins.name; | 144 | name = pos->ops.locked.ins.name; |
| @@ -139,9 +146,11 @@ static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) · 1 unmodified line | |||
| 139 | name = pos->ins.name; | 146 | name = pos->ins.name; |
| 140 | 147 | ||
| 141 | if (!name || !cursor->ins.name) | 148 | if (!name || !cursor->ins.name) |
| 142 | return false; | 149 | return 0; |
| 143 | 150 | ||
| 144 | return ins__is_fused(ab->arch, name, cursor->ins.name); | 151 | if (ins__is_fused(ab->arch, name, cursor->ins.name)) |
| 152 | return diff; | ||
| 153 | return 0; | ||
| 145 | } | 154 | } |
| 146 | 155 | ||
| 147 | static void annotate_browser__draw_current_jump(struct ui_browser *browser) | 156 | static void annotate_browser__draw_current_jump(struct ui_browser *browser) |
| @@ -155,6 +164,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) · 7 unmodified lines | |||
| 155 | struct annotation *notes = symbol__annotation(sym); | 164 | struct annotation *notes = symbol__annotation(sym); |
| 156 | u8 pcnt_width = annotation__pcnt_width(notes); | 165 | u8 pcnt_width = annotation__pcnt_width(notes); |
| 157 | int width; | 166 | int width; |
| 167 | int diff = 0; | ||
| 158 | 168 | ||
| 159 | /* PLT symbols contain external offsets */ | 169 | /* PLT symbols contain external offsets */ |
| 160 | if (strstr(sym->name, "@plt")) | 170 | if (strstr(sym->name, "@plt")) |
| @@ -205,11 +215,11 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) · 44 unmodified lines | |||
| 205 | pcnt_width + 2 + notes->widths.addr + width, | 215 | pcnt_width + 2 + notes->widths.addr + width, |
| 206 | from, to); | 216 | from, to); |
| 207 | 217 | ||
| 208 | if (is_fused(ab, cursor)) { | 218 | diff = is_fused(ab, cursor); |
| 219 | if (diff > 0) { | ||
| 209 | ui_browser__mark_fused(browser, | 220 | ui_browser__mark_fused(browser, |
| 210 | pcnt_width + 3 + notes->widths.addr + width, | 221 | pcnt_width + 3 + notes->widths.addr + width, |
| 211 | from - 1, | 222 | from - diff, diff, to > from); |
| 212 | to > from); | ||
| 213 | } | 223 | } |
| 214 | } | 224 | } |
| 215 | 225 | ||
| @@ -24,7 +24,10 @@ · 23 unmodified lines | |||
| 24 | struct btf * __weak btf__load_from_kernel_by_id(__u32 id) | 24 | struct btf * __weak btf__load_from_kernel_by_id(__u32 id) |
| 25 | { | 25 | { |
| 26 | struct btf *btf; | 26 | struct btf *btf; |
| 27 | #pragma GCC diagnostic push | ||
| 28 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | ||
| 27 | int err = btf__get_from_id(id, &btf); | 29 | int err = btf__get_from_id(id, &btf); |
| 30 | #pragma GCC diagnostic pop | ||
| 28 | 31 | ||
| 29 | return err ? ERR_PTR(err) : btf; | 32 | return err ? ERR_PTR(err) : btf; |
| 30 | } | 33 | } |
| @@ -2149,6 +2149,7 @@ static int add_callchain_ip(struct thread *thread, · 2148 unmodified lines | |||
| 2149 | 2149 | ||
| 2150 | al.filtered = 0; | 2150 | al.filtered = 0; |
| 2151 | al.sym = NULL; | 2151 | al.sym = NULL; |
| 2152 | al.srcline = NULL; | ||
| 2152 | if (!cpumode) { | 2153 | if (!cpumode) { |
| 2153 | thread__find_cpumode_addr_location(thread, ip, &al); | 2154 | thread__find_cpumode_addr_location(thread, ip, &al); |
| 2154 | } else { | 2155 | } else { |
| @@ -1,6 +1,6 @@ | |||
| 1 | #!/bin/bash | 1 | #!/bin/bash |
| 2 | # SPDX-License-Identifier: GPL-2.0 | 2 | # SPDX-License-Identifier: GPL-2.0 |
| 3 | # Copyright 2020 NXP Semiconductors | 3 | # Copyright 2020 NXP |
| 4 | 4 | ||
| 5 | WAIT_TIME=1 | 5 | WAIT_TIME=1 |
| 6 | NUM_NETIFS=4 | 6 | NUM_NETIFS=4 |
| @@ -1,5 +1,2 @@ | |||
| 1 | ##TEST_GEN_FILES := test_unix_oob | 1 | TEST_GEN_PROGS := test_unix_oob |
| 2 | TEST_PROGS := test_unix_oob | ||
| 3 | include ../../lib.mk | 2 | include ../../lib.mk |
| 4 | |||
| 5 | all: $(TEST_PROGS) | ||
| @@ -271,8 +271,9 @@ main(int argc, char **argv) · 270 unmodified lines | |||
| 271 | read_oob(pfd, &oob); | 271 | read_oob(pfd, &oob); |
| 272 | 272 | ||
| 273 | if (!signal_recvd || len != 127 || oob != '%' || atmark != 1) { | 273 | if (!signal_recvd || len != 127 || oob != '%' || atmark != 1) { |
| 274 | fprintf(stderr, "Test 3 failed, sigurg %d len %d OOB %c ", | 274 | fprintf(stderr, |
| 275 | "atmark %d\n", signal_recvd, len, oob, atmark); | 275 | "Test 3 failed, sigurg %d len %d OOB %c atmark %d\n", |
| 276 | signal_recvd, len, oob, atmark); | ||
| 276 | die(1); | 277 | die(1); |
| 277 | } | 278 | } |
| 278 | 279 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | #include <ppc-asm.h> | 2 | #include <basic_asm.h> |
| 3 | #include <asm/unistd.h> | 3 | #include <asm/unistd.h> |
| 4 | 4 | ||
| 5 | .text | 5 | .text |
| @@ -26,3 +26,38 @@ FUNC_START(getppid_tm_suspended) · 20 unmodified lines | |||
| 26 | 1: | 26 | 1: |
| 27 | li r3, -1 | 27 | li r3, -1 |
| 28 | blr | 28 | blr |
| 29 | |||
| 30 | |||
| 31 | .macro scv level | ||
| 32 | .long (0x44000001 | (\level) << 5) | ||
| 33 | .endm | ||
| 34 | |||
| 35 | FUNC_START(getppid_scv_tm_active) | ||
| 36 | PUSH_BASIC_STACK(0) | ||
| 37 | tbegin. | ||
| 38 | beq 1f | ||
| 39 | li r0, __NR_getppid | ||
| 40 | scv 0 | ||
| 41 | tend. | ||
| 42 | POP_BASIC_STACK(0) | ||
| 43 | blr | ||
| 44 | 1: | ||
| 45 | li r3, -1 | ||
| 46 | POP_BASIC_STACK(0) | ||
| 47 | blr | ||
| 48 | |||
| 49 | FUNC_START(getppid_scv_tm_suspended) | ||
| 50 | PUSH_BASIC_STACK(0) | ||
| 51 | tbegin. | ||
| 52 | beq 1f | ||
| 53 | li r0, __NR_getppid | ||
| 54 | tsuspend. | ||
| 55 | scv 0 | ||
| 56 | tresume. | ||
| 57 | tend. | ||
| 58 | POP_BASIC_STACK(0) | ||
| 59 | blr | ||
| 60 | 1: | ||
| 61 | li r3, -1 | ||
| 62 | POP_BASIC_STACK(0) | ||
| 63 | blr | ||
| @@ -19,23 +19,36 @@ · 18 unmodified lines | |||
| 19 | #include "utils.h" | 19 | #include "utils.h" |
| 20 | #include "tm.h" | 20 | #include "tm.h" |
| 21 | 21 | ||
| 22 | #ifndef PPC_FEATURE2_SCV | ||
| 23 | #define PPC_FEATURE2_SCV 0x00100000 /* scv syscall */ | ||
| 24 | #endif | ||
| 25 | |||
| 22 | extern int getppid_tm_active(void); | 26 | extern int getppid_tm_active(void); |
| 23 | extern int getppid_tm_suspended(void); | 27 | extern int getppid_tm_suspended(void); |
| 28 | extern int getppid_scv_tm_active(void); | ||
| 29 | extern int getppid_scv_tm_suspended(void); | ||
| 24 | 30 | ||
| 25 | unsigned retries = 0; | 31 | unsigned retries = 0; |
| 26 | 32 | ||
| 27 | #define TEST_DURATION 10 /* seconds */ | 33 | #define TEST_DURATION 10 /* seconds */ |
| 28 | 34 | ||
| 29 | pid_t getppid_tm(bool suspend) | 35 | pid_t getppid_tm(bool scv, bool suspend) |
| 30 | { | 36 | { |
| 31 | int i; | 37 | int i; |
| 32 | pid_t pid; | 38 | pid_t pid; |
| 33 | 39 | ||
| 34 | for (i = 0; i < TM_RETRIES; i++) { | 40 | for (i = 0; i < TM_RETRIES; i++) { |
| 35 | if (suspend) | 41 | if (suspend) { |
| 36 | pid = getppid_tm_suspended(); | 42 | if (scv) |
| 37 | else | 43 | pid = getppid_scv_tm_suspended(); |
| 38 | pid = getppid_tm_active(); | 44 | else |
| 45 | pid = getppid_tm_suspended(); | ||
| 46 | } else { | ||
| 47 | if (scv) | ||
| 48 | pid = getppid_scv_tm_active(); | ||
| 49 | else | ||
| 50 | pid = getppid_tm_active(); | ||
| 51 | } | ||
| 39 | 52 | ||
| 40 | if (pid >= 0) | 53 | if (pid >= 0) |
| 41 | return pid; | 54 | return pid; |
| @@ -82,15 +95,24 @@ int tm_syscall(void) · 40 unmodified lines | |||
| 82 | * Test a syscall within a suspended transaction and verify | 95 | * Test a syscall within a suspended transaction and verify |
| 83 | * that it succeeds. | 96 | * that it succeeds. |
| 84 | */ | 97 | */ |
| 85 | FAIL_IF(getppid_tm(true) == -1); /* Should succeed. */ | 98 | FAIL_IF(getppid_tm(false, true) == -1); /* Should succeed. */ |
| 86 | 99 | ||
| 87 | /* | 100 | /* |
| 88 | * Test a syscall within an active transaction and verify that | 101 | * Test a syscall within an active transaction and verify that |
| 89 | * it fails with the correct failure code. | 102 | * it fails with the correct failure code. |
| 90 | */ | 103 | */ |
| 91 | FAIL_IF(getppid_tm(false) != -1); /* Should fail... */ | 104 | FAIL_IF(getppid_tm(false, false) != -1); /* Should fail... */ |
| 92 | FAIL_IF(!failure_is_persistent()); /* ...persistently... */ | 105 | FAIL_IF(!failure_is_persistent()); /* ...persistently... */ |
| 93 | FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */ | 106 | FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */ |
| 107 | |||
| 108 | /* Now do it all again with scv if it is available. */ | ||
| 109 | if (have_hwcap2(PPC_FEATURE2_SCV)) { | ||
| 110 | FAIL_IF(getppid_tm(true, true) == -1); /* Should succeed. */ | ||
| 111 | FAIL_IF(getppid_tm(true, false) != -1); /* Should fail... */ | ||
| 112 | FAIL_IF(!failure_is_persistent()); /* ...persistently... */ | ||
| 113 | FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */ | ||
| 114 | } | ||
| 115 | |||
| 94 | gettimeofday(&now, 0); | 116 | gettimeofday(&now, 0); |
| 95 | } | 117 | } |
| 96 | 118 | ||