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 | 54 | - const: toradex,apalis_t30 |
| 55 | 55 | - const: nvidia,tegra30 |
| 56 | 56 | - items: |
| 57 | − - const: toradex,apalis_t30-eval-v1.1 | |
| 57 | + - const: toradex,apalis_t30-v1.1-eval | |
| 58 | 58 | - const: toradex,apalis_t30-eval |
| 59 | 59 | - const: toradex,apalis_t30-v1.1 |
| 60 | 60 | - const: toradex,apalis_t30 |
| @@ -9,7 +9,7 @@ function block. · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | All DISP device tree nodes must be siblings to the central MMSYS_CONFIG node. |
| 11 | 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 | 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 | 851 | - 0x88A8 traffic will not be received unless VLAN stripping is disabled with |
| 852 | 852 | the following command:: |
| 853 | 853 | |
| 854 | − # ethool -K <ethX> rxvlan off | |
| 854 | + # ethtool -K <ethX> rxvlan off | |
| 855 | 855 | |
| 856 | 856 | - 0x88A8/0x8100 double VLANs cannot be used with 0x8100 or 0x8100/0x8100 VLANS |
| 857 | 857 | configured on the same port. 0x88a8/0x8100 traffic will not be received if |
| @@ -296,7 +296,7 @@ not available. · 295 unmodified lines | ||
| 296 | 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 | 300 | and aims to showcase some potential switch caveats. |
| 301 | 301 | |
| 302 | 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 | 2804 | F: arch/arm/mach-pxa/vpac270.c |
| 2805 | 2805 | |
| 2806 | 2806 | ARM/VT8500 ARM ARCHITECTURE |
| 2807 | −M: Tony Prisk <linux@prisktech.co.nz> | |
| 2808 | 2807 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2809 | −S: Maintained | |
| 2808 | +S: Orphan | |
| 2810 | 2809 | F: Documentation/devicetree/bindings/i2c/i2c-wmt.txt |
| 2811 | 2810 | F: arch/arm/mach-vt8500/ |
| 2812 | 2811 | F: drivers/clocksource/timer-vt8500.c |
| @@ -13255,9 +13254,9 @@ F: Documentation/scsi/NinjaSCSI.rst · 10442 unmodified lines | ||
| 13255 | 13254 | F: drivers/scsi/nsp32* |
| 13256 | 13255 | |
| 13257 | 13256 | NIOS2 ARCHITECTURE |
| 13258 | −M: Ley Foon Tan <ley.foon.tan@intel.com> | |
| 13257 | +M: Dinh Nguyen <dinguyen@kernel.org> | |
| 13259 | 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 | 13260 | F: arch/nios2/ |
| 13262 | 13261 | |
| 13263 | 13262 | NITRO ENCLAVES (NE) |
| @@ -14342,7 +14341,8 @@ F: Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml · 1078 unmodified lines | ||
| 14342 | 14341 | F: drivers/pci/controller/pci-ixp4xx.c |
| 14343 | 14342 | |
| 14344 | 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 | 14346 | L: linux-pci@vger.kernel.org |
| 14347 | 14347 | S: Supported |
| 14348 | 14348 | F: drivers/pci/controller/vmd.c |
| @@ -16955,7 +16955,6 @@ F: drivers/misc/sgi-xp/ · 2606 unmodified lines | ||
| 16955 | 16955 | |
| 16956 | 16956 | SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS |
| 16957 | 16957 | M: Karsten Graul <kgraul@linux.ibm.com> |
| 16958 | −M: Guvenc Gulce <guvenc@linux.ibm.com> | |
| 16959 | 16958 | L: linux-s390@vger.kernel.org |
| 16960 | 16959 | S: Supported |
| 16961 | 16960 | W: http://www.ibm.com/developerworks/linux/linux390/ |
| @@ -17968,10 +17967,11 @@ F: Documentation/admin-guide/svga.rst · 1006 unmodified lines | ||
| 17968 | 17967 | F: arch/x86/boot/video* |
| 17969 | 17968 | |
| 17970 | 17969 | SWIOTLB SUBSYSTEM |
| 17971 | −M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | |
| 17970 | +M: Christoph Hellwig <hch@infradead.org> | |
| 17972 | 17971 | L: iommu@lists.linux-foundation.org |
| 17973 | 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 | 17975 | F: arch/*/kernel/pci-swiotlb.c |
| 17976 | 17976 | F: include/linux/swiotlb.h |
| 17977 | 17977 | F: kernel/dma/swiotlb.c |
| @@ -20474,7 +20474,6 @@ F: samples/bpf/xdpsock* · 2496 unmodified lines | ||
| 20474 | 20474 | F: tools/lib/bpf/xsk* |
| 20475 | 20475 | |
| 20476 | 20476 | XEN BLOCK SUBSYSTEM |
| 20477 | −M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | |
| 20478 | 20477 | M: Roger Pau Monné <roger.pau@citrix.com> |
| 20479 | 20478 | L: xen-devel@lists.xenproject.org (moderated for non-subscribers) |
| 20480 | 20479 | S: Supported |
| @@ -20522,7 +20521,7 @@ S: Supported · 41 unmodified lines | ||
| 20522 | 20521 | F: drivers/net/xen-netback/* |
| 20523 | 20522 | |
| 20524 | 20523 | XEN PCI SUBSYSTEM |
| 20525 | −M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | |
| 20524 | +M: Juergen Gross <jgross@suse.com> | |
| 20526 | 20525 | L: xen-devel@lists.xenproject.org (moderated for non-subscribers) |
| 20527 | 20526 | S: Supported |
| 20528 | 20527 | F: arch/x86/pci/*xen* |
| @@ -20545,7 +20544,8 @@ S: Supported · 16 unmodified lines | ||
| 20545 | 20544 | F: sound/xen/* |
| 20546 | 20545 | |
| 20547 | 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 | 20549 | L: xen-devel@lists.xenproject.org (moderated for non-subscribers) |
| 20550 | 20550 | L: iommu@lists.linux-foundation.org |
| 20551 | 20551 | S: Supported |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 5 |
| 3 | 3 | PATCHLEVEL = 15 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc1 | |
| 5 | +EXTRAVERSION = -rc2 | |
| 6 | 6 | NAME = Opossums on Parade |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -20,7 +20,7 @@ config ALPHA · 19 unmodified lines | ||
| 20 | 20 | select NEED_SG_DMA_LENGTH |
| 21 | 21 | select VIRT_TO_BUS |
| 22 | 22 | select GENERIC_IRQ_PROBE |
| 23 | − select GENERIC_PCI_IOMAP if PCI | |
| 23 | + select GENERIC_PCI_IOMAP | |
| 24 | 24 | select AUTO_IRQ_AFFINITY if SMP |
| 25 | 25 | select GENERIC_IRQ_SHOW |
| 26 | 26 | select ARCH_WANT_IPC_PARSE_VERSION |
| @@ -199,7 +199,6 @@ config ALPHA_EIGER · 172 unmodified lines | ||
| 199 | 199 | |
| 200 | 200 | config ALPHA_JENSEN |
| 201 | 201 | bool "Jensen" |
| 202 | − depends on BROKEN | |
| 203 | 202 | select HAVE_EISA |
| 204 | 203 | help |
| 205 | 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 | 16 | extern void __remlu(void); |
| 17 | 17 | extern void __divqu(void); |
| 18 | 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 | 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 | 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 | 121 | *(vuip)((addr << 9) + EISA_VL82C106) = b; |
| 122 | 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 | 127 | long result; |
| 128 | 128 | |
| @@ -131,7 +131,7 @@ static inline unsigned int jensen_bus_inb(unsigned long addr) · 2 unmodified lines | ||
| 131 | 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 | 136 | jensen_set_hae(0); |
| 137 | 137 | *(vuip)((addr << 7) + EISA_IO + 0x00) = b * 0x01010101; |
| @@ -7,6 +7,11 @@ · 6 unmodified lines | ||
| 7 | 7 | * |
| 8 | 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 | 15 | #include <linux/interrupt.h> |
| 11 | 16 | #include <linux/kernel.h> |
| 12 | 17 | #include <linux/types.h> |
| @@ -17,11 +22,6 @@ · 4 unmodified lines | ||
| 17 | 22 | |
| 18 | 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 | 25 | #include <asm/dma.h> |
| 26 | 26 | #include <asm/irq.h> |
| 27 | 27 | #include <asm/mmu_context.h> |
| @@ -14,6 +14,7 @@ ev6-$(CONFIG_ALPHA_EV6) := ev6- · 13 unmodified lines | ||
| 14 | 14 | ev67-$(CONFIG_ALPHA_EV67) := ev67- |
| 15 | 15 | |
| 16 | 16 | lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \ |
| 17 | + udiv-qrnnd.o \ | |
| 17 | 18 | udelay.o \ |
| 18 | 19 | $(ev6-y)memset.o \ |
| 19 | 20 | $(ev6-y)memcpy.o \ |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | # along with GCC; see the file COPYING. If not, write to the |
| 26 | 26 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
| 27 | 27 | # MA 02111-1307, USA. |
| 28 | +#include <asm/export.h> | |
| 28 | 29 | |
| 29 | 30 | .set noreorder |
| 30 | 31 | .set noat |
| @@ -161,3 +162,4 @@ $Odd: · 130 unmodified lines | ||
| 161 | 162 | ret $31,($26),1 |
| 162 | 163 | |
| 163 | 164 | .end __udiv_qrnnd |
| 165 | +EXPORT_SYMBOL(__udiv_qrnnd) | |
| @@ -7,4 +7,4 @@ ccflags-y := -w · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 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 | 403 | egress: |
| 404 | 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 | 513 | void sve_alloc(struct task_struct *task) |
| 514 | 514 | { |
| 515 | 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 | 517 | return; |
| 518 | 518 | } |
| 519 | 519 | |
| @@ -18,7 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/mman.h> |
| 19 | 19 | #include <linux/mm.h> |
| 20 | 20 | #include <linux/nospec.h> |
| 21 | −#include <linux/sched.h> | |
| 22 | 21 | #include <linux/stddef.h> |
| 23 | 22 | #include <linux/sysctl.h> |
| 24 | 23 | #include <linux/unistd.h> |
| @@ -58,7 +57,7 @@ · 33 unmodified lines | ||
| 58 | 57 | |
| 59 | 58 | #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK) |
| 60 | 59 | #include <linux/stackprotector.h> |
| 61 | −unsigned long __stack_chk_guard __read_mostly; | |
| 60 | +unsigned long __stack_chk_guard __ro_after_init; | |
| 62 | 61 | EXPORT_SYMBOL(__stack_chk_guard); |
| 63 | 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 | 517 | void pci_iounmap(struct pci_dev *dev, void __iomem * addr) |
| 517 | 518 | { |
| 518 | 519 | if (!INDIRECT_ADDR(addr)) { |
| 519 | 520 | iounmap(addr); |
| 520 | 521 | } |
| 521 | 522 | } |
| 523 | +EXPORT_SYMBOL(pci_iounmap); | |
| 524 | +#endif | |
| 522 | 525 | |
| 523 | 526 | EXPORT_SYMBOL(ioread8); |
| 524 | 527 | EXPORT_SYMBOL(ioread16); |
| @@ -544,4 +547,3 @@ EXPORT_SYMBOL(iowrite16_rep); · 19 unmodified lines | ||
| 544 | 547 | EXPORT_SYMBOL(iowrite32_rep); |
| 545 | 548 | EXPORT_SYMBOL(ioport_map); |
| 546 | 549 | EXPORT_SYMBOL(ioport_unmap); |
| 547 | −EXPORT_SYMBOL(pci_iounmap); | |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <asm/switch_to.h> |
| 19 | 19 | #include <asm/syscall.h> |
| 20 | 20 | #include <asm/time.h> |
| 21 | +#include <asm/tm.h> | |
| 21 | 22 | #include <asm/unistd.h> |
| 22 | 23 | |
| 23 | 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 | 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 | 182 | local_irq_enable(); |
| 140 | 183 | |
| 141 | 184 | if (unlikely(current_thread_info()->flags & _TIF_SYSCALL_DOTRACE)) { |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <asm/mmu.h> |
| 13 | 13 | #include <asm/ppc_asm.h> |
| 14 | 14 | #include <asm/ptrace.h> |
| 15 | −#include <asm/tm.h> | |
| 16 | 15 | |
| 17 | 16 | .section ".toc","aw" |
| 18 | 17 | SYS_CALL_TABLE: |
| @@ -55,12 +54,6 @@ COMPAT_SYS_CALL_TABLE: · 36 unmodified lines | ||
| 55 | 54 | .globl system_call_vectored_\name |
| 56 | 55 | system_call_vectored_\name: |
| 57 | 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 | 57 | SCV_INTERRUPT_TO_KERNEL |
| 65 | 58 | mr r10,r1 |
| 66 | 59 | ld r1,PACAKSAVE(r13) |
| @@ -247,12 +240,6 @@ _ASM_NOKPROBE_SYMBOL(system_call_common_real) · 180 unmodified lines | ||
| 247 | 240 | .globl system_call_common |
| 248 | 241 | system_call_common: |
| 249 | 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 | 243 | mr r10,r1 |
| 257 | 244 | ld r1,PACAKSAVE(r13) |
| 258 | 245 | std r10,0(r1) |
| @@ -425,34 +412,6 @@ SOFT_MASK_TABLE(.Lsyscall_rst_start, 1b) · 166 unmodified lines | ||
| 425 | 412 | RESTART_TABLE(.Lsyscall_rst_start, .Lsyscall_rst_end, syscall_restart) |
| 426 | 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 | 416 | * If MSR EE/RI was never enabled, IRQs not reconciled, NVGPRs not |
| 458 | 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 | 250 | int index; |
| 251 | 251 | struct machine_check_event evt; |
| 252 | + unsigned long msr; | |
| 252 | 253 | |
| 253 | 254 | if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) |
| 254 | 255 | return; |
| @@ -262,8 +263,20 @@ void machine_check_queue_event(void) · 7 unmodified lines | ||
| 262 | 263 | memcpy(&local_paca->mce_info->mce_event_queue[index], |
| 263 | 264 | &evt, sizeof(evt)); |
| 264 | 265 | |
| 265 | − /* Queue irq work to process this event later. */ | |
| 266 | − irq_work_queue(&mce_event_process_work); | |
| 266 | + /* | |
| 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 | 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 | 2536 | /* The following code handles the fake_suspend = 1 case */ |
| 2537 | 2537 | mflr r0 |
| 2538 | 2538 | std r0, PPC_LR_STKOFF(r1) |
| 2539 | − stdu r1, -PPC_MIN_STKFRM(r1) | |
| 2539 | + stdu r1, -TM_FRAME_SIZE(r1) | |
| 2540 | 2540 | |
| 2541 | 2541 | /* Turn on TM. */ |
| 2542 | 2542 | mfmsr r8 |
| @@ -2551,10 +2551,42 @@ BEGIN_FTR_SECTION · 8 unmodified lines | ||
| 2551 | 2551 | END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG) |
| 2552 | 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 | 2572 | /* We have to treclaim here because that's the only way to do S->N */ |
| 2555 | 2573 | li r3, TM_CAUSE_KVM_RESCHED |
| 2556 | 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 | 2591 | * We were in fake suspend, so we are not going to save the |
| 2560 | 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 | 2614 | std r5, VCPU_TFHAR(r9) |
| 2583 | 2615 | std r6, VCPU_TFIAR(r9) |
| 2584 | 2616 | |
| 2585 | − addi r1, r1, PPC_MIN_STKFRM | |
| 2617 | + addi r1, r1, TM_FRAME_SIZE | |
| 2586 | 2618 | ld r0, PPC_LR_STKOFF(r1) |
| 2587 | 2619 | mtlr r0 |
| 2588 | 2620 | blr |
| @@ -348,9 +348,9 @@ static int xics_host_map(struct irq_domain *domain, unsigned int virq, · 347 unmodified lines | ||
| 348 | 348 | if (xics_ics->check(xics_ics, hwirq)) |
| 349 | 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 | 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 | 355 | return 0; |
| 356 | 356 | } |
| @@ -685,16 +685,6 @@ config STACK_GUARD · 684 unmodified lines | ||
| 685 | 685 | The minimum size for the stack guard should be 256 for 31 bit and |
| 686 | 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 | 688 | endmenu |
| 699 | 689 | |
| 700 | 690 | menu "I/O subsystem" |
| @@ -85,13 +85,6 @@ cflags-$(CONFIG_CHECK_STACK) += -mstack-guard=$(CONFIG_STACK_GUARD) · 84 unmodified lines | ||
| 85 | 85 | endif |
| 86 | 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 | 88 | ifdef CONFIG_EXPOLINE |
| 96 | 89 | ifneq ($(call cc-option,$(CC_FLAGS_MARCH) -mindirect-branch=thunk),) |
| 97 | 90 | CC_FLAGS_EXPOLINE := -mindirect-branch=thunk |
| @@ -10,6 +10,7 @@ CONFIG_BPF_JIT=y · 9 unmodified lines | ||
| 10 | 10 | CONFIG_BPF_JIT_ALWAYS_ON=y |
| 11 | 11 | CONFIG_BPF_LSM=y |
| 12 | 12 | CONFIG_PREEMPT=y |
| 13 | +CONFIG_SCHED_CORE=y | |
| 13 | 14 | CONFIG_BSD_PROCESS_ACCT=y |
| 14 | 15 | CONFIG_BSD_PROCESS_ACCT_V3=y |
| 15 | 16 | CONFIG_TASKSTATS=y |
| @@ -503,6 +504,7 @@ CONFIG_NLMON=m · 487 unmodified lines | ||
| 503 | 504 | # CONFIG_NET_VENDOR_HUAWEI is not set |
| 504 | 505 | # CONFIG_NET_VENDOR_INTEL is not set |
| 505 | 506 | # CONFIG_NET_VENDOR_MICROSOFT is not set |
| 507 | +# CONFIG_NET_VENDOR_LITEX is not set | |
| 506 | 508 | # CONFIG_NET_VENDOR_MARVELL is not set |
| 507 | 509 | CONFIG_MLX4_EN=m |
| 508 | 510 | CONFIG_MLX5_CORE=m |
| @@ -661,7 +663,6 @@ CONFIG_NFSD_V3_ACL=y · 152 unmodified lines | ||
| 661 | 663 | CONFIG_NFSD_V4=y |
| 662 | 664 | CONFIG_NFSD_V4_SECURITY_LABEL=y |
| 663 | 665 | CONFIG_CIFS=m |
| 664 | −CONFIG_CIFS_WEAK_PW_HASH=y | |
| 665 | 666 | CONFIG_CIFS_UPCALL=y |
| 666 | 667 | CONFIG_CIFS_XATTR=y |
| 667 | 668 | CONFIG_CIFS_POSIX=y |
| @@ -720,6 +721,8 @@ CONFIG_CRYPTO_XCBC=m · 52 unmodified lines | ||
| 720 | 721 | CONFIG_CRYPTO_VMAC=m |
| 721 | 722 | CONFIG_CRYPTO_CRC32=m |
| 722 | 723 | CONFIG_CRYPTO_BLAKE2S=m |
| 724 | +CONFIG_CRYPTO_MD4=m | |
| 725 | +CONFIG_CRYPTO_MD5=y | |
| 723 | 726 | CONFIG_CRYPTO_MICHAEL_MIC=m |
| 724 | 727 | CONFIG_CRYPTO_RMD160=m |
| 725 | 728 | CONFIG_CRYPTO_SHA3=m |
| @@ -774,7 +777,6 @@ CONFIG_RANDOM32_SELFTEST=y · 48 unmodified lines | ||
| 774 | 777 | CONFIG_DMA_CMA=y |
| 775 | 778 | CONFIG_CMA_SIZE_MBYTES=0 |
| 776 | 779 | CONFIG_DMA_API_DEBUG=y |
| 777 | −CONFIG_STRING_SELFTEST=y | |
| 778 | 780 | CONFIG_PRINTK_TIME=y |
| 779 | 781 | CONFIG_DYNAMIC_DEBUG=y |
| 780 | 782 | CONFIG_DEBUG_INFO=y |
| @@ -853,12 +855,12 @@ CONFIG_FAIL_FUNCTION=y · 72 unmodified lines | ||
| 853 | 855 | CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y |
| 854 | 856 | CONFIG_LKDTM=m |
| 855 | 857 | CONFIG_TEST_MIN_HEAP=y |
| 856 | −CONFIG_TEST_SORT=y | |
| 857 | 858 | CONFIG_KPROBES_SANITY_TEST=y |
| 858 | 859 | CONFIG_RBTREE_TEST=y |
| 859 | 860 | CONFIG_INTERVAL_TREE_TEST=m |
| 860 | 861 | CONFIG_PERCPU_TEST=m |
| 861 | 862 | CONFIG_ATOMIC64_SELFTEST=y |
| 863 | +CONFIG_STRING_SELFTEST=y | |
| 862 | 864 | CONFIG_TEST_BITOPS=m |
| 863 | 865 | CONFIG_TEST_BPF=m |
| 864 | 866 | CONFIG_TEST_LIVEPATCH=m |
| @@ -8,6 +8,7 @@ CONFIG_BPF_SYSCALL=y · 7 unmodified lines | ||
| 8 | 8 | CONFIG_BPF_JIT=y |
| 9 | 9 | CONFIG_BPF_JIT_ALWAYS_ON=y |
| 10 | 10 | CONFIG_BPF_LSM=y |
| 11 | +CONFIG_SCHED_CORE=y | |
| 11 | 12 | CONFIG_BSD_PROCESS_ACCT=y |
| 12 | 13 | CONFIG_BSD_PROCESS_ACCT_V3=y |
| 13 | 14 | CONFIG_TASKSTATS=y |
| @@ -494,6 +495,7 @@ CONFIG_NLMON=m · 480 unmodified lines | ||
| 494 | 495 | # CONFIG_NET_VENDOR_HUAWEI is not set |
| 495 | 496 | # CONFIG_NET_VENDOR_INTEL is not set |
| 496 | 497 | # CONFIG_NET_VENDOR_MICROSOFT is not set |
| 498 | +# CONFIG_NET_VENDOR_LITEX is not set | |
| 497 | 499 | # CONFIG_NET_VENDOR_MARVELL is not set |
| 498 | 500 | CONFIG_MLX4_EN=m |
| 499 | 501 | CONFIG_MLX5_CORE=m |
| @@ -648,7 +650,6 @@ CONFIG_NFSD_V3_ACL=y · 148 unmodified lines | ||
| 648 | 650 | CONFIG_NFSD_V4=y |
| 649 | 651 | CONFIG_NFSD_V4_SECURITY_LABEL=y |
| 650 | 652 | CONFIG_CIFS=m |
| 651 | −CONFIG_CIFS_WEAK_PW_HASH=y | |
| 652 | 653 | CONFIG_CIFS_UPCALL=y |
| 653 | 654 | CONFIG_CIFS_XATTR=y |
| 654 | 655 | CONFIG_CIFS_POSIX=y |
| @@ -708,6 +709,8 @@ CONFIG_CRYPTO_XCBC=m · 53 unmodified lines | ||
| 708 | 709 | CONFIG_CRYPTO_VMAC=m |
| 709 | 710 | CONFIG_CRYPTO_CRC32=m |
| 710 | 711 | CONFIG_CRYPTO_BLAKE2S=m |
| 712 | +CONFIG_CRYPTO_MD4=m | |
| 713 | +CONFIG_CRYPTO_MD5=y | |
| 711 | 714 | CONFIG_CRYPTO_MICHAEL_MIC=m |
| 712 | 715 | CONFIG_CRYPTO_RMD160=m |
| 713 | 716 | CONFIG_CRYPTO_SHA3=m |
| @@ -55,7 +55,7 @@ int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv, · 54 unmodified lines | ||
| 55 | 55 | int num_devices, const char *buf); |
| 56 | 56 | |
| 57 | 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 | 60 | extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev); |
| 61 | 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 | 249 | #define EMIT6_PCREL(op1, op2, b1, b2, i, off, mask) \ |
| 250 | 250 | ({ \ |
| 251 | − /* Branch instruction needs 6 bytes */ \ | |
| 252 | − int rel = (addrs[(i) + (off) + 1] - (addrs[(i) + 1] - 6)) / 2;\ | |
| 251 | + int rel = (addrs[(i) + (off) + 1] - jit->prg) / 2; \ | |
| 253 | 252 | _EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), (op2) | (mask));\ |
| 254 | 253 | REG_SET_SEEN(b1); \ |
| 255 | 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 | 760 | EMIT4(0xb9080000, dst_reg, src_reg); |
| 762 | 761 | break; |
| 763 | 762 | case BPF_ALU | BPF_ADD | BPF_K: /* dst = (u32) dst + (u32) imm */ |
| 764 | − if (!imm) | |
| 765 | − break; | |
| 766 | − /* alfi %dst,imm */ | |
| 767 | − EMIT6_IMM(0xc20b0000, dst_reg, imm); | |
| 763 | + if (imm != 0) { | |
| 764 | + /* alfi %dst,imm */ | |
| 765 | + EMIT6_IMM(0xc20b0000, dst_reg, imm); | |
| 766 | + } | |
| 768 | 767 | EMIT_ZERO(dst_reg); |
| 769 | 768 | break; |
| 770 | 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 | 785 | EMIT4(0xb9090000, dst_reg, src_reg); |
| 787 | 786 | break; |
| 788 | 787 | case BPF_ALU | BPF_SUB | BPF_K: /* dst = (u32) dst - (u32) imm */ |
| 789 | − if (!imm) | |
| 790 | − break; | |
| 791 | − /* alfi %dst,-imm */ | |
| 792 | − EMIT6_IMM(0xc20b0000, dst_reg, -imm); | |
| 788 | + if (imm != 0) { | |
| 789 | + /* alfi %dst,-imm */ | |
| 790 | + EMIT6_IMM(0xc20b0000, dst_reg, -imm); | |
| 791 | + } | |
| 793 | 792 | EMIT_ZERO(dst_reg); |
| 794 | 793 | break; |
| 795 | 794 | case BPF_ALU64 | BPF_SUB | BPF_K: /* dst = dst - imm */ |
| 796 | 795 | if (!imm) |
| 797 | 796 | break; |
| 798 | − /* agfi %dst,-imm */ | |
| 799 | − EMIT6_IMM(0xc2080000, dst_reg, -imm); | |
| 797 | + if (imm == -0x80000000) { | |
| 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 | 804 | break; |
| 801 | 805 | /* |
| 802 | 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 | 815 | EMIT4(0xb90c0000, dst_reg, src_reg); |
| 812 | 816 | break; |
| 813 | 817 | case BPF_ALU | BPF_MUL | BPF_K: /* dst = (u32) dst * (u32) imm */ |
| 814 | − if (imm == 1) | |
| 815 | − break; | |
| 816 | − /* msfi %r5,imm */ | |
| 817 | − EMIT6_IMM(0xc2010000, dst_reg, imm); | |
| 818 | + if (imm != 1) { | |
| 819 | + /* msfi %r5,imm */ | |
| 820 | + EMIT6_IMM(0xc2010000, dst_reg, imm); | |
| 821 | + } | |
| 818 | 822 | EMIT_ZERO(dst_reg); |
| 819 | 823 | break; |
| 820 | 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 | 871 | if (BPF_OP(insn->code) == BPF_MOD) |
| 868 | 872 | /* lhgi %dst,0 */ |
| 869 | 873 | EMIT4_IMM(0xa7090000, dst_reg, 0); |
| 874 | + else | |
| 875 | + EMIT_ZERO(dst_reg); | |
| 870 | 876 | break; |
| 871 | 877 | } |
| 872 | 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 | 1005 | EMIT4(0xb9820000, dst_reg, src_reg); |
| 1000 | 1006 | break; |
| 1001 | 1007 | case BPF_ALU | BPF_XOR | BPF_K: /* dst = (u32) dst ^ (u32) imm */ |
| 1002 | − if (!imm) | |
| 1003 | − break; | |
| 1004 | − /* xilf %dst,imm */ | |
| 1005 | − EMIT6_IMM(0xc0070000, dst_reg, imm); | |
| 1008 | + if (imm != 0) { | |
| 1009 | + /* xilf %dst,imm */ | |
| 1010 | + EMIT6_IMM(0xc0070000, dst_reg, imm); | |
| 1011 | + } | |
| 1006 | 1012 | EMIT_ZERO(dst_reg); |
| 1007 | 1013 | break; |
| 1008 | 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 | 1039 | EMIT6_DISP_LH(0xeb000000, 0x000d, dst_reg, dst_reg, src_reg, 0); |
| 1034 | 1040 | break; |
| 1035 | 1041 | case BPF_ALU | BPF_LSH | BPF_K: /* dst = (u32) dst << (u32) imm */ |
| 1036 | − if (imm == 0) | |
| 1037 | − break; | |
| 1038 | − /* sll %dst,imm(%r0) */ | |
| 1039 | − EMIT4_DISP(0x89000000, dst_reg, REG_0, imm); | |
| 1042 | + if (imm != 0) { | |
| 1043 | + /* sll %dst,imm(%r0) */ | |
| 1044 | + EMIT4_DISP(0x89000000, dst_reg, REG_0, imm); | |
| 1045 | + } | |
| 1040 | 1046 | EMIT_ZERO(dst_reg); |
| 1041 | 1047 | break; |
| 1042 | 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 | 1064 | EMIT6_DISP_LH(0xeb000000, 0x000c, dst_reg, dst_reg, src_reg, 0); |
| 1059 | 1065 | break; |
| 1060 | 1066 | case BPF_ALU | BPF_RSH | BPF_K: /* dst = (u32) dst >> (u32) imm */ |
| 1061 | − if (imm == 0) | |
| 1062 | − break; | |
| 1063 | − /* srl %dst,imm(%r0) */ | |
| 1064 | − EMIT4_DISP(0x88000000, dst_reg, REG_0, imm); | |
| 1067 | + if (imm != 0) { | |
| 1068 | + /* srl %dst,imm(%r0) */ | |
| 1069 | + EMIT4_DISP(0x88000000, dst_reg, REG_0, imm); | |
| 1070 | + } | |
| 1065 | 1071 | EMIT_ZERO(dst_reg); |
| 1066 | 1072 | break; |
| 1067 | 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 | 1089 | EMIT6_DISP_LH(0xeb000000, 0x000a, dst_reg, dst_reg, src_reg, 0); |
| 1084 | 1090 | break; |
| 1085 | 1091 | case BPF_ALU | BPF_ARSH | BPF_K: /* ((s32) dst >> imm */ |
| 1086 | − if (imm == 0) | |
| 1087 | − break; | |
| 1088 | − /* sra %dst,imm(%r0) */ | |
| 1089 | − EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm); | |
| 1092 | + if (imm != 0) { | |
| 1093 | + /* sra %dst,imm(%r0) */ | |
| 1094 | + EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm); | |
| 1095 | + } | |
| 1090 | 1096 | EMIT_ZERO(dst_reg); |
| 1091 | 1097 | break; |
| 1092 | 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 | 160 | mmap_read_lock(current->mm); |
| 161 | 161 | ret = -EINVAL; |
| 162 | − vma = find_vma(current->mm, mmio_addr); | |
| 162 | + vma = vma_lookup(current->mm, mmio_addr); | |
| 163 | 163 | if (!vma) |
| 164 | 164 | goto out_unlock_mmap; |
| 165 | 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 | 299 | mmap_read_lock(current->mm); |
| 300 | 300 | ret = -EINVAL; |
| 301 | − vma = find_vma(current->mm, mmio_addr); | |
| 301 | + vma = vma_lookup(current->mm, mmio_addr); | |
| 302 | 302 | if (!vma) |
| 303 | 303 | goto out_unlock_mmap; |
| 304 | 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 | 80 | $(obj)/vmlinux.bin.lzo: $(obj)/vmlinux.bin FORCE |
| 81 | 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 | 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 | 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 | 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 | 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 | 96 | $(call if_changed,uimage,lzo) |
| 97 | 97 | |
| 98 | −$(obj)/uImage.bin: $(obj)/vmlinux.bin | |
| 98 | +$(obj)/uImage.bin: $(obj)/vmlinux.bin FORCE | |
| 99 | 99 | $(call if_changed,uimage,none) |
| 100 | 100 | |
| 101 | 101 | OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec |
| 102 | −$(obj)/vmlinux.srec: $(obj)/compressed/vmlinux | |
| 102 | +$(obj)/vmlinux.srec: $(obj)/compressed/vmlinux FORCE | |
| 103 | 103 | $(call if_changed,objcopy) |
| 104 | 104 | |
| 105 | 105 | OBJCOPYFLAGS_uImage.srec := -I binary -O srec |
| 106 | −$(obj)/uImage.srec: $(obj)/uImage | |
| 106 | +$(obj)/uImage.srec: $(obj)/uImage FORCE | |
| 107 | 107 | $(call if_changed,objcopy) |
| 108 | 108 | |
| 109 | 109 | $(obj)/uImage: $(obj)/uImage.$(suffix-y) |
| @@ -356,7 +356,9 @@ err_nomem: · 355 unmodified lines | ||
| 356 | 356 | void arch_dma_free(struct device *dev, size_t size, void *cpu_addr, |
| 357 | 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 | 362 | return; |
| 361 | 363 | |
| 362 | 364 | dma_make_coherent(dma_addr, size); |
| @@ -19,8 +19,10 @@ void ioport_unmap(void __iomem *addr) · 18 unmodified lines | ||
| 19 | 19 | EXPORT_SYMBOL(ioport_map); |
| 20 | 20 | EXPORT_SYMBOL(ioport_unmap); |
| 21 | 21 | |
| 22 | +#ifdef CONFIG_PCI | |
| 22 | 23 | void pci_iounmap(struct pci_dev *dev, void __iomem * addr) |
| 23 | 24 | { |
| 24 | 25 | /* nothing to do */ |
| 25 | 26 | } |
| 26 | 27 | EXPORT_SYMBOL(pci_iounmap); |
| 28 | +#endif | |
| @@ -339,6 +339,11 @@ config NEED_PER_CPU_PAGE_FIRST_CHUNK · 338 unmodified lines | ||
| 339 | 339 | config ARCH_HIBERNATION_POSSIBLE |
| 340 | 340 | def_bool y |
| 341 | 341 | |
| 342 | +config ARCH_NR_GPIO | |
| 343 | + int | |
| 344 | + default 1024 if X86_64 | |
| 345 | + default 512 | |
| 346 | + | |
| 342 | 347 | config ARCH_SUSPEND_POSSIBLE |
| 343 | 348 | def_bool y |
| 344 | 349 | |
| @@ -4,6 +4,12 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 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 | 13 | cflags-$(CONFIG_M486SX) += -march=i486 |
| 8 | 14 | cflags-$(CONFIG_M486) += -march=i486 |
| 9 | 15 | cflags-$(CONFIG_M586) += -march=i586 |
| @@ -19,11 +25,11 @@ cflags-$(CONFIG_MK6) += -march=k6 · 9 unmodified lines | ||
| 19 | 25 | # They make zero difference whatsosever to performance at this time. |
| 20 | 26 | cflags-$(CONFIG_MK7) += -march=athlon |
| 21 | 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 | |
| 23 | −cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) -falign-functions=0 -falign-jumps=0 -falign-loops=0 | |
| 28 | +cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align) | |
| 29 | +cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) $(align) | |
| 24 | 30 | cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586) |
| 25 | 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 | 33 | cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) |
| 28 | 34 | cflags-$(CONFIG_MVIAC7) += -march=i686 |
| 29 | 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 | 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 | 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 | 1265 | int flags = MF_ACTION_REQUIRED; |
| 1263 | 1266 | int ret; |
| 1264 | 1267 | |
| 1268 | + p->mce_count = 0; | |
| 1265 | 1269 | pr_err("Uncorrected hardware memory error in user-access at %llx", p->mce_addr); |
| 1266 | 1270 | |
| 1267 | 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; | |
| 1296 | − current->mce_kflags = m->kflags; | |
| 1297 | − current->mce_ripv = !!(m->mcgstatus & MCG_STATUS_RIPV); | |
| 1298 | − current->mce_whole_page = whole_page(m); | |
| 1299 | + int count = ++current->mce_count; | |
| 1299 | 1300 | |
| 1300 | − if (kill_current_task) | |
| 1301 | − current->mce_kill_me.func = kill_me_now; | |
| 1302 | − else | |
| 1303 | − current->mce_kill_me.func = kill_me_maybe; | |
| 1301 | + /* First call, save all the details */ | |
| 1302 | + if (count == 1) { | |
| 1303 | + current->mce_addr = m->addr; | |
| 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 | 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 | 1459 | /* If this triggers there is no way to recover. Die hard. */ |
| 1439 | 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 | 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 | 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 | 1482 | out: |
| 1462 | 1483 | mce_wrmsrl(MSR_IA32_MCG_STATUS, 0); |
| @@ -1432,18 +1432,18 @@ int kern_addr_valid(unsigned long addr) · 1431 unmodified lines | ||
| 1432 | 1432 | return 0; |
| 1433 | 1433 | |
| 1434 | 1434 | p4d = p4d_offset(pgd, addr); |
| 1435 | − if (p4d_none(*p4d)) | |
| 1435 | + if (!p4d_present(*p4d)) | |
| 1436 | 1436 | return 0; |
| 1437 | 1437 | |
| 1438 | 1438 | pud = pud_offset(p4d, addr); |
| 1439 | − if (pud_none(*pud)) | |
| 1439 | + if (!pud_present(*pud)) | |
| 1440 | 1440 | return 0; |
| 1441 | 1441 | |
| 1442 | 1442 | if (pud_large(*pud)) |
| 1443 | 1443 | return pfn_valid(pud_pfn(*pud)); |
| 1444 | 1444 | |
| 1445 | 1445 | pmd = pmd_offset(pud, addr); |
| 1446 | − if (pmd_none(*pmd)) | |
| 1446 | + if (!pmd_present(*pmd)) | |
| 1447 | 1447 | return 0; |
| 1448 | 1448 | |
| 1449 | 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 | 583 | int err = 0; |
| 584 | 584 | |
| 585 | 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 | 592 | if (start >= end) { |
| 588 | 593 | WARN(1, "%s failed: [mem %#010Lx-%#010Lx], req %s\n", __func__, |
| 589 | 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 | 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 | 1222 | /* First C function to be called on Xen boot */ |
| 1218 | 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 | 1364 | add_preferred_console("xenboot", 0, NULL); |
| 1360 | 1365 | if (pci_xen) |
| 1361 | 1366 | x86_init.pci.arch_init = pci_xen_init; |
| 1367 | + x86_platform.set_legacy_features = | |
| 1368 | + xen_domu_set_legacy_features; | |
| 1362 | 1369 | } else { |
| 1363 | 1370 | const struct dom0_vga_console_info *info = |
| 1364 | 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 | 1518 | if (pinned) { |
| 1519 | 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 | 1524 | SetPagePinned(page); |
| 1525 | + } | |
| 1523 | 1526 | |
| 1524 | 1527 | xen_mc_batch(); |
| 1525 | 1528 | |
| 1526 | 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 | 1532 | __pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); |
| 1530 | 1533 | |
| 1531 | 1534 | xen_mc_issue(PARAVIRT_LAZY_MMU); |
| @@ -1182,10 +1182,6 @@ int blkcg_init_queue(struct request_queue *q) · 1181 unmodified lines | ||
| 1182 | 1182 | if (preloaded) |
| 1183 | 1183 | radix_tree_preload_end(); |
| 1184 | 1184 | |
| 1185 | − ret = blk_iolatency_init(q); | |
| 1186 | − if (ret) | |
| 1187 | − goto err_destroy_all; | |
| 1188 | − | |
| 1189 | 1185 | ret = blk_ioprio_init(q); |
| 1190 | 1186 | if (ret) |
| 1191 | 1187 | goto err_destroy_all; |
| @@ -1194,6 +1190,12 @@ int blkcg_init_queue(struct request_queue *q) · 2 unmodified lines | ||
| 1194 | 1190 | if (ret) |
| 1195 | 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 | 1199 | return 0; |
| 1198 | 1200 | |
| 1199 | 1201 | err_destroy_all: |
| @@ -1364,10 +1366,14 @@ enomem: · 164 unmodified lines | ||
| 1364 | 1366 | /* alloc failed, nothing's initialized yet, free everything */ |
| 1365 | 1367 | spin_lock_irq(&q->queue_lock); |
| 1366 | 1368 | list_for_each_entry(blkg, &q->blkg_list, q_node) { |
| 1369 | + struct blkcg *blkcg = blkg->blkcg; | |
| 1370 | + | |
| 1371 | + spin_lock(&blkcg->lock); | |
| 1367 | 1372 | if (blkg->pd[pol->plid]) { |
| 1368 | 1373 | pol->pd_free_fn(blkg->pd[pol->plid]); |
| 1369 | 1374 | blkg->pd[pol->plid] = NULL; |
| 1370 | 1375 | } |
| 1376 | + spin_unlock(&blkcg->lock); | |
| 1371 | 1377 | } |
| 1372 | 1378 | spin_unlock_irq(&q->queue_lock); |
| 1373 | 1379 | ret = -ENOMEM; |
| @@ -1399,12 +1405,16 @@ void blkcg_deactivate_policy(struct request_queue *q, · 25 unmodified lines | ||
| 1399 | 1405 | __clear_bit(pol->plid, q->blkcg_pols); |
| 1400 | 1406 | |
| 1401 | 1407 | list_for_each_entry(blkg, &q->blkg_list, q_node) { |
| 1408 | + struct blkcg *blkcg = blkg->blkcg; | |
| 1409 | + | |
| 1410 | + spin_lock(&blkcg->lock); | |
| 1402 | 1411 | if (blkg->pd[pol->plid]) { |
| 1403 | 1412 | if (pol->pd_offline_fn) |
| 1404 | 1413 | pol->pd_offline_fn(blkg->pd[pol->plid]); |
| 1405 | 1414 | pol->pd_free_fn(blkg->pd[pol->plid]); |
| 1406 | 1415 | blkg->pd[pol->plid] = NULL; |
| 1407 | 1416 | } |
| 1417 | + spin_unlock(&blkcg->lock); | |
| 1408 | 1418 | } |
| 1409 | 1419 | |
| 1410 | 1420 | spin_unlock_irq(&q->queue_lock); |
| @@ -426,8 +426,15 @@ EXPORT_SYMBOL(blk_integrity_register); · 425 unmodified lines | ||
| 426 | 426 | */ |
| 427 | 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 | 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 | 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 | 209 | spin_lock_irqsave(&tags->lock, flags); |
| 210 | 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 | 212 | rq = NULL; |
| 213 | 213 | spin_unlock_irqrestore(&tags->lock, flags); |
| 214 | 214 | return rq; |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/export.h> |
| 14 | 14 | #include <linux/rtc.h> |
| 15 | 15 | #include <linux/suspend.h> |
| 16 | +#include <linux/init.h> | |
| 16 | 17 | |
| 17 | 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 | 166 | const char *file = *(const char **)(tracedata + 2); |
| 166 | 167 | unsigned int user_hash_value, file_hash_value; |
| 167 | 168 | |
| 169 | + if (!x86_platform.legacy.rtc) | |
| 170 | + return; | |
| 171 | + | |
| 168 | 172 | user_hash_value = user % USERHASH; |
| 169 | 173 | file_hash_value = hash_string(lineno, file, FILEHASH); |
| 170 | 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 | 272 | static int __init early_resume_init(void) |
| 269 | 273 | { |
| 274 | + if (!x86_platform.legacy.rtc) | |
| 275 | + return 0; | |
| 276 | + | |
| 270 | 277 | hash_value_early_read = read_magic_time(); |
| 271 | 278 | register_pm_notifier(&pm_trace_nb); |
| 272 | 279 | return 0; |
| @@ -277,6 +284,9 @@ static int __init late_resume_init(void) · 4 unmodified lines | ||
| 277 | 284 | unsigned int val = hash_value_early_read; |
| 278 | 285 | unsigned int user, file, dev; |
| 279 | 286 | |
| 287 | + if (!x86_platform.legacy.rtc) | |
| 288 | + return 0; | |
| 289 | + | |
| 280 | 290 | user = val % USERHASH; |
| 281 | 291 | val = val / USERHASH; |
| 282 | 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 | 74 | if (count) |
| 75 | 75 | return count; |
| 76 | 76 | |
| 77 | − kobject_put(&attr_set->kobj); | |
| 78 | 77 | mutex_destroy(&attr_set->update_lock); |
| 78 | + kobject_put(&attr_set->kobj); | |
| 79 | 79 | return 0; |
| 80 | 80 | } |
| 81 | 81 | EXPORT_SYMBOL_GPL(gov_attr_set_put); |
| @@ -3205,11 +3205,15 @@ static int __init intel_pstate_init(void) · 3204 unmodified lines | ||
| 3205 | 3205 | if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) |
| 3206 | 3206 | return -ENODEV; |
| 3207 | 3207 | |
| 3208 | − if (no_load) | |
| 3209 | − return -ENODEV; | |
| 3210 | − | |
| 3211 | 3208 | id = x86_match_cpu(hwp_support_ids); |
| 3212 | 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 | 3217 | copy_cpu_funcs(&core_funcs); |
| 3214 | 3218 | /* |
| 3215 | 3219 | * Avoid enabling HWP for processors without EPP support, |
| @@ -3219,8 +3223,7 @@ static int __init intel_pstate_init(void) · 3 unmodified lines | ||
| 3219 | 3223 | * If HWP is enabled already, though, there is no choice but to |
| 3220 | 3224 | * deal with it. |
| 3221 | 3225 | */ |
| 3222 | − if ((!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) || | |
| 3223 | − intel_pstate_hwp_is_enabled()) { | |
| 3226 | + if ((!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) || hwp_forced) { | |
| 3224 | 3227 | hwp_active++; |
| 3225 | 3228 | hwp_mode_bdw = id->driver_data; |
| 3226 | 3229 | intel_pstate.attr = hwp_cpufreq_attrs; |
| @@ -3235,7 +3238,11 @@ static int __init intel_pstate_init(void) · 8 unmodified lines | ||
| 3235 | 3238 | |
| 3236 | 3239 | goto hwp_cpu_matched; |
| 3237 | 3240 | } |
| 3241 | + pr_info("HWP not enabled\n"); | |
| 3238 | 3242 | } else { |
| 3243 | + if (no_load) | |
| 3244 | + return -ENODEV; | |
| 3245 | + | |
| 3239 | 3246 | id = x86_match_cpu(intel_pstate_cpu_ids); |
| 3240 | 3247 | if (!id) { |
| 3241 | 3248 | pr_info("CPU model not supported\n"); |
| @@ -3314,10 +3321,9 @@ static int __init intel_pstate_setup(char *str) · 72 unmodified lines | ||
| 3314 | 3321 | else if (!strcmp(str, "passive")) |
| 3315 | 3322 | default_driver = &intel_cpufreq; |
| 3316 | 3323 | |
| 3317 | − if (!strcmp(str, "no_hwp")) { | |
| 3318 | − pr_info("HWP disabled\n"); | |
| 3324 | + if (!strcmp(str, "no_hwp")) | |
| 3319 | 3325 | no_hwp = 1; |
| 3320 | − } | |
| 3326 | + | |
| 3321 | 3327 | if (!strcmp(str, "force")) |
| 3322 | 3328 | force_load = 1; |
| 3323 | 3329 | if (!strcmp(str, "hwp_only")) |
| @@ -758,7 +758,7 @@ enum amd_hw_ip_block_type { · 757 unmodified lines | ||
| 758 | 758 | MAX_HWIP |
| 759 | 759 | }; |
| 760 | 760 | |
| 761 | −#define HWIP_MAX_INSTANCE 8 | |
| 761 | +#define HWIP_MAX_INSTANCE 10 | |
| 762 | 762 | |
| 763 | 763 | struct amd_powerplay { |
| 764 | 764 | void *pp_handle; |
| @@ -192,6 +192,16 @@ void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm) · 191 unmodified lines | ||
| 192 | 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 | 205 | int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm) |
| 196 | 206 | { |
| 197 | 207 | int r = 0; |
| @@ -137,6 +137,7 @@ int amdgpu_amdkfd_init(void); · 136 unmodified lines | ||
| 137 | 137 | void amdgpu_amdkfd_fini(void); |
| 138 | 138 | |
| 139 | 139 | void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm); |
| 140 | +int amdgpu_amdkfd_resume_iommu(struct amdgpu_device *adev); | |
| 140 | 141 | int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm); |
| 141 | 142 | void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev, |
| 142 | 143 | const void *ih_ring_entry); |
| @@ -327,6 +328,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, · 184 unmodified lines | ||
| 327 | 328 | const struct kgd2kfd_shared_resources *gpu_resources); |
| 328 | 329 | void kgd2kfd_device_exit(struct kfd_dev *kfd); |
| 329 | 330 | void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm); |
| 331 | +int kgd2kfd_resume_iommu(struct kfd_dev *kfd); | |
| 330 | 332 | int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm); |
| 331 | 333 | int kgd2kfd_pre_reset(struct kfd_dev *kfd); |
| 332 | 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 | 375 | static inline int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) |
| 369 | 376 | { |
| 370 | 377 | return 0; |
| @@ -1544,20 +1544,18 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) · 1543 unmodified lines | ||
| 1544 | 1544 | struct dentry *ent; |
| 1545 | 1545 | int r, i; |
| 1546 | 1546 | |
| 1547 | − | |
| 1548 | − | |
| 1549 | 1547 | ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev, |
| 1550 | 1548 | &fops_ib_preempt); |
| 1551 | − if (!ent) { | |
| 1549 | + if (IS_ERR(ent)) { | |
| 1552 | 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 | 1554 | ent = debugfs_create_file("amdgpu_force_sclk", 0200, root, adev, |
| 1557 | 1555 | &fops_sclk_set); |
| 1558 | − if (!ent) { | |
| 1556 | + if (IS_ERR(ent)) { | |
| 1559 | 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 | 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 | 2394 | if (r) |
| 2395 | 2395 | goto init_failed; |
| 2396 | 2396 | |
| 2397 | + r = amdgpu_amdkfd_resume_iommu(adev); | |
| 2398 | + if (r) | |
| 2399 | + goto init_failed; | |
| 2400 | + | |
| 2397 | 2401 | r = amdgpu_device_ip_hw_init_phase1(adev); |
| 2398 | 2402 | if (r) |
| 2399 | 2403 | goto init_failed; |
| @@ -3148,6 +3152,10 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev) · 748 unmodified lines | ||
| 3148 | 3152 | { |
| 3149 | 3153 | int r; |
| 3150 | 3154 | |
| 3155 | + r = amdgpu_amdkfd_resume_iommu(adev); | |
| 3156 | + if (r) | |
| 3157 | + return r; | |
| 3158 | + | |
| 3151 | 3159 | r = amdgpu_device_ip_resume_phase1(adev); |
| 3152 | 3160 | if (r) |
| 3153 | 3161 | return r; |
| @@ -4601,6 +4609,10 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle, · 1447 unmodified lines | ||
| 4601 | 4609 | dev_warn(tmp_adev->dev, "asic atom init failed!"); |
| 4602 | 4610 | } else { |
| 4603 | 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 | 4616 | r = amdgpu_device_ip_resume_phase1(tmp_adev); |
| 4605 | 4617 | if (r) |
| 4606 | 4618 | goto out; |
| @@ -598,7 +598,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) · 597 unmodified lines | ||
| 598 | 598 | break; |
| 599 | 599 | default: |
| 600 | 600 | adev->gmc.tmz_enabled = false; |
| 601 | − dev_warn(adev->dev, | |
| 601 | + dev_info(adev->dev, | |
| 602 | 602 | "Trusted Memory Zone (TMZ) feature not supported\n"); |
| 603 | 603 | break; |
| 604 | 604 | } |
| @@ -757,7 +757,7 @@ Out: · 756 unmodified lines | ||
| 757 | 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 | 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 | 120 | int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control, |
| 121 | 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 | 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 | 428 | ent = debugfs_create_file(name, |
| 429 | 429 | S_IFREG | S_IRUGO, root, |
| 430 | 430 | ring, &amdgpu_debugfs_ring_fops); |
| 431 | − if (!ent) | |
| 432 | − return -ENOMEM; | |
| 431 | + if (IS_ERR(ent)) | |
| 432 | + return PTR_ERR(ent); | |
| 433 | 433 | |
| 434 | 434 | i_size_write(ent->d_inode, ring->ring_size + 12); |
| 435 | 435 | ring->ent = ent; |
| @@ -515,6 +515,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, · 514 unmodified lines | ||
| 515 | 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 | 527 | if (adev->mman.buffer_funcs_enabled) { |
| 519 | 528 | if (((old_mem->mem_type == TTM_PL_SYSTEM && |
| 520 | 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 | 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 | 557 | out: |
| 558 | 558 | /* update statistics */ |
| 559 | 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 | 468 | .needs_iommu_device = false, |
| 469 | 469 | .supports_cwsr = true, |
| 470 | 470 | .needs_pci_atomics = true, |
| 471 | + .no_atomic_fw_version = 145, | |
| 471 | 472 | .num_sdma_engines = 2, |
| 472 | 473 | .num_xgmi_sdma_engines = 0, |
| 473 | 474 | .num_sdma_queues_per_engine = 8, |
| @@ -487,6 +488,7 @@ static const struct kfd_device_info navi12_device_info = { · 13 unmodified lines | ||
| 487 | 488 | .needs_iommu_device = false, |
| 488 | 489 | .supports_cwsr = true, |
| 489 | 490 | .needs_pci_atomics = true, |
| 491 | + .no_atomic_fw_version = 145, | |
| 490 | 492 | .num_sdma_engines = 2, |
| 491 | 493 | .num_xgmi_sdma_engines = 0, |
| 492 | 494 | .num_sdma_queues_per_engine = 8, |
| @@ -506,6 +508,7 @@ static const struct kfd_device_info navi14_device_info = { · 13 unmodified lines | ||
| 506 | 508 | .needs_iommu_device = false, |
| 507 | 509 | .supports_cwsr = true, |
| 508 | 510 | .needs_pci_atomics = true, |
| 511 | + .no_atomic_fw_version = 145, | |
| 509 | 512 | .num_sdma_engines = 2, |
| 510 | 513 | .num_xgmi_sdma_engines = 0, |
| 511 | 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 | 528 | .needs_iommu_device = false, |
| 526 | 529 | .supports_cwsr = true, |
| 527 | 530 | .needs_pci_atomics = true, |
| 531 | + .no_atomic_fw_version = 92, | |
| 528 | 532 | .num_sdma_engines = 4, |
| 529 | 533 | .num_xgmi_sdma_engines = 0, |
| 530 | 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 | 548 | .needs_iommu_device = false, |
| 545 | 549 | .supports_cwsr = true, |
| 546 | 550 | .needs_pci_atomics = true, |
| 551 | + .no_atomic_fw_version = 92, | |
| 547 | 552 | .num_sdma_engines = 2, |
| 548 | 553 | .num_xgmi_sdma_engines = 0, |
| 549 | 554 | .num_sdma_queues_per_engine = 8, |
| @@ -562,7 +567,8 @@ static const struct kfd_device_info vangogh_device_info = { · 12 unmodified lines | ||
| 562 | 567 | .mqd_size_aligned = MQD_SIZE_ALIGNED, |
| 563 | 568 | .needs_iommu_device = false, |
| 564 | 569 | .supports_cwsr = true, |
| 565 | − .needs_pci_atomics = false, | |
| 570 | + .needs_pci_atomics = true, | |
| 571 | + .no_atomic_fw_version = 92, | |
| 566 | 572 | .num_sdma_engines = 1, |
| 567 | 573 | .num_xgmi_sdma_engines = 0, |
| 568 | 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 | 588 | .needs_iommu_device = false, |
| 583 | 589 | .supports_cwsr = true, |
| 584 | 590 | .needs_pci_atomics = true, |
| 591 | + .no_atomic_fw_version = 92, | |
| 585 | 592 | .num_sdma_engines = 2, |
| 586 | 593 | .num_xgmi_sdma_engines = 0, |
| 587 | 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 | 608 | .needs_iommu_device = false, |
| 602 | 609 | .supports_cwsr = true, |
| 603 | 610 | .needs_pci_atomics = true, |
| 611 | + .no_atomic_fw_version = 92, | |
| 604 | 612 | .num_sdma_engines = 1, |
| 605 | 613 | .num_xgmi_sdma_engines = 0, |
| 606 | 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 | 627 | .mqd_size_aligned = MQD_SIZE_ALIGNED, |
| 620 | 628 | .needs_iommu_device = false, |
| 621 | 629 | .supports_cwsr = true, |
| 622 | − .needs_pci_atomics = false, | |
| 630 | + .needs_pci_atomics = true, | |
| 631 | + .no_atomic_fw_version = 92, | |
| 623 | 632 | .num_sdma_engines = 1, |
| 624 | 633 | .num_xgmi_sdma_engines = 0, |
| 625 | 634 | .num_sdma_queues_per_engine = 2, |
| @@ -708,20 +717,6 @@ struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, · 82 unmodified lines | ||
| 708 | 717 | if (!kfd) |
| 709 | 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 | 720 | kfd->kgd = kgd; |
| 726 | 721 | kfd->device_info = device_info; |
| 727 | 722 | kfd->pdev = pdev; |
| @@ -821,6 +816,23 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, · 93 unmodified lines | ||
| 821 | 816 | kfd->vm_info.vmid_num_kfd = kfd->vm_info.last_vmid_kfd |
| 822 | 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 | 836 | /* Verify module parameters regarding mapped process number*/ |
| 825 | 837 | if ((hws_max_conc_proc < 0) |
| 826 | 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 | 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 | 1074 | int err = 0; |
| 1063 | 1075 | |
| 1064 | 1076 | err = kfd_iommu_resume(kfd); |
| 1065 | − if (err) { | |
| 1077 | + if (err) | |
| 1066 | 1078 | dev_err(kfd_device, |
| 1067 | 1079 | "Failed to resume IOMMU for device %x:%x\n", |
| 1068 | 1080 | kfd->pdev->vendor, kfd->pdev->device); |
| 1069 | − return err; | |
| 1070 | − } | |
| 1081 | + return err; | |
| 1082 | +} | |
| 1083 | + | |
| 1084 | +static int kfd_resume(struct kfd_dev *kfd) | |
| 1085 | +{ | |
| 1086 | + int err = 0; | |
| 1071 | 1087 | |
| 1072 | 1088 | err = kfd->dqm->ops.start(kfd->dqm); |
| 1073 | 1089 | if (err) { |
| @@ -207,6 +207,7 @@ struct kfd_device_info { · 206 unmodified lines | ||
| 207 | 207 | bool supports_cwsr; |
| 208 | 208 | bool needs_iommu_device; |
| 209 | 209 | bool needs_pci_atomics; |
| 210 | + uint32_t no_atomic_fw_version; | |
| 210 | 211 | unsigned int num_sdma_engines; |
| 211 | 212 | unsigned int num_xgmi_sdma_engines; |
| 212 | 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 | 998 | uint32_t agp_base, agp_bot, agp_top; |
| 999 | 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 | 1003 | logical_addr_low = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18; |
| 1002 | 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 | 6026 | return 0; |
| 6025 | 6027 | |
| 6026 | 6028 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 6027 | − work = kzalloc(sizeof(*work), GFP_ATOMIC); | |
| 6028 | − if (!work) | |
| 6029 | − return -ENOMEM; | |
| 6029 | + if (dm->vblank_control_workqueue) { | |
| 6030 | + work = kzalloc(sizeof(*work), GFP_ATOMIC); | |
| 6031 | + if (!work) | |
| 6032 | + return -ENOMEM; | |
| 6030 | 6033 | |
| 6031 | − INIT_WORK(&work->work, vblank_control_worker); | |
| 6032 | − work->dm = dm; | |
| 6033 | − work->acrtc = acrtc; | |
| 6034 | − work->enable = enable; | |
| 6034 | + INIT_WORK(&work->work, vblank_control_worker); | |
| 6035 | + work->dm = dm; | |
| 6036 | + work->acrtc = acrtc; | |
| 6037 | + work->enable = enable; | |
| 6035 | 6038 | |
| 6036 | − if (acrtc_state->stream) { | |
| 6037 | − dc_stream_retain(acrtc_state->stream); | |
| 6038 | − work->stream = acrtc_state->stream; | |
| 6039 | − } | |
| 6039 | + if (acrtc_state->stream) { | |
| 6040 | + dc_stream_retain(acrtc_state->stream); | |
| 6041 | + work->stream = acrtc_state->stream; | |
| 6042 | + } | |
| 6040 | 6043 | |
| 6041 | − queue_work(dm->vblank_control_workqueue, &work->work); | |
| 6044 | + queue_work(dm->vblank_control_workqueue, &work->work); | |
| 6045 | + } | |
| 6042 | 6046 | #endif |
| 6043 | 6047 | |
| 6044 | 6048 | return 0; |
| @@ -6792,14 +6796,15 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { · 747 unmodified lines | ||
| 6792 | 6796 | |
| 6793 | 6797 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 6794 | 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 | 6802 | struct dc_stream_state *stream = NULL; |
| 6798 | 6803 | struct drm_connector *connector; |
| 6799 | 6804 | struct drm_connector_state *new_con_state; |
| 6800 | 6805 | struct amdgpu_dm_connector *aconnector; |
| 6801 | 6806 | struct dm_connector_state *dm_conn_state; |
| 6802 | − int i, j, clock, bpp; | |
| 6807 | + int i, j, clock; | |
| 6803 | 6808 | int vcpi, pbn_div, pbn = 0; |
| 6804 | 6809 | |
| 6805 | 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 | 6845 | pbn_div = dm_mst_get_pbn_divider(stream->link); |
| 6841 | − bpp = stream->timing.dsc_cfg.bits_per_pixel; | |
| 6842 | 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 | 6855 | vcpi = drm_dp_mst_atomic_enable_dsc(state, |
| 6845 | 6856 | aconnector->port, |
| 6846 | 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 | 7559 | static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, |
| 7523 | 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 | 7584 | * restored here. |
| 7548 | 7585 | */ |
| 7549 | 7586 | amdgpu_dm_update_freesync_caps(connector, edid); |
| 7587 | + | |
| 7588 | + amdgpu_set_panel_orientation(connector); | |
| 7550 | 7589 | } else { |
| 7551 | 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 | 8097 | state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED) |
| 8059 | 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 | |
| 8062 | − * hot-plug, headless s3, dpms | |
| 8100 | + /* Stream removed and re-enabled | |
| 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 | 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 | 8705 | * If PSR or idle optimizations are enabled then flush out |
| 8649 | 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 | 8710 | #endif |
| 8653 | 8711 | |
| 8654 | 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 | 9041 | /* if there mode set or reset, disable eDP PSR */ |
| 8984 | 9042 | if (mode_set_reset_required) { |
| 8985 | 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 | 9046 | #endif |
| 8988 | 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 | 10302 | int ret, i; |
| 10244 | 10303 | bool lock_and_validation_needed = false; |
| 10245 | 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 | 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 | 10535 | goto fail; |
| 10474 | 10536 | |
| 10475 | 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 | 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 | 10542 | if (ret) |
| 10481 | 10543 | goto fail; |
| 10482 | 10544 | #endif |
| @@ -10492,7 +10554,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, · 9 unmodified lines | ||
| 10492 | 10554 | goto fail; |
| 10493 | 10555 | status = dc_validate_global_state(dc, dm_state->context, false); |
| 10494 | 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 | 10559 | dc_status_to_str(status), status); |
| 10497 | 10560 | ret = -EINVAL; |
| 10498 | 10561 | goto fail; |
| @@ -518,12 +518,7 @@ struct dsc_mst_fairness_params { · 517 unmodified lines | ||
| 518 | 518 | uint32_t num_slices_h; |
| 519 | 519 | uint32_t num_slices_v; |
| 520 | 520 | uint32_t bpp_overwrite; |
| 521 | −}; | |
| 522 | − | |
| 523 | −struct dsc_mst_fairness_vars { | |
| 524 | − int pbn; | |
| 525 | − bool dsc_enabled; | |
| 526 | − int bpp_x16; | |
| 521 | + struct amdgpu_dm_connector *aconnector; | |
| 527 | 522 | }; |
| 528 | 523 | |
| 529 | 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 | 746 | static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, |
| 752 | 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 | 751 | int i; |
| 756 | 752 | struct dc_stream_state *stream; |
| 757 | 753 | struct dsc_mst_fairness_params params[MAX_PIPES]; |
| 758 | − struct dsc_mst_fairness_vars vars[MAX_PIPES]; | |
| 759 | 754 | struct amdgpu_dm_connector *aconnector; |
| 760 | 755 | int count = 0; |
| 761 | 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 | 771 | params[count].timing = &stream->timing; |
| 777 | 772 | params[count].sink = stream->sink; |
| 778 | 773 | aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; |
| 774 | + params[count].aconnector = aconnector; | |
| 779 | 775 | params[count].port = aconnector->port; |
| 780 | 776 | params[count].clock_force_enable = aconnector->dsc_settings.dsc_force_enable; |
| 781 | 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 | 795 | /* Try no compression */ |
| 800 | 796 | for (i = 0; i < count; i++) { |
| 797 | + vars[i].aconnector = params[i].aconnector; | |
| 801 | 798 | vars[i].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); |
| 802 | 799 | vars[i].dsc_enabled = false; |
| 803 | 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 | 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 | 854 | int i, j; |
| 857 | 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 | 880 | return false; |
| 883 | 881 | |
| 884 | 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 | 884 | mutex_unlock(&aconnector->mst_mgr.lock); |
| 887 | 885 | return false; |
| 888 | 886 | } |
| @@ -39,8 +39,17 @@ void · 38 unmodified lines | ||
| 39 | 39 | dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev); |
| 40 | 40 | |
| 41 | 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 | 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 | 53 | #endif |
| 45 | 54 | |
| 46 | 55 | #endif |
| @@ -62,7 +62,7 @@ inline void dc_assert_fp_enabled(void) · 61 unmodified lines | ||
| 62 | 62 | depth = *pcpu; |
| 63 | 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 | 2587 | int dc_link_get_backlight_level(const struct dc_link *link) |
| 2588 | 2588 | { |
| 2589 | − | |
| 2590 | 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) | |
| 2593 | − return DC_ERROR_UNEXPECTED; | |
| 2595 | + if (dmcu) | |
| 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 | 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 | 24 | #include "dm_services.h" |
| 3 | 25 | #include "dc.h" |
| 4 | 26 | #include "dc_link_dp.h" |
| @@ -1840,9 +1862,13 @@ bool perform_link_training_with_retries( · 1835 unmodified lines | ||
| 1840 | 1862 | dp_disable_link_phy(link, signal); |
| 1841 | 1863 | |
| 1842 | 1864 | /* Abort link training if failure due to sink being unplugged. */ |
| 1843 | − if (status == LINK_TRAINING_ABORT) | |
| 1844 | − break; | |
| 1845 | − else if (do_fallback) { | |
| 1865 | + if (status == LINK_TRAINING_ABORT) { | |
| 1866 | + enum dc_connection_type type = dc_connection_none; | |
| 1867 | + | |
| 1868 | + dc_link_detect_sink(link, &type); | |
| 1869 | + if (type == dc_connection_none) | |
| 1870 | + break; | |
| 1871 | + } else if (do_fallback) { | |
| 1846 | 1872 | decide_fallback_link_setting(*link_setting, ¤t_setting, status); |
| 1847 | 1873 | /* Fail link training if reduced link bandwidth no longer meets |
| 1848 | 1874 | * stream requirements. |
| @@ -49,7 +49,6 @@ · 48 unmodified lines | ||
| 49 | 49 | static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl) |
| 50 | 50 | { |
| 51 | 51 | uint64_t current_backlight; |
| 52 | − uint32_t round_result; | |
| 53 | 52 | uint32_t bl_period, bl_int_count; |
| 54 | 53 | uint32_t bl_pwm, fractional_duty_cycle_en; |
| 55 | 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 | 83 | current_backlight = div_u64(current_backlight, bl_period); |
| 85 | 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 | 86 | return (uint32_t)(current_backlight); |
| 97 | 87 | } |
| 98 | 88 | |
| @@ -33,63 +33,47 @@ · 32 unmodified lines | ||
| 33 | 33 | #define TABLE_PMSTATUSLOG 3 // Called by Tools for Agm logging |
| 34 | 34 | #define TABLE_DPMCLOCKS 4 // Called by Driver; defined here, but not used, for backward compatible |
| 35 | 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 | −#define NUM_SOCCLK_DPM_LEVELS 8 | |
| 40 | −#define NUM_DCEFCLK_DPM_LEVELS 4 | |
| 41 | −#define NUM_FCLK_DPM_LEVELS 4 | |
| 42 | −#define NUM_MEMCLK_DPM_LEVELS 4 | |
| 39 | +typedef struct SmuMetricsTable_t { | |
| 40 | + //CPU status | |
| 41 | + uint16_t CoreFrequency[6]; //[MHz] | |
| 42 | + uint32_t CorePower[6]; //[mW] | |
| 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 | |
| 45 | −#define NUMBER_OF_CORES 8 | |
| 48 | + // GFX status | |
| 49 | + uint16_t GfxclkFrequency; //[MHz] | |
| 50 | + uint16_t GfxTemperature; //[centi-Celsius] | |
| 46 | 51 | |
| 47 | −typedef enum { | |
| 48 | − S3_TYPE_ENTRY, | |
| 49 | − S5_TYPE_ENTRY, | |
| 50 | −} Sleep_Type_e; | |
| 52 | + // SOC IP info | |
| 53 | + uint16_t SocclkFrequency; //[MHz] | |
| 54 | + uint16_t VclkFrequency; //[MHz] | |
| 55 | + uint16_t DclkFrequency; //[MHz] | |
| 56 | + uint16_t MemclkFrequency; //[MHz] | |
| 51 | 57 | |
| 52 | −typedef enum { | |
| 53 | − GFX_OFF = 0, | |
| 54 | − GFX_ON = 1, | |
| 55 | −} GFX_Mode_e; | |
| 58 | + // power, VF info for CPU/GFX telemetry rails, and then socket power total | |
| 59 | + uint32_t Voltage[2]; //[mV] indices: VDDCR_VDD, VDDCR_GFX | |
| 60 | + uint32_t Current[2]; //[mA] indices: VDDCR_VDD, VDDCR_GFX | |
| 61 | + uint32_t Power[2]; //[mW] indices: VDDCR_VDD, VDDCR_GFX | |
| 62 | + uint32_t CurrentSocketPower; //[mW] | |
| 56 | 63 | |
| 57 | −typedef enum { | |
| 58 | − CPU_P0 = 0, | |
| 59 | − CPU_P1, | |
| 60 | − CPU_P2, | |
| 61 | − CPU_P3, | |
| 62 | − CPU_P4, | |
| 63 | − CPU_P5, | |
| 64 | − CPU_P6, | |
| 65 | − CPU_P7 | |
| 66 | −} CPU_PState_e; | |
| 64 | + uint16_t SocTemperature; //[centi-Celsius] | |
| 65 | + uint16_t EdgeTemperature; | |
| 66 | + uint16_t ThrottlerStatus; | |
| 67 | + uint16_t Spare; | |
| 67 | 68 | |
| 68 | −typedef enum { | |
| 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; | |
| 69 | +} SmuMetricsTable_t; | |
| 78 | 70 | |
| 79 | −typedef enum { | |
| 80 | − DF_DPM0 = 0, | |
| 81 | − DF_DPM1, | |
| 82 | − DF_DPM2, | |
| 83 | − DF_DPM3, | |
| 84 | − DF_PState_Count | |
| 85 | −} DF_PState_e; | |
| 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; | |
| 71 | +typedef struct SmuMetrics_t { | |
| 72 | + SmuMetricsTable_t Current; | |
| 73 | + SmuMetricsTable_t Average; | |
| 74 | + uint32_t SampleStartTime; | |
| 75 | + uint32_t SampleStopTime; | |
| 76 | + uint32_t Accnt; | |
| 77 | +} SmuMetrics_t; | |
| 94 | 78 | |
| 95 | 79 | #endif |
| @@ -226,7 +226,10 @@ · 225 unmodified lines | ||
| 226 | 226 | __SMU_DUMMY_MAP(SetUclkDpmMode), \ |
| 227 | 227 | __SMU_DUMMY_MAP(LightSBR), \ |
| 228 | 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 | 234 | #undef __SMU_DUMMY_MAP |
| 232 | 235 | #define __SMU_DUMMY_MAP(type) SMU_MSG_##type |
| @@ -65,6 +65,13 @@ · 64 unmodified lines | ||
| 65 | 65 | #define PPSMC_MSG_SetDriverTableVMID 0x34 |
| 66 | 66 | #define PPSMC_MSG_SetSoftMinCclk 0x35 |
| 67 | 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 | 77 | #endif |
| @@ -1404,7 +1404,7 @@ static int smu_disable_dpms(struct smu_context *smu) · 1403 unmodified lines | ||
| 1404 | 1404 | */ |
| 1405 | 1405 | if (smu->uploading_custom_pp_table && |
| 1406 | 1406 | (adev->asic_type >= CHIP_NAVI10) && |
| 1407 | − (adev->asic_type <= CHIP_DIMGREY_CAVEFISH)) | |
| 1407 | + (adev->asic_type <= CHIP_BEIGE_GOBY)) | |
| 1408 | 1408 | return smu_disable_all_features_with_exception(smu, |
| 1409 | 1409 | true, |
| 1410 | 1410 | SMU_FEATURE_COUNT); |
| @@ -771,8 +771,12 @@ static int arcturus_print_clk_levels(struct smu_context *smu, · 770 unmodified lines | ||
| 771 | 771 | struct smu_11_0_dpm_context *dpm_context = NULL; |
| 772 | 772 | uint32_t gen_speed, lane_width; |
| 773 | 773 | |
| 774 | − if (amdgpu_ras_intr_triggered()) | |
| 775 | − return sysfs_emit(buf, "unavailable\n"); | |
| 774 | + smu_cmn_get_sysfs_buf(&buf, &size); | |
| 775 | + | |
| 776 | + if (amdgpu_ras_intr_triggered()) { | |
| 777 | + size += sysfs_emit_at(buf, size, "unavailable\n"); | |
| 778 | + return size; | |
| 779 | + } | |
| 776 | 780 | |
| 777 | 781 | dpm_context = smu_dpm->dpm_context; |
| 778 | 782 | |
| @@ -44,6 +44,27 @@ · 43 unmodified lines | ||
| 44 | 44 | #undef pr_info |
| 45 | 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 | 68 | static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = { |
| 48 | 69 | MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), |
| 49 | 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 | 73 | MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverTableDramAddrLow, 0), |
| 53 | 74 | MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), |
| 54 | 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 | 530 | static const struct pptable_funcs cyan_skillfish_ppt_funcs = { |
| 58 | 531 | |
| 59 | 532 | .check_fw_status = smu_v11_0_check_fw_status, |
| 60 | 533 | .check_fw_version = smu_v11_0_check_fw_version, |
| 61 | 534 | .init_power = smu_v11_0_init_power, |
| 62 | 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 | 543 | .register_irq_handler = smu_v11_0_register_irq_handler, |
| 64 | 544 | .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, |
| 65 | 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 | 553 | smu->ppt_funcs = &cyan_skillfish_ppt_funcs; |
| 74 | 554 | smu->message_map = cyan_skillfish_message_map; |
| 555 | + smu->table_map = cyan_skillfish_table_map; | |
| 75 | 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 | 1279 | struct smu_11_0_overdrive_table *od_settings = smu->od_settings; |
| 1280 | 1280 | uint32_t min_value, max_value; |
| 1281 | 1281 | |
| 1282 | + smu_cmn_get_sysfs_buf(&buf, &size); | |
| 1283 | + | |
| 1282 | 1284 | switch (clk_type) { |
| 1283 | 1285 | case SMU_GFXCLK: |
| 1284 | 1286 | case SMU_SCLK: |
| @@ -1392,7 +1394,7 @@ static int navi10_print_clk_levels(struct smu_context *smu, · 107 unmodified lines | ||
| 1392 | 1394 | case SMU_OD_RANGE: |
| 1393 | 1395 | if (!smu->od_enabled || !od_table || !od_settings) |
| 1394 | 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 | 1399 | if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) { |
| 1398 | 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 | 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 | 2298 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); |
| 2277 | 2299 | else |
| 2278 | 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 | 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 | 2308 | /* Wait for PMFW handling for the Dstate change */ |
| 2287 | 2309 | msleep(10); |
| 2288 | 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 | 1058 | uint32_t min_value, max_value; |
| 1059 | 1059 | uint32_t smu_version; |
| 1060 | 1060 | |
| 1061 | + smu_cmn_get_sysfs_buf(&buf, &size); | |
| 1062 | + | |
| 1061 | 1063 | switch (clk_type) { |
| 1062 | 1064 | case SMU_GFXCLK: |
| 1063 | 1065 | case SMU_SCLK: |
| @@ -1180,7 +1182,7 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu, · 116 unmodified lines | ||
| 1180 | 1182 | if (!smu->od_enabled || !od_table || !od_settings) |
| 1181 | 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 | 1187 | if (sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_GFXCLK_LIMITS)) { |
| 1186 | 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 | 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 | 2193 | return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); |
| 2192 | 2194 | else |
| 2193 | 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 | 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 | 2203 | /* Wait for PMFW handling for the Dstate change */ |
| 2202 | 2204 | msleep(10); |
| 2203 | 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 | 589 | if (ret) |
| 590 | 590 | return ret; |
| 591 | 591 | |
| 592 | + smu_cmn_get_sysfs_buf(&buf, &size); | |
| 593 | + | |
| 592 | 594 | switch (clk_type) { |
| 593 | 595 | case SMU_OD_SCLK: |
| 594 | 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 | 598 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", |
| 597 | 599 | (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); |
| 598 | 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 | 603 | break; |
| 602 | 604 | case SMU_OD_CCLK: |
| 603 | 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 | 607 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", |
| 606 | 608 | (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq); |
| 607 | 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 | 612 | break; |
| 611 | 613 | case SMU_OD_RANGE: |
| 612 | 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 | 616 | size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", |
| 615 | 617 | smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); |
| 616 | 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 | 690 | if (ret) |
| 689 | 691 | return ret; |
| 690 | 692 | |
| 693 | + smu_cmn_get_sysfs_buf(&buf, &size); | |
| 694 | + | |
| 691 | 695 | switch (clk_type) { |
| 692 | 696 | case SMU_OD_SCLK: |
| 693 | 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 | 699 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", |
| 696 | 700 | (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); |
| 697 | 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 | 704 | break; |
| 701 | 705 | case SMU_OD_CCLK: |
| 702 | 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 | 708 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", |
| 705 | 709 | (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq); |
| 706 | 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 | 713 | break; |
| 710 | 714 | case SMU_OD_RANGE: |
| 711 | 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 | 717 | size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", |
| 714 | 718 | smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); |
| 715 | 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 | 497 | if (ret) |
| 498 | 498 | return ret; |
| 499 | 499 | |
| 500 | + smu_cmn_get_sysfs_buf(&buf, &size); | |
| 501 | + | |
| 500 | 502 | switch (clk_type) { |
| 501 | 503 | case SMU_OD_RANGE: |
| 502 | 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 | 733 | uint32_t freq_values[3] = {0}; |
| 734 | 734 | uint32_t min_clk, max_clk; |
| 735 | 735 | |
| 736 | − if (amdgpu_ras_intr_triggered()) | |
| 737 | − return sysfs_emit(buf, "unavailable\n"); | |
| 736 | + smu_cmn_get_sysfs_buf(&buf, &size); | |
| 737 | + | |
| 738 | + if (amdgpu_ras_intr_triggered()) { | |
| 739 | + size += sysfs_emit_at(buf, size, "unavailable\n"); | |
| 740 | + return size; | |
| 741 | + } | |
| 738 | 742 | |
| 739 | 743 | dpm_context = smu_dpm->dpm_context; |
| 740 | 744 | |
| 741 | 745 | switch (type) { |
| 742 | 746 | |
| 743 | 747 | case SMU_OD_SCLK: |
| 744 | − size = sysfs_emit(buf, "%s:\n", "GFXCLK"); | |
| 748 | + size += sysfs_emit_at(buf, size, "%s:\n", "GFXCLK"); | |
| 745 | 749 | fallthrough; |
| 746 | 750 | case SMU_SCLK: |
| 747 | 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 | 799 | break; |
| 796 | 800 | |
| 797 | 801 | case SMU_OD_MCLK: |
| 798 | − size = sysfs_emit(buf, "%s:\n", "MCLK"); | |
| 802 | + size += sysfs_emit_at(buf, size, "%s:\n", "MCLK"); | |
| 799 | 803 | fallthrough; |
| 800 | 804 | case SMU_MCLK: |
| 801 | 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 | 1052 | int i, size = 0, ret = 0; |
| 1053 | 1053 | uint32_t cur_value = 0, value = 0, count = 0; |
| 1054 | 1054 | |
| 1055 | + smu_cmn_get_sysfs_buf(&buf, &size); | |
| 1056 | + | |
| 1055 | 1057 | switch (clk_type) { |
| 1056 | 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 | 1060 | size += sysfs_emit_at(buf, size, "0: %10uMhz\n", |
| 1059 | 1061 | (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); |
| 1060 | 1062 | size += sysfs_emit_at(buf, size, "1: %10uMhz\n", |
| 1061 | 1063 | (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); |
| 1062 | 1064 | break; |
| 1063 | 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 | 1067 | size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", |
| 1066 | 1068 | smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); |
| 1067 | 1069 | break; |
| @@ -1053,3 +1053,24 @@ int smu_cmn_set_mp1_state(struct smu_context *smu, · 1052 unmodified lines | ||
| 1053 | 1053 | |
| 1054 | 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 | 110 | int smu_cmn_set_mp1_state(struct smu_context *smu, |
| 111 | 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 | 128 | #endif |
| 114 | 129 | #endif |
| @@ -397,8 +397,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state, · 396 unmodified lines | ||
| 397 | 397 | if (switch_mmu_context) { |
| 398 | 398 | struct etnaviv_iommu_context *old_context = gpu->mmu_context; |
| 399 | 399 | |
| 400 | − etnaviv_iommu_context_get(mmu_context); | |
| 401 | − gpu->mmu_context = mmu_context; | |
| 400 | + gpu->mmu_context = etnaviv_iommu_context_get(mmu_context); | |
| 402 | 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 | 294 | list_del(&mapping->obj_node); |
| 295 | 295 | } |
| 296 | 296 | |
| 297 | − etnaviv_iommu_context_get(mmu_context); | |
| 298 | − mapping->context = mmu_context; | |
| 297 | + mapping->context = etnaviv_iommu_context_get(mmu_context); | |
| 299 | 298 | mapping->use = 1; |
| 300 | 299 | |
| 301 | 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 | 532 | goto err_submit_objects; |
| 533 | 533 | |
| 534 | 534 | submit->ctx = file->driver_priv; |
| 535 | − etnaviv_iommu_context_get(submit->ctx->mmu); | |
| 536 | − submit->mmu_context = submit->ctx->mmu; | |
| 535 | + submit->mmu_context = etnaviv_iommu_context_get(submit->ctx->mmu); | |
| 537 | 536 | submit->exec_state = args->exec_state; |
| 538 | 537 | submit->flags = args->flags; |
| 539 | 538 | |
| @@ -569,6 +569,12 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu) · 568 unmodified lines | ||
| 569 | 569 | /* We rely on the GPU running, so program the clock */ |
| 570 | 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 | 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 | 643 | VIVS_MMUv2_SEC_COMMAND_CONTROL_ENABLE | |
| 638 | 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 | 653 | u16 prefetch; |
| 654 | + u32 address; | |
| 647 | 655 | |
| 648 | 656 | /* setup the MMU */ |
| 649 | − etnaviv_iommu_restore(gpu, gpu->mmu_context); | |
| 657 | + etnaviv_iommu_restore(gpu, context); | |
| 650 | 658 | |
| 651 | 659 | /* Start command processor */ |
| 652 | 660 | prefetch = etnaviv_buffer_init(gpu); |
| 661 | + address = etnaviv_cmdbuf_get_va(&gpu->buffer, | |
| 662 | + &gpu->mmu_context->cmdbuf_mapping); | |
| 653 | 663 | |
| 654 | 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 | 842 | /* Now program the hardware */ |
| 833 | 843 | mutex_lock(&gpu->lock); |
| 834 | 844 | etnaviv_gpu_hw_init(gpu); |
| 835 | − gpu->exec_state = -1; | |
| 836 | 845 | mutex_unlock(&gpu->lock); |
| 837 | 846 | |
| 838 | 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 | 1066 | spin_unlock(&gpu->event_spinlock); |
| 1058 | 1067 | |
| 1059 | 1068 | etnaviv_gpu_hw_init(gpu); |
| 1060 | − gpu->exec_state = -1; | |
| 1061 | − gpu->mmu_context = NULL; | |
| 1062 | 1069 | |
| 1063 | 1070 | mutex_unlock(&gpu->lock); |
| 1064 | 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 | 1377 | goto out_unlock; |
| 1371 | 1378 | } |
| 1372 | 1379 | |
| 1373 | − if (!gpu->mmu_context) { | |
| 1374 | − etnaviv_iommu_context_get(submit->mmu_context); | |
| 1375 | − gpu->mmu_context = submit->mmu_context; | |
| 1376 | − etnaviv_gpu_start_fe_idleloop(gpu); | |
| 1377 | − } else { | |
| 1378 | − etnaviv_iommu_context_get(gpu->mmu_context); | |
| 1379 | − submit->prev_mmu_context = gpu->mmu_context; | |
| 1380 | − } | |
| 1380 | + if (!gpu->fe_running) | |
| 1381 | + etnaviv_gpu_start_fe_idleloop(gpu, submit->mmu_context); | |
| 1382 | + | |
| 1383 | + if (submit->prev_mmu_context) | |
| 1384 | + etnaviv_iommu_context_put(submit->prev_mmu_context); | |
| 1385 | + submit->prev_mmu_context = etnaviv_iommu_context_get(gpu->mmu_context); | |
| 1381 | 1386 | |
| 1382 | 1387 | if (submit->nr_pmrs) { |
| 1383 | 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 | 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 | 1588 | /* Replace the last WAIT with END */ |
| 1584 | 1589 | mutex_lock(&gpu->lock); |
| 1585 | 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 | 1598 | etnaviv_gpu_wait_idle(gpu, 100); |
| 1594 | 1599 | |
| 1595 | − etnaviv_iommu_context_put(gpu->mmu_context); | |
| 1596 | − gpu->mmu_context = NULL; | |
| 1600 | + gpu->fe_running = false; | |
| 1597 | 1601 | } |
| 1598 | 1602 | |
| 1599 | 1603 | gpu->exec_state = -1; |
| @@ -1741,6 +1745,9 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master, · 141 unmodified lines | ||
| 1741 | 1745 | etnaviv_gpu_hw_suspend(gpu); |
| 1742 | 1746 | #endif |
| 1743 | 1747 | |
| 1748 | + if (gpu->mmu_context) | |
| 1749 | + etnaviv_iommu_context_put(gpu->mmu_context); | |
| 1750 | + | |
| 1744 | 1751 | if (gpu->initialized) { |
| 1745 | 1752 | etnaviv_cmdbuf_free(&gpu->buffer); |
| 1746 | 1753 | etnaviv_iommu_global_fini(gpu); |
| @@ -101,6 +101,7 @@ struct etnaviv_gpu { · 100 unmodified lines | ||
| 101 | 101 | struct workqueue_struct *wq; |
| 102 | 102 | struct drm_gpu_scheduler sched; |
| 103 | 103 | bool initialized; |
| 104 | + bool fe_running; | |
| 104 | 105 | |
| 105 | 106 | /* 'ring'-buffer: */ |
| 106 | 107 | struct etnaviv_cmdbuf buffer; |
| @@ -92,6 +92,10 @@ static void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu, · 91 unmodified lines | ||
| 92 | 92 | struct etnaviv_iommuv1_context *v1_context = to_v1_context(context); |
| 93 | 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 | 99 | /* set base addresses */ |
| 96 | 100 | gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_RA, context->global->memory_base); |
| 97 | 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 | 172 | if (gpu_read(gpu, VIVS_MMUv2_CONTROL) & VIVS_MMUv2_CONTROL_ENABLE) |
| 173 | 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 | 179 | prefetch = etnaviv_buffer_config_mmuv2(gpu, |
| 176 | 180 | (u32)v2_context->mtlb_dma, |
| 177 | 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 | 196 | if (gpu_read(gpu, VIVS_MMUv2_SEC_CONTROL) & VIVS_MMUv2_SEC_CONTROL_ENABLE) |
| 193 | 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 | 203 | gpu_write(gpu, VIVS_MMUv2_PTA_ADDRESS_LOW, |
| 196 | 204 | lower_32_bits(context->global->v2.pta_dma)); |
| 197 | 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 | 200 | list_for_each_entry_safe(m, n, &list, scan_node) { |
| 201 | 201 | etnaviv_iommu_remove_mapping(context, m); |
| 202 | + etnaviv_iommu_context_put(m->context); | |
| 202 | 203 | m->context = NULL; |
| 203 | 204 | list_del_init(&m->mmu_node); |
| 204 | 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 | 105 | struct etnaviv_iommu_context * |
| 106 | 106 | etnaviv_iommu_context_init(struct etnaviv_iommu_global *global, |
| 107 | 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 | 111 | kref_get(&ctx->refcount); |
| 112 | + return ctx; | |
| 111 | 113 | } |
| 112 | 114 | void etnaviv_iommu_context_put(struct etnaviv_iommu_context *ctx); |
| 113 | 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 | 19 | subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable) |
| 20 | 20 | # clang warnings |
| 21 | 21 | subdir-ccflags-y += $(call cc-disable-warning, sign-compare) |
| 22 | −subdir-ccflags-y += $(call cc-disable-warning, sometimes-uninitialized) | |
| 23 | 22 | subdir-ccflags-y += $(call cc-disable-warning, initializer-overrides) |
| 24 | 23 | subdir-ccflags-y += $(call cc-disable-warning, frame-address) |
| 25 | 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 | 2446 | if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, |
| 2447 | 2447 | intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) == |
| 2448 | − sizeof(intel_dp->edp_dpcd)) | |
| 2448 | + sizeof(intel_dp->edp_dpcd)) { | |
| 2449 | 2449 | drm_dbg_kms(&dev_priv->drm, "eDP DPCD: %*ph\n", |
| 2450 | 2450 | (int)sizeof(intel_dp->edp_dpcd), |
| 2451 | 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 | 2457 | * This has to be called after intel_dp->edp_dpcd is filled, PSR checks |
| 2455 | 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 | 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 | 853 | if (intel_dp->set_idle_link_train) |
| 854 | 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 | 986 | trace_i915_context_free(ctx); |
| 987 | 987 | GEM_BUG_ON(!i915_gem_context_is_closed(ctx)); |
| 988 | 988 | |
| 989 | + if (ctx->syncobj) | |
| 990 | + drm_syncobj_put(ctx->syncobj); | |
| 991 | + | |
| 989 | 992 | mutex_destroy(&ctx->engines_mutex); |
| 990 | 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 | 1208 | if (vm) |
| 1206 | 1209 | i915_vm_close(vm); |
| 1207 | 1210 | |
| 1208 | − if (ctx->syncobj) | |
| 1209 | − drm_syncobj_put(ctx->syncobj); | |
| 1210 | − | |
| 1211 | 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 | 59 | err = PTR_ERR(import); |
| 60 | 60 | goto out_dmabuf; |
| 61 | 61 | } |
| 62 | + import_obj = to_intel_bo(import); | |
| 62 | 63 | |
| 63 | 64 | if (import != &obj->base) { |
| 64 | 65 | pr_err("i915_gem_prime_import created a new object!\n"); |
| 65 | 66 | err = -EINVAL; |
| 66 | 67 | goto out_import; |
| 67 | 68 | } |
| 68 | − import_obj = to_intel_bo(import); | |
| 69 | 69 | |
| 70 | 70 | i915_gem_object_lock(import_obj, NULL); |
| 71 | 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 | 128 | pr_err("i915_gem_prime_import failed with the wrong err=%ld\n", |
| 129 | 129 | PTR_ERR(import)); |
| 130 | 130 | err = PTR_ERR(import); |
| 131 | + } else { | |
| 132 | + err = 0; | |
| 131 | 133 | } |
| 132 | 134 | |
| 133 | 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 | 178 | err = PTR_ERR(import); |
| 177 | 179 | goto out_dmabuf; |
| 178 | 180 | } |
| 181 | + import_obj = to_intel_bo(import); | |
| 179 | 182 | |
| 180 | 183 | if (import == &obj->base) { |
| 181 | 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 | 186 | goto out_import; |
| 184 | 187 | } |
| 185 | 188 | |
| 186 | − import_obj = to_intel_bo(import); | |
| 187 | − | |
| 188 | 189 | i915_gem_object_lock(import_obj, NULL); |
| 189 | 190 | err = __i915_gem_object_get_pages(import_obj); |
| 190 | 191 | if (err) { |
| @@ -581,6 +581,20 @@ static enum i915_mmap_type default_mapping(struct drm_i915_private *i915) · 580 unmodified lines | ||
| 581 | 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 | 598 | static bool assert_mmap_offset(struct drm_i915_private *i915, |
| 585 | 599 | unsigned long size, |
| 586 | 600 | int expected) |
| @@ -589,7 +603,7 @@ static bool assert_mmap_offset(struct drm_i915_private *i915, · 2 unmodified lines | ||
| 589 | 603 | u64 offset; |
| 590 | 604 | int ret; |
| 591 | 605 | |
| 592 | − obj = i915_gem_object_create_internal(i915, size); | |
| 606 | + obj = create_sys_or_internal(i915, size); | |
| 593 | 607 | if (IS_ERR(obj)) |
| 594 | 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 | 647 | struct drm_mm_node *hole, *next; |
| 634 | 648 | int loop, err = 0; |
| 635 | 649 | u64 offset; |
| 650 | + int enospc = HAS_LMEM(i915) ? -ENXIO : -ENOSPC; | |
| 636 | 651 | |
| 637 | 652 | /* Disable background reaper */ |
| 638 | 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 | 700 | /* Too large */ |
| 686 | − if (!assert_mmap_offset(i915, 2 * PAGE_SIZE, -ENOSPC)) { | |
| 701 | + if (!assert_mmap_offset(i915, 2 * PAGE_SIZE, enospc)) { | |
| 687 | 702 | pr_err("Unexpectedly succeeded in inserting too large object into single page hole\n"); |
| 688 | 703 | err = -EINVAL; |
| 689 | 704 | goto out; |
| 690 | 705 | } |
| 691 | 706 | |
| 692 | 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 | 709 | if (IS_ERR(obj)) { |
| 695 | 710 | err = PTR_ERR(obj); |
| 696 | 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 | 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 | 722 | pr_err("Unexpectedly succeeded in inserting object into no holes!\n"); |
| 708 | 723 | err = -EINVAL; |
| 709 | 724 | goto err_obj; |
| @@ -839,10 +854,9 @@ static int wc_check(struct drm_i915_gem_object *obj) · 129 unmodified lines | ||
| 839 | 854 | |
| 840 | 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 | 857 | bool no_map; |
| 844 | 858 | |
| 845 | − if (HAS_LMEM(i915)) | |
| 859 | + if (obj->ops->mmap_offset) | |
| 846 | 860 | return type == I915_MMAP_TYPE_FIXED; |
| 847 | 861 | else if (type == I915_MMAP_TYPE_FIXED) |
| 848 | 862 | return false; |
| @@ -1973,8 +1973,14 @@ u32 intel_rps_read_actual_frequency(struct intel_rps *rps) · 1972 unmodified lines | ||
| 1973 | 1973 | u32 intel_rps_read_punit_req(struct intel_rps *rps) |
| 1974 | 1974 | { |
| 1975 | 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 | 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 | 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 | 176 | * Events triggered while CT buffers are disabled are logged in the SCRATCH_15 |
| 182 | 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 | 205 | static void guc_handle_mmio_msg(struct intel_guc *guc) |
| 211 | 206 | { |
| 212 | 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 | 210 | spin_lock_irq(&guc->irq_lock); |
| 216 | 211 | if (guc->mmio_msg) { |
| @@ -226,7 +221,7 @@ static int guc_enable_communication(struct intel_guc *guc) · 9 unmodified lines | ||
| 226 | 221 | struct drm_i915_private *i915 = gt->i915; |
| 227 | 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 | 226 | ret = i915_inject_probe_error(i915, -ENXIO); |
| 232 | 227 | if (ret) |
| @@ -662,7 +657,7 @@ static int __uc_resume(struct intel_uc *uc, bool enable_communication) · 429 unmodified lines | ||
| 662 | 657 | return 0; |
| 663 | 658 | |
| 664 | 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 | 662 | if (enable_communication) |
| 668 | 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 | 57 | args->v0.count = 0; |
| 58 | 58 | args->v0.ustate_ac = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE; |
| 59 | 59 | args->v0.ustate_dc = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE; |
| 60 | − args->v0.pwrsrc = -ENOSYS; | |
| 60 | + args->v0.pwrsrc = -ENODEV; | |
| 61 | 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 | 119 | #endif |
| 120 | 120 | |
| 121 | 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 | 123 | if (rdev->agp) { |
| 124 | 124 | rdev->agp->agp_mtrr = arch_phys_wc_add( |
| 125 | 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 | 167 | struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); |
| 168 | 168 | bool connected = false; |
| 169 | 169 | |
| 170 | − WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); | |
| 171 | − | |
| 172 | 170 | if (vc4_hdmi->hpd_gpio && |
| 173 | 171 | gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) { |
| 174 | 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 | 190 | return connector_status_connected; |
| 194 | 191 | } |
| 195 | 192 | |
| 196 | 193 | cec_phys_addr_invalidate(vc4_hdmi->cec_adap); |
| 197 | − pm_runtime_put(&vc4_hdmi->pdev->dev); | |
| 198 | 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 | 432 | struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); |
| 437 | 433 | struct drm_connector *connector = &vc4_hdmi->connector; |
| 438 | 434 | struct drm_connector_state *cstate = connector->state; |
| 439 | − struct drm_crtc *crtc = cstate->crtc; | |
| 435 | + struct drm_crtc *crtc = encoder->crtc; | |
| 440 | 436 | const struct drm_display_mode *mode = &crtc->state->adjusted_mode; |
| 441 | 437 | union hdmi_infoframe frame; |
| 442 | 438 | int ret; |
| @@ -541,11 +537,8 @@ static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder, · 98 unmodified lines | ||
| 541 | 537 | |
| 542 | 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 | 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 | 543 | if (!vc4_hdmi_supports_scrambling(encoder, mode)) |
| 551 | 544 | return; |
| @@ -566,18 +559,17 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) · 14 unmodified lines | ||
| 566 | 559 | static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) |
| 567 | 560 | { |
| 568 | 561 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); |
| 569 | − struct drm_connector *connector = &vc4_hdmi->connector; | |
| 570 | − struct drm_connector_state *cstate = connector->state; | |
| 562 | + struct drm_crtc *crtc = encoder->crtc; | |
| 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 | 566 | * state of the scrambler and in order to avoid any |
| 575 | 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 | 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 | 573 | return; |
| 582 | 574 | |
| 583 | 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 | 627 | vc4_hdmi->variant->phy_disable(vc4_hdmi); |
| 636 | 628 | |
| 637 | 629 | clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); |
| 630 | + clk_disable_unprepare(vc4_hdmi->hsm_clock); | |
| 638 | 631 | clk_disable_unprepare(vc4_hdmi->pixel_clock); |
| 639 | 632 | |
| 640 | 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 | 891 | vc4_hdmi_encoder_get_connector_state(encoder, state); |
| 899 | 892 | struct vc4_hdmi_connector_state *vc4_conn_state = |
| 900 | 893 | conn_state_to_vc4_hdmi_conn_state(conn_state); |
| 901 | − struct drm_crtc_state *crtc_state = | |
| 902 | − drm_atomic_get_new_crtc_state(state, conn_state->crtc); | |
| 903 | − struct drm_display_mode *mode = &crtc_state->adjusted_mode; | |
| 894 | + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; | |
| 904 | 895 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); |
| 905 | 896 | unsigned long bvb_rate, pixel_rate, hsm_rate; |
| 906 | 897 | int ret; |
| @@ -947,6 +938,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 40 unmodified lines | ||
| 947 | 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 | 948 | vc4_hdmi_cec_update_clk_div(vc4_hdmi); |
| 951 | 949 | |
| 952 | 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 | 957 | ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate); |
| 960 | 958 | if (ret) { |
| 961 | 959 | DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret); |
| 960 | + clk_disable_unprepare(vc4_hdmi->hsm_clock); | |
| 962 | 961 | clk_disable_unprepare(vc4_hdmi->pixel_clock); |
| 963 | 962 | return; |
| 964 | 963 | } |
| @@ -966,6 +965,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 1 unmodified line | ||
| 966 | 965 | ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); |
| 967 | 966 | if (ret) { |
| 968 | 967 | DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret); |
| 968 | + clk_disable_unprepare(vc4_hdmi->hsm_clock); | |
| 969 | 969 | clk_disable_unprepare(vc4_hdmi->pixel_clock); |
| 970 | 970 | return; |
| 971 | 971 | } |
| @@ -985,11 +985,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, · 13 unmodified lines | ||
| 985 | 985 | static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, |
| 986 | 986 | struct drm_atomic_state *state) |
| 987 | 987 | { |
| 988 | − struct drm_connector_state *conn_state = | |
| 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; | |
| 988 | + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; | |
| 993 | 989 | struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); |
| 994 | 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 | 1008 | static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, |
| 1013 | 1009 | struct drm_atomic_state *state) |
| 1014 | 1010 | { |
| 1015 | − struct drm_connector_state *conn_state = | |
| 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; | |
| 1011 | + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; | |
| 1020 | 1012 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); |
| 1021 | 1013 | struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); |
| 1022 | 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 | 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; | |
| 1208 | − struct drm_crtc *crtc = connector->state->crtc; | |
| 1199 | + struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; | |
| 1200 | + struct drm_crtc *crtc = encoder->crtc; | |
| 1209 | 1201 | const struct drm_display_mode *mode = &crtc->state->adjusted_mode; |
| 1210 | 1202 | u32 n, cts; |
| 1211 | 1203 | u64 tmp; |
| @@ -1238,13 +1230,13 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai) · 26 unmodified lines | ||
| 1238 | 1230 | static int vc4_hdmi_audio_startup(struct device *dev, void *data) |
| 1239 | 1231 | { |
| 1240 | 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 | 1236 | * If the HDMI encoder hasn't probed, or the encoder is |
| 1245 | 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 | 1240 | VC4_HDMI_RAM_PACKET_ENABLE)) |
| 1249 | 1241 | return -ENODEV; |
| 1250 | 1242 | |
| @@ -2114,29 +2106,6 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) · 863 unmodified lines | ||
| 2114 | 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 | 2109 | static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) |
| 2141 | 2110 | { |
| 2142 | 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 | 2363 | struct platform_driver vc4_hdmi_driver = { |
| 2401 | 2364 | .probe = vc4_hdmi_dev_probe, |
| 2402 | 2365 | .remove = vc4_hdmi_dev_remove, |
| 2403 | 2366 | .driver = { |
| 2404 | 2367 | .name = "vc4_hdmi", |
| 2405 | 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 | 351 | static void b53_mdio_remove(struct mdio_device *mdiodev) |
| 352 | 352 | { |
| 353 | 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 | 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 | 389 | static struct mdio_driver b53_mdio_driver = { |
| 374 | 390 | .probe = b53_mdio_probe, |
| 375 | 391 | .remove = b53_mdio_remove, |
| 392 | + .shutdown = b53_mdio_shutdown, | |
| 376 | 393 | .mdiodrv.driver = { |
| 377 | 394 | .name = "bcm53xx", |
| 378 | 395 | .of_match_table = b53_of_match, |
| @@ -316,9 +316,21 @@ static int b53_mmap_remove(struct platform_device *pdev) · 315 unmodified lines | ||
| 316 | 316 | if (dev) |
| 317 | 317 | b53_switch_remove(dev); |
| 318 | 318 | |
| 319 | + platform_set_drvdata(pdev, NULL); | |
| 320 | + | |
| 319 | 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 | 334 | static const struct of_device_id b53_mmap_of_table[] = { |
| 323 | 335 | { .compatible = "brcm,bcm3384-switch" }, |
| 324 | 336 | { .compatible = "brcm,bcm6328-switch" }, |
| @@ -331,6 +343,7 @@ MODULE_DEVICE_TABLE(of, b53_mmap_of_table); · 6 unmodified lines | ||
| 331 | 343 | static struct platform_driver b53_mmap_driver = { |
| 332 | 344 | .probe = b53_mmap_probe, |
| 333 | 345 | .remove = b53_mmap_remove, |
| 346 | + .shutdown = b53_mmap_shutdown, | |
| 334 | 347 | .driver = { |
| 335 | 348 | .name = "b53-switch", |
| 336 | 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 | 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 | 235 | #define b53_build_op(type_op_size, val_type) \ |
| 231 | 236 | static inline int b53_##type_op_size(struct b53_device *dev, u8 page, \ |
| 232 | 237 | u8 reg, val_type val) \ |
| @@ -321,9 +321,21 @@ static int b53_spi_remove(struct spi_device *spi) · 320 unmodified lines | ||
| 321 | 321 | if (dev) |
| 322 | 322 | b53_switch_remove(dev); |
| 323 | 323 | |
| 324 | + spi_set_drvdata(spi, NULL); | |
| 325 | + | |
| 324 | 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 | 339 | static const struct of_device_id b53_spi_of_match[] = { |
| 328 | 340 | { .compatible = "brcm,bcm5325" }, |
| 329 | 341 | { .compatible = "brcm,bcm5365" }, |
| @@ -344,6 +356,7 @@ static struct spi_driver b53_spi_driver = { · 14 unmodified lines | ||
| 344 | 356 | }, |
| 345 | 357 | .probe = b53_spi_probe, |
| 346 | 358 | .remove = b53_spi_remove, |
| 359 | + .shutdown = b53_spi_shutdown, | |
| 347 | 360 | }; |
| 348 | 361 | |
| 349 | 362 | module_spi_driver(b53_spi_driver); |
| @@ -629,17 +629,34 @@ static int b53_srab_probe(struct platform_device *pdev) · 628 unmodified lines | ||
| 629 | 629 | static int b53_srab_remove(struct platform_device *pdev) |
| 630 | 630 | { |
| 631 | 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 | 637 | b53_switch_remove(dev); |
| 636 | 638 | |
| 639 | + platform_set_drvdata(pdev, NULL); | |
| 640 | + | |
| 637 | 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 | 656 | static struct platform_driver b53_srab_driver = { |
| 641 | 657 | .probe = b53_srab_probe, |
| 642 | 658 | .remove = b53_srab_remove, |
| 659 | + .shutdown = b53_srab_shutdown, | |
| 643 | 660 | .driver = { |
| 644 | 661 | .name = "b53-srab-switch", |
| 645 | 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 | 68 | struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); |
| 69 | 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 | 72 | if (dsa_is_cpu_port(ds, port)) |
| 73 | 73 | continue; |
| 74 | 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 | 1515 | struct bcm_sf2_priv *priv = platform_get_drvdata(pdev); |
| 1516 | 1516 | |
| 1517 | + if (!priv) | |
| 1518 | + return 0; | |
| 1519 | + | |
| 1517 | 1520 | priv->wol_ports_mask = 0; |
| 1518 | 1521 | /* Disable interrupts */ |
| 1519 | 1522 | bcm_sf2_intr_disable(priv); |
| @@ -1525,6 +1528,8 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev) · 5 unmodified lines | ||
| 1525 | 1528 | if (priv->type == BCM7278_DEVICE_ID) |
| 1526 | 1529 | reset_control_assert(priv->rcdev); |
| 1527 | 1530 | |
| 1531 | + platform_set_drvdata(pdev, NULL); | |
| 1532 | + | |
| 1528 | 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 | 1538 | struct bcm_sf2_priv *priv = platform_get_drvdata(pdev); |
| 1534 | 1539 | |
| 1540 | + if (!priv) | |
| 1541 | + return; | |
| 1542 | + | |
| 1535 | 1543 | /* For a kernel about to be kexec'd we want to keep the GPHY on for a |
| 1536 | 1544 | * successful MDIO bus scan to occur. If we did turn off the GPHY |
| 1537 | 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 | 1549 | if (priv->hw_params.num_gphy == 1) |
| 1542 | 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 | 1557 | #ifdef CONFIG_PM_SLEEP |
| @@ -340,10 +340,29 @@ static int dsa_loop_drv_probe(struct mdio_device *mdiodev) · 339 unmodified lines | ||
| 340 | 340 | static void dsa_loop_drv_remove(struct mdio_device *mdiodev) |
| 341 | 341 | { |
| 342 | 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 | 350 | dsa_unregister_switch(ds); |
| 346 | 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 | 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 | 372 | .probe = dsa_loop_drv_probe, |
| 354 | 373 | .remove = dsa_loop_drv_remove, |
| 374 | + .shutdown = dsa_loop_drv_shutdown, | |
| 355 | 375 | }; |
| 356 | 376 | |
| 357 | 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 | 1917 | struct hellcreek *hellcreek = platform_get_drvdata(pdev); |
| 1918 | 1918 | |
| 1919 | + if (!hellcreek) | |
| 1920 | + return 0; | |
| 1921 | + | |
| 1919 | 1922 | hellcreek_hwtstamp_free(hellcreek); |
| 1920 | 1923 | hellcreek_ptp_free(hellcreek); |
| 1921 | 1924 | dsa_unregister_switch(hellcreek->ds); |
| @@ -1924,6 +1927,18 @@ static int hellcreek_remove(struct platform_device *pdev) · 2 unmodified lines | ||
| 1924 | 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 | 1942 | static const struct hellcreek_platform_data de1soc_r1_pdata = { |
| 1928 | 1943 | .name = "r4c30", |
| 1929 | 1944 | .num_ports = 4, |
| @@ -1946,6 +1961,7 @@ MODULE_DEVICE_TABLE(of, hellcreek_of_match); · 16 unmodified lines | ||
| 1946 | 1961 | static struct platform_driver hellcreek_driver = { |
| 1947 | 1962 | .probe = hellcreek_probe, |
| 1948 | 1963 | .remove = hellcreek_remove, |
| 1964 | + .shutdown = hellcreek_shutdown, | |
| 1949 | 1965 | .driver = { |
| 1950 | 1966 | .name = "hellcreek", |
| 1951 | 1967 | .of_match_table = hellcreek_of_match, |
| @@ -1379,6 +1379,12 @@ int lan9303_remove(struct lan9303 *chip) · 1378 unmodified lines | ||
| 1379 | 1379 | } |
| 1380 | 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 | 1388 | MODULE_AUTHOR("Juergen Borleis <kernel@pengutronix.de>"); |
| 1383 | 1389 | MODULE_DESCRIPTION("Core driver for SMSC/Microchip LAN9303 three port ethernet switch"); |
| 1384 | 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 | 11 | int lan9303_probe(struct lan9303 *chip, struct device_node *np); |
| 12 | 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 | 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 | 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 | 113 | .probe = lan9303_i2c_probe, |
| 99 | 114 | .remove = lan9303_i2c_remove, |
| 115 | + .shutdown = lan9303_i2c_shutdown, | |
| 100 | 116 | .id_table = lan9303_i2c_id, |
| 101 | 117 | }; |
| 102 | 118 | module_i2c_driver(lan9303_i2c_driver); |
| @@ -138,6 +138,20 @@ static void lan9303_mdio_remove(struct mdio_device *mdiodev) · 137 unmodified lines | ||
| 138 | 138 | return; |
| 139 | 139 | |
| 140 | 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 | 170 | .probe = lan9303_mdio_probe, |
| 157 | 171 | .remove = lan9303_mdio_remove, |
| 172 | + .shutdown = lan9303_mdio_shutdown, | |
| 158 | 173 | }; |
| 159 | 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 | 2184 | struct gswip_priv *priv = platform_get_drvdata(pdev); |
| 2185 | 2185 | int i; |
| 2186 | 2186 | |
| 2187 | + if (!priv) | |
| 2188 | + return 0; | |
| 2189 | + | |
| 2187 | 2190 | /* disable the switch */ |
| 2188 | 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 | 2200 | for (i = 0; i < priv->num_gphy_fw; i++) |
| 2198 | 2201 | gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]); |
| 2199 | 2202 | |
| 2203 | + platform_set_drvdata(pdev, NULL); | |
| 2204 | + | |
| 2200 | 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 | 2220 | static const struct gswip_hw_info gswip_xrx200 = { |
| 2204 | 2221 | .max_ports = 7, |
| 2205 | 2222 | .cpu_port = 6, |
| @@ -2223,6 +2240,7 @@ MODULE_DEVICE_TABLE(of, gswip_of_match); · 17 unmodified lines | ||
| 2223 | 2240 | static struct platform_driver gswip_driver = { |
| 2224 | 2241 | .probe = gswip_probe, |
| 2225 | 2242 | .remove = gswip_remove, |
| 2243 | + .shutdown = gswip_shutdown, | |
| 2226 | 2244 | .driver = { |
| 2227 | 2245 | .name = "gswip", |
| 2228 | 2246 | .of_match_table = gswip_of_match, |
| @@ -94,6 +94,8 @@ static int ksz8795_spi_remove(struct spi_device *spi) · 93 unmodified lines | ||
| 94 | 94 | if (dev) |
| 95 | 95 | ksz_switch_remove(dev); |
| 96 | 96 | |
| 97 | + spi_set_drvdata(spi, NULL); | |
| 98 | + | |
| 97 | 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 | 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 | 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 | 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 | 192 | if (dev) |
| 193 | 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 | 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 | 215 | static struct mdio_driver ksz8863_driver = { |
| 204 | 216 | .probe = ksz8863_smi_probe, |
| 205 | 217 | .remove = ksz8863_smi_remove, |
| 218 | + .shutdown = ksz8863_smi_shutdown, | |
| 206 | 219 | .mdiodrv.driver = { |
| 207 | 220 | .name = "ksz8863-switch", |
| 208 | 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 | 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 | 64 | return 0; |
| 62 | 65 | } |
| @@ -65,8 +68,15 @@ static void ksz9477_i2c_shutdown(struct i2c_client *i2c) · 2 unmodified lines | ||
| 65 | 68 | { |
| 66 | 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 | 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 | 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 | 72 | if (dev) |
| 73 | 73 | ksz_switch_remove(dev); |
| 74 | 74 | |
| 75 | + spi_set_drvdata(spi, NULL); | |
| 76 | + | |
| 75 | 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 | 82 | struct ksz_device *dev = spi_get_drvdata(spi); |
| 81 | 83 | |
| 82 | − if (dev && dev->dev_ops->shutdown) | |
| 83 | − dev->dev_ops->shutdown(dev); | |
| 84 | + if (dev) | |
| 85 | + dsa_switch_shutdown(dev->ds); | |
| 86 | + | |
| 87 | + spi_set_drvdata(spi, NULL); | |
| 84 | 88 | } |
| 85 | 89 | |
| 86 | 90 | static const struct of_device_id ksz9477_dt_ids[] = { |
| @@ -3286,6 +3286,9 @@ mt7530_remove(struct mdio_device *mdiodev) · 3285 unmodified lines | ||
| 3286 | 3286 | struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); |
| 3287 | 3287 | int ret = 0; |
| 3288 | 3288 | |
| 3289 | + if (!priv) | |
| 3290 | + return; | |
| 3291 | + | |
| 3289 | 3292 | ret = regulator_disable(priv->core_pwr); |
| 3290 | 3293 | if (ret < 0) |
| 3291 | 3294 | dev_err(priv->dev, |
| @@ -3301,11 +3304,26 @@ mt7530_remove(struct mdio_device *mdiodev) · 9 unmodified lines | ||
| 3301 | 3304 | |
| 3302 | 3305 | dsa_unregister_switch(priv->ds); |
| 3303 | 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 | 3323 | static struct mdio_driver mt7530_mdio_driver = { |
| 3307 | 3324 | .probe = mt7530_probe, |
| 3308 | 3325 | .remove = mt7530_remove, |
| 3326 | + .shutdown = mt7530_shutdown, | |
| 3309 | 3327 | .mdiodrv.driver = { |
| 3310 | 3328 | .name = "mt7530", |
| 3311 | 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 | 291 | struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); |
| 292 | 292 | |
| 293 | + if (!ds) | |
| 294 | + return; | |
| 295 | + | |
| 293 | 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 | 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 | 320 | static struct mdio_driver mv88e6060_driver = { |
| 304 | 321 | .probe = mv88e6060_probe, |
| 305 | 322 | .remove = mv88e6060_remove, |
| 323 | + .shutdown = mv88e6060_shutdown, | |
| 306 | 324 | .mdiodrv.driver = { |
| 307 | 325 | .name = "mv88e6060", |
| 308 | 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 | 3072 | mv88e6xxx_teardown_devlink_params(ds); |
| 3073 | 3073 | dsa_devlink_resources_unregister(ds); |
| 3074 | − mv88e6xxx_teardown_devlink_regions(ds); | |
| 3074 | + mv88e6xxx_teardown_devlink_regions_global(ds); | |
| 3075 | 3075 | } |
| 3076 | 3076 | |
| 3077 | 3077 | static int mv88e6xxx_setup(struct dsa_switch *ds) |
| @@ -3215,7 +3215,7 @@ unlock: · 137 unmodified lines | ||
| 3215 | 3215 | if (err) |
| 3216 | 3216 | goto out_resources; |
| 3217 | 3217 | |
| 3218 | − err = mv88e6xxx_setup_devlink_regions(ds); | |
| 3218 | + err = mv88e6xxx_setup_devlink_regions_global(ds); | |
| 3219 | 3219 | if (err) |
| 3220 | 3220 | goto out_params; |
| 3221 | 3221 | |
| @@ -3229,6 +3229,16 @@ out_resources: · 7 unmodified lines | ||
| 3229 | 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 | 3242 | /* prod_id for switch families which do not have a PHY model number */ |
| 3233 | 3243 | static const u16 family_prod_id_table[] = { |
| 3234 | 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 | 6126 | .change_tag_protocol = mv88e6xxx_change_tag_protocol, |
| 6117 | 6127 | .setup = mv88e6xxx_setup, |
| 6118 | 6128 | .teardown = mv88e6xxx_teardown, |
| 6129 | + .port_setup = mv88e6xxx_port_setup, | |
| 6130 | + .port_teardown = mv88e6xxx_port_teardown, | |
| 6119 | 6131 | .phylink_validate = mv88e6xxx_validate, |
| 6120 | 6132 | .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state, |
| 6121 | 6133 | .phylink_mac_config = mv88e6xxx_mac_config, |
| @@ -6389,7 +6401,12 @@ out: · 267 unmodified lines | ||
| 6389 | 6401 | static void mv88e6xxx_remove(struct mdio_device *mdiodev) |
| 6390 | 6402 | { |
| 6391 | 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 | 6411 | if (chip->info->ptp_support) { |
| 6395 | 6412 | mv88e6xxx_hwtstamp_free(chip); |
| @@ -6410,6 +6427,20 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev) · 14 unmodified lines | ||
| 6410 | 6427 | mv88e6xxx_g1_irq_free(chip); |
| 6411 | 6428 | else |
| 6412 | 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 | 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 | 6464 | static struct mdio_driver mv88e6xxx_driver = { |
| 6434 | 6465 | .probe = mv88e6xxx_probe, |
| 6435 | 6466 | .remove = mv88e6xxx_remove, |
| 6467 | + .shutdown = mv88e6xxx_shutdown, | |
| 6436 | 6468 | .mdiodrv.driver = { |
| 6437 | 6469 | .name = "mv88e6085", |
| 6438 | 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 | |
| 651 | −mv88e6xxx_teardown_devlink_regions_global(struct mv88e6xxx_chip *chip) | |
| 650 | +void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds) | |
| 652 | 651 | { |
| 652 | + struct mv88e6xxx_chip *chip = ds->priv; | |
| 653 | 653 | int i; |
| 654 | 654 | |
| 655 | 655 | for (i = 0; i < ARRAY_SIZE(mv88e6xxx_regions); i++) |
| 656 | 656 | dsa_devlink_region_destroy(chip->regions[i]); |
| 657 | 657 | } |
| 658 | 658 | |
| 659 | −static void | |
| 660 | −mv88e6xxx_teardown_devlink_regions_port(struct mv88e6xxx_chip *chip, | |
| 661 | − int port) | |
| 659 | +void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port) | |
| 662 | 660 | { |
| 661 | + struct mv88e6xxx_chip *chip = ds->priv; | |
| 662 | + | |
| 663 | 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, | |
| 667 | − struct mv88e6xxx_chip *chip, | |
| 668 | − int port) | |
| 666 | +int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, int port) | |
| 669 | 667 | { |
| 668 | + struct mv88e6xxx_chip *chip = ds->priv; | |
| 670 | 669 | struct devlink_region *region; |
| 671 | 670 | |
| 672 | 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 | 680 | return 0; |
| 682 | 681 | } |
| 683 | 682 | |
| 684 | −static void | |
| 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) | |
| 683 | +int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds) | |
| 716 | 684 | { |
| 717 | 685 | bool (*cond)(struct mv88e6xxx_chip *chip); |
| 686 | + struct mv88e6xxx_chip *chip = ds->priv; | |
| 718 | 687 | struct devlink_region_ops *ops; |
| 719 | 688 | struct devlink_region *region; |
| 720 | 689 | u64 size; |
| @@ -753,30 +722,6 @@ out: · 32 unmodified lines | ||
| 753 | 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 | 725 | int mv88e6xxx_devlink_info_get(struct dsa_switch *ds, |
| 781 | 726 | struct devlink_info_req *req, |
| 782 | 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 | 12 | struct devlink_param_gset_ctx *ctx); |
| 13 | 13 | int mv88e6xxx_devlink_param_set(struct dsa_switch *ds, u32 id, |
| 14 | 14 | struct devlink_param_gset_ctx *ctx); |
| 15 | −int mv88e6xxx_setup_devlink_regions(struct dsa_switch *ds); | |
| 16 | −void mv88e6xxx_teardown_devlink_regions(struct dsa_switch *ds); | |
| 15 | +int mv88e6xxx_setup_devlink_regions_global(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 | 20 | int mv88e6xxx_devlink_info_get(struct dsa_switch *ds, |
| 19 | 21 | struct devlink_info_req *req, |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | −/* Copyright 2019-2021 NXP Semiconductors | |
| 2 | +/* Copyright 2019-2021 NXP | |
| 3 | 3 | * |
| 4 | 4 | * This is an umbrella module for all network switches that are |
| 5 | 5 | * register-compatible with Ocelot and that perform I/O to their host CPU |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | −/* Copyright 2019 NXP Semiconductors | |
| 2 | +/* Copyright 2019 NXP | |
| 3 | 3 | */ |
| 4 | 4 | #ifndef _MSCC_FELIX_H |
| 5 | 5 | #define _MSCC_FELIX_H |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: (GPL-2.0 OR MIT) |
| 2 | 2 | /* Copyright 2017 Microsemi Corporation |
| 3 | − * Copyright 2018-2019 NXP Semiconductors | |
| 3 | + * Copyright 2018-2019 NXP | |
| 4 | 4 | */ |
| 5 | 5 | #include <linux/fsl/enetc_mdio.h> |
| 6 | 6 | #include <soc/mscc/ocelot_qsys.h> |
| @@ -1472,9 +1472,10 @@ err_pci_enable: · 1465 unmodified lines | ||
| 1472 | 1472 | |
| 1473 | 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 | 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 | 1483 | kfree(felix); |
| 1483 | 1484 | |
| 1484 | 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 | 1502 | static struct pci_device_id felix_ids[] = { |
| @@ -1498,6 +1513,7 @@ static struct pci_driver felix_vsc9959_pci_driver = { · 10 unmodified lines | ||
| 1498 | 1513 | .id_table = felix_ids, |
| 1499 | 1514 | .probe = felix_pci_probe, |
| 1500 | 1515 | .remove = felix_pci_remove, |
| 1516 | + .shutdown = felix_pci_shutdown, | |
| 1501 | 1517 | }; |
| 1502 | 1518 | module_pci_driver(felix_vsc9959_pci_driver); |
| 1503 | 1519 | |
| @@ -1245,18 +1245,33 @@ err_alloc_felix: · 1244 unmodified lines | ||
| 1245 | 1245 | |
| 1246 | 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 | 1253 | dsa_unregister_switch(felix->ds); |
| 1253 | 1254 | |
| 1254 | 1255 | kfree(felix->ds); |
| 1255 | 1256 | kfree(felix); |
| 1256 | 1257 | |
| 1258 | + platform_set_drvdata(pdev, NULL); | |
| 1259 | + | |
| 1257 | 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 | 1275 | static const struct of_device_id seville_of_match[] = { |
| 1261 | 1276 | { .compatible = "mscc,vsc9953-switch" }, |
| 1262 | 1277 | { }, |
| @@ -1266,6 +1281,7 @@ MODULE_DEVICE_TABLE(of, seville_of_match); · 3 unmodified lines | ||
| 1266 | 1281 | static struct platform_driver seville_vsc9953_driver = { |
| 1267 | 1282 | .probe = seville_probe, |
| 1268 | 1283 | .remove = seville_remove, |
| 1284 | + .shutdown = seville_shutdown, | |
| 1269 | 1285 | .driver = { |
| 1270 | 1286 | .name = "mscc_seville", |
| 1271 | 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 | 1083 | struct ar9331_sw_priv *priv = dev_get_drvdata(&mdiodev->dev); |
| 1084 | 1084 | unsigned int i; |
| 1085 | 1085 | |
| 1086 | + if (!priv) | |
| 1087 | + return; | |
| 1088 | + | |
| 1086 | 1089 | for (i = 0; i < ARRAY_SIZE(priv->port); i++) { |
| 1087 | 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 | 1097 | dsa_unregister_switch(&priv->ds); |
| 1095 | 1098 | |
| 1096 | 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 | 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 | 1121 | static struct mdio_driver ar9331_sw_mdio_driver = { |
| 1105 | 1122 | .probe = ar9331_sw_probe, |
| 1106 | 1123 | .remove = ar9331_sw_remove, |
| 1124 | + .shutdown = ar9331_sw_shutdown, | |
| 1107 | 1125 | .mdiodrv.driver = { |
| 1108 | 1126 | .name = AR9331_SW_NAME, |
| 1109 | 1127 | .of_match_table = ar9331_sw_of_match, |
| @@ -1880,10 +1880,27 @@ qca8k_sw_remove(struct mdio_device *mdiodev) · 1879 unmodified lines | ||
| 1880 | 1880 | struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev); |
| 1881 | 1881 | int i; |
| 1882 | 1882 | |
| 1883 | + if (!priv) | |
| 1884 | + return; | |
| 1885 | + | |
| 1883 | 1886 | for (i = 0; i < QCA8K_NUM_PORTS; i++) |
| 1884 | 1887 | qca8k_port_set_status(priv, i, 0); |
| 1885 | 1888 | |
| 1886 | 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 | 1906 | #ifdef CONFIG_PM_SLEEP |
| @@ -1940,6 +1957,7 @@ static const struct of_device_id qca8k_of_match[] = { · 50 unmodified lines | ||
| 1940 | 1957 | static struct mdio_driver qca8kmdio_driver = { |
| 1941 | 1958 | .probe = qca8k_sw_probe, |
| 1942 | 1959 | .remove = qca8k_sw_remove, |
| 1960 | + .shutdown = qca8k_sw_shutdown, | |
| 1943 | 1961 | .mdiodrv.driver = { |
| 1944 | 1962 | .name = "qca8k", |
| 1945 | 1963 | .of_match_table = qca8k_of_match, |
| @@ -368,7 +368,7 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi) · 367 unmodified lines | ||
| 368 | 368 | smi->slave_mii_bus->parent = smi->dev; |
| 369 | 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 | 372 | if (ret) { |
| 373 | 373 | dev_err(smi->dev, "unable to register MDIO bus %s\n", |
| 374 | 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 | 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 | 472 | dsa_unregister_switch(smi->ds); |
| 470 | 473 | if (smi->slave_mii_bus) |
| 471 | 474 | of_node_put(smi->slave_mii_bus->dev.of_node); |
| 472 | 475 | gpiod_set_value(smi->reset, 1); |
| 473 | 476 | |
| 477 | + platform_set_drvdata(pdev, NULL); | |
| 478 | + | |
| 474 | 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 | 494 | static const struct of_device_id realtek_smi_of_match[] = { |
| 478 | 495 | { |
| 479 | 496 | .compatible = "realtek,rtl8366rb", |
| @@ -495,6 +512,7 @@ static struct platform_driver realtek_smi_driver = { · 15 unmodified lines | ||
| 495 | 512 | }, |
| 496 | 513 | .probe = realtek_smi_probe, |
| 497 | 514 | .remove = realtek_smi_remove, |
| 515 | + .shutdown = realtek_smi_shutdown, | |
| 498 | 516 | }; |
| 499 | 517 | module_platform_driver(realtek_smi_driver); |
| 500 | 518 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: BSD-3-Clause |
| 2 | −/* Copyright (c) 2016-2018, NXP Semiconductors | |
| 2 | +/* Copyright 2016-2018 NXP | |
| 3 | 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 4 | 4 | */ |
| 5 | 5 | #include <linux/packing.h> |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | /* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 3 | − * Copyright 2020 NXP Semiconductors | |
| 3 | + * Copyright 2020 NXP | |
| 4 | 4 | */ |
| 5 | 5 | #include "sja1105.h" |
| 6 | 6 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | −/* Copyright 2020, NXP Semiconductors | |
| 2 | +/* Copyright 2020 NXP | |
| 3 | 3 | */ |
| 4 | 4 | #include "sja1105.h" |
| 5 | 5 | #include "sja1105_vl.h" |
| @@ -3340,13 +3340,29 @@ static int sja1105_probe(struct spi_device *spi) · 3339 unmodified lines | ||
| 3340 | 3340 | static int sja1105_remove(struct spi_device *spi) |
| 3341 | 3341 | { |
| 3342 | 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 | 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 | 3366 | static const struct of_device_id sja1105_dt_ids[] = { |
| 3351 | 3367 | { .compatible = "nxp,sja1105e", .data = &sja1105e_info }, |
| 3352 | 3368 | { .compatible = "nxp,sja1105t", .data = &sja1105t_info }, |
| @@ -3370,6 +3386,7 @@ static struct spi_driver sja1105_driver = { · 17 unmodified lines | ||
| 3370 | 3386 | }, |
| 3371 | 3387 | .probe = sja1105_probe, |
| 3372 | 3388 | .remove = sja1105_remove, |
| 3389 | + .shutdown = sja1105_shutdown, | |
| 3373 | 3390 | }; |
| 3374 | 3391 | |
| 3375 | 3392 | module_spi_driver(sja1105_driver); |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | −/* Copyright 2021, NXP Semiconductors | |
| 2 | +/* Copyright 2021 NXP | |
| 3 | 3 | */ |
| 4 | 4 | #include <linux/pcs/pcs-xpcs.h> |
| 5 | 5 | #include <linux/of_mdio.h> |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: BSD-3-Clause |
| 2 | −/* Copyright (c) 2016-2018, NXP Semiconductors | |
| 2 | +/* Copyright 2016-2018 NXP | |
| 3 | 3 | * Copyright (c) 2018, Sensor-Technik Wiedemann GmbH |
| 4 | 4 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 5 | 5 | */ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: BSD-3-Clause |
| 2 | −/* Copyright (c) 2016-2018, NXP Semiconductors | |
| 2 | +/* Copyright 2016-2018 NXP | |
| 3 | 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 4 | 4 | */ |
| 5 | 5 | #include "sja1105_static_config.h" |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: BSD-3-Clause */ |
| 2 | −/* Copyright (c) 2016-2018, NXP Semiconductors | |
| 2 | +/* Copyright 2016-2018 NXP | |
| 3 | 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 4 | 4 | */ |
| 5 | 5 | #ifndef _SJA1105_STATIC_CONFIG_H |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | −/* Copyright 2020, NXP Semiconductors | |
| 2 | +/* Copyright 2020 NXP | |
| 3 | 3 | */ |
| 4 | 4 | #include <net/tc_act/tc_gate.h> |
| 5 | 5 | #include <linux/dsa/8021q.h> |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | −/* Copyright 2020, NXP Semiconductors | |
| 2 | +/* Copyright 2020 NXP | |
| 3 | 3 | */ |
| 4 | 4 | #ifndef _SJA1105_VL_H |
| 5 | 5 | #define _SJA1105_VL_H |
| @@ -1225,6 +1225,12 @@ int vsc73xx_remove(struct vsc73xx *vsc) · 1224 unmodified lines | ||
| 1225 | 1225 | } |
| 1226 | 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 | 1234 | MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); |
| 1229 | 1235 | MODULE_DESCRIPTION("Vitesse VSC7385/7388/7395/7398 driver"); |
| 1230 | 1236 | MODULE_LICENSE("GPL v2"); |
| @@ -116,7 +116,26 @@ static int vsc73xx_platform_remove(struct platform_device *pdev) · 115 unmodified lines | ||
| 116 | 116 | { |
| 117 | 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 | 141 | static const struct vsc73xx_ops vsc73xx_platform_ops = { |
| @@ -144,6 +163,7 @@ MODULE_DEVICE_TABLE(of, vsc73xx_of_match); · 21 unmodified lines | ||
| 144 | 163 | static struct platform_driver vsc73xx_platform_driver = { |
| 145 | 164 | .probe = vsc73xx_platform_probe, |
| 146 | 165 | .remove = vsc73xx_platform_remove, |
| 166 | + .shutdown = vsc73xx_platform_shutdown, | |
| 147 | 167 | .driver = { |
| 148 | 168 | .name = "vsc73xx-platform", |
| 149 | 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 | 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 | 188 | static const struct vsc73xx_ops vsc73xx_spi_ops = { |
| @@ -191,6 +210,7 @@ MODULE_DEVICE_TABLE(of, vsc73xx_of_match); · 21 unmodified lines | ||
| 191 | 210 | static struct spi_driver vsc73xx_spi_driver = { |
| 192 | 211 | .probe = vsc73xx_spi_probe, |
| 193 | 212 | .remove = vsc73xx_spi_remove, |
| 213 | + .shutdown = vsc73xx_spi_shutdown, | |
| 194 | 214 | .driver = { |
| 195 | 215 | .name = "vsc73xx-spi", |
| 196 | 216 | .of_match_table = vsc73xx_of_match, |
| @@ -27,3 +27,4 @@ struct vsc73xx_ops { · 26 unmodified lines | ||
| 27 | 27 | int vsc73xx_is_addr_valid(u8 block, u8 subblock); |
| 28 | 28 | int vsc73xx_probe(struct vsc73xx *vsc); |
| 29 | 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 | 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 | 831 | MODULE_AUTHOR("George McCollister <george.mccollister@gmail.com>"); |
| 826 | 832 | MODULE_DESCRIPTION("Arrow SpeedChips XRS700x DSA driver"); |
| 827 | 833 | MODULE_LICENSE("GPL v2"); |
| @@ -40,3 +40,4 @@ struct xrs700x { · 39 unmodified lines | ||
| 40 | 40 | struct xrs700x *xrs700x_switch_alloc(struct device *base, void *devpriv); |
| 41 | 41 | int xrs700x_switch_register(struct xrs700x *priv); |
| 42 | 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 | 110 | struct xrs700x *priv = i2c_get_clientdata(i2c); |
| 111 | 111 | |
| 112 | + if (!priv) | |
| 113 | + return 0; | |
| 114 | + | |
| 112 | 115 | xrs700x_switch_remove(priv); |
| 113 | 116 | |
| 117 | + i2c_set_clientdata(i2c, NULL); | |
| 118 | + | |
| 114 | 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 | 134 | static const struct i2c_device_id xrs700x_i2c_id[] = { |
| 118 | 135 | { "xrs700x-switch", 0 }, |
| 119 | 136 | {}, |
| @@ -137,6 +154,7 @@ static struct i2c_driver xrs700x_i2c_driver = { · 17 unmodified lines | ||
| 137 | 154 | }, |
| 138 | 155 | .probe = xrs700x_i2c_probe, |
| 139 | 156 | .remove = xrs700x_i2c_remove, |
| 157 | + .shutdown = xrs700x_i2c_shutdown, | |
| 140 | 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 | 137 | struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev); |
| 138 | 138 | |
| 139 | + if (!priv) | |
| 140 | + return; | |
| 141 | + | |
| 139 | 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 | 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 | 173 | .probe = xrs700x_mdio_probe, |
| 157 | 174 | .remove = xrs700x_mdio_remove, |
| 175 | + .shutdown = xrs700x_mdio_shutdown, | |
| 158 | 176 | }; |
| 159 | 177 | |
| 160 | 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 | 413 | if (deep) { |
| 414 | 414 | /* Reinitialize Nic/Vecs objects */ |
| 415 | 415 | aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol); |
| 416 | + } | |
| 416 | 417 | |
| 418 | + if (netif_running(nic->ndev)) { | |
| 417 | 419 | ret = aq_nic_init(nic); |
| 418 | 420 | if (ret) |
| 419 | 421 | goto err_exit; |
| 420 | − } | |
| 421 | 422 | |
| 422 | − if (netif_running(nic->ndev)) { | |
| 423 | 423 | ret = aq_nic_start(nic); |
| 424 | 424 | if (ret) |
| 425 | 425 | goto err_exit; |
| @@ -129,6 +129,8 @@ static int bgmac_probe(struct bcma_device *core) · 128 unmodified lines | ||
| 129 | 129 | bcma_set_drvdata(core, bgmac); |
| 130 | 130 | |
| 131 | 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 | 135 | /* If no MAC address assigned via device tree, check SPROM */ |
| 134 | 136 | if (err) { |
| @@ -391,7 +391,7 @@ static bool bnxt_txr_netif_try_stop_queue(struct bnxt *bp, · 390 unmodified lines | ||
| 391 | 391 | * netif_tx_queue_stopped(). |
| 392 | 392 | */ |
| 393 | 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 | 395 | netif_tx_wake_queue(txq); |
| 396 | 396 | return false; |
| 397 | 397 | } |
| @@ -764,7 +764,7 @@ next_tx_int: · 366 unmodified lines | ||
| 764 | 764 | smp_mb(); |
| 765 | 765 | |
| 766 | 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 | 768 | READ_ONCE(txr->dev_state) != BNXT_DEV_STATE_CLOSING) |
| 769 | 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 | 2416 | if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) { |
| 2417 | 2417 | tx_pkts++; |
| 2418 | 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 | 2420 | rx_pkts = budget; |
| 2421 | 2421 | raw_cons = NEXT_RAW_CMP(raw_cons); |
| 2422 | 2422 | if (budget) |
| @@ -3640,7 +3640,7 @@ static int bnxt_init_tx_rings(struct bnxt *bp) · 1217 unmodified lines | ||
| 3640 | 3640 | u16 i; |
| 3641 | 3641 | |
| 3642 | 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 | 3645 | for (i = 0; i < bp->tx_nr_rings; i++) { |
| 3646 | 3646 | struct bnxt_tx_ring_info *txr = &bp->tx_ring[i]; |
| @@ -629,6 +629,11 @@ struct nqe_cn { · 628 unmodified lines | ||
| 629 | 629 | #define BNXT_MAX_RX_JUM_DESC_CNT (RX_DESC_CNT * MAX_RX_AGG_PAGES - 1) |
| 630 | 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 | 637 | #define RX_RING(x) (((x) & ~(RX_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4)) |
| 633 | 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 | 799 | if ((ering->rx_pending > BNXT_MAX_RX_DESC_CNT) || |
| 800 | 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 | 802 | return -EINVAL; |
| 803 | 803 | |
| 804 | 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 | 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 | 424 | v->comp_cnt++; |
| 425 | 425 | |
| @@ -1879,7 +1879,6 @@ static void enetc_clear_bdrs(struct enetc_ndev_priv *priv) · 1453 unmodified lines | ||
| 1879 | 1879 | static int enetc_setup_irqs(struct enetc_ndev_priv *priv) |
| 1880 | 1880 | { |
| 1881 | 1881 | struct pci_dev *pdev = priv->si->pdev; |
| 1882 | − cpumask_t cpu_mask; | |
| 1883 | 1882 | int i, j, err; |
| 1884 | 1883 | |
| 1885 | 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 | 1908 | enetc_wr(hw, ENETC_SIMSITRV(idx), entry); |
| 1910 | 1909 | } |
| 1911 | − cpumask_clear(&cpu_mask); | |
| 1912 | − cpumask_set_cpu(i % num_online_cpus(), &cpu_mask); | |
| 1913 | − irq_set_affinity_hint(irq, &cpu_mask); | |
| 1910 | + irq_set_affinity_hint(irq, get_cpu_mask(i % num_online_cpus())); | |
| 1914 | 1911 | } |
| 1915 | 1912 | |
| 1916 | 1913 | return 0; |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
| 2 | −/* Copyright 2021 NXP Semiconductors | |
| 2 | +/* Copyright 2021 NXP | |
| 3 | 3 | * |
| 4 | 4 | * The Integrated Endpoint Register Block (IERB) is configured by pre-boot |
| 5 | 5 | * software and is supposed to be to ENETC what a NVRAM is to a 'real' PCIe |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ |
| 2 | −/* Copyright 2021 NXP Semiconductors */ | |
| 2 | +/* Copyright 2021 NXP */ | |
| 3 | 3 | |
| 4 | 4 | #include <linux/pci.h> |
| 5 | 5 | #include <linux/platform_device.h> |
| @@ -4176,5 +4176,4 @@ static struct platform_driver fec_driver = { · 4175 unmodified lines | ||
| 4176 | 4176 | |
| 4177 | 4177 | module_platform_driver(fec_driver); |
| 4178 | 4178 | |
| 4179 | −MODULE_ALIAS("platform:"DRIVER_NAME); | |
| 4180 | 4179 | MODULE_LICENSE("GPL"); |
| @@ -2445,12 +2445,12 @@ static void hclge_handle_over_8bd_err(struct hclge_dev *hdev, · 2444 unmodified lines | ||
| 2445 | 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 | 2449 | vf_id, q_id); |
| 2450 | 2450 | |
| 2451 | 2451 | if (vf_id) { |
| 2452 | 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 | 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 | 2464 | ret = hclge_inform_reset_assert_to_vf(&hdev->vport[vf_id]); |
| 2465 | 2465 | if (ret) |
| 2466 | − dev_err(dev, "inform reset to vf(%u) failed %d!\n", | |
| 2467 | − hdev->vport->vport_id, ret); | |
| 2466 | + dev_err(dev, "inform reset to vport(%u) failed %d!\n", | |
| 2467 | + vf_id, ret); | |
| 2468 | 2468 | } else { |
| 2469 | 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 | 3667 | if (ret) { |
| 3668 | 3668 | dev_err(&hdev->pdev->dev, |
| 3669 | 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 | 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 | 3683 | if (ret) |
| 3683 | 3684 | dev_warn(&hdev->pdev->dev, |
| 3684 | 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 | 3690 | return 0; |
| @@ -4747,6 +4749,24 @@ static int hclge_get_rss(struct hnae3_handle *handle, u32 *indir, · 1058 unmodified lines | ||
| 4747 | 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 | 4770 | static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir, |
| 4751 | 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 | 4776 | u8 hash_algo; |
| 4757 | 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 | 4785 | /* Set the RSS Hash Key if specififed by the user */ |
| 4760 | 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 | 4787 | ret = hclge_set_rss_algo_key(hdev, hash_algo, key); |
| 4776 | 4788 | if (ret) |
| 4777 | 4789 | return ret; |
| 4778 | 4790 | |
| 4779 | 4791 | /* Update the shadow RSS key with user specified qids */ |
| 4780 | 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 | 4801 | /* Update the shadow RSS table with user specified qids */ |
| 4785 | 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 | 6650 | u8 vf = ethtool_get_flow_spec_ring_vf(ring_cookie); |
| 6634 | 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 | 6656 | if (vf > hdev->num_req_vfs) { |
| 6637 | 6657 | dev_err(&hdev->pdev->dev, |
| 6638 | − "Error: vf id (%u) > max vf num (%u)\n", | |
| 6639 | − vf, hdev->num_req_vfs); | |
| 6658 | + "Error: vf id (%u) should be less than %u\n", | |
| 6659 | + vf - 1, hdev->num_req_vfs); | |
| 6640 | 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 | 9845 | if (is_kill && !vlan_id) |
| 9826 | 9846 | return 0; |
| 9827 | 9847 | |
| 9848 | + if (vlan_id >= VLAN_N_VID) | |
| 9849 | + return -EINVAL; | |
| 9850 | + | |
| 9828 | 9851 | ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id); |
| 9829 | 9852 | if (ret) { |
| 9830 | 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 | 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 | 10760 | struct hclge_reset_tqp_queue_cmd *req; |
| 10737 | 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 | 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 | 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 | 10794 | struct hclge_vport *vport = hclge_get_vport(handle); |
| 10769 | 10795 | struct hclge_dev *hdev = vport->back; |
| 10770 | 10796 | u16 reset_try_times = 0; |
| 10771 | − int reset_status; | |
| 10797 | + u8 reset_status; | |
| 10772 | 10798 | u16 queue_gid; |
| 10773 | 10799 | int ret; |
| 10774 | 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 | 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 | 10818 | if (reset_status) |
| 10789 | 10819 | break; |
| 10790 | 10820 | |
| @@ -11477,11 +11507,11 @@ static void hclge_clear_resetting_state(struct hclge_dev *hdev) · 686 unmodified lines | ||
| 11477 | 11507 | struct hclge_vport *vport = &hdev->vport[i]; |
| 11478 | 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 | 11511 | ret = hclge_set_vf_rst(hdev, vport->vport_id, false); |
| 11482 | 11512 | if (ret) |
| 11483 | 11513 | dev_warn(&hdev->pdev->dev, |
| 11484 | − "clear vf(%u) rst failed %d!\n", | |
| 11514 | + "clear vport(%u) rst failed %d!\n", | |
| 11485 | 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 | 566 | struct hclge_dev *hdev = vport->back; |
| 567 | 567 | |
| 568 | 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 | 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 | 590 | struct hclge_mbx_vf_to_pf_cmd *mbx_req, |
| 591 | 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 | 595 | u16 queue_id, qid_in_pf; |
| 594 | 596 | |
| 595 | 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 | 604 | qid_in_pf = hclge_covert_handle_qid_global(&vport->nic, queue_id); |
| 597 | 605 | memcpy(resp_msg->data, &qid_in_pf, sizeof(qid_in_pf)); |
| 598 | 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 | 581 | ret = hclge_cmd_send(&hdev->hw, &desc, 1); |
| 582 | 582 | if (ret) { |
| 583 | 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 | 585 | vport->vport_id, shap_cfg_cmd->qs_id, |
| 586 | 586 | max_tx_rate, ret); |
| 587 | 587 | return ret; |
| @@ -816,40 +816,56 @@ static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key, · 815 unmodified lines | ||
| 816 | 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 | 837 | static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir, |
| 820 | 838 | const u8 *key, const u8 hfunc) |
| 821 | 839 | { |
| 822 | 840 | struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); |
| 823 | 841 | struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; |
| 842 | + u8 hash_algo; | |
| 824 | 843 | int ret, i; |
| 825 | 844 | |
| 826 | 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 | 850 | /* Set the RSS Hash Key if specififed by the user */ |
| 828 | 851 | if (key) { |
| 829 | − switch (hfunc) { | |
| 830 | − case ETH_RSS_HASH_TOP: | |
| 831 | − rss_cfg->hash_algo = | |
| 832 | − HCLGEVF_RSS_HASH_ALGO_TOEPLITZ; | |
| 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) | |
| 852 | + ret = hclgevf_set_rss_algo_key(hdev, hash_algo, key); | |
| 853 | + if (ret) { | |
| 854 | + dev_err(&hdev->pdev->dev, | |
| 855 | + "invalid hfunc type %u\n", hfunc); | |
| 847 | 856 | return ret; |
| 857 | + } | |
| 848 | 858 | |
| 849 | 859 | /* Update the shadow RSS key with user specified qids */ |
| 850 | 860 | memcpy(rss_cfg->rss_hash_key, key, |
| 851 | 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 | 871 | /* update the shadow RSS table with user specified qids */ |
| @@ -335,6 +335,7 @@ config IGC · 334 unmodified lines | ||
| 335 | 335 | tristate "Intel(R) Ethernet Controller I225-LM/I225-V support" |
| 336 | 336 | default n |
| 337 | 337 | depends on PCI |
| 338 | + depends on PTP_1588_CLOCK_OPTIONAL | |
| 338 | 339 | help |
| 339 | 340 | This driver supports Intel(R) Ethernet Controller I225-LM/I225-V |
| 340 | 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 | 186 | int hash; |
| 187 | 187 | int i; |
| 188 | 188 | |
| 189 | + if (rhashtable_lookup(ð->flow_table, &f->cookie, mtk_flow_ht_params)) | |
| 190 | + return -EEXIST; | |
| 191 | + | |
| 189 | 192 | if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) { |
| 190 | 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 | 372 | int nhoff = skb_network_offset(skb); |
| 373 | 373 | int ret = 0; |
| 374 | 374 | |
| 375 | + if (skb->encapsulation) | |
| 376 | + return -EPROTONOSUPPORT; | |
| 377 | + | |
| 375 | 378 | if (skb->protocol != htons(ETH_P_IP)) |
| 376 | 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 | 1272 | if (!netif_carrier_ok(dev)) { |
| 1270 | 1273 | if (!mlx4_en_QUERY_PORT(mdev, priv->port)) { |
| 1271 | 1274 | if (priv->port_state.link_state) { |
| 1272 | − priv->last_link_state = MLX4_DEV_EVENT_PORT_UP; | |
| 1273 | 1275 | netif_carrier_on(dev); |
| 1274 | 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 | 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 | 1586 | struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, |
| 1563 | 1587 | linkstate_task); |
| 1564 | 1588 | struct mlx4_en_dev *mdev = priv->mdev; |
| 1565 | − int linkstate = priv->link_state; | |
| 1566 | 1589 | |
| 1567 | 1590 | mutex_lock(&mdev->state_lock); |
| 1568 | − /* If observable port state changed set carrier state and | |
| 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; | |
| 1591 | + mlx4_en_linkstate(priv); | |
| 1580 | 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 | 2091 | mlx4_en_clear_stats(dev); |
| 2080 | 2092 | |
| 2081 | 2093 | err = mlx4_en_start_port(dev); |
| 2082 | − if (err) | |
| 2094 | + if (err) { | |
| 2083 | 2095 | en_err(priv, "Failed starting port:%d\n", priv->port); |
| 2084 | − | |
| 2096 | + goto out; | |
| 2097 | + } | |
| 2098 | + mlx4_en_linkstate(priv); | |
| 2085 | 2099 | out: |
| 2086 | 2100 | mutex_unlock(&mdev->state_lock); |
| 2087 | 2101 | return err; |
| @@ -3168,7 +3182,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, · 1080 unmodified lines | ||
| 3168 | 3182 | spin_lock_init(&priv->stats_lock); |
| 3169 | 3183 | INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode); |
| 3170 | 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 | 3186 | INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); |
| 3173 | 3187 | INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task); |
| 3174 | 3188 | #ifdef CONFIG_RFS_ACCEL |
| @@ -552,7 +552,6 @@ struct mlx4_en_priv { · 551 unmodified lines | ||
| 552 | 552 | |
| 553 | 553 | struct mlx4_hwq_resources res; |
| 554 | 554 | int link_state; |
| 555 | − int last_link_state; | |
| 556 | 555 | bool port_up; |
| 557 | 556 | int port; |
| 558 | 557 | int registered; |
| @@ -563,16 +563,6 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port, · 562 unmodified lines | ||
| 563 | 563 | ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA | |
| 564 | 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 | 566 | /* Core: Enable port for frame transfer */ |
| 577 | 567 | ocelot_fields_write(ocelot, port, |
| 578 | 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 | 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 | 1297 | struct net_device *bridge) |
| 1308 | 1298 | { |
| 1299 | + struct ocelot_port *ocelot_port = ocelot->ports[src_port]; | |
| 1309 | 1300 | u32 mask = 0; |
| 1310 | 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 | 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 | 1310 | if (!ocelot_port) |
| 1316 | 1311 | continue; |
| @@ -1376,7 +1371,7 @@ void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot) · 59 unmodified lines | ||
| 1376 | 1371 | struct net_device *bridge = ocelot_port->bridge; |
| 1377 | 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 | 1375 | mask |= cpu_fwd_mask; |
| 1381 | 1376 | mask &= ~BIT(port); |
| 1382 | 1377 | if (bond) { |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: (GPL-2.0 OR MIT) |
| 2 | −/* Copyright 2020-2021 NXP Semiconductors | |
| 2 | +/* Copyright 2020-2021 NXP | |
| 3 | 3 | */ |
| 4 | 4 | #include <net/devlink.h> |
| 5 | 5 | #include "ocelot.h" |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | /* Microsemi Ocelot Switch driver |
| 3 | 3 | * |
| 4 | 4 | * Copyright (c) 2017, 2019 Microsemi Corporation |
| 5 | − * Copyright 2020-2021 NXP Semiconductors | |
| 5 | + * Copyright 2020-2021 NXP | |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | #include <linux/if_bridge.h> |
| @@ -5,7 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | * mscc_ocelot_switch_lib. |
| 6 | 6 | * |
| 7 | 7 | * Copyright (c) 2017, 2019 Microsemi Corporation |
| 8 | − * Copyright 2020-2021 NXP Semiconductors | |
| 8 | + * Copyright 2020-2021 NXP | |
| 9 | 9 | */ |
| 10 | 10 | |
| 11 | 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 | 1297 | prev_weight = weight; |
| 1298 | 1298 | |
| 1299 | 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 | 1308 | msleep(QED_IWARP_MAX_CID_CLEAN_TIME); |
| 1301 | 1309 | |
| 1302 | 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 | 77 | * Beyond the added delay we clear the bitmap anyway. |
| 78 | 78 | */ |
| 79 | 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 | 88 | msleep(100); |
| 81 | 89 | if (wait_count++ > 20) { |
| 82 | 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 | 973 | flags = claim_dma_lock(); |
| 974 | 974 | set_dma_mode(priv->param.dma, DMA_MODE_WRITE); |
| 975 | 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 | 977 | set_dma_count(priv->param.dma, |
| 978 | 978 | priv->tx_len[priv->tx_tail] - n); |
| 979 | 979 | release_dma_lock(flags); |
| @@ -1020,7 +1020,7 @@ static inline void rx_on(struct scc_priv *priv) · 40 unmodified lines | ||
| 1020 | 1020 | flags = claim_dma_lock(); |
| 1021 | 1021 | set_dma_mode(priv->param.dma, DMA_MODE_READ); |
| 1022 | 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 | 1024 | set_dma_count(priv->param.dma, BUF_SIZE); |
| 1025 | 1025 | release_dma_lock(flags); |
| 1026 | 1026 | enable_dma(priv->param.dma); |
| @@ -1233,7 +1233,7 @@ static void special_condition(struct scc_priv *priv, int rc) · 206 unmodified lines | ||
| 1233 | 1233 | if (priv->param.dma >= 0) { |
| 1234 | 1234 | flags = claim_dma_lock(); |
| 1235 | 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 | 1237 | set_dma_count(priv->param.dma, BUF_SIZE); |
| 1238 | 1238 | release_dma_lock(flags); |
| 1239 | 1239 | } else { |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | −/* Copyright 2021 NXP Semiconductors | |
| 2 | +/* Copyright 2021 NXP | |
| 3 | 3 | */ |
| 4 | 4 | #include <linux/pcs/pcs-xpcs.h> |
| 5 | 5 | #include "pcs-xpcs.h" |
| @@ -179,6 +179,16 @@ static int mdio_remove(struct device *dev) · 178 unmodified lines | ||
| 179 | 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 | 193 | * mdio_driver_register - register an mdio_driver with the MDIO layer |
| 184 | 194 | * @drv: new mdio_driver to register |
| @@ -193,6 +203,7 @@ int mdio_driver_register(struct mdio_driver *drv) · 8 unmodified lines | ||
| 193 | 203 | mdiodrv->driver.bus = &mdio_bus_type; |
| 194 | 204 | mdiodrv->driver.probe = mdio_probe; |
| 195 | 205 | mdiodrv->driver.remove = mdio_remove; |
| 206 | + mdiodrv->driver.shutdown = mdio_shutdown; | |
| 196 | 207 | |
| 197 | 208 | retval = driver_register(&mdiodrv->driver); |
| 198 | 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 | 2720 | serial = kzalloc(sizeof(*serial), GFP_KERNEL); |
| 2721 | 2721 | if (!serial) |
| 2722 | − goto exit; | |
| 2722 | + goto err_free_dev; | |
| 2723 | 2723 | |
| 2724 | 2724 | hso_dev->port_data.dev_serial = serial; |
| 2725 | 2725 | serial->parent = hso_dev; |
| 2726 | 2726 | |
| 2727 | 2727 | if (hso_serial_common_create |
| 2728 | 2728 | (serial, 1, CTRL_URB_RX_SIZE, CTRL_URB_TX_SIZE)) |
| 2729 | − goto exit; | |
| 2729 | + goto err_free_serial; | |
| 2730 | 2730 | |
| 2731 | 2731 | serial->tx_data_length--; |
| 2732 | 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 | 2742 | /* done, return it */ |
| 2743 | 2743 | return hso_dev; |
| 2744 | 2744 | |
| 2745 | −exit: | |
| 2746 | − if (serial) { | |
| 2747 | − tty_unregister_device(tty_drv, serial->minor); | |
| 2748 | − kfree(serial); | |
| 2749 | − } | |
| 2745 | +err_free_serial: | |
| 2746 | + kfree(serial); | |
| 2747 | +err_free_dev: | |
| 2750 | 2748 | kfree(hso_dev); |
| 2751 | 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 | 426 | skb_reserve(skb, p - buf); |
| 427 | 427 | skb_put(skb, len); |
| 428 | + | |
| 429 | + page = (struct page *)page->private; | |
| 430 | + if (page) | |
| 431 | + give_pages(rq, page); | |
| 428 | 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 | 4756 | LIST_HEAD(list); |
| 4757 | 4757 | unsigned int h; |
| 4758 | 4758 | |
| 4759 | − rtnl_lock(); | |
| 4760 | 4759 | list_for_each_entry(net, net_list, exit_list) { |
| 4761 | 4760 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); |
| 4762 | 4761 | |
| 4763 | 4762 | unregister_nexthop_notifier(net, &vn->nexthop_notifier_block); |
| 4764 | 4763 | } |
| 4764 | + rtnl_lock(); | |
| 4765 | 4765 | list_for_each_entry(net, net_list, exit_list) |
| 4766 | 4766 | vxlan_destroy_tunnels(net, &list); |
| 4767 | 4767 | |
| @@ -499,7 +499,7 @@ check_frags: · 498 unmodified lines | ||
| 499 | 499 | * the header's copy failed, and they are |
| 500 | 500 | * sharing a slot, send an error |
| 501 | 501 | */ |
| 502 | − if (i == 0 && sharedslot) | |
| 502 | + if (i == 0 && !first_shinfo && sharedslot) | |
| 503 | 503 | xenvif_idx_release(queue, pending_idx, |
| 504 | 504 | XEN_NETIF_RSP_ERROR); |
| 505 | 505 | else |
| @@ -278,6 +278,7 @@ static int st_nci_spi_remove(struct spi_device *dev) · 277 unmodified lines | ||
| 278 | 278 | |
| 279 | 279 | static struct spi_device_id st_nci_spi_id_table[] = { |
| 280 | 280 | {ST_NCI_SPI_DRIVER_NAME, 0}, |
| 281 | + {"st21nfcb-spi", 0}, | |
| 281 | 282 | {} |
| 282 | 283 | }; |
| 283 | 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 | 3524 | lockdep_assert_held(&subsys->lock); |
| 3525 | 3525 | |
| 3526 | 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 | 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 | 3846 | mutex_lock(&ns->ctrl->subsys->lock); |
| 3845 | 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 | 3852 | mutex_unlock(&ns->ctrl->subsys->lock); |
| 3847 | 3853 | |
| 3848 | 3854 | /* guarantee not available in head->list */ |
| @@ -3856,20 +3862,11 @@ static void nvme_ns_remove(struct nvme_ns *ns) · 7 unmodified lines | ||
| 3856 | 3862 | nvme_cdev_del(&ns->cdev, &ns->cdev_device); |
| 3857 | 3863 | del_gendisk(ns->disk); |
| 3858 | 3864 | blk_cleanup_queue(ns->queue); |
| 3859 | − if (blk_get_integrity(ns->disk)) | |
| 3860 | − blk_integrity_unregister(ns->disk); | |
| 3861 | 3865 | |
| 3862 | 3866 | down_write(&ns->ctrl->namespaces_rwsem); |
| 3863 | 3867 | list_del_init(&ns->list); |
| 3864 | 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 | 3870 | if (last_path) |
| 3874 | 3871 | nvme_mpath_shutdown_disk(ns->head); |
| 3875 | 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 | 601 | down_read(&ctrl->namespaces_rwsem); |
| 602 | 602 | list_for_each_entry(ns, &ctrl->namespaces, list) { |
| 603 | − unsigned nsid = le32_to_cpu(desc->nsids[n]); | |
| 604 | − | |
| 603 | + unsigned nsid; | |
| 604 | +again: | |
| 605 | + nsid = le32_to_cpu(desc->nsids[n]); | |
| 605 | 606 | if (ns->head->ns_id < nsid) |
| 606 | 607 | continue; |
| 607 | 608 | if (ns->head->ns_id == nsid) |
| 608 | 609 | nvme_update_ns_ana_state(desc, ns); |
| 609 | 610 | if (++n == nr_nsids) |
| 610 | 611 | break; |
| 612 | + if (ns->head->ns_id > nsid) | |
| 613 | + goto again; | |
| 611 | 614 | } |
| 612 | 615 | up_read(&ctrl->namespaces_rwsem); |
| 613 | 616 | return 0; |
| @@ -656,8 +656,8 @@ static void nvme_rdma_free_queue(struct nvme_rdma_queue *queue) · 655 unmodified lines | ||
| 656 | 656 | if (!test_and_clear_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags)) |
| 657 | 657 | return; |
| 658 | 658 | |
| 659 | − nvme_rdma_destroy_queue_ib(queue); | |
| 660 | 659 | rdma_destroy_id(queue->cm_id); |
| 660 | + nvme_rdma_destroy_queue_ib(queue); | |
| 661 | 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 | 1815 | for (i = 0; i < queue->queue_size; i++) { |
| 1816 | 1816 | ret = nvme_rdma_post_recv(queue, &queue->rsp_ring[i]); |
| 1817 | 1817 | if (ret) |
| 1818 | − goto out_destroy_queue_ib; | |
| 1818 | + return ret; | |
| 1819 | 1819 | } |
| 1820 | 1820 | |
| 1821 | 1821 | return 0; |
| 1822 | − | |
| 1823 | −out_destroy_queue_ib: | |
| 1824 | − nvme_rdma_destroy_queue_ib(queue); | |
| 1825 | − return ret; | |
| 1826 | 1822 | } |
| 1827 | 1823 | |
| 1828 | 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 | 1912 | if (ret) { |
| 1917 | 1913 | dev_err(ctrl->ctrl.device, |
| 1918 | 1914 | "rdma_connect_locked failed (%d).\n", ret); |
| 1919 | − goto out_destroy_queue_ib; | |
| 1915 | + return ret; | |
| 1920 | 1916 | } |
| 1921 | 1917 | |
| 1922 | 1918 | return 0; |
| 1923 | − | |
| 1924 | −out_destroy_queue_ib: | |
| 1925 | − nvme_rdma_destroy_queue_ib(queue); | |
| 1926 | − return ret; | |
| 1927 | 1919 | } |
| 1928 | 1920 | |
| 1929 | 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 | 1946 | case RDMA_CM_EVENT_ROUTE_ERROR: |
| 1955 | 1947 | case RDMA_CM_EVENT_CONNECT_ERROR: |
| 1956 | 1948 | case RDMA_CM_EVENT_UNREACHABLE: |
| 1957 | − nvme_rdma_destroy_queue_ib(queue); | |
| 1958 | − fallthrough; | |
| 1959 | 1949 | case RDMA_CM_EVENT_ADDR_ERROR: |
| 1960 | 1950 | dev_dbg(queue->ctrl->ctrl.device, |
| 1961 | 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 | 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 | 283 | static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req, |
| 278 | 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 | 300 | nvme_tcp_send_all(queue); |
| 295 | 301 | queue->more_requests = false; |
| 296 | 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 | 309 | static void nvme_tcp_process_req_list(struct nvme_tcp_queue *queue) |
| @@ -906,12 +913,6 @@ done: · 603 unmodified lines | ||
| 906 | 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 | 916 | static inline void nvme_tcp_done_send_req(struct nvme_tcp_queue *queue) |
| 916 | 917 | { |
| 917 | 918 | queue->request = NULL; |
| @@ -1145,8 +1146,7 @@ static void nvme_tcp_io_work(struct work_struct *w) · 227 unmodified lines | ||
| 1145 | 1146 | pending = true; |
| 1146 | 1147 | else if (unlikely(result < 0)) |
| 1147 | 1148 | break; |
| 1148 | − } else | |
| 1149 | − pending = !llist_empty(&queue->req_list); | |
| 1149 | + } | |
| 1150 | 1150 | |
| 1151 | 1151 | result = nvme_tcp_try_recv(queue); |
| 1152 | 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 | 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 | 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 | 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 | 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 | 1291 | DEFINE_SIMPLE_PROP(resets, "resets", "#reset-cells") |
| 1292 | 1292 | DEFINE_SIMPLE_PROP(leds, "leds", NULL) |
| 1293 | 1293 | DEFINE_SIMPLE_PROP(backlight, "backlight", NULL) |
| 1294 | −DEFINE_SIMPLE_PROP(phy_handle, "phy-handle", NULL) | |
| 1295 | 1294 | DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) |
| 1296 | 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 | 1379 | { .parse_prop = parse_resets, }, |
| 1381 | 1380 | { .parse_prop = parse_leds, }, |
| 1382 | 1381 | { .parse_prop = parse_backlight, }, |
| 1383 | − { .parse_prop = parse_phy_handle, }, | |
| 1384 | 1382 | { .parse_prop = parse_gpio_compat, }, |
| 1385 | 1383 | { .parse_prop = parse_interrupts, }, |
| 1386 | 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 | 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 | 941 | ACPI_COMPANION_SET(&dev->dev, |
| 942 | 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 | 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 | 5439 | * controller to VGA. |
| 5440 | 5440 | */ |
| 5441 | 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 | 5445 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, |
| 5446 | 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 | 5452 | * to VGA. Currently there is no class code defined for UCSI device over PCI |
| 5451 | 5453 | * so using UNKNOWN class for now and it will be updated when UCSI |
| 5452 | 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 | 5461 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, |
| 5460 | 5462 | PCI_CLASS_SERIAL_UNKNOWN, 8, |
| 5461 | 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 | 5469 | * Enable the NVIDIA GPU integrated HDA controller if the BIOS left it |
| @@ -99,6 +99,24 @@ error: · 98 unmodified lines | ||
| 99 | 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 | 121 | * Wait for last operation to complete. |
| 104 | 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 | 163 | loff_t end = pos + count; |
| 146 | 164 | u8 *buf = arg; |
| 147 | 165 | |
| 148 | − if (!vpd->cap) | |
| 166 | + if (!pci_vpd_available(dev)) | |
| 149 | 167 | return -ENODEV; |
| 150 | 168 | |
| 151 | 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 | 224 | loff_t end = pos + count; |
| 207 | 225 | int ret = 0; |
| 208 | 226 | |
| 209 | − if (!vpd->cap) | |
| 227 | + if (!pci_vpd_available(dev)) | |
| 210 | 228 | return -ENODEV; |
| 211 | 229 | |
| 212 | 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 | 261 | void pci_vpd_init(struct pci_dev *dev) |
| 244 | 262 | { |
| 263 | + if (dev->vpd.len == PCI_VPD_SZ_INVALID) | |
| 264 | + return; | |
| 265 | + | |
| 245 | 266 | dev->vpd.cap = pci_find_capability(dev, PCI_CAP_ID_VPD); |
| 246 | 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 | 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 | 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 | 313 | void *buf; |
| 299 | 314 | int cnt; |
| 300 | 315 | |
| 301 | − if (!dev->vpd.cap) | |
| 316 | + if (!pci_vpd_available(dev)) | |
| 302 | 317 | return ERR_PTR(-ENODEV); |
| 303 | 318 | |
| 319 | + len = dev->vpd.len; | |
| 304 | 320 | buf = kmalloc(len, GFP_KERNEL); |
| 305 | 321 | if (!buf) |
| 306 | 322 | return ERR_PTR(-ENOMEM); |
| @@ -71,7 +71,7 @@ · 70 unmodified lines | ||
| 71 | 71 | #define AMD_CPU_ID_YC 0x14B5 |
| 72 | 72 | |
| 73 | 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 | 76 | #define SOC_SUBSYSTEM_IP_MAX 12 |
| 77 | 77 | #define DELAY_MIN_US 2000 |
| @@ -166,8 +166,7 @@ config DELL_WMI · 165 unmodified lines | ||
| 166 | 166 | |
| 167 | 167 | config DELL_WMI_PRIVACY |
| 168 | 168 | bool "Dell WMI Hardware Privacy Support" |
| 169 | − depends on DELL_WMI | |
| 170 | − depends on LEDS_TRIGGER_AUDIO | |
| 169 | + depends on LEDS_TRIGGER_AUDIO = y || DELL_WMI = LEDS_TRIGGER_AUDIO | |
| 171 | 170 | help |
| 172 | 171 | This option adds integration with the "Dell Hardware Privacy" |
| 173 | 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 | 144 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"), |
| 145 | 145 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE V2"), |
| 146 | 146 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 GAMING X V2"), |
| 147 | + DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550I AORUS PRO AX"), | |
| 147 | 148 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M AORUS PRO-P"), |
| 148 | 149 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M DS3H"), |
| 149 | 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 | 139 | struct intel_hid_priv { |
| 122 | 140 | struct input_dev *input_dev; |
| 123 | 141 | struct input_dev *array; |
| 124 | 142 | struct input_dev *switches; |
| 125 | 143 | bool wakeup_mode; |
| 126 | − bool dual_accel; | |
| 144 | + bool auto_add_switch; | |
| 127 | 145 | }; |
| 128 | 146 | |
| 129 | 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 | 470 | * Some convertible have unreliable VGBS return which could cause incorrect |
| 453 | 471 | * SW_TABLET_MODE report, in these cases we enable support when receiving |
| 454 | 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 | 475 | dev_info(&device->dev, "switch event received, enable switches supports\n"); |
| 460 | 476 | err = intel_hid_switches_setup(device); |
| 461 | 477 | if (err) |
| @@ -596,7 +612,8 @@ static int intel_hid_probe(struct platform_device *device) · 134 unmodified lines | ||
| 596 | 612 | return -ENOMEM; |
| 597 | 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 | 618 | err = intel_hid_input_setup(device); |
| 602 | 619 | if (err) { |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | ||
| 8 | 8 | * which provide mailbox interface for power management usage. |
| 9 | 9 | */ |
| 10 | 10 | |
| 11 | −#include <linux/acpi.h> | |
| 12 | 11 | #include <linux/bitops.h> |
| 13 | 12 | #include <linux/delay.h> |
| 14 | 13 | #include <linux/device.h> |
| @@ -319,7 +318,7 @@ static struct platform_driver intel_punit_ipc_driver = { · 304 unmodified lines | ||
| 319 | 318 | .remove = intel_punit_ipc_remove, |
| 320 | 319 | .driver = { |
| 321 | 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 | 655 | goto out_platform_registered; |
| 656 | 656 | } |
| 657 | 657 | product = dmi_get_system_info(DMI_PRODUCT_NAME); |
| 658 | − if (strlen(product) > 4) | |
| 658 | + if (product && strlen(product) > 4) | |
| 659 | 659 | switch (product[4]) { |
| 660 | 660 | case '5': |
| 661 | 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 | 102 | static const struct property_entry chuwi_hi10_plus_props[] = { |
| 103 | − PROPERTY_ENTRY_U32("touchscreen-min-x", 0), | |
| 104 | − PROPERTY_ENTRY_U32("touchscreen-min-y", 5), | |
| 105 | − PROPERTY_ENTRY_U32("touchscreen-size-x", 1914), | |
| 106 | − PROPERTY_ENTRY_U32("touchscreen-size-y", 1283), | |
| 103 | + PROPERTY_ENTRY_U32("touchscreen-min-x", 12), | |
| 104 | + PROPERTY_ENTRY_U32("touchscreen-min-y", 10), | |
| 105 | + PROPERTY_ENTRY_U32("touchscreen-size-x", 1908), | |
| 106 | + PROPERTY_ENTRY_U32("touchscreen-size-y", 1270), | |
| 107 | 107 | PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi10plus.fw"), |
| 108 | 108 | PROPERTY_ENTRY_U32("silead,max-fingers", 10), |
| 109 | 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 | 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 | 123 | .acpi_name = "MSSL0017:00", |
| 115 | 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 | 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 | 180 | static const struct property_entry chuwi_vi8_props[] = { |
| 145 | 181 | PROPERTY_ENTRY_U32("touchscreen-min-x", 4), |
| 146 | 182 | PROPERTY_ENTRY_U32("touchscreen-min-y", 6), |
| @@ -979,6 +1015,16 @@ const struct dmi_system_id touchscreen_dmi_table[] = { · 832 unmodified lines | ||
| 979 | 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 | 1029 | /* Chuwi Vi8 (CWI506) */ |
| 984 | 1030 | .driver_data = (void *)&chuwi_vi8_data, |
| @@ -174,6 +174,7 @@ config PTP_1588_CLOCK_OCP · 173 unmodified lines | ||
| 174 | 174 | depends on I2C && MTD |
| 175 | 175 | depends on SERIAL_8250 |
| 176 | 176 | depends on !S390 |
| 177 | + depends on COMMON_CLK | |
| 177 | 178 | select NET_DEVLINK |
| 178 | 179 | help |
| 179 | 180 | This driver adds support for an OpenCompute time card. |
| @@ -269,5 +269,3 @@ module_exit(max14577_regulator_exit); · 268 unmodified lines | ||
| 269 | 269 | MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>"); |
| 270 | 270 | MODULE_DESCRIPTION("Maxim 14577/77836 regulator driver"); |
| 271 | 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 | 991 | RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"), |
| 992 | 992 | RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6"), |
| 993 | 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 | 45 | sclp.has_gisaf = !!(sccb->fac118 & 0x08); |
| 46 | 46 | sclp.has_hvs = !!(sccb->fac119 & 0x80); |
| 47 | 47 | sclp.has_kss = !!(sccb->fac98 & 0x01); |
| 48 | − sclp.has_sipl = !!(sccb->cbl & 0x4000); | |
| 49 | 48 | if (sccb->fac85 & 0x02) |
| 50 | 49 | S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; |
| 51 | 50 | if (sccb->fac91 & 0x40) |
| 52 | 51 | S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_GUEST; |
| 53 | 52 | if (sccb->cpuoff > 134) |
| 54 | 53 | sclp.has_diag318 = !!(sccb->byte_134 & 0x80); |
| 54 | + if (sccb->cpuoff > 137) | |
| 55 | + sclp.has_sipl = !!(sccb->cbl & 0x4000); | |
| 55 | 56 | sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; |
| 56 | 57 | sclp.rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; |
| 57 | 58 | sclp.rzm <<= 20; |
| @@ -77,12 +77,13 @@ EXPORT_SYMBOL(ccwgroup_set_online); · 76 unmodified lines | ||
| 77 | 77 | /** |
| 78 | 78 | * ccwgroup_set_offline() - disable a ccwgroup device |
| 79 | 79 | * @gdev: target ccwgroup device |
| 80 | + * @call_gdrv: Call the registered gdrv set_offline function | |
| 80 | 81 | * |
| 81 | 82 | * This function attempts to put the ccwgroup device into the offline state. |
| 82 | 83 | * Returns: |
| 83 | 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 | 88 | struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); |
| 88 | 89 | int ret = -EINVAL; |
| @@ -91,11 +92,16 @@ int ccwgroup_set_offline(struct ccwgroup_device *gdev) · 2 unmodified lines | ||
| 91 | 92 | return -EAGAIN; |
| 92 | 93 | if (gdev->state == CCWGROUP_OFFLINE) |
| 93 | 94 | goto out; |
| 95 | + if (!call_gdrv) { | |
| 96 | + ret = 0; | |
| 97 | + goto offline; | |
| 98 | + } | |
| 94 | 99 | if (gdrv->set_offline) |
| 95 | 100 | ret = gdrv->set_offline(gdev); |
| 96 | 101 | if (ret) |
| 97 | 102 | goto out; |
| 98 | 103 | |
| 104 | +offline: | |
| 99 | 105 | gdev->state = CCWGROUP_OFFLINE; |
| 100 | 106 | out: |
| 101 | 107 | atomic_set(&gdev->onoff, 0); |
| @@ -124,7 +130,7 @@ static ssize_t ccwgroup_online_store(struct device *dev, · 22 unmodified lines | ||
| 124 | 130 | if (value == 1) |
| 125 | 131 | ret = ccwgroup_set_online(gdev); |
| 126 | 132 | else if (value == 0) |
| 127 | − ret = ccwgroup_set_offline(gdev); | |
| 133 | + ret = ccwgroup_set_offline(gdev, true); | |
| 128 | 134 | else |
| 129 | 135 | ret = -EINVAL; |
| 130 | 136 | out: |
| @@ -213,7 +213,6 @@ static inline int ap_fetch_qci_info(struct ap_config_info *info) · 212 unmodified lines | ||
| 213 | 213 | * ap_init_qci_info(): Allocate and query qci config info. |
| 214 | 214 | * Does also update the static variables ap_max_domain_id |
| 215 | 215 | * and ap_max_adapter_id if this info is available. |
| 216 | − | |
| 217 | 216 | */ |
| 218 | 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 | 439 | * ap_interrupt_handler() - Schedule ap_tasklet on interrupt |
| 441 | 440 | * @airq: pointer to adapter interrupt descriptor |
| 441 | + * @floating: ignored | |
| 442 | 442 | */ |
| 443 | 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 | 1787 | * ap_scan_bus(): Scan the AP bus for new devices |
| 1788 | 1788 | * Runs periodically, workqueue timer (ap_config_time) |
| 1789 | + * @unused: Unused pointer. | |
| 1789 | 1790 | */ |
| 1790 | 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 | 22 | * ap_queue_enable_irq(): Enable interrupt support on this AP queue. |
| 23 | − * @qid: The AP queue number | |
| 23 | + * @aq: The AP queue | |
| 24 | 24 | * @ind: the notification indicator byte |
| 25 | 25 | * |
| 26 | 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 | 313 | * ap_sm_reset(): Reset an AP queue. |
| 314 | − * @qid: The AP queue number | |
| 314 | + * @aq: The AP queue | |
| 315 | 315 | * |
| 316 | 316 | * Submit the Reset command to an AP queue. |
| 317 | 317 | */ |
| @@ -858,7 +858,6 @@ struct qeth_card { · 857 unmodified lines | ||
| 858 | 858 | struct napi_struct napi; |
| 859 | 859 | struct qeth_rx rx; |
| 860 | 860 | struct delayed_work buffer_reclaim_work; |
| 861 | − struct work_struct close_dev_work; | |
| 862 | 861 | }; |
| 863 | 862 | |
| 864 | 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 | 70 | static int qeth_qdio_establish(struct qeth_card *); |
| 71 | 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 | 73 | static const char *qeth_get_cardname(struct qeth_card *card) |
| 83 | 74 | { |
| 84 | 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 | 193 | &card->qdio.in_buf_pool.entry_list, list) |
| 203 | 194 | list_del(&pool_entry->list); |
| 204 | 195 | |
| 196 | + if (!queue) | |
| 197 | + return; | |
| 198 | + | |
| 205 | 199 | for (i = 0; i < ARRAY_SIZE(queue->bufs); i++) |
| 206 | 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 | 786 | case IPA_CMD_STOPLAN: |
| 793 | 787 | if (cmd->hdr.return_code == IPA_RC_VEPA_TO_VEB_TRANSITION) { |
| 794 | 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 | 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 | 793 | } else { |
| 794 | + /* stay online for subsequent STARTLAN */ | |
| 799 | 795 | dev_warn(&card->gdev->dev, |
| 800 | 796 | "The link for interface %s on CHPID 0x%X failed\n", |
| 801 | 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 | 1533 | INIT_LIST_HEAD(&card->ipato.entries); |
| 1538 | 1534 | qeth_init_qdio_info(card); |
| 1539 | 1535 | INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work); |
| 1540 | − INIT_WORK(&card->close_dev_work, qeth_close_dev_handler); | |
| 1541 | 1536 | hash_init(card->rx_mode_addrs); |
| 1542 | 1537 | hash_init(card->local_addrs4); |
| 1543 | 1538 | hash_init(card->local_addrs6); |
| @@ -5519,7 +5514,8 @@ static int qeth_do_reset(void *data) · 3975 unmodified lines | ||
| 5519 | 5514 | dev_info(&card->gdev->dev, |
| 5520 | 5515 | "Device successfully recovered!\n"); |
| 5521 | 5516 | } else { |
| 5522 | − ccwgroup_set_offline(card->gdev); | |
| 5517 | + qeth_set_offline(card, disc, true); | |
| 5518 | + ccwgroup_set_offline(card->gdev, false); | |
| 5523 | 5519 | dev_warn(&card->gdev->dev, |
| 5524 | 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 | 2307 | if (gdev->state == CCWGROUP_ONLINE) |
| 2308 | 2308 | qeth_set_offline(card, card->discipline, false); |
| 2309 | 2309 | |
| 2310 | − cancel_work_sync(&card->close_dev_work); | |
| 2311 | 2310 | if (card->dev->reg_state == NETREG_REGISTERED) { |
| 2312 | 2311 | priv = netdev_priv(card->dev); |
| 2313 | 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 | 1969 | if (cgdev->state == CCWGROUP_ONLINE) |
| 1970 | 1970 | qeth_set_offline(card, card->discipline, false); |
| 1971 | 1971 | |
| 1972 | − cancel_work_sync(&card->close_dev_work); | |
| 1973 | 1972 | if (card->dev->reg_state == NETREG_REGISTERED) |
| 1974 | 1973 | unregister_netdev(card->dev); |
| 1975 | 1974 | |
| @@ -600,6 +600,12 @@ static int rockchip_spi_transfer_one( · 599 unmodified lines | ||
| 600 | 600 | int ret; |
| 601 | 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 | 609 | WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && |
| 604 | 610 | (readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY)); |
| 605 | 611 | |
| @@ -204,9 +204,6 @@ struct tegra_slink_data { · 203 unmodified lines | ||
| 204 | 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 | 207 | static inline u32 tegra_slink_readl(struct tegra_slink_data *tspi, |
| 211 | 208 | unsigned long reg) |
| 212 | 209 | { |
| @@ -1185,6 +1182,7 @@ static int tegra_slink_resume(struct device *dev) · 972 unmodified lines | ||
| 1185 | 1182 | } |
| 1186 | 1183 | #endif |
| 1187 | 1184 | |
| 1185 | +#ifdef CONFIG_PM | |
| 1188 | 1186 | static int tegra_slink_runtime_suspend(struct device *dev) |
| 1189 | 1187 | { |
| 1190 | 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 | 1209 | return 0; |
| 1212 | 1210 | } |
| 1211 | +#endif /* CONFIG_PM */ | |
| 1213 | 1212 | |
| 1214 | 1213 | static const struct dev_pm_ops slink_pm_ops = { |
| 1215 | 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 | 58 | const struct spi_device *spi = to_spi_device(dev); |
| 59 | 59 | int len; |
| 60 | 60 | |
| 61 | − len = of_device_modalias(dev, buf, PAGE_SIZE); | |
| 62 | − if (len != -ENODEV) | |
| 63 | − return len; | |
| 64 | − | |
| 65 | 61 | len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); |
| 66 | 62 | if (len != -ENODEV) |
| 67 | 63 | return len; |
| @@ -367,10 +363,6 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) · 299 unmodified lines | ||
| 367 | 363 | const struct spi_device *spi = to_spi_device(dev); |
| 368 | 364 | int rc; |
| 369 | 365 | |
| 370 | − rc = of_device_uevent_modalias(dev, env); | |
| 371 | − if (rc != -ENODEV) | |
| 372 | − return rc; | |
| 373 | − | |
| 374 | 366 | rc = acpi_device_uevent_modalias(dev, env); |
| 375 | 367 | if (rc != -ENODEV) |
| 376 | 368 | return rc; |
| @@ -582,7 +582,9 @@ config FB_HP300 · 581 unmodified lines | ||
| 582 | 582 | |
| 583 | 583 | config FB_TGA |
| 584 | 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 | 588 | select FB_CFB_FILLRECT |
| 587 | 589 | select FB_CFB_COPYAREA |
| 588 | 590 | select FB_CFB_IMAGEBLIT |
| @@ -214,7 +214,7 @@ config XEN_PVCALLS_FRONTEND · 213 unmodified lines | ||
| 214 | 214 | implements them. |
| 215 | 215 | |
| 216 | 216 | config XEN_PVCALLS_BACKEND |
| 217 | − bool "XEN PV Calls backend driver" | |
| 217 | + tristate "XEN PV Calls backend driver" | |
| 218 | 218 | depends on INET && XEN && XEN_BACKEND |
| 219 | 219 | help |
| 220 | 220 | Experimental backend for the Xen PV Calls protocol |
| @@ -43,6 +43,8 @@ · 42 unmodified lines | ||
| 43 | 43 | #include <linux/sched.h> |
| 44 | 44 | #include <linux/cred.h> |
| 45 | 45 | #include <linux/errno.h> |
| 46 | +#include <linux/freezer.h> | |
| 47 | +#include <linux/kthread.h> | |
| 46 | 48 | #include <linux/mm.h> |
| 47 | 49 | #include <linux/memblock.h> |
| 48 | 50 | #include <linux/pagemap.h> |
| @@ -115,7 +117,7 @@ static struct ctl_table xen_root[] = { · 66 unmodified lines | ||
| 115 | 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 | 122 | * BP_DONE: done or nothing to do, |
| 121 | 123 | * BP_WAIT: wait to be rescheduled, |
| @@ -130,6 +132,8 @@ enum bp_state { · 8 unmodified lines | ||
| 130 | 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 | 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 | 148 | static LIST_HEAD(ballooned_pages); |
| 145 | 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 | 151 | /* When ballooning out (allocating memory to return to Xen) we don't really |
| 152 | 152 | want the kernel to try too hard since that can trigger the oom killer. */ |
| 153 | 153 | #define GFP_BALLOON \ |
| @@ -366,7 +366,7 @@ static void xen_online_page(struct page *page, unsigned int order) · 212 unmodified lines | ||
| 366 | 366 | static int xen_memory_notifier(struct notifier_block *nb, unsigned long val, void *v) |
| 367 | 367 | { |
| 368 | 368 | if (val == MEM_ONLINE) |
| 369 | − schedule_delayed_work(&balloon_worker, 0); | |
| 369 | + wake_up(&balloon_thread_wq); | |
| 370 | 370 | |
| 371 | 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 | 507 | * We may of course race updates of the target counts (which are protected |
| 496 | 508 | * by the balloon lock), or with changes to the Xen hard limit, but we will |
| 497 | 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 | 513 | enum bp_state state = BP_DONE; |
| 502 | 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 | 531 | mutex_lock(&balloon_mutex); |
| 507 | 532 | |
| 508 | 533 | credit = current_credit(); |
| @@ -529,12 +554,7 @@ static void balloon_process(struct work_struct *work) · 20 unmodified lines | ||
| 529 | 554 | mutex_unlock(&balloon_mutex); |
| 530 | 555 | |
| 531 | 556 | cond_resched(); |
| 532 | − | |
| 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); | |
| 557 | + } | |
| 538 | 558 | } |
| 539 | 559 | |
| 540 | 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 | 563 | /* No need for lock. Not read-modify-write updates. */ |
| 544 | 564 | balloon_stats.target_pages = target; |
| 545 | − schedule_delayed_work(&balloon_worker, 0); | |
| 565 | + wake_up(&balloon_thread_wq); | |
| 546 | 566 | } |
| 547 | 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 | 668 | /* The balloon may be too large now. Shrink it if needed. */ |
| 649 | 669 | if (current_credit()) |
| 650 | − schedule_delayed_work(&balloon_worker, 0); | |
| 670 | + wake_up(&balloon_thread_wq); | |
| 651 | 671 | |
| 652 | 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 | 700 | static int __init balloon_init(void) |
| 681 | 701 | { |
| 702 | + struct task_struct *task; | |
| 703 | + | |
| 682 | 704 | if (!xen_domain()) |
| 683 | 705 | return -ENODEV; |
| 684 | 706 | |
| @@ -722,6 +744,12 @@ static int __init balloon_init(void) · 37 unmodified lines | ||
| 722 | 744 | } |
| 723 | 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 | 753 | /* Init the xen-balloon driver. */ |
| 726 | 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 | 107 | static int xen_swiotlb_fixup(void *buf, unsigned long nslabs) |
| 108 | 108 | { |
| 109 | − int i, rc; | |
| 110 | − int dma_bits; | |
| 109 | + int rc; | |
| 110 | + unsigned int order = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT); | |
| 111 | + unsigned int i, dma_bits = order + PAGE_SHIFT; | |
| 111 | 112 | dma_addr_t dma_handle; |
| 112 | 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 | 118 | i = 0; |
| 117 | 119 | do { |
| 118 | − int slabs = min(nslabs - i, (unsigned long)IO_TLB_SEGSIZE); | |
| 119 | − | |
| 120 | 120 | do { |
| 121 | 121 | rc = xen_create_contiguous_region( |
| 122 | − p + (i << IO_TLB_SHIFT), | |
| 123 | − get_order(slabs << IO_TLB_SHIFT), | |
| 122 | + p + (i << IO_TLB_SHIFT), order, | |
| 124 | 123 | dma_bits, &dma_handle); |
| 125 | 124 | } while (rc && dma_bits++ < MAX_DMA_BITS); |
| 126 | 125 | if (rc) |
| 127 | 126 | return rc; |
| 128 | 127 | |
| 129 | − i += slabs; | |
| 128 | + i += IO_TLB_SEGSIZE; | |
| 130 | 129 | } while (i < nslabs); |
| 131 | 130 | return 0; |
| 132 | 131 | } |
| @@ -153,9 +152,7 @@ static const char *xen_swiotlb_error(enum xen_swiotlb_err err) · 20 unmodified lines | ||
| 153 | 152 | return ""; |
| 154 | 153 | } |
| 155 | 154 | |
| 156 | −#define DEFAULT_NSLABS ALIGN(SZ_64M >> IO_TLB_SHIFT, IO_TLB_SEGSIZE) | |
| 157 | − | |
| 158 | −int __ref xen_swiotlb_init(void) | |
| 155 | +int xen_swiotlb_init(void) | |
| 159 | 156 | { |
| 160 | 157 | enum xen_swiotlb_err m_ret = XEN_SWIOTLB_UNKNOWN; |
| 161 | 158 | unsigned long bytes = swiotlb_size_or_default(); |
| @@ -185,7 +182,7 @@ retry: · 23 unmodified lines | ||
| 185 | 182 | order--; |
| 186 | 183 | } |
| 187 | 184 | if (!start) |
| 188 | − goto error; | |
| 185 | + goto exit; | |
| 189 | 186 | if (order != get_order(bytes)) { |
| 190 | 187 | pr_warn("Warning: only able to allocate %ld MB for software IO TLB\n", |
| 191 | 188 | (PAGE_SIZE << order) >> 20); |
| @@ -208,15 +205,15 @@ retry: · 16 unmodified lines | ||
| 208 | 205 | swiotlb_set_max_segment(PAGE_SIZE); |
| 209 | 206 | return 0; |
| 210 | 207 | error: |
| 211 | − if (repeat--) { | |
| 208 | + if (nslabs > 1024 && repeat--) { | |
| 212 | 209 | /* Min is 2MB */ |
| 213 | − nslabs = max(1024UL, (nslabs >> 1)); | |
| 214 | − pr_info("Lowering to %luMB\n", | |
| 215 | − (nslabs << IO_TLB_SHIFT) >> 20); | |
| 210 | + nslabs = max(1024UL, ALIGN(nslabs >> 1, IO_TLB_SEGSIZE)); | |
| 211 | + bytes = nslabs << IO_TLB_SHIFT; | |
| 212 | + pr_info("Lowering to %luMB\n", bytes >> 20); | |
| 216 | 213 | goto retry; |
| 217 | 214 | } |
| 215 | +exit: | |
| 218 | 216 | pr_err("%s (rc:%d)\n", xen_swiotlb_error(m_ret), rc); |
| 219 | − free_pages((unsigned long)start, order); | |
| 220 | 217 | return rc; |
| 221 | 218 | } |
| 222 | 219 | |
| @@ -244,9 +241,9 @@ retry: · 21 unmodified lines | ||
| 244 | 241 | rc = xen_swiotlb_fixup(start, nslabs); |
| 245 | 242 | if (rc) { |
| 246 | 243 | memblock_free(__pa(start), PAGE_ALIGN(bytes)); |
| 247 | − if (repeat--) { | |
| 244 | + if (nslabs > 1024 && repeat--) { | |
| 248 | 245 | /* Min is 2MB */ |
| 249 | − nslabs = max(1024UL, (nslabs >> 1)); | |
| 246 | + nslabs = max(1024UL, ALIGN(nslabs >> 1, IO_TLB_SEGSIZE)); | |
| 250 | 247 | bytes = nslabs << IO_TLB_SHIFT; |
| 251 | 248 | pr_info("Lowering to %luMB\n", bytes >> 20); |
| 252 | 249 | goto retry; |
| @@ -254,7 +251,7 @@ retry: · 1 unmodified line | ||
| 254 | 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 | 255 | panic("Cannot allocate SWIOTLB buffer"); |
| 259 | 256 | swiotlb_set_max_segment(PAGE_SIZE); |
| 260 | 257 | } |
| @@ -20,6 +20,37 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/sched.h> |
| 21 | 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 | 55 | * Allow the fileserver to request callback state (re-)initialisation. |
| 25 | 56 | * Unfortunately, UUIDs are not guaranteed unique. |
| @@ -29,8 +60,11 @@ void afs_init_callback_state(struct afs_server *server) · 3 unmodified lines | ||
| 29 | 60 | rcu_read_lock(); |
| 30 | 61 | do { |
| 31 | 62 | server->cb_s_break++; |
| 32 | − server = rcu_dereference(server->uuid_next); | |
| 33 | − } while (0); | |
| 63 | + atomic_inc(&server->cell->fs_s_break); | |
| 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 | 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 | 78 | clear_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); |
| 45 | 79 | if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { |
| 46 | 80 | vnode->cb_break++; |
| 81 | + vnode->cb_v_break = vnode->volume->cb_v_break; | |
| 47 | 82 | afs_clear_permits(vnode); |
| 48 | 83 | |
| 49 | 84 | if (vnode->lock_state == AFS_VNODE_LOCK_WAITING_FOR_CB) |
| 50 | 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 | 92 | trace_afs_cb_break(&vnode->fid, vnode->cb_break, reason, true); |
| 53 | 93 | } else { |
| 54 | 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 | 166 | seqlock_init(&cell->volume_lock); |
| 167 | 167 | cell->fs_servers = RB_ROOT; |
| 168 | 168 | seqlock_init(&cell->fs_lock); |
| 169 | + INIT_LIST_HEAD(&cell->fs_open_mmaps); | |
| 170 | + init_rwsem(&cell->fs_open_mmaps_lock); | |
| 169 | 171 | rwlock_init(&cell->vl_servers_lock); |
| 170 | 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 | 1078 | static int afs_d_revalidate_rcu(struct dentry *dentry) |
| 1079 | 1079 | { |
| 1080 | − struct afs_vnode *dvnode, *vnode; | |
| 1080 | + struct afs_vnode *dvnode; | |
| 1081 | 1081 | struct dentry *parent; |
| 1082 | − struct inode *dir, *inode; | |
| 1082 | + struct inode *dir; | |
| 1083 | 1083 | long dir_version, de_version; |
| 1084 | 1084 | |
| 1085 | 1085 | _enter("%p", dentry); |
| @@ -1109,18 +1109,6 @@ static int afs_d_revalidate_rcu(struct dentry *dentry) · 23 unmodified lines | ||
| 1109 | 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 | 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 | 1144 | if (IS_ERR(key)) |
| 1157 | 1145 | key = NULL; |
| 1158 | 1146 | |
| 1159 | − if (d_really_is_positive(dentry)) { | |
| 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 */ | |
| 1147 | + /* Hold the parent dentry so we can peer at it */ | |
| 1170 | 1148 | parent = dget_parent(dentry); |
| 1171 | 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 | 1154 | if (test_bit(AFS_VNODE_DELETED, &dir->flags)) { |
| 1177 | 1155 | _debug("%pd: parent dir deleted", dentry); |
| 1178 | − goto out_bad_parent; | |
| 1156 | + goto not_found; | |
| 1179 | 1157 | } |
| 1180 | 1158 | |
| 1181 | 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 | 1179 | case 0: |
| 1202 | 1180 | /* the filename maps to something */ |
| 1203 | 1181 | if (d_really_is_negative(dentry)) |
| 1204 | − goto out_bad_parent; | |
| 1182 | + goto not_found; | |
| 1205 | 1183 | inode = d_inode(dentry); |
| 1206 | 1184 | if (is_bad_inode(inode)) { |
| 1207 | 1185 | printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n", |
| 1208 | 1186 | dentry); |
| 1209 | − goto out_bad_parent; | |
| 1187 | + goto not_found; | |
| 1210 | 1188 | } |
| 1211 | 1189 | |
| 1212 | 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 | 1206 | dentry, fid.unique, |
| 1229 | 1207 | vnode->fid.unique, |
| 1230 | 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 | 1209 | goto not_found; |
| 1235 | 1210 | } |
| 1236 | 1211 | goto out_valid; |
| @@ -1245,7 +1220,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) · 8 unmodified lines | ||
| 1245 | 1220 | default: |
| 1246 | 1221 | _debug("failed to iterate dir %pd: %d", |
| 1247 | 1222 | parent, ret); |
| 1248 | − goto out_bad_parent; | |
| 1223 | + goto not_found; | |
| 1249 | 1224 | } |
| 1250 | 1225 | |
| 1251 | 1226 | out_valid: |
| @@ -1256,16 +1231,9 @@ out_valid_noupdate: · 4 unmodified lines | ||
| 1256 | 1231 | _leave(" = 1 [valid]"); |
| 1257 | 1232 | return 1; |
| 1258 | 1233 | |
| 1259 | − /* the dirent, if it exists, now points to a different vnode */ | |
| 1260 | 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 | 1235 | _debug("dropping dentry %pd2", dentry); |
| 1267 | 1236 | dput(parent); |
| 1268 | −out_bad: | |
| 1269 | 1237 | key_put(key); |
| 1270 | 1238 | |
| 1271 | 1239 | _leave(" = 0 [bad]"); |
| @@ -1792,6 +1760,10 @@ static int afs_link(struct dentry *from, struct inode *dir, · 520 unmodified lines | ||
| 1792 | 1760 | goto error; |
| 1793 | 1761 | } |
| 1794 | 1762 | |
| 1763 | + ret = afs_validate(vnode, op->key); | |
| 1764 | + if (ret < 0) | |
| 1765 | + goto error_op; | |
| 1766 | + | |
| 1795 | 1767 | afs_op_set_vnode(op, 0, dvnode); |
| 1796 | 1768 | afs_op_set_vnode(op, 1, vnode); |
| 1797 | 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 | 1777 | op->create.reason = afs_edit_dir_for_link; |
| 1806 | 1778 | return afs_do_sync_operation(op); |
| 1807 | 1779 | |
| 1780 | +error_op: | |
| 1781 | + afs_put_operation(op); | |
| 1808 | 1782 | error: |
| 1809 | 1783 | d_drop(dentry); |
| 1810 | 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 | 1963 | if (IS_ERR(op)) |
| 1990 | 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 | 1971 | afs_op_set_vnode(op, 0, orig_dvnode); |
| 1993 | 1972 | afs_op_set_vnode(op, 1, new_dvnode); /* May be same as orig_dvnode */ |
| 1994 | 1973 | op->file[0].dv_delta = 1; |
| @@ -263,7 +263,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode, · 262 unmodified lines | ||
| 263 | 263 | if (b == nr_blocks) { |
| 264 | 264 | _debug("init %u", b); |
| 265 | 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 | 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 | 296 | new_directory: |
| 297 | 297 | afs_edit_init_block(meta, meta, 0); |
| 298 | 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 | 300 | slot = AFS_DIR_RESV_BLOCKS0; |
| 301 | 301 | page = page0; |
| 302 | 302 | block = meta; |
| @@ -24,12 +24,16 @@ static void afs_invalidatepage(struct page *page, unsigned int offset, · 23 unmodified lines | ||
| 24 | 24 | static int afs_releasepage(struct page *page, gfp_t gfp_flags); |
| 25 | 25 | |
| 26 | 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 | 32 | const struct file_operations afs_file_operations = { |
| 29 | 33 | .open = afs_open, |
| 30 | 34 | .release = afs_release, |
| 31 | 35 | .llseek = generic_file_llseek, |
| 32 | − .read_iter = generic_file_read_iter, | |
| 36 | + .read_iter = afs_file_read_iter, | |
| 33 | 37 | .write_iter = afs_file_write, |
| 34 | 38 | .mmap = afs_file_mmap, |
| 35 | 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 | 65 | static const struct vm_operations_struct afs_vm_ops = { |
| 66 | + .open = afs_vm_open, | |
| 67 | + .close = afs_vm_close, | |
| 62 | 68 | .fault = filemap_fault, |
| 63 | − .map_pages = filemap_map_pages, | |
| 69 | + .map_pages = afs_vm_map_pages, | |
| 64 | 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 | 301 | fsreq->subreq = subreq; |
| 296 | 302 | fsreq->pos = subreq->start + subreq->transferred; |
| 297 | 303 | fsreq->len = subreq->len - subreq->transferred; |
| 298 | − fsreq->key = subreq->rreq->netfs_priv; | |
| 304 | + fsreq->key = key_get(subreq->rreq->netfs_priv); | |
| 299 | 305 | fsreq->vnode = vnode; |
| 300 | 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 | 310 | fsreq->pos, fsreq->len); |
| 305 | 311 | |
| 306 | 312 | afs_fetch_data(fsreq->vnode, fsreq); |
| 313 | + afs_put_read(fsreq); | |
| 307 | 314 | } |
| 308 | 315 | |
| 309 | 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 | 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 | 527 | * Handle setting up a memory mapping on an AFS file. |
| 495 | 528 | */ |
| 496 | 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 | 532 | int ret; |
| 499 | 533 | |
| 534 | + afs_add_open_mmap(vnode); | |
| 535 | + | |
| 500 | 536 | ret = generic_file_mmap(file, vma); |
| 501 | 537 | if (ret == 0) |
| 502 | 538 | vma->vm_ops = &afs_vm_ops; |
| 539 | + else | |
| 540 | + afs_drop_open_mmap(vnode); | |
| 503 | 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 | 9 | #include <linux/slab.h> |
| 10 | 10 | #include "afs_fs.h" |
| 11 | 11 | #include "internal.h" |
| 12 | +#include "protocol_afs.h" | |
| 12 | 13 | #include "protocol_yfs.h" |
| 13 | 14 | |
| 14 | 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 | 103 | struct afs_addr_list *alist = call->alist; |
| 103 | 104 | struct afs_server *server = call->server; |
| 104 | 105 | unsigned int index = call->addr_ix; |
| 105 | − unsigned int rtt_us = 0; | |
| 106 | + unsigned int rtt_us = 0, cap0; | |
| 106 | 107 | int ret = call->error; |
| 107 | 108 | |
| 108 | 109 | _enter("%pU,%u", &server->uuid, index); |
| @@ -159,6 +160,11 @@ responded: · 50 unmodified lines | ||
| 159 | 160 | clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags); |
| 160 | 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 | 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 | 456 | struct afs_read *req = op->fetch.req; |
| 457 | 457 | __be32 *bp; |
| 458 | 458 | |
| 459 | − if (upper_32_bits(req->pos) || | |
| 460 | − upper_32_bits(req->len) || | |
| 461 | − upper_32_bits(req->pos + req->len)) | |
| 459 | + if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags)) | |
| 462 | 460 | return afs_fs_fetch_data64(op); |
| 463 | 461 | |
| 464 | 462 | _enter(""); |
| @@ -1113,9 +1111,7 @@ void afs_fs_store_data(struct afs_operation *op) · 648 unmodified lines | ||
| 1113 | 1111 | (unsigned long long)op->store.pos, |
| 1114 | 1112 | (unsigned long long)op->store.i_size); |
| 1115 | 1113 | |
| 1116 | − if (upper_32_bits(op->store.pos) || | |
| 1117 | − upper_32_bits(op->store.size) || | |
| 1118 | − upper_32_bits(op->store.i_size)) | |
| 1114 | + if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags)) | |
| 1119 | 1115 | return afs_fs_store_data64(op); |
| 1120 | 1116 | |
| 1121 | 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 | 1225 | key_serial(op->key), vp->fid.vid, vp->fid.vnode); |
| 1230 | 1226 | |
| 1231 | 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 | 1229 | return afs_fs_setattr_size64(op); |
| 1234 | 1230 | |
| 1235 | 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 | 1653 | return ret; |
| 1658 | 1654 | |
| 1659 | 1655 | count = ntohl(call->tmp); |
| 1660 | − | |
| 1661 | 1656 | call->count = count; |
| 1662 | 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 | 1666 | call->unmarshall++; |
| 1665 | 1667 | fallthrough; |
| 1666 | 1668 | |
| 1667 | − /* Extract capabilities words */ | |
| 1668 | 1669 | case 2: |
| 1669 | 1670 | ret = afs_extract_data(call, false); |
| 1670 | 1671 | if (ret < 0) |
| 1671 | 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 | 1684 | call->unmarshall++; |
| 1676 | 1685 | break; |
| @@ -53,16 +53,6 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren · 52 unmodified lines | ||
| 53 | 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 | 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 | 586 | struct afs_server *server; |
| 587 | + bool good; | |
| 596 | 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 | 596 | for (i = 0; i < slist->nr_servers; i++) { |
| 599 | 597 | server = slist->servers[i].server; |
| 600 | 598 | if (server == vnode->cb_server) { |
| 601 | − *_s_break = READ_ONCE(server->cb_s_break); | |
| 602 | − return true; | |
| 599 | + good = (vnode->cb_s_break == server->cb_s_break); | |
| 600 | + rcu_read_unlock(); | |
| 601 | + return good; | |
| 603 | 602 | } |
| 604 | 603 | } |
| 605 | 604 | |
| 605 | + rcu_read_unlock(); | |
| 606 | 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 | 612 | bool afs_check_validity(struct afs_vnode *vnode) |
| 613 | 613 | { |
| 614 | − struct afs_volume *volume = vnode->volume; | |
| 615 | 614 | enum afs_cb_break_reason need_clear = afs_cb_break_no_break; |
| 616 | 615 | time64_t now = ktime_get_real_seconds(); |
| 617 | − bool valid; | |
| 618 | − unsigned int cb_break, cb_s_break, cb_v_break; | |
| 616 | + unsigned int cb_break; | |
| 619 | 617 | int seq = 0; |
| 620 | 618 | |
| 621 | 619 | do { |
| 622 | 620 | read_seqbegin_or_lock(&vnode->cb_lock, &seq); |
| 623 | − cb_v_break = READ_ONCE(volume->cb_v_break); | |
| 624 | 621 | cb_break = vnode->cb_break; |
| 625 | 622 | |
| 626 | − if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags) && | |
| 627 | − afs_get_s_break_rcu(vnode, &cb_s_break)) { | |
| 628 | − if (vnode->cb_s_break != cb_s_break || | |
| 629 | − vnode->cb_v_break != cb_v_break) { | |
| 630 | − vnode->cb_s_break = cb_s_break; | |
| 631 | − vnode->cb_v_break = cb_v_break; | |
| 632 | − need_clear = afs_cb_break_for_vsbreak; | |
| 633 | − valid = false; | |
| 634 | − } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) { | |
| 623 | + if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { | |
| 624 | + if (vnode->cb_v_break != vnode->volume->cb_v_break) | |
| 625 | + need_clear = afs_cb_break_for_v_break; | |
| 626 | + else if (!afs_check_server_good(vnode)) | |
| 627 | + need_clear = afs_cb_break_for_s_reinit; | |
| 628 | + else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) | |
| 635 | 629 | need_clear = afs_cb_break_for_zap; |
| 636 | − valid = false; | |
| 637 | − } else if (vnode->cb_expires_at - 10 <= now) { | |
| 630 | + else if (vnode->cb_expires_at - 10 <= now) | |
| 638 | 631 | need_clear = afs_cb_break_for_lapsed; |
| 639 | − valid = false; | |
| 640 | − } else { | |
| 641 | − valid = true; | |
| 642 | − } | |
| 643 | 632 | } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { |
| 644 | − valid = true; | |
| 633 | + ; | |
| 645 | 634 | } else { |
| 646 | − vnode->cb_v_break = cb_v_break; | |
| 647 | − valid = false; | |
| 635 | + need_clear = afs_cb_break_no_promise; | |
| 648 | 636 | } |
| 649 | 637 | |
| 650 | 638 | } while (need_seqretry(&vnode->cb_lock, seq)); |
| 651 | 639 | |
| 652 | 640 | done_seqretry(&vnode->cb_lock, seq); |
| 653 | 641 | |
| 654 | − if (need_clear != afs_cb_break_no_break) { | |
| 655 | − write_seqlock(&vnode->cb_lock); | |
| 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 | − } | |
| 642 | + if (need_clear == afs_cb_break_no_break) | |
| 643 | + return true; | |
| 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 | 665 | int afs_validate(struct afs_vnode *vnode, struct key *key) |
| 677 | 666 | { |
| 678 | − bool valid; | |
| 679 | 667 | int ret; |
| 680 | 668 | |
| 681 | 669 | _enter("{v={%llx:%llu} fl=%lx},%x", |
| 682 | 670 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, |
| 683 | 671 | key_serial(key)); |
| 684 | 672 | |
| 685 | − rcu_read_lock(); | |
| 686 | − valid = afs_check_validity(vnode); | |
| 687 | − rcu_read_unlock(); | |
| 688 | − | |
| 689 | − if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) | |
| 690 | − clear_nlink(&vnode->vfs_inode); | |
| 673 | + if (unlikely(test_bit(AFS_VNODE_DELETED, &vnode->flags))) { | |
| 674 | + if (vnode->vfs_inode.i_nlink) | |
| 675 | + clear_nlink(&vnode->vfs_inode); | |
| 676 | + goto valid; | |
| 677 | + } | |
| 691 | 678 | |
| 692 | − if (valid) | |
| 679 | + if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags) && | |
| 680 | + afs_check_validity(vnode)) | |
| 693 | 681 | goto valid; |
| 694 | 682 | |
| 695 | 683 | down_write(&vnode->validate_lock); |
| @@ -390,6 +390,9 @@ struct afs_cell { · 389 unmodified lines | ||
| 390 | 390 | /* Active fileserver interaction state. */ |
| 391 | 391 | struct rb_root fs_servers; /* afs_server (by server UUID) */ |
| 392 | 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 | 397 | /* VL server list. */ |
| 395 | 398 | rwlock_t vl_servers_lock; /* Lock on vl_servers */ |
| @@ -503,6 +506,7 @@ struct afs_server { · 107 unmodified lines | ||
| 503 | 506 | struct hlist_node addr4_link; /* Link in net->fs_addresses4 */ |
| 504 | 507 | struct hlist_node addr6_link; /* Link in net->fs_addresses6 */ |
| 505 | 508 | struct hlist_node proc_link; /* Link in net->fs_proc */ |
| 509 | + struct work_struct initcb_work; /* Work for CB.InitCallBackState* */ | |
| 506 | 510 | struct afs_server *gc_next; /* Next server in manager's list */ |
| 507 | 511 | time64_t unuse_time; /* Time at which last unused */ |
| 508 | 512 | unsigned long flags; |
| @@ -516,6 +520,7 @@ struct afs_server { · 7 unmodified lines | ||
| 516 | 520 | #define AFS_SERVER_FL_IS_YFS 16 /* Server is YFS not AFS */ |
| 517 | 521 | #define AFS_SERVER_FL_NO_IBULK 17 /* Fileserver doesn't support FS.InlineBulkStatus */ |
| 518 | 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 | 524 | atomic_t ref; /* Object refcount */ |
| 520 | 525 | atomic_t active; /* Active user count */ |
| 521 | 526 | u32 addr_version; /* Address list version */ |
| @@ -657,7 +662,11 @@ struct afs_vnode { · 135 unmodified lines | ||
| 657 | 662 | afs_lock_type_t lock_type : 8; |
| 658 | 663 | |
| 659 | 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 | 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 | 670 | unsigned int cb_s_break; /* Mass break counter on ->server */ |
| 662 | 671 | unsigned int cb_v_break; /* Mass break counter on ->volume */ |
| 663 | 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 | 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 | 979 | extern void afs_init_callback_state(struct afs_server *); |
| 969 | 980 | extern void __afs_break_callback(struct afs_vnode *, enum afs_cb_break_reason); |
| 970 | 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 | 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 | 1610 | * Check for a conflicting operation on a directory that we just unlinked from. |
| 1590 | 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 | 168 | yfs_LockMandatoryWrite = 0x101, |
| 169 | 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 | 374 | if (vnode->cb_server != server) { |
| 375 | 375 | vnode->cb_server = server; |
| 376 | 376 | vnode->cb_s_break = server->cb_s_break; |
| 377 | + vnode->cb_fs_s_break = atomic_read(&server->cell->fs_s_break); | |
| 377 | 378 | vnode->cb_v_break = vnode->volume->cb_v_break; |
| 378 | 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 | 235 | server->addr_version = alist->version; |
| 236 | 236 | server->uuid = *uuid; |
| 237 | 237 | rwlock_init(&server->fs_lock); |
| 238 | + INIT_WORK(&server->initcb_work, afs_server_init_callback_work); | |
| 238 | 239 | init_waitqueue_head(&server->probe_wq); |
| 239 | 240 | INIT_LIST_HEAD(&server->probe_link); |
| 240 | 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 | 468 | if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags)) |
| 468 | 469 | afs_give_up_callbacks(net, server); |
| 469 | 470 | |
| 471 | + flush_work(&server->initcb_work); | |
| 470 | 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 | 698 | vnode->lock_state = AFS_VNODE_LOCK_NONE; |
| 699 | 699 | |
| 700 | 700 | init_rwsem(&vnode->rmdir_lock); |
| 701 | + INIT_WORK(&vnode->cb_work, afs_invalidate_mmap_work); | |
| 701 | 702 | |
| 702 | 703 | _leave(" = %p", &vnode->vfs_inode); |
| 703 | 704 | return &vnode->vfs_inode; |
| @@ -137,7 +137,7 @@ int afs_write_end(struct file *file, struct address_space *mapping, · 136 unmodified lines | ||
| 137 | 137 | write_seqlock(&vnode->cb_lock); |
| 138 | 138 | i_size = i_size_read(&vnode->vfs_inode); |
| 139 | 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 | 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 | 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 | 476 | break; |
| 477 | + } | |
| 476 | 478 | |
| 477 | − if (!trylock_page(page)) | |
| 479 | + if (!trylock_page(page)) { | |
| 480 | + put_page(page); | |
| 478 | 481 | break; |
| 482 | + } | |
| 479 | 483 | if (!PageDirty(page) || PageWriteback(page)) { |
| 480 | 484 | unlock_page(page); |
| 485 | + put_page(page); | |
| 481 | 486 | break; |
| 482 | 487 | } |
| 483 | 488 | |
| @@ -487,6 +492,7 @@ static void afs_extend_writeback(struct address_space *mapping, · 3 unmodified lines | ||
| 487 | 492 | t = afs_page_dirty_to(page, priv); |
| 488 | 493 | if (f != 0 && !new_content) { |
| 489 | 494 | unlock_page(page); |
| 495 | + put_page(page); | |
| 490 | 496 | break; |
| 491 | 497 | } |
| 492 | 498 | |
| @@ -801,6 +807,7 @@ int afs_writepages(struct address_space *mapping, · 308 unmodified lines | ||
| 801 | 807 | ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from) |
| 802 | 808 | { |
| 803 | 809 | struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp)); |
| 810 | + struct afs_file *af = iocb->ki_filp->private_data; | |
| 804 | 811 | ssize_t result; |
| 805 | 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 | 823 | if (!count) |
| 817 | 824 | return 0; |
| 818 | 825 | |
| 826 | + result = afs_validate(vnode, af->key); | |
| 827 | + if (result < 0) | |
| 828 | + return result; | |
| 829 | + | |
| 819 | 830 | result = generic_file_write_iter(iocb, from); |
| 820 | 831 | |
| 821 | 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 | 841 | int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
| 831 | 842 | { |
| 832 | − struct inode *inode = file_inode(file); | |
| 833 | − struct afs_vnode *vnode = AFS_FS_I(inode); | |
| 843 | + struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); | |
| 844 | + struct afs_file *af = file->private_data; | |
| 845 | + int ret; | |
| 834 | 846 | |
| 835 | 847 | _enter("{%llx:%llu},{n=%pD},%d", |
| 836 | 848 | vnode->fid.vid, vnode->fid.vnode, file, |
| 837 | 849 | datasync); |
| 838 | 850 | |
| 851 | + ret = afs_validate(vnode, af->key); | |
| 852 | + if (ret < 0) | |
| 853 | + return ret; | |
| 854 | + | |
| 839 | 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 | 865 | struct file *file = vmf->vma->vm_file; |
| 850 | 866 | struct inode *inode = file_inode(file); |
| 851 | 867 | struct afs_vnode *vnode = AFS_FS_I(inode); |
| 868 | + struct afs_file *af = file->private_data; | |
| 852 | 869 | unsigned long priv; |
| 853 | 870 | vm_fault_t ret = VM_FAULT_RETRY; |
| 854 | 871 | |
| 855 | 872 | _enter("{{%llx:%llu}},{%lx}", vnode->fid.vid, vnode->fid.vnode, page->index); |
| 856 | 873 | |
| 874 | + afs_validate(vnode, af->key); | |
| 875 | + | |
| 857 | 876 | sb_start_pagefault(inode->i_sb); |
| 858 | 877 | |
| 859 | 878 | /* Wait for the page to be written to the cache before we allow it to |
| @@ -1,6 +1,6 @@ | ||
| 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 | 5 | * Copyright (c) 2010 Novell, Inc. |
| 6 | 6 | * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | − * fs/cifs_debug.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2000,2005 |
| 6 | 5 | * |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifs_fs_sb.h | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2002,2004 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifs_ioctl.h | |
| 4 | 3 | * |
| 5 | 4 | * Structure definitions for io control for cifs/smb3 |
| 6 | 5 | * |
| @@ -1,6 +1,6 @@ | ||
| 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 | 5 | * Copyright (c) 2007 Red Hat, Inc. |
| 6 | 6 | * Author(s): Jeff Layton (jlayton@redhat.com) |
| @@ -1,6 +1,6 @@ | ||
| 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 | 5 | * Copyright (c) 2007 Red Hat, Inc. |
| 6 | 6 | * Author(s): Jeff Layton (jlayton@redhat.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifs_unicode.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2000,2009 |
| 6 | 5 | * Modified by Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifsacl.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2007,2008 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifsacl.h | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2007 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifsencrypt.c | |
| 4 | 3 | * |
| 5 | 4 | * Encryption and hashing operations relating to NTLM, NTLMv2. See MS-NLMP |
| 6 | 5 | * for more detailed information |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifsfs.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002,2008 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifsfs.h | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2002, 2007 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifsglob.h | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002,2008 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1400,6 +1399,7 @@ struct cifsInodeInfo { · 1393 unmodified lines | ||
| 1400 | 1399 | #define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */ |
| 1401 | 1400 | #define CIFS_INO_LOCK (5) /* lock bit for synchronization */ |
| 1402 | 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 | 1403 | unsigned long flags; |
| 1404 | 1404 | spinlock_t writers_lock; |
| 1405 | 1405 | unsigned int writers; /* Number of writers on this inode */ |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifspdu.h | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2002,2009 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifsproto.h | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2002,2008 |
| 6 | 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 | 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 | 273 | extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx); |
| 272 | 274 | extern void cifs_put_tcp_session(struct TCP_Server_Info *server, |
| 273 | 275 | int from_reconnect); |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/cifssmb.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002,2010 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/connect.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002,2011 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1090,7 +1089,7 @@ next_pdu: · 1083 unmodified lines | ||
| 1090 | 1089 | module_put_and_exit(0); |
| 1091 | 1090 | } |
| 1092 | 1091 | |
| 1093 | −/** | |
| 1092 | +/* | |
| 1094 | 1093 | * Returns true if srcaddr isn't specified and rhs isn't specified, or |
| 1095 | 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 | 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 | 1556 | * A new IPC connection is made and stored in the session |
| 1555 | 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 | 1609 | * cifs_free_ipc - helper to release the session IPC tcon |
| 1610 | + * @ses: smb session to unmount the IPC from | |
| 1608 | 1611 | * |
| 1609 | 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 | 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 | 1864 | * This function assumes it is being called from cifs_mount() where we |
| 1860 | 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 | 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 | 2076 | * - tcon refcount is the number of mount points using the tcon. |
| 2070 | 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 | 3037 | return full_path; |
| 3031 | 3038 | } |
| 3032 | 3039 | |
| 3033 | −/** | |
| 3040 | +/* | |
| 3034 | 3041 | * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb |
| 3035 | 3042 | * |
| 3036 | 3043 | * If a referral is found, cifs_sb->ctx->mount_options will be (re-)allocated |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/dir.c | |
| 4 | 3 | * |
| 5 | 4 | * vfs operations that deal with dentries |
| 6 | 5 | * |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/dns_resolve.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) 2007 Igor Mammedov |
| 6 | 5 | * Author(s): Igor Mammedov (niallain@gmail.com) |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/dns_resolve.h -- DNS Resolver upcall management for CIFS DFS | |
| 4 | − * Handles host name to IP address resolution | |
| 3 | + * DNS Resolver upcall management for CIFS DFS | |
| 4 | + * Handles host name to IP address resolution | |
| 5 | 5 | * |
| 6 | 6 | * Copyright (c) International Business Machines Corp., 2008 |
| 7 | 7 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/export.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2007 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/file.c | |
| 4 | 3 | * |
| 5 | 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 | 882 | dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL); |
| 884 | 883 | if ((cinode->oplock == CIFS_CACHE_RHW_FLG) && |
| 885 | 884 | cinode->lease_granted && |
| 885 | + !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) && | |
| 886 | 886 | dclose) { |
| 887 | 887 | if (test_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) { |
| 888 | 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 | 1865 | cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag, |
| 1866 | 1866 | tcon->ses->server); |
| 1867 | 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 | 1870 | if (cap_unix(tcon->ses) && |
| 1870 | 1871 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && |
| @@ -1,6 +1,6 @@ | ||
| 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 | 5 | * Copyright (c) 2010 Novell, Inc. |
| 6 | 6 | * Author(s): Suresh Jayaraman <sjayaraman@suse.de> |
| @@ -1,6 +1,6 @@ | ||
| 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 | 5 | * Copyright (c) 2010 Novell, Inc. |
| 6 | 6 | * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/inode.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002,2010 |
| 6 | 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 | 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 | 1628 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
| 1630 | 1629 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
| 1631 | 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 | 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 | 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 | 2120 | rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry, |
| 2122 | 2121 | to_name); |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/ioctl.c | |
| 4 | 3 | * |
| 5 | 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 | 358 | if (pSMBFile == NULL) |
| 360 | 359 | break; |
| 361 | 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 | 363 | if (get_user(ExtAttrBits, (int __user *)arg)) { |
| 365 | 364 | rc = -EFAULT; |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/link.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002,2008 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/misc.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002,2008 |
| 6 | 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 | 735 | if (cancel_delayed_work(&cfile->deferred)) { |
| 737 | 736 | tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); |
| 738 | 737 | if (tmp_list == NULL) |
| 739 | − continue; | |
| 738 | + break; | |
| 740 | 739 | tmp_list->cfile = cfile; |
| 741 | 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 | 766 | if (cancel_delayed_work(&cfile->deferred)) { |
| 768 | 767 | tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); |
| 769 | 768 | if (tmp_list == NULL) |
| 770 | − continue; | |
| 769 | + break; | |
| 771 | 770 | tmp_list->cfile = cfile; |
| 772 | 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 | 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 | 821 | /* parses DFS refferal V3 structure |
| 786 | 822 | * caller is responsible for freeing target_nodes |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | − * fs/cifs/netmisc.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2002,2008 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/ntlmssp.h | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2002,2007 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/readdir.c | |
| 4 | 3 | * |
| 5 | 4 | * Directory search handling |
| 6 | 5 | * |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/rfc1002pdu.h | |
| 4 | 3 | * |
| 5 | 4 | * Protocol Data Unit definitions for RFC 1001/1002 support |
| 6 | 5 | * |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/sess.c | |
| 4 | 3 | * |
| 5 | 4 | * SMB/CIFS session setup handling routines |
| 6 | 5 | * |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/smb2file.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002, 2011 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com), |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/smb2glob.h | |
| 4 | 3 | * |
| 5 | 4 | * Definitions for various global variables and structures |
| 6 | 5 | * |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/smb2inode.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002, 2011 |
| 6 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/smb2misc.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002,2011 |
| 6 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/smb2pdu.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2009, 2013 |
| 6 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/smb2pdu.h | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2009, 2013 |
| 6 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/smb2proto.h | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2002, 2011 |
| 6 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/smb2status.h | |
| 4 | 3 | * |
| 5 | 4 | * SMB2 Status code (network error) definitions |
| 6 | 5 | * Definitions are from MS-ERREF |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/smb2transport.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002, 2011 |
| 6 | 5 | * Etersoft, 2012 |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1 */ |
| 2 | 2 | /* |
| 3 | − * fs/cifs/smberr.h | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2002,2004 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/transport.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (C) International Business Machines Corp., 2002,2008 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | /* |
| 3 | − * fs/cifs/winucase.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) Jeffrey Layton <jlayton@redhat.com>, 2013 |
| 6 | 5 | * |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
| 2 | 2 | /* |
| 3 | − * fs/cifs/xattr.c | |
| 4 | 3 | * |
| 5 | 4 | * Copyright (c) International Business Machines Corp., 2003, 2007 |
| 6 | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/rculist_nulls.h> |
| 15 | 15 | #include <linux/cpu.h> |
| 16 | 16 | #include <linux/tracehook.h> |
| 17 | +#include <uapi/linux/io_uring.h> | |
| 17 | 18 | |
| 18 | 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 | 177 | static void io_worker_exit(struct io_worker *worker) |
| 177 | 178 | { |
| 178 | 179 | struct io_wqe *wqe = worker->wqe; |
| 179 | − struct io_wqe_acct *acct = io_wqe_get_acct(worker); | |
| 180 | 180 | |
| 181 | 181 | if (refcount_dec_and_test(&worker->ref)) |
| 182 | 182 | complete(&worker->ref_done); |
| @@ -186,7 +186,6 @@ static void io_worker_exit(struct io_worker *worker) · 3 unmodified lines | ||
| 186 | 186 | if (worker->flags & IO_WORKER_F_FREE) |
| 187 | 187 | hlist_nulls_del_rcu(&worker->nulls_node); |
| 188 | 188 | list_del_rcu(&worker->all_list); |
| 189 | − acct->nr_workers--; | |
| 190 | 189 | preempt_disable(); |
| 191 | 190 | io_wqe_dec_running(worker); |
| 192 | 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 | 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 | 249 | * Most likely an attempt to queue unbounded work on an io_wq that |
| 253 | 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 | 253 | pr_warn_once("io-wq is not configured for unbound workers"); |
| 257 | 254 | |
| 258 | 255 | raw_spin_lock(&wqe->lock); |
| 259 | − if (acct->nr_workers < acct->max_workers) { | |
| 260 | − acct->nr_workers++; | |
| 261 | − do_create = true; | |
| 256 | + if (acct->nr_workers == acct->max_workers) { | |
| 257 | + raw_spin_unlock(&wqe->lock); | |
| 258 | + return true; | |
| 262 | 259 | } |
| 260 | + acct->nr_workers++; | |
| 263 | 261 | raw_spin_unlock(&wqe->lock); |
| 264 | − if (do_create) { | |
| 265 | − atomic_inc(&acct->nr_running); | |
| 266 | − atomic_inc(&wqe->wq->worker_refs); | |
| 267 | − return create_io_worker(wqe->wq, wqe, acct->index); | |
| 268 | − } | |
| 269 | − | |
| 270 | − return true; | |
| 262 | + atomic_inc(&acct->nr_running); | |
| 263 | + atomic_inc(&wqe->wq->worker_refs); | |
| 264 | + return create_io_worker(wqe->wq, wqe, acct->index); | |
| 271 | 265 | } |
| 272 | 266 | |
| 273 | 267 | static void io_wqe_inc_running(struct io_worker *worker) |
| @@ -574,6 +568,7 @@ loop: · 300 unmodified lines | ||
| 574 | 568 | } |
| 575 | 569 | /* timed out, exit unless we're the last worker */ |
| 576 | 570 | if (last_timeout && acct->nr_workers > 1) { |
| 571 | + acct->nr_workers--; | |
| 577 | 572 | raw_spin_unlock(&wqe->lock); |
| 578 | 573 | __set_current_state(TASK_RUNNING); |
| 579 | 574 | break; |
| @@ -1287,6 +1282,10 @@ int io_wq_max_workers(struct io_wq *wq, int *new_count) · 707 unmodified lines | ||
| 1287 | 1282 | { |
| 1288 | 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 | 1289 | for (i = 0; i < 2; i++) { |
| 1291 | 1290 | if (new_count[i] > task_rlimit(current, RLIMIT_NPROC)) |
| 1292 | 1291 | new_count[i] = task_rlimit(current, RLIMIT_NPROC); |
| @@ -712,6 +712,7 @@ struct io_async_rw { · 711 unmodified lines | ||
| 712 | 712 | struct iovec fast_iov[UIO_FASTIOV]; |
| 713 | 713 | const struct iovec *free_iovec; |
| 714 | 714 | struct iov_iter iter; |
| 715 | + struct iov_iter_state iter_state; | |
| 715 | 716 | size_t bytes_done; |
| 716 | 717 | struct wait_page_queue wpq; |
| 717 | 718 | }; |
| @@ -735,7 +736,6 @@ enum { · 17 unmodified lines | ||
| 735 | 736 | REQ_F_BUFFER_SELECTED_BIT, |
| 736 | 737 | REQ_F_COMPLETE_INLINE_BIT, |
| 737 | 738 | REQ_F_REISSUE_BIT, |
| 738 | − REQ_F_DONT_REISSUE_BIT, | |
| 739 | 739 | REQ_F_CREDS_BIT, |
| 740 | 740 | REQ_F_REFCOUNT_BIT, |
| 741 | 741 | REQ_F_ARM_LTIMEOUT_BIT, |
| @@ -782,8 +782,6 @@ enum { · 40 unmodified lines | ||
| 782 | 782 | REQ_F_COMPLETE_INLINE = BIT(REQ_F_COMPLETE_INLINE_BIT), |
| 783 | 783 | /* caller should reissue async */ |
| 784 | 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 | 785 | /* supports async reads */ |
| 788 | 786 | REQ_F_NOWAIT_READ = BIT(REQ_F_NOWAIT_READ_BIT), |
| 789 | 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 | 2442 | req = list_first_entry(done, struct io_kiocb, inflight_entry); |
| 2445 | 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 | 2445 | __io_cqring_fill_event(ctx, req->user_data, req->result, |
| 2455 | 2446 | io_put_rw_kbuf(req)); |
| 2456 | 2447 | (*nr_events)++; |
| @@ -2613,8 +2604,7 @@ static bool io_resubmit_prep(struct io_kiocb *req) · 156 unmodified lines | ||
| 2613 | 2604 | |
| 2614 | 2605 | if (!rw) |
| 2615 | 2606 | return !io_req_prep_async(req); |
| 2616 | − /* may have left rw->iter inconsistent on -EIOCBQUEUED */ | |
| 2617 | − iov_iter_revert(&rw->iter, req->result - iov_iter_count(&rw->iter)); | |
| 2607 | + iov_iter_restore(&rw->iter, &rw->iter_state); | |
| 2618 | 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 | 2704 | if (kiocb->ki_flags & IOCB_WRITE) |
| 2715 | 2705 | kiocb_end_write(req); |
| 2716 | 2706 | if (unlikely(res != req->result)) { |
| 2717 | − if (!(res == -EAGAIN && io_rw_should_reissue(req) && | |
| 2718 | − io_resubmit_prep(req))) { | |
| 2719 | − req_set_fail(req); | |
| 2720 | − req->flags |= REQ_F_DONT_REISSUE; | |
| 2707 | + if (res == -EAGAIN && io_rw_should_reissue(req)) { | |
| 2708 | + req->flags |= REQ_F_REISSUE; | |
| 2709 | + return; | |
| 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 | 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 | 2838 | struct io_ring_ctx *ctx = req->ctx; |
| 2849 | 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 | 2855 | if (unlikely(ret)) |
| 2866 | 2856 | return ret; |
| 2867 | 2857 | |
| 2868 | − /* don't allow async punt for O_NONBLOCK or RWF_NOWAIT */ | |
| 2869 | − if ((kiocb->ki_flags & IOCB_NOWAIT) || (file->f_flags & O_NONBLOCK)) | |
| 2858 | + /* | |
| 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 | 2865 | req->flags |= REQ_F_NOWAIT; |
| 2871 | 2866 | |
| 2872 | 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 | 2927 | struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw.kiocb); |
| 2933 | 2928 | struct io_async_rw *io = req->async_data; |
| 2934 | − bool check_reissue = kiocb->ki_complete == io_complete_rw; | |
| 2935 | 2929 | |
| 2936 | 2930 | /* add previously done IO, if any */ |
| 2937 | 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 | 2938 | if (req->flags & REQ_F_CUR_POS) |
| 2945 | 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 | 2941 | __io_complete_rw(req, ret, 0, issue_flags); |
| 2948 | 2942 | else |
| 2949 | 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 | 2946 | req->flags &= ~REQ_F_REISSUE; |
| 2953 | 2947 | if (io_resubmit_prep(req)) { |
| 2954 | 2948 | io_req_task_queue_reissue(req); |
| 2955 | 2949 | } else { |
| 2950 | + unsigned int cflags = io_put_rw_kbuf(req); | |
| 2951 | + struct io_ring_ctx *ctx = req->ctx; | |
| 2952 | + | |
| 2956 | 2953 | req_set_fail(req); |
| 2957 | − __io_req_complete(req, issue_flags, ret, | |
| 2958 | − io_put_rw_kbuf(req)); | |
| 2954 | + if (issue_flags & IO_URING_F_NONBLOCK) { | |
| 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 | 3265 | ret = nr; |
| 3264 | 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 | 3274 | ret += nr; |
| 3267 | 3275 | if (nr != iovec.iov_len) |
| 3268 | 3276 | break; |
| 3269 | − req->rw.len -= nr; | |
| 3270 | − req->rw.addr += nr; | |
| 3271 | − iov_iter_advance(iter, nr); | |
| 3272 | 3277 | } |
| 3273 | 3278 | |
| 3274 | 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 | 3320 | if (!force && !io_op_defs[req->opcode].needs_async_setup) |
| 3316 | 3321 | return 0; |
| 3317 | 3322 | if (!req->async_data) { |
| 3323 | + struct io_async_rw *iorw; | |
| 3324 | + | |
| 3318 | 3325 | if (io_alloc_async_data(req)) { |
| 3319 | 3326 | kfree(iovec); |
| 3320 | 3327 | return -ENOMEM; |
| 3321 | 3328 | } |
| 3322 | 3329 | |
| 3323 | 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 | 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 | 3349 | iorw->free_iovec = iov; |
| 3340 | 3350 | if (iov) |
| 3341 | 3351 | req->flags |= REQ_F_NEED_CLEANUP; |
| 3352 | + iov_iter_save_state(&iorw->iter, &iorw->iter_state); | |
| 3342 | 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 | 3358 | if (unlikely(!(req->file->f_mode & FMODE_READ))) |
| 3348 | 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 | 3453 | struct kiocb *kiocb = &req->rw.kiocb; |
| 3443 | 3454 | struct iov_iter __iter, *iter = &__iter; |
| 3444 | 3455 | struct io_async_rw *rw = req->async_data; |
| 3445 | − ssize_t io_size, ret, ret2; | |
| 3446 | 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 | 3460 | if (rw) { |
| 3449 | 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 | 3469 | iovec = NULL; |
| 3451 | 3470 | } else { |
| 3452 | 3471 | ret = io_import_iovec(READ, req, &iovec, iter, !force_nonblock); |
| 3453 | 3472 | if (ret < 0) |
| 3454 | 3473 | return ret; |
| 3474 | + state = &__state; | |
| 3475 | + iov_iter_save_state(iter, state); | |
| 3455 | 3476 | } |
| 3456 | − io_size = iov_iter_count(iter); | |
| 3457 | − req->result = io_size; | |
| 3477 | + req->result = iov_iter_count(iter); | |
| 3458 | 3478 | |
| 3459 | 3479 | /* Ensure we clear previously set non-block flag */ |
| 3460 | 3480 | if (!force_nonblock) |
| @@ -3468,7 +3488,7 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags) · 7 unmodified lines | ||
| 3468 | 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 | 3492 | if (unlikely(ret)) { |
| 3473 | 3493 | kfree(iovec); |
| 3474 | 3494 | return ret; |
| @@ -3484,30 +3504,49 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags) · 9 unmodified lines | ||
| 3484 | 3504 | /* no retry on NONBLOCK nor RWF_NOWAIT */ |
| 3485 | 3505 | if (req->flags & REQ_F_NOWAIT) |
| 3486 | 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 | 3507 | ret = 0; |
| 3491 | 3508 | } else if (ret == -EIOCBQUEUED) { |
| 3492 | 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 | 3511 | (req->flags & REQ_F_NOWAIT) || !need_read_all(req)) { |
| 3495 | 3512 | /* read all, failed, already did sync or don't want to retry */ |
| 3496 | 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 | 3523 | ret2 = io_setup_async_rw(req, iovec, inline_vecs, iter, true); |
| 3500 | 3524 | if (ret2) |
| 3501 | 3525 | return ret2; |
| 3502 | 3526 | |
| 3503 | 3527 | iovec = NULL; |
| 3504 | 3528 | rw = req->async_data; |
| 3505 | − /* now use our persistent iterator, if we aren't already */ | |
| 3506 | − iter = &rw->iter; | |
| 3529 | + /* | |
| 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 | 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 | 3547 | rw->bytes_done += ret; |
| 3548 | + iov_iter_save_state(iter, state); | |
| 3549 | + | |
| 3511 | 3550 | /* if we can retry, do so with the callbacks armed */ |
| 3512 | 3551 | if (!io_rw_should_retry(req)) { |
| 3513 | 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 | 3564 | return 0; |
| 3526 | 3565 | /* we got some bytes, but not all. retry. */ |
| 3527 | 3566 | kiocb->ki_flags &= ~IOCB_WAITQ; |
| 3528 | − } while (ret > 0 && ret < io_size); | |
| 3567 | + iov_iter_restore(iter, state); | |
| 3568 | + } while (ret > 0); | |
| 3529 | 3569 | done: |
| 3530 | 3570 | kiocb_done(kiocb, ret, issue_flags); |
| 3531 | 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 | 3580 | if (unlikely(!(req->file->f_mode & FMODE_WRITE))) |
| 3541 | 3581 | return -EBADF; |
| 3542 | − return io_prep_rw(req, sqe); | |
| 3582 | + return io_prep_rw(req, sqe, WRITE); | |
| 3543 | 3583 | } |
| 3544 | 3584 | |
| 3545 | 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 | 3588 | struct kiocb *kiocb = &req->rw.kiocb; |
| 3549 | 3589 | struct iov_iter __iter, *iter = &__iter; |
| 3550 | 3590 | struct io_async_rw *rw = req->async_data; |
| 3551 | − ssize_t ret, ret2, io_size; | |
| 3552 | 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 | 3595 | if (rw) { |
| 3555 | 3596 | iter = &rw->iter; |
| 3597 | + state = &rw->iter_state; | |
| 3598 | + iov_iter_restore(iter, state); | |
| 3556 | 3599 | iovec = NULL; |
| 3557 | 3600 | } else { |
| 3558 | 3601 | ret = io_import_iovec(WRITE, req, &iovec, iter, !force_nonblock); |
| 3559 | 3602 | if (ret < 0) |
| 3560 | 3603 | return ret; |
| 3604 | + state = &__state; | |
| 3605 | + iov_iter_save_state(iter, state); | |
| 3561 | 3606 | } |
| 3562 | − io_size = iov_iter_count(iter); | |
| 3563 | − req->result = io_size; | |
| 3607 | + req->result = iov_iter_count(iter); | |
| 3608 | + ret2 = 0; | |
| 3564 | 3609 | |
| 3565 | 3610 | /* Ensure we clear previously set non-block flag */ |
| 3566 | 3611 | if (!force_nonblock) |
| @@ -3577,7 +3622,7 @@ static int io_write(struct io_kiocb *req, unsigned int issue_flags) · 10 unmodified lines | ||
| 3577 | 3622 | (req->flags & REQ_F_ISREG)) |
| 3578 | 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 | 3626 | if (unlikely(ret)) |
| 3582 | 3627 | goto out_free; |
| 3583 | 3628 | |
| @@ -3624,9 +3669,9 @@ done: · 40 unmodified lines | ||
| 3624 | 3669 | kiocb_done(kiocb, ret2, issue_flags); |
| 3625 | 3670 | } else { |
| 3626 | 3671 | copy_iov: |
| 3627 | − /* some cases will consume bytes even on error returns */ | |
| 3628 | − iov_iter_reexpand(iter, iter->count + iter->truncated); | |
| 3629 | − iov_iter_revert(iter, io_size - iov_iter_count(iter)); | |
| 3672 | + iov_iter_restore(iter, state); | |
| 3673 | + if (ret2 > 0) | |
| 3674 | + iov_iter_advance(iter, ret2); | |
| 3630 | 3675 | ret = io_setup_async_rw(req, iovec, inline_vecs, iter, false); |
| 3631 | 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 | 7560 | break; |
| 7516 | 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 | 7571 | if (sig) { |
| 7519 | 7572 | #ifdef CONFIG_COMPAT |
| 7520 | 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 | 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 | 7584 | init_waitqueue_func_entry(&iowq.wq, io_wake_function); |
| 7540 | 7585 | iowq.wq.private = current; |
| 7541 | 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 | 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 | 8347 | static int io_install_fixed_file(struct io_kiocb *req, struct file *file, |
| 8288 | 8348 | unsigned int issue_flags, u32 slot_index) |
| 8289 | 8349 | { |
| 8290 | 8350 | struct io_ring_ctx *ctx = req->ctx; |
| 8291 | 8351 | bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; |
| 8352 | + bool needs_switch = false; | |
| 8292 | 8353 | struct io_fixed_file *file_slot; |
| 8293 | 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 | 8366 | slot_index = array_index_nospec(slot_index, ctx->nr_user_files); |
| 8306 | 8367 | file_slot = io_fixed_file_slot(&ctx->file_table, slot_index); |
| 8307 | − ret = -EBADF; | |
| 8308 | − if (file_slot->file_ptr) | |
| 8309 | − goto err; | |
| 8368 | + | |
| 8369 | + if (file_slot->file_ptr) { | |
| 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 | 8385 | *io_get_tag_slot(ctx->file_data, slot_index) = 0; |
| 8312 | 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 | 8393 | ret = 0; |
| 8320 | 8394 | err: |
| 8395 | + if (needs_switch) | |
| 8396 | + io_rsrc_node_switch(ctx, ctx->file_data); | |
| 8321 | 8397 | io_ring_submit_unlock(ctx, !force_nonblock); |
| 8322 | 8398 | if (ret) |
| 8323 | 8399 | fput(file); |
| 8324 | 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 | 8403 | static int __io_sqe_files_update(struct io_ring_ctx *ctx, |
| 8343 | 8404 | struct io_uring_rsrc_update2 *up, |
| 8344 | 8405 | unsigned nr_args) |
| @@ -10560,10 +10621,12 @@ static int io_register_iowq_max_workers(struct io_ring_ctx *ctx, · 2215 unmodified lines | ||
| 10560 | 10621 | * ordering. Fine to drop uring_lock here, we hold |
| 10561 | 10622 | * a ref to the ctx. |
| 10562 | 10623 | */ |
| 10624 | + refcount_inc(&sqd->refs); | |
| 10563 | 10625 | mutex_unlock(&ctx->uring_lock); |
| 10564 | 10626 | mutex_lock(&sqd->lock); |
| 10565 | 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 | 10631 | } else { |
| 10569 | 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 | 10640 | if (ret) |
| 10578 | 10641 | goto err; |
| 10579 | 10642 | |
| 10580 | − if (sqd) | |
| 10643 | + if (sqd) { | |
| 10581 | 10644 | mutex_unlock(&sqd->lock); |
| 10645 | + io_put_sq_data(sqd); | |
| 10646 | + } | |
| 10582 | 10647 | |
| 10583 | 10648 | if (copy_to_user(arg, new_count, sizeof(new_count))) |
| 10584 | 10649 | return -EFAULT; |
| 10585 | 10650 | |
| 10586 | 10651 | return 0; |
| 10587 | 10652 | err: |
| 10588 | − if (sqd) | |
| 10653 | + if (sqd) { | |
| 10589 | 10654 | mutex_unlock(&sqd->lock); |
| 10655 | + io_put_sq_data(sqd); | |
| 10656 | + } | |
| 10590 | 10657 | return ret; |
| 10591 | 10658 | } |
| 10592 | 10659 | |
| @@ -191,19 +191,77 @@ int get_nlink(struct kstat *st) · 190 unmodified lines | ||
| 191 | 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 | 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) | |
| 200 | −{ | |
| 201 | − int len = strlen(path); | |
| 207 | + out_path = kzalloc(path_len + 2, GFP_KERNEL); | |
| 208 | + if (!out_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] == '/') { | |
| 204 | − path[len - 1] = '\0'; | |
| 205 | − len--; | |
| 206 | − } | |
| 244 | + } | |
| 245 | + | |
| 246 | + if (name_len != 0 && | |
| 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 | 267 | void ksmbd_conv_path_to_windows(char *path) |
| @@ -16,8 +16,7 @@ int ksmbd_validate_filename(char *filename); · 15 unmodified lines | ||
| 16 | 16 | int parse_stream_name(char *filename, char **stream_name, int *s_type); |
| 17 | 17 | char *convert_to_nt_pathname(char *filename, char *sharepath); |
| 18 | 18 | int get_nlink(struct kstat *st); |
| 19 | −void ksmbd_conv_path_to_unix(char *path); | |
| 20 | −void ksmbd_strip_last_slash(char *path); | |
| 19 | +char *ksmbd_conv_path_to_unix(char *path); | |
| 21 | 20 | void ksmbd_conv_path_to_windows(char *path); |
| 22 | 21 | char *ksmbd_extract_sharename(char *treename); |
| 23 | 22 | char *convert_to_unix_name(struct ksmbd_share_config *share, char *name); |
| @@ -634,7 +634,7 @@ static char * · 633 unmodified lines | ||
| 634 | 634 | smb2_get_name(struct ksmbd_share_config *share, const char *src, |
| 635 | 635 | const int maxlen, struct nls_table *local_nls) |
| 636 | 636 | { |
| 637 | − char *name, *unixname; | |
| 637 | + char *name, *norm_name, *unixname; | |
| 638 | 638 | |
| 639 | 639 | name = smb_strndup_from_utf16(src, maxlen, 1, local_nls); |
| 640 | 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 | 645 | /* change it to absolute unix name */ |
| 646 | − ksmbd_conv_path_to_unix(name); | |
| 647 | − ksmbd_strip_last_slash(name); | |
| 648 | − | |
| 649 | − unixname = convert_to_unix_name(share, name); | |
| 646 | + norm_name = ksmbd_conv_path_to_unix(name); | |
| 647 | + if (IS_ERR(norm_name)) { | |
| 648 | + kfree(name); | |
| 649 | + return norm_name; | |
| 650 | + } | |
| 650 | 651 | kfree(name); |
| 652 | + | |
| 653 | + unixname = convert_to_unix_name(share, norm_name); | |
| 654 | + kfree(norm_name); | |
| 651 | 655 | if (!unixname) { |
| 652 | 656 | pr_err("can not convert absolute name\n"); |
| 653 | 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 | 4045 | path = &fp->filp->f_path; |
| 4042 | 4046 | /* single EA entry is requested with given user.* name */ |
| 4043 | 4047 | if (req->InputBufferLength) { |
| 4048 | + if (le32_to_cpu(req->InputBufferLength) < | |
| 4049 | + sizeof(struct smb2_ea_info_req)) | |
| 4050 | + return -EINVAL; | |
| 4051 | + | |
| 4044 | 4052 | ea_req = (struct smb2_ea_info_req *)req->Buffer; |
| 4045 | 4053 | } else { |
| 4046 | 4054 | /* need to send all EAs, if no specific EA is requested*/ |
| @@ -20,7 +20,6 @@ · 19 unmodified lines | ||
| 20 | 20 | #define SUBMOD_NAME "smb_direct" |
| 21 | 21 | |
| 22 | 22 | #include <linux/kthread.h> |
| 23 | −#include <linux/rwlock.h> | |
| 24 | 23 | #include <linux/list.h> |
| 25 | 24 | #include <linux/mempool.h> |
| 26 | 25 | #include <linux/highmem.h> |
| @@ -134,18 +134,9 @@ svcxdr_decode_owner(struct xdr_stream *xdr, struct xdr_netobj *obj) · 133 unmodified lines | ||
| 134 | 134 | static inline bool |
| 135 | 135 | svcxdr_encode_owner(struct xdr_stream *xdr, const struct xdr_netobj *obj) |
| 136 | 136 | { |
| 137 | − unsigned int quadlen = XDR_QUADLEN(obj->len); | |
| 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) | |
| 137 | + if (obj->len > XDR_MAX_NETOBJ) | |
| 144 | 138 | return false; |
| 145 | − p[quadlen - 1] = 0; /* XDR pad */ | |
| 146 | − memcpy(p, obj->data, obj->len); | |
| 147 | − | |
| 148 | − return true; | |
| 139 | + return xdr_stream_encode_opaque(xdr, obj->data, obj->len) > 0; | |
| 149 | 140 | } |
| 150 | 141 | |
| 151 | 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 | 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 | 3575 | struct nfs4_client *clp = session->se_client; |
| 3576 | 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 | 3593 | else |
| 3594 | 3594 | status = nfserr_inval; |
| 3595 | 3595 | spin_unlock(&clp->cl_lock); |
| 3596 | + if (status == nfs_ok && conn) | |
| 3597 | + *conn = c; | |
| 3596 | 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 | 3619 | status = nfserr_wrong_cred; |
| 3618 | 3620 | if (!nfsd4_mach_creds_match(session->se_client, rqstp)) |
| 3619 | 3621 | goto out; |
| 3620 | − status = nfsd4_match_existing_connection(rqstp, session, bcts->dir); | |
| 3621 | − if (status == nfs_ok || status == nfserr_inval) | |
| 3622 | + status = nfsd4_match_existing_connection(rqstp, session, | |
| 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 | 3632 | goto out; |
| 3623 | 3633 | status = nfsd4_map_bcts_dir(&bcts->dir); |
| 3624 | 3634 | if (status) |
| @@ -20,12 +20,33 @@ · 19 unmodified lines | ||
| 20 | 20 | * depending on the status field in the last byte. The |
| 21 | 21 | * first byte is where the name start either way, and a |
| 22 | 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 | 45 | union qnx4_directory_entry { |
| 25 | 46 | struct { |
| 26 | − char de_name; | |
| 27 | − char de_pad[62]; | |
| 28 | − char de_status; | |
| 47 | + const char de_name[48]; | |
| 48 | + u8 de_pad[15]; | |
| 49 | + u8 de_status; | |
| 29 | 50 | }; |
| 30 | 51 | struct qnx4_inode_entry inode; |
| 31 | 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 | 74 | ix = (ctx->pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK; |
| 54 | 75 | for (; ix < QNX4_INODES_PER_BLOCK; ix++, ctx->pos += QNX4_DIR_ENTRY_SIZE) { |
| 55 | 76 | union qnx4_directory_entry *de; |
| 56 | − const char *name; | |
| 57 | 77 | |
| 58 | 78 | offset = ix * QNX4_DIR_ENTRY_SIZE; |
| 59 | 79 | de = (union qnx4_directory_entry *) (bh->b_data + offset); |
| 60 | 80 | |
| 61 | − if (!de->de_name) | |
| 81 | + if (!de->de_name[0]) | |
| 62 | 82 | continue; |
| 63 | 83 | if (!(de->de_status & (QNX4_FILE_USED|QNX4_FILE_LINK))) |
| 64 | 84 | continue; |
| 65 | 85 | if (!(de->de_status & QNX4_FILE_LINK)) { |
| 66 | 86 | size = sizeof(de->inode.di_fname); |
| 67 | − name = de->inode.di_fname; | |
| 68 | 87 | ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1; |
| 69 | 88 | } else { |
| 70 | 89 | size = sizeof(de->link.dl_fname); |
| 71 | − name = de->link.dl_fname; | |
| 72 | 90 | ino = ( le32_to_cpu(de->link.dl_inode_blk) - 1 ) * |
| 73 | 91 | QNX4_INODES_PER_BLOCK + |
| 74 | 92 | de->link.dl_inode_ndx; |
| 75 | 93 | } |
| 76 | − size = strnlen(name, size); | |
| 94 | + size = strnlen(de->de_name, size); | |
| 77 | 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 | 97 | brelse(bh); |
| 80 | 98 | return 0; |
| 81 | 99 | } |
| @@ -1,6 +1,6 @@ | ||
| 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 | 5 | * Copyright (c) International Business Machines Corp., 2002,2013 |
| 6 | 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 | 1023 | port &= IO_SPACE_LIMIT; |
| 1024 | 1024 | return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port; |
| 1025 | 1025 | } |
| 1026 | −#define __pci_ioport_unmap __pci_ioport_unmap | |
| 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 | −} | |
| 1026 | +#define ARCH_HAS_GENERIC_IOPORT_MAP | |
| 1036 | 1027 | #endif |
| 1037 | 1028 | |
| 1038 | 1029 | #ifndef ioport_unmap |
| @@ -1048,21 +1039,10 @@ extern void ioport_unmap(void __iomem *p); · 9 unmodified lines | ||
| 1048 | 1039 | #endif /* CONFIG_HAS_IOPORT_MAP */ |
| 1049 | 1040 | |
| 1050 | 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 | 1042 | #ifndef pci_iounmap |
| 1059 | −#define pci_iounmap pci_iounmap | |
| 1060 | −static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p) | |
| 1061 | −{ | |
| 1062 | − __pci_ioport_unmap(p); | |
| 1063 | −} | |
| 1043 | +#define ARCH_WANTS_GENERIC_PCI_IOUNMAP | |
| 1044 | +#endif | |
| 1064 | 1045 | #endif |
| 1065 | −#endif /* CONFIG_GENERIC_IOMAP */ | |
| 1066 | 1046 | |
| 1067 | 1047 | #ifndef xlate_dev_mem_ptr |
| 1068 | 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 | 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 | 113 | #include <asm-generic/pci_iomap.h> |
| 124 | 114 | |
| 125 | 115 | #endif |
| @@ -18,6 +18,7 @@ extern void __iomem *pci_iomap_range(struct pci_dev *dev, int bar, · 17 unmodified lines | ||
| 18 | 18 | extern void __iomem *pci_iomap_wc_range(struct pci_dev *dev, int bar, |
| 19 | 19 | unsigned long offset, |
| 20 | 20 | unsigned long maxlen); |
| 21 | +extern void pci_iounmap(struct pci_dev *dev, void __iomem *); | |
| 21 | 22 | /* Create a virtual mapping cookie for a port on a given PCI device. |
| 22 | 23 | * Do not call this directly, it exists to make it easier for architectures |
| 23 | 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 | 52 | return NULL; |
| 52 | 53 | } |
| 54 | +static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) | |
| 55 | +{ } | |
| 53 | 56 | #endif |
| 54 | 57 | |
| 55 | 58 | #endif /* __ASM_GENERIC_PCI_IOMAP_H */ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0 |
| 2 | − * Copyright 2019-2021 NXP Semiconductors | |
| 2 | + * Copyright 2019-2021 NXP | |
| 3 | 3 | */ |
| 4 | 4 | |
| 5 | 5 | #ifndef _NET_DSA_TAG_OCELOT_H |
| @@ -80,6 +80,9 @@ struct mdio_driver { · 79 unmodified lines | ||
| 80 | 80 | |
| 81 | 81 | /* Clears up any memory if needed */ |
| 82 | 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 | 88 | static inline struct mdio_driver * |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: BSD-3-Clause |
| 2 | − * Copyright (c) 2016-2018, NXP Semiconductors | |
| 2 | + * Copyright 2016-2018 NXP | |
| 3 | 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 4 | 4 | */ |
| 5 | 5 | #ifndef _LINUX_PACKING_H |
| @@ -1471,6 +1471,7 @@ struct task_struct { · 1470 unmodified lines | ||
| 1471 | 1471 | mce_whole_page : 1, |
| 1472 | 1472 | __mce_reserved : 62; |
| 1473 | 1473 | struct callback_head mce_kill_me; |
| 1474 | + int mce_count; | |
| 1474 | 1475 | #endif |
| 1475 | 1476 | |
| 1476 | 1477 | #ifdef CONFIG_KRETPROBES |
| @@ -27,6 +27,12 @@ enum iter_type { · 26 unmodified lines | ||
| 27 | 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 | 36 | struct iov_iter { |
| 31 | 37 | u8 iter_type; |
| 32 | 38 | bool data_source; |
| @@ -47,7 +53,6 @@ struct iov_iter { · 14 unmodified lines | ||
| 47 | 53 | }; |
| 48 | 54 | loff_t xarray_start; |
| 49 | 55 | }; |
| 50 | − size_t truncated; | |
| 51 | 56 | }; |
| 52 | 57 | |
| 53 | 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 | 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 | 71 | static inline bool iter_is_iovec(const struct iov_iter *i) |
| 59 | 72 | { |
| 60 | 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 | 246 | ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages, |
| 234 | 247 | size_t maxsize, size_t *start); |
| 235 | 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 | 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 | 269 | * conversion in assignement is by definition greater than all |
| 256 | 270 | * values of size_t, including old i->count. |
| 257 | 271 | */ |
| 258 | − if (i->count > count) { | |
| 259 | − i->truncated += i->count - count; | |
| 272 | + if (i->count > count) | |
| 260 | 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 | 280 | static inline void iov_iter_reexpand(struct iov_iter *i, size_t count) |
| 269 | 281 | { |
| 270 | − i->truncated -= count - i->count; | |
| 271 | 282 | i->count = count; |
| 272 | 283 | } |
| 273 | 284 | |
| @@ -585,8 +585,16 @@ struct dsa_switch_ops { · 584 unmodified lines | ||
| 585 | 585 | int (*change_tag_protocol)(struct dsa_switch *ds, int port, |
| 586 | 586 | enum dsa_tag_protocol proto); |
| 587 | 587 | |
| 588 | + /* Optional switch-wide initialization and destruction methods */ | |
| 588 | 589 | int (*setup)(struct dsa_switch *ds); |
| 589 | 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 | 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 | 1055 | void dsa_unregister_switch(struct dsa_switch *ds); |
| 1048 | 1056 | int dsa_register_switch(struct dsa_switch *ds); |
| 1057 | +void dsa_switch_shutdown(struct dsa_switch *ds); | |
| 1049 | 1058 | struct dsa_switch *dsa_switch_find(int tree_index, int sw_index); |
| 1050 | 1059 | #ifdef CONFIG_PM_SLEEP |
| 1051 | 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 | 1628 | release_sock(sk); |
| 1629 | 1629 | __release(&sk->sk_lock.slock); |
| 1630 | 1630 | } else { |
| 1631 | + mutex_release(&sk->sk_lock.dep_map, _RET_IP_); | |
| 1631 | 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 | 307 | enum afs_cb_break_reason { |
| 308 | 308 | afs_cb_break_no_break, |
| 309 | + afs_cb_break_no_promise, | |
| 309 | 310 | afs_cb_break_for_callback, |
| 310 | 311 | afs_cb_break_for_deleted, |
| 311 | 312 | afs_cb_break_for_lapsed, |
| 313 | + afs_cb_break_for_s_reinit, | |
| 312 | 314 | afs_cb_break_for_unlink, |
| 313 | − afs_cb_break_for_vsbreak, | |
| 315 | + afs_cb_break_for_v_break, | |
| 314 | 316 | afs_cb_break_for_volume_callback, |
| 315 | 317 | afs_cb_break_for_zap, |
| 316 | 318 | }; |
| @@ -602,11 +604,13 @@ enum afs_cb_break_reason { · 285 unmodified lines | ||
| 602 | 604 | |
| 603 | 605 | #define afs_cb_break_reasons \ |
| 604 | 606 | EM(afs_cb_break_no_break, "no-break") \ |
| 607 | + EM(afs_cb_break_no_promise, "no-promise") \ | |
| 605 | 608 | EM(afs_cb_break_for_callback, "break-cb") \ |
| 606 | 609 | EM(afs_cb_break_for_deleted, "break-del") \ |
| 607 | 610 | EM(afs_cb_break_for_lapsed, "break-lapsed") \ |
| 611 | + EM(afs_cb_break_for_s_reinit, "s-reinit") \ | |
| 608 | 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 | 614 | EM(afs_cb_break_for_volume_callback, "break-v-cb") \ |
| 611 | 615 | E_(afs_cb_break_for_zap, "break-zap") |
| 612 | 616 | |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */ |
| 2 | 2 | /* |
| 3 | − * include/uapi/linux/cifs/cifs_mount.h | |
| 4 | 3 | * |
| 5 | 4 | * Author(s): Scott Lovenberg (scott.lovenberg@gmail.com) |
| 6 | 5 | * |
| @@ -317,13 +317,19 @@ enum { · 316 unmodified lines | ||
| 317 | 317 | IORING_REGISTER_IOWQ_AFF = 17, |
| 318 | 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 | 321 | IORING_REGISTER_IOWQ_MAX_WORKERS = 19, |
| 322 | 322 | |
| 323 | 323 | /* this goes last */ |
| 324 | 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 | 333 | /* deprecated, see struct io_uring_rsrc_update */ |
| 328 | 334 | struct io_uring_files_update { |
| 329 | 335 | __u32 offset; |
| @@ -1242,7 +1242,7 @@ trace_initcall_start_cb(void *data, initcall_t fn) · 1241 unmodified lines | ||
| 1242 | 1242 | { |
| 1243 | 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 | 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 | 1256 | rettime = ktime_get(); |
| 1257 | 1257 | delta = ktime_sub(rettime, *calltime); |
| 1258 | 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", | |
| 1260 | − fn, ret, duration, irqs_disabled()); | |
| 1259 | + printk(KERN_DEBUG "initcall %pS returned %d after %lld usecs\n", | |
| 1260 | + fn, ret, duration); | |
| 1261 | 1261 | } |
| 1262 | 1262 | |
| 1263 | 1263 | static ktime_t initcall_calltime; |
| @@ -567,7 +567,8 @@ static void add_dma_entry(struct dma_debug_entry *entry) · 566 unmodified lines | ||
| 567 | 567 | pr_err("cacheline tracking ENOMEM, dma-debug disabled\n"); |
| 568 | 568 | global_disable = true; |
| 569 | 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 | 207 | * dma_map_sg_attrs - Map the given buffer for DMA |
| 208 | 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 | 211 | * @dir: DMA direction |
| 211 | 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 | 10193 | return; |
| 10194 | 10194 | |
| 10195 | 10195 | if (ifh->nr_file_filters) { |
| 10196 | − mm = get_task_mm(event->ctx->task); | |
| 10196 | + mm = get_task_mm(task); | |
| 10197 | 10197 | if (!mm) |
| 10198 | 10198 | goto restart; |
| 10199 | 10199 | |
| @@ -41,6 +41,12 @@ · 40 unmodified lines | ||
| 41 | 41 | * The risk of writer starvation is there, but the pathological use cases |
| 42 | 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 | 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 | 59 | * set. |
| 54 | 60 | */ |
| 55 | 61 | for (r = atomic_read(&rwb->readers); r < 0;) { |
| 62 | + /* Fully-ordered if cmpxchg() succeeds, provides ACQUIRE */ | |
| 56 | 63 | if (likely(atomic_try_cmpxchg(&rwb->readers, &r, r + 1))) |
| 57 | 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 | 170 | * rwb->readers can only hit 0 when a writer is waiting for the |
| 164 | 171 | * active readers to leave the critical section. |
| 172 | + * | |
| 173 | + * dec_and_test() is fully ordered, provides RELEASE. | |
| 165 | 174 | */ |
| 166 | 175 | if (unlikely(atomic_dec_and_test(&rwb->readers))) |
| 167 | 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 | 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 | 189 | raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); |
| 177 | 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 | 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 | 229 | static int __sched rwbase_write_lock(struct rwbase_rt *rwb, |
| 200 | 230 | unsigned int state) |
| 201 | 231 | { |
| @@ -210,34 +240,30 @@ static int __sched rwbase_write_lock(struct rwbase_rt *rwb, · 8 unmodified lines | ||
| 210 | 240 | atomic_sub(READER_BIAS, &rwb->readers); |
| 211 | 241 | |
| 212 | 242 | raw_spin_lock_irqsave(&rtm->wait_lock, flags); |
| 213 | − /* | |
| 214 | − * set_current_state() for rw_semaphore | |
| 215 | − * current_save_and_set_rtlock_wait_state() for rwlock | |
| 216 | − */ | |
| 217 | − rwbase_set_and_save_current_state(state); | |
| 243 | + if (__rwbase_write_trylock(rwb)) | |
| 244 | + goto out_unlock; | |
| 218 | 245 | |
| 219 | − /* Block until all readers have left the critical section. */ | |
| 220 | − for (; atomic_read(&rwb->readers);) { | |
| 246 | + rwbase_set_and_save_current_state(state); | |
| 247 | + for (;;) { | |
| 221 | 248 | /* Optimized out for rwlocks */ |
| 222 | 249 | if (rwbase_signal_pending_state(state, current)) { |
| 223 | − __set_current_state(TASK_RUNNING); | |
| 250 | + rwbase_restore_current_state(); | |
| 224 | 251 | __rwbase_write_unlock(rwb, 0, flags); |
| 225 | 252 | return -EINTR; |
| 226 | 253 | } |
| 254 | + | |
| 255 | + if (__rwbase_write_trylock(rwb)) | |
| 256 | + break; | |
| 257 | + | |
| 227 | 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 | 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 | 264 | rwbase_restore_current_state(); |
| 265 | + | |
| 266 | +out_unlock: | |
| 241 | 267 | raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); |
| 242 | 268 | return 0; |
| 243 | 269 | } |
| @@ -253,8 +279,7 @@ static inline int rwbase_write_trylock(struct rwbase_rt *rwb) · 9 unmodified lines | ||
| 253 | 279 | atomic_sub(READER_BIAS, &rwb->readers); |
| 254 | 280 | |
| 255 | 281 | raw_spin_lock_irqsave(&rtm->wait_lock, flags); |
| 256 | − if (!atomic_read(&rwb->readers)) { | |
| 257 | − atomic_set(&rwb->readers, WRITER_BIAS); | |
| 282 | + if (__rwbase_write_trylock(rwb)) { | |
| 258 | 283 | raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); |
| 259 | 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 | 1972 | return 0; |
| 1973 | 1973 | } |
| 1974 | 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 | 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
| 2 | −/* Copyright (c) 2016-2018, NXP Semiconductors | |
| 2 | +/* Copyright 2016-2018 NXP | |
| 3 | 3 | * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com> |
| 4 | 4 | */ |
| 5 | 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 | 134 | return pci_iomap_wc_range(dev, bar, 0, maxlen); |
| 135 | 135 | } |
| 136 | 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 | 180 | #endif /* CONFIG_PCI */ |
| @@ -106,9 +106,6 @@ static bool do_memsw_account(void) · 105 unmodified lines | ||
| 106 | 106 | /* memcg and lruvec stats flushing */ |
| 107 | 107 | static void flush_memcg_stats_dwork(struct work_struct *w); |
| 108 | 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 | 109 | static DEFINE_SPINLOCK(stats_flush_lock); |
| 113 | 110 | |
| 114 | 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 | 680 | /* Update lruvec */ |
| 684 | 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 | 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 | 5359 | static void mem_cgroup_css_rstat_flush(struct cgroup_subsys_state *css, int cpu) |
| 5370 | 5360 | { |
| 5371 | 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 | 3403 | unmap_mapping_range_tree(&mapping->i_mmap, &details); |
| 3404 | 3404 | i_mmap_unlock_write(mapping); |
| 3405 | 3405 | } |
| 3406 | +EXPORT_SYMBOL_GPL(unmap_mapping_pages); | |
| 3406 | 3407 | |
| 3407 | 3408 | /** |
| 3408 | 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 | 353 | inc_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + file); |
| 354 | 354 | |
| 355 | + mem_cgroup_flush_stats(); | |
| 355 | 356 | /* |
| 356 | 357 | * Compare the distance to the existing workingset size. We |
| 357 | 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 | 6926 | void napi_enable(struct napi_struct *n) |
| 6927 | 6927 | { |
| 6928 | − BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); | |
| 6929 | − smp_mb__before_atomic(); | |
| 6930 | − clear_bit(NAPI_STATE_SCHED, &n->state); | |
| 6931 | − clear_bit(NAPI_STATE_NPSVC, &n->state); | |
| 6932 | − if (n->dev->threaded && n->thread) | |
| 6933 | − set_bit(NAPI_STATE_THREADED, &n->state); | |
| 6928 | + unsigned long val, new; | |
| 6929 | + | |
| 6930 | + do { | |
| 6931 | + val = READ_ONCE(n->state); | |
| 6932 | + BUG_ON(!test_bit(NAPI_STATE_SCHED, &val)); | |
| 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 | 6939 | EXPORT_SYMBOL(napi_enable); |
| 6936 | 6940 | |
| @@ -3179,17 +3179,15 @@ EXPORT_SYMBOL(sock_init_data); · 3178 unmodified lines | ||
| 3179 | 3179 | |
| 3180 | 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 | 3185 | might_sleep(); |
| 3183 | 3186 | spin_lock_bh(&sk->sk_lock.slock); |
| 3184 | 3187 | if (sk->sk_lock.owned) |
| 3185 | 3188 | __lock_sock(sk); |
| 3186 | 3189 | sk->sk_lock.owned = 1; |
| 3187 | − spin_unlock(&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(); | |
| 3190 | + spin_unlock_bh(&sk->sk_lock.slock); | |
| 3193 | 3191 | } |
| 3194 | 3192 | EXPORT_SYMBOL(lock_sock_nested); |
| 3195 | 3193 | |
| @@ -3227,24 +3225,35 @@ EXPORT_SYMBOL(release_sock); · 31 unmodified lines | ||
| 3227 | 3225 | */ |
| 3228 | 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 | 3231 | might_sleep(); |
| 3231 | 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 | 3250 | return false; |
| 3251 | + } | |
| 3238 | 3252 | |
| 3239 | 3253 | __lock_sock(sk); |
| 3240 | 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 | 3255 | __acquire(&sk->sk_lock.slock); |
| 3247 | − local_bh_enable(); | |
| 3256 | + spin_unlock_bh(&sk->sk_lock.slock); | |
| 3248 | 3257 | return true; |
| 3249 | 3258 | } |
| 3250 | 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 | 430 | struct devlink_port *dlp = &dp->devlink_port; |
| 431 | 431 | bool dsa_port_link_registered = false; |
| 432 | + struct dsa_switch *ds = dp->ds; | |
| 432 | 433 | bool dsa_port_enabled = false; |
| 433 | 434 | int err = 0; |
| 434 | 435 | |
| @@ -438,6 +439,12 @@ static int dsa_port_setup(struct dsa_port *dp) · 3 unmodified lines | ||
| 438 | 439 | INIT_LIST_HEAD(&dp->fdbs); |
| 439 | 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 | 448 | switch (dp->type) { |
| 442 | 449 | case DSA_PORT_TYPE_UNUSED: |
| 443 | 450 | dsa_port_disable(dp); |
| @@ -480,8 +487,11 @@ static int dsa_port_setup(struct dsa_port *dp) · 36 unmodified lines | ||
| 480 | 487 | dsa_port_disable(dp); |
| 481 | 488 | if (err && dsa_port_link_registered) |
| 482 | 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 | 493 | return err; |
| 494 | + } | |
| 485 | 495 | |
| 486 | 496 | dp->setup = true; |
| 487 | 497 | |
| @@ -533,11 +543,15 @@ static int dsa_port_devlink_setup(struct dsa_port *dp) · 45 unmodified lines | ||
| 533 | 543 | static void dsa_port_teardown(struct dsa_port *dp) |
| 534 | 544 | { |
| 535 | 545 | struct devlink_port *dlp = &dp->devlink_port; |
| 546 | + struct dsa_switch *ds = dp->ds; | |
| 536 | 547 | struct dsa_mac_addr *a, *tmp; |
| 537 | 548 | |
| 538 | 549 | if (!dp->setup) |
| 539 | 550 | return; |
| 540 | 551 | |
| 552 | + if (ds->ops->port_teardown) | |
| 553 | + ds->ops->port_teardown(ds, dp->index); | |
| 554 | + | |
| 541 | 555 | devlink_port_type_clear(dlp); |
| 542 | 556 | |
| 543 | 557 | switch (dp->type) { |
| @@ -581,6 +595,36 @@ static void dsa_port_devlink_teardown(struct dsa_port *dp) · 37 unmodified lines | ||
| 581 | 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 | 628 | static int dsa_devlink_info_get(struct devlink *dl, |
| 585 | 629 | struct devlink_info_req *req, |
| 586 | 630 | struct netlink_ext_ack *extack) |
| @@ -833,7 +877,7 @@ static int dsa_switch_setup(struct dsa_switch *ds) · 246 unmodified lines | ||
| 833 | 877 | devlink_params_publish(ds->devlink); |
| 834 | 878 | |
| 835 | 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 | 881 | if (!ds->slave_mii_bus) { |
| 838 | 882 | err = -ENOMEM; |
| 839 | 883 | goto teardown; |
| @@ -843,13 +887,16 @@ static int dsa_switch_setup(struct dsa_switch *ds) · 3 unmodified lines | ||
| 843 | 887 | |
| 844 | 888 | err = mdiobus_register(ds->slave_mii_bus); |
| 845 | 889 | if (err < 0) |
| 846 | − goto teardown; | |
| 890 | + goto free_slave_mii_bus; | |
| 847 | 891 | } |
| 848 | 892 | |
| 849 | 893 | ds->setup = true; |
| 850 | 894 | |
| 851 | 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 | 900 | teardown: |
| 854 | 901 | if (ds->ops->teardown) |
| 855 | 902 | ds->ops->teardown(ds); |
| @@ -872,8 +919,11 @@ static void dsa_switch_teardown(struct dsa_switch *ds) · 16 unmodified lines | ||
| 872 | 919 | if (!ds->setup) |
| 873 | 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 | 923 | mdiobus_unregister(ds->slave_mii_bus); |
| 924 | + mdiobus_free(ds->slave_mii_bus); | |
| 925 | + ds->slave_mii_bus = NULL; | |
| 926 | + } | |
| 877 | 927 | |
| 878 | 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 | 983 | list_for_each_entry(dp, &dst->ports, list) { |
| 934 | 984 | err = dsa_port_setup(dp); |
| 935 | 985 | if (err) { |
| 936 | − dsa_port_devlink_teardown(dp); | |
| 937 | − dp->type = DSA_PORT_TYPE_UNUSED; | |
| 938 | − err = dsa_port_devlink_setup(dp); | |
| 986 | + err = dsa_port_reinit_as_unused(dp); | |
| 939 | 987 | if (err) |
| 940 | 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 | 1090 | teardown_master: |
| 1044 | 1091 | dsa_tree_teardown_master(dst); |
| 1045 | 1092 | teardown_switches: |
| 1093 | + dsa_tree_teardown_ports(dst); | |
| 1046 | 1094 | dsa_tree_teardown_switches(dst); |
| 1047 | 1095 | teardown_cpu_ports: |
| 1048 | 1096 | dsa_tree_teardown_cpu_ports(dst); |
| @@ -1557,3 +1605,53 @@ void dsa_unregister_switch(struct dsa_switch *ds) · 508 unmodified lines | ||
| 1557 | 1605 | mutex_unlock(&dsa2_mutex); |
| 1558 | 1606 | } |
| 1559 | 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 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | −/* Copyright 2019 NXP Semiconductors | |
| 2 | +/* Copyright 2019 NXP | |
| 3 | 3 | */ |
| 4 | 4 | #include <linux/dsa/ocelot.h> |
| 5 | 5 | #include <soc/mscc/ocelot.h> |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | −/* Copyright 2020-2021 NXP Semiconductors | |
| 2 | +/* Copyright 2020-2021 NXP | |
| 3 | 3 | * |
| 4 | 4 | * An implementation of the software-defined tag_8021q.c tagger format, which |
| 5 | 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 | 1982 | rcu_assign_pointer(old->nh_grp, newg); |
| 1983 | 1983 | |
| 1984 | 1984 | if (newg->resilient) { |
| 1985 | + /* Make sure concurrent readers are not using 'oldg' anymore. */ | |
| 1986 | + synchronize_net(); | |
| 1985 | 1987 | rcu_assign_pointer(oldg->res_table, tmp_table); |
| 1986 | 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 | 3569 | static int nexthops_dump(struct net *net, struct notifier_block *nb, |
| 3570 | + enum nexthop_event_type event_type, | |
| 3568 | 3571 | struct netlink_ext_ack *extack) |
| 3569 | 3572 | { |
| 3570 | 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 | 3578 | struct nexthop *nh; |
| 3576 | 3579 | |
| 3577 | 3580 | nh = rb_entry(node, struct nexthop, rb_node); |
| 3578 | − err = call_nexthop_notifier(nb, net, NEXTHOP_EVENT_REPLACE, nh, | |
| 3579 | − extack); | |
| 3581 | + err = call_nexthop_notifier(nb, net, event_type, nh, extack); | |
| 3580 | 3582 | if (err) |
| 3581 | 3583 | break; |
| 3582 | 3584 | } |
| @@ -3590,7 +3592,7 @@ int register_nexthop_notifier(struct net *net, struct notifier_block *nb, · 7 unmodified lines | ||
| 3590 | 3592 | int err; |
| 3591 | 3593 | |
| 3592 | 3594 | rtnl_lock(); |
| 3593 | − err = nexthops_dump(net, nb, extack); | |
| 3595 | + err = nexthops_dump(net, nb, NEXTHOP_EVENT_REPLACE, extack); | |
| 3594 | 3596 | if (err) |
| 3595 | 3597 | goto unlock; |
| 3596 | 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 | 3606 | int unregister_nexthop_notifier(struct net *net, struct notifier_block *nb) |
| 3605 | 3607 | { |
| 3606 | − return blocking_notifier_chain_unregister(&net->nexthop.notifier_chain, | |
| 3607 | − nb); | |
| 3608 | + int err; | |
| 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 | 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 | 510 | goto out_rel; |
| 511 | 511 | } |
| 512 | 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 | 515 | /* analyze IP specific data of net_device belonging to TCP socket */ |
| 515 | 516 | addr6 = (struct sockaddr_in6 *)&addrs; |
| 516 | 517 | rcu_read_lock(); |
| @@ -1468,7 +1468,9 @@ static void smc_conn_abort_work(struct work_struct *work) · 1467 unmodified lines | ||
| 1468 | 1468 | abort_work); |
| 1469 | 1469 | struct smc_sock *smc = container_of(conn, struct smc_sock, conn); |
| 1470 | 1470 | |
| 1471 | + lock_sock(&smc->sk); | |
| 1471 | 1472 | smc_conn_kill(conn, true); |
| 1473 | + release_sock(&smc->sk); | |
| 1472 | 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 | 29 | else |
| 30 | 30 | CLANG_FLAGS += -fintegrated-as |
| 31 | 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 | 36 | CLANG_FLAGS += -Werror=unknown-warning-option |
| 37 | +CLANG_FLAGS += -Werror=ignored-optimization-argument | |
| 33 | 38 | KBUILD_CFLAGS += $(CLANG_FLAGS) |
| 34 | 39 | KBUILD_AFLAGS += $(CLANG_FLAGS) |
| 35 | 40 | export CLANG_FLAGS |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | # Stage 2 is handled by this file and does the following |
| 14 | 14 | # 1) Find all modules listed in modules.order |
| 15 | 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 | 17 | # 4) create one Module.symvers file with CRC for all exported symbols |
| 18 | 18 | |
| 19 | 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 | 34 | REGEX_KCONFIG_DEF = re.compile(DEF) |
| 35 | 35 | REGEX_KCONFIG_EXPR = re.compile(EXPR) |
| 36 | 36 | REGEX_KCONFIG_STMT = re.compile(STMT) |
| 37 | −REGEX_KCONFIG_HELP = re.compile(r"^\s+help\s*$") | |
| 38 | 37 | REGEX_FILTER_SYMBOLS = re.compile(r"[A-Za-z0-9]$") |
| 39 | 38 | REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+") |
| 40 | 39 | REGEX_QUOTES = re.compile("(\"(.*?)\")") |
| @@ -102,6 +101,9 @@ def parse_options(): · 61 unmodified lines | ||
| 102 | 101 | "continue.") |
| 103 | 102 | |
| 104 | 103 | if args.commit: |
| 104 | + if args.commit.startswith('HEAD'): | |
| 105 | + sys.exit("The --commit option can't use the HEAD ref") | |
| 106 | + | |
| 105 | 107 | args.find = False |
| 106 | 108 | |
| 107 | 109 | if args.ignore: |
| @@ -432,7 +434,6 @@ def parse_kconfig_file(kfile): · 324 unmodified lines | ||
| 432 | 434 | lines = [] |
| 433 | 435 | defined = [] |
| 434 | 436 | references = [] |
| 435 | − skip = False | |
| 436 | 437 | |
| 437 | 438 | if not os.path.exists(kfile): |
| 438 | 439 | return defined, references |
| @@ -448,12 +449,6 @@ def parse_kconfig_file(kfile): · 9 unmodified lines | ||
| 448 | 449 | if REGEX_KCONFIG_DEF.match(line): |
| 449 | 450 | symbol_def = REGEX_KCONFIG_DEF.findall(line) |
| 450 | 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 | 452 | elif REGEX_KCONFIG_STMT.match(line): |
| 458 | 453 | line = REGEX_QUOTES.sub("", line) |
| 459 | 454 | symbols = get_symbols_in_line(line) |
| @@ -13,6 +13,7 @@ import logging · 12 unmodified lines | ||
| 13 | 13 | import os |
| 14 | 14 | import re |
| 15 | 15 | import subprocess |
| 16 | +import sys | |
| 16 | 17 | |
| 17 | 18 | _DEFAULT_OUTPUT = 'compile_commands.json' |
| 18 | 19 | _DEFAULT_LOG_LEVEL = 'WARNING' |
| @@ -43,7 +43,7 @@ void perf_evsel__delete(struct perf_evsel *evsel) · 42 unmodified lines | ||
| 43 | 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 | 47 | #define MMAP(e, x, y) (e->mmap ? ((struct perf_mmap *) xyarray__entry(e->mmap, x, y)) : NULL) |
| 48 | 48 | |
| 49 | 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 | 54 | int cpu, thread; |
| 55 | 55 | for (cpu = 0; cpu < ncpus; cpu++) { |
| 56 | 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 | 83 | static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread, int *group_fd) |
| 81 | 84 | { |
| 82 | 85 | struct perf_evsel *leader = evsel->leader; |
| 83 | − int fd; | |
| 86 | + int *fd; | |
| 84 | 87 | |
| 85 | 88 | if (evsel == leader) { |
| 86 | 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 | 98 | return -ENOTCONN; |
| 96 | 99 | |
| 97 | 100 | fd = FD(leader, cpu, thread); |
| 98 | − if (fd == -1) | |
| 101 | + if (fd == NULL || *fd == -1) | |
| 99 | 102 | return -EBADF; |
| 100 | 103 | |
| 101 | − *group_fd = fd; | |
| 104 | + *group_fd = *fd; | |
| 102 | 105 | |
| 103 | 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 | 142 | for (cpu = 0; cpu < cpus->nr; cpu++) { |
| 140 | 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 | 150 | err = get_group_fd(evsel, cpu, thread, &group_fd); |
| 144 | 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 | 158 | if (fd < 0) |
| 152 | 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 | 170 | int thread; |
| 164 | 171 | |
| 165 | 172 | for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) { |
| 166 | − if (FD(evsel, cpu, thread) >= 0) | |
| 167 | − close(FD(evsel, cpu, thread)); | |
| 168 | − FD(evsel, cpu, thread) = -1; | |
| 173 | + int *fd = FD(evsel, cpu, thread); | |
| 174 | + | |
| 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 | 220 | for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) { |
| 211 | 221 | for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { |
| 212 | − int fd = FD(evsel, cpu, thread); | |
| 213 | − struct perf_mmap *map = MMAP(evsel, cpu, thread); | |
| 222 | + int *fd = FD(evsel, cpu, thread); | |
| 214 | 223 | |
| 215 | − if (fd < 0) | |
| 224 | + if (fd == NULL || *fd < 0) | |
| 216 | 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 | 249 | for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) { |
| 241 | 250 | for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { |
| 242 | − int fd = FD(evsel, cpu, thread); | |
| 243 | − struct perf_mmap *map = MMAP(evsel, cpu, thread); | |
| 251 | + int *fd = FD(evsel, cpu, thread); | |
| 252 | + struct perf_mmap *map; | |
| 244 | 253 | |
| 245 | − if (fd < 0) | |
| 254 | + if (fd == NULL || *fd < 0) | |
| 246 | 255 | continue; |
| 247 | 256 | |
| 257 | + map = MMAP(evsel, cpu, thread); | |
| 248 | 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 | 261 | if (ret) { |
| 252 | 262 | perf_evsel__munmap(evsel); |
| 253 | 263 | return ret; |
| @@ -260,7 +270,9 @@ int perf_evsel__mmap(struct perf_evsel *evsel, int pages) · 6 unmodified lines | ||
| 260 | 270 | |
| 261 | 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 | 276 | return NULL; |
| 265 | 277 | |
| 266 | 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 | 307 | struct perf_counts_values *count) |
| 296 | 308 | { |
| 297 | 309 | size_t size = perf_evsel__read_size(evsel); |
| 310 | + int *fd = FD(evsel, cpu, thread); | |
| 298 | 311 | |
| 299 | 312 | memset(count, 0, sizeof(*count)); |
| 300 | 313 | |
| 301 | − if (FD(evsel, cpu, thread) < 0) | |
| 314 | + if (fd == NULL || *fd < 0) | |
| 302 | 315 | return -EINVAL; |
| 303 | 316 | |
| 304 | 317 | if (MMAP(evsel, cpu, thread) && |
| 305 | 318 | !perf_mmap__read_self(MMAP(evsel, cpu, thread), count)) |
| 306 | 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 | 322 | return -errno; |
| 310 | 323 | |
| 311 | 324 | return 0; |
| @@ -318,8 +331,13 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, · 6 unmodified lines | ||
| 318 | 331 | int thread; |
| 319 | 332 | |
| 320 | 333 | for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { |
| 321 | − int fd = FD(evsel, cpu, thread), | |
| 322 | − err = ioctl(fd, ioc, arg); | |
| 334 | + int err; | |
| 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 | 342 | if (err) |
| 325 | 343 | return err; |
| @@ -368,16 +368,6 @@ static inline int output_type(unsigned int type) · 367 unmodified lines | ||
| 368 | 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 | 371 | static bool output_set_by_user(void) |
| 382 | 372 | { |
| 383 | 373 | int j; |
| @@ -556,6 +546,18 @@ static void set_print_ip_opts(struct perf_event_attr *attr) · 172 unmodified lines | ||
| 556 | 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 | 562 | * verify all user requested events exist and the samples |
| 561 | 563 | * have the expected data |
| @@ -567,7 +569,7 @@ static int perf_session__check_output_opt(struct perf_session *session) · 5 unmodified lines | ||
| 567 | 569 | struct evsel *evsel; |
| 568 | 570 | |
| 569 | 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 | 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 | 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) | |
| 765 | − end_row = row - browser->top_idx; | |
| 766 | − else | |
| 764 | + if (diff <= 0) | |
| 767 | 765 | return; |
| 768 | 766 | |
| 769 | 767 | SLsmg_set_char_set(1); |
| 770 | 768 | |
| 771 | 769 | if (arrow_down) { |
| 770 | + if (row + diff <= browser->top_idx) | |
| 771 | + return; | |
| 772 | + | |
| 773 | + end_row = row + diff - browser->top_idx; | |
| 772 | 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 | 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 | 789 | } else { |
| 790 | + if (row < browser->top_idx) | |
| 791 | + return; | |
| 792 | + | |
| 793 | + end_row = row - browser->top_idx; | |
| 779 | 794 | ui_browser__gotorc(browser, end_row, column - 1); |
| 780 | 795 | SLsmg_write_char(SLSMG_LTEE_CHAR); |
| 781 | 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 | 51 | void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, |
| 52 | 52 | u64 start, u64 end); |
| 53 | 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 | 55 | void __ui_browser__show_title(struct ui_browser *browser, const char *title); |
| 56 | 56 | void ui_browser__show_title(struct ui_browser *browser, const char *title); |
| 57 | 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 | 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 | 130 | struct disasm_line *pos = list_prev_entry(cursor, al.node); |
| 131 | 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 | 140 | if (!pos) |
| 134 | − return false; | |
| 141 | + return 0; | |
| 135 | 142 | |
| 136 | 143 | if (ins__is_lock(&pos->ins)) |
| 137 | 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 | 146 | name = pos->ins.name; |
| 140 | 147 | |
| 141 | 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 | 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 | 164 | struct annotation *notes = symbol__annotation(sym); |
| 156 | 165 | u8 pcnt_width = annotation__pcnt_width(notes); |
| 157 | 166 | int width; |
| 167 | + int diff = 0; | |
| 158 | 168 | |
| 159 | 169 | /* PLT symbols contain external offsets */ |
| 160 | 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 | 215 | pcnt_width + 2 + notes->widths.addr + width, |
| 206 | 216 | from, to); |
| 207 | 217 | |
| 208 | − if (is_fused(ab, cursor)) { | |
| 218 | + diff = is_fused(ab, cursor); | |
| 219 | + if (diff > 0) { | |
| 209 | 220 | ui_browser__mark_fused(browser, |
| 210 | 221 | pcnt_width + 3 + notes->widths.addr + width, |
| 211 | − from - 1, | |
| 212 | − to > from); | |
| 222 | + from - diff, diff, to > from); | |
| 213 | 223 | } |
| 214 | 224 | } |
| 215 | 225 | |
| @@ -24,7 +24,10 @@ · 23 unmodified lines | ||
| 24 | 24 | struct btf * __weak btf__load_from_kernel_by_id(__u32 id) |
| 25 | 25 | { |
| 26 | 26 | struct btf *btf; |
| 27 | +#pragma GCC diagnostic push | |
| 28 | +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |
| 27 | 29 | int err = btf__get_from_id(id, &btf); |
| 30 | +#pragma GCC diagnostic pop | |
| 28 | 31 | |
| 29 | 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 | 2150 | al.filtered = 0; |
| 2151 | 2151 | al.sym = NULL; |
| 2152 | + al.srcline = NULL; | |
| 2152 | 2153 | if (!cpumode) { |
| 2153 | 2154 | thread__find_cpumode_addr_location(thread, ip, &al); |
| 2154 | 2155 | } else { |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | #!/bin/bash |
| 2 | 2 | # SPDX-License-Identifier: GPL-2.0 |
| 3 | −# Copyright 2020 NXP Semiconductors | |
| 3 | +# Copyright 2020 NXP | |
| 4 | 4 | |
| 5 | 5 | WAIT_TIME=1 |
| 6 | 6 | NUM_NETIFS=4 |
| @@ -1,5 +1,2 @@ | ||
| 1 | −##TEST_GEN_FILES := test_unix_oob | |
| 2 | −TEST_PROGS := test_unix_oob | |
| 1 | +TEST_GEN_PROGS := test_unix_oob | |
| 3 | 2 | include ../../lib.mk |
| 4 | − | |
| 5 | −all: $(TEST_PROGS) | |
| @@ -271,8 +271,9 @@ main(int argc, char **argv) · 270 unmodified lines | ||
| 271 | 271 | read_oob(pfd, &oob); |
| 272 | 272 | |
| 273 | 273 | if (!signal_recvd || len != 127 || oob != '%' || atmark != 1) { |
| 274 | − fprintf(stderr, "Test 3 failed, sigurg %d len %d OOB %c ", | |
| 275 | − "atmark %d\n", signal_recvd, len, oob, atmark); | |
| 274 | + fprintf(stderr, | |
| 275 | + "Test 3 failed, sigurg %d len %d OOB %c atmark %d\n", | |
| 276 | + signal_recvd, len, oob, atmark); | |
| 276 | 277 | die(1); |
| 277 | 278 | } |
| 278 | 279 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | −#include <ppc-asm.h> | |
| 2 | +#include <basic_asm.h> | |
| 3 | 3 | #include <asm/unistd.h> |
| 4 | 4 | |
| 5 | 5 | .text |
| @@ -26,3 +26,38 @@ FUNC_START(getppid_tm_suspended) · 20 unmodified lines | ||
| 26 | 26 | 1: |
| 27 | 27 | li r3, -1 |
| 28 | 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 | 19 | #include "utils.h" |
| 20 | 20 | #include "tm.h" |
| 21 | 21 | |
| 22 | +#ifndef PPC_FEATURE2_SCV | |
| 23 | +#define PPC_FEATURE2_SCV 0x00100000 /* scv syscall */ | |
| 24 | +#endif | |
| 25 | + | |
| 22 | 26 | extern int getppid_tm_active(void); |
| 23 | 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 | 31 | unsigned retries = 0; |
| 26 | 32 | |
| 27 | 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 | 37 | int i; |
| 32 | 38 | pid_t pid; |
| 33 | 39 | |
| 34 | 40 | for (i = 0; i < TM_RETRIES; i++) { |
| 35 | − if (suspend) | |
| 36 | − pid = getppid_tm_suspended(); | |
| 37 | − else | |
| 38 | − pid = getppid_tm_active(); | |
| 41 | + if (suspend) { | |
| 42 | + if (scv) | |
| 43 | + pid = getppid_scv_tm_suspended(); | |
| 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 | 53 | if (pid >= 0) |
| 41 | 54 | return pid; |
| @@ -82,15 +95,24 @@ int tm_syscall(void) · 40 unmodified lines | ||
| 82 | 95 | * Test a syscall within a suspended transaction and verify |
| 83 | 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 | 101 | * Test a syscall within an active transaction and verify that |
| 89 | 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 | 105 | FAIL_IF(!failure_is_persistent()); /* ...persistently... */ |
| 93 | 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 | 116 | gettimeofday(&now, 0); |
| 95 | 117 | } |
| 96 | 118 | |