Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 6 Nov 2022 18:46:59 +0000 (10:46 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 6 Nov 2022 18:46:59 +0000 (10:46 -0800)
Pull kvm fixes from Paolo Bonzini:
"ARM:

   - Fix the pKVM stage-1 walker erronously using the stage-2 accessor

   - Correctly convert vcpu->kvm to a hyp pointer when generating an
     exception in a nVHE+MTE configuration

   - Check that KVM_CAP_DIRTY_LOG_* are valid before enabling them

   - Fix SMPRI_EL1/TPIDR2_EL0 trapping on VHE

   - Document the boot requirements for FGT when entering the kernel at
     EL1

  x86:

   - Use SRCU to protect zap in __kvm_set_or_clear_apicv_inhibit()

   - Make argument order consistent for kvcalloc()

   - Userspace API fixes for DEBUGCTL and LBRs"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: x86: Fix a typo about the usage of kvcalloc()
  KVM: x86: Use SRCU to protect zap in __kvm_set_or_clear_apicv_inhibit()
  KVM: VMX: Ignore guest CPUID for host userspace writes to DEBUGCTL
  KVM: VMX: Fold vmx_supported_debugctl() into vcpu_supported_debugctl()
  KVM: VMX: Advertise PMU LBRs if and only if perf supports LBRs
  arm64: booting: Document our requirements for fine grained traps with SME
  KVM: arm64: Fix SMPRI_EL1/TPIDR2_EL0 trapping on VHE
  KVM: Check KVM_CAP_DIRTY_LOG_{RING, RING_ACQ_REL} prior to enabling them
  KVM: arm64: Fix bad dereference on MTE-enabled systems
  KVM: arm64: Use correct accessor to parse stage-1 PTEs

226 files changed:
Documentation/arm64/cpu-feature-registers.rst
Documentation/devicetree/bindings/power/fsl,imx-gpcv2.yaml
Documentation/driver-api/driver-model/devres.rst
MAINTAINERS
arch/arm/boot/dts/imx6q-yapp4-crux.dts
arch/arm/boot/dts/imx6qdl-gw5910.dtsi
arch/arm/boot/dts/imx6qdl-gw5913.dtsi
arch/arm/boot/dts/imx6qp-yapp4-crux-plus.dts
arch/arm/boot/dts/ste-href.dtsi
arch/arm/boot/dts/ste-snowball.dts
arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts
arch/arm/boot/dts/ste-ux500-samsung-codina.dts
arch/arm/boot/dts/ste-ux500-samsung-gavini.dts
arch/arm/boot/dts/ste-ux500-samsung-golden.dts
arch/arm/boot/dts/ste-ux500-samsung-janice.dts
arch/arm/boot/dts/ste-ux500-samsung-kyle.dts
arch/arm/boot/dts/ste-ux500-samsung-skomer.dts
arch/arm64/boot/dts/arm/juno-base.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
arch/arm64/boot/dts/freescale/imx8mm-mx8menlo.dts
arch/arm64/boot/dts/freescale/imx8mm.dtsi
arch/arm64/boot/dts/freescale/imx8mn.dtsi
arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
arch/arm64/boot/dts/freescale/imx93.dtsi
arch/arm64/include/asm/efi.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/efi-rt-wrapper.S
arch/arm64/kernel/efi.c
arch/arm64/kernel/entry-common.c
arch/arm64/mm/fault.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/syscalls.h
arch/powerpc/kernel/sys_ppc32.c
arch/powerpc/kernel/syscalls/syscall.tbl
arch/x86/xen/pmu.c
arch/x86/xen/setup.c
block/blk-mq.c
block/genhd.c
drivers/acpi/x86/utils.c
drivers/ata/pata_legacy.c
drivers/ata/pata_palmld.c
drivers/block/Kconfig
drivers/block/ublk_drv.c
drivers/bluetooth/virtio_bt.c
drivers/clk/clk-renesas-pcie.c
drivers/clk/clk.c
drivers/clk/mediatek/clk-mt8195-topckgen.c
drivers/clk/qcom/gcc-sc7280.c
drivers/clk/qcom/gpucc-sc7280.c
drivers/clk/renesas/r8a779g0-cpg-mssr.c
drivers/clk/sifive/Kconfig
drivers/firmware/arm_scmi/bus.c
drivers/firmware/arm_scmi/common.h
drivers/firmware/arm_scmi/driver.c
drivers/firmware/arm_scmi/mailbox.c
drivers/firmware/arm_scmi/optee.c
drivers/firmware/arm_scmi/shmem.c
drivers/firmware/arm_scmi/smc.c
drivers/firmware/arm_scmi/virtio.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/random.c
drivers/firmware/efi/tpm.c
drivers/firmware/efi/vars.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h
drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_rq_dlg_calc_32.c
drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
drivers/gpu/drm/drm_format_helper.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display_core.h
drivers/gpu/drm/i915/display/intel_display_power_well.c
drivers/gpu/drm/i915/display/intel_dkl_phy.c [new file with mode: 0644]
drivers/gpu/drm/i915/display/intel_dkl_phy.h [new file with mode: 0644]
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_dpll_mgr.c
drivers/gpu/drm/i915/display/intel_lvds.c
drivers/gpu/drm/i915/display/intel_panel.c
drivers/gpu/drm/i915/display/intel_panel.h
drivers/gpu/drm/i915/display/intel_sdvo.c
drivers/gpu/drm/i915/gem/i915_gem_internal.c
drivers/gpu/drm/i915/gem/i915_gem_shmem.c
drivers/gpu/drm/i915/gem/i915_gem_ttm.c
drivers/gpu/drm/i915/gem/i915_gem_userptr.c
drivers/gpu/drm/i915/i915_driver.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_scatterlist.h
drivers/gpu/drm/imx/Kconfig
drivers/gpu/drm/imx/imx-tve.c
drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
drivers/gpu/drm/rockchip/rockchip_drm_gem.c
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-tegra.c
drivers/isdn/hardware/mISDN/netjet.c
drivers/isdn/mISDN/core.c
drivers/net/dsa/dsa_loop.c
drivers/net/ethernet/adi/adin1110.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.h
drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/phy/mdio_bus.c
drivers/net/tun.c
drivers/nfc/fdp/fdp.c
drivers/nfc/nfcmrvl/i2c.c
drivers/nfc/nxp-nci/core.c
drivers/nfc/s3fwrn5/core.c
drivers/soc/imx/imx93-pd.c
fs/btrfs/backref.c
fs/btrfs/ctree.h
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/tests/qgroup-tests.c
fs/cifs/cifsfs.c
fs/cifs/inode.c
fs/cifs/misc.c
fs/cifs/smb2misc.c
fs/cifs/smb2ops.c
fs/cifs/smb2transport.c
fs/ext4/fast_commit.c
fs/ext4/ioctl.c
fs/ext4/migrate.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/fuse/file.c
fs/fuse/readdir.c
fs/xfs/libxfs/xfs_ag.h
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_dir2_leaf.c
fs/xfs/libxfs/xfs_format.h
fs/xfs/libxfs/xfs_log_format.h
fs/xfs/libxfs/xfs_refcount.c
fs/xfs/libxfs/xfs_refcount.h
fs/xfs/libxfs/xfs_refcount_btree.c
fs/xfs/libxfs/xfs_rmap.c
fs/xfs/libxfs/xfs_trans_resv.c
fs/xfs/libxfs/xfs_types.h
fs/xfs/scrub/alloc.c
fs/xfs/scrub/ialloc.c
fs/xfs/scrub/refcount.c
fs/xfs/xfs_attr_item.c
fs/xfs/xfs_bmap_item.c
fs/xfs/xfs_error.c
fs/xfs/xfs_extfree_item.c
fs/xfs/xfs_extfree_item.h
fs/xfs/xfs_file.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_ondisk.h
fs/xfs/xfs_refcount_item.c
fs/xfs/xfs_rmap_item.c
fs/xfs/xfs_super.c
fs/xfs/xfs_sysfs.h
fs/xfs/xfs_trace.h
fs/xfs/xfs_trans_ail.c
include/asm-generic/compat.h
include/linux/efi.h
include/linux/fortify-string.h
include/net/netlink.h
include/net/sock.h
kernel/kprobes.c
kernel/trace/fprobe.c
kernel/trace/ftrace.c
kernel/trace/kprobe_event_gen_test.c
kernel/trace/ring_buffer.c
lib/nlattr.c
net/bluetooth/hci_conn.c
net/bluetooth/iso.c
net/bluetooth/l2cap_core.c
net/bridge/br_netlink.c
net/bridge/br_sysfs_br.c
net/core/neighbour.c
net/dsa/dsa2.c
net/ipv4/af_inet.c
net/ipv4/tcp_bpf.c
net/ipv4/tcp_ulp.c
net/ipv4/udp_bpf.c
net/ipv6/route.c
net/ipv6/udp.c
net/netfilter/ipset/ip_set_hash_gen.h
net/netfilter/ipvs/ip_vs_app.c
net/netfilter/ipvs/ip_vs_conn.c
net/netfilter/nf_nat_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_payload.c
net/openvswitch/datapath.c
net/rose/rose_link.c
net/sched/sch_red.c
net/smc/af_smc.c
net/unix/unix_bpf.c
net/vmw_vsock/af_vsock.c
tools/testing/selftests/landlock/Makefile
tools/testing/selftests/pidfd/Makefile
tools/testing/selftests/pidfd/pidfd_test.c
tools/testing/selftests/pidfd/pidfd_wait.c

index 04ba83e..c7adc78 100644 (file)
@@ -92,7 +92,7 @@ operation if the source belongs to the supported system register space.
 
 The infrastructure emulates only the following system register space::
 
-       Op0=3, Op1=0, CRn=0, CRm=0,4,5,6,7
+       Op0=3, Op1=0, CRn=0, CRm=0,2,3,4,5,6,7
 
 (See Table C5-6 'System instruction encodings for non-Debug System
 register accesses' in ARMv8 ARM DDI 0487A.h, for the list of
@@ -293,6 +293,42 @@ infrastructure:
      | WFXT                         | [3-0]   |    y    |
      +------------------------------+---------+---------+
 
+  10) MVFR0_EL1 - AArch32 Media and VFP Feature Register 0
+
+     +------------------------------+---------+---------+
+     | Name                         |  bits   | visible |
+     +------------------------------+---------+---------+
+     | FPDP                         | [11-8]  |    y    |
+     +------------------------------+---------+---------+
+
+  11) MVFR1_EL1 - AArch32 Media and VFP Feature Register 1
+
+     +------------------------------+---------+---------+
+     | Name                         |  bits   | visible |
+     +------------------------------+---------+---------+
+     | SIMDFMAC                     | [31-28] |    y    |
+     +------------------------------+---------+---------+
+     | SIMDSP                       | [19-16] |    y    |
+     +------------------------------+---------+---------+
+     | SIMDInt                      | [15-12] |    y    |
+     +------------------------------+---------+---------+
+     | SIMDLS                       | [11-8]  |    y    |
+     +------------------------------+---------+---------+
+
+  12) ID_ISAR5_EL1 - AArch32 Instruction Set Attribute Register 5
+
+     +------------------------------+---------+---------+
+     | Name                         |  bits   | visible |
+     +------------------------------+---------+---------+
+     | CRC32                        | [19-16] |    y    |
+     +------------------------------+---------+---------+
+     | SHA2                         | [15-12] |    y    |
+     +------------------------------+---------+---------+
+     | SHA1                         | [11-8]  |    y    |
+     +------------------------------+---------+---------+
+     | AES                          | [7-4]   |    y    |
+     +------------------------------+---------+---------+
+
 
 Appendix I: Example
 -------------------
index 58022ae..dfdb8df 100644 (file)
@@ -81,6 +81,9 @@ properties:
 
           power-supply: true
 
+          power-domains:
+            maxItems: 1
+
           resets:
             description: |
               A number of phandles to resets that need to be asserted during
index 687adb5..5608226 100644 (file)
@@ -279,6 +279,7 @@ GPIO
   devm_gpio_request_one()
 
 I2C
+  devm_i2c_add_adapter()
   devm_i2c_new_dummy_device()
 
 IIO
index 9774e7b..046ff06 100644 (file)
@@ -3984,7 +3984,7 @@ M:        RafaÅ‚ MiÅ‚ecki <rafal@milecki.pl>
 R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-T:     git git://github.com/broadcom/stblinux.git
+T:     git https://github.com/broadcom/stblinux.git
 F:     Documentation/devicetree/bindings/arm/bcm/brcm,bcmbca.yaml
 F:     arch/arm64/boot/dts/broadcom/bcmbca/*
 N:     bcmbca
@@ -4009,7 +4009,7 @@ R:        Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
 L:     linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-T:     git git://github.com/broadcom/stblinux.git
+T:     git https://github.com/broadcom/stblinux.git
 F:     Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
 F:     drivers/pci/controller/pcie-brcmstb.c
 F:     drivers/staging/vc04_services
@@ -4023,7 +4023,7 @@ M:        Ray Jui <rjui@broadcom.com>
 M:     Scott Branden <sbranden@broadcom.com>
 R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
 S:     Maintained
-T:     git git://github.com/broadcom/mach-bcm
+T:     git https://github.com/broadcom/mach-bcm
 F:     arch/arm/mach-bcm/
 N:     bcm281*
 N:     bcm113*
@@ -4088,7 +4088,7 @@ M:        Florian Fainelli <f.fainelli@gmail.com>
 R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-T:     git git://github.com/broadcom/stblinux.git
+T:     git https://github.com/broadcom/stblinux.git
 F:     Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
 F:     arch/arm/boot/dts/bcm7*.dts*
 F:     arch/arm/include/asm/hardware/cache-b15-rac.h
@@ -4121,7 +4121,7 @@ M:        Florian Fainelli <f.fainelli@gmail.com>
 R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
 L:     linux-mips@vger.kernel.org
 S:     Maintained
-T:     git git://github.com/broadcom/stblinux.git
+T:     git https://github.com/broadcom/stblinux.git
 F:     arch/mips/bmips/*
 F:     arch/mips/boot/dts/brcm/bcm*.dts*
 F:     arch/mips/include/asm/mach-bmips/*
@@ -4262,7 +4262,7 @@ M:        Scott Branden <sbranden@broadcom.com>
 R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-T:     git git://github.com/broadcom/stblinux.git
+T:     git https://github.com/broadcom/stblinux.git
 F:     arch/arm64/boot/dts/broadcom/northstar2/*
 F:     arch/arm64/boot/dts/broadcom/stingray/*
 F:     drivers/clk/bcm/clk-ns*
@@ -4332,7 +4332,7 @@ M:        Florian Fainelli <f.fainelli@gmail.com>
 R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
-T:     git git://github.com/broadcom/stblinux.git
+T:     git https://github.com/broadcom/stblinux.git
 F:     drivers/soc/bcm/bcm63xx/bcm-pmb.c
 F:     include/dt-bindings/soc/bcm-pmb.h
 
@@ -5041,7 +5041,7 @@ F:        drivers/scsi/snic/
 
 CISCO VIC ETHERNET NIC DRIVER
 M:     Christian Benvenuti <benve@cisco.com>
-M:     Govindarajulu Varadarajan <_govind@gmx.com>
+M:     Satish Kharat <satishkh@cisco.com>
 S:     Supported
 F:     drivers/net/ethernet/cisco/enic/
 
@@ -9217,7 +9217,7 @@ W:        https://www.hisilicon.com
 F:     drivers/i2c/busses/i2c-hisi.c
 
 HISILICON LPC BUS DRIVER
-M:     john.garry@huawei.com
+M:     Jay Fang <f.fangjian@huawei.com>
 S:     Maintained
 W:     http://www.hisilicon.com
 F:     Documentation/devicetree/bindings/arm/hisilicon/low-pin-count.yaml
@@ -9778,7 +9778,10 @@ S:       Supported
 F:     drivers/pci/hotplug/rpaphp*
 
 IBM Power SRIOV Virtual NIC Device Driver
-M:     Dany Madden <drt@linux.ibm.com>
+M:     Haren Myneni <haren@linux.ibm.com>
+M:     Rick Lindsley <ricklind@linux.ibm.com>
+R:     Nick Child <nnac123@linux.ibm.com>
+R:     Dany Madden <danymadden@us.ibm.com>
 R:     Thomas Falcon <tlfalcon@linux.ibm.com>
 L:     netdev@vger.kernel.org
 S:     Supported
index 15f4824..bddf382 100644 (file)
        status = "okay";
 };
 
+&reg_pu {
+       regulator-always-on;
+};
+
 &reg_usb_h1_vbus {
        status = "okay";
 };
index 68e5ab2..6bb4855 100644 (file)
@@ -29,7 +29,7 @@
 
                user-pb {
                        label = "user_pb";
-                       gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+                       gpios = <&gsc_gpio 2 GPIO_ACTIVE_LOW>;
                        linux,code = <BTN_0>;
                };
 
index 8e23cec..696427b 100644 (file)
@@ -26,7 +26,7 @@
 
                user-pb {
                        label = "user_pb";
-                       gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
+                       gpios = <&gsc_gpio 2 GPIO_ACTIVE_LOW>;
                        linux,code = <BTN_0>;
                };
 
index cea165f..afaf4a6 100644 (file)
        status = "okay";
 };
 
+&reg_pu {
+       regulator-always-on;
+};
+
 &reg_usb_h1_vbus {
        status = "okay";
 };
index fbaa0ce..8f1bb78 100644 (file)
                        polling-delay = <0>;
                        polling-delay-passive = <0>;
                        thermal-sensors = <&bat_therm>;
+
+                       trips {
+                               battery-crit-hi {
+                                       temperature = <70000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
                };
        };
 
index 1c9094f..e2f0cda 100644 (file)
                        polling-delay = <0>;
                        polling-delay-passive = <0>;
                        thermal-sensors = <&bat_therm>;
+
+                       trips {
+                               battery-crit-hi {
+                                       temperature = <70000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
                };
        };
 
index d6940e0..27a3ab7 100644 (file)
                        polling-delay = <0>;
                        polling-delay-passive = <0>;
                        thermal-sensors = <&bat_therm>;
+
+                       trips {
+                               battery-crit-hi {
+                                       temperature = <70000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
                };
        };
 
index 5f41256..b88f0c0 100644 (file)
                        polling-delay = <0>;
                        polling-delay-passive = <0>;
                        thermal-sensors = <&bat_therm>;
+
+                       trips {
+                               battery-crit-hi {
+                                       temperature = <70000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
                };
        };
 
index 806da3f..7231bc7 100644 (file)
                        polling-delay = <0>;
                        polling-delay-passive = <0>;
                        thermal-sensors = <&bat_therm>;
+
+                       trips {
+                               battery-crit-hi {
+                                       temperature = <70000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
                };
        };
 
index b0dce91..9604695 100644 (file)
                        polling-delay = <0>;
                        polling-delay-passive = <0>;
                        thermal-sensors = <&bat_therm>;
+
+                       trips {
+                               battery-crit-hi {
+                                       temperature = <70000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
                };
        };
 
index ed5c79c..69387e8 100644 (file)
                        polling-delay = <0>;
                        polling-delay-passive = <0>;
                        thermal-sensors = <&bat_therm>;
+
+                       trips {
+                               battery-crit-hi {
+                                       temperature = <70000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
                };
        };
 
index c57676f..167846d 100644 (file)
                        polling-delay = <0>;
                        polling-delay-passive = <0>;
                        thermal-sensors = <&bat_therm>;
+
+                       trips {
+                               battery-crit-hi {
+                                       temperature = <70000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
                };
        };
 
index 81b341a..93e5f5e 100644 (file)
                        polling-delay = <0>;
                        polling-delay-passive = <0>;
                        thermal-sensors = <&bat_therm>;
+
+                       trips {
+                               battery-crit-hi {
+                                       temperature = <70000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
                };
        };
 
index 2f27619..8b4d280 100644 (file)
                        polling-delay = <1000>;
                        polling-delay-passive = <100>;
                        thermal-sensors = <&scpi_sensors0 0>;
+                       trips {
+                               pmic_crit0: trip0 {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
                };
 
                soc {
                        polling-delay = <1000>;
                        polling-delay-passive = <100>;
                        thermal-sensors = <&scpi_sensors0 3>;
+                       trips {
+                               soc_crit0: trip0 {
+                                       temperature = <80000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
                };
 
                big_cluster_thermal_zone: big-cluster {
index 421d879..260d045 100644 (file)
                        little-endian;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       clock-frequency = <2500000>;
+                       clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
+                                           QORIQ_CLK_PLL_DIV(1)>;
                        status = "disabled";
                };
 
                        little-endian;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       clock-frequency = <2500000>;
+                       clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
+                                           QORIQ_CLK_PLL_DIV(1)>;
                        status = "disabled";
                };
 
index f1b9cc8..348d9e3 100644 (file)
                        little-endian;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       clock-frequency = <2500000>;
+                       clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
+                                           QORIQ_CLK_PLL_DIV(2)>;
                        status = "disabled";
                };
 
                        little-endian;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       clock-frequency = <2500000>;
+                       clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
+                                           QORIQ_CLK_PLL_DIV(2)>;
                        status = "disabled";
                };
 
index 6680fb2..8c76d86 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <0>;
                        little-endian;
+                       clock-frequency = <2500000>;
+                       clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
+                                           QORIQ_CLK_PLL_DIV(2)>;
                        status = "disabled";
                };
 
                        little-endian;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       clock-frequency = <2500000>;
+                       clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
+                                           QORIQ_CLK_PLL_DIV(2)>;
                        status = "disabled";
                };
 
index 82a1c44..10370d1 100644 (file)
@@ -38,9 +38,9 @@ conn_subsys: bus@5b000000 {
                interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
                reg = <0x5b010000 0x10000>;
                clocks = <&sdhc0_lpcg IMX_LPCG_CLK_4>,
-                        <&sdhc0_lpcg IMX_LPCG_CLK_5>,
-                        <&sdhc0_lpcg IMX_LPCG_CLK_0>;
-               clock-names = "ipg", "per", "ahb";
+                        <&sdhc0_lpcg IMX_LPCG_CLK_0>,
+                        <&sdhc0_lpcg IMX_LPCG_CLK_5>;
+               clock-names = "ipg", "ahb", "per";
                power-domains = <&pd IMX_SC_R_SDHC_0>;
                status = "disabled";
        };
@@ -49,9 +49,9 @@ conn_subsys: bus@5b000000 {
                interrupts = <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>;
                reg = <0x5b020000 0x10000>;
                clocks = <&sdhc1_lpcg IMX_LPCG_CLK_4>,
-                        <&sdhc1_lpcg IMX_LPCG_CLK_5>,
-                        <&sdhc1_lpcg IMX_LPCG_CLK_0>;
-               clock-names = "ipg", "per", "ahb";
+                        <&sdhc1_lpcg IMX_LPCG_CLK_0>,
+                        <&sdhc1_lpcg IMX_LPCG_CLK_5>;
+               clock-names = "ipg", "ahb", "per";
                power-domains = <&pd IMX_SC_R_SDHC_1>;
                fsl,tuning-start-tap = <20>;
                fsl,tuning-step = <2>;
@@ -62,9 +62,9 @@ conn_subsys: bus@5b000000 {
                interrupts = <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH>;
                reg = <0x5b030000 0x10000>;
                clocks = <&sdhc2_lpcg IMX_LPCG_CLK_4>,
-                        <&sdhc2_lpcg IMX_LPCG_CLK_5>,
-                        <&sdhc2_lpcg IMX_LPCG_CLK_0>;
-               clock-names = "ipg", "per", "ahb";
+                        <&sdhc2_lpcg IMX_LPCG_CLK_0>,
+                        <&sdhc2_lpcg IMX_LPCG_CLK_5>;
+               clock-names = "ipg", "ahb", "per";
                power-domains = <&pd IMX_SC_R_SDHC_2>;
                status = "disabled";
        };
index 32f6f2f..43e8985 100644 (file)
                /* SODIMM 96 */
                MX8MM_IOMUXC_SAI1_RXD2_GPIO4_IO4                        0x1c4
                /* CPLD_D[7] */
-               MX8MM_IOMUXC_SAI1_RXD3_GPIO4_IO5                        0x1c4
+               MX8MM_IOMUXC_SAI1_RXD3_GPIO4_IO5                        0x184
                /* CPLD_D[6] */
-               MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0                        0x1c4
+               MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0                        0x184
                /* CPLD_D[5] */
-               MX8MM_IOMUXC_SAI1_TXC_GPIO4_IO11                        0x1c4
+               MX8MM_IOMUXC_SAI1_TXC_GPIO4_IO11                        0x184
                /* CPLD_D[4] */
-               MX8MM_IOMUXC_SAI1_TXD0_GPIO4_IO12                       0x1c4
+               MX8MM_IOMUXC_SAI1_TXD0_GPIO4_IO12                       0x184
                /* CPLD_D[3] */
-               MX8MM_IOMUXC_SAI1_TXD1_GPIO4_IO13                       0x1c4
+               MX8MM_IOMUXC_SAI1_TXD1_GPIO4_IO13                       0x184
                /* CPLD_D[2] */
-               MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14                       0x1c4
+               MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14                       0x184
                /* CPLD_D[1] */
-               MX8MM_IOMUXC_SAI1_TXD3_GPIO4_IO15                       0x1c4
+               MX8MM_IOMUXC_SAI1_TXD3_GPIO4_IO15                       0x184
                /* CPLD_D[0] */
-               MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16                       0x1c4
+               MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16                       0x184
                /* KBD_intK */
                MX8MM_IOMUXC_SAI2_MCLK_GPIO4_IO27                       0x1c4
                /* DISP_reset */
index afb90f5..dabd94d 100644 (file)
                assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
                assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_100M>;
                clock-names = "main_clk";
+               power-domains = <&pgc_otg1>;
        };
 
        usbphynop2: usbphynop2 {
                assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
                assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_100M>;
                clock-names = "main_clk";
+               power-domains = <&pgc_otg2>;
        };
 
        soc: soc@0 {
                                        pgc_otg1: power-domain@2 {
                                                #power-domain-cells = <0>;
                                                reg = <IMX8MM_POWER_DOMAIN_OTG1>;
-                                               power-domains = <&pgc_hsiomix>;
                                        };
 
                                        pgc_otg2: power-domain@3 {
                                                #power-domain-cells = <0>;
                                                reg = <IMX8MM_POWER_DOMAIN_OTG2>;
-                                               power-domains = <&pgc_hsiomix>;
                                        };
 
                                        pgc_gpumix: power-domain@4 {
                                assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
                                phys = <&usbphynop1>;
                                fsl,usbmisc = <&usbmisc1 0>;
-                               power-domains = <&pgc_otg1>;
+                               power-domains = <&pgc_hsiomix>;
                                status = "disabled";
                        };
 
                                assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
                                phys = <&usbphynop2>;
                                fsl,usbmisc = <&usbmisc2 0>;
-                               power-domains = <&pgc_otg2>;
+                               power-domains = <&pgc_hsiomix>;
                                status = "disabled";
                        };
 
index cb2836b..ad0b99a 100644 (file)
                                        pgc_otg1: power-domain@1 {
                                                #power-domain-cells = <0>;
                                                reg = <IMX8MN_POWER_DOMAIN_OTG1>;
-                                               power-domains = <&pgc_hsiomix>;
                                        };
 
                                        pgc_gpumix: power-domain@2 {
                                assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_500M>;
                                phys = <&usbphynop1>;
                                fsl,usbmisc = <&usbmisc1 0>;
-                               power-domains = <&pgc_otg1>;
+                               power-domains = <&pgc_hsiomix>;
                                status = "disabled";
                        };
 
                assigned-clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
                assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_100M>;
                clock-names = "main_clk";
+               power-domains = <&pgc_otg1>;
        };
 };
index 7b712d1..5dcd1de 100644 (file)
                          "SODIMM_82",
                          "SODIMM_70",
                          "SODIMM_72";
-
-       ctrl-sleep-moci-hog {
-               gpio-hog;
-               /* Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */
-               gpios = <29 GPIO_ACTIVE_HIGH>;
-               line-name = "CTRL_SLEEP_MOCI#";
-               output-high;
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_ctrl_sleep_moci>;
-       };
 };
 
 &gpio3 {
                          "SODIMM_256",
                          "SODIMM_48",
                          "SODIMM_44";
+
+       ctrl-sleep-moci-hog {
+               gpio-hog;
+               /* Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */
+               gpios = <29 GPIO_ACTIVE_HIGH>;
+               line-name = "CTRL_SLEEP_MOCI#";
+               output-high;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ctrl_sleep_moci>;
+       };
 };
 
 /* On-module I2C */
index 3a5713b..0247866 100644 (file)
                        clocks = <&clk IMX93_CLK_GPIO2_GATE>,
                                 <&clk IMX93_CLK_GPIO2_GATE>;
                        clock-names = "gpio", "port";
-                       gpio-ranges = <&iomuxc 0 32 32>;
+                       gpio-ranges = <&iomuxc 0 4 30>;
                };
 
                gpio3: gpio@43820080 {
                        clocks = <&clk IMX93_CLK_GPIO3_GATE>,
                                 <&clk IMX93_CLK_GPIO3_GATE>;
                        clock-names = "gpio", "port";
-                       gpio-ranges = <&iomuxc 0 64 32>;
+                       gpio-ranges = <&iomuxc 0 84 8>, <&iomuxc 8 66 18>,
+                                     <&iomuxc 26 34 2>, <&iomuxc 28 0 4>;
                };
 
                gpio4: gpio@43830080 {
                        clocks = <&clk IMX93_CLK_GPIO4_GATE>,
                                 <&clk IMX93_CLK_GPIO4_GATE>;
                        clock-names = "gpio", "port";
-                       gpio-ranges = <&iomuxc 0 96 32>;
+                       gpio-ranges = <&iomuxc 0 38 28>, <&iomuxc 28 36 2>;
                };
 
                gpio1: gpio@47400080 {
                        clocks = <&clk IMX93_CLK_GPIO1_GATE>,
                                 <&clk IMX93_CLK_GPIO1_GATE>;
                        clock-names = "gpio", "port";
-                       gpio-ranges = <&iomuxc 0 0 32>;
+                       gpio-ranges = <&iomuxc 0 92 16>;
                };
 
                s4muap: mailbox@47520000 {
                        reg = <0x47520000 0x10000>;
                        interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-names = "txirq", "rxirq";
+                       interrupt-names = "tx", "rx";
                        #mbox-cells = <2>;
                };
 
index 439e2bc..d6cf535 100644 (file)
 
 #ifdef CONFIG_EFI
 extern void efi_init(void);
+
+bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg);
 #else
 #define efi_init()
+
+static inline
+bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)
+{
+       return false;
+}
 #endif
 
 int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
index 6062454..b3f37e2 100644 (file)
@@ -428,6 +428,30 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
        ARM64_FTR_END,
 };
 
+static const struct arm64_ftr_bits ftr_mvfr0[] = {
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPROUND_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSHVEC_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSQRT_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPDIVIDE_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPTRAP_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPDP_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSP_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_SIMD_SHIFT, 4, 0),
+       ARM64_FTR_END,
+};
+
+static const struct arm64_ftr_bits ftr_mvfr1[] = {
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDFMAC_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPHP_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDHP_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDSP_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDINT_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDLS_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPDNAN_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPFTZ_SHIFT, 4, 0),
+       ARM64_FTR_END,
+};
+
 static const struct arm64_ftr_bits ftr_mvfr2[] = {
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR2_FPMISC_SHIFT, 4, 0),
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR2_SIMDMISC_SHIFT, 4, 0),
@@ -458,10 +482,10 @@ static const struct arm64_ftr_bits ftr_id_isar0[] = {
 
 static const struct arm64_ftr_bits ftr_id_isar5[] = {
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_RDM_SHIFT, 4, 0),
-       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0),
-       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA2_SHIFT, 4, 0),
-       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA1_SHIFT, 4, 0),
-       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_AES_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA2_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA1_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_AES_SHIFT, 4, 0),
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SEVL_SHIFT, 4, 0),
        ARM64_FTR_END,
 };
@@ -574,7 +598,7 @@ static const struct arm64_ftr_bits ftr_smcr[] = {
  * Common ftr bits for a 32bit register with all hidden, strict
  * attributes, with 4bit feature fields and a default safe value of
  * 0. Covers the following 32bit registers:
- * id_isar[1-4], id_mmfr[1-3], id_pfr1, mvfr[0-1]
+ * id_isar[1-3], id_mmfr[1-3]
  */
 static const struct arm64_ftr_bits ftr_generic_32bits[] = {
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0),
@@ -645,8 +669,8 @@ static const struct __ftr_reg_entry {
        ARM64_FTR_REG(SYS_ID_ISAR6_EL1, ftr_id_isar6),
 
        /* Op1 = 0, CRn = 0, CRm = 3 */
-       ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_generic_32bits),
-       ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_generic_32bits),
+       ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_mvfr0),
+       ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_mvfr1),
        ARM64_FTR_REG(SYS_MVFR2_EL1, ftr_mvfr2),
        ARM64_FTR_REG(SYS_ID_PFR2_EL1, ftr_id_pfr2),
        ARM64_FTR_REG(SYS_ID_DFR1_EL1, ftr_id_dfr1),
@@ -3339,7 +3363,7 @@ static void __maybe_unused cpu_enable_cnp(struct arm64_cpu_capabilities const *c
 
 /*
  * We emulate only the following system register space.
- * Op0 = 0x3, CRn = 0x0, Op1 = 0x0, CRm = [0, 4 - 7]
+ * Op0 = 0x3, CRn = 0x0, Op1 = 0x0, CRm = [0, 2 - 7]
  * See Table C5-6 System instruction encodings for System register accesses,
  * ARMv8 ARM(ARM DDI 0487A.f) for more details.
  */
@@ -3349,7 +3373,7 @@ static inline bool __attribute_const__ is_emulated(u32 id)
                sys_reg_CRn(id) == 0x0 &&
                sys_reg_Op1(id) == 0x0 &&
                (sys_reg_CRm(id) == 0 ||
-                ((sys_reg_CRm(id) >= 4) && (sys_reg_CRm(id) <= 7))));
+                ((sys_reg_CRm(id) >= 2) && (sys_reg_CRm(id) <= 7))));
 }
 
 /*
index 75691a2..67babd5 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/linkage.h>
 
 SYM_FUNC_START(__efi_rt_asm_wrapper)
-       stp     x29, x30, [sp, #-32]!
+       stp     x29, x30, [sp, #-112]!
        mov     x29, sp
 
        /*
@@ -17,6 +17,20 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
        stp     x1, x18, [sp, #16]
 
        /*
+        * Preserve all callee saved registers and record the stack pointer
+        * value in a per-CPU variable so we can recover from synchronous
+        * exceptions occurring while running the firmware routines.
+        */
+       stp     x19, x20, [sp, #32]
+       stp     x21, x22, [sp, #48]
+       stp     x23, x24, [sp, #64]
+       stp     x25, x26, [sp, #80]
+       stp     x27, x28, [sp, #96]
+
+       adr_this_cpu    x8, __efi_rt_asm_recover_sp, x9
+       str             x29, [x8]
+
+       /*
         * We are lucky enough that no EFI runtime services take more than
         * 5 arguments, so all are passed in registers rather than via the
         * stack.
@@ -31,7 +45,7 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
 
        ldp     x1, x2, [sp, #16]
        cmp     x2, x18
-       ldp     x29, x30, [sp], #32
+       ldp     x29, x30, [sp], #112
        b.ne    0f
        ret
 0:
@@ -45,3 +59,18 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
        mov     x18, x2
        b       efi_handle_corrupted_x18        // tail call
 SYM_FUNC_END(__efi_rt_asm_wrapper)
+
+SYM_FUNC_START(__efi_rt_asm_recover)
+       ldr_this_cpu    x8, __efi_rt_asm_recover_sp, x9
+       mov             sp, x8
+
+       ldp     x0,  x18, [sp, #16]
+       ldp     x19, x20, [sp, #32]
+       ldp     x21, x22, [sp, #48]
+       ldp     x23, x24, [sp, #64]
+       ldp     x25, x26, [sp, #80]
+       ldp     x27, x28, [sp, #96]
+       ldp     x29, x30, [sp], #112
+
+       b       efi_handle_runtime_exception
+SYM_FUNC_END(__efi_rt_asm_recover)
index e1be6c4..8d36e66 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/efi.h>
 #include <linux/init.h>
+#include <linux/percpu.h>
 
 #include <asm/efi.h>
 
@@ -128,3 +129,28 @@ asmlinkage efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f)
        pr_err_ratelimited(FW_BUG "register x18 corrupted by EFI %s\n", f);
        return s;
 }
+
+asmlinkage DEFINE_PER_CPU(u64, __efi_rt_asm_recover_sp);
+
+asmlinkage efi_status_t __efi_rt_asm_recover(void);
+
+asmlinkage efi_status_t efi_handle_runtime_exception(const char *f)
+{
+       pr_err(FW_BUG "Synchronous exception occurred in EFI runtime service %s()\n", f);
+       clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+       return EFI_ABORTED;
+}
+
+bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)
+{
+        /* Check whether the exception occurred while running the firmware */
+       if (current_work() != &efi_rts_work.work || regs->pc >= TASK_SIZE_64)
+               return false;
+
+       pr_err(FW_BUG "Unable to handle %s in EFI runtime service\n", msg);
+       add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
+       dump_stack();
+
+       regs->pc = (u64)__efi_rt_asm_recover;
+       return true;
+}
index 9173fad..27369fa 100644 (file)
@@ -329,7 +329,8 @@ static void cortex_a76_erratum_1463225_svc_handler(void)
        __this_cpu_write(__in_cortex_a76_erratum_1463225_wa, 0);
 }
 
-static bool cortex_a76_erratum_1463225_debug_handler(struct pt_regs *regs)
+static __always_inline bool
+cortex_a76_erratum_1463225_debug_handler(struct pt_regs *regs)
 {
        if (!__this_cpu_read(__in_cortex_a76_erratum_1463225_wa))
                return false;
index 5b39149..3e9cf98 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/bug.h>
 #include <asm/cmpxchg.h>
 #include <asm/cpufeature.h>
+#include <asm/efi.h>
 #include <asm/exception.h>
 #include <asm/daifflags.h>
 #include <asm/debug-monitors.h>
@@ -391,6 +392,9 @@ static void __do_kernel_fault(unsigned long addr, unsigned long esr,
                msg = "paging request";
        }
 
+       if (efi_runtime_fixup_exception(regs, msg))
+               return;
+
        die_kernel_fault(msg, addr, esr, regs);
 }
 
index 699df27..2ca5418 100644 (file)
@@ -147,6 +147,7 @@ config PPC
        select ARCH_MIGHT_HAVE_PC_SERIO
        select ARCH_OPTIONAL_KERNEL_RWX         if ARCH_HAS_STRICT_KERNEL_RWX
        select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
+       select ARCH_SPLIT_ARG64                 if PPC32
        select ARCH_STACKWALK
        select ARCH_SUPPORTS_ATOMIC_RMW
        select ARCH_SUPPORTS_DEBUG_PAGEALLOC    if PPC_BOOK3S || PPC_8xx || 40x
@@ -285,7 +286,7 @@ config PPC
        #
 
 config PPC_LONG_DOUBLE_128
-       depends on PPC64
+       depends on PPC64 && ALTIVEC
        def_bool $(success,test "$(shell,echo __LONG_DOUBLE_128__ | $(CC) -E -P -)" = 1)
 
 config PPC_BARRIER_NOSPEC
index a114249..6d51b00 100644 (file)
@@ -104,6 +104,13 @@ long sys_ppc_ftruncate64(unsigned int fd, u32 reg4,
                         unsigned long len1, unsigned long len2);
 long sys_ppc32_fadvise64(int fd, u32 unused, u32 offset1, u32 offset2,
                         size_t len, int advice);
+long sys_ppc_sync_file_range2(int fd, unsigned int flags,
+                             unsigned int offset1,
+                             unsigned int offset2,
+                             unsigned int nbytes1,
+                             unsigned int nbytes2);
+long sys_ppc_fallocate(int fd, int mode, u32 offset1, u32 offset2,
+                      u32 len1, u32 len2);
 #endif
 #ifdef CONFIG_COMPAT
 long compat_sys_mmap2(unsigned long addr, size_t len,
index 1ab4a4d..d451a82 100644 (file)
@@ -112,7 +112,7 @@ PPC32_SYSCALL_DEFINE6(ppc32_fadvise64,
                                 advice);
 }
 
-COMPAT_SYSCALL_DEFINE6(ppc_sync_file_range2,
+PPC32_SYSCALL_DEFINE6(ppc_sync_file_range2,
                       int, fd, unsigned int, flags,
                       unsigned int, offset1, unsigned int, offset2,
                       unsigned int, nbytes1, unsigned int, nbytes2)
@@ -122,3 +122,14 @@ COMPAT_SYSCALL_DEFINE6(ppc_sync_file_range2,
 
        return ksys_sync_file_range(fd, offset, nbytes, flags);
 }
+
+#ifdef CONFIG_PPC32
+SYSCALL_DEFINE6(ppc_fallocate,
+               int, fd, int, mode,
+               u32, offset1, u32, offset2, u32, len1, u32, len2)
+{
+       return ksys_fallocate(fd, mode,
+                             merge_64(offset1, offset2),
+                             merge_64(len1, len2));
+}
+#endif
index e9e0df4..a0be127 100644 (file)
 305    common  signalfd                        sys_signalfd                    compat_sys_signalfd
 306    common  timerfd_create                  sys_timerfd_create
 307    common  eventfd                         sys_eventfd
-308    common  sync_file_range2                sys_sync_file_range2            compat_sys_ppc_sync_file_range2
-309    nospu   fallocate                       sys_fallocate                   compat_sys_fallocate
+308    32      sync_file_range2                sys_ppc_sync_file_range2        compat_sys_ppc_sync_file_range2
+308    64      sync_file_range2                sys_sync_file_range2
+308    spu     sync_file_range2                sys_sync_file_range2
+309    32      fallocate                       sys_ppc_fallocate               compat_sys_fallocate
+309    64      fallocate                       sys_fallocate
 310    nospu   subpage_prot                    sys_subpage_prot
 311    32      timerfd_settime                 sys_timerfd_settime32
 311    64      timerfd_settime                 sys_timerfd_settime
index 68aff13..246d67d 100644 (file)
@@ -302,7 +302,7 @@ static bool xen_amd_pmu_emulate(unsigned int msr, u64 *val, bool is_read)
 static bool pmu_msr_chk_emulated(unsigned int msr, uint64_t *val, bool is_read,
                                 bool *emul)
 {
-       int type, index;
+       int type, index = 0;
 
        if (is_amd_pmu_msr(msr))
                *emul = xen_amd_pmu_emulate(msr, val, is_read);
index cfa99e8..4f43095 100644 (file)
@@ -910,17 +910,9 @@ static int register_callback(unsigned type, const void *func)
 
 void xen_enable_sysenter(void)
 {
-       int ret;
-       unsigned sysenter_feature;
-
-       sysenter_feature = X86_FEATURE_SYSENTER32;
-
-       if (!boot_cpu_has(sysenter_feature))
-               return;
-
-       ret = register_callback(CALLBACKTYPE_sysenter, xen_entry_SYSENTER_compat);
-       if(ret != 0)
-               setup_clear_cpu_cap(sysenter_feature);
+       if (cpu_feature_enabled(X86_FEATURE_SYSENTER32) &&
+           register_callback(CALLBACKTYPE_sysenter, xen_entry_SYSENTER_compat))
+               setup_clear_cpu_cap(X86_FEATURE_SYSENTER32);
 }
 
 void xen_enable_syscall(void)
@@ -934,12 +926,9 @@ void xen_enable_syscall(void)
                   mechanism for syscalls. */
        }
 
-       if (boot_cpu_has(X86_FEATURE_SYSCALL32)) {
-               ret = register_callback(CALLBACKTYPE_syscall32,
-                                       xen_entry_SYSCALL_compat);
-               if (ret != 0)
-                       setup_clear_cpu_cap(X86_FEATURE_SYSCALL32);
-       }
+       if (cpu_feature_enabled(X86_FEATURE_SYSCALL32) &&
+           register_callback(CALLBACKTYPE_syscall32, xen_entry_SYSCALL_compat))
+               setup_clear_cpu_cap(X86_FEATURE_SYSCALL32);
 }
 
 static void __init xen_pvmmu_arch_setup(void)
index 75c8296..6a789cd 100644 (file)
@@ -1262,6 +1262,7 @@ static void blk_add_rq_to_plug(struct blk_plug *plug, struct request *rq)
                   (!blk_queue_nomerges(rq->q) &&
                    blk_rq_bytes(last) >= BLK_PLUG_FLUSH_SIZE)) {
                blk_mq_flush_plug_list(plug, false);
+               last = NULL;
                trace_block_plug(rq->q);
        }
 
@@ -4193,9 +4194,7 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
        return 0;
 
 err_hctxs:
-       xa_destroy(&q->hctx_table);
-       q->nr_hw_queues = 0;
-       blk_mq_sysfs_deinit(q);
+       blk_mq_release(q);
 err_poll:
        blk_stat_free_callback(q->poll_cb);
        q->poll_cb = NULL;
index fee90eb..0f9769d 100644 (file)
@@ -527,6 +527,7 @@ out_unregister_bdi:
                bdi_unregister(disk->bdi);
 out_unregister_queue:
        blk_unregister_queue(disk);
+       rq_qos_exit(disk->queue);
 out_put_slave_dir:
        kobject_put(disk->slave_dir);
 out_put_holder_dir:
index f8a2cbd..d7d3f16 100644 (file)
@@ -219,6 +219,12 @@ static const struct dmi_system_id force_storage_d3_dmi[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 14 7425 2-in-1"),
                }
        },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 16 5625"),
+               }
+       },
        {}
 };
 
index 0a8bf09..03c5806 100644 (file)
@@ -315,9 +315,10 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
        outb(inb(0x1F4) & 0x07, 0x1F4);
 
        rt = inb(0x1F3);
-       rt &= 0x07 << (3 * adev->devno);
+       rt &= ~(0x07 << (3 * !adev->devno));
        if (pio)
-               rt |= (1 + 3 * pio) << (3 * adev->devno);
+               rt |= (1 + 3 * pio) << (3 * !adev->devno);
+       outb(rt, 0x1F3);
 
        udelay(100);
        outb(inb(0x1F2) | 0x01, 0x1F2);
index 400e651..51caa2a 100644 (file)
@@ -63,8 +63,8 @@ static int palmld_pata_probe(struct platform_device *pdev)
 
        /* remap drive's physical memory address */
        mem = devm_platform_ioremap_resource(pdev, 0);
-       if (!mem)
-               return -ENOMEM;
+       if (IS_ERR(mem))
+               return PTR_ERR(mem);
 
        /* request and activate power and reset GPIOs */
        lda->power = devm_gpiod_get(dev, "power", GPIOD_OUT_HIGH);
index db1b4b2..a41145d 100644 (file)
@@ -408,6 +408,12 @@ config BLK_DEV_UBLK
          definition isn't finalized yet, and might change according to future
          requirement, so mark is as experimental now.
 
+         Say Y if you want to get better performance because task_work_add()
+         can be used in IO path for replacing io_uring cmd, which will become
+         shared between IO tasks and ubq daemon, meantime task_work_add() can
+         can handle batch more effectively, but task_work_add() isn't exported
+         for module, so ublk has to be built to kernel.
+
 source "drivers/block/rnbd/Kconfig"
 
 endif # BLK_DEV
index 5afce6f..f96cb01 100644 (file)
 #define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD)
 
 struct ublk_rq_data {
-       struct callback_head work;
+       union {
+               struct callback_head work;
+               struct llist_node node;
+       };
 };
 
 struct ublk_uring_cmd_pdu {
-       struct request *req;
+       struct ublk_queue *ubq;
 };
 
 /*
@@ -119,6 +122,8 @@ struct ublk_queue {
        struct task_struct      *ubq_daemon;
        char *io_cmd_buf;
 
+       struct llist_head       io_cmds;
+
        unsigned long io_addr;  /* mapped vm address */
        unsigned int max_io_sz;
        bool force_abort;
@@ -764,8 +769,12 @@ static inline void __ublk_rq_task_work(struct request *req)
 static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd)
 {
        struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
+       struct ublk_queue *ubq = pdu->ubq;
+       struct llist_node *io_cmds = llist_del_all(&ubq->io_cmds);
+       struct ublk_rq_data *data;
 
-       __ublk_rq_task_work(pdu->req);
+       llist_for_each_entry(data, io_cmds, node)
+               __ublk_rq_task_work(blk_mq_rq_from_pdu(data));
 }
 
 static void ublk_rq_task_work_fn(struct callback_head *work)
@@ -777,6 +786,54 @@ static void ublk_rq_task_work_fn(struct callback_head *work)
        __ublk_rq_task_work(req);
 }
 
+static void ublk_submit_cmd(struct ublk_queue *ubq, const struct request *rq)
+{
+       struct ublk_io *io = &ubq->ios[rq->tag];
+
+       /*
+        * If the check pass, we know that this is a re-issued request aborted
+        * previously in monitor_work because the ubq_daemon(cmd's task) is
+        * PF_EXITING. We cannot call io_uring_cmd_complete_in_task() anymore
+        * because this ioucmd's io_uring context may be freed now if no inflight
+        * ioucmd exists. Otherwise we may cause null-deref in ctx->fallback_work.
+        *
+        * Note: monitor_work sets UBLK_IO_FLAG_ABORTED and ends this request(releasing
+        * the tag). Then the request is re-started(allocating the tag) and we are here.
+        * Since releasing/allocating a tag implies smp_mb(), finding UBLK_IO_FLAG_ABORTED
+        * guarantees that here is a re-issued request aborted previously.
+        */
+       if (unlikely(io->flags & UBLK_IO_FLAG_ABORTED)) {
+               struct llist_node *io_cmds = llist_del_all(&ubq->io_cmds);
+               struct ublk_rq_data *data;
+
+               llist_for_each_entry(data, io_cmds, node)
+                       __ublk_abort_rq(ubq, blk_mq_rq_from_pdu(data));
+       } else {
+               struct io_uring_cmd *cmd = io->cmd;
+               struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
+
+               pdu->ubq = ubq;
+               io_uring_cmd_complete_in_task(cmd, ublk_rq_task_work_cb);
+       }
+}
+
+static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq,
+               bool last)
+{
+       struct ublk_rq_data *data = blk_mq_rq_to_pdu(rq);
+
+       if (ublk_can_use_task_work(ubq)) {
+               enum task_work_notify_mode notify_mode = last ?
+                       TWA_SIGNAL_NO_IPI : TWA_NONE;
+
+               if (task_work_add(ubq->ubq_daemon, &data->work, notify_mode))
+                       __ublk_abort_rq(ubq, rq);
+       } else {
+               if (llist_add(&data->node, &ubq->io_cmds))
+                       ublk_submit_cmd(ubq, rq);
+       }
+}
+
 static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx,
                const struct blk_mq_queue_data *bd)
 {
@@ -788,6 +845,7 @@ static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx,
        res = ublk_setup_iod(ubq, rq);
        if (unlikely(res != BLK_STS_OK))
                return BLK_STS_IOERR;
+
        /* With recovery feature enabled, force_abort is set in
         * ublk_stop_dev() before calling del_gendisk(). We have to
         * abort all requeued and new rqs here to let del_gendisk()
@@ -803,41 +861,11 @@ static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx,
        blk_mq_start_request(bd->rq);
 
        if (unlikely(ubq_daemon_is_dying(ubq))) {
- fail:
                __ublk_abort_rq(ubq, rq);
                return BLK_STS_OK;
        }
 
-       if (ublk_can_use_task_work(ubq)) {
-               struct ublk_rq_data *data = blk_mq_rq_to_pdu(rq);
-               enum task_work_notify_mode notify_mode = bd->last ?
-                       TWA_SIGNAL_NO_IPI : TWA_NONE;
-
-               if (task_work_add(ubq->ubq_daemon, &data->work, notify_mode))
-                       goto fail;
-       } else {
-               struct ublk_io *io = &ubq->ios[rq->tag];
-               struct io_uring_cmd *cmd = io->cmd;
-               struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
-
-               /*
-                * If the check pass, we know that this is a re-issued request aborted
-                * previously in monitor_work because the ubq_daemon(cmd's task) is
-                * PF_EXITING. We cannot call io_uring_cmd_complete_in_task() anymore
-                * because this ioucmd's io_uring context may be freed now if no inflight
-                * ioucmd exists. Otherwise we may cause null-deref in ctx->fallback_work.
-                *
-                * Note: monitor_work sets UBLK_IO_FLAG_ABORTED and ends this request(releasing
-                * the tag). Then the request is re-started(allocating the tag) and we are here.
-                * Since releasing/allocating a tag implies smp_mb(), finding UBLK_IO_FLAG_ABORTED
-                * guarantees that here is a re-issued request aborted previously.
-                */
-               if ((io->flags & UBLK_IO_FLAG_ABORTED))
-                       goto fail;
-
-               pdu->req = rq;
-               io_uring_cmd_complete_in_task(cmd, ublk_rq_task_work_cb);
-       }
+       ublk_queue_cmd(ubq, rq, bd->last);
 
        return BLK_STS_OK;
 }
@@ -1164,22 +1192,12 @@ static void ublk_mark_io_ready(struct ublk_device *ub, struct ublk_queue *ubq)
 }
 
 static void ublk_handle_need_get_data(struct ublk_device *ub, int q_id,
-               int tag, struct io_uring_cmd *cmd)
+               int tag)
 {
        struct ublk_queue *ubq = ublk_get_queue(ub, q_id);
        struct request *req = blk_mq_tag_to_rq(ub->tag_set.tags[q_id], tag);
 
-       if (ublk_can_use_task_work(ubq)) {
-               struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
-
-               /* should not fail since we call it just in ubq->ubq_daemon */
-               task_work_add(ubq->ubq_daemon, &data->work, TWA_SIGNAL_NO_IPI);
-       } else {
-               struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
-
-               pdu->req = req;
-               io_uring_cmd_complete_in_task(cmd, ublk_rq_task_work_cb);
-       }
+       ublk_queue_cmd(ubq, req, true);
 }
 
 static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
@@ -1267,7 +1285,7 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
                io->addr = ub_cmd->addr;
                io->cmd = cmd;
                io->flags |= UBLK_IO_FLAG_ACTIVE;
-               ublk_handle_need_get_data(ub, ub_cmd->q_id, ub_cmd->tag, cmd);
+               ublk_handle_need_get_data(ub, ub_cmd->q_id, ub_cmd->tag);
                break;
        default:
                goto out;
@@ -1658,6 +1676,9 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
         */
        ub->dev_info.flags &= UBLK_F_ALL;
 
+       if (!IS_BUILTIN(CONFIG_BLK_DEV_UBLK))
+               ub->dev_info.flags |= UBLK_F_URING_CMD_COMP_IN_TASK;
+
        /* We are not ready to support zero copy */
        ub->dev_info.flags &= ~UBLK_F_SUPPORT_ZERO_COPY;
 
index 67c2126..fd281d4 100644 (file)
@@ -219,7 +219,7 @@ static void virtbt_rx_work(struct work_struct *work)
        if (!skb)
                return;
 
-       skb->len = len;
+       skb_put(skb, len);
        virtbt_rx_handle(vbt, skb);
 
        if (virtbt_add_inbuf(vbt) < 0)
index 4f5df1f..e624714 100644 (file)
@@ -90,13 +90,66 @@ static const struct regmap_access_table rs9_writeable_table = {
        .n_yes_ranges = ARRAY_SIZE(rs9_writeable_ranges),
 };
 
+static int rs9_regmap_i2c_write(void *context,
+                               unsigned int reg, unsigned int val)
+{
+       struct i2c_client *i2c = context;
+       const u8 data[3] = { reg, 1, val };
+       const int count = ARRAY_SIZE(data);
+       int ret;
+
+       ret = i2c_master_send(i2c, data, count);
+       if (ret == count)
+               return 0;
+       else if (ret < 0)
+               return ret;
+       else
+               return -EIO;
+}
+
+static int rs9_regmap_i2c_read(void *context,
+                              unsigned int reg, unsigned int *val)
+{
+       struct i2c_client *i2c = context;
+       struct i2c_msg xfer[2];
+       u8 txdata = reg;
+       u8 rxdata[2];
+       int ret;
+
+       xfer[0].addr = i2c->addr;
+       xfer[0].flags = 0;
+       xfer[0].len = 1;
+       xfer[0].buf = (void *)&txdata;
+
+       xfer[1].addr = i2c->addr;
+       xfer[1].flags = I2C_M_RD;
+       xfer[1].len = 2;
+       xfer[1].buf = (void *)rxdata;
+
+       ret = i2c_transfer(i2c->adapter, xfer, 2);
+       if (ret < 0)
+               return ret;
+       if (ret != 2)
+               return -EIO;
+
+       /*
+        * Byte 0 is transfer length, which is always 1 due
+        * to BCP register programming to 1 in rs9_probe(),
+        * ignore it and use data from Byte 1.
+        */
+       *val = rxdata[1];
+       return 0;
+}
+
 static const struct regmap_config rs9_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
-       .cache_type = REGCACHE_FLAT,
-       .max_register = 0x8,
+       .cache_type = REGCACHE_NONE,
+       .max_register = RS9_REG_BCP,
        .rd_table = &rs9_readable_table,
        .wr_table = &rs9_writeable_table,
+       .reg_write = rs9_regmap_i2c_write,
+       .reg_read = rs9_regmap_i2c_read,
 };
 
 static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx)
@@ -242,11 +295,17 @@ static int rs9_probe(struct i2c_client *client)
                        return ret;
        }
 
-       rs9->regmap = devm_regmap_init_i2c(client, &rs9_regmap_config);
+       rs9->regmap = devm_regmap_init(&client->dev, NULL,
+                                      client, &rs9_regmap_config);
        if (IS_ERR(rs9->regmap))
                return dev_err_probe(&client->dev, PTR_ERR(rs9->regmap),
                                     "Failed to allocate register map\n");
 
+       /* Always read back 1 Byte via I2C */
+       ret = regmap_write(rs9->regmap, RS9_REG_BCP, 1);
+       if (ret < 0)
+               return ret;
+
        /* Register clock */
        for (i = 0; i < rs9->chip_info->num_clks; i++) {
                snprintf(name, 5, "DIF%d", i);
index c3c3f8c..57b8366 100644 (file)
@@ -1459,10 +1459,14 @@ static void clk_core_init_rate_req(struct clk_core * const core,
 {
        struct clk_core *parent;
 
-       if (WARN_ON(!core || !req))
+       if (WARN_ON(!req))
                return;
 
        memset(req, 0, sizeof(*req));
+       req->max_rate = ULONG_MAX;
+
+       if (!core)
+               return;
 
        req->rate = rate;
        clk_core_get_boundaries(core, &req->min_rate, &req->max_rate);
index 8cbab5c..1e01632 100644 (file)
@@ -1270,8 +1270,10 @@ static int clk_mt8195_topck_probe(struct platform_device *pdev)
        hw = devm_clk_hw_register_mux(&pdev->dev, "mfg_ck_fast_ref", mfg_fast_parents,
                                      ARRAY_SIZE(mfg_fast_parents), CLK_SET_RATE_PARENT,
                                      (base + 0x250), 8, 1, 0, &mt8195_clk_lock);
-       if (IS_ERR(hw))
+       if (IS_ERR(hw)) {
+               r = PTR_ERR(hw);
                goto unregister_muxes;
+       }
        top_clk_data->hws[CLK_TOP_MFG_CK_FAST_REF] = hw;
 
        r = clk_mt8195_reg_mfg_mux_notifier(&pdev->dev,
index 8afb757..46d41eb 100644 (file)
@@ -3467,6 +3467,7 @@ static int gcc_sc7280_probe(struct platform_device *pdev)
        regmap_update_bits(regmap, 0x28004, BIT(0), BIT(0));
        regmap_update_bits(regmap, 0x28014, BIT(0), BIT(0));
        regmap_update_bits(regmap, 0x71004, BIT(0), BIT(0));
+       regmap_update_bits(regmap, 0x7100C, BIT(13), BIT(13));
 
        ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks,
                        ARRAY_SIZE(gcc_dfs_clocks));
index 9a832f2..1490cd4 100644 (file)
@@ -463,6 +463,7 @@ static int gpu_cc_sc7280_probe(struct platform_device *pdev)
         */
        regmap_update_bits(regmap, 0x1170, BIT(0), BIT(0));
        regmap_update_bits(regmap, 0x1098, BIT(0), BIT(0));
+       regmap_update_bits(regmap, 0x1098, BIT(13), BIT(13));
 
        return qcom_cc_really_probe(pdev, &gpu_cc_sc7280_desc, regmap);
 }
index 9641122..d5b325e 100644 (file)
@@ -47,6 +47,7 @@ enum clk_ids {
        CLK_S0_VIO,
        CLK_S0_VC,
        CLK_S0_HSC,
+       CLK_SASYNCPER,
        CLK_SV_VIP,
        CLK_SV_IR,
        CLK_SDSRC,
@@ -84,6 +85,7 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
        DEF_FIXED(".s0_vio",    CLK_S0_VIO,     CLK_PLL1_DIV2,  2, 1),
        DEF_FIXED(".s0_vc",     CLK_S0_VC,      CLK_PLL1_DIV2,  2, 1),
        DEF_FIXED(".s0_hsc",    CLK_S0_HSC,     CLK_PLL1_DIV2,  2, 1),
+       DEF_FIXED(".sasyncper", CLK_SASYNCPER,  CLK_PLL5_DIV4,  3, 1),
        DEF_FIXED(".sv_vip",    CLK_SV_VIP,     CLK_PLL1,       5, 1),
        DEF_FIXED(".sv_ir",     CLK_SV_IR,      CLK_PLL1,       5, 1),
        DEF_BASE(".sdsrc",      CLK_SDSRC,      CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
@@ -128,6 +130,9 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
        DEF_FIXED("s0d4_hsc",   R8A779G0_CLK_S0D4_HSC,  CLK_S0_HSC,     4, 1),
        DEF_FIXED("cl16m_hsc",  R8A779G0_CLK_CL16M_HSC, CLK_S0_HSC,     48, 1),
        DEF_FIXED("s0d2_cc",    R8A779G0_CLK_S0D2_CC,   CLK_S0,         2, 1),
+       DEF_FIXED("sasyncperd1",R8A779G0_CLK_SASYNCPERD1, CLK_SASYNCPER,1, 1),
+       DEF_FIXED("sasyncperd2",R8A779G0_CLK_SASYNCPERD2, CLK_SASYNCPER,2, 1),
+       DEF_FIXED("sasyncperd4",R8A779G0_CLK_SASYNCPERD4, CLK_SASYNCPER,4, 1),
        DEF_FIXED("svd1_ir",    R8A779G0_CLK_SVD1_IR,   CLK_SV_IR,      1, 1),
        DEF_FIXED("svd2_ir",    R8A779G0_CLK_SVD2_IR,   CLK_SV_IR,      2, 1),
        DEF_FIXED("svd1_vip",   R8A779G0_CLK_SVD1_VIP,  CLK_SV_VIP,     1, 1),
@@ -153,10 +158,10 @@ static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = {
        DEF_MOD("avb0",         211,    R8A779G0_CLK_S0D4_HSC),
        DEF_MOD("avb1",         212,    R8A779G0_CLK_S0D4_HSC),
        DEF_MOD("avb2",         213,    R8A779G0_CLK_S0D4_HSC),
-       DEF_MOD("hscif0",       514,    R8A779G0_CLK_S0D3_PER),
-       DEF_MOD("hscif1",       515,    R8A779G0_CLK_S0D3_PER),
-       DEF_MOD("hscif2",       516,    R8A779G0_CLK_S0D3_PER),
-       DEF_MOD("hscif3",       517,    R8A779G0_CLK_S0D3_PER),
+       DEF_MOD("hscif0",       514,    R8A779G0_CLK_SASYNCPERD1),
+       DEF_MOD("hscif1",       515,    R8A779G0_CLK_SASYNCPERD1),
+       DEF_MOD("hscif2",       516,    R8A779G0_CLK_SASYNCPERD1),
+       DEF_MOD("hscif3",       517,    R8A779G0_CLK_SASYNCPERD1),
        DEF_MOD("i2c0",         518,    R8A779G0_CLK_S0D6_PER),
        DEF_MOD("i2c1",         519,    R8A779G0_CLK_S0D6_PER),
        DEF_MOD("i2c2",         520,    R8A779G0_CLK_S0D6_PER),
index 9132c3c..b7fde0a 100644 (file)
@@ -2,7 +2,8 @@
 
 menuconfig CLK_SIFIVE
        bool "SiFive SoC driver support"
-       depends on RISCV || COMPILE_TEST
+       depends on SOC_SIFIVE || COMPILE_TEST
+       default SOC_SIFIVE
        help
          SoC drivers for SiFive Linux-capable SoCs.
 
@@ -10,6 +11,7 @@ if CLK_SIFIVE
 
 config CLK_SIFIVE_PRCI
        bool "PRCI driver for SiFive SoCs"
+       default SOC_SIFIVE
        select RESET_CONTROLLER
        select RESET_SIMPLE
        select CLK_ANALOGBITS_WRPLL_CLN28HPC
index d4e2310..35bb707 100644 (file)
@@ -216,9 +216,20 @@ void scmi_device_destroy(struct scmi_device *scmi_dev)
        device_unregister(&scmi_dev->dev);
 }
 
+void scmi_device_link_add(struct device *consumer, struct device *supplier)
+{
+       struct device_link *link;
+
+       link = device_link_add(consumer, supplier, DL_FLAG_AUTOREMOVE_CONSUMER);
+
+       WARN_ON(!link);
+}
+
 void scmi_set_handle(struct scmi_device *scmi_dev)
 {
        scmi_dev->handle = scmi_handle_get(&scmi_dev->dev);
+       if (scmi_dev->handle)
+               scmi_device_link_add(&scmi_dev->dev, scmi_dev->handle->dev);
 }
 
 int scmi_protocol_register(const struct scmi_protocol *proto)
index 61aba74..a1c0154 100644 (file)
@@ -97,6 +97,7 @@ static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr)
 struct scmi_revision_info *
 scmi_revision_area_get(const struct scmi_protocol_handle *ph);
 int scmi_handle_put(const struct scmi_handle *handle);
+void scmi_device_link_add(struct device *consumer, struct device *supplier);
 struct scmi_handle *scmi_handle_get(struct device *dev);
 void scmi_set_handle(struct scmi_device *scmi_dev);
 void scmi_setup_protocol_implemented(const struct scmi_protocol_handle *ph,
@@ -117,6 +118,7 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id);
  *
  * @dev: Reference to device in the SCMI hierarchy corresponding to this
  *      channel
+ * @rx_timeout_ms: The configured RX timeout in milliseconds.
  * @handle: Pointer to SCMI entity handle
  * @no_completion_irq: Flag to indicate that this channel has no completion
  *                    interrupt mechanism for synchronous commands.
@@ -126,6 +128,7 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id);
  */
 struct scmi_chan_info {
        struct device *dev;
+       unsigned int rx_timeout_ms;
        struct scmi_handle *handle;
        bool no_completion_irq;
        void *transport_info;
@@ -232,7 +235,7 @@ void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id);
 struct scmi_shared_mem;
 
 void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem,
-                     struct scmi_xfer *xfer);
+                     struct scmi_xfer *xfer, struct scmi_chan_info *cinfo);
 u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem);
 void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
                          struct scmi_xfer *xfer);
index 609ebed..f818d00 100644 (file)
@@ -2013,6 +2013,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device *dev,
                return -ENOMEM;
 
        cinfo->dev = dev;
+       cinfo->rx_timeout_ms = info->desc->max_rx_timeout_ms;
 
        ret = info->desc->ops->chan_setup(cinfo, info->dev, tx);
        if (ret)
@@ -2044,8 +2045,12 @@ scmi_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id)
 {
        int ret = scmi_chan_setup(info, dev, prot_id, true);
 
-       if (!ret) /* Rx is optional, hence no error check */
-               scmi_chan_setup(info, dev, prot_id, false);
+       if (!ret) {
+               /* Rx is optional, report only memory errors */
+               ret = scmi_chan_setup(info, dev, prot_id, false);
+               if (ret && ret != -ENOMEM)
+                       ret = 0;
+       }
 
        return ret;
 }
@@ -2273,10 +2278,16 @@ int scmi_protocol_device_request(const struct scmi_device_id *id_table)
                        sdev = scmi_get_protocol_device(child, info,
                                                        id_table->protocol_id,
                                                        id_table->name);
-                       /* Set handle if not already set: device existed */
-                       if (sdev && !sdev->handle)
-                               sdev->handle =
-                                       scmi_handle_get_from_info_unlocked(info);
+                       if (sdev) {
+                               /* Set handle if not already set: device existed */
+                               if (!sdev->handle)
+                                       sdev->handle =
+                                               scmi_handle_get_from_info_unlocked(info);
+                               /* Relink consumer and suppliers */
+                               if (sdev->handle)
+                                       scmi_device_link_add(&sdev->dev,
+                                                            sdev->handle->dev);
+                       }
                } else {
                        dev_err(info->dev,
                                "Failed. SCMI protocol %d not active.\n",
@@ -2475,20 +2486,17 @@ void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id)
 
 static int scmi_remove(struct platform_device *pdev)
 {
-       int ret = 0, id;
+       int ret, id;
        struct scmi_info *info = platform_get_drvdata(pdev);
        struct device_node *child;
 
        mutex_lock(&scmi_list_mutex);
        if (info->users)
-               ret = -EBUSY;
-       else
-               list_del(&info->node);
+               dev_warn(&pdev->dev,
+                        "Still active SCMI users will be forcibly unbound.\n");
+       list_del(&info->node);
        mutex_unlock(&scmi_list_mutex);
 
-       if (ret)
-               return ret;
-
        scmi_notification_exit(&info->handle);
 
        mutex_lock(&info->protocols_mtx);
@@ -2500,7 +2508,11 @@ static int scmi_remove(struct platform_device *pdev)
        idr_destroy(&info->active_protocols);
 
        /* Safe to free channels since no more users */
-       return scmi_cleanup_txrx_channels(info);
+       ret = scmi_cleanup_txrx_channels(info);
+       if (ret)
+               dev_warn(&pdev->dev, "Failed to cleanup SCMI channels.\n");
+
+       return 0;
 }
 
 static ssize_t protocol_version_show(struct device *dev,
@@ -2571,6 +2583,7 @@ MODULE_DEVICE_TABLE(of, scmi_of_match);
 static struct platform_driver scmi_driver = {
        .driver = {
                   .name = "arm-scmi",
+                  .suppress_bind_attrs = true,
                   .of_match_table = scmi_of_match,
                   .dev_groups = versions_groups,
                   },
index 08ff4d1..1e40cb0 100644 (file)
@@ -36,7 +36,7 @@ static void tx_prepare(struct mbox_client *cl, void *m)
 {
        struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl);
 
-       shmem_tx_prepare(smbox->shmem, m);
+       shmem_tx_prepare(smbox->shmem, m, smbox->cinfo);
 }
 
 static void rx_callback(struct mbox_client *cl, void *m)
index f42dad9..2a7aeab 100644 (file)
@@ -498,7 +498,7 @@ static int scmi_optee_send_message(struct scmi_chan_info *cinfo,
                msg_tx_prepare(channel->req.msg, xfer);
                ret = invoke_process_msg_channel(channel, msg_command_size(xfer));
        } else {
-               shmem_tx_prepare(channel->req.shmem, xfer);
+               shmem_tx_prepare(channel->req.shmem, xfer, cinfo);
                ret = invoke_process_smt_channel(channel);
        }
 
index 0e3eaea..1dfe534 100644 (file)
@@ -5,10 +5,13 @@
  * Copyright (C) 2019 ARM Ltd.
  */
 
+#include <linux/ktime.h>
 #include <linux/io.h>
 #include <linux/processor.h>
 #include <linux/types.h>
 
+#include <asm-generic/bug.h>
+
 #include "common.h"
 
 /*
@@ -30,16 +33,36 @@ struct scmi_shared_mem {
 };
 
 void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem,
-                     struct scmi_xfer *xfer)
+                     struct scmi_xfer *xfer, struct scmi_chan_info *cinfo)
 {
+       ktime_t stop;
+
        /*
         * Ideally channel must be free by now unless OS timeout last
         * request and platform continued to process the same, wait
         * until it releases the shared memory, otherwise we may endup
-        * overwriting its response with new message payload or vice-versa
+        * overwriting its response with new message payload or vice-versa.
+        * Giving up anyway after twice the expected channel timeout so as
+        * not to bail-out on intermittent issues where the platform is
+        * occasionally a bit slower to answer.
+        *
+        * Note that after a timeout is detected we bail-out and carry on but
+        * the transport functionality is probably permanently compromised:
+        * this is just to ease debugging and avoid complete hangs on boot
+        * due to a misbehaving SCMI firmware.
         */
-       spin_until_cond(ioread32(&shmem->channel_status) &
-                       SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
+       stop = ktime_add_ms(ktime_get(), 2 * cinfo->rx_timeout_ms);
+       spin_until_cond((ioread32(&shmem->channel_status) &
+                        SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE) ||
+                        ktime_after(ktime_get(), stop));
+       if (!(ioread32(&shmem->channel_status) &
+             SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE)) {
+               WARN_ON_ONCE(1);
+               dev_err(cinfo->dev,
+                       "Timeout waiting for a free TX channel !\n");
+               return;
+       }
+
        /* Mark channel busy + clear error */
        iowrite32(0x0, &shmem->channel_status);
        iowrite32(xfer->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED,
index 745acfd..87a7b13 100644 (file)
@@ -188,7 +188,7 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
         */
        smc_channel_lock_acquire(scmi_info, xfer);
 
-       shmem_tx_prepare(scmi_info->shmem, xfer);
+       shmem_tx_prepare(scmi_info->shmem, xfer, cinfo);
 
        arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res);
 
index 14709db..33c9b81 100644 (file)
@@ -148,7 +148,6 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch)
 {
        unsigned long flags;
        DECLARE_COMPLETION_ONSTACK(vioch_shutdown_done);
-       void *deferred_wq = NULL;
 
        /*
         * Prepare to wait for the last release if not already released
@@ -162,16 +161,11 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch)
 
        vioch->shutdown_done = &vioch_shutdown_done;
        virtio_break_device(vioch->vqueue->vdev);
-       if (!vioch->is_rx && vioch->deferred_tx_wq) {
-               deferred_wq = vioch->deferred_tx_wq;
+       if (!vioch->is_rx && vioch->deferred_tx_wq)
                /* Cannot be kicked anymore after this...*/
                vioch->deferred_tx_wq = NULL;
-       }
        spin_unlock_irqrestore(&vioch->lock, flags);
 
-       if (deferred_wq)
-               destroy_workqueue(deferred_wq);
-
        scmi_vio_channel_release(vioch);
 
        /* Let any possibly concurrent RX path release the channel */
@@ -416,6 +410,11 @@ static bool virtio_chan_available(struct device *dev, int idx)
        return vioch && !vioch->cinfo;
 }
 
+static void scmi_destroy_tx_workqueue(void *deferred_tx_wq)
+{
+       destroy_workqueue(deferred_tx_wq);
+}
+
 static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
                             bool tx)
 {
@@ -430,6 +429,8 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
 
        /* Setup a deferred worker for polling. */
        if (tx && !vioch->deferred_tx_wq) {
+               int ret;
+
                vioch->deferred_tx_wq =
                        alloc_workqueue(dev_name(&scmi_vdev->dev),
                                        WQ_UNBOUND | WQ_FREEZABLE | WQ_SYSFS,
@@ -437,6 +438,11 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
                if (!vioch->deferred_tx_wq)
                        return -ENOMEM;
 
+               ret = devm_add_action_or_reset(dev, scmi_destroy_tx_workqueue,
+                                              vioch->deferred_tx_wq);
+               if (ret)
+                       return ret;
+
                INIT_WORK(&vioch->deferred_tx_work,
                          scmi_vio_deferred_tx_worker);
        }
@@ -444,12 +450,12 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
        for (i = 0; i < vioch->max_msg; i++) {
                struct scmi_vio_msg *msg;
 
-               msg = devm_kzalloc(cinfo->dev, sizeof(*msg), GFP_KERNEL);
+               msg = devm_kzalloc(dev, sizeof(*msg), GFP_KERNEL);
                if (!msg)
                        return -ENOMEM;
 
                if (tx) {
-                       msg->request = devm_kzalloc(cinfo->dev,
+                       msg->request = devm_kzalloc(dev,
                                                    VIRTIO_SCMI_MAX_PDU_SIZE,
                                                    GFP_KERNEL);
                        if (!msg->request)
@@ -458,7 +464,7 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
                        refcount_set(&msg->users, 1);
                }
 
-               msg->input = devm_kzalloc(cinfo->dev, VIRTIO_SCMI_MAX_PDU_SIZE,
+               msg->input = devm_kzalloc(dev, VIRTIO_SCMI_MAX_PDU_SIZE,
                                          GFP_KERNEL);
                if (!msg->input)
                        return -ENOMEM;
index 3ecdc43..a46df5d 100644 (file)
@@ -611,7 +611,7 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
 
                seed = early_memremap(efi_rng_seed, sizeof(*seed));
                if (seed != NULL) {
-                       size = READ_ONCE(seed->size);
+                       size = min(seed->size, EFI_RANDOM_SEED_SIZE);
                        early_memunmap(seed, sizeof(*seed));
                } else {
                        pr_err("Could not map UEFI random seed!\n");
index 24aa375..33ab567 100644 (file)
@@ -75,7 +75,12 @@ efi_status_t efi_random_get_seed(void)
        if (status != EFI_SUCCESS)
                return status;
 
-       status = efi_bs_call(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
+       /*
+        * Use EFI_ACPI_RECLAIM_MEMORY here so that it is guaranteed that the
+        * allocation will survive a kexec reboot (although we refresh the seed
+        * beforehand)
+        */
+       status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
                             sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
                             (void **)&seed);
        if (status != EFI_SUCCESS)
index 8f66567..e8d69bd 100644 (file)
@@ -97,7 +97,7 @@ int __init efi_tpm_eventlog_init(void)
                goto out_calc;
        }
 
-       memblock_reserve((unsigned long)final_tbl,
+       memblock_reserve(efi.tpm_final_log,
                         tbl_size + sizeof(*final_tbl));
        efi_tpm_final_log_size = tbl_size;
 
index 433b615..0ba9f18 100644 (file)
@@ -21,29 +21,22 @@ static struct efivars *__efivars;
 
 static DEFINE_SEMAPHORE(efivars_lock);
 
-static efi_status_t check_var_size(u32 attributes, unsigned long size)
-{
-       const struct efivar_operations *fops;
-
-       fops = __efivars->ops;
-
-       if (!fops->query_variable_store)
-               return (size <= SZ_64K) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
-
-       return fops->query_variable_store(attributes, size, false);
-}
-
-static
-efi_status_t check_var_size_nonblocking(u32 attributes, unsigned long size)
+static efi_status_t check_var_size(bool nonblocking, u32 attributes,
+                                  unsigned long size)
 {
        const struct efivar_operations *fops;
+       efi_status_t status;
 
        fops = __efivars->ops;
 
        if (!fops->query_variable_store)
+               status = EFI_UNSUPPORTED;
+       else
+               status = fops->query_variable_store(attributes, size,
+                                                   nonblocking);
+       if (status == EFI_UNSUPPORTED)
                return (size <= SZ_64K) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
-
-       return fops->query_variable_store(attributes, size, true);
+       return status;
 }
 
 /**
@@ -196,26 +189,6 @@ efi_status_t efivar_get_next_variable(unsigned long *name_size,
 EXPORT_SYMBOL_NS_GPL(efivar_get_next_variable, EFIVAR);
 
 /*
- * efivar_set_variable_blocking() - local helper function for set_variable
- *
- * Must be called with efivars_lock held.
- */
-static efi_status_t
-efivar_set_variable_blocking(efi_char16_t *name, efi_guid_t *vendor,
-                            u32 attr, unsigned long data_size, void *data)
-{
-       efi_status_t status;
-
-       if (data_size > 0) {
-               status = check_var_size(attr, data_size +
-                                             ucs2_strsize(name, 1024));
-               if (status != EFI_SUCCESS)
-                       return status;
-       }
-       return __efivars->ops->set_variable(name, vendor, attr, data_size, data);
-}
-
-/*
  * efivar_set_variable_locked() - set a variable identified by name/vendor
  *
  * Must be called with efivars_lock held. If @nonblocking is set, it will use
@@ -228,23 +201,21 @@ efi_status_t efivar_set_variable_locked(efi_char16_t *name, efi_guid_t *vendor,
        efi_set_variable_t *setvar;
        efi_status_t status;
 
-       if (!nonblocking)
-               return efivar_set_variable_blocking(name, vendor, attr,
-                                                   data_size, data);
+       if (data_size > 0) {
+               status = check_var_size(nonblocking, attr,
+                                       data_size + ucs2_strsize(name, 1024));
+               if (status != EFI_SUCCESS)
+                       return status;
+       }
 
        /*
         * If no _nonblocking variant exists, the ordinary one
         * is assumed to be non-blocking.
         */
-       setvar = __efivars->ops->set_variable_nonblocking ?:
-                __efivars->ops->set_variable;
+       setvar = __efivars->ops->set_variable_nonblocking;
+       if (!setvar || !nonblocking)
+                setvar = __efivars->ops->set_variable;
 
-       if (data_size > 0) {
-               status = check_var_size_nonblocking(attr, data_size +
-                                                         ucs2_strsize(name, 1024));
-               if (status != EFI_SUCCESS)
-                       return status;
-       }
        return setvar(name, vendor, attr, data_size, data);
 }
 EXPORT_SYMBOL_NS_GPL(efivar_set_variable_locked, EFIVAR);
@@ -264,7 +235,8 @@ efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor,
        if (efivar_lock())
                return EFI_ABORTED;
 
-       status = efivar_set_variable_blocking(name, vendor, attr, data_size, data);
+       status = efivar_set_variable_locked(name, vendor, attr, data_size,
+                                           data, false);
        efivar_unlock();
        return status;
 }
index 0561812..5d9a346 100644 (file)
@@ -706,6 +706,13 @@ err:
 
 void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle)
 {
+       /* Temporary workaround to fix issues observed in some
+        * compute applications when GFXOFF is enabled on GFX11.
+        */
+       if (IP_VERSION_MAJ(adev->ip_versions[GC_HWIP][0]) == 11) {
+               pr_debug("GFXOFF is %s\n", idle ? "enabled" : "disabled");
+               amdgpu_gfx_off_ctrl(adev, idle);
+       }
        amdgpu_dpm_switch_power_profile(adev,
                                        PP_SMC_POWER_PROFILE_COMPUTE,
                                        !idle);
index ddaecb2..6451089 100644 (file)
@@ -4060,15 +4060,18 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
  * at suspend time.
  *
  */
-static void amdgpu_device_evict_resources(struct amdgpu_device *adev)
+static int amdgpu_device_evict_resources(struct amdgpu_device *adev)
 {
+       int ret;
+
        /* No need to evict vram on APUs for suspend to ram or s2idle */
        if ((adev->in_s3 || adev->in_s0ix) && (adev->flags & AMD_IS_APU))
-               return;
+               return 0;
 
-       if (amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM))
+       ret = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM);
+       if (ret)
                DRM_WARN("evicting device resources failed\n");
-
+       return ret;
 }
 
 /*
@@ -4118,7 +4121,9 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
        if (!adev->in_s0ix)
                amdgpu_amdkfd_suspend(adev, adev->in_runpm);
 
-       amdgpu_device_evict_resources(adev);
+       r = amdgpu_device_evict_resources(adev);
+       if (r)
+               return r;
 
        amdgpu_fence_driver_hw_fini(adev);
 
index 3c9fecd..bf2d50c 100644 (file)
@@ -2201,7 +2201,8 @@ amdgpu_pci_remove(struct pci_dev *pdev)
                pm_runtime_forbid(dev->dev);
        }
 
-       if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)) {
+       if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2) &&
+           !amdgpu_sriov_vf(adev)) {
                bool need_to_reset_gpu = false;
 
                if (adev->gmc.xgmi.num_physical_nodes > 1) {
index bf1ff8f..4e42dcb 100644 (file)
@@ -337,12 +337,14 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
                fw_info->feature = adev->psp.cap_feature_version;
                break;
        case AMDGPU_INFO_FW_MES_KIQ:
-               fw_info->ver = adev->mes.ucode_fw_version[0];
-               fw_info->feature = 0;
+               fw_info->ver = adev->mes.kiq_version & AMDGPU_MES_VERSION_MASK;
+               fw_info->feature = (adev->mes.kiq_version & AMDGPU_MES_FEAT_VERSION_MASK)
+                                       >> AMDGPU_MES_FEAT_VERSION_SHIFT;
                break;
        case AMDGPU_INFO_FW_MES:
-               fw_info->ver = adev->mes.ucode_fw_version[1];
-               fw_info->feature = 0;
+               fw_info->ver = adev->mes.sched_version & AMDGPU_MES_VERSION_MASK;
+               fw_info->feature = (adev->mes.sched_version & AMDGPU_MES_FEAT_VERSION_MASK)
+                                       >> AMDGPU_MES_FEAT_VERSION_SHIFT;
                break;
        case AMDGPU_INFO_FW_IMU:
                fw_info->ver = adev->gfx.imu_fw_version;
index f4b5301..500a1dc 100644 (file)
@@ -500,6 +500,8 @@ static int amdgpu_vkms_sw_init(void *handle)
 
        adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
 
+       adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
+
        r = amdgpu_display_modeset_create_props(adev);
        if (r)
                return r;
index c711884..0c4c549 100644 (file)
@@ -2495,442 +2495,444 @@ static const uint32_t cwsr_trap_gfx10_hex[] = {
        0xbf9f0000, 0x00000000,
 };
 static const uint32_t cwsr_trap_gfx11_hex[] = {
-       0xbfa00001, 0xbfa0021e,
+       0xbfa00001, 0xbfa00221,
        0xb0804006, 0xb8f8f802,
        0x9178ff78, 0x00020006,
-       0xb8fbf803, 0xbf0d9f6d,
-       0xbfa20006, 0x8b6eff78,
-       0x00002000, 0xbfa10009,
-       0x8b6eff6d, 0x00ff0000,
-       0xbfa2001e, 0x8b6eff7b,
-       0x00000400, 0xbfa20041,
-       0xbf830010, 0xb8fbf803,
-       0xbfa0fffa, 0x8b6eff7b,
-       0x00000900, 0xbfa20015,
-       0x8b6eff7b, 0x000071ff,
-       0xbfa10008, 0x8b6fff7b,
-       0x00007080, 0xbfa10001,
-       0xbeee1287, 0xb8eff801,
-       0x846e8c6e, 0x8b6e6f6e,
-       0xbfa2000a, 0x8b6eff6d,
-       0x00ff0000, 0xbfa20007,
-       0xb8eef801, 0x8b6eff6e,
-       0x00000800, 0xbfa20003,
+       0xb8fbf803, 0xbf0d9e6d,
+       0xbfa10001, 0xbfbd0000,
+       0xbf0d9f6d, 0xbfa20006,
+       0x8b6eff78, 0x00002000,
+       0xbfa10009, 0x8b6eff6d,
+       0x00ff0000, 0xbfa2001e,
        0x8b6eff7b, 0x00000400,
-       0xbfa20026, 0xbefa4d82,
-       0xbf89fc07, 0x84fa887a,
-       0xf4005bbd, 0xf8000010,
-       0xbf89fc07, 0x846e976e,
-       0x9177ff77, 0x00800000,
-       0x8c776e77, 0xf4045bbd,
-       0xf8000000, 0xbf89fc07,
-       0xf4045ebd, 0xf8000008,
-       0xbf89fc07, 0x8bee6e6e,
-       0xbfa10001, 0xbe80486e,
-       0x8b6eff6d, 0x01ff0000,
-       0xbfa20005, 0x8c78ff78,
-       0x00002000, 0x80ec886c,
-       0x82ed806d, 0xbfa00005,
-       0x8b6eff6d, 0x01000000,
-       0xbfa20002, 0x806c846c,
-       0x826d806d, 0x8b6dff6d,
-       0x0000ffff, 0x8bfe7e7e,
-       0x8bea6a6a, 0xb978f802,
-       0xbe804a6c, 0x8b6dff6d,
-       0x0000ffff, 0xbefa0080,
-       0xb97a0283, 0xbeee007e,
-       0xbeef007f, 0xbefe0180,
-       0xbefe4d84, 0xbf89fc07,
-       0x8b7aff7f, 0x04000000,
-       0x847a857a, 0x8c6d7a6d,
-       0xbefa007e, 0x8b7bff7f,
-       0x0000ffff, 0xbefe00c1,
-       0xbeff00c1, 0xdca6c000,
-       0x007a0000, 0x7e000280,
-       0xbefe007a, 0xbeff007b,
-       0xb8fb02dc, 0x847b997b,
-       0xb8fa3b05, 0x807a817a,
-       0xbf0d997b, 0xbfa20002,
-       0x847a897a, 0xbfa00001,
-       0x847a8a7a, 0xb8fb1e06,
-       0x847b8a7b, 0x807a7b7a,
+       0xbfa20041, 0xbf830010,
+       0xb8fbf803, 0xbfa0fffa,
+       0x8b6eff7b, 0x00000900,
+       0xbfa20015, 0x8b6eff7b,
+       0x000071ff, 0xbfa10008,
+       0x8b6fff7b, 0x00007080,
+       0xbfa10001, 0xbeee1287,
+       0xb8eff801, 0x846e8c6e,
+       0x8b6e6f6e, 0xbfa2000a,
+       0x8b6eff6d, 0x00ff0000,
+       0xbfa20007, 0xb8eef801,
+       0x8b6eff6e, 0x00000800,
+       0xbfa20003, 0x8b6eff7b,
+       0x00000400, 0xbfa20026,
+       0xbefa4d82, 0xbf89fc07,
+       0x84fa887a, 0xf4005bbd,
+       0xf8000010, 0xbf89fc07,
+       0x846e976e, 0x9177ff77,
+       0x00800000, 0x8c776e77,
+       0xf4045bbd, 0xf8000000,
+       0xbf89fc07, 0xf4045ebd,
+       0xf8000008, 0xbf89fc07,
+       0x8bee6e6e, 0xbfa10001,
+       0xbe80486e, 0x8b6eff6d,
+       0x01ff0000, 0xbfa20005,
+       0x8c78ff78, 0x00002000,
+       0x80ec886c, 0x82ed806d,
+       0xbfa00005, 0x8b6eff6d,
+       0x01000000, 0xbfa20002,
+       0x806c846c, 0x826d806d,
+       0x8b6dff6d, 0x0000ffff,
+       0x8bfe7e7e, 0x8bea6a6a,
+       0xb978f802, 0xbe804a6c,
+       0x8b6dff6d, 0x0000ffff,
+       0xbefa0080, 0xb97a0283,
+       0xbeee007e, 0xbeef007f,
+       0xbefe0180, 0xbefe4d84,
+       0xbf89fc07, 0x8b7aff7f,
+       0x04000000, 0x847a857a,
+       0x8c6d7a6d, 0xbefa007e,
        0x8b7bff7f, 0x0000ffff,
-       0x807aff7a, 0x00000200,
-       0x807a7e7a, 0x827b807b,
-       0xd7610000, 0x00010870,
-       0xd7610000, 0x00010a71,
-       0xd7610000, 0x00010c72,
-       0xd7610000, 0x00010e73,
-       0xd7610000, 0x00011074,
-       0xd7610000, 0x00011275,
-       0xd7610000, 0x00011476,
-       0xd7610000, 0x00011677,
-       0xd7610000, 0x00011a79,
-       0xd7610000, 0x00011c7e,
-       0xd7610000, 0x00011e7f,
-       0xbefe00ff, 0x00003fff,
-       0xbeff0080, 0xdca6c040,
-       0x007a0000, 0xd760007a,
-       0x00011d00, 0xd760007b,
-       0x00011f00, 0xbefe007a,
-       0xbeff007b, 0xbef4007e,
-       0x8b75ff7f, 0x0000ffff,
-       0x8c75ff75, 0x00040000,
-       0xbef60080, 0xbef700ff,
-       0x10807fac, 0xbef1007d,
-       0xbef00080, 0xb8f302dc,
-       0x84739973, 0xbefe00c1,
-       0x857d9973, 0x8b7d817d,
-       0xbf06817d, 0xbfa20002,
-       0xbeff0080, 0xbfa00002,
-       0xbeff00c1, 0xbfa00009,
+       0xbefe00c1, 0xbeff00c1,
+       0xdca6c000, 0x007a0000,
+       0x7e000280, 0xbefe007a,
+       0xbeff007b, 0xb8fb02dc,
+       0x847b997b, 0xb8fa3b05,
+       0x807a817a, 0xbf0d997b,
+       0xbfa20002, 0x847a897a,
+       0xbfa00001, 0x847a8a7a,
+       0xb8fb1e06, 0x847b8a7b,
+       0x807a7b7a, 0x8b7bff7f,
+       0x0000ffff, 0x807aff7a,
+       0x00000200, 0x807a7e7a,
+       0x827b807b, 0xd7610000,
+       0x00010870, 0xd7610000,
+       0x00010a71, 0xd7610000,
+       0x00010c72, 0xd7610000,
+       0x00010e73, 0xd7610000,
+       0x00011074, 0xd7610000,
+       0x00011275, 0xd7610000,
+       0x00011476, 0xd7610000,
+       0x00011677, 0xd7610000,
+       0x00011a79, 0xd7610000,
+       0x00011c7e, 0xd7610000,
+       0x00011e7f, 0xbefe00ff,
+       0x00003fff, 0xbeff0080,
+       0xdca6c040, 0x007a0000,
+       0xd760007a, 0x00011d00,
+       0xd760007b, 0x00011f00,
+       0xbefe007a, 0xbeff007b,
+       0xbef4007e, 0x8b75ff7f,
+       0x0000ffff, 0x8c75ff75,
+       0x00040000, 0xbef60080,
+       0xbef700ff, 0x10807fac,
+       0xbef1007d, 0xbef00080,
+       0xb8f302dc, 0x84739973,
+       0xbefe00c1, 0x857d9973,
+       0x8b7d817d, 0xbf06817d,
+       0xbfa20002, 0xbeff0080,
+       0xbfa00002, 0xbeff00c1,
+       0xbfa00009, 0xbef600ff,
+       0x01000000, 0xe0685080,
+       0x701d0100, 0xe0685100,
+       0x701d0200, 0xe0685180,
+       0x701d0300, 0xbfa00008,
        0xbef600ff, 0x01000000,
-       0xe0685080, 0x701d0100,
-       0xe0685100, 0x701d0200,
-       0xe0685180, 0x701d0300,
-       0xbfa00008, 0xbef600ff,
-       0x01000000, 0xe0685100,
-       0x701d0100, 0xe0685200,
-       0x701d0200, 0xe0685300,
-       0x701d0300, 0xb8f03b05,
-       0x80708170, 0xbf0d9973,
-       0xbfa20002, 0x84708970,
-       0xbfa00001, 0x84708a70,
-       0xb8fa1e06, 0x847a8a7a,
-       0x80707a70, 0x8070ff70,
-       0x00000200, 0xbef600ff,
-       0x01000000, 0x7e000280,
-       0x7e020280, 0x7e040280,
-       0xbefd0080, 0xd7610002,
-       0x0000fa71, 0x807d817d,
-       0xd7610002, 0x0000fa6c,
-       0x807d817d, 0x917aff6d,
-       0x80000000, 0xd7610002,
-       0x0000fa7a, 0x807d817d,
-       0xd7610002, 0x0000fa6e,
-       0x807d817d, 0xd7610002,
-       0x0000fa6f, 0x807d817d,
-       0xd7610002, 0x0000fa78,
-       0x807d817d, 0xb8faf803,
-       0xd7610002, 0x0000fa7a,
-       0x807d817d, 0xd7610002,
-       0x0000fa7b, 0x807d817d,
-       0xb8f1f801, 0xd7610002,
-       0x0000fa71, 0x807d817d,
-       0xb8f1f814, 0xd7610002,
-       0x0000fa71, 0x807d817d,
-       0xb8f1f815, 0xd7610002,
-       0x0000fa71, 0x807d817d,
-       0xbefe00ff, 0x0000ffff,
-       0xbeff0080, 0xe0685000,
-       0x701d0200, 0xbefe00c1,
+       0xe0685100, 0x701d0100,
+       0xe0685200, 0x701d0200,
+       0xe0685300, 0x701d0300,
        0xb8f03b05, 0x80708170,
        0xbf0d9973, 0xbfa20002,
        0x84708970, 0xbfa00001,
        0x84708a70, 0xb8fa1e06,
        0x847a8a7a, 0x80707a70,
+       0x8070ff70, 0x00000200,
        0xbef600ff, 0x01000000,
-       0xbef90080, 0xbefd0080,
-       0xbf800000, 0xbe804100,
-       0xbe824102, 0xbe844104,
-       0xbe864106, 0xbe884108,
-       0xbe8a410a, 0xbe8c410c,
-       0xbe8e410e, 0xd7610002,
-       0x0000f200, 0x80798179,
-       0xd7610002, 0x0000f201,
+       0x7e000280, 0x7e020280,
+       0x7e040280, 0xbefd0080,
+       0xd7610002, 0x0000fa71,
+       0x807d817d, 0xd7610002,
+       0x0000fa6c, 0x807d817d,
+       0x917aff6d, 0x80000000,
+       0xd7610002, 0x0000fa7a,
+       0x807d817d, 0xd7610002,
+       0x0000fa6e, 0x807d817d,
+       0xd7610002, 0x0000fa6f,
+       0x807d817d, 0xd7610002,
+       0x0000fa78, 0x807d817d,
+       0xb8faf803, 0xd7610002,
+       0x0000fa7a, 0x807d817d,
+       0xd7610002, 0x0000fa7b,
+       0x807d817d, 0xb8f1f801,
+       0xd7610002, 0x0000fa71,
+       0x807d817d, 0xb8f1f814,
+       0xd7610002, 0x0000fa71,
+       0x807d817d, 0xb8f1f815,
+       0xd7610002, 0x0000fa71,
+       0x807d817d, 0xbefe00ff,
+       0x0000ffff, 0xbeff0080,
+       0xe0685000, 0x701d0200,
+       0xbefe00c1, 0xb8f03b05,
+       0x80708170, 0xbf0d9973,
+       0xbfa20002, 0x84708970,
+       0xbfa00001, 0x84708a70,
+       0xb8fa1e06, 0x847a8a7a,
+       0x80707a70, 0xbef600ff,
+       0x01000000, 0xbef90080,
+       0xbefd0080, 0xbf800000,
+       0xbe804100, 0xbe824102,
+       0xbe844104, 0xbe864106,
+       0xbe884108, 0xbe8a410a,
+       0xbe8c410c, 0xbe8e410e,
+       0xd7610002, 0x0000f200,
        0x80798179, 0xd7610002,
-       0x0000f202, 0x80798179,
-       0xd7610002, 0x0000f203,
+       0x0000f201, 0x80798179,
+       0xd7610002, 0x0000f202,
        0x80798179, 0xd7610002,
-       0x0000f204, 0x80798179,
-       0xd7610002, 0x0000f205,
+       0x0000f203, 0x80798179,
+       0xd7610002, 0x0000f204,
        0x80798179, 0xd7610002,
-       0x0000f206, 0x80798179,
-       0xd7610002, 0x0000f207,
+       0x0000f205, 0x80798179,
+       0xd7610002, 0x0000f206,
        0x80798179, 0xd7610002,
-       0x0000f208, 0x80798179,
-       0xd7610002, 0x0000f209,
+       0x0000f207, 0x80798179,
+       0xd7610002, 0x0000f208,
        0x80798179, 0xd7610002,
-       0x0000f20a, 0x80798179,
-       0xd7610002, 0x0000f20b,
+       0x0000f209, 0x80798179,
+       0xd7610002, 0x0000f20a,
        0x80798179, 0xd7610002,
-       0x0000f20c, 0x80798179,
-       0xd7610002, 0x0000f20d,
+       0x0000f20b, 0x80798179,
+       0xd7610002, 0x0000f20c,
        0x80798179, 0xd7610002,
-       0x0000f20e, 0x80798179,
-       0xd7610002, 0x0000f20f,
-       0x80798179, 0xbf06a079,
-       0xbfa10006, 0xe0685000,
-       0x701d0200, 0x8070ff70,
-       0x00000080, 0xbef90080,
-       0x7e040280, 0x807d907d,
-       0xbf0aff7d, 0x00000060,
-       0xbfa2ffbc, 0xbe804100,
-       0xbe824102, 0xbe844104,
-       0xbe864106, 0xbe884108,
-       0xbe8a410a, 0xd7610002,
-       0x0000f200, 0x80798179,
-       0xd7610002, 0x0000f201,
+       0x0000f20d, 0x80798179,
+       0xd7610002, 0x0000f20e,
        0x80798179, 0xd7610002,
-       0x0000f202, 0x80798179,
-       0xd7610002, 0x0000f203,
+       0x0000f20f, 0x80798179,
+       0xbf06a079, 0xbfa10006,
+       0xe0685000, 0x701d0200,
+       0x8070ff70, 0x00000080,
+       0xbef90080, 0x7e040280,
+       0x807d907d, 0xbf0aff7d,
+       0x00000060, 0xbfa2ffbc,
+       0xbe804100, 0xbe824102,
+       0xbe844104, 0xbe864106,
+       0xbe884108, 0xbe8a410a,
+       0xd7610002, 0x0000f200,
        0x80798179, 0xd7610002,
-       0x0000f204, 0x80798179,
-       0xd7610002, 0x0000f205,
+       0x0000f201, 0x80798179,
+       0xd7610002, 0x0000f202,
        0x80798179, 0xd7610002,
-       0x0000f206, 0x80798179,
-       0xd7610002, 0x0000f207,
+       0x0000f203, 0x80798179,
+       0xd7610002, 0x0000f204,
        0x80798179, 0xd7610002,
-       0x0000f208, 0x80798179,
-       0xd7610002, 0x0000f209,
+       0x0000f205, 0x80798179,
+       0xd7610002, 0x0000f206,
        0x80798179, 0xd7610002,
-       0x0000f20a, 0x80798179,
-       0xd7610002, 0x0000f20b,
-       0x80798179, 0xe0685000,
-       0x701d0200, 0xbefe00c1,
-       0x857d9973, 0x8b7d817d,
-       0xbf06817d, 0xbfa20002,
-       0xbeff0080, 0xbfa00001,
-       0xbeff00c1, 0xb8fb4306,
-       0x8b7bc17b, 0xbfa10044,
-       0xbfbd0000, 0x8b7aff6d,
-       0x80000000, 0xbfa10040,
-       0x847b867b, 0x847b827b,
-       0xbef6007b, 0xb8f03b05,
-       0x80708170, 0xbf0d9973,
-       0xbfa20002, 0x84708970,
-       0xbfa00001, 0x84708a70,
-       0xb8fa1e06, 0x847a8a7a,
-       0x80707a70, 0x8070ff70,
-       0x00000200, 0x8070ff70,
-       0x00000080, 0xbef600ff,
-       0x01000000, 0xd71f0000,
-       0x000100c1, 0xd7200000,
-       0x000200c1, 0x16000084,
-       0x857d9973, 0x8b7d817d,
-       0xbf06817d, 0xbefd0080,
-       0xbfa20012, 0xbe8300ff,
-       0x00000080, 0xbf800000,
-       0xbf800000, 0xbf800000,
-       0xd8d80000, 0x01000000,
-       0xbf890000, 0xe0685000,
-       0x701d0100, 0x807d037d,
-       0x80700370, 0xd5250000,
-       0x0001ff00, 0x00000080,
-       0xbf0a7b7d, 0xbfa2fff4,
-       0xbfa00011, 0xbe8300ff,
-       0x00000100, 0xbf800000,
-       0xbf800000, 0xbf800000,
-       0xd8d80000, 0x01000000,
-       0xbf890000, 0xe0685000,
-       0x701d0100, 0x807d037d,
-       0x80700370, 0xd5250000,
-       0x0001ff00, 0x00000100,
-       0xbf0a7b7d, 0xbfa2fff4,
+       0x0000f207, 0x80798179,
+       0xd7610002, 0x0000f208,
+       0x80798179, 0xd7610002,
+       0x0000f209, 0x80798179,
+       0xd7610002, 0x0000f20a,
+       0x80798179, 0xd7610002,
+       0x0000f20b, 0x80798179,
+       0xe0685000, 0x701d0200,
        0xbefe00c1, 0x857d9973,
        0x8b7d817d, 0xbf06817d,
-       0xbfa20004, 0xbef000ff,
-       0x00000200, 0xbeff0080,
-       0xbfa00003, 0xbef000ff,
-       0x00000400, 0xbeff00c1,
-       0xb8fb3b05, 0x807b817b,
-       0x847b827b, 0x857d9973,
+       0xbfa20002, 0xbeff0080,
+       0xbfa00001, 0xbeff00c1,
+       0xb8fb4306, 0x8b7bc17b,
+       0xbfa10044, 0xbfbd0000,
+       0x8b7aff6d, 0x80000000,
+       0xbfa10040, 0x847b867b,
+       0x847b827b, 0xbef6007b,
+       0xb8f03b05, 0x80708170,
+       0xbf0d9973, 0xbfa20002,
+       0x84708970, 0xbfa00001,
+       0x84708a70, 0xb8fa1e06,
+       0x847a8a7a, 0x80707a70,
+       0x8070ff70, 0x00000200,
+       0x8070ff70, 0x00000080,
+       0xbef600ff, 0x01000000,
+       0xd71f0000, 0x000100c1,
+       0xd7200000, 0x000200c1,
+       0x16000084, 0x857d9973,
        0x8b7d817d, 0xbf06817d,
-       0xbfa20017, 0xbef600ff,
-       0x01000000, 0xbefd0084,
-       0xbf0a7b7d, 0xbfa10037,
-       0x7e008700, 0x7e028701,
-       0x7e048702, 0x7e068703,
-       0xe0685000, 0x701d0000,
-       0xe0685080, 0x701d0100,
-       0xe0685100, 0x701d0200,
-       0xe0685180, 0x701d0300,
-       0x807d847d, 0x8070ff70,
-       0x00000200, 0xbf0a7b7d,
-       0xbfa2ffef, 0xbfa00025,
+       0xbefd0080, 0xbfa20012,
+       0xbe8300ff, 0x00000080,
+       0xbf800000, 0xbf800000,
+       0xbf800000, 0xd8d80000,
+       0x01000000, 0xbf890000,
+       0xe0685000, 0x701d0100,
+       0x807d037d, 0x80700370,
+       0xd5250000, 0x0001ff00,
+       0x00000080, 0xbf0a7b7d,
+       0xbfa2fff4, 0xbfa00011,
+       0xbe8300ff, 0x00000100,
+       0xbf800000, 0xbf800000,
+       0xbf800000, 0xd8d80000,
+       0x01000000, 0xbf890000,
+       0xe0685000, 0x701d0100,
+       0x807d037d, 0x80700370,
+       0xd5250000, 0x0001ff00,
+       0x00000100, 0xbf0a7b7d,
+       0xbfa2fff4, 0xbefe00c1,
+       0x857d9973, 0x8b7d817d,
+       0xbf06817d, 0xbfa20004,
+       0xbef000ff, 0x00000200,
+       0xbeff0080, 0xbfa00003,
+       0xbef000ff, 0x00000400,
+       0xbeff00c1, 0xb8fb3b05,
+       0x807b817b, 0x847b827b,
+       0x857d9973, 0x8b7d817d,
+       0xbf06817d, 0xbfa20017,
        0xbef600ff, 0x01000000,
        0xbefd0084, 0xbf0a7b7d,
-       0xbfa10011, 0x7e008700,
+       0xbfa10037, 0x7e008700,
        0x7e028701, 0x7e048702,
        0x7e068703, 0xe0685000,
-       0x701d0000, 0xe0685100,
-       0x701d0100, 0xe0685200,
-       0x701d0200, 0xe0685300,
+       0x701d0000, 0xe0685080,
+       0x701d0100, 0xe0685100,
+       0x701d0200, 0xe0685180,
        0x701d0300, 0x807d847d,
-       0x8070ff70, 0x00000400,
+       0x8070ff70, 0x00000200,
        0xbf0a7b7d, 0xbfa2ffef,
-       0xb8fb1e06, 0x8b7bc17b,
-       0xbfa1000c, 0x847b837b,
-       0x807b7d7b, 0xbefe00c1,
-       0xbeff0080, 0x7e008700,
+       0xbfa00025, 0xbef600ff,
+       0x01000000, 0xbefd0084,
+       0xbf0a7b7d, 0xbfa10011,
+       0x7e008700, 0x7e028701,
+       0x7e048702, 0x7e068703,
        0xe0685000, 0x701d0000,
-       0x807d817d, 0x8070ff70,
-       0x00000080, 0xbf0a7b7d,
-       0xbfa2fff8, 0xbfa00146,
-       0xbef4007e, 0x8b75ff7f,
-       0x0000ffff, 0x8c75ff75,
-       0x00040000, 0xbef60080,
-       0xbef700ff, 0x10807fac,
-       0xb8f202dc, 0x84729972,
-       0x8b6eff7f, 0x04000000,
-       0xbfa1003a, 0xbefe00c1,
-       0x857d9972, 0x8b7d817d,
-       0xbf06817d, 0xbfa20002,
-       0xbeff0080, 0xbfa00001,
-       0xbeff00c1, 0xb8ef4306,
-       0x8b6fc16f, 0xbfa1002f,
-       0x846f866f, 0x846f826f,
-       0xbef6006f, 0xb8f83b05,
-       0x80788178, 0xbf0d9972,
-       0xbfa20002, 0x84788978,
-       0xbfa00001, 0x84788a78,
-       0xb8ee1e06, 0x846e8a6e,
-       0x80786e78, 0x8078ff78,
-       0x00000200, 0x8078ff78,
-       0x00000080, 0xbef600ff,
-       0x01000000, 0x857d9972,
-       0x8b7d817d, 0xbf06817d,
-       0xbefd0080, 0xbfa2000c,
-       0xe0500000, 0x781d0000,
-       0xbf8903f7, 0xdac00000,
-       0x00000000, 0x807dff7d,
-       0x00000080, 0x8078ff78,
-       0x00000080, 0xbf0a6f7d,
-       0xbfa2fff5, 0xbfa0000b,
-       0xe0500000, 0x781d0000,
-       0xbf8903f7, 0xdac00000,
-       0x00000000, 0x807dff7d,
-       0x00000100, 0x8078ff78,
-       0x00000100, 0xbf0a6f7d,
-       0xbfa2fff5, 0xbef80080,
+       0xe0685100, 0x701d0100,
+       0xe0685200, 0x701d0200,
+       0xe0685300, 0x701d0300,
+       0x807d847d, 0x8070ff70,
+       0x00000400, 0xbf0a7b7d,
+       0xbfa2ffef, 0xb8fb1e06,
+       0x8b7bc17b, 0xbfa1000c,
+       0x847b837b, 0x807b7d7b,
+       0xbefe00c1, 0xbeff0080,
+       0x7e008700, 0xe0685000,
+       0x701d0000, 0x807d817d,
+       0x8070ff70, 0x00000080,
+       0xbf0a7b7d, 0xbfa2fff8,
+       0xbfa00146, 0xbef4007e,
+       0x8b75ff7f, 0x0000ffff,
+       0x8c75ff75, 0x00040000,
+       0xbef60080, 0xbef700ff,
+       0x10807fac, 0xb8f202dc,
+       0x84729972, 0x8b6eff7f,
+       0x04000000, 0xbfa1003a,
        0xbefe00c1, 0x857d9972,
        0x8b7d817d, 0xbf06817d,
        0xbfa20002, 0xbeff0080,
        0xbfa00001, 0xbeff00c1,
-       0xb8ef3b05, 0x806f816f,
-       0x846f826f, 0x857d9972,
-       0x8b7d817d, 0xbf06817d,
-       0xbfa20024, 0xbef600ff,
-       0x01000000, 0xbeee0078,
+       0xb8ef4306, 0x8b6fc16f,
+       0xbfa1002f, 0x846f866f,
+       0x846f826f, 0xbef6006f,
+       0xb8f83b05, 0x80788178,
+       0xbf0d9972, 0xbfa20002,
+       0x84788978, 0xbfa00001,
+       0x84788a78, 0xb8ee1e06,
+       0x846e8a6e, 0x80786e78,
        0x8078ff78, 0x00000200,
-       0xbefd0084, 0xbf0a6f7d,
-       0xbfa10050, 0xe0505000,
-       0x781d0000, 0xe0505080,
-       0x781d0100, 0xe0505100,
-       0x781d0200, 0xe0505180,
-       0x781d0300, 0xbf8903f7,
-       0x7e008500, 0x7e028501,
-       0x7e048502, 0x7e068503,
-       0x807d847d, 0x8078ff78,
-       0x00000200, 0xbf0a6f7d,
-       0xbfa2ffee, 0xe0505000,
-       0x6e1d0000, 0xe0505080,
-       0x6e1d0100, 0xe0505100,
-       0x6e1d0200, 0xe0505180,
-       0x6e1d0300, 0xbf8903f7,
-       0xbfa00034, 0xbef600ff,
-       0x01000000, 0xbeee0078,
-       0x8078ff78, 0x00000400,
-       0xbefd0084, 0xbf0a6f7d,
-       0xbfa10012, 0xe0505000,
-       0x781d0000, 0xe0505100,
-       0x781d0100, 0xe0505200,
-       0x781d0200, 0xe0505300,
-       0x781d0300, 0xbf8903f7,
-       0x7e008500, 0x7e028501,
-       0x7e048502, 0x7e068503,
-       0x807d847d, 0x8078ff78,
-       0x00000400, 0xbf0a6f7d,
-       0xbfa2ffee, 0xb8ef1e06,
-       0x8b6fc16f, 0xbfa1000e,
-       0x846f836f, 0x806f7d6f,
-       0xbefe00c1, 0xbeff0080,
+       0x8078ff78, 0x00000080,
+       0xbef600ff, 0x01000000,
+       0x857d9972, 0x8b7d817d,
+       0xbf06817d, 0xbefd0080,
+       0xbfa2000c, 0xe0500000,
+       0x781d0000, 0xbf8903f7,
+       0xdac00000, 0x00000000,
+       0x807dff7d, 0x00000080,
+       0x8078ff78, 0x00000080,
+       0xbf0a6f7d, 0xbfa2fff5,
+       0xbfa0000b, 0xe0500000,
+       0x781d0000, 0xbf8903f7,
+       0xdac00000, 0x00000000,
+       0x807dff7d, 0x00000100,
+       0x8078ff78, 0x00000100,
+       0xbf0a6f7d, 0xbfa2fff5,
+       0xbef80080, 0xbefe00c1,
+       0x857d9972, 0x8b7d817d,
+       0xbf06817d, 0xbfa20002,
+       0xbeff0080, 0xbfa00001,
+       0xbeff00c1, 0xb8ef3b05,
+       0x806f816f, 0x846f826f,
+       0x857d9972, 0x8b7d817d,
+       0xbf06817d, 0xbfa20024,
+       0xbef600ff, 0x01000000,
+       0xbeee0078, 0x8078ff78,
+       0x00000200, 0xbefd0084,
+       0xbf0a6f7d, 0xbfa10050,
        0xe0505000, 0x781d0000,
+       0xe0505080, 0x781d0100,
+       0xe0505100, 0x781d0200,
+       0xe0505180, 0x781d0300,
        0xbf8903f7, 0x7e008500,
-       0x807d817d, 0x8078ff78,
-       0x00000080, 0xbf0a6f7d,
-       0xbfa2fff7, 0xbeff00c1,
+       0x7e028501, 0x7e048502,
+       0x7e068503, 0x807d847d,
+       0x8078ff78, 0x00000200,
+       0xbf0a6f7d, 0xbfa2ffee,
        0xe0505000, 0x6e1d0000,
-       0xe0505100, 0x6e1d0100,
-       0xe0505200, 0x6e1d0200,
-       0xe0505300, 0x6e1d0300,
-       0xbf8903f7, 0xb8f83b05,
-       0x80788178, 0xbf0d9972,
-       0xbfa20002, 0x84788978,
-       0xbfa00001, 0x84788a78,
-       0xb8ee1e06, 0x846e8a6e,
-       0x80786e78, 0x8078ff78,
-       0x00000200, 0x80f8ff78,
-       0x00000050, 0xbef600ff,
-       0x01000000, 0xbefd00ff,
-       0x0000006c, 0x80f89078,
-       0xf428403a, 0xf0000000,
-       0xbf89fc07, 0x80fd847d,
-       0xbf800000, 0xbe804300,
-       0xbe824302, 0x80f8a078,
-       0xf42c403a, 0xf0000000,
-       0xbf89fc07, 0x80fd887d,
-       0xbf800000, 0xbe804300,
-       0xbe824302, 0xbe844304,
-       0xbe864306, 0x80f8c078,
-       0xf430403a, 0xf0000000,
-       0xbf89fc07, 0x80fd907d,
-       0xbf800000, 0xbe804300,
-       0xbe824302, 0xbe844304,
-       0xbe864306, 0xbe884308,
-       0xbe8a430a, 0xbe8c430c,
-       0xbe8e430e, 0xbf06807d,
-       0xbfa1fff0, 0xb980f801,
-       0x00000000, 0xbfbd0000,
+       0xe0505080, 0x6e1d0100,
+       0xe0505100, 0x6e1d0200,
+       0xe0505180, 0x6e1d0300,
+       0xbf8903f7, 0xbfa00034,
+       0xbef600ff, 0x01000000,
+       0xbeee0078, 0x8078ff78,
+       0x00000400, 0xbefd0084,
+       0xbf0a6f7d, 0xbfa10012,
+       0xe0505000, 0x781d0000,
+       0xe0505100, 0x781d0100,
+       0xe0505200, 0x781d0200,
+       0xe0505300, 0x781d0300,
+       0xbf8903f7, 0x7e008500,
+       0x7e028501, 0x7e048502,
+       0x7e068503, 0x807d847d,
+       0x8078ff78, 0x00000400,
+       0xbf0a6f7d, 0xbfa2ffee,
+       0xb8ef1e06, 0x8b6fc16f,
+       0xbfa1000e, 0x846f836f,
+       0x806f7d6f, 0xbefe00c1,
+       0xbeff0080, 0xe0505000,
+       0x781d0000, 0xbf8903f7,
+       0x7e008500, 0x807d817d,
+       0x8078ff78, 0x00000080,
+       0xbf0a6f7d, 0xbfa2fff7,
+       0xbeff00c1, 0xe0505000,
+       0x6e1d0000, 0xe0505100,
+       0x6e1d0100, 0xe0505200,
+       0x6e1d0200, 0xe0505300,
+       0x6e1d0300, 0xbf8903f7,
        0xb8f83b05, 0x80788178,
        0xbf0d9972, 0xbfa20002,
        0x84788978, 0xbfa00001,
        0x84788a78, 0xb8ee1e06,
        0x846e8a6e, 0x80786e78,
        0x8078ff78, 0x00000200,
+       0x80f8ff78, 0x00000050,
        0xbef600ff, 0x01000000,
-       0xf4205bfa, 0xf0000000,
-       0x80788478, 0xf4205b3a,
+       0xbefd00ff, 0x0000006c,
+       0x80f89078, 0xf428403a,
+       0xf0000000, 0xbf89fc07,
+       0x80fd847d, 0xbf800000,
+       0xbe804300, 0xbe824302,
+       0x80f8a078, 0xf42c403a,
+       0xf0000000, 0xbf89fc07,
+       0x80fd887d, 0xbf800000,
+       0xbe804300, 0xbe824302,
+       0xbe844304, 0xbe864306,
+       0x80f8c078, 0xf430403a,
+       0xf0000000, 0xbf89fc07,
+       0x80fd907d, 0xbf800000,
+       0xbe804300, 0xbe824302,
+       0xbe844304, 0xbe864306,
+       0xbe884308, 0xbe8a430a,
+       0xbe8c430c, 0xbe8e430e,
+       0xbf06807d, 0xbfa1fff0,
+       0xb980f801, 0x00000000,
+       0xbfbd0000, 0xb8f83b05,
+       0x80788178, 0xbf0d9972,
+       0xbfa20002, 0x84788978,
+       0xbfa00001, 0x84788a78,
+       0xb8ee1e06, 0x846e8a6e,
+       0x80786e78, 0x8078ff78,
+       0x00000200, 0xbef600ff,
+       0x01000000, 0xf4205bfa,
        0xf0000000, 0x80788478,
-       0xf4205b7a, 0xf0000000,
-       0x80788478, 0xf4205c3a,
+       0xf4205b3a, 0xf0000000,
+       0x80788478, 0xf4205b7a,
        0xf0000000, 0x80788478,
-       0xf4205c7a, 0xf0000000,
-       0x80788478, 0xf4205eba,
+       0xf4205c3a, 0xf0000000,
+       0x80788478, 0xf4205c7a,
        0xf0000000, 0x80788478,
-       0xf4205efa, 0xf0000000,
-       0x80788478, 0xf4205e7a,
+       0xf4205eba, 0xf0000000,
+       0x80788478, 0xf4205efa,
        0xf0000000, 0x80788478,
-       0xf4205cfa, 0xf0000000,
-       0x80788478, 0xf4205bba,
+       0xf4205e7a, 0xf0000000,
+       0x80788478, 0xf4205cfa,
        0xf0000000, 0x80788478,
-       0xbf89fc07, 0xb96ef814,
        0xf4205bba, 0xf0000000,
        0x80788478, 0xbf89fc07,
-       0xb96ef815, 0xbefd006f,
-       0xbefe0070, 0xbeff0071,
-       0x8b6f7bff, 0x000003ff,
-       0xb96f4803, 0x8b6f7bff,
-       0xfffff800, 0x856f8b6f,
-       0xb96fa2c3, 0xb973f801,
-       0xb8ee3b05, 0x806e816e,
-       0xbf0d9972, 0xbfa20002,
-       0x846e896e, 0xbfa00001,
-       0x846e8a6e, 0xb8ef1e06,
-       0x846f8a6f, 0x806e6f6e,
-       0x806eff6e, 0x00000200,
-       0x806e746e, 0x826f8075,
-       0x8b6fff6f, 0x0000ffff,
-       0xf4085c37, 0xf8000050,
-       0xf4085d37, 0xf8000060,
-       0xf4005e77, 0xf8000074,
-       0xbf89fc07, 0x8b6dff6d,
-       0x0000ffff, 0x8bfe7e7e,
-       0x8bea6a6a, 0xb8eef802,
-       0xbf0d866e, 0xbfa20002,
-       0xb97af802, 0xbe80486c,
-       0xb97af802, 0xbe804a6c,
-       0xbfb00000, 0xbf9f0000,
+       0xb96ef814, 0xf4205bba,
+       0xf0000000, 0x80788478,
+       0xbf89fc07, 0xb96ef815,
+       0xbefd006f, 0xbefe0070,
+       0xbeff0071, 0x8b6f7bff,
+       0x000003ff, 0xb96f4803,
+       0x8b6f7bff, 0xfffff800,
+       0x856f8b6f, 0xb96fa2c3,
+       0xb973f801, 0xb8ee3b05,
+       0x806e816e, 0xbf0d9972,
+       0xbfa20002, 0x846e896e,
+       0xbfa00001, 0x846e8a6e,
+       0xb8ef1e06, 0x846f8a6f,
+       0x806e6f6e, 0x806eff6e,
+       0x00000200, 0x806e746e,
+       0x826f8075, 0x8b6fff6f,
+       0x0000ffff, 0xf4085c37,
+       0xf8000050, 0xf4085d37,
+       0xf8000060, 0xf4005e77,
+       0xf8000074, 0xbf89fc07,
+       0x8b6dff6d, 0x0000ffff,
+       0x8bfe7e7e, 0x8bea6a6a,
+       0xb8eef802, 0xbf0d866e,
+       0xbfa20002, 0xb97af802,
+       0xbe80486c, 0xb97af802,
+       0xbe804a6c, 0xbfb00000,
        0xbf9f0000, 0xbf9f0000,
        0xbf9f0000, 0xbf9f0000,
+       0xbf9f0000, 0x00000000,
 };
index 0f81670..8b92c33 100644 (file)
@@ -186,6 +186,12 @@ L_SKIP_RESTORE:
        s_getreg_b32    s_save_trapsts, hwreg(HW_REG_TRAPSTS)
 
 #if SW_SA_TRAP
+       // If ttmp1[30] is set then issue s_barrier to unblock dependent waves.
+       s_bitcmp1_b32   s_save_pc_hi, 30
+       s_cbranch_scc0  L_TRAP_NO_BARRIER
+       s_barrier
+
+L_TRAP_NO_BARRIER:
        // If ttmp1[31] is set then trap may occur early.
        // Spin wait until SAVECTX exception is raised.
        s_bitcmp1_b32   s_save_pc_hi, 31
index 2797029..22b077a 100644 (file)
@@ -973,12 +973,10 @@ out_unlock_prange:
 out_unlock_svms:
        mutex_unlock(&p->svms.lock);
 out_unref_process:
+       pr_debug("CPU fault svms 0x%p address 0x%lx done\n", &p->svms, addr);
        kfd_unref_process(p);
 out_mmput:
        mmput(mm);
-
-       pr_debug("CPU fault svms 0x%p address 0x%lx done\n", &p->svms, addr);
-
        return r ? VM_FAULT_SIGBUS : 0;
 }
 
index c053cb7..589bee9 100644 (file)
@@ -1549,6 +1549,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
 
        adev->dm.dc->debug.visual_confirm = amdgpu_dc_visual_confirm;
 
+       /* TODO: Remove after DP2 receiver gets proper support of Cable ID feature */
+       adev->dm.dc->debug.ignore_cable_id = true;
+
        r = dm_dmub_hw_init(adev);
        if (r) {
                DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r);
index 1c612cc..6f77d8e 100644 (file)
@@ -157,6 +157,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
        unsigned int num_levels;
        struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
+       unsigned int i;
 
        memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
        clk_mgr_base->clks.p_state_change_support = true;
@@ -205,18 +206,17 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
                clk_mgr->dpm_present = true;
 
        if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) {
-               unsigned int i;
-
                for (i = 0; i < num_levels; i++)
                        if (clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz
                                        < khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz))
                                clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz
                                        = khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz);
        }
+       for (i = 0; i < num_levels; i++)
+               if (clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz > 1950)
+                       clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz = 1950;
 
        if (clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz) {
-               unsigned int i;
-
                for (i = 0; i < num_levels; i++)
                        if (clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz
                                        < khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz))
@@ -669,6 +669,9 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
                        &clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz,
                        &num_entries_per_clk->num_memclk_levels);
 
+       /* memclk must have at least one level */
+       num_entries_per_clk->num_memclk_levels = num_entries_per_clk->num_memclk_levels ? num_entries_per_clk->num_memclk_levels : 1;
+
        dcn32_init_single_clock(clk_mgr, PPCLK_FCLK,
                        &clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz,
                        &num_entries_per_clk->num_fclk_levels);
index bfc5474..737b221 100644 (file)
@@ -852,6 +852,7 @@ struct dc_debug_options {
        bool enable_double_buffered_dsc_pg_support;
        bool enable_dp_dig_pixel_rate_div_policy;
        enum lttpr_mode lttpr_mode_override;
+       unsigned int dsc_delay_factor_wa_x1000;
 };
 
 struct gpu_info_soc_bounding_box_v1_0;
index 4996d28..938dba5 100644 (file)
@@ -623,6 +623,10 @@ void hubp2_cursor_set_attributes(
        hubp->att.size.bits.width    = attr->width;
        hubp->att.size.bits.height   = attr->height;
        hubp->att.cur_ctl.bits.mode  = attr->color_format;
+
+       hubp->cur_rect.w = attr->width;
+       hubp->cur_rect.h = attr->height;
+
        hubp->att.cur_ctl.bits.pitch = hw_pitch;
        hubp->att.cur_ctl.bits.line_per_chunk = lpc;
        hubp->att.cur_ctl.bits.cur_2x_magnify = attr->attribute_flags.bits.ENABLE_MAGNIFICATION;
index d0ad72c..9066c51 100644 (file)
@@ -847,7 +847,7 @@ static const struct resource_caps res_cap_dcn314 = {
        .num_ddc = 5,
        .num_vmid = 16,
        .num_mpc_3dlut = 2,
-       .num_dsc = 3,
+       .num_dsc = 4,
 };
 
 static const struct dc_plane_cap plane_cap = {
index d680f1c..45db40c 100644 (file)
@@ -1228,6 +1228,7 @@ int dcn20_populate_dml_pipes_from_context(
                pipes[pipe_cnt].pipe.src.dcc = false;
                pipes[pipe_cnt].pipe.src.dcc_rate = 1;
                pipes[pipe_cnt].pipe.dest.synchronized_vblank_all_planes = synchronized_vblank;
+               pipes[pipe_cnt].pipe.dest.synchronize_timings = synchronized_vblank;
                pipes[pipe_cnt].pipe.dest.hblank_start = timing->h_total - timing->h_front_porch;
                pipes[pipe_cnt].pipe.dest.hblank_end = pipes[pipe_cnt].pipe.dest.hblank_start
                                - timing->h_addressable
index 819de0f..f37c9a6 100644 (file)
@@ -2359,9 +2359,11 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
 
                if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
                        dcn3_2_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
-
        }
 
+       /* DML DSC delay factor workaround */
+       dcn3_2_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0;
+
        /* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */
        dcn3_2_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
        dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
index 5b91660..3d18467 100644 (file)
@@ -364,10 +364,11 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
        for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) {
                v->DSCDelay[k] = dml32_DSCDelayRequirement(mode_lib->vba.DSCEnabled[k],
                                mode_lib->vba.ODMCombineEnabled[k], mode_lib->vba.DSCInputBitPerComponent[k],
-                               mode_lib->vba.OutputBpp[k], mode_lib->vba.HActive[k], mode_lib->vba.HTotal[k],
+                               mode_lib->vba.OutputBppPerState[mode_lib->vba.VoltageLevel][k],
+                               mode_lib->vba.HActive[k], mode_lib->vba.HTotal[k],
                                mode_lib->vba.NumberOfDSCSlices[k], mode_lib->vba.OutputFormat[k],
                                mode_lib->vba.Output[k], mode_lib->vba.PixelClock[k],
-                               mode_lib->vba.PixelClockBackEnd[k]);
+                               mode_lib->vba.PixelClockBackEnd[k], mode_lib->vba.ip.dsc_delay_factor_wa);
        }
 
        for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k)
@@ -1627,7 +1628,7 @@ static void mode_support_configuration(struct vba_vars_st *v,
                                && !mode_lib->vba.MSOOrODMSplitWithNonDPLink
                                && !mode_lib->vba.NotEnoughLanesForMSO
                                && mode_lib->vba.LinkCapacitySupport[i] == true && !mode_lib->vba.P2IWith420
-                               && !mode_lib->vba.DSCOnlyIfNecessaryWithBPP
+                               //&& !mode_lib->vba.DSCOnlyIfNecessaryWithBPP
                                && !mode_lib->vba.DSC422NativeNotSupported
                                && !mode_lib->vba.MPCCombineMethodIncompatible
                                && mode_lib->vba.ODMCombine2To1SupportCheckOK[i] == true
@@ -2475,7 +2476,8 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                        mode_lib->vba.OutputBppPerState[i][k], mode_lib->vba.HActive[k],
                                        mode_lib->vba.HTotal[k], mode_lib->vba.NumberOfDSCSlices[k],
                                        mode_lib->vba.OutputFormat[k], mode_lib->vba.Output[k],
-                                       mode_lib->vba.PixelClock[k], mode_lib->vba.PixelClockBackEnd[k]);
+                                       mode_lib->vba.PixelClock[k], mode_lib->vba.PixelClockBackEnd[k],
+                                       mode_lib->vba.ip.dsc_delay_factor_wa);
                }
 
                for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) {
index ad66e24..968924c 100644 (file)
@@ -1726,7 +1726,8 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled,
                enum output_format_class  OutputFormat,
                enum output_encoder_class Output,
                double PixelClock,
-               double PixelClockBackEnd)
+               double PixelClockBackEnd,
+               double dsc_delay_factor_wa)
 {
        unsigned int DSCDelayRequirement_val;
 
@@ -1746,7 +1747,7 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled,
                }
 
                DSCDelayRequirement_val = DSCDelayRequirement_val + (HTotal - HActive) *
-                               dml_ceil(DSCDelayRequirement_val / HActive, 1);
+                               dml_ceil((double)DSCDelayRequirement_val / HActive, 1);
 
                DSCDelayRequirement_val = DSCDelayRequirement_val * PixelClock / PixelClockBackEnd;
 
@@ -1764,7 +1765,7 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled,
        dml_print("DML::%s: DSCDelayRequirement_val = %d\n", __func__, DSCDelayRequirement_val);
 #endif
 
-       return DSCDelayRequirement_val;
+       return dml_ceil(DSCDelayRequirement_val * dsc_delay_factor_wa, 1);
 }
 
 void dml32_CalculateSurfaceSizeInMall(
index 55cead0..2c38275 100644 (file)
@@ -327,7 +327,8 @@ unsigned int dml32_DSCDelayRequirement(bool DSCEnabled,
                enum output_format_class  OutputFormat,
                enum output_encoder_class Output,
                double PixelClock,
-               double PixelClockBackEnd);
+               double PixelClockBackEnd,
+               double dsc_delay_factor_wa);
 
 void dml32_CalculateSurfaceSizeInMall(
                unsigned int NumberOfActiveSurfaces,
index a1276f6..395ae87 100644 (file)
@@ -291,8 +291,8 @@ void dml32_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib,
 
        dml_print("DML_DLG: %s: vready_after_vcount0 = %d\n", __func__, dlg_regs->vready_after_vcount0);
 
-       dst_x_after_scaler = get_dst_x_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx);
-       dst_y_after_scaler = get_dst_y_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx);
+       dst_x_after_scaler = dml_ceil(get_dst_x_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx), 1);
+       dst_y_after_scaler = dml_ceil(get_dst_y_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx), 1);
 
        // do some adjustment on the dst_after scaler to account for odm combine mode
        dml_print("DML_DLG: %s: input dst_x_after_scaler   = %d\n", __func__, dst_x_after_scaler);
index dd90f24..ec0486e 100644 (file)
@@ -29,6 +29,7 @@
 #include "dcn321_fpu.h"
 #include "dcn32/dcn32_resource.h"
 #include "dcn321/dcn321_resource.h"
+#include "dml/dcn32/display_mode_vba_util_32.h"
 
 #define DCN3_2_DEFAULT_DET_SIZE 256
 
@@ -119,15 +120,15 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_21_soc = {
                },
        },
        .num_states = 1,
-       .sr_exit_time_us = 12.36,
-       .sr_enter_plus_exit_time_us = 16.72,
+       .sr_exit_time_us = 19.95,
+       .sr_enter_plus_exit_time_us = 24.36,
        .sr_exit_z8_time_us = 285.0,
        .sr_enter_plus_exit_z8_time_us = 320,
        .writeback_latency_us = 12.0,
        .round_trip_ping_latency_dcfclk_cycles = 263,
-       .urgent_latency_pixel_data_only_us = 4.0,
-       .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
-       .urgent_latency_vm_data_only_us = 4.0,
+       .urgent_latency_pixel_data_only_us = 9.35,
+       .urgent_latency_pixel_mixed_with_vm_data_us = 9.35,
+       .urgent_latency_vm_data_only_us = 9.35,
        .fclk_change_latency_us = 20,
        .usr_retraining_latency_us = 2,
        .smn_latency_us = 2,
@@ -538,9 +539,11 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
 
                if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
                        dcn3_21_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
-
        }
 
+       /* DML DSC delay factor workaround */
+       dcn3_21_ip.dsc_delay_factor_wa = dc->debug.dsc_delay_factor_wa_x1000 / 1000.0;
+
        /* Override dispclk_dppclk_vco_speed_mhz from Clk Mgr */
        dcn3_21_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
        dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
index f33a887..d7be01a 100644 (file)
@@ -364,6 +364,9 @@ struct _vcs_dpi_ip_params_st {
        unsigned int max_num_dp2p0_outputs;
        unsigned int max_num_dp2p0_streams;
        unsigned int VBlankNomDefaultUS;
+
+       /* DM workarounds */
+       double dsc_delay_factor_wa; // TODO: Remove after implementing root cause fix
 };
 
 struct _vcs_dpi_display_xfc_params_st {
index 03924ae..8e6585d 100644 (file)
@@ -625,7 +625,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
                mode_lib->vba.skip_dio_check[mode_lib->vba.NumberOfActivePlanes] =
                                dout->is_virtual;
 
-               if (!dout->dsc_enable)
+               if (dout->dsc_enable)
                        mode_lib->vba.ForcedOutputLinkBPP[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpp;
                else
                        mode_lib->vba.ForcedOutputLinkBPP[mode_lib->vba.NumberOfActivePlanes] = 0.0;
index e2f7662..3ee59ba 100644 (file)
@@ -807,6 +807,38 @@ static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t
        return false;
 }
 
+static const uint32_t conv_from_xrgb8888[] = {
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_ARGB8888,
+       DRM_FORMAT_XRGB2101010,
+       DRM_FORMAT_ARGB2101010,
+       DRM_FORMAT_RGB565,
+       DRM_FORMAT_RGB888,
+};
+
+static const uint32_t conv_from_rgb565_888[] = {
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_ARGB8888,
+};
+
+static bool is_conversion_supported(uint32_t from, uint32_t to)
+{
+       switch (from) {
+       case DRM_FORMAT_XRGB8888:
+       case DRM_FORMAT_ARGB8888:
+               return is_listed_fourcc(conv_from_xrgb8888, ARRAY_SIZE(conv_from_xrgb8888), to);
+       case DRM_FORMAT_RGB565:
+       case DRM_FORMAT_RGB888:
+               return is_listed_fourcc(conv_from_rgb565_888, ARRAY_SIZE(conv_from_rgb565_888), to);
+       case DRM_FORMAT_XRGB2101010:
+               return to == DRM_FORMAT_ARGB2101010;
+       case DRM_FORMAT_ARGB2101010:
+               return to == DRM_FORMAT_XRGB2101010;
+       default:
+               return false;
+       }
+}
+
 /**
  * drm_fb_build_fourcc_list - Filters a list of supported color formats against
  *                            the device's native formats
@@ -827,7 +859,9 @@ static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t
  * be handed over to drm_universal_plane_init() et al. Native formats
  * will go before emulated formats. Other heuristics might be applied
  * to optimize the order. Formats near the beginning of the list are
- * usually preferred over formats near the end of the list.
+ * usually preferred over formats near the end of the list. Formats
+ * without conversion helpers will be skipped. New drivers should only
+ * pass in XRGB8888 and avoid exposing additional emulated formats.
  *
  * Returns:
  * The number of color-formats 4CC codes returned in @fourccs_out.
@@ -839,7 +873,7 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
 {
        u32 *fourccs = fourccs_out;
        const u32 *fourccs_end = fourccs_out + nfourccs_out;
-       bool found_native = false;
+       uint32_t native_format = 0;
        size_t i;
 
        /*
@@ -858,27 +892,19 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
 
                drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc);
 
-               if (!found_native)
-                       found_native = is_listed_fourcc(driver_fourccs, driver_nfourccs, fourcc);
+               /*
+                * There should only be one native format with the current API.
+                * This API needs to be refactored to correctly support arbitrary
+                * sets of native formats, since it needs to report which native
+                * format to use for each emulated format.
+                */
+               if (!native_format)
+                       native_format = fourcc;
                *fourccs = fourcc;
                ++fourccs;
        }
 
        /*
-        * The plane's atomic_update helper converts the framebuffer's color format
-        * to a native format when copying to device memory.
-        *
-        * If there is not a single format supported by both, device and
-        * driver, the native formats are likely not supported by the conversion
-        * helpers. Therefore *only* support the native formats and add a
-        * conversion helper ASAP.
-        */
-       if (!found_native) {
-               drm_warn(dev, "Format conversion helpers required to add extra formats.\n");
-               goto out;
-       }
-
-       /*
         * The extra formats, emulated by the driver, go second.
         */
 
@@ -890,6 +916,9 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
                } else if (fourccs == fourccs_end) {
                        drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc);
                        continue; /* end of available output buffer */
+               } else if (!is_conversion_supported(fourcc, native_format)) {
+                       drm_dbg_kms(dev, "Unsupported emulated format %p4cc\n", &fourcc);
+                       continue; /* format is not supported for conversion */
                }
 
                drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc);
@@ -898,7 +927,6 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev,
                ++fourccs;
        }
 
-out:
        return fourccs - fourccs_out;
 }
 EXPORT_SYMBOL(drm_fb_build_fourcc_list);
index a26edcd..cea00aa 100644 (file)
@@ -282,6 +282,7 @@ i915-y += \
        display/intel_ddi.o \
        display/intel_ddi_buf_trans.o \
        display/intel_display_trace.o \
+       display/intel_dkl_phy.o \
        display/intel_dp.o \
        display/intel_dp_aux.o \
        display/intel_dp_aux_backlight.o \
index da8472c..69ecf2a 100644 (file)
@@ -43,6 +43,7 @@
 #include "intel_de.h"
 #include "intel_display_power.h"
 #include "intel_display_types.h"
+#include "intel_dkl_phy.h"
 #include "intel_dp.h"
 #include "intel_dp_link_training.h"
 #include "intel_dp_mst.h"
@@ -1262,33 +1263,30 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
        for (ln = 0; ln < 2; ln++) {
                int level;
 
-               intel_de_write(dev_priv, HIP_INDEX_REG(tc_port),
-                              HIP_INDEX_VAL(tc_port, ln));
-
-               intel_de_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port), 0);
+               intel_dkl_phy_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port), ln, 0);
 
                level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
 
-               intel_de_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port),
-                            DKL_TX_PRESHOOT_COEFF_MASK |
-                            DKL_TX_DE_EMPAHSIS_COEFF_MASK |
-                            DKL_TX_VSWING_CONTROL_MASK,
-                            DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
-                            DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
-                            DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
+               intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port), ln,
+                                 DKL_TX_PRESHOOT_COEFF_MASK |
+                                 DKL_TX_DE_EMPAHSIS_COEFF_MASK |
+                                 DKL_TX_VSWING_CONTROL_MASK,
+                                 DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
+                                 DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
+                                 DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
 
                level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
 
-               intel_de_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port),
-                            DKL_TX_PRESHOOT_COEFF_MASK |
-                            DKL_TX_DE_EMPAHSIS_COEFF_MASK |
-                            DKL_TX_VSWING_CONTROL_MASK,
-                            DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
-                            DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
-                            DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
+               intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port), ln,
+                                 DKL_TX_PRESHOOT_COEFF_MASK |
+                                 DKL_TX_DE_EMPAHSIS_COEFF_MASK |
+                                 DKL_TX_VSWING_CONTROL_MASK,
+                                 DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
+                                 DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
+                                 DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
 
-               intel_de_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port),
-                            DKL_TX_DP20BITMODE, 0);
+               intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), ln,
+                                 DKL_TX_DP20BITMODE, 0);
 
                if (IS_ALDERLAKE_P(dev_priv)) {
                        u32 val;
@@ -1306,10 +1304,10 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
                                val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(0);
                        }
 
-                       intel_de_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port),
-                                    DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK |
-                                    DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK,
-                                    val);
+                       intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), ln,
+                                         DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK |
+                                         DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK,
+                                         val);
                }
        }
 }
@@ -2019,12 +2017,8 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port,
                return;
 
        if (DISPLAY_VER(dev_priv) >= 12) {
-               intel_de_write(dev_priv, HIP_INDEX_REG(tc_port),
-                              HIP_INDEX_VAL(tc_port, 0x0));
-               ln0 = intel_de_read(dev_priv, DKL_DP_MODE(tc_port));
-               intel_de_write(dev_priv, HIP_INDEX_REG(tc_port),
-                              HIP_INDEX_VAL(tc_port, 0x1));
-               ln1 = intel_de_read(dev_priv, DKL_DP_MODE(tc_port));
+               ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port), 0);
+               ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port), 1);
        } else {
                ln0 = intel_de_read(dev_priv, MG_DP_MODE(0, tc_port));
                ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port));
@@ -2085,12 +2079,8 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port,
        }
 
        if (DISPLAY_VER(dev_priv) >= 12) {
-               intel_de_write(dev_priv, HIP_INDEX_REG(tc_port),
-                              HIP_INDEX_VAL(tc_port, 0x0));
-               intel_de_write(dev_priv, DKL_DP_MODE(tc_port), ln0);
-               intel_de_write(dev_priv, HIP_INDEX_REG(tc_port),
-                              HIP_INDEX_VAL(tc_port, 0x1));
-               intel_de_write(dev_priv, DKL_DP_MODE(tc_port), ln1);
+               intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port), 0, ln0);
+               intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port), 1, ln1);
        } else {
                intel_de_write(dev_priv, MG_DP_MODE(0, tc_port), ln0);
                intel_de_write(dev_priv, MG_DP_MODE(1, tc_port), ln1);
@@ -3094,10 +3084,8 @@ static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder)
        enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
        int ln;
 
-       for (ln = 0; ln < 2; ln++) {
-               intel_de_write(i915, HIP_INDEX_REG(tc_port), HIP_INDEX_VAL(tc_port, ln));
-               intel_de_rmw(i915, DKL_PCS_DW5(tc_port), DKL_PCS_DW5_CORE_SOFTRESET, 0);
-       }
+       for (ln = 0; ln < 2; ln++)
+               intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port), ln, DKL_PCS_DW5_CORE_SOFTRESET, 0);
 }
 
 static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
index 96cf994..9b51148 100644 (file)
@@ -316,6 +316,14 @@ struct intel_display {
        } dbuf;
 
        struct {
+               /*
+                * dkl.phy_lock protects against concurrent access of the
+                * Dekel TypeC PHYs.
+                */
+               spinlock_t phy_lock;
+       } dkl;
+
+       struct {
                /* VLV/CHV/BXT/GLK DSI MMIO register base address */
                u32 mmio_base;
        } dsi;
index df7ee49..1d18eee 100644 (file)
@@ -12,6 +12,7 @@
 #include "intel_de.h"
 #include "intel_display_power_well.h"
 #include "intel_display_types.h"
+#include "intel_dkl_phy.h"
 #include "intel_dmc.h"
 #include "intel_dpio_phy.h"
 #include "intel_dpll.h"
@@ -529,11 +530,9 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
                enum tc_port tc_port;
 
                tc_port = TGL_AUX_PW_TO_TC_PORT(i915_power_well_instance(power_well)->hsw.idx);
-               intel_de_write(dev_priv, HIP_INDEX_REG(tc_port),
-                              HIP_INDEX_VAL(tc_port, 0x2));
 
-               if (intel_de_wait_for_set(dev_priv, DKL_CMN_UC_DW_27(tc_port),
-                                         DKL_CMN_UC_DW27_UC_HEALTH, 1))
+               if (wait_for(intel_dkl_phy_read(dev_priv, DKL_CMN_UC_DW_27(tc_port), 2) &
+                            DKL_CMN_UC_DW27_UC_HEALTH, 1))
                        drm_warn(&dev_priv->drm,
                                 "Timeout waiting TC uC health\n");
        }
diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.c b/drivers/gpu/drm/i915/display/intel_dkl_phy.c
new file mode 100644 (file)
index 0000000..710b030
--- /dev/null
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright Â© 2022 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "i915_reg.h"
+
+#include "intel_de.h"
+#include "intel_display.h"
+#include "intel_dkl_phy.h"
+
+static void
+dkl_phy_set_hip_idx(struct drm_i915_private *i915, i915_reg_t reg, int idx)
+{
+       enum tc_port tc_port = DKL_REG_TC_PORT(reg);
+
+       drm_WARN_ON(&i915->drm, tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS);
+
+       intel_de_write(i915,
+                      HIP_INDEX_REG(tc_port),
+                      HIP_INDEX_VAL(tc_port, idx));
+}
+
+/**
+ * intel_dkl_phy_read - read a Dekel PHY register
+ * @i915: i915 device instance
+ * @reg: Dekel PHY register
+ * @ln: lane instance of @reg
+ *
+ * Read the @reg Dekel PHY register.
+ *
+ * Returns the read value.
+ */
+u32
+intel_dkl_phy_read(struct drm_i915_private *i915, i915_reg_t reg, int ln)
+{
+       u32 val;
+
+       spin_lock(&i915->display.dkl.phy_lock);
+
+       dkl_phy_set_hip_idx(i915, reg, ln);
+       val = intel_de_read(i915, reg);
+
+       spin_unlock(&i915->display.dkl.phy_lock);
+
+       return val;
+}
+
+/**
+ * intel_dkl_phy_write - write a Dekel PHY register
+ * @i915: i915 device instance
+ * @reg: Dekel PHY register
+ * @ln: lane instance of @reg
+ * @val: value to write
+ *
+ * Write @val to the @reg Dekel PHY register.
+ */
+void
+intel_dkl_phy_write(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 val)
+{
+       spin_lock(&i915->display.dkl.phy_lock);
+
+       dkl_phy_set_hip_idx(i915, reg, ln);
+       intel_de_write(i915, reg, val);
+
+       spin_unlock(&i915->display.dkl.phy_lock);
+}
+
+/**
+ * intel_dkl_phy_rmw - read-modify-write a Dekel PHY register
+ * @i915: i915 device instance
+ * @reg: Dekel PHY register
+ * @ln: lane instance of @reg
+ * @clear: mask to clear
+ * @set: mask to set
+ *
+ * Read the @reg Dekel PHY register, clearing then setting the @clear/@set bits in it, and writing
+ * this value back to the register if the value differs from the read one.
+ */
+void
+intel_dkl_phy_rmw(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 clear, u32 set)
+{
+       spin_lock(&i915->display.dkl.phy_lock);
+
+       dkl_phy_set_hip_idx(i915, reg, ln);
+       intel_de_rmw(i915, reg, clear, set);
+
+       spin_unlock(&i915->display.dkl.phy_lock);
+}
+
+/**
+ * intel_dkl_phy_posting_read - do a posting read from a Dekel PHY register
+ * @i915: i915 device instance
+ * @reg: Dekel PHY register
+ * @ln: lane instance of @reg
+ *
+ * Read the @reg Dekel PHY register without returning the read value.
+ */
+void
+intel_dkl_phy_posting_read(struct drm_i915_private *i915, i915_reg_t reg, int ln)
+{
+       spin_lock(&i915->display.dkl.phy_lock);
+
+       dkl_phy_set_hip_idx(i915, reg, ln);
+       intel_de_posting_read(i915, reg);
+
+       spin_unlock(&i915->display.dkl.phy_lock);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.h b/drivers/gpu/drm/i915/display/intel_dkl_phy.h
new file mode 100644 (file)
index 0000000..260ad12
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright Â© 2022 Intel Corporation
+ */
+
+#ifndef __INTEL_DKL_PHY_H__
+#define __INTEL_DKL_PHY_H__
+
+#include <linux/types.h>
+
+#include "i915_reg_defs.h"
+
+struct drm_i915_private;
+
+u32
+intel_dkl_phy_read(struct drm_i915_private *i915, i915_reg_t reg, int ln);
+void
+intel_dkl_phy_write(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 val);
+void
+intel_dkl_phy_rmw(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 clear, u32 set);
+void
+intel_dkl_phy_posting_read(struct drm_i915_private *i915, i915_reg_t reg, int ln);
+
+#endif /* __INTEL_DKL_PHY_H__ */
index 47419d1..2b5bc95 100644 (file)
@@ -5276,7 +5276,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
                              encoder->devdata, IS_ERR(edid) ? NULL : edid);
 
        intel_panel_add_edid_fixed_modes(intel_connector,
-                                        intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE,
+                                        intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE ||
                                         intel_vrr_is_capable(intel_connector));
 
        /* MSO requires information from the EDID */
index e5fb66a..64dd603 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "intel_de.h"
 #include "intel_display_types.h"
+#include "intel_dkl_phy.h"
 #include "intel_dpio_phy.h"
 #include "intel_dpll.h"
 #include "intel_dpll_mgr.h"
@@ -3508,15 +3509,12 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv,
         * All registers read here have the same HIP_INDEX_REG even though
         * they are on different building blocks
         */
-       intel_de_write(dev_priv, HIP_INDEX_REG(tc_port),
-                      HIP_INDEX_VAL(tc_port, 0x2));
-
-       hw_state->mg_refclkin_ctl = intel_de_read(dev_priv,
-                                                 DKL_REFCLKIN_CTL(tc_port));
+       hw_state->mg_refclkin_ctl = intel_dkl_phy_read(dev_priv,
+                                                      DKL_REFCLKIN_CTL(tc_port), 2);
        hw_state->mg_refclkin_ctl &= MG_REFCLKIN_CTL_OD_2_MUX_MASK;
 
        hw_state->mg_clktop2_hsclkctl =
-               intel_de_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port));
+               intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), 2);
        hw_state->mg_clktop2_hsclkctl &=
                MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
                MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
@@ -3524,32 +3522,32 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv,
                MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK;
 
        hw_state->mg_clktop2_coreclkctl1 =
-               intel_de_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port));
+               intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), 2);
        hw_state->mg_clktop2_coreclkctl1 &=
                MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
 
-       hw_state->mg_pll_div0 = intel_de_read(dev_priv, DKL_PLL_DIV0(tc_port));
+       hw_state->mg_pll_div0 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV0(tc_port), 2);
        val = DKL_PLL_DIV0_MASK;
        if (dev_priv->display.vbt.override_afc_startup)
                val |= DKL_PLL_DIV0_AFC_STARTUP_MASK;
        hw_state->mg_pll_div0 &= val;
 
-       hw_state->mg_pll_div1 = intel_de_read(dev_priv, DKL_PLL_DIV1(tc_port));
+       hw_state->mg_pll_div1 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port), 2);
        hw_state->mg_pll_div1 &= (DKL_PLL_DIV1_IREF_TRIM_MASK |
                                  DKL_PLL_DIV1_TDC_TARGET_CNT_MASK);
 
-       hw_state->mg_pll_ssc = intel_de_read(dev_priv, DKL_PLL_SSC(tc_port));
+       hw_state->mg_pll_ssc = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port), 2);
        hw_state->mg_pll_ssc &= (DKL_PLL_SSC_IREF_NDIV_RATIO_MASK |
                                 DKL_PLL_SSC_STEP_LEN_MASK |
                                 DKL_PLL_SSC_STEP_NUM_MASK |
                                 DKL_PLL_SSC_EN);
 
-       hw_state->mg_pll_bias = intel_de_read(dev_priv, DKL_PLL_BIAS(tc_port));
+       hw_state->mg_pll_bias = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port), 2);
        hw_state->mg_pll_bias &= (DKL_PLL_BIAS_FRAC_EN_H |
                                  DKL_PLL_BIAS_FBDIV_FRAC_MASK);
 
        hw_state->mg_pll_tdc_coldst_bias =
-               intel_de_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port));
+               intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2);
        hw_state->mg_pll_tdc_coldst_bias &= (DKL_PLL_TDC_SSC_STEP_SIZE_MASK |
                                             DKL_PLL_TDC_FEED_FWD_GAIN_MASK);
 
@@ -3737,61 +3735,58 @@ static void dkl_pll_write(struct drm_i915_private *dev_priv,
         * All registers programmed here have the same HIP_INDEX_REG even
         * though on different building block
         */
-       intel_de_write(dev_priv, HIP_INDEX_REG(tc_port),
-                      HIP_INDEX_VAL(tc_port, 0x2));
-
        /* All the registers are RMW */
-       val = intel_de_read(dev_priv, DKL_REFCLKIN_CTL(tc_port));
+       val = intel_dkl_phy_read(dev_priv, DKL_REFCLKIN_CTL(tc_port), 2);
        val &= ~MG_REFCLKIN_CTL_OD_2_MUX_MASK;
        val |= hw_state->mg_refclkin_ctl;
-       intel_de_write(dev_priv, DKL_REFCLKIN_CTL(tc_port), val);
+       intel_dkl_phy_write(dev_priv, DKL_REFCLKIN_CTL(tc_port), 2, val);
 
-       val = intel_de_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port));
+       val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), 2);
        val &= ~MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
        val |= hw_state->mg_clktop2_coreclkctl1;
-       intel_de_write(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), val);
+       intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), 2, val);
 
-       val = intel_de_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port));
+       val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), 2);
        val &= ~(MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
                 MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
                 MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK |
                 MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK);
        val |= hw_state->mg_clktop2_hsclkctl;
-       intel_de_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), val);
+       intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), 2, val);
 
        val = DKL_PLL_DIV0_MASK;
        if (dev_priv->display.vbt.override_afc_startup)
                val |= DKL_PLL_DIV0_AFC_STARTUP_MASK;
-       intel_de_rmw(dev_priv, DKL_PLL_DIV0(tc_port), val,
-                    hw_state->mg_pll_div0);
+       intel_dkl_phy_rmw(dev_priv, DKL_PLL_DIV0(tc_port), 2, val,
+                         hw_state->mg_pll_div0);
 
-       val = intel_de_read(dev_priv, DKL_PLL_DIV1(tc_port));
+       val = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port), 2);
        val &= ~(DKL_PLL_DIV1_IREF_TRIM_MASK |
                 DKL_PLL_DIV1_TDC_TARGET_CNT_MASK);
        val |= hw_state->mg_pll_div1;
-       intel_de_write(dev_priv, DKL_PLL_DIV1(tc_port), val);
+       intel_dkl_phy_write(dev_priv, DKL_PLL_DIV1(tc_port), 2, val);
 
-       val = intel_de_read(dev_priv, DKL_PLL_SSC(tc_port));
+       val = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port), 2);
        val &= ~(DKL_PLL_SSC_IREF_NDIV_RATIO_MASK |
                 DKL_PLL_SSC_STEP_LEN_MASK |
                 DKL_PLL_SSC_STEP_NUM_MASK |
                 DKL_PLL_SSC_EN);
        val |= hw_state->mg_pll_ssc;
-       intel_de_write(dev_priv, DKL_PLL_SSC(tc_port), val);
+       intel_dkl_phy_write(dev_priv, DKL_PLL_SSC(tc_port), 2, val);
 
-       val = intel_de_read(dev_priv, DKL_PLL_BIAS(tc_port));
+       val = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port), 2);
        val &= ~(DKL_PLL_BIAS_FRAC_EN_H |
                 DKL_PLL_BIAS_FBDIV_FRAC_MASK);
        val |= hw_state->mg_pll_bias;
-       intel_de_write(dev_priv, DKL_PLL_BIAS(tc_port), val);
+       intel_dkl_phy_write(dev_priv, DKL_PLL_BIAS(tc_port), 2, val);
 
-       val = intel_de_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port));
+       val = intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2);
        val &= ~(DKL_PLL_TDC_SSC_STEP_SIZE_MASK |
                 DKL_PLL_TDC_FEED_FWD_GAIN_MASK);
        val |= hw_state->mg_pll_tdc_coldst_bias;
-       intel_de_write(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), val);
+       intel_dkl_phy_write(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2, val);
 
-       intel_de_posting_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port));
+       intel_dkl_phy_posting_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2);
 }
 
 static void icl_pll_power_enable(struct drm_i915_private *dev_priv,
index 9aa38e8..e535223 100644 (file)
@@ -972,8 +972,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
 
        /* Try EDID first */
        intel_panel_add_edid_fixed_modes(intel_connector,
-                                        intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE,
-                                        false);
+                                        intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE);
 
        /* Failed to get EDID, what about VBT? */
        if (!intel_panel_preferred_fixed_mode(intel_connector))
index a3a3f9f..41cec9d 100644 (file)
@@ -254,10 +254,10 @@ static void intel_panel_destroy_probed_modes(struct intel_connector *connector)
 }
 
 void intel_panel_add_edid_fixed_modes(struct intel_connector *connector,
-                                     bool has_drrs, bool has_vrr)
+                                     bool use_alt_fixed_modes)
 {
        intel_panel_add_edid_preferred_mode(connector);
-       if (intel_panel_preferred_fixed_mode(connector) && (has_drrs || has_vrr))
+       if (intel_panel_preferred_fixed_mode(connector) && use_alt_fixed_modes)
                intel_panel_add_edid_alt_fixed_modes(connector);
        intel_panel_destroy_probed_modes(connector);
 }
index eff3ffd..5c5b5b7 100644 (file)
@@ -44,7 +44,7 @@ int intel_panel_fitting(struct intel_crtc_state *crtc_state,
 int intel_panel_compute_config(struct intel_connector *connector,
                               struct drm_display_mode *adjusted_mode);
 void intel_panel_add_edid_fixed_modes(struct intel_connector *connector,
-                                     bool has_drrs, bool has_vrr);
+                                     bool use_alt_fixed_modes);
 void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector);
 void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector);
 void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector,
index f5b744b..774c1dc 100644 (file)
@@ -2747,13 +2747,10 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
        if (!intel_sdvo_connector)
                return false;
 
-       if (device == 0) {
-               intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS0;
+       if (device == 0)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS0;
-       } else if (device == 1) {
-               intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS1;
+       else if (device == 1)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS1;
-       }
 
        intel_connector = &intel_sdvo_connector->base;
        connector = &intel_connector->base;
@@ -2808,7 +2805,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
        encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
        connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
 
-       intel_sdvo->controlled_output |= type;
        intel_sdvo_connector->output_flag = type;
 
        if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
@@ -2849,13 +2845,10 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
        encoder->encoder_type = DRM_MODE_ENCODER_DAC;
        connector->connector_type = DRM_MODE_CONNECTOR_VGA;
 
-       if (device == 0) {
-               intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB0;
+       if (device == 0)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0;
-       } else if (device == 1) {
-               intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB1;
+       else if (device == 1)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
-       }
 
        if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
                kfree(intel_sdvo_connector);
@@ -2885,13 +2878,10 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
        encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
        connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
 
-       if (device == 0) {
-               intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS0;
+       if (device == 0)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0;
-       } else if (device == 1) {
-               intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS1;
+       else if (device == 1)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
-       }
 
        if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
                kfree(intel_sdvo_connector);
@@ -2910,8 +2900,12 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
        intel_panel_add_vbt_sdvo_fixed_mode(intel_connector);
 
        if (!intel_panel_preferred_fixed_mode(intel_connector)) {
+               mutex_lock(&i915->drm.mode_config.mutex);
+
                intel_ddc_get_modes(connector, &intel_sdvo->ddc);
-               intel_panel_add_edid_fixed_modes(intel_connector, false, false);
+               intel_panel_add_edid_fixed_modes(intel_connector, false);
+
+               mutex_unlock(&i915->drm.mode_config.mutex);
        }
 
        intel_panel_init(intel_connector);
@@ -2926,16 +2920,39 @@ err:
        return false;
 }
 
+static u16 intel_sdvo_filter_output_flags(u16 flags)
+{
+       flags &= SDVO_OUTPUT_MASK;
+
+       /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/
+       if (!(flags & SDVO_OUTPUT_TMDS0))
+               flags &= ~SDVO_OUTPUT_TMDS1;
+
+       if (!(flags & SDVO_OUTPUT_RGB0))
+               flags &= ~SDVO_OUTPUT_RGB1;
+
+       if (!(flags & SDVO_OUTPUT_LVDS0))
+               flags &= ~SDVO_OUTPUT_LVDS1;
+
+       return flags;
+}
+
 static bool
 intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags)
 {
-       /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/
+       struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev);
+
+       flags = intel_sdvo_filter_output_flags(flags);
+
+       intel_sdvo->controlled_output = flags;
+
+       intel_sdvo_select_ddc_bus(i915, intel_sdvo);
 
        if (flags & SDVO_OUTPUT_TMDS0)
                if (!intel_sdvo_dvi_init(intel_sdvo, 0))
                        return false;
 
-       if ((flags & SDVO_TMDS_MASK) == SDVO_TMDS_MASK)
+       if (flags & SDVO_OUTPUT_TMDS1)
                if (!intel_sdvo_dvi_init(intel_sdvo, 1))
                        return false;
 
@@ -2956,7 +2973,7 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags)
                if (!intel_sdvo_analog_init(intel_sdvo, 0))
                        return false;
 
-       if ((flags & SDVO_RGB_MASK) == SDVO_RGB_MASK)
+       if (flags & SDVO_OUTPUT_RGB1)
                if (!intel_sdvo_analog_init(intel_sdvo, 1))
                        return false;
 
@@ -2964,14 +2981,13 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags)
                if (!intel_sdvo_lvds_init(intel_sdvo, 0))
                        return false;
 
-       if ((flags & SDVO_LVDS_MASK) == SDVO_LVDS_MASK)
+       if (flags & SDVO_OUTPUT_LVDS1)
                if (!intel_sdvo_lvds_init(intel_sdvo, 1))
                        return false;
 
-       if ((flags & SDVO_OUTPUT_MASK) == 0) {
+       if (flags == 0) {
                unsigned char bytes[2];
 
-               intel_sdvo->controlled_output = 0;
                memcpy(bytes, &intel_sdvo->caps.output_flags, 2);
                DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n",
                              SDVO_NAME(intel_sdvo),
@@ -3383,8 +3399,6 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
         */
        intel_sdvo->base.cloneable = 0;
 
-       intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo);
-
        /* Set the input timing to the screen. Assume always input 0. */
        if (!intel_sdvo_set_target_input(intel_sdvo))
                goto err_output;
index c698f95..629acb4 100644 (file)
@@ -6,7 +6,6 @@
 
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
-#include <linux/swiotlb.h>
 
 #include "i915_drv.h"
 #include "i915_gem.h"
@@ -38,22 +37,12 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
        struct scatterlist *sg;
        unsigned int sg_page_sizes;
        unsigned int npages;
-       int max_order;
+       int max_order = MAX_ORDER;
+       unsigned int max_segment;
        gfp_t gfp;
 
-       max_order = MAX_ORDER;
-#ifdef CONFIG_SWIOTLB
-       if (is_swiotlb_active(obj->base.dev->dev)) {
-               unsigned int max_segment;
-
-               max_segment = swiotlb_max_segment();
-               if (max_segment) {
-                       max_segment = max_t(unsigned int, max_segment,
-                                           PAGE_SIZE) >> PAGE_SHIFT;
-                       max_order = min(max_order, ilog2(max_segment));
-               }
-       }
-#endif
+       max_segment = i915_sg_segment_size(i915->drm.dev) >> PAGE_SHIFT;
+       max_order = min(max_order, get_order(max_segment));
 
        gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_RECLAIMABLE;
        if (IS_I965GM(i915) || IS_I965G(i915)) {
index f42ca11..11125c3 100644 (file)
@@ -194,7 +194,7 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj)
        struct intel_memory_region *mem = obj->mm.region;
        struct address_space *mapping = obj->base.filp->f_mapping;
        const unsigned long page_count = obj->base.size / PAGE_SIZE;
-       unsigned int max_segment = i915_sg_segment_size();
+       unsigned int max_segment = i915_sg_segment_size(i915->drm.dev);
        struct sg_table *st;
        struct sgt_iter sgt_iter;
        struct page *page;
index 4f86178..a4aa950 100644 (file)
@@ -189,7 +189,7 @@ static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev,
        struct drm_i915_private *i915 = container_of(bdev, typeof(*i915), bdev);
        struct intel_memory_region *mr = i915->mm.regions[INTEL_MEMORY_SYSTEM];
        struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm);
-       const unsigned int max_segment = i915_sg_segment_size();
+       const unsigned int max_segment = i915_sg_segment_size(i915->drm.dev);
        const size_t size = (size_t)ttm->num_pages << PAGE_SHIFT;
        struct file *filp = i915_tt->filp;
        struct sgt_iter sgt_iter;
@@ -538,7 +538,7 @@ static struct i915_refct_sgt *i915_ttm_tt_get_st(struct ttm_tt *ttm)
        ret = sg_alloc_table_from_pages_segment(st,
                        ttm->pages, ttm->num_pages,
                        0, (unsigned long)ttm->num_pages << PAGE_SHIFT,
-                       i915_sg_segment_size(), GFP_KERNEL);
+                       i915_sg_segment_size(i915_tt->dev), GFP_KERNEL);
        if (ret) {
                st->sgl = NULL;
                return ERR_PTR(ret);
index d439894..f34e01a 100644 (file)
@@ -129,7 +129,7 @@ static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj)
 static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
 {
        const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
-       unsigned int max_segment = i915_sg_segment_size();
+       unsigned int max_segment = i915_sg_segment_size(obj->base.dev->dev);
        struct sg_table *st;
        unsigned int sg_page_sizes;
        struct page **pvec;
index c459eb3..f2a15d8 100644 (file)
@@ -353,6 +353,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
        mutex_init(&dev_priv->display.wm.wm_mutex);
        mutex_init(&dev_priv->display.pps.mutex);
        mutex_init(&dev_priv->display.hdcp.comp_mutex);
+       spin_lock_init(&dev_priv->display.dkl.phy_lock);
 
        i915_memcpy_init_early(dev_priv);
        intel_runtime_pm_init_early(&dev_priv->runtime_pm);
index 0b287a5..da35bb2 100644 (file)
@@ -7420,6 +7420,9 @@ enum skl_power_gate {
 #define _DKL_PHY5_BASE                 0x16C000
 #define _DKL_PHY6_BASE                 0x16D000
 
+#define DKL_REG_TC_PORT(__reg) \
+       (TC_PORT_1 + ((__reg).reg - _DKL_PHY1_BASE) / (_DKL_PHY2_BASE - _DKL_PHY1_BASE))
+
 /* DEKEL PHY MMIO Address = Phy base + (internal address & ~index_mask) */
 #define _DKL_PCS_DW5                   0x14
 #define DKL_PCS_DW5(tc_port)           _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \
index 9ddb3e7..b0a1db4 100644 (file)
@@ -9,7 +9,8 @@
 
 #include <linux/pfn.h>
 #include <linux/scatterlist.h>
-#include <linux/swiotlb.h>
+#include <linux/dma-mapping.h>
+#include <xen/xen.h>
 
 #include "i915_gem.h"
 
@@ -127,19 +128,26 @@ static inline unsigned int i915_sg_dma_sizes(struct scatterlist *sg)
        return page_sizes;
 }
 
-static inline unsigned int i915_sg_segment_size(void)
+static inline unsigned int i915_sg_segment_size(struct device *dev)
 {
-       unsigned int size = swiotlb_max_segment();
-
-       if (size == 0)
-               size = UINT_MAX;
-
-       size = rounddown(size, PAGE_SIZE);
-       /* swiotlb_max_segment_size can return 1 byte when it means one page. */
-       if (size < PAGE_SIZE)
-               size = PAGE_SIZE;
-
-       return size;
+       size_t max = min_t(size_t, UINT_MAX, dma_max_mapping_size(dev));
+
+       /*
+        * For Xen PV guests pages aren't contiguous in DMA (machine) address
+        * space.  The DMA API takes care of that both in dma_alloc_* (by
+        * calling into the hypervisor to make the pages contiguous) and in
+        * dma_map_* (by bounce buffering).  But i915 abuses ignores the
+        * coherency aspects of the DMA API and thus can't cope with bounce
+        * buffering actually happening, so add a hack here to force small
+        * allocations and mappings when running in PV mode on Xen.
+        *
+        * Note this will still break if bounce buffering is required for other
+        * reasons, like confidential computing hypervisors or PCIe root ports
+        * with addressing limitations.
+        */
+       if (xen_pv_domain())
+               max = PAGE_SIZE;
+       return round_down(max, PAGE_SIZE);
 }
 
 bool i915_sg_trim(struct sg_table *orig_st);
index 975de4f..fd5b247 100644 (file)
@@ -4,7 +4,6 @@ config DRM_IMX
        select DRM_KMS_HELPER
        select VIDEOMODE_HELPERS
        select DRM_GEM_DMA_HELPER
-       select DRM_KMS_HELPER
        depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM || COMPILE_TEST)
        depends on IMX_IPUV3_CORE
        help
index 6b34fac..ab4d1c8 100644 (file)
@@ -218,8 +218,9 @@ static int imx_tve_connector_get_modes(struct drm_connector *connector)
        return ret;
 }
 
-static int imx_tve_connector_mode_valid(struct drm_connector *connector,
-                                       struct drm_display_mode *mode)
+static enum drm_mode_status
+imx_tve_connector_mode_valid(struct drm_connector *connector,
+                            struct drm_display_mode *mode)
 {
        struct imx_tve *tve = con_to_tve(connector);
        unsigned long rate;
index bf69481..f4df982 100644 (file)
@@ -752,7 +752,7 @@ static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi)
 static void dw_mipi_dsi_rockchip_set_lcdsel(struct dw_mipi_dsi_rockchip *dsi,
                                            int mux)
 {
-       if (dsi->cdata->lcdsel_grf_reg < 0)
+       if (dsi->cdata->lcdsel_grf_reg)
                regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg,
                        mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big);
 }
@@ -1051,23 +1051,31 @@ static int dw_mipi_dsi_rockchip_host_attach(void *priv_data,
        if (ret) {
                DRM_DEV_ERROR(dsi->dev, "Failed to register component: %d\n",
                                        ret);
-               return ret;
+               goto out;
        }
 
        second = dw_mipi_dsi_rockchip_find_second(dsi);
-       if (IS_ERR(second))
-               return PTR_ERR(second);
+       if (IS_ERR(second)) {
+               ret = PTR_ERR(second);
+               goto out;
+       }
        if (second) {
                ret = component_add(second, &dw_mipi_dsi_rockchip_ops);
                if (ret) {
                        DRM_DEV_ERROR(second,
                                      "Failed to register component: %d\n",
                                      ret);
-                       return ret;
+                       goto out;
                }
        }
 
        return 0;
+
+out:
+       mutex_lock(&dsi->usage_mutex);
+       dsi->usage_mode = DW_DSI_USAGE_IDLE;
+       mutex_unlock(&dsi->usage_mutex);
+       return ret;
 }
 
 static int dw_mipi_dsi_rockchip_host_detach(void *priv_data,
@@ -1635,7 +1643,6 @@ static const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = {
 static const struct rockchip_dw_dsi_chip_data rk3568_chip_data[] = {
        {
                .reg = 0xfe060000,
-               .lcdsel_grf_reg = -1,
                .lanecfg1_grf_reg = RK3568_GRF_VO_CON2,
                .lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI0_SKEWCALHS |
                                          RK3568_DSI0_FORCETXSTOPMODE |
@@ -1645,7 +1652,6 @@ static const struct rockchip_dw_dsi_chip_data rk3568_chip_data[] = {
        },
        {
                .reg = 0xfe070000,
-               .lcdsel_grf_reg = -1,
                .lanecfg1_grf_reg = RK3568_GRF_VO_CON3,
                .lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI1_SKEWCALHS |
                                          RK3568_DSI1_FORCETXSTOPMODE |
@@ -1681,5 +1687,11 @@ struct platform_driver dw_mipi_dsi_rockchip_driver = {
                .of_match_table = dw_mipi_dsi_rockchip_dt_ids,
                .pm     = &dw_mipi_dsi_rockchip_pm_ops,
                .name   = "dw-mipi-dsi-rockchip",
+               /*
+                * For dual-DSI display, one DSI pokes at the other DSI's
+                * drvdata in dw_mipi_dsi_rockchip_find_second(). This is not
+                * safe for asynchronous probe.
+                */
+               .probe_type = PROBE_FORCE_SYNCHRONOUS,
        },
 };
index c14f888..2f4b8f6 100644 (file)
@@ -565,7 +565,8 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 
        ret = rockchip_hdmi_parse_dt(hdmi);
        if (ret) {
-               DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n");
+               if (ret != -EPROBE_DEFER)
+                       DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n");
                return ret;
        }
 
index 614e97a..da8a699 100644 (file)
@@ -364,9 +364,12 @@ rockchip_gem_create_with_handle(struct drm_file *file_priv,
 {
        struct rockchip_gem_object *rk_obj;
        struct drm_gem_object *obj;
+       bool is_framebuffer;
        int ret;
 
-       rk_obj = rockchip_gem_create_object(drm, size, false);
+       is_framebuffer = drm->fb_helper && file_priv == drm->fb_helper->client.file;
+
+       rk_obj = rockchip_gem_create_object(drm, size, is_framebuffer);
        if (IS_ERR(rk_obj))
                return ERR_CAST(rk_obj);
 
index aac20be..105a548 100644 (file)
@@ -877,10 +877,14 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
 {
        struct vop2_video_port *vp = to_vop2_video_port(crtc);
        struct vop2 *vop2 = vp->vop2;
+       struct drm_crtc_state *old_crtc_state;
        int ret;
 
        vop2_lock(vop2);
 
+       old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
+       drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false);
+
        drm_crtc_vblank_off(crtc);
 
        /*
@@ -996,13 +1000,15 @@ static int vop2_plane_atomic_check(struct drm_plane *plane,
 static void vop2_plane_atomic_disable(struct drm_plane *plane,
                                      struct drm_atomic_state *state)
 {
-       struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state, plane);
+       struct drm_plane_state *old_pstate = NULL;
        struct vop2_win *win = to_vop2_win(plane);
        struct vop2 *vop2 = win->vop2;
 
        drm_dbg(vop2->drm, "%s disable\n", win->data->name);
 
-       if (!old_pstate->crtc)
+       if (state)
+               old_pstate = drm_atomic_get_old_plane_state(state, plane);
+       if (old_pstate && !old_pstate->crtc)
                return;
 
        vop2_win_disable(win);
index e06509e..1fda1ea 100644 (file)
@@ -1243,6 +1243,7 @@ static const struct {
         */
        { "Latitude 5480",      0x29 },
        { "Vostro V131",        0x1d },
+       { "Vostro 5568",        0x29 },
 };
 
 static void register_dell_lis3lv02d_i2c_device(struct i801_priv *priv)
index 39cb1b7..809fbd0 100644 (file)
@@ -1080,6 +1080,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
                                           "", &piix4_main_adapters[0]);
                if (retval < 0)
                        return retval;
+               piix4_adapter_count = 1;
        }
 
        /* Check for auxiliary SMBus on some AMD chipsets */
index 954022c..3869c25 100644 (file)
@@ -284,6 +284,7 @@ struct tegra_i2c_dev {
        struct dma_chan *tx_dma_chan;
        struct dma_chan *rx_dma_chan;
        unsigned int dma_buf_size;
+       struct device *dma_dev;
        dma_addr_t dma_phys;
        void *dma_buf;
 
@@ -420,7 +421,7 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len)
 static void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev)
 {
        if (i2c_dev->dma_buf) {
-               dma_free_coherent(i2c_dev->dev, i2c_dev->dma_buf_size,
+               dma_free_coherent(i2c_dev->dma_dev, i2c_dev->dma_buf_size,
                                  i2c_dev->dma_buf, i2c_dev->dma_phys);
                i2c_dev->dma_buf = NULL;
        }
@@ -472,10 +473,13 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
 
        i2c_dev->tx_dma_chan = chan;
 
+       WARN_ON(i2c_dev->tx_dma_chan->device != i2c_dev->rx_dma_chan->device);
+       i2c_dev->dma_dev = chan->device->dev;
+
        i2c_dev->dma_buf_size = i2c_dev->hw->quirks->max_write_len +
                                I2C_PACKET_HEADER_SIZE;
 
-       dma_buf = dma_alloc_coherent(i2c_dev->dev, i2c_dev->dma_buf_size,
+       dma_buf = dma_alloc_coherent(i2c_dev->dma_dev, i2c_dev->dma_buf_size,
                                     &dma_phys, GFP_KERNEL | __GFP_NOWARN);
        if (!dma_buf) {
                dev_err(i2c_dev->dev, "failed to allocate DMA buffer\n");
@@ -1272,7 +1276,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 
        if (i2c_dev->dma_mode) {
                if (i2c_dev->msg_read) {
-                       dma_sync_single_for_device(i2c_dev->dev,
+                       dma_sync_single_for_device(i2c_dev->dma_dev,
                                                   i2c_dev->dma_phys,
                                                   xfer_size, DMA_FROM_DEVICE);
 
@@ -1280,7 +1284,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
                        if (err)
                                return err;
                } else {
-                       dma_sync_single_for_cpu(i2c_dev->dev,
+                       dma_sync_single_for_cpu(i2c_dev->dma_dev,
                                                i2c_dev->dma_phys,
                                                xfer_size, DMA_TO_DEVICE);
                }
@@ -1293,7 +1297,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
                        memcpy(i2c_dev->dma_buf + I2C_PACKET_HEADER_SIZE,
                               msg->buf, msg->len);
 
-                       dma_sync_single_for_device(i2c_dev->dev,
+                       dma_sync_single_for_device(i2c_dev->dma_dev,
                                                   i2c_dev->dma_phys,
                                                   xfer_size, DMA_TO_DEVICE);
 
@@ -1344,7 +1348,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
                }
 
                if (i2c_dev->msg_read && i2c_dev->msg_err == I2C_ERR_NONE) {
-                       dma_sync_single_for_cpu(i2c_dev->dev,
+                       dma_sync_single_for_cpu(i2c_dev->dma_dev,
                                                i2c_dev->dma_phys,
                                                xfer_size, DMA_FROM_DEVICE);
 
index a52f275..f844713 100644 (file)
@@ -956,7 +956,7 @@ nj_release(struct tiger_hw *card)
        }
        if (card->irq > 0)
                free_irq(card->irq, card);
-       if (card->isac.dch.dev.dev.class)
+       if (device_is_registered(&card->isac.dch.dev.dev))
                mISDN_unregister_device(&card->isac.dch.dev);
 
        for (i = 0; i < 2; i++) {
index a41b4b2..7ea0100 100644 (file)
@@ -233,11 +233,12 @@ mISDN_register_device(struct mISDNdevice *dev,
        if (debug & DEBUG_CORE)
                printk(KERN_DEBUG "mISDN_register %s %d\n",
                       dev_name(&dev->dev), dev->id);
+       dev->dev.class = &mISDN_class;
+
        err = create_stack(dev);
        if (err)
                goto error1;
 
-       dev->dev.class = &mISDN_class;
        dev->dev.platform_data = dev;
        dev->dev.parent = parent;
        dev_set_drvdata(&dev->dev, dev);
@@ -249,8 +250,8 @@ mISDN_register_device(struct mISDNdevice *dev,
 
 error3:
        delete_stack(dev);
-       return err;
 error1:
+       put_device(&dev->dev);
        return err;
 
 }
index b9107fe..5b139f2 100644 (file)
@@ -376,6 +376,17 @@ static struct mdio_driver dsa_loop_drv = {
 
 #define NUM_FIXED_PHYS (DSA_LOOP_NUM_PORTS - 2)
 
+static void dsa_loop_phydevs_unregister(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < NUM_FIXED_PHYS; i++)
+               if (!IS_ERR(phydevs[i])) {
+                       fixed_phy_unregister(phydevs[i]);
+                       phy_device_free(phydevs[i]);
+               }
+}
+
 static int __init dsa_loop_init(void)
 {
        struct fixed_phy_status status = {
@@ -383,23 +394,23 @@ static int __init dsa_loop_init(void)
                .speed = SPEED_100,
                .duplex = DUPLEX_FULL,
        };
-       unsigned int i;
+       unsigned int i, ret;
 
        for (i = 0; i < NUM_FIXED_PHYS; i++)
                phydevs[i] = fixed_phy_register(PHY_POLL, &status, NULL);
 
-       return mdio_driver_register(&dsa_loop_drv);
+       ret = mdio_driver_register(&dsa_loop_drv);
+       if (ret)
+               dsa_loop_phydevs_unregister();
+
+       return ret;
 }
 module_init(dsa_loop_init);
 
 static void __exit dsa_loop_exit(void)
 {
-       unsigned int i;
-
        mdio_driver_unregister(&dsa_loop_drv);
-       for (i = 0; i < NUM_FIXED_PHYS; i++)
-               if (!IS_ERR(phydevs[i]))
-                       fixed_phy_unregister(phydevs[i]);
+       dsa_loop_phydevs_unregister();
 }
 module_exit(dsa_loop_exit);
 
index 1744d62..606c976 100644 (file)
@@ -1512,16 +1512,15 @@ static struct notifier_block adin1110_switchdev_notifier = {
        .notifier_call = adin1110_switchdev_event,
 };
 
-static void adin1110_unregister_notifiers(void *data)
+static void adin1110_unregister_notifiers(void)
 {
        unregister_switchdev_blocking_notifier(&adin1110_switchdev_blocking_notifier);
        unregister_switchdev_notifier(&adin1110_switchdev_notifier);
        unregister_netdevice_notifier(&adin1110_netdevice_nb);
 }
 
-static int adin1110_setup_notifiers(struct adin1110_priv *priv)
+static int adin1110_setup_notifiers(void)
 {
-       struct device *dev = &priv->spidev->dev;
        int ret;
 
        ret = register_netdevice_notifier(&adin1110_netdevice_nb);
@@ -1536,13 +1535,14 @@ static int adin1110_setup_notifiers(struct adin1110_priv *priv)
        if (ret < 0)
                goto err_sdev;
 
-       return devm_add_action_or_reset(dev, adin1110_unregister_notifiers, NULL);
+       return 0;
 
 err_sdev:
        unregister_switchdev_notifier(&adin1110_switchdev_notifier);
 
 err_netdev:
        unregister_netdevice_notifier(&adin1110_netdevice_nb);
+
        return ret;
 }
 
@@ -1613,10 +1613,6 @@ static int adin1110_probe_netdevs(struct adin1110_priv *priv)
        if (ret < 0)
                return ret;
 
-       ret = adin1110_setup_notifiers(priv);
-       if (ret < 0)
-               return ret;
-
        for (i = 0; i < priv->cfg->ports_nr; i++) {
                ret = devm_register_netdev(dev, priv->ports[i]->netdev);
                if (ret < 0) {
@@ -1693,7 +1689,31 @@ static struct spi_driver adin1110_driver = {
        .probe = adin1110_probe,
        .id_table = adin1110_spi_id,
 };
-module_spi_driver(adin1110_driver);
+
+static int __init adin1110_driver_init(void)
+{
+       int ret;
+
+       ret = adin1110_setup_notifiers();
+       if (ret < 0)
+               return ret;
+
+       ret = spi_register_driver(&adin1110_driver);
+       if (ret < 0) {
+               adin1110_unregister_notifiers();
+               return ret;
+       }
+
+       return 0;
+}
+
+static void __exit adin1110_exit(void)
+{
+       adin1110_unregister_notifiers();
+       spi_unregister_driver(&adin1110_driver);
+}
+module_init(adin1110_driver_init);
+module_exit(adin1110_exit);
 
 MODULE_DESCRIPTION("ADIN1110 Network driver");
 MODULE_AUTHOR("Alexandru Tachici <alexandru.tachici@analog.com>");
index 28ef4d3..f623c12 100644 (file)
@@ -713,7 +713,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
                dev_kfree_skb_any(skb);
                if (net_ratelimit())
                        netdev_err(ndev, "Tx DMA memory map failed\n");
-               return NETDEV_TX_BUSY;
+               return NETDEV_TX_OK;
        }
 
        bdp->cbd_datlen = cpu_to_fec16(size);
@@ -775,7 +775,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
                        dev_kfree_skb_any(skb);
                        if (net_ratelimit())
                                netdev_err(ndev, "Tx DMA memory map failed\n");
-                       return NETDEV_TX_BUSY;
+                       return NETDEV_TX_OK;
                }
        }
 
index 65dbfbe..9282381 100644 (file)
@@ -3007,19 +3007,19 @@ static void __ibmvnic_reset(struct work_struct *work)
                rwi = get_next_rwi(adapter);
 
                /*
-                * If there is another reset queued, free the previous rwi
-                * and process the new reset even if previous reset failed
-                * (the previous reset could have failed because of a fail
-                * over for instance, so process the fail over).
-                *
                 * If there are no resets queued and the previous reset failed,
                 * the adapter would be in an undefined state. So retry the
                 * previous reset as a hard reset.
+                *
+                * Else, free the previous rwi and, if there is another reset
+                * queued, process the new reset even if previous reset failed
+                * (the previous reset could have failed because of a fail
+                * over for instance, so process the fail over).
                 */
-               if (rwi)
-                       kfree(tmprwi);
-               else if (rc)
+               if (!rwi && rc)
                        rwi = tmprwi;
+               else
+                       kfree(tmprwi);
 
                if (rwi && (rwi->reset_reason == VNIC_RESET_FAILOVER ||
                            rwi->reset_reason == VNIC_RESET_MOBILITY || rc))
index a42035c..e694893 100644 (file)
@@ -414,13 +414,15 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx)
        /* Get the received frame and unmap it */
        db = &rx->dcbs[rx->dcb_index].db[rx->db_index];
        page = rx->page[rx->dcb_index][rx->db_index];
+
+       dma_sync_single_for_cpu(lan966x->dev, (dma_addr_t)db->dataptr,
+                               FDMA_DCB_STATUS_BLOCKL(db->status),
+                               DMA_FROM_DEVICE);
+
        skb = build_skb(page_address(page), PAGE_SIZE << rx->page_order);
        if (unlikely(!skb))
                goto unmap_page;
 
-       dma_unmap_single(lan966x->dev, (dma_addr_t)db->dataptr,
-                        FDMA_DCB_STATUS_BLOCKL(db->status),
-                        DMA_FROM_DEVICE);
        skb_put(skb, FDMA_DCB_STATUS_BLOCKL(db->status));
 
        lan966x_ifh_get_src_port(skb->data, &src_port);
@@ -429,6 +431,10 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx)
        if (WARN_ON(src_port >= lan966x->num_phys_ports))
                goto free_skb;
 
+       dma_unmap_single_attrs(lan966x->dev, (dma_addr_t)db->dataptr,
+                              PAGE_SIZE << rx->page_order, DMA_FROM_DEVICE,
+                              DMA_ATTR_SKIP_CPU_SYNC);
+
        skb->dev = lan966x->ports[src_port]->dev;
        skb_pull(skb, IFH_LEN * sizeof(u32));
 
@@ -454,9 +460,9 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx)
 free_skb:
        kfree_skb(skb);
 unmap_page:
-       dma_unmap_page(lan966x->dev, (dma_addr_t)db->dataptr,
-                      FDMA_DCB_STATUS_BLOCKL(db->status),
-                      DMA_FROM_DEVICE);
+       dma_unmap_single_attrs(lan966x->dev, (dma_addr_t)db->dataptr,
+                              PAGE_SIZE << rx->page_order, DMA_FROM_DEVICE,
+                              DMA_ATTR_SKIP_CPU_SYNC);
        __free_pages(page, rx->page_order);
 
        return NULL;
@@ -668,12 +674,14 @@ static int lan966x_fdma_get_max_mtu(struct lan966x *lan966x)
        int i;
 
        for (i = 0; i < lan966x->num_phys_ports; ++i) {
+               struct lan966x_port *port;
                int mtu;
 
-               if (!lan966x->ports[i])
+               port = lan966x->ports[i];
+               if (!port)
                        continue;
 
-               mtu = lan966x->ports[i]->dev->mtu;
+               mtu = lan_rd(lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
                if (mtu > max_mtu)
                        max_mtu = mtu;
        }
@@ -733,6 +741,8 @@ int lan966x_fdma_change_mtu(struct lan966x *lan966x)
 
        max_mtu = lan966x_fdma_get_max_mtu(lan966x);
        max_mtu += IFH_LEN * sizeof(u32);
+       max_mtu += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+       max_mtu += VLAN_HLEN * 2;
 
        if (round_up(max_mtu, PAGE_SIZE) / PAGE_SIZE - 1 ==
            lan966x->rx.page_order)
index be2fd03..20ee5b2 100644 (file)
@@ -386,7 +386,7 @@ static int lan966x_port_change_mtu(struct net_device *dev, int new_mtu)
        int old_mtu = dev->mtu;
        int err;
 
-       lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(new_mtu),
+       lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(LAN966X_HW_MTU(new_mtu)),
               lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
        dev->mtu = new_mtu;
 
@@ -395,7 +395,7 @@ static int lan966x_port_change_mtu(struct net_device *dev, int new_mtu)
 
        err = lan966x_fdma_change_mtu(lan966x);
        if (err) {
-               lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(old_mtu),
+               lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(LAN966X_HW_MTU(old_mtu)),
                       lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
                dev->mtu = old_mtu;
        }
index 9656071..4ec3399 100644 (file)
@@ -26,6 +26,8 @@
 #define LAN966X_BUFFER_MEMORY          (160 * 1024)
 #define LAN966X_BUFFER_MIN_SZ          60
 
+#define LAN966X_HW_MTU(mtu)            ((mtu) + ETH_HLEN + ETH_FCS_LEN)
+
 #define PGID_AGGR                      64
 #define PGID_SRC                       80
 #define PGID_ENTRIES                   89
index 1d90b93..fb5087f 100644 (file)
@@ -585,6 +585,21 @@ enum lan966x_target {
 #define DEV_MAC_MAXLEN_CFG_MAX_LEN_GET(x)\
        FIELD_GET(DEV_MAC_MAXLEN_CFG_MAX_LEN, x)
 
+/*      DEV:MAC_CFG_STATUS:MAC_TAGS_CFG */
+#define DEV_MAC_TAGS_CFG(t)       __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 12, 0, 1, 4)
+
+#define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA        BIT(1)
+#define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_SET(x)\
+       FIELD_PREP(DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA, x)
+#define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_GET(x)\
+       FIELD_GET(DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA, x)
+
+#define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA            BIT(0)
+#define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(x)\
+       FIELD_PREP(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA, x)
+#define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_GET(x)\
+       FIELD_GET(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA, x)
+
 /*      DEV:MAC_CFG_STATUS:MAC_IFG_CFG */
 #define DEV_MAC_IFG_CFG(t)        __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 20, 0, 1, 4)
 
index 8d7260c..3c44660 100644 (file)
@@ -169,6 +169,12 @@ void lan966x_vlan_port_apply(struct lan966x_port *port)
                ANA_VLAN_CFG_VLAN_POP_CNT,
                lan966x, ANA_VLAN_CFG(port->chip_port));
 
+       lan_rmw(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(port->vlan_aware) |
+               DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_SET(port->vlan_aware),
+               DEV_MAC_TAGS_CFG_VLAN_AWR_ENA |
+               DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA,
+               lan966x, DEV_MAC_TAGS_CFG(port->chip_port));
+
        /* Drop frames with multicast source address */
        val = ANA_DROP_CFG_DROP_MC_SMAC_ENA_SET(1);
        if (port->vlan_aware && !pvid)
index 054d5ce..0556542 100644 (file)
@@ -1059,8 +1059,10 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
 
        /* Allocate and initialise a struct net_device */
        net_dev = alloc_etherdev_mq(sizeof(probe_data), EFX_MAX_CORE_TX_QUEUES);
-       if (!net_dev)
-               return -ENOMEM;
+       if (!net_dev) {
+               rc = -ENOMEM;
+               goto fail0;
+       }
        probe_ptr = netdev_priv(net_dev);
        *probe_ptr = probe_data;
        efx->net_dev = net_dev;
@@ -1132,6 +1134,8 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
        WARN_ON(rc > 0);
        netif_dbg(efx, drv, efx->net_dev, "initialisation failed. rc=%d\n", rc);
        free_netdev(net_dev);
+ fail0:
+       kfree(probe_data);
        return rc;
 }
 
index 017dbbd..79fa787 100644 (file)
@@ -51,7 +51,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
        struct stmmac_resources res;
        struct device_node *np;
        int ret, i, phy_mode;
-       bool mdio = false;
 
        np = dev_of_node(&pdev->dev);
 
@@ -69,12 +68,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
        if (!plat)
                return -ENOMEM;
 
+       plat->mdio_node = of_get_child_by_name(np, "mdio");
        if (plat->mdio_node) {
-               dev_err(&pdev->dev, "Found MDIO subnode\n");
-               mdio = true;
-       }
+               dev_info(&pdev->dev, "Found MDIO subnode\n");
 
-       if (mdio) {
                plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
                                                   sizeof(*plat->mdio_bus_data),
                                                   GFP_KERNEL);
index 05848ff..a3967f8 100644 (file)
  * @next_tx_buf_to_use:        next Tx buffer to write to
  * @next_rx_buf_to_use:        next Rx buffer to read from
  * @base_addr:         base address of the Emaclite device
- * @reset_lock:                lock used for synchronization
+ * @reset_lock:                lock to serialize xmit and tx_timeout execution
  * @deferred_skb:      holds an skb (for transmission at a later time) when the
  *                     Tx buffer is not free
  * @phy_dev:           pointer to the PHY device
index f82090b..1cd604c 100644 (file)
@@ -583,7 +583,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
        }
 
        for (i = 0; i < PHY_MAX_ADDR; i++) {
-               if ((bus->phy_mask & (1 << i)) == 0) {
+               if ((bus->phy_mask & BIT(i)) == 0) {
                        struct phy_device *phydev;
 
                        phydev = mdiobus_scan(bus, i);
index 27c6d23..9466280 100644 (file)
@@ -1459,7 +1459,8 @@ static struct sk_buff *tun_napi_alloc_frags(struct tun_file *tfile,
        int err;
        int i;
 
-       if (it->nr_segs > MAX_SKB_FRAGS + 1)
+       if (it->nr_segs > MAX_SKB_FRAGS + 1 ||
+           len > (ETH_MAX_MTU - NET_SKB_PAD - NET_IP_ALIGN))
                return ERR_PTR(-EMSGSIZE);
 
        local_bh_disable();
index c6b3334..f12f903 100644 (file)
@@ -249,11 +249,19 @@ static int fdp_nci_close(struct nci_dev *ndev)
 static int fdp_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
 {
        struct fdp_nci_info *info = nci_get_drvdata(ndev);
+       int ret;
 
        if (atomic_dec_and_test(&info->data_pkt_counter))
                info->data_pkt_counter_cb(ndev);
 
-       return info->phy_ops->write(info->phy, skb);
+       ret = info->phy_ops->write(info->phy, skb);
+       if (ret < 0) {
+               kfree_skb(skb);
+               return ret;
+       }
+
+       consume_skb(skb);
+       return 0;
 }
 
 static int fdp_nci_request_firmware(struct nci_dev *ndev)
index acef0cf..24436c9 100644 (file)
@@ -132,10 +132,15 @@ static int nfcmrvl_i2c_nci_send(struct nfcmrvl_private *priv,
                        ret = -EREMOTEIO;
                } else
                        ret = 0;
+       }
+
+       if (ret) {
                kfree_skb(skb);
+               return ret;
        }
 
-       return ret;
+       consume_skb(skb);
+       return 0;
 }
 
 static void nfcmrvl_i2c_nci_update_config(struct nfcmrvl_private *priv,
index 7c93d48..580cb6e 100644 (file)
@@ -80,10 +80,13 @@ static int nxp_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
                return -EINVAL;
 
        r = info->phy_ops->write(info->phy_id, skb);
-       if (r < 0)
+       if (r < 0) {
                kfree_skb(skb);
+               return r;
+       }
 
-       return r;
+       consume_skb(skb);
+       return 0;
 }
 
 static int nxp_nci_rf_pll_unlocked_ntf(struct nci_dev *ndev,
index 1c41200..0270e05 100644 (file)
@@ -110,11 +110,15 @@ static int s3fwrn5_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
        }
 
        ret = s3fwrn5_write(info, skb);
-       if (ret < 0)
+       if (ret < 0) {
                kfree_skb(skb);
+               mutex_unlock(&info->mutex);
+               return ret;
+       }
 
+       consume_skb(skb);
        mutex_unlock(&info->mutex);
-       return ret;
+       return 0;
 }
 
 static int s3fwrn5_nci_post_setup(struct nci_dev *ndev)
index 1f3d703..4d235c8 100644 (file)
@@ -135,11 +135,24 @@ static int imx93_pd_probe(struct platform_device *pdev)
 
        ret = pm_genpd_init(&domain->genpd, NULL, domain->init_off);
        if (ret)
-               return ret;
+               goto err_clk_unprepare;
 
        platform_set_drvdata(pdev, domain);
 
-       return of_genpd_add_provider_simple(np, &domain->genpd);
+       ret = of_genpd_add_provider_simple(np, &domain->genpd);
+       if (ret)
+               goto err_genpd_remove;
+
+       return 0;
+
+err_genpd_remove:
+       pm_genpd_remove(&domain->genpd);
+
+err_clk_unprepare:
+       if (!domain->init_off)
+               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       return ret;
 }
 
 static const struct of_device_id imx93_pd_ids[] = {
index 4ec18ce..18374a6 100644 (file)
@@ -289,8 +289,10 @@ static void prelim_release(struct preftree *preftree)
        struct prelim_ref *ref, *next_ref;
 
        rbtree_postorder_for_each_entry_safe(ref, next_ref,
-                                            &preftree->root.rb_root, rbnode)
+                                            &preftree->root.rb_root, rbnode) {
+               free_inode_elem_list(ref->inode_list);
                free_pref(ref);
+       }
 
        preftree->root = RB_ROOT_CACHED;
        preftree->count = 0;
@@ -648,6 +650,18 @@ unode_aux_to_inode_list(struct ulist_node *node)
        return (struct extent_inode_elem *)(uintptr_t)node->aux;
 }
 
+static void free_leaf_list(struct ulist *ulist)
+{
+       struct ulist_node *node;
+       struct ulist_iterator uiter;
+
+       ULIST_ITER_INIT(&uiter);
+       while ((node = ulist_next(ulist, &uiter)))
+               free_inode_elem_list(unode_aux_to_inode_list(node));
+
+       ulist_free(ulist);
+}
+
 /*
  * We maintain three separate rbtrees: one for direct refs, one for
  * indirect refs which have a key, and one for indirect refs which do not
@@ -762,7 +776,11 @@ static int resolve_indirect_refs(struct btrfs_fs_info *fs_info,
                cond_resched();
        }
 out:
-       ulist_free(parents);
+       /*
+        * We may have inode lists attached to refs in the parents ulist, so we
+        * must free them before freeing the ulist and its refs.
+        */
+       free_leaf_list(parents);
        return ret;
 }
 
@@ -1368,6 +1386,12 @@ again:
                                if (ret < 0)
                                        goto out;
                                ref->inode_list = eie;
+                               /*
+                                * We transferred the list ownership to the ref,
+                                * so set to NULL to avoid a double free in case
+                                * an error happens after this.
+                                */
+                               eie = NULL;
                        }
                        ret = ulist_add_merge_ptr(refs, ref->parent,
                                                  ref->inode_list,
@@ -1393,6 +1417,14 @@ again:
                                eie->next = ref->inode_list;
                        }
                        eie = NULL;
+                       /*
+                        * We have transferred the inode list ownership from
+                        * this ref to the ref we added to the 'refs' ulist.
+                        * So set this ref's inode list to NULL to avoid
+                        * use-after-free when our caller uses it or double
+                        * frees in case an error happens before we return.
+                        */
+                       ref->inode_list = NULL;
                }
                cond_resched();
        }
@@ -1409,24 +1441,6 @@ out:
        return ret;
 }
 
-static void free_leaf_list(struct ulist *blocks)
-{
-       struct ulist_node *node = NULL;
-       struct extent_inode_elem *eie;
-       struct ulist_iterator uiter;
-
-       ULIST_ITER_INIT(&uiter);
-       while ((node = ulist_next(blocks, &uiter))) {
-               if (!node->aux)
-                       continue;
-               eie = unode_aux_to_inode_list(node);
-               free_inode_elem_list(eie);
-               node->aux = 0;
-       }
-
-       ulist_free(blocks);
-}
-
 /*
  * Finds all leafs with a reference to the specified combination of bytenr and
  * offset. key_list_head will point to a list of corresponding keys (caller must
index 727595e..f677b49 100644 (file)
@@ -3462,7 +3462,10 @@ ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
 ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
                             const struct btrfs_ioctl_encoded_io_args *encoded);
 
-ssize_t btrfs_dio_rw(struct kiocb *iocb, struct iov_iter *iter, size_t done_before);
+ssize_t btrfs_dio_read(struct kiocb *iocb, struct iov_iter *iter,
+                      size_t done_before);
+struct iomap_dio *btrfs_dio_write(struct kiocb *iocb, struct iov_iter *iter,
+                                 size_t done_before);
 
 extern const struct dentry_operations btrfs_dentry_operations;
 
index 176b432..d01631d 100644 (file)
@@ -1598,14 +1598,19 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
                                                write_bytes);
                        else
                                btrfs_check_nocow_unlock(BTRFS_I(inode));
+
+                       if (nowait && ret == -ENOSPC)
+                               ret = -EAGAIN;
                        break;
                }
 
                release_bytes = reserve_bytes;
 again:
                ret = balance_dirty_pages_ratelimited_flags(inode->i_mapping, bdp_flags);
-               if (ret)
+               if (ret) {
+                       btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes);
                        break;
+               }
 
                /*
                 * This is going to setup the pages array with the number of
@@ -1765,6 +1770,7 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
        loff_t endbyte;
        ssize_t err;
        unsigned int ilock_flags = 0;
+       struct iomap_dio *dio;
 
        if (iocb->ki_flags & IOCB_NOWAIT)
                ilock_flags |= BTRFS_ILOCK_TRY;
@@ -1825,11 +1831,22 @@ relock:
         * So here we disable page faults in the iov_iter and then retry if we
         * got -EFAULT, faulting in the pages before the retry.
         */
-again:
        from->nofault = true;
-       err = btrfs_dio_rw(iocb, from, written);
+       dio = btrfs_dio_write(iocb, from, written);
        from->nofault = false;
 
+       /*
+        * iomap_dio_complete() will call btrfs_sync_file() if we have a dsync
+        * iocb, and that needs to lock the inode. So unlock it before calling
+        * iomap_dio_complete() to avoid a deadlock.
+        */
+       btrfs_inode_unlock(inode, ilock_flags);
+
+       if (IS_ERR_OR_NULL(dio))
+               err = PTR_ERR_OR_ZERO(dio);
+       else
+               err = iomap_dio_complete(dio);
+
        /* No increment (+=) because iomap returns a cumulative value. */
        if (err > 0)
                written = err;
@@ -1855,12 +1872,10 @@ again:
                } else {
                        fault_in_iov_iter_readable(from, left);
                        prev_left = left;
-                       goto again;
+                       goto relock;
                }
        }
 
-       btrfs_inode_unlock(inode, ilock_flags);
-
        /*
         * If 'err' is -ENOTBLK or we have not written all data, then it means
         * we must fallback to buffered IO.
@@ -4035,7 +4050,7 @@ again:
         */
        pagefault_disable();
        to->nofault = true;
-       ret = btrfs_dio_rw(iocb, to, read);
+       ret = btrfs_dio_read(iocb, to, read);
        to->nofault = false;
        pagefault_enable();
 
index b0807c5..0e516ae 100644 (file)
@@ -7980,7 +7980,7 @@ static void btrfs_submit_direct(const struct iomap_iter *iter,
                 */
                status = BLK_STS_RESOURCE;
                dip->csums = kcalloc(nr_sectors, fs_info->csum_size, GFP_NOFS);
-               if (!dip)
+               if (!dip->csums)
                        goto out_err;
 
                status = btrfs_lookup_bio_sums(inode, dio_bio, dip->csums);
@@ -8078,13 +8078,21 @@ static const struct iomap_dio_ops btrfs_dio_ops = {
        .bio_set                = &btrfs_dio_bioset,
 };
 
-ssize_t btrfs_dio_rw(struct kiocb *iocb, struct iov_iter *iter, size_t done_before)
+ssize_t btrfs_dio_read(struct kiocb *iocb, struct iov_iter *iter, size_t done_before)
 {
        struct btrfs_dio_data data;
 
        return iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
-                           IOMAP_DIO_PARTIAL | IOMAP_DIO_NOSYNC,
-                           &data, done_before);
+                           IOMAP_DIO_PARTIAL, &data, done_before);
+}
+
+struct iomap_dio *btrfs_dio_write(struct kiocb *iocb, struct iov_iter *iter,
+                                 size_t done_before)
+{
+       struct btrfs_dio_data data;
+
+       return __iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
+                           IOMAP_DIO_PARTIAL, &data, done_before);
 }
 
 static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
index eee1e44..63676ea 100644 (file)
@@ -225,20 +225,20 @@ static int test_no_shared_qgroup(struct btrfs_root *root,
         */
        ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
        if (ret) {
-               ulist_free(old_roots);
                test_err("couldn't find old roots: %d", ret);
                return ret;
        }
 
        ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
                                BTRFS_FS_TREE_OBJECTID);
-       if (ret)
+       if (ret) {
+               ulist_free(old_roots);
                return ret;
+       }
 
        ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
        if (ret) {
                ulist_free(old_roots);
-               ulist_free(new_roots);
                test_err("couldn't find old roots: %d", ret);
                return ret;
        }
@@ -250,29 +250,31 @@ static int test_no_shared_qgroup(struct btrfs_root *root,
                return ret;
        }
 
+       /* btrfs_qgroup_account_extent() always frees the ulists passed to it. */
+       old_roots = NULL;
+       new_roots = NULL;
+
        if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
                                nodesize, nodesize)) {
                test_err("qgroup counts didn't match expected values");
                return -EINVAL;
        }
-       old_roots = NULL;
-       new_roots = NULL;
 
        ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
        if (ret) {
-               ulist_free(old_roots);
                test_err("couldn't find old roots: %d", ret);
                return ret;
        }
 
        ret = remove_extent_item(root, nodesize, nodesize);
-       if (ret)
+       if (ret) {
+               ulist_free(old_roots);
                return -EINVAL;
+       }
 
        ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
        if (ret) {
                ulist_free(old_roots);
-               ulist_free(new_roots);
                test_err("couldn't find old roots: %d", ret);
                return ret;
        }
@@ -322,20 +324,20 @@ static int test_multiple_refs(struct btrfs_root *root,
 
        ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
        if (ret) {
-               ulist_free(old_roots);
                test_err("couldn't find old roots: %d", ret);
                return ret;
        }
 
        ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
                                BTRFS_FS_TREE_OBJECTID);
-       if (ret)
+       if (ret) {
+               ulist_free(old_roots);
                return ret;
+       }
 
        ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
        if (ret) {
                ulist_free(old_roots);
-               ulist_free(new_roots);
                test_err("couldn't find old roots: %d", ret);
                return ret;
        }
@@ -355,20 +357,20 @@ static int test_multiple_refs(struct btrfs_root *root,
 
        ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
        if (ret) {
-               ulist_free(old_roots);
                test_err("couldn't find old roots: %d", ret);
                return ret;
        }
 
        ret = add_tree_ref(root, nodesize, nodesize, 0,
                        BTRFS_FIRST_FREE_OBJECTID);
-       if (ret)
+       if (ret) {
+               ulist_free(old_roots);
                return ret;
+       }
 
        ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
        if (ret) {
                ulist_free(old_roots);
-               ulist_free(new_roots);
                test_err("couldn't find old roots: %d", ret);
                return ret;
        }
@@ -394,20 +396,20 @@ static int test_multiple_refs(struct btrfs_root *root,
 
        ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots, false);
        if (ret) {
-               ulist_free(old_roots);
                test_err("couldn't find old roots: %d", ret);
                return ret;
        }
 
        ret = remove_extent_ref(root, nodesize, nodesize, 0,
                                BTRFS_FIRST_FREE_OBJECTID);
-       if (ret)
+       if (ret) {
+               ulist_free(old_roots);
                return ret;
+       }
 
        ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
        if (ret) {
                ulist_free(old_roots);
-               ulist_free(new_roots);
                test_err("couldn't find old roots: %d", ret);
                return ret;
        }
index d0b9fec..fe22068 100644 (file)
@@ -1143,8 +1143,32 @@ const struct inode_operations cifs_file_inode_ops = {
        .fiemap = cifs_fiemap,
 };
 
+const char *cifs_get_link(struct dentry *dentry, struct inode *inode,
+                           struct delayed_call *done)
+{
+       char *target_path;
+
+       target_path = kmalloc(PATH_MAX, GFP_KERNEL);
+       if (!target_path)
+               return ERR_PTR(-ENOMEM);
+
+       spin_lock(&inode->i_lock);
+       if (likely(CIFS_I(inode)->symlink_target)) {
+               strscpy(target_path, CIFS_I(inode)->symlink_target, PATH_MAX);
+       } else {
+               kfree(target_path);
+               target_path = ERR_PTR(-EOPNOTSUPP);
+       }
+       spin_unlock(&inode->i_lock);
+
+       if (!IS_ERR(target_path))
+               set_delayed_call(done, kfree_link, target_path);
+
+       return target_path;
+}
+
 const struct inode_operations cifs_symlink_inode_ops = {
-       .get_link = simple_get_link,
+       .get_link = cifs_get_link,
        .permission = cifs_permission,
        .listxattr = cifs_listxattr,
 };
index 9bde08d..4e2ca3c 100644 (file)
@@ -215,11 +215,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
                kfree(cifs_i->symlink_target);
                cifs_i->symlink_target = fattr->cf_symlink_target;
                fattr->cf_symlink_target = NULL;
-
-               if (unlikely(!cifs_i->symlink_target))
-                       inode->i_link = ERR_PTR(-EOPNOTSUPP);
-               else
-                       inode->i_link = cifs_i->symlink_target;
        }
        spin_unlock(&inode->i_lock);
 
index da51ffd..3e68d82 100644 (file)
@@ -400,6 +400,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
 {
        struct smb_hdr *buf = (struct smb_hdr *)buffer;
        struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
+       struct TCP_Server_Info *pserver;
        struct cifs_ses *ses;
        struct cifs_tcon *tcon;
        struct cifsInodeInfo *pCifsInode;
@@ -464,9 +465,12 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
        if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
                return false;
 
+       /* If server is a channel, select the primary channel */
+       pserver = CIFS_SERVER_IS_CHAN(srv) ? srv->primary_server : srv;
+
        /* look up tcon based on tid & uid */
        spin_lock(&cifs_tcp_ses_lock);
-       list_for_each_entry(ses, &srv->smb_ses_list, smb_ses_list) {
+       list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
                list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
                        if (tcon->tid != buf->Tid)
                                continue;
index a387204..572293c 100644 (file)
@@ -135,6 +135,7 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len,
 int
 smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server)
 {
+       struct TCP_Server_Info *pserver;
        struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
        struct smb2_pdu *pdu = (struct smb2_pdu *)shdr;
        int hdr_size = sizeof(struct smb2_hdr);
@@ -143,6 +144,9 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server)
        __u32 calc_len; /* calculated length */
        __u64 mid;
 
+       /* If server is a channel, select the primary channel */
+       pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
        /*
         * Add function to do table lookup of StructureSize by command
         * ie Validate the wct via smb2_struct_sizes table above
@@ -155,7 +159,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server)
 
                /* decrypt frame now that it is completely read in */
                spin_lock(&cifs_tcp_ses_lock);
-               list_for_each_entry(iter, &server->smb_ses_list, smb_ses_list) {
+               list_for_each_entry(iter, &pserver->smb_ses_list, smb_ses_list) {
                        if (iter->Suid == le64_to_cpu(thdr->SessionId)) {
                                ses = iter;
                                break;
@@ -608,51 +612,52 @@ smb2_tcon_find_pending_open_lease(struct cifs_tcon *tcon,
 }
 
 static bool
-smb2_is_valid_lease_break(char *buffer)
+smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server)
 {
        struct smb2_lease_break *rsp = (struct smb2_lease_break *)buffer;
-       struct TCP_Server_Info *server;
+       struct TCP_Server_Info *pserver;
        struct cifs_ses *ses;
        struct cifs_tcon *tcon;
        struct cifs_pending_open *open;
 
        cifs_dbg(FYI, "Checking for lease break\n");
 
+       /* If server is a channel, select the primary channel */
+       pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
        /* look up tcon based on tid & uid */
        spin_lock(&cifs_tcp_ses_lock);
-       list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
-               list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
-                       list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
-                               spin_lock(&tcon->open_file_lock);
-                               cifs_stats_inc(
-                                   &tcon->stats.cifs_stats.num_oplock_brks);
-                               if (smb2_tcon_has_lease(tcon, rsp)) {
-                                       spin_unlock(&tcon->open_file_lock);
-                                       spin_unlock(&cifs_tcp_ses_lock);
-                                       return true;
-                               }
-                               open = smb2_tcon_find_pending_open_lease(tcon,
-                                                                        rsp);
-                               if (open) {
-                                       __u8 lease_key[SMB2_LEASE_KEY_SIZE];
-                                       struct tcon_link *tlink;
-
-                                       tlink = cifs_get_tlink(open->tlink);
-                                       memcpy(lease_key, open->lease_key,
-                                              SMB2_LEASE_KEY_SIZE);
-                                       spin_unlock(&tcon->open_file_lock);
-                                       spin_unlock(&cifs_tcp_ses_lock);
-                                       smb2_queue_pending_open_break(tlink,
-                                                                     lease_key,
-                                                                     rsp->NewLeaseState);
-                                       return true;
-                               }
+       list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+               list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+                       spin_lock(&tcon->open_file_lock);
+                       cifs_stats_inc(
+                                      &tcon->stats.cifs_stats.num_oplock_brks);
+                       if (smb2_tcon_has_lease(tcon, rsp)) {
                                spin_unlock(&tcon->open_file_lock);
+                               spin_unlock(&cifs_tcp_ses_lock);
+                               return true;
+                       }
+                       open = smb2_tcon_find_pending_open_lease(tcon,
+                                                                rsp);
+                       if (open) {
+                               __u8 lease_key[SMB2_LEASE_KEY_SIZE];
+                               struct tcon_link *tlink;
+
+                               tlink = cifs_get_tlink(open->tlink);
+                               memcpy(lease_key, open->lease_key,
+                                      SMB2_LEASE_KEY_SIZE);
+                               spin_unlock(&tcon->open_file_lock);
+                               spin_unlock(&cifs_tcp_ses_lock);
+                               smb2_queue_pending_open_break(tlink,
+                                                             lease_key,
+                                                             rsp->NewLeaseState);
+                               return true;
+                       }
+                       spin_unlock(&tcon->open_file_lock);
 
-                               if (cached_dir_lease_break(tcon, rsp->LeaseKey)) {
-                                       spin_unlock(&cifs_tcp_ses_lock);
-                                       return true;
-                               }
+                       if (cached_dir_lease_break(tcon, rsp->LeaseKey)) {
+                               spin_unlock(&cifs_tcp_ses_lock);
+                               return true;
                        }
                }
        }
@@ -671,6 +676,7 @@ bool
 smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
 {
        struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
+       struct TCP_Server_Info *pserver;
        struct cifs_ses *ses;
        struct cifs_tcon *tcon;
        struct cifsInodeInfo *cinode;
@@ -684,16 +690,19 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
        if (rsp->StructureSize !=
                                smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
                if (le16_to_cpu(rsp->StructureSize) == 44)
-                       return smb2_is_valid_lease_break(buffer);
+                       return smb2_is_valid_lease_break(buffer, server);
                else
                        return false;
        }
 
        cifs_dbg(FYI, "oplock level 0x%x\n", rsp->OplockLevel);
 
+       /* If server is a channel, select the primary channel */
+       pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
        /* look up tcon based on tid & uid */
        spin_lock(&cifs_tcp_ses_lock);
-       list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+       list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
                list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
 
                        spin_lock(&tcon->open_file_lock);
index 4f53fa0..880cd49 100644 (file)
@@ -2302,14 +2302,18 @@ static void
 smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
 {
        struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
+       struct TCP_Server_Info *pserver;
        struct cifs_ses *ses;
        struct cifs_tcon *tcon;
 
        if (shdr->Status != STATUS_NETWORK_NAME_DELETED)
                return;
 
+       /* If server is a channel, select the primary channel */
+       pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
        spin_lock(&cifs_tcp_ses_lock);
-       list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+       list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
                list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
                        if (tcon->tid == le32_to_cpu(shdr->Id.SyncId.TreeId)) {
                                spin_lock(&tcon->tc_lock);
@@ -4264,21 +4268,23 @@ init_sg(int num_rqst, struct smb_rqst *rqst, u8 *sign)
 static int
 smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
 {
+       struct TCP_Server_Info *pserver;
        struct cifs_ses *ses;
        u8 *ses_enc_key;
 
+       /* If server is a channel, select the primary channel */
+       pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
        spin_lock(&cifs_tcp_ses_lock);
-       list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
-               list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
-                       if (ses->Suid == ses_id) {
-                               spin_lock(&ses->ses_lock);
-                               ses_enc_key = enc ? ses->smb3encryptionkey :
-                                       ses->smb3decryptionkey;
-                               memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
-                               spin_unlock(&ses->ses_lock);
-                               spin_unlock(&cifs_tcp_ses_lock);
-                               return 0;
-                       }
+       list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+               if (ses->Suid == ses_id) {
+                       spin_lock(&ses->ses_lock);
+                       ses_enc_key = enc ? ses->smb3encryptionkey :
+                               ses->smb3decryptionkey;
+                       memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
+                       spin_unlock(&ses->ses_lock);
+                       spin_unlock(&cifs_tcp_ses_lock);
+                       return 0;
                }
        }
        spin_unlock(&cifs_tcp_ses_lock);
index 8e3f26e..381babc 100644 (file)
@@ -77,18 +77,19 @@ static
 int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
 {
        struct cifs_chan *chan;
+       struct TCP_Server_Info *pserver;
        struct cifs_ses *ses = NULL;
-       struct TCP_Server_Info *it = NULL;
        int i;
        int rc = 0;
 
        spin_lock(&cifs_tcp_ses_lock);
 
-       list_for_each_entry(it, &cifs_tcp_ses_list, tcp_ses_list) {
-               list_for_each_entry(ses, &it->smb_ses_list, smb_ses_list) {
-                       if (ses->Suid == ses_id)
-                               goto found;
-               }
+       /* If server is a channel, select the primary channel */
+       pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+       list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+               if (ses->Suid == ses_id)
+                       goto found;
        }
        cifs_server_dbg(VFS, "%s: Could not find session 0x%llx\n",
                        __func__, ses_id);
@@ -136,9 +137,13 @@ out:
 static struct cifs_ses *
 smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
 {
+       struct TCP_Server_Info *pserver;
        struct cifs_ses *ses;
 
-       list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+       /* If server is a channel, select the primary channel */
+       pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+       list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
                if (ses->Suid != ses_id)
                        continue;
                ++ses->ses_count;
index ef05bfa..0f6d0a8 100644 (file)
@@ -1521,6 +1521,7 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl,
        struct ext4_iloc iloc;
        int inode_len, ino, ret, tag = tl->fc_tag;
        struct ext4_extent_header *eh;
+       size_t off_gen = offsetof(struct ext4_inode, i_generation);
 
        memcpy(&fc_inode, val, sizeof(fc_inode));
 
@@ -1548,8 +1549,8 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl,
        raw_inode = ext4_raw_inode(&iloc);
 
        memcpy(raw_inode, raw_fc_inode, offsetof(struct ext4_inode, i_block));
-       memcpy(&raw_inode->i_generation, &raw_fc_inode->i_generation,
-               inode_len - offsetof(struct ext4_inode, i_generation));
+       memcpy((u8 *)raw_inode + off_gen, (u8 *)raw_fc_inode + off_gen,
+              inode_len - off_gen);
        if (le32_to_cpu(raw_inode->i_flags) & EXT4_EXTENTS_FL) {
                eh = (struct ext4_extent_header *)(&raw_inode->i_block[0]);
                if (eh->eh_magic != EXT4_EXT_MAGIC) {
index ded5355..95dfea2 100644 (file)
@@ -145,9 +145,8 @@ static int ext4_update_backup_sb(struct super_block *sb,
        if (ext4_has_metadata_csum(sb) &&
            es->s_checksum != ext4_superblock_csum(sb, es)) {
                ext4_msg(sb, KERN_ERR, "Invalid checksum for backup "
-               "superblock %llu\n", sb_block);
+               "superblock %llu", sb_block);
                unlock_buffer(bh);
-               err = -EFSBADCRC;
                goto out_bh;
        }
        func(es, arg);
index 0a220ec..a19a966 100644 (file)
@@ -424,7 +424,8 @@ int ext4_ext_migrate(struct inode *inode)
         * already is extent-based, error out.
         */
        if (!ext4_has_feature_extents(inode->i_sb) ||
-           (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
+           ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) ||
+           ext4_has_inline_data(inode))
                return -EINVAL;
 
        if (S_ISLNK(inode->i_mode) && inode->i_blocks == 0)
index d5daaf4..c08c0ab 100644 (file)
@@ -2259,8 +2259,16 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
        memset(de, 0, len); /* wipe old data */
        de = (struct ext4_dir_entry_2 *) data2;
        top = data2 + len;
-       while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top)
+       while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top) {
+               if (ext4_check_dir_entry(dir, NULL, de, bh2, data2, len,
+                                        (data2 + (blocksize - csum_size) -
+                                         (char *) de))) {
+                       brelse(bh2);
+                       brelse(bh);
+                       return -EFSCORRUPTED;
+               }
                de = de2;
+       }
        de->rec_len = ext4_rec_len_to_disk(data2 + (blocksize - csum_size) -
                                           (char *) de, blocksize);
 
index 6dfe9cc..46b87ff 100644 (file)
@@ -1158,6 +1158,7 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
        while (group < sbi->s_groups_count) {
                struct buffer_head *bh;
                ext4_fsblk_t backup_block;
+               struct ext4_super_block *es;
 
                /* Out of journal space, and can't get more - abort - so sad */
                err = ext4_resize_ensure_credits_batch(handle, 1);
@@ -1186,6 +1187,10 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
                memcpy(bh->b_data, data, size);
                if (rest)
                        memset(bh->b_data + size, 0, rest);
+               es = (struct ext4_super_block *) bh->b_data;
+               es->s_block_group_nr = cpu_to_le16(group);
+               if (ext4_has_metadata_csum(sb))
+                       es->s_checksum = ext4_superblock_csum(sb, es);
                set_buffer_uptodate(bh);
                unlock_buffer(bh);
                err = ext4_handle_dirty_metadata(handle, NULL, bh);
index 7950904..7cdd213 100644 (file)
@@ -4881,7 +4881,7 @@ out:
        flush_work(&sbi->s_error_work);
        jbd2_journal_destroy(sbi->s_journal);
        sbi->s_journal = NULL;
-       return err;
+       return -EINVAL;
 }
 
 static int ext4_journal_data_mode_check(struct super_block *sb)
index 1a3afd4..71bfb66 100644 (file)
@@ -3001,6 +3001,10 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
                        goto out;
        }
 
+       err = file_modified(file);
+       if (err)
+               goto out;
+
        if (!(mode & FALLOC_FL_KEEP_SIZE))
                set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
 
index b4e5657..e8deaac 100644 (file)
@@ -77,8 +77,10 @@ static void fuse_add_dirent_to_cache(struct file *file,
                goto unlock;
 
        addr = kmap_local_page(page);
-       if (!offset)
+       if (!offset) {
                clear_page(addr);
+               SetPageUptodate(page);
+       }
        memcpy(addr + offset, dirent, reclen);
        kunmap_local(addr);
        fi->rdc.size = (index << PAGE_SHIFT) + offset + reclen;
@@ -516,6 +518,12 @@ retry_locked:
 
        page = find_get_page_flags(file->f_mapping, index,
                                   FGP_ACCESSED | FGP_LOCK);
+       /* Page gone missing, then re-added to cache, but not initialized? */
+       if (page && !PageUptodate(page)) {
+               unlock_page(page);
+               put_page(page);
+               page = NULL;
+       }
        spin_lock(&fi->rdc.lock);
        if (!page) {
                /*
index 517a138..191b22b 100644 (file)
@@ -133,6 +133,21 @@ xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)
        return true;
 }
 
+static inline bool
+xfs_verify_agbext(
+       struct xfs_perag        *pag,
+       xfs_agblock_t           agbno,
+       xfs_agblock_t           len)
+{
+       if (agbno + len <= agbno)
+               return false;
+
+       if (!xfs_verify_agbno(pag, agbno))
+               return false;
+
+       return xfs_verify_agbno(pag, agbno + len - 1);
+}
+
 /*
  * Verify that an AG inode number pointer neither points outside the AG
  * nor points at static metadata.
index 6261599..de79f5d 100644 (file)
@@ -263,11 +263,7 @@ xfs_alloc_get_rec(
                goto out_bad_rec;
 
        /* check for valid extent range, including overflow */
-       if (!xfs_verify_agbno(pag, *bno))
-               goto out_bad_rec;
-       if (*bno > *bno + *len)
-               goto out_bad_rec;
-       if (!xfs_verify_agbno(pag, *bno + *len - 1))
+       if (!xfs_verify_agbext(pag, *bno, *len))
                goto out_bad_rec;
 
        return 0;
index d9b6630..cb9e950 100644 (file)
@@ -146,6 +146,8 @@ xfs_dir3_leaf_check_int(
        xfs_dir2_leaf_tail_t            *ltp;
        int                             stale;
        int                             i;
+       bool                            isleaf1 = (hdr->magic == XFS_DIR2_LEAF1_MAGIC ||
+                                                  hdr->magic == XFS_DIR3_LEAF1_MAGIC);
 
        ltp = xfs_dir2_leaf_tail_p(geo, leaf);
 
@@ -158,8 +160,7 @@ xfs_dir3_leaf_check_int(
                return __this_address;
 
        /* Leaves and bests don't overlap in leaf format. */
-       if ((hdr->magic == XFS_DIR2_LEAF1_MAGIC ||
-            hdr->magic == XFS_DIR3_LEAF1_MAGIC) &&
+       if (isleaf1 &&
            (char *)&hdr->ents[hdr->count] > (char *)xfs_dir2_leaf_bests_p(ltp))
                return __this_address;
 
@@ -175,6 +176,10 @@ xfs_dir3_leaf_check_int(
                }
                if (hdr->ents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
                        stale++;
+               if (isleaf1 && xfs_dir2_dataptr_to_db(geo,
+                               be32_to_cpu(hdr->ents[i].address)) >=
+                               be32_to_cpu(ltp->bestcount))
+                       return __this_address;
        }
        if (hdr->stale != stale)
                return __this_address;
index b55bdfa..371dc07 100644 (file)
@@ -1564,20 +1564,6 @@ struct xfs_rmap_rec {
 #define RMAPBT_UNUSED_OFFSET_BITLEN    7
 #define RMAPBT_OFFSET_BITLEN           54
 
-#define XFS_RMAP_ATTR_FORK             (1 << 0)
-#define XFS_RMAP_BMBT_BLOCK            (1 << 1)
-#define XFS_RMAP_UNWRITTEN             (1 << 2)
-#define XFS_RMAP_KEY_FLAGS             (XFS_RMAP_ATTR_FORK | \
-                                        XFS_RMAP_BMBT_BLOCK)
-#define XFS_RMAP_REC_FLAGS             (XFS_RMAP_UNWRITTEN)
-struct xfs_rmap_irec {
-       xfs_agblock_t   rm_startblock;  /* extent start block */
-       xfs_extlen_t    rm_blockcount;  /* extent length */
-       uint64_t        rm_owner;       /* extent owner */
-       uint64_t        rm_offset;      /* offset within the owner */
-       unsigned int    rm_flags;       /* state flags */
-};
-
 /*
  * Key structure
  *
@@ -1626,7 +1612,7 @@ unsigned int xfs_refc_block(struct xfs_mount *mp);
  * on the startblock.  This speeds up mount time deletion of stale
  * staging extents because they're all at the right side of the tree.
  */
-#define XFS_REFC_COW_START             ((xfs_agblock_t)(1U << 31))
+#define XFS_REFC_COWFLAG               (1U << 31)
 #define REFCNTBT_COWFLAG_BITLEN                1
 #define REFCNTBT_AGBLOCK_BITLEN                31
 
@@ -1640,12 +1626,6 @@ struct xfs_refcount_key {
        __be32          rc_startblock;  /* starting block number */
 };
 
-struct xfs_refcount_irec {
-       xfs_agblock_t   rc_startblock;  /* starting block number */
-       xfs_extlen_t    rc_blockcount;  /* count of free blocks */
-       xfs_nlink_t     rc_refcount;    /* number of inodes linked here */
-};
-
 #define MAXREFCOUNT    ((xfs_nlink_t)~0U)
 #define MAXREFCEXTLEN  ((xfs_extlen_t)~0U)
 
index b351b9d..f13e080 100644 (file)
@@ -613,25 +613,49 @@ typedef struct xfs_efi_log_format {
        uint16_t                efi_size;       /* size of this item */
        uint32_t                efi_nextents;   /* # extents to free */
        uint64_t                efi_id;         /* efi identifier */
-       xfs_extent_t            efi_extents[1]; /* array of extents to free */
+       xfs_extent_t            efi_extents[];  /* array of extents to free */
 } xfs_efi_log_format_t;
 
+static inline size_t
+xfs_efi_log_format_sizeof(
+       unsigned int            nr)
+{
+       return sizeof(struct xfs_efi_log_format) +
+                       nr * sizeof(struct xfs_extent);
+}
+
 typedef struct xfs_efi_log_format_32 {
        uint16_t                efi_type;       /* efi log item type */
        uint16_t                efi_size;       /* size of this item */
        uint32_t                efi_nextents;   /* # extents to free */
        uint64_t                efi_id;         /* efi identifier */
-       xfs_extent_32_t         efi_extents[1]; /* array of extents to free */
+       xfs_extent_32_t         efi_extents[];  /* array of extents to free */
 } __attribute__((packed)) xfs_efi_log_format_32_t;
 
+static inline size_t
+xfs_efi_log_format32_sizeof(
+       unsigned int            nr)
+{
+       return sizeof(struct xfs_efi_log_format_32) +
+                       nr * sizeof(struct xfs_extent_32);
+}
+
 typedef struct xfs_efi_log_format_64 {
        uint16_t                efi_type;       /* efi log item type */
        uint16_t                efi_size;       /* size of this item */
        uint32_t                efi_nextents;   /* # extents to free */
        uint64_t                efi_id;         /* efi identifier */
-       xfs_extent_64_t         efi_extents[1]; /* array of extents to free */
+       xfs_extent_64_t         efi_extents[];  /* array of extents to free */
 } xfs_efi_log_format_64_t;
 
+static inline size_t
+xfs_efi_log_format64_sizeof(
+       unsigned int            nr)
+{
+       return sizeof(struct xfs_efi_log_format_64) +
+                       nr * sizeof(struct xfs_extent_64);
+}
+
 /*
  * This is the structure used to lay out an efd log item in the
  * log.  The efd_extents array is a variable size array whose
@@ -642,25 +666,49 @@ typedef struct xfs_efd_log_format {
        uint16_t                efd_size;       /* size of this item */
        uint32_t                efd_nextents;   /* # of extents freed */
        uint64_t                efd_efi_id;     /* id of corresponding efi */
-       xfs_extent_t            efd_extents[1]; /* array of extents freed */
+       xfs_extent_t            efd_extents[];  /* array of extents freed */
 } xfs_efd_log_format_t;
 
+static inline size_t
+xfs_efd_log_format_sizeof(
+       unsigned int            nr)
+{
+       return sizeof(struct xfs_efd_log_format) +
+                       nr * sizeof(struct xfs_extent);
+}
+
 typedef struct xfs_efd_log_format_32 {
        uint16_t                efd_type;       /* efd log item type */
        uint16_t                efd_size;       /* size of this item */
        uint32_t                efd_nextents;   /* # of extents freed */
        uint64_t                efd_efi_id;     /* id of corresponding efi */
-       xfs_extent_32_t         efd_extents[1]; /* array of extents freed */
+       xfs_extent_32_t         efd_extents[];  /* array of extents freed */
 } __attribute__((packed)) xfs_efd_log_format_32_t;
 
+static inline size_t
+xfs_efd_log_format32_sizeof(
+       unsigned int            nr)
+{
+       return sizeof(struct xfs_efd_log_format_32) +
+                       nr * sizeof(struct xfs_extent_32);
+}
+
 typedef struct xfs_efd_log_format_64 {
        uint16_t                efd_type;       /* efd log item type */
        uint16_t                efd_size;       /* size of this item */
        uint32_t                efd_nextents;   /* # of extents freed */
        uint64_t                efd_efi_id;     /* id of corresponding efi */
-       xfs_extent_64_t         efd_extents[1]; /* array of extents freed */
+       xfs_extent_64_t         efd_extents[];  /* array of extents freed */
 } xfs_efd_log_format_64_t;
 
+static inline size_t
+xfs_efd_log_format64_sizeof(
+       unsigned int            nr)
+{
+       return sizeof(struct xfs_efd_log_format_64) +
+                       nr * sizeof(struct xfs_extent_64);
+}
+
 /*
  * RUI/RUD (reverse mapping) log format definitions
  */
index 64b910c..3f34baf 100644 (file)
@@ -46,13 +46,16 @@ STATIC int __xfs_refcount_cow_free(struct xfs_btree_cur *rcur,
 int
 xfs_refcount_lookup_le(
        struct xfs_btree_cur    *cur,
+       enum xfs_refc_domain    domain,
        xfs_agblock_t           bno,
        int                     *stat)
 {
-       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno, bno,
+       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno,
+                       xfs_refcount_encode_startblock(bno, domain),
                        XFS_LOOKUP_LE);
        cur->bc_rec.rc.rc_startblock = bno;
        cur->bc_rec.rc.rc_blockcount = 0;
+       cur->bc_rec.rc.rc_domain = domain;
        return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
 }
 
@@ -63,13 +66,16 @@ xfs_refcount_lookup_le(
 int
 xfs_refcount_lookup_ge(
        struct xfs_btree_cur    *cur,
+       enum xfs_refc_domain    domain,
        xfs_agblock_t           bno,
        int                     *stat)
 {
-       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno, bno,
+       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno,
+                       xfs_refcount_encode_startblock(bno, domain),
                        XFS_LOOKUP_GE);
        cur->bc_rec.rc.rc_startblock = bno;
        cur->bc_rec.rc.rc_blockcount = 0;
+       cur->bc_rec.rc.rc_domain = domain;
        return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat);
 }
 
@@ -80,13 +86,16 @@ xfs_refcount_lookup_ge(
 int
 xfs_refcount_lookup_eq(
        struct xfs_btree_cur    *cur,
+       enum xfs_refc_domain    domain,
        xfs_agblock_t           bno,
        int                     *stat)
 {
-       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno, bno,
+       trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.pag->pag_agno,
+                       xfs_refcount_encode_startblock(bno, domain),
                        XFS_LOOKUP_LE);
        cur->bc_rec.rc.rc_startblock = bno;
        cur->bc_rec.rc.rc_blockcount = 0;
+       cur->bc_rec.rc.rc_domain = domain;
        return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
 }
 
@@ -96,7 +105,17 @@ xfs_refcount_btrec_to_irec(
        const union xfs_btree_rec       *rec,
        struct xfs_refcount_irec        *irec)
 {
-       irec->rc_startblock = be32_to_cpu(rec->refc.rc_startblock);
+       uint32_t                        start;
+
+       start = be32_to_cpu(rec->refc.rc_startblock);
+       if (start & XFS_REFC_COWFLAG) {
+               start &= ~XFS_REFC_COWFLAG;
+               irec->rc_domain = XFS_REFC_DOMAIN_COW;
+       } else {
+               irec->rc_domain = XFS_REFC_DOMAIN_SHARED;
+       }
+
+       irec->rc_startblock = start;
        irec->rc_blockcount = be32_to_cpu(rec->refc.rc_blockcount);
        irec->rc_refcount = be32_to_cpu(rec->refc.rc_refcount);
 }
@@ -114,7 +133,6 @@ xfs_refcount_get_rec(
        struct xfs_perag                *pag = cur->bc_ag.pag;
        union xfs_btree_rec             *rec;
        int                             error;
-       xfs_agblock_t                   realstart;
 
        error = xfs_btree_get_rec(cur, &rec, stat);
        if (error || !*stat)
@@ -124,22 +142,11 @@ xfs_refcount_get_rec(
        if (irec->rc_blockcount == 0 || irec->rc_blockcount > MAXREFCEXTLEN)
                goto out_bad_rec;
 
-       /* handle special COW-staging state */
-       realstart = irec->rc_startblock;
-       if (realstart & XFS_REFC_COW_START) {
-               if (irec->rc_refcount != 1)
-                       goto out_bad_rec;
-               realstart &= ~XFS_REFC_COW_START;
-       } else if (irec->rc_refcount < 2) {
+       if (!xfs_refcount_check_domain(irec))
                goto out_bad_rec;
-       }
 
        /* check for valid extent range, including overflow */
-       if (!xfs_verify_agbno(pag, realstart))
-               goto out_bad_rec;
-       if (realstart > realstart + irec->rc_blockcount)
-               goto out_bad_rec;
-       if (!xfs_verify_agbno(pag, realstart + irec->rc_blockcount - 1))
+       if (!xfs_verify_agbext(pag, irec->rc_startblock, irec->rc_blockcount))
                goto out_bad_rec;
 
        if (irec->rc_refcount == 0 || irec->rc_refcount > MAXREFCOUNT)
@@ -169,12 +176,17 @@ xfs_refcount_update(
        struct xfs_refcount_irec        *irec)
 {
        union xfs_btree_rec     rec;
+       uint32_t                start;
        int                     error;
 
        trace_xfs_refcount_update(cur->bc_mp, cur->bc_ag.pag->pag_agno, irec);
-       rec.refc.rc_startblock = cpu_to_be32(irec->rc_startblock);
+
+       start = xfs_refcount_encode_startblock(irec->rc_startblock,
+                       irec->rc_domain);
+       rec.refc.rc_startblock = cpu_to_be32(start);
        rec.refc.rc_blockcount = cpu_to_be32(irec->rc_blockcount);
        rec.refc.rc_refcount = cpu_to_be32(irec->rc_refcount);
+
        error = xfs_btree_update(cur, &rec);
        if (error)
                trace_xfs_refcount_update_error(cur->bc_mp,
@@ -196,9 +208,12 @@ xfs_refcount_insert(
        int                             error;
 
        trace_xfs_refcount_insert(cur->bc_mp, cur->bc_ag.pag->pag_agno, irec);
+
        cur->bc_rec.rc.rc_startblock = irec->rc_startblock;
        cur->bc_rec.rc.rc_blockcount = irec->rc_blockcount;
        cur->bc_rec.rc.rc_refcount = irec->rc_refcount;
+       cur->bc_rec.rc.rc_domain = irec->rc_domain;
+
        error = xfs_btree_insert(cur, i);
        if (error)
                goto out_error;
@@ -244,7 +259,8 @@ xfs_refcount_delete(
        }
        if (error)
                goto out_error;
-       error = xfs_refcount_lookup_ge(cur, irec.rc_startblock, &found_rec);
+       error = xfs_refcount_lookup_ge(cur, irec.rc_domain, irec.rc_startblock,
+                       &found_rec);
 out_error:
        if (error)
                trace_xfs_refcount_delete_error(cur->bc_mp,
@@ -343,6 +359,7 @@ xfs_refc_next(
 STATIC int
 xfs_refcount_split_extent(
        struct xfs_btree_cur            *cur,
+       enum xfs_refc_domain            domain,
        xfs_agblock_t                   agbno,
        bool                            *shape_changed)
 {
@@ -351,7 +368,7 @@ xfs_refcount_split_extent(
        int                             error;
 
        *shape_changed = false;
-       error = xfs_refcount_lookup_le(cur, agbno, &found_rec);
+       error = xfs_refcount_lookup_le(cur, domain, agbno, &found_rec);
        if (error)
                goto out_error;
        if (!found_rec)
@@ -364,6 +381,8 @@ xfs_refcount_split_extent(
                error = -EFSCORRUPTED;
                goto out_error;
        }
+       if (rcext.rc_domain != domain)
+               return 0;
        if (rcext.rc_startblock == agbno || xfs_refc_next(&rcext) <= agbno)
                return 0;
 
@@ -415,6 +434,9 @@ xfs_refcount_merge_center_extents(
        trace_xfs_refcount_merge_center_extents(cur->bc_mp,
                        cur->bc_ag.pag->pag_agno, left, center, right);
 
+       ASSERT(left->rc_domain == center->rc_domain);
+       ASSERT(right->rc_domain == center->rc_domain);
+
        /*
         * Make sure the center and right extents are not in the btree.
         * If the center extent was synthesized, the first delete call
@@ -423,8 +445,8 @@ xfs_refcount_merge_center_extents(
         * call removes the center and the second one removes the right
         * extent.
         */
-       error = xfs_refcount_lookup_ge(cur, center->rc_startblock,
-                       &found_rec);
+       error = xfs_refcount_lookup_ge(cur, center->rc_domain,
+                       center->rc_startblock, &found_rec);
        if (error)
                goto out_error;
        if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
@@ -451,8 +473,8 @@ xfs_refcount_merge_center_extents(
        }
 
        /* Enlarge the left extent. */
-       error = xfs_refcount_lookup_le(cur, left->rc_startblock,
-                       &found_rec);
+       error = xfs_refcount_lookup_le(cur, left->rc_domain,
+                       left->rc_startblock, &found_rec);
        if (error)
                goto out_error;
        if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
@@ -491,10 +513,12 @@ xfs_refcount_merge_left_extent(
        trace_xfs_refcount_merge_left_extent(cur->bc_mp,
                        cur->bc_ag.pag->pag_agno, left, cleft);
 
+       ASSERT(left->rc_domain == cleft->rc_domain);
+
        /* If the extent at agbno (cleft) wasn't synthesized, remove it. */
        if (cleft->rc_refcount > 1) {
-               error = xfs_refcount_lookup_le(cur, cleft->rc_startblock,
-                               &found_rec);
+               error = xfs_refcount_lookup_le(cur, cleft->rc_domain,
+                               cleft->rc_startblock, &found_rec);
                if (error)
                        goto out_error;
                if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
@@ -512,8 +536,8 @@ xfs_refcount_merge_left_extent(
        }
 
        /* Enlarge the left extent. */
-       error = xfs_refcount_lookup_le(cur, left->rc_startblock,
-                       &found_rec);
+       error = xfs_refcount_lookup_le(cur, left->rc_domain,
+                       left->rc_startblock, &found_rec);
        if (error)
                goto out_error;
        if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
@@ -552,13 +576,15 @@ xfs_refcount_merge_right_extent(
        trace_xfs_refcount_merge_right_extent(cur->bc_mp,
                        cur->bc_ag.pag->pag_agno, cright, right);
 
+       ASSERT(right->rc_domain == cright->rc_domain);
+
        /*
         * If the extent ending at agbno+aglen (cright) wasn't synthesized,
         * remove it.
         */
        if (cright->rc_refcount > 1) {
-               error = xfs_refcount_lookup_le(cur, cright->rc_startblock,
-                       &found_rec);
+               error = xfs_refcount_lookup_le(cur, cright->rc_domain,
+                               cright->rc_startblock, &found_rec);
                if (error)
                        goto out_error;
                if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
@@ -576,8 +602,8 @@ xfs_refcount_merge_right_extent(
        }
 
        /* Enlarge the right extent. */
-       error = xfs_refcount_lookup_le(cur, right->rc_startblock,
-                       &found_rec);
+       error = xfs_refcount_lookup_le(cur, right->rc_domain,
+                       right->rc_startblock, &found_rec);
        if (error)
                goto out_error;
        if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
@@ -600,8 +626,6 @@ out_error:
        return error;
 }
 
-#define XFS_FIND_RCEXT_SHARED  1
-#define XFS_FIND_RCEXT_COW     2
 /*
  * Find the left extent and the one after it (cleft).  This function assumes
  * that we've already split any extent crossing agbno.
@@ -611,16 +635,16 @@ xfs_refcount_find_left_extents(
        struct xfs_btree_cur            *cur,
        struct xfs_refcount_irec        *left,
        struct xfs_refcount_irec        *cleft,
+       enum xfs_refc_domain            domain,
        xfs_agblock_t                   agbno,
-       xfs_extlen_t                    aglen,
-       int                             flags)
+       xfs_extlen_t                    aglen)
 {
        struct xfs_refcount_irec        tmp;
        int                             error;
        int                             found_rec;
 
        left->rc_startblock = cleft->rc_startblock = NULLAGBLOCK;
-       error = xfs_refcount_lookup_le(cur, agbno - 1, &found_rec);
+       error = xfs_refcount_lookup_le(cur, domain, agbno - 1, &found_rec);
        if (error)
                goto out_error;
        if (!found_rec)
@@ -634,11 +658,9 @@ xfs_refcount_find_left_extents(
                goto out_error;
        }
 
-       if (xfs_refc_next(&tmp) != agbno)
-               return 0;
-       if ((flags & XFS_FIND_RCEXT_SHARED) && tmp.rc_refcount < 2)
+       if (tmp.rc_domain != domain)
                return 0;
-       if ((flags & XFS_FIND_RCEXT_COW) && tmp.rc_refcount > 1)
+       if (xfs_refc_next(&tmp) != agbno)
                return 0;
        /* We have a left extent; retrieve (or invent) the next right one */
        *left = tmp;
@@ -655,6 +677,9 @@ xfs_refcount_find_left_extents(
                        goto out_error;
                }
 
+               if (tmp.rc_domain != domain)
+                       goto not_found;
+
                /* if tmp starts at the end of our range, just use that */
                if (tmp.rc_startblock == agbno)
                        *cleft = tmp;
@@ -671,8 +696,10 @@ xfs_refcount_find_left_extents(
                        cleft->rc_blockcount = min(aglen,
                                        tmp.rc_startblock - agbno);
                        cleft->rc_refcount = 1;
+                       cleft->rc_domain = domain;
                }
        } else {
+not_found:
                /*
                 * No extents, so pretend that there's one covering the whole
                 * range.
@@ -680,6 +707,7 @@ xfs_refcount_find_left_extents(
                cleft->rc_startblock = agbno;
                cleft->rc_blockcount = aglen;
                cleft->rc_refcount = 1;
+               cleft->rc_domain = domain;
        }
        trace_xfs_refcount_find_left_extent(cur->bc_mp, cur->bc_ag.pag->pag_agno,
                        left, cleft, agbno);
@@ -700,16 +728,16 @@ xfs_refcount_find_right_extents(
        struct xfs_btree_cur            *cur,
        struct xfs_refcount_irec        *right,
        struct xfs_refcount_irec        *cright,
+       enum xfs_refc_domain            domain,
        xfs_agblock_t                   agbno,
-       xfs_extlen_t                    aglen,
-       int                             flags)
+       xfs_extlen_t                    aglen)
 {
        struct xfs_refcount_irec        tmp;
        int                             error;
        int                             found_rec;
 
        right->rc_startblock = cright->rc_startblock = NULLAGBLOCK;
-       error = xfs_refcount_lookup_ge(cur, agbno + aglen, &found_rec);
+       error = xfs_refcount_lookup_ge(cur, domain, agbno + aglen, &found_rec);
        if (error)
                goto out_error;
        if (!found_rec)
@@ -723,11 +751,9 @@ xfs_refcount_find_right_extents(
                goto out_error;
        }
 
-       if (tmp.rc_startblock != agbno + aglen)
-               return 0;
-       if ((flags & XFS_FIND_RCEXT_SHARED) && tmp.rc_refcount < 2)
+       if (tmp.rc_domain != domain)
                return 0;
-       if ((flags & XFS_FIND_RCEXT_COW) && tmp.rc_refcount > 1)
+       if (tmp.rc_startblock != agbno + aglen)
                return 0;
        /* We have a right extent; retrieve (or invent) the next left one */
        *right = tmp;
@@ -744,6 +770,9 @@ xfs_refcount_find_right_extents(
                        goto out_error;
                }
 
+               if (tmp.rc_domain != domain)
+                       goto not_found;
+
                /* if tmp ends at the end of our range, just use that */
                if (xfs_refc_next(&tmp) == agbno + aglen)
                        *cright = tmp;
@@ -760,8 +789,10 @@ xfs_refcount_find_right_extents(
                        cright->rc_blockcount = right->rc_startblock -
                                        cright->rc_startblock;
                        cright->rc_refcount = 1;
+                       cright->rc_domain = domain;
                }
        } else {
+not_found:
                /*
                 * No extents, so pretend that there's one covering the whole
                 * range.
@@ -769,6 +800,7 @@ xfs_refcount_find_right_extents(
                cright->rc_startblock = agbno;
                cright->rc_blockcount = aglen;
                cright->rc_refcount = 1;
+               cright->rc_domain = domain;
        }
        trace_xfs_refcount_find_right_extent(cur->bc_mp, cur->bc_ag.pag->pag_agno,
                        cright, right, agbno + aglen);
@@ -794,10 +826,10 @@ xfs_refc_valid(
 STATIC int
 xfs_refcount_merge_extents(
        struct xfs_btree_cur    *cur,
+       enum xfs_refc_domain    domain,
        xfs_agblock_t           *agbno,
        xfs_extlen_t            *aglen,
        enum xfs_refc_adjust_op adjust,
-       int                     flags,
        bool                    *shape_changed)
 {
        struct xfs_refcount_irec        left = {0}, cleft = {0};
@@ -812,12 +844,12 @@ xfs_refcount_merge_extents(
         * just below (agbno + aglen) [cright], and just above (agbno + aglen)
         * [right].
         */
-       error = xfs_refcount_find_left_extents(cur, &left, &cleft, *agbno,
-                       *aglen, flags);
+       error = xfs_refcount_find_left_extents(cur, &left, &cleft, domain,
+                       *agbno, *aglen);
        if (error)
                return error;
-       error = xfs_refcount_find_right_extents(cur, &right, &cright, *agbno,
-                       *aglen, flags);
+       error = xfs_refcount_find_right_extents(cur, &right, &cright, domain,
+                       *agbno, *aglen);
        if (error)
                return error;
 
@@ -870,7 +902,7 @@ xfs_refcount_merge_extents(
                                aglen);
        }
 
-       return error;
+       return 0;
 }
 
 /*
@@ -933,7 +965,8 @@ xfs_refcount_adjust_extents(
        if (*aglen == 0)
                return 0;
 
-       error = xfs_refcount_lookup_ge(cur, *agbno, &found_rec);
+       error = xfs_refcount_lookup_ge(cur, XFS_REFC_DOMAIN_SHARED, *agbno,
+                       &found_rec);
        if (error)
                goto out_error;
 
@@ -941,10 +974,11 @@ xfs_refcount_adjust_extents(
                error = xfs_refcount_get_rec(cur, &ext, &found_rec);
                if (error)
                        goto out_error;
-               if (!found_rec) {
+               if (!found_rec || ext.rc_domain != XFS_REFC_DOMAIN_SHARED) {
                        ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks;
                        ext.rc_blockcount = 0;
                        ext.rc_refcount = 0;
+                       ext.rc_domain = XFS_REFC_DOMAIN_SHARED;
                }
 
                /*
@@ -957,6 +991,8 @@ xfs_refcount_adjust_extents(
                        tmp.rc_blockcount = min(*aglen,
                                        ext.rc_startblock - *agbno);
                        tmp.rc_refcount = 1 + adj;
+                       tmp.rc_domain = XFS_REFC_DOMAIN_SHARED;
+
                        trace_xfs_refcount_modify_extent(cur->bc_mp,
                                        cur->bc_ag.pag->pag_agno, &tmp);
 
@@ -986,15 +1022,30 @@ xfs_refcount_adjust_extents(
                        (*agbno) += tmp.rc_blockcount;
                        (*aglen) -= tmp.rc_blockcount;
 
-                       error = xfs_refcount_lookup_ge(cur, *agbno,
+                       /* Stop if there's nothing left to modify */
+                       if (*aglen == 0 || !xfs_refcount_still_have_space(cur))
+                               break;
+
+                       /* Move the cursor to the start of ext. */
+                       error = xfs_refcount_lookup_ge(cur,
+                                       XFS_REFC_DOMAIN_SHARED, *agbno,
                                        &found_rec);
                        if (error)
                                goto out_error;
                }
 
-               /* Stop if there's nothing left to modify */
-               if (*aglen == 0 || !xfs_refcount_still_have_space(cur))
-                       break;
+               /*
+                * A previous step trimmed agbno/aglen such that the end of the
+                * range would not be in the middle of the record.  If this is
+                * no longer the case, something is seriously wrong with the
+                * btree.  Make sure we never feed the synthesized record into
+                * the processing loop below.
+                */
+               if (XFS_IS_CORRUPT(cur->bc_mp, ext.rc_blockcount == 0) ||
+                   XFS_IS_CORRUPT(cur->bc_mp, ext.rc_blockcount > *aglen)) {
+                       error = -EFSCORRUPTED;
+                       goto out_error;
+               }
 
                /*
                 * Adjust the reference count and either update the tree
@@ -1070,13 +1121,15 @@ xfs_refcount_adjust(
        /*
         * Ensure that no rcextents cross the boundary of the adjustment range.
         */
-       error = xfs_refcount_split_extent(cur, agbno, &shape_changed);
+       error = xfs_refcount_split_extent(cur, XFS_REFC_DOMAIN_SHARED,
+                       agbno, &shape_changed);
        if (error)
                goto out_error;
        if (shape_changed)
                shape_changes++;
 
-       error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed);
+       error = xfs_refcount_split_extent(cur, XFS_REFC_DOMAIN_SHARED,
+                       agbno + aglen, &shape_changed);
        if (error)
                goto out_error;
        if (shape_changed)
@@ -1085,8 +1138,8 @@ xfs_refcount_adjust(
        /*
         * Try to merge with the left or right extents of the range.
         */
-       error = xfs_refcount_merge_extents(cur, new_agbno, new_aglen, adj,
-                       XFS_FIND_RCEXT_SHARED, &shape_changed);
+       error = xfs_refcount_merge_extents(cur, XFS_REFC_DOMAIN_SHARED,
+                       new_agbno, new_aglen, adj, &shape_changed);
        if (error)
                goto out_error;
        if (shape_changed)
@@ -1125,6 +1178,32 @@ xfs_refcount_finish_one_cleanup(
 }
 
 /*
+ * Set up a continuation a deferred refcount operation by updating the intent.
+ * Checks to make sure we're not going to run off the end of the AG.
+ */
+static inline int
+xfs_refcount_continue_op(
+       struct xfs_btree_cur            *cur,
+       xfs_fsblock_t                   startblock,
+       xfs_agblock_t                   new_agbno,
+       xfs_extlen_t                    new_len,
+       xfs_fsblock_t                   *new_fsbno)
+{
+       struct xfs_mount                *mp = cur->bc_mp;
+       struct xfs_perag                *pag = cur->bc_ag.pag;
+
+       if (XFS_IS_CORRUPT(mp, !xfs_verify_agbext(pag, new_agbno, new_len)))
+               return -EFSCORRUPTED;
+
+       *new_fsbno = XFS_AGB_TO_FSB(mp, pag->pag_agno, new_agbno);
+
+       ASSERT(xfs_verify_fsbext(mp, *new_fsbno, new_len));
+       ASSERT(pag->pag_agno == XFS_FSB_TO_AGNO(mp, *new_fsbno));
+
+       return 0;
+}
+
+/*
  * Process one of the deferred refcount operations.  We pass back the
  * btree cursor to maintain our lock on the btree between calls.
  * This saves time and eliminates a buffer deadlock between the
@@ -1191,12 +1270,20 @@ xfs_refcount_finish_one(
        case XFS_REFCOUNT_INCREASE:
                error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
                                new_len, XFS_REFCOUNT_ADJUST_INCREASE);
-               *new_fsb = XFS_AGB_TO_FSB(mp, pag->pag_agno, new_agbno);
+               if (error)
+                       goto out_drop;
+               if (*new_len > 0)
+                       error = xfs_refcount_continue_op(rcur, startblock,
+                                       new_agbno, *new_len, new_fsb);
                break;
        case XFS_REFCOUNT_DECREASE:
                error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
                                new_len, XFS_REFCOUNT_ADJUST_DECREASE);
-               *new_fsb = XFS_AGB_TO_FSB(mp, pag->pag_agno, new_agbno);
+               if (error)
+                       goto out_drop;
+               if (*new_len > 0)
+                       error = xfs_refcount_continue_op(rcur, startblock,
+                                       new_agbno, *new_len, new_fsb);
                break;
        case XFS_REFCOUNT_ALLOC_COW:
                *new_fsb = startblock + blockcount;
@@ -1307,7 +1394,8 @@ xfs_refcount_find_shared(
        *flen = 0;
 
        /* Try to find a refcount extent that crosses the start */
-       error = xfs_refcount_lookup_le(cur, agbno, &have);
+       error = xfs_refcount_lookup_le(cur, XFS_REFC_DOMAIN_SHARED, agbno,
+                       &have);
        if (error)
                goto out_error;
        if (!have) {
@@ -1325,6 +1413,8 @@ xfs_refcount_find_shared(
                error = -EFSCORRUPTED;
                goto out_error;
        }
+       if (tmp.rc_domain != XFS_REFC_DOMAIN_SHARED)
+               goto done;
 
        /* If the extent ends before the start, look at the next one */
        if (tmp.rc_startblock + tmp.rc_blockcount <= agbno) {
@@ -1340,6 +1430,8 @@ xfs_refcount_find_shared(
                        error = -EFSCORRUPTED;
                        goto out_error;
                }
+               if (tmp.rc_domain != XFS_REFC_DOMAIN_SHARED)
+                       goto done;
        }
 
        /* If the extent starts after the range we want, bail out */
@@ -1371,7 +1463,8 @@ xfs_refcount_find_shared(
                        error = -EFSCORRUPTED;
                        goto out_error;
                }
-               if (tmp.rc_startblock >= agbno + aglen ||
+               if (tmp.rc_domain != XFS_REFC_DOMAIN_SHARED ||
+                   tmp.rc_startblock >= agbno + aglen ||
                    tmp.rc_startblock != *fbno + *flen)
                        break;
                *flen = min(*flen + tmp.rc_blockcount, agbno + aglen - *fbno);
@@ -1455,17 +1548,23 @@ xfs_refcount_adjust_cow_extents(
                return 0;
 
        /* Find any overlapping refcount records */
-       error = xfs_refcount_lookup_ge(cur, agbno, &found_rec);
+       error = xfs_refcount_lookup_ge(cur, XFS_REFC_DOMAIN_COW, agbno,
+                       &found_rec);
        if (error)
                goto out_error;
        error = xfs_refcount_get_rec(cur, &ext, &found_rec);
        if (error)
                goto out_error;
+       if (XFS_IS_CORRUPT(cur->bc_mp, found_rec &&
+                               ext.rc_domain != XFS_REFC_DOMAIN_COW)) {
+               error = -EFSCORRUPTED;
+               goto out_error;
+       }
        if (!found_rec) {
-               ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks +
-                               XFS_REFC_COW_START;
+               ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks;
                ext.rc_blockcount = 0;
                ext.rc_refcount = 0;
+               ext.rc_domain = XFS_REFC_DOMAIN_COW;
        }
 
        switch (adj) {
@@ -1480,6 +1579,8 @@ xfs_refcount_adjust_cow_extents(
                tmp.rc_startblock = agbno;
                tmp.rc_blockcount = aglen;
                tmp.rc_refcount = 1;
+               tmp.rc_domain = XFS_REFC_DOMAIN_COW;
+
                trace_xfs_refcount_modify_extent(cur->bc_mp,
                                cur->bc_ag.pag->pag_agno, &tmp);
 
@@ -1542,24 +1643,24 @@ xfs_refcount_adjust_cow(
        bool                    shape_changed;
        int                     error;
 
-       agbno += XFS_REFC_COW_START;
-
        /*
         * Ensure that no rcextents cross the boundary of the adjustment range.
         */
-       error = xfs_refcount_split_extent(cur, agbno, &shape_changed);
+       error = xfs_refcount_split_extent(cur, XFS_REFC_DOMAIN_COW,
+                       agbno, &shape_changed);
        if (error)
                goto out_error;
 
-       error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed);
+       error = xfs_refcount_split_extent(cur, XFS_REFC_DOMAIN_COW,
+                       agbno + aglen, &shape_changed);
        if (error)
                goto out_error;
 
        /*
         * Try to merge with the left or right extents of the range.
         */
-       error = xfs_refcount_merge_extents(cur, &agbno, &aglen, adj,
-                       XFS_FIND_RCEXT_COW, &shape_changed);
+       error = xfs_refcount_merge_extents(cur, XFS_REFC_DOMAIN_COW, &agbno,
+                       &aglen, adj, &shape_changed);
        if (error)
                goto out_error;
 
@@ -1666,10 +1767,18 @@ xfs_refcount_recover_extent(
                           be32_to_cpu(rec->refc.rc_refcount) != 1))
                return -EFSCORRUPTED;
 
-       rr = kmem_alloc(sizeof(struct xfs_refcount_recovery), 0);
+       rr = kmalloc(sizeof(struct xfs_refcount_recovery),
+                       GFP_KERNEL | __GFP_NOFAIL);
+       INIT_LIST_HEAD(&rr->rr_list);
        xfs_refcount_btrec_to_irec(rec, &rr->rr_rrec);
-       list_add_tail(&rr->rr_list, debris);
 
+       if (XFS_IS_CORRUPT(cur->bc_mp,
+                          rr->rr_rrec.rc_domain != XFS_REFC_DOMAIN_COW)) {
+               kfree(rr);
+               return -EFSCORRUPTED;
+       }
+
+       list_add_tail(&rr->rr_list, debris);
        return 0;
 }
 
@@ -1687,10 +1796,11 @@ xfs_refcount_recover_cow_leftovers(
        union xfs_btree_irec            low;
        union xfs_btree_irec            high;
        xfs_fsblock_t                   fsb;
-       xfs_agblock_t                   agbno;
        int                             error;
 
-       if (mp->m_sb.sb_agblocks >= XFS_REFC_COW_START)
+       /* reflink filesystems mustn't have AGs larger than 2^31-1 blocks */
+       BUILD_BUG_ON(XFS_MAX_CRC_AG_BLOCKS >= XFS_REFC_COWFLAG);
+       if (mp->m_sb.sb_agblocks > XFS_MAX_CRC_AG_BLOCKS)
                return -EOPNOTSUPP;
 
        INIT_LIST_HEAD(&debris);
@@ -1717,7 +1827,7 @@ xfs_refcount_recover_cow_leftovers(
        /* Find all the leftover CoW staging extents. */
        memset(&low, 0, sizeof(low));
        memset(&high, 0, sizeof(high));
-       low.rc.rc_startblock = XFS_REFC_COW_START;
+       low.rc.rc_domain = high.rc.rc_domain = XFS_REFC_DOMAIN_COW;
        high.rc.rc_startblock = -1U;
        error = xfs_btree_query_range(cur, &low, &high,
                        xfs_refcount_recover_extent, &debris);
@@ -1738,8 +1848,8 @@ xfs_refcount_recover_cow_leftovers(
                                &rr->rr_rrec);
 
                /* Free the orphan record */
-               agbno = rr->rr_rrec.rc_startblock - XFS_REFC_COW_START;
-               fsb = XFS_AGB_TO_FSB(mp, pag->pag_agno, agbno);
+               fsb = XFS_AGB_TO_FSB(mp, pag->pag_agno,
+                               rr->rr_rrec.rc_startblock);
                xfs_refcount_free_cow_extent(tp, fsb,
                                rr->rr_rrec.rc_blockcount);
 
@@ -1751,7 +1861,7 @@ xfs_refcount_recover_cow_leftovers(
                        goto out_free;
 
                list_del(&rr->rr_list);
-               kmem_free(rr);
+               kfree(rr);
        }
 
        return error;
@@ -1761,7 +1871,7 @@ out_free:
        /* Free the leftover list */
        list_for_each_entry_safe(rr, n, &debris, rr_list) {
                list_del(&rr->rr_list);
-               kmem_free(rr);
+               kfree(rr);
        }
        return error;
 }
@@ -1770,6 +1880,7 @@ out_free:
 int
 xfs_refcount_has_record(
        struct xfs_btree_cur    *cur,
+       enum xfs_refc_domain    domain,
        xfs_agblock_t           bno,
        xfs_extlen_t            len,
        bool                    *exists)
@@ -1781,6 +1892,7 @@ xfs_refcount_has_record(
        low.rc.rc_startblock = bno;
        memset(&high, 0xFF, sizeof(high));
        high.rc.rc_startblock = bno + len - 1;
+       low.rc.rc_domain = high.rc.rc_domain = domain;
 
        return xfs_btree_has_record(cur, &low, &high, exists);
 }
index e8b322d..452f305 100644 (file)
@@ -14,14 +14,33 @@ struct xfs_bmbt_irec;
 struct xfs_refcount_irec;
 
 extern int xfs_refcount_lookup_le(struct xfs_btree_cur *cur,
-               xfs_agblock_t bno, int *stat);
+               enum xfs_refc_domain domain, xfs_agblock_t bno, int *stat);
 extern int xfs_refcount_lookup_ge(struct xfs_btree_cur *cur,
-               xfs_agblock_t bno, int *stat);
+               enum xfs_refc_domain domain, xfs_agblock_t bno, int *stat);
 extern int xfs_refcount_lookup_eq(struct xfs_btree_cur *cur,
-               xfs_agblock_t bno, int *stat);
+               enum xfs_refc_domain domain, xfs_agblock_t bno, int *stat);
 extern int xfs_refcount_get_rec(struct xfs_btree_cur *cur,
                struct xfs_refcount_irec *irec, int *stat);
 
+static inline uint32_t
+xfs_refcount_encode_startblock(
+       xfs_agblock_t           startblock,
+       enum xfs_refc_domain    domain)
+{
+       uint32_t                start;
+
+       /*
+        * low level btree operations need to handle the generic btree range
+        * query functions (which set rc_domain == -1U), so we check that the
+        * domain is /not/ shared.
+        */
+       start = startblock & ~XFS_REFC_COWFLAG;
+       if (domain != XFS_REFC_DOMAIN_SHARED)
+               start |= XFS_REFC_COWFLAG;
+
+       return start;
+}
+
 enum xfs_refcount_intent_type {
        XFS_REFCOUNT_INCREASE = 1,
        XFS_REFCOUNT_DECREASE,
@@ -36,6 +55,18 @@ struct xfs_refcount_intent {
        xfs_fsblock_t                           ri_startblock;
 };
 
+/* Check that the refcount is appropriate for the record domain. */
+static inline bool
+xfs_refcount_check_domain(
+       const struct xfs_refcount_irec  *irec)
+{
+       if (irec->rc_domain == XFS_REFC_DOMAIN_COW && irec->rc_refcount != 1)
+               return false;
+       if (irec->rc_domain == XFS_REFC_DOMAIN_SHARED && irec->rc_refcount < 2)
+               return false;
+       return true;
+}
+
 void xfs_refcount_increase_extent(struct xfs_trans *tp,
                struct xfs_bmbt_irec *irec);
 void xfs_refcount_decrease_extent(struct xfs_trans *tp,
@@ -79,7 +110,8 @@ extern int xfs_refcount_recover_cow_leftovers(struct xfs_mount *mp,
 #define XFS_REFCOUNT_ITEM_OVERHEAD     32
 
 extern int xfs_refcount_has_record(struct xfs_btree_cur *cur,
-               xfs_agblock_t bno, xfs_extlen_t len, bool *exists);
+               enum xfs_refc_domain domain, xfs_agblock_t bno,
+               xfs_extlen_t len, bool *exists);
 union xfs_btree_rec;
 extern void xfs_refcount_btrec_to_irec(const union xfs_btree_rec *rec,
                struct xfs_refcount_irec *irec);
index 316c1ec..e1f7898 100644 (file)
@@ -13,6 +13,7 @@
 #include "xfs_btree.h"
 #include "xfs_btree_staging.h"
 #include "xfs_refcount_btree.h"
+#include "xfs_refcount.h"
 #include "xfs_alloc.h"
 #include "xfs_error.h"
 #include "xfs_trace.h"
@@ -160,7 +161,12 @@ xfs_refcountbt_init_rec_from_cur(
        struct xfs_btree_cur    *cur,
        union xfs_btree_rec     *rec)
 {
-       rec->refc.rc_startblock = cpu_to_be32(cur->bc_rec.rc.rc_startblock);
+       const struct xfs_refcount_irec *irec = &cur->bc_rec.rc;
+       uint32_t                start;
+
+       start = xfs_refcount_encode_startblock(irec->rc_startblock,
+                       irec->rc_domain);
+       rec->refc.rc_startblock = cpu_to_be32(start);
        rec->refc.rc_blockcount = cpu_to_be32(cur->bc_rec.rc.rc_blockcount);
        rec->refc.rc_refcount = cpu_to_be32(cur->bc_rec.rc.rc_refcount);
 }
@@ -182,10 +188,13 @@ xfs_refcountbt_key_diff(
        struct xfs_btree_cur            *cur,
        const union xfs_btree_key       *key)
 {
-       struct xfs_refcount_irec        *rec = &cur->bc_rec.rc;
        const struct xfs_refcount_key   *kp = &key->refc;
+       const struct xfs_refcount_irec  *irec = &cur->bc_rec.rc;
+       uint32_t                        start;
 
-       return (int64_t)be32_to_cpu(kp->rc_startblock) - rec->rc_startblock;
+       start = xfs_refcount_encode_startblock(irec->rc_startblock,
+                       irec->rc_domain);
+       return (int64_t)be32_to_cpu(kp->rc_startblock) - start;
 }
 
 STATIC int64_t
index 094dfc8..b56aca1 100644 (file)
@@ -235,13 +235,8 @@ xfs_rmap_get_rec(
                        goto out_bad_rec;
        } else {
                /* check for valid extent range, including overflow */
-               if (!xfs_verify_agbno(pag, irec->rm_startblock))
-                       goto out_bad_rec;
-               if (irec->rm_startblock >
-                               irec->rm_startblock + irec->rm_blockcount)
-                       goto out_bad_rec;
-               if (!xfs_verify_agbno(pag,
-                               irec->rm_startblock + irec->rm_blockcount - 1))
+               if (!xfs_verify_agbext(pag, irec->rm_startblock,
+                                           irec->rm_blockcount))
                        goto out_bad_rec;
        }
 
index 2c4ad6e..5b2f27c 100644 (file)
@@ -422,7 +422,7 @@ xfs_calc_itruncate_reservation_minlogsize(
 
 /*
  * In renaming a files we can modify:
- *    the four inodes involved: 4 * inode size
+ *    the five inodes involved: 5 * inode size
  *    the two directory btrees: 2 * (max depth + v2) * dir block size
  *    the two directory bmap btrees: 2 * max depth * block size
  * And the bmap_finish transaction can free dir and bmap blocks (two sets
@@ -437,7 +437,7 @@ xfs_calc_rename_reservation(
        struct xfs_mount        *mp)
 {
        return XFS_DQUOT_LOGRES(mp) +
-               max((xfs_calc_inode_res(mp, 4) +
+               max((xfs_calc_inode_res(mp, 5) +
                     xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
                                      XFS_FSB_TO_B(mp, 1))),
                    (xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
index a6b7d98..5ebdda7 100644 (file)
@@ -166,6 +166,36 @@ typedef struct xfs_bmbt_irec
        xfs_exntst_t    br_state;       /* extent state */
 } xfs_bmbt_irec_t;
 
+enum xfs_refc_domain {
+       XFS_REFC_DOMAIN_SHARED = 0,
+       XFS_REFC_DOMAIN_COW,
+};
+
+#define XFS_REFC_DOMAIN_STRINGS \
+       { XFS_REFC_DOMAIN_SHARED,       "shared" }, \
+       { XFS_REFC_DOMAIN_COW,          "cow" }
+
+struct xfs_refcount_irec {
+       xfs_agblock_t   rc_startblock;  /* starting block number */
+       xfs_extlen_t    rc_blockcount;  /* count of free blocks */
+       xfs_nlink_t     rc_refcount;    /* number of inodes linked here */
+       enum xfs_refc_domain    rc_domain; /* shared or cow staging extent? */
+};
+
+#define XFS_RMAP_ATTR_FORK             (1 << 0)
+#define XFS_RMAP_BMBT_BLOCK            (1 << 1)
+#define XFS_RMAP_UNWRITTEN             (1 << 2)
+#define XFS_RMAP_KEY_FLAGS             (XFS_RMAP_ATTR_FORK | \
+                                        XFS_RMAP_BMBT_BLOCK)
+#define XFS_RMAP_REC_FLAGS             (XFS_RMAP_UNWRITTEN)
+struct xfs_rmap_irec {
+       xfs_agblock_t   rm_startblock;  /* extent start block */
+       xfs_extlen_t    rm_blockcount;  /* extent length */
+       uint64_t        rm_owner;       /* extent owner */
+       uint64_t        rm_offset;      /* offset within the owner */
+       unsigned int    rm_flags;       /* state flags */
+};
+
 /* per-AG block reservation types */
 enum xfs_ag_resv_type {
        XFS_AG_RESV_NONE = 0,
index ab427b4..3b38f4e 100644 (file)
@@ -100,9 +100,7 @@ xchk_allocbt_rec(
        bno = be32_to_cpu(rec->alloc.ar_startblock);
        len = be32_to_cpu(rec->alloc.ar_blockcount);
 
-       if (bno + len <= bno ||
-           !xfs_verify_agbno(pag, bno) ||
-           !xfs_verify_agbno(pag, bno + len - 1))
+       if (!xfs_verify_agbext(pag, bno, len))
                xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
 
        xchk_allocbt_xref(bs->sc, bno, len);
index e1026e0..e312be7 100644 (file)
@@ -108,9 +108,8 @@ xchk_iallocbt_chunk(
        xfs_agblock_t                   bno;
 
        bno = XFS_AGINO_TO_AGBNO(mp, agino);
-       if (bno + len <= bno ||
-           !xfs_verify_agbno(pag, bno) ||
-           !xfs_verify_agbno(pag, bno + len - 1))
+
+       if (!xfs_verify_agbext(pag, bno, len))
                xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
 
        xchk_iallocbt_chunk_xref(bs->sc, irec, agino, bno, len);
index c68b767..a26ee0f 100644 (file)
@@ -269,15 +269,13 @@ done:
 STATIC void
 xchk_refcountbt_xref_rmap(
        struct xfs_scrub                *sc,
-       xfs_agblock_t                   bno,
-       xfs_extlen_t                    len,
-       xfs_nlink_t                     refcount)
+       const struct xfs_refcount_irec  *irec)
 {
        struct xchk_refcnt_check        refchk = {
-               .sc = sc,
-               .bno = bno,
-               .len = len,
-               .refcount refcount,
+               .sc                     = sc,
+               .bno                    = irec->rc_startblock,
+               .len                    = irec->rc_blockcount,
+               .refcount               = irec->rc_refcount,
                .seen = 0,
        };
        struct xfs_rmap_irec            low;
@@ -291,9 +289,9 @@ xchk_refcountbt_xref_rmap(
 
        /* Cross-reference with the rmapbt to confirm the refcount. */
        memset(&low, 0, sizeof(low));
-       low.rm_startblock = bno;
+       low.rm_startblock = irec->rc_startblock;
        memset(&high, 0xFF, sizeof(high));
-       high.rm_startblock = bno + len - 1;
+       high.rm_startblock = irec->rc_startblock + irec->rc_blockcount - 1;
 
        INIT_LIST_HEAD(&refchk.fragments);
        error = xfs_rmap_query_range(sc->sa.rmap_cur, &low, &high,
@@ -302,7 +300,7 @@ xchk_refcountbt_xref_rmap(
                goto out_free;
 
        xchk_refcountbt_process_rmap_fragments(&refchk);
-       if (refcount != refchk.seen)
+       if (irec->rc_refcount != refchk.seen)
                xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
 
 out_free:
@@ -315,17 +313,16 @@ out_free:
 /* Cross-reference with the other btrees. */
 STATIC void
 xchk_refcountbt_xref(
-       struct xfs_scrub        *sc,
-       xfs_agblock_t           agbno,
-       xfs_extlen_t            len,
-       xfs_nlink_t             refcount)
+       struct xfs_scrub                *sc,
+       const struct xfs_refcount_irec  *irec)
 {
        if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
                return;
 
-       xchk_xref_is_used_space(sc, agbno, len);
-       xchk_xref_is_not_inode_chunk(sc, agbno, len);
-       xchk_refcountbt_xref_rmap(sc, agbno, len, refcount);
+       xchk_xref_is_used_space(sc, irec->rc_startblock, irec->rc_blockcount);
+       xchk_xref_is_not_inode_chunk(sc, irec->rc_startblock,
+                       irec->rc_blockcount);
+       xchk_refcountbt_xref_rmap(sc, irec);
 }
 
 /* Scrub a refcountbt record. */
@@ -334,35 +331,27 @@ xchk_refcountbt_rec(
        struct xchk_btree       *bs,
        const union xfs_btree_rec *rec)
 {
+       struct xfs_refcount_irec irec;
        xfs_agblock_t           *cow_blocks = bs->private;
        struct xfs_perag        *pag = bs->cur->bc_ag.pag;
-       xfs_agblock_t           bno;
-       xfs_extlen_t            len;
-       xfs_nlink_t             refcount;
-       bool                    has_cowflag;
 
-       bno = be32_to_cpu(rec->refc.rc_startblock);
-       len = be32_to_cpu(rec->refc.rc_blockcount);
-       refcount = be32_to_cpu(rec->refc.rc_refcount);
+       xfs_refcount_btrec_to_irec(rec, &irec);
 
-       /* Only CoW records can have refcount == 1. */
-       has_cowflag = (bno & XFS_REFC_COW_START);
-       if ((refcount == 1 && !has_cowflag) || (refcount != 1 && has_cowflag))
+       /* Check the domain and refcount are not incompatible. */
+       if (!xfs_refcount_check_domain(&irec))
                xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
-       if (has_cowflag)
-               (*cow_blocks) += len;
+
+       if (irec.rc_domain == XFS_REFC_DOMAIN_COW)
+               (*cow_blocks) += irec.rc_blockcount;
 
        /* Check the extent. */
-       bno &= ~XFS_REFC_COW_START;
-       if (bno + len <= bno ||
-           !xfs_verify_agbno(pag, bno) ||
-           !xfs_verify_agbno(pag, bno + len - 1))
+       if (!xfs_verify_agbext(pag, irec.rc_startblock, irec.rc_blockcount))
                xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
 
-       if (refcount == 0)
+       if (irec.rc_refcount == 0)
                xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
 
-       xchk_refcountbt_xref(bs->sc, bno, len, refcount);
+       xchk_refcountbt_xref(bs->sc, &irec);
 
        return 0;
 }
@@ -426,7 +415,6 @@ xchk_xref_is_cow_staging(
        xfs_extlen_t                    len)
 {
        struct xfs_refcount_irec        rc;
-       bool                            has_cowflag;
        int                             has_refcount;
        int                             error;
 
@@ -434,8 +422,8 @@ xchk_xref_is_cow_staging(
                return;
 
        /* Find the CoW staging extent. */
-       error = xfs_refcount_lookup_le(sc->sa.refc_cur,
-                       agbno + XFS_REFC_COW_START, &has_refcount);
+       error = xfs_refcount_lookup_le(sc->sa.refc_cur, XFS_REFC_DOMAIN_COW,
+                       agbno, &has_refcount);
        if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
                return;
        if (!has_refcount) {
@@ -451,9 +439,8 @@ xchk_xref_is_cow_staging(
                return;
        }
 
-       /* CoW flag must be set, refcount must be 1. */
-       has_cowflag = (rc.rc_startblock & XFS_REFC_COW_START);
-       if (!has_cowflag || rc.rc_refcount != 1)
+       /* CoW lookup returned a shared extent record? */
+       if (rc.rc_domain != XFS_REFC_DOMAIN_COW)
                xchk_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0);
 
        /* Must be at least as long as what was passed in */
@@ -477,7 +464,8 @@ xchk_xref_is_not_shared(
        if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm))
                return;
 
-       error = xfs_refcount_has_record(sc->sa.refc_cur, agbno, len, &shared);
+       error = xfs_refcount_has_record(sc->sa.refc_cur, XFS_REFC_DOMAIN_SHARED,
+                       agbno, len, &shared);
        if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
                return;
        if (shared)
index cf5ce60..2788a6f 100644 (file)
@@ -245,28 +245,6 @@ xfs_attri_init(
        return attrip;
 }
 
-/*
- * Copy an attr format buffer from the given buf, and into the destination attr
- * format structure.
- */
-STATIC int
-xfs_attri_copy_format(
-       struct xfs_log_iovec            *buf,
-       struct xfs_attri_log_format     *dst_attr_fmt)
-{
-       struct xfs_attri_log_format     *src_attr_fmt = buf->i_addr;
-       size_t                          len;
-
-       len = sizeof(struct xfs_attri_log_format);
-       if (buf->i_len != len) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
-               return -EFSCORRUPTED;
-       }
-
-       memcpy((char *)dst_attr_fmt, (char *)src_attr_fmt, len);
-       return 0;
-}
-
 static inline struct xfs_attrd_log_item *ATTRD_ITEM(struct xfs_log_item *lip)
 {
        return container_of(lip, struct xfs_attrd_log_item, attrd_item);
@@ -731,24 +709,50 @@ xlog_recover_attri_commit_pass2(
        struct xfs_attri_log_nameval    *nv;
        const void                      *attr_value = NULL;
        const void                      *attr_name;
-       int                             error;
+       size_t                          len;
 
        attri_formatp = item->ri_buf[0].i_addr;
        attr_name = item->ri_buf[1].i_addr;
 
        /* Validate xfs_attri_log_format before the large memory allocation */
+       len = sizeof(struct xfs_attri_log_format);
+       if (item->ri_buf[0].i_len != len) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
+               return -EFSCORRUPTED;
+       }
+
        if (!xfs_attri_validate(mp, attri_formatp)) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
+               return -EFSCORRUPTED;
+       }
+
+       /* Validate the attr name */
+       if (item->ri_buf[1].i_len !=
+                       xlog_calc_iovec_len(attri_formatp->alfi_name_len)) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
                return -EFSCORRUPTED;
        }
 
        if (!xfs_attr_namecheck(attr_name, attri_formatp->alfi_name_len)) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[1].i_addr, item->ri_buf[1].i_len);
                return -EFSCORRUPTED;
        }
 
-       if (attri_formatp->alfi_value_len)
+       /* Validate the attr value, if present */
+       if (attri_formatp->alfi_value_len != 0) {
+               if (item->ri_buf[2].i_len != xlog_calc_iovec_len(attri_formatp->alfi_value_len)) {
+                       XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                                       item->ri_buf[0].i_addr,
+                                       item->ri_buf[0].i_len);
+                       return -EFSCORRUPTED;
+               }
+
                attr_value = item->ri_buf[2].i_addr;
+       }
 
        /*
         * Memory alloc failure will cause replay to abort.  We attach the
@@ -760,9 +764,7 @@ xlog_recover_attri_commit_pass2(
                        attri_formatp->alfi_value_len);
 
        attrip = xfs_attri_init(mp, nv);
-       error = xfs_attri_copy_format(&item->ri_buf[0], &attrip->attri_format);
-       if (error)
-               goto out;
+       memcpy(&attrip->attri_format, attri_formatp, len);
 
        /*
         * The ATTRI has two references. One for the ATTRD and one for ATTRI to
@@ -774,10 +776,6 @@ xlog_recover_attri_commit_pass2(
        xfs_attri_release(attrip);
        xfs_attri_log_nameval_put(nv);
        return 0;
-out:
-       xfs_attri_item_free(attrip);
-       xfs_attri_log_nameval_put(nv);
-       return error;
 }
 
 /*
@@ -842,7 +840,8 @@ xlog_recover_attrd_commit_pass2(
 
        attrd_formatp = item->ri_buf[0].i_addr;
        if (item->ri_buf[0].i_len != sizeof(struct xfs_attrd_log_format)) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
                return -EFSCORRUPTED;
        }
 
index 51f66e9..41323da 100644 (file)
@@ -608,28 +608,18 @@ static const struct xfs_item_ops xfs_bui_item_ops = {
        .iop_relog      = xfs_bui_item_relog,
 };
 
-/*
- * Copy an BUI format buffer from the given buf, and into the destination
- * BUI format structure.  The BUI/BUD items were designed not to need any
- * special alignment handling.
- */
-static int
+static inline void
 xfs_bui_copy_format(
-       struct xfs_log_iovec            *buf,
-       struct xfs_bui_log_format       *dst_bui_fmt)
+       struct xfs_bui_log_format       *dst,
+       const struct xfs_bui_log_format *src)
 {
-       struct xfs_bui_log_format       *src_bui_fmt;
-       uint                            len;
+       unsigned int                    i;
 
-       src_bui_fmt = buf->i_addr;
-       len = xfs_bui_log_format_sizeof(src_bui_fmt->bui_nextents);
+       memcpy(dst, src, offsetof(struct xfs_bui_log_format, bui_extents));
 
-       if (buf->i_len == len) {
-               memcpy(dst_bui_fmt, src_bui_fmt, len);
-               return 0;
-       }
-       XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
-       return -EFSCORRUPTED;
+       for (i = 0; i < src->bui_nextents; i++)
+               memcpy(&dst->bui_extents[i], &src->bui_extents[i],
+                               sizeof(struct xfs_map_extent));
 }
 
 /*
@@ -646,23 +636,34 @@ xlog_recover_bui_commit_pass2(
        struct xlog_recover_item        *item,
        xfs_lsn_t                       lsn)
 {
-       int                             error;
        struct xfs_mount                *mp = log->l_mp;
        struct xfs_bui_log_item         *buip;
        struct xfs_bui_log_format       *bui_formatp;
+       size_t                          len;
 
        bui_formatp = item->ri_buf[0].i_addr;
 
+       if (item->ri_buf[0].i_len < xfs_bui_log_format_sizeof(0)) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
+               return -EFSCORRUPTED;
+       }
+
        if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
                return -EFSCORRUPTED;
        }
-       buip = xfs_bui_init(mp);
-       error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format);
-       if (error) {
-               xfs_bui_item_free(buip);
-               return error;
+
+       len = xfs_bui_log_format_sizeof(bui_formatp->bui_nextents);
+       if (item->ri_buf[0].i_len != len) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
+               return -EFSCORRUPTED;
        }
+
+       buip = xfs_bui_init(mp);
+       xfs_bui_copy_format(&buip->bui_format, bui_formatp);
        atomic_set(&buip->bui_next_extent, bui_formatp->bui_nextents);
        /*
         * Insert the intent into the AIL directly and drop one reference so
@@ -696,7 +697,8 @@ xlog_recover_bud_commit_pass2(
 
        bud_formatp = item->ri_buf[0].i_addr;
        if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
                return -EFSCORRUPTED;
        }
 
index 7db588e..c6b2aab 100644 (file)
@@ -234,13 +234,18 @@ int
 xfs_errortag_init(
        struct xfs_mount        *mp)
 {
+       int ret;
+
        mp->m_errortag = kmem_zalloc(sizeof(unsigned int) * XFS_ERRTAG_MAX,
                        KM_MAYFAIL);
        if (!mp->m_errortag)
                return -ENOMEM;
 
-       return xfs_sysfs_init(&mp->m_errortag_kobj, &xfs_errortag_ktype,
-                              &mp->m_kobj, "errortag");
+       ret = xfs_sysfs_init(&mp->m_errortag_kobj, &xfs_errortag_ktype,
+                               &mp->m_kobj, "errortag");
+       if (ret)
+               kmem_free(mp->m_errortag);
+       return ret;
 }
 
 void
index 27ccfcd..d5130d1 100644 (file)
@@ -66,27 +66,16 @@ xfs_efi_release(
        xfs_efi_item_free(efip);
 }
 
-/*
- * This returns the number of iovecs needed to log the given efi item.
- * We only need 1 iovec for an efi item.  It just logs the efi_log_format
- * structure.
- */
-static inline int
-xfs_efi_item_sizeof(
-       struct xfs_efi_log_item *efip)
-{
-       return sizeof(struct xfs_efi_log_format) +
-              (efip->efi_format.efi_nextents - 1) * sizeof(xfs_extent_t);
-}
-
 STATIC void
 xfs_efi_item_size(
        struct xfs_log_item     *lip,
        int                     *nvecs,
        int                     *nbytes)
 {
+       struct xfs_efi_log_item *efip = EFI_ITEM(lip);
+
        *nvecs += 1;
-       *nbytes += xfs_efi_item_sizeof(EFI_ITEM(lip));
+       *nbytes += xfs_efi_log_format_sizeof(efip->efi_format.efi_nextents);
 }
 
 /*
@@ -112,7 +101,7 @@ xfs_efi_item_format(
 
        xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFI_FORMAT,
                        &efip->efi_format,
-                       xfs_efi_item_sizeof(efip));
+                       xfs_efi_log_format_sizeof(efip->efi_format.efi_nextents));
 }
 
 
@@ -155,13 +144,11 @@ xfs_efi_init(
 
 {
        struct xfs_efi_log_item *efip;
-       uint                    size;
 
        ASSERT(nextents > 0);
        if (nextents > XFS_EFI_MAX_FAST_EXTENTS) {
-               size = (uint)(sizeof(struct xfs_efi_log_item) +
-                       ((nextents - 1) * sizeof(xfs_extent_t)));
-               efip = kmem_zalloc(size, 0);
+               efip = kzalloc(xfs_efi_log_item_sizeof(nextents),
+                               GFP_KERNEL | __GFP_NOFAIL);
        } else {
                efip = kmem_cache_zalloc(xfs_efi_cache,
                                         GFP_KERNEL | __GFP_NOFAIL);
@@ -188,15 +175,17 @@ xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
 {
        xfs_efi_log_format_t *src_efi_fmt = buf->i_addr;
        uint i;
-       uint len = sizeof(xfs_efi_log_format_t) +
-               (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t);
-       uint len32 = sizeof(xfs_efi_log_format_32_t) +
-               (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t);
-       uint len64 = sizeof(xfs_efi_log_format_64_t) +
-               (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t);
+       uint len = xfs_efi_log_format_sizeof(src_efi_fmt->efi_nextents);
+       uint len32 = xfs_efi_log_format32_sizeof(src_efi_fmt->efi_nextents);
+       uint len64 = xfs_efi_log_format64_sizeof(src_efi_fmt->efi_nextents);
 
        if (buf->i_len == len) {
-               memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len);
+               memcpy(dst_efi_fmt, src_efi_fmt,
+                      offsetof(struct xfs_efi_log_format, efi_extents));
+               for (i = 0; i < src_efi_fmt->efi_nextents; i++)
+                       memcpy(&dst_efi_fmt->efi_extents[i],
+                              &src_efi_fmt->efi_extents[i],
+                              sizeof(struct xfs_extent));
                return 0;
        } else if (buf->i_len == len32) {
                xfs_efi_log_format_32_t *src_efi_fmt_32 = buf->i_addr;
@@ -227,7 +216,8 @@ xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
                }
                return 0;
        }
-       XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
+       XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, NULL, buf->i_addr,
+                       buf->i_len);
        return -EFSCORRUPTED;
 }
 
@@ -246,27 +236,16 @@ xfs_efd_item_free(struct xfs_efd_log_item *efdp)
                kmem_cache_free(xfs_efd_cache, efdp);
 }
 
-/*
- * This returns the number of iovecs needed to log the given efd item.
- * We only need 1 iovec for an efd item.  It just logs the efd_log_format
- * structure.
- */
-static inline int
-xfs_efd_item_sizeof(
-       struct xfs_efd_log_item *efdp)
-{
-       return sizeof(xfs_efd_log_format_t) +
-              (efdp->efd_format.efd_nextents - 1) * sizeof(xfs_extent_t);
-}
-
 STATIC void
 xfs_efd_item_size(
        struct xfs_log_item     *lip,
        int                     *nvecs,
        int                     *nbytes)
 {
+       struct xfs_efd_log_item *efdp = EFD_ITEM(lip);
+
        *nvecs += 1;
-       *nbytes += xfs_efd_item_sizeof(EFD_ITEM(lip));
+       *nbytes += xfs_efd_log_format_sizeof(efdp->efd_format.efd_nextents);
 }
 
 /*
@@ -291,7 +270,7 @@ xfs_efd_item_format(
 
        xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_EFD_FORMAT,
                        &efdp->efd_format,
-                       xfs_efd_item_sizeof(efdp));
+                       xfs_efd_log_format_sizeof(efdp->efd_format.efd_nextents));
 }
 
 /*
@@ -340,9 +319,8 @@ xfs_trans_get_efd(
        ASSERT(nextents > 0);
 
        if (nextents > XFS_EFD_MAX_FAST_EXTENTS) {
-               efdp = kmem_zalloc(sizeof(struct xfs_efd_log_item) +
-                               (nextents - 1) * sizeof(struct xfs_extent),
-                               0);
+               efdp = kzalloc(xfs_efd_log_item_sizeof(nextents),
+                               GFP_KERNEL | __GFP_NOFAIL);
        } else {
                efdp = kmem_cache_zalloc(xfs_efd_cache,
                                        GFP_KERNEL | __GFP_NOFAIL);
@@ -733,6 +711,12 @@ xlog_recover_efi_commit_pass2(
 
        efi_formatp = item->ri_buf[0].i_addr;
 
+       if (item->ri_buf[0].i_len < xfs_efi_log_format_sizeof(0)) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
+               return -EFSCORRUPTED;
+       }
+
        efip = xfs_efi_init(mp, efi_formatp->efi_nextents);
        error = xfs_efi_copy_format(&item->ri_buf[0], &efip->efi_format);
        if (error) {
@@ -769,12 +753,24 @@ xlog_recover_efd_commit_pass2(
        xfs_lsn_t                       lsn)
 {
        struct xfs_efd_log_format       *efd_formatp;
+       int                             buflen = item->ri_buf[0].i_len;
 
        efd_formatp = item->ri_buf[0].i_addr;
-       ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) +
-               ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) ||
-              (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) +
-               ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_64_t)))));
+
+       if (buflen < sizeof(struct xfs_efd_log_format)) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
+                               efd_formatp, buflen);
+               return -EFSCORRUPTED;
+       }
+
+       if (item->ri_buf[0].i_len != xfs_efd_log_format32_sizeof(
+                                               efd_formatp->efd_nextents) &&
+           item->ri_buf[0].i_len != xfs_efd_log_format64_sizeof(
+                                               efd_formatp->efd_nextents)) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
+                               efd_formatp, buflen);
+               return -EFSCORRUPTED;
+       }
 
        xlog_recover_release_intent(log, XFS_LI_EFI, efd_formatp->efd_efi_id);
        return 0;
index 186d0f2..da6a5af 100644 (file)
@@ -52,6 +52,14 @@ struct xfs_efi_log_item {
        xfs_efi_log_format_t    efi_format;
 };
 
+static inline size_t
+xfs_efi_log_item_sizeof(
+       unsigned int            nr)
+{
+       return offsetof(struct xfs_efi_log_item, efi_format) +
+                       xfs_efi_log_format_sizeof(nr);
+}
+
 /*
  * This is the "extent free done" log item.  It is used to log
  * the fact that some extents earlier mentioned in an efi item
@@ -64,6 +72,14 @@ struct xfs_efd_log_item {
        xfs_efd_log_format_t    efd_format;
 };
 
+static inline size_t
+xfs_efd_log_item_sizeof(
+       unsigned int            nr)
+{
+       return offsetof(struct xfs_efd_log_item, efd_format) +
+                       xfs_efd_log_format_sizeof(nr);
+}
+
 /*
  * Max number of extents in fast allocation path.
  */
index c6c8026..e462d39 100644 (file)
@@ -1261,7 +1261,7 @@ xfs_file_llseek(
 }
 
 #ifdef CONFIG_FS_DAX
-static int
+static inline vm_fault_t
 xfs_dax_fault(
        struct vm_fault         *vmf,
        enum page_entry_size    pe_size,
@@ -1274,14 +1274,15 @@ xfs_dax_fault(
                                &xfs_read_iomap_ops);
 }
 #else
-static int
+static inline vm_fault_t
 xfs_dax_fault(
        struct vm_fault         *vmf,
        enum page_entry_size    pe_size,
        bool                    write_fault,
        pfn_t                   *pfn)
 {
-       return 0;
+       ASSERT(0);
+       return VM_FAULT_SIGBUS;
 }
 #endif
 
index c000b74..aa303be 100644 (file)
@@ -2818,7 +2818,7 @@ retry:
         * Lock all the participating inodes. Depending upon whether
         * the target_name exists in the target directory, and
         * whether the target directory is the same as the source
-        * directory, we can lock from 2 to 4 inodes.
+        * directory, we can lock from 2 to 5 inodes.
         */
        xfs_lock_inodes(inodes, num_inodes, XFS_ILOCK_EXCL);
 
index 17e923b..322eb2e 100644 (file)
@@ -2552,6 +2552,8 @@ xlog_recover_process_intents(
        for (lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
             lip != NULL;
             lip = xfs_trans_ail_cursor_next(ailp, &cur)) {
+               const struct xfs_item_ops       *ops;
+
                if (!xlog_item_is_intent(lip))
                        break;
 
@@ -2567,13 +2569,17 @@ xlog_recover_process_intents(
                 * deferred ops, you /must/ attach them to the capture list in
                 * the recover routine or else those subsequent intents will be
                 * replayed in the wrong order!
+                *
+                * The recovery function can free the log item, so we must not
+                * access lip after it returns.
                 */
                spin_unlock(&ailp->ail_lock);
-               error = lip->li_ops->iop_recover(lip, &capture_list);
+               ops = lip->li_ops;
+               error = ops->iop_recover(lip, &capture_list);
                spin_lock(&ailp->ail_lock);
                if (error) {
                        trace_xlog_intent_recovery_failed(log->l_mp, error,
-                                       lip->li_ops->iop_recover);
+                                       ops->iop_recover);
                        break;
                }
        }
index 758702b..9737b5a 100644 (file)
@@ -118,10 +118,10 @@ xfs_check_ondisk_structs(void)
        /* log structures */
        XFS_CHECK_STRUCT_SIZE(struct xfs_buf_log_format,        88);
        XFS_CHECK_STRUCT_SIZE(struct xfs_dq_logformat,          24);
-       XFS_CHECK_STRUCT_SIZE(struct xfs_efd_log_format_32,     28);
-       XFS_CHECK_STRUCT_SIZE(struct xfs_efd_log_format_64,     32);
-       XFS_CHECK_STRUCT_SIZE(struct xfs_efi_log_format_32,     28);
-       XFS_CHECK_STRUCT_SIZE(struct xfs_efi_log_format_64,     32);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_efd_log_format_32,     16);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_efd_log_format_64,     16);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_efi_log_format_32,     16);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_efi_log_format_64,     16);
        XFS_CHECK_STRUCT_SIZE(struct xfs_extent_32,             12);
        XFS_CHECK_STRUCT_SIZE(struct xfs_extent_64,             16);
        XFS_CHECK_STRUCT_SIZE(struct xfs_log_dinode,            176);
@@ -134,6 +134,21 @@ xfs_check_ondisk_structs(void)
        XFS_CHECK_STRUCT_SIZE(struct xfs_trans_header,          16);
        XFS_CHECK_STRUCT_SIZE(struct xfs_attri_log_format,      40);
        XFS_CHECK_STRUCT_SIZE(struct xfs_attrd_log_format,      16);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_bui_log_format,        16);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_bud_log_format,        16);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_cui_log_format,        16);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_cud_log_format,        16);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_rui_log_format,        16);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_rud_log_format,        16);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_map_extent,            32);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_phys_extent,           16);
+
+       XFS_CHECK_OFFSET(struct xfs_bui_log_format, bui_extents,        16);
+       XFS_CHECK_OFFSET(struct xfs_cui_log_format, cui_extents,        16);
+       XFS_CHECK_OFFSET(struct xfs_rui_log_format, rui_extents,        16);
+       XFS_CHECK_OFFSET(struct xfs_efi_log_format, efi_extents,        16);
+       XFS_CHECK_OFFSET(struct xfs_efi_log_format_32, efi_extents,     16);
+       XFS_CHECK_OFFSET(struct xfs_efi_log_format_64, efi_extents,     16);
 
        /*
         * The v5 superblock format extended several v4 header structures with
index 7e97bf1..858e3e9 100644 (file)
@@ -523,7 +523,9 @@ xfs_cui_item_recover(
                        type = refc_type;
                        break;
                default:
-                       XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
+                       XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                                       &cuip->cui_format,
+                                       sizeof(cuip->cui_format));
                        error = -EFSCORRUPTED;
                        goto abort_error;
                }
@@ -536,7 +538,8 @@ xfs_cui_item_recover(
                                &new_fsb, &new_len, &rcur);
                if (error == -EFSCORRUPTED)
                        XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
-                                       refc, sizeof(*refc));
+                                       &cuip->cui_format,
+                                       sizeof(cuip->cui_format));
                if (error)
                        goto abort_error;
 
@@ -622,28 +625,18 @@ static const struct xfs_item_ops xfs_cui_item_ops = {
        .iop_relog      = xfs_cui_item_relog,
 };
 
-/*
- * Copy an CUI format buffer from the given buf, and into the destination
- * CUI format structure.  The CUI/CUD items were designed not to need any
- * special alignment handling.
- */
-static int
+static inline void
 xfs_cui_copy_format(
-       struct xfs_log_iovec            *buf,
-       struct xfs_cui_log_format       *dst_cui_fmt)
+       struct xfs_cui_log_format       *dst,
+       const struct xfs_cui_log_format *src)
 {
-       struct xfs_cui_log_format       *src_cui_fmt;
-       uint                            len;
+       unsigned int                    i;
 
-       src_cui_fmt = buf->i_addr;
-       len = xfs_cui_log_format_sizeof(src_cui_fmt->cui_nextents);
+       memcpy(dst, src, offsetof(struct xfs_cui_log_format, cui_extents));
 
-       if (buf->i_len == len) {
-               memcpy(dst_cui_fmt, src_cui_fmt, len);
-               return 0;
-       }
-       XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
-       return -EFSCORRUPTED;
+       for (i = 0; i < src->cui_nextents; i++)
+               memcpy(&dst->cui_extents[i], &src->cui_extents[i],
+                               sizeof(struct xfs_phys_extent));
 }
 
 /*
@@ -660,19 +653,28 @@ xlog_recover_cui_commit_pass2(
        struct xlog_recover_item        *item,
        xfs_lsn_t                       lsn)
 {
-       int                             error;
        struct xfs_mount                *mp = log->l_mp;
        struct xfs_cui_log_item         *cuip;
        struct xfs_cui_log_format       *cui_formatp;
+       size_t                          len;
 
        cui_formatp = item->ri_buf[0].i_addr;
 
-       cuip = xfs_cui_init(mp, cui_formatp->cui_nextents);
-       error = xfs_cui_copy_format(&item->ri_buf[0], &cuip->cui_format);
-       if (error) {
-               xfs_cui_item_free(cuip);
-               return error;
+       if (item->ri_buf[0].i_len < xfs_cui_log_format_sizeof(0)) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
+               return -EFSCORRUPTED;
        }
+
+       len = xfs_cui_log_format_sizeof(cui_formatp->cui_nextents);
+       if (item->ri_buf[0].i_len != len) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
+               return -EFSCORRUPTED;
+       }
+
+       cuip = xfs_cui_init(mp, cui_formatp->cui_nextents);
+       xfs_cui_copy_format(&cuip->cui_format, cui_formatp);
        atomic_set(&cuip->cui_next_extent, cui_formatp->cui_nextents);
        /*
         * Insert the intent into the AIL directly and drop one reference so
@@ -706,7 +708,8 @@ xlog_recover_cud_commit_pass2(
 
        cud_formatp = item->ri_buf[0].i_addr;
        if (item->ri_buf[0].i_len != sizeof(struct xfs_cud_log_format)) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
                return -EFSCORRUPTED;
        }
 
index fef92e0..534504e 100644 (file)
@@ -155,31 +155,6 @@ xfs_rui_init(
        return ruip;
 }
 
-/*
- * Copy an RUI format buffer from the given buf, and into the destination
- * RUI format structure.  The RUI/RUD items were designed not to need any
- * special alignment handling.
- */
-STATIC int
-xfs_rui_copy_format(
-       struct xfs_log_iovec            *buf,
-       struct xfs_rui_log_format       *dst_rui_fmt)
-{
-       struct xfs_rui_log_format       *src_rui_fmt;
-       uint                            len;
-
-       src_rui_fmt = buf->i_addr;
-       len = xfs_rui_log_format_sizeof(src_rui_fmt->rui_nextents);
-
-       if (buf->i_len != len) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
-               return -EFSCORRUPTED;
-       }
-
-       memcpy(dst_rui_fmt, src_rui_fmt, len);
-       return 0;
-}
-
 static inline struct xfs_rud_log_item *RUD_ITEM(struct xfs_log_item *lip)
 {
        return container_of(lip, struct xfs_rud_log_item, rud_item);
@@ -582,7 +557,9 @@ xfs_rui_item_recover(
                        type = XFS_RMAP_FREE;
                        break;
                default:
-                       XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
+                       XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                                       &ruip->rui_format,
+                                       sizeof(ruip->rui_format));
                        error = -EFSCORRUPTED;
                        goto abort_error;
                }
@@ -652,6 +629,20 @@ static const struct xfs_item_ops xfs_rui_item_ops = {
        .iop_relog      = xfs_rui_item_relog,
 };
 
+static inline void
+xfs_rui_copy_format(
+       struct xfs_rui_log_format       *dst,
+       const struct xfs_rui_log_format *src)
+{
+       unsigned int                    i;
+
+       memcpy(dst, src, offsetof(struct xfs_rui_log_format, rui_extents));
+
+       for (i = 0; i < src->rui_nextents; i++)
+               memcpy(&dst->rui_extents[i], &src->rui_extents[i],
+                               sizeof(struct xfs_map_extent));
+}
+
 /*
  * This routine is called to create an in-core extent rmap update
  * item from the rui format structure which was logged on disk.
@@ -666,19 +657,28 @@ xlog_recover_rui_commit_pass2(
        struct xlog_recover_item        *item,
        xfs_lsn_t                       lsn)
 {
-       int                             error;
        struct xfs_mount                *mp = log->l_mp;
        struct xfs_rui_log_item         *ruip;
        struct xfs_rui_log_format       *rui_formatp;
+       size_t                          len;
 
        rui_formatp = item->ri_buf[0].i_addr;
 
-       ruip = xfs_rui_init(mp, rui_formatp->rui_nextents);
-       error = xfs_rui_copy_format(&item->ri_buf[0], &ruip->rui_format);
-       if (error) {
-               xfs_rui_item_free(ruip);
-               return error;
+       if (item->ri_buf[0].i_len < xfs_rui_log_format_sizeof(0)) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
+               return -EFSCORRUPTED;
+       }
+
+       len = xfs_rui_log_format_sizeof(rui_formatp->rui_nextents);
+       if (item->ri_buf[0].i_len != len) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                               item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
+               return -EFSCORRUPTED;
        }
+
+       ruip = xfs_rui_init(mp, rui_formatp->rui_nextents);
+       xfs_rui_copy_format(&ruip->rui_format, rui_formatp);
        atomic_set(&ruip->rui_next_extent, rui_formatp->rui_nextents);
        /*
         * Insert the intent into the AIL directly and drop one reference so
@@ -711,7 +711,11 @@ xlog_recover_rud_commit_pass2(
        struct xfs_rud_log_format       *rud_formatp;
 
        rud_formatp = item->ri_buf[0].i_addr;
-       ASSERT(item->ri_buf[0].i_len == sizeof(struct xfs_rud_log_format));
+       if (item->ri_buf[0].i_len != sizeof(struct xfs_rud_log_format)) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
+                               rud_formatp, item->ri_buf[0].i_len);
+               return -EFSCORRUPTED;
+       }
 
        xlog_recover_release_intent(log, XFS_LI_RUI, rud_formatp->rud_rui_id);
        return 0;
index f029c67..ee4b429 100644 (file)
@@ -2028,18 +2028,14 @@ xfs_init_caches(void)
                goto out_destroy_trans_cache;
 
        xfs_efd_cache = kmem_cache_create("xfs_efd_item",
-                                       (sizeof(struct xfs_efd_log_item) +
-                                       (XFS_EFD_MAX_FAST_EXTENTS - 1) *
-                                       sizeof(struct xfs_extent)),
-                                       0, 0, NULL);
+                       xfs_efd_log_item_sizeof(XFS_EFD_MAX_FAST_EXTENTS),
+                       0, 0, NULL);
        if (!xfs_efd_cache)
                goto out_destroy_buf_item_cache;
 
        xfs_efi_cache = kmem_cache_create("xfs_efi_item",
-                                        (sizeof(struct xfs_efi_log_item) +
-                                        (XFS_EFI_MAX_FAST_EXTENTS - 1) *
-                                        sizeof(struct xfs_extent)),
-                                        0, 0, NULL);
+                       xfs_efi_log_item_sizeof(XFS_EFI_MAX_FAST_EXTENTS),
+                       0, 0, NULL);
        if (!xfs_efi_cache)
                goto out_destroy_efd_cache;
 
index 4358585..513095e 100644 (file)
@@ -33,10 +33,15 @@ xfs_sysfs_init(
        const char              *name)
 {
        struct kobject          *parent;
+       int err;
 
        parent = parent_kobj ? &parent_kobj->kobject : NULL;
        init_completion(&kobj->complete);
-       return kobject_init_and_add(&kobj->kobject, ktype, parent, "%s", name);
+       err = kobject_init_and_add(&kobj->kobject, ktype, parent, "%s", name);
+       if (err)
+               kobject_put(&kobj->kobject);
+
+       return err;
 }
 
 static inline void
index cb7c81b..372d871 100644 (file)
@@ -799,6 +799,9 @@ TRACE_DEFINE_ENUM(PE_SIZE_PTE);
 TRACE_DEFINE_ENUM(PE_SIZE_PMD);
 TRACE_DEFINE_ENUM(PE_SIZE_PUD);
 
+TRACE_DEFINE_ENUM(XFS_REFC_DOMAIN_SHARED);
+TRACE_DEFINE_ENUM(XFS_REFC_DOMAIN_COW);
+
 TRACE_EVENT(xfs_filemap_fault,
        TP_PROTO(struct xfs_inode *ip, enum page_entry_size pe_size,
                 bool write_fault),
@@ -2925,6 +2928,7 @@ DECLARE_EVENT_CLASS(xfs_refcount_extent_class,
        TP_STRUCT__entry(
                __field(dev_t, dev)
                __field(xfs_agnumber_t, agno)
+               __field(enum xfs_refc_domain, domain)
                __field(xfs_agblock_t, startblock)
                __field(xfs_extlen_t, blockcount)
                __field(xfs_nlink_t, refcount)
@@ -2932,13 +2936,15 @@ DECLARE_EVENT_CLASS(xfs_refcount_extent_class,
        TP_fast_assign(
                __entry->dev = mp->m_super->s_dev;
                __entry->agno = agno;
+               __entry->domain = irec->rc_domain;
                __entry->startblock = irec->rc_startblock;
                __entry->blockcount = irec->rc_blockcount;
                __entry->refcount = irec->rc_refcount;
        ),
-       TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x refcount %u",
+       TP_printk("dev %d:%d agno 0x%x dom %s agbno 0x%x fsbcount 0x%x refcount %u",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->agno,
+                 __print_symbolic(__entry->domain, XFS_REFC_DOMAIN_STRINGS),
                  __entry->startblock,
                  __entry->blockcount,
                  __entry->refcount)
@@ -2958,6 +2964,7 @@ DECLARE_EVENT_CLASS(xfs_refcount_extent_at_class,
        TP_STRUCT__entry(
                __field(dev_t, dev)
                __field(xfs_agnumber_t, agno)
+               __field(enum xfs_refc_domain, domain)
                __field(xfs_agblock_t, startblock)
                __field(xfs_extlen_t, blockcount)
                __field(xfs_nlink_t, refcount)
@@ -2966,14 +2973,16 @@ DECLARE_EVENT_CLASS(xfs_refcount_extent_at_class,
        TP_fast_assign(
                __entry->dev = mp->m_super->s_dev;
                __entry->agno = agno;
+               __entry->domain = irec->rc_domain;
                __entry->startblock = irec->rc_startblock;
                __entry->blockcount = irec->rc_blockcount;
                __entry->refcount = irec->rc_refcount;
                __entry->agbno = agbno;
        ),
-       TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x refcount %u @ agbno 0x%x",
+       TP_printk("dev %d:%d agno 0x%x dom %s agbno 0x%x fsbcount 0x%x refcount %u @ agbno 0x%x",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->agno,
+                 __print_symbolic(__entry->domain, XFS_REFC_DOMAIN_STRINGS),
                  __entry->startblock,
                  __entry->blockcount,
                  __entry->refcount,
@@ -2994,9 +3003,11 @@ DECLARE_EVENT_CLASS(xfs_refcount_double_extent_class,
        TP_STRUCT__entry(
                __field(dev_t, dev)
                __field(xfs_agnumber_t, agno)
+               __field(enum xfs_refc_domain, i1_domain)
                __field(xfs_agblock_t, i1_startblock)
                __field(xfs_extlen_t, i1_blockcount)
                __field(xfs_nlink_t, i1_refcount)
+               __field(enum xfs_refc_domain, i2_domain)
                __field(xfs_agblock_t, i2_startblock)
                __field(xfs_extlen_t, i2_blockcount)
                __field(xfs_nlink_t, i2_refcount)
@@ -3004,20 +3015,24 @@ DECLARE_EVENT_CLASS(xfs_refcount_double_extent_class,
        TP_fast_assign(
                __entry->dev = mp->m_super->s_dev;
                __entry->agno = agno;
+               __entry->i1_domain = i1->rc_domain;
                __entry->i1_startblock = i1->rc_startblock;
                __entry->i1_blockcount = i1->rc_blockcount;
                __entry->i1_refcount = i1->rc_refcount;
+               __entry->i2_domain = i2->rc_domain;
                __entry->i2_startblock = i2->rc_startblock;
                __entry->i2_blockcount = i2->rc_blockcount;
                __entry->i2_refcount = i2->rc_refcount;
        ),
-       TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x refcount %u -- "
-                 "agbno 0x%x fsbcount 0x%x refcount %u",
+       TP_printk("dev %d:%d agno 0x%x dom %s agbno 0x%x fsbcount 0x%x refcount %u -- "
+                 "dom %s agbno 0x%x fsbcount 0x%x refcount %u",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->agno,
+                 __print_symbolic(__entry->i1_domain, XFS_REFC_DOMAIN_STRINGS),
                  __entry->i1_startblock,
                  __entry->i1_blockcount,
                  __entry->i1_refcount,
+                 __print_symbolic(__entry->i2_domain, XFS_REFC_DOMAIN_STRINGS),
                  __entry->i2_startblock,
                  __entry->i2_blockcount,
                  __entry->i2_refcount)
@@ -3038,9 +3053,11 @@ DECLARE_EVENT_CLASS(xfs_refcount_double_extent_at_class,
        TP_STRUCT__entry(
                __field(dev_t, dev)
                __field(xfs_agnumber_t, agno)
+               __field(enum xfs_refc_domain, i1_domain)
                __field(xfs_agblock_t, i1_startblock)
                __field(xfs_extlen_t, i1_blockcount)
                __field(xfs_nlink_t, i1_refcount)
+               __field(enum xfs_refc_domain, i2_domain)
                __field(xfs_agblock_t, i2_startblock)
                __field(xfs_extlen_t, i2_blockcount)
                __field(xfs_nlink_t, i2_refcount)
@@ -3049,21 +3066,25 @@ DECLARE_EVENT_CLASS(xfs_refcount_double_extent_at_class,
        TP_fast_assign(
                __entry->dev = mp->m_super->s_dev;
                __entry->agno = agno;
+               __entry->i1_domain = i1->rc_domain;
                __entry->i1_startblock = i1->rc_startblock;
                __entry->i1_blockcount = i1->rc_blockcount;
                __entry->i1_refcount = i1->rc_refcount;
+               __entry->i2_domain = i2->rc_domain;
                __entry->i2_startblock = i2->rc_startblock;
                __entry->i2_blockcount = i2->rc_blockcount;
                __entry->i2_refcount = i2->rc_refcount;
                __entry->agbno = agbno;
        ),
-       TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x refcount %u -- "
-                 "agbno 0x%x fsbcount 0x%x refcount %u @ agbno 0x%x",
+       TP_printk("dev %d:%d agno 0x%x dom %s agbno 0x%x fsbcount 0x%x refcount %u -- "
+                 "dom %s agbno 0x%x fsbcount 0x%x refcount %u @ agbno 0x%x",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->agno,
+                 __print_symbolic(__entry->i1_domain, XFS_REFC_DOMAIN_STRINGS),
                  __entry->i1_startblock,
                  __entry->i1_blockcount,
                  __entry->i1_refcount,
+                 __print_symbolic(__entry->i2_domain, XFS_REFC_DOMAIN_STRINGS),
                  __entry->i2_startblock,
                  __entry->i2_blockcount,
                  __entry->i2_refcount,
@@ -3086,12 +3107,15 @@ DECLARE_EVENT_CLASS(xfs_refcount_triple_extent_class,
        TP_STRUCT__entry(
                __field(dev_t, dev)
                __field(xfs_agnumber_t, agno)
+               __field(enum xfs_refc_domain, i1_domain)
                __field(xfs_agblock_t, i1_startblock)
                __field(xfs_extlen_t, i1_blockcount)
                __field(xfs_nlink_t, i1_refcount)
+               __field(enum xfs_refc_domain, i2_domain)
                __field(xfs_agblock_t, i2_startblock)
                __field(xfs_extlen_t, i2_blockcount)
                __field(xfs_nlink_t, i2_refcount)
+               __field(enum xfs_refc_domain, i3_domain)
                __field(xfs_agblock_t, i3_startblock)
                __field(xfs_extlen_t, i3_blockcount)
                __field(xfs_nlink_t, i3_refcount)
@@ -3099,27 +3123,33 @@ DECLARE_EVENT_CLASS(xfs_refcount_triple_extent_class,
        TP_fast_assign(
                __entry->dev = mp->m_super->s_dev;
                __entry->agno = agno;
+               __entry->i1_domain = i1->rc_domain;
                __entry->i1_startblock = i1->rc_startblock;
                __entry->i1_blockcount = i1->rc_blockcount;
                __entry->i1_refcount = i1->rc_refcount;
+               __entry->i2_domain = i2->rc_domain;
                __entry->i2_startblock = i2->rc_startblock;
                __entry->i2_blockcount = i2->rc_blockcount;
                __entry->i2_refcount = i2->rc_refcount;
+               __entry->i3_domain = i3->rc_domain;
                __entry->i3_startblock = i3->rc_startblock;
                __entry->i3_blockcount = i3->rc_blockcount;
                __entry->i3_refcount = i3->rc_refcount;
        ),
-       TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x refcount %u -- "
-                 "agbno 0x%x fsbcount 0x%x refcount %u -- "
-                 "agbno 0x%x fsbcount 0x%x refcount %u",
+       TP_printk("dev %d:%d agno 0x%x dom %s agbno 0x%x fsbcount 0x%x refcount %u -- "
+                 "dom %s agbno 0x%x fsbcount 0x%x refcount %u -- "
+                 "dom %s agbno 0x%x fsbcount 0x%x refcount %u",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->agno,
+                 __print_symbolic(__entry->i1_domain, XFS_REFC_DOMAIN_STRINGS),
                  __entry->i1_startblock,
                  __entry->i1_blockcount,
                  __entry->i1_refcount,
+                 __print_symbolic(__entry->i2_domain, XFS_REFC_DOMAIN_STRINGS),
                  __entry->i2_startblock,
                  __entry->i2_blockcount,
                  __entry->i2_refcount,
+                 __print_symbolic(__entry->i3_domain, XFS_REFC_DOMAIN_STRINGS),
                  __entry->i3_startblock,
                  __entry->i3_blockcount,
                  __entry->i3_refcount)
index 16fbf2a..f51df7d 100644 (file)
@@ -730,11 +730,10 @@ void
 xfs_ail_push_all_sync(
        struct xfs_ail  *ailp)
 {
-       struct xfs_log_item     *lip;
        DEFINE_WAIT(wait);
 
        spin_lock(&ailp->ail_lock);
-       while ((lip = xfs_ail_max(ailp)) != NULL) {
+       while (xfs_ail_max(ailp) != NULL) {
                prepare_to_wait(&ailp->ail_empty, &wait, TASK_UNINTERRUPTIBLE);
                wake_up_process(ailp->ail_task);
                spin_unlock(&ailp->ail_lock);
index aeb257a..8392cae 100644 (file)
@@ -15,7 +15,7 @@
 #endif
 
 #ifndef compat_arg_u64
-#ifdef CONFIG_CPU_BIG_ENDIAN
+#ifndef CONFIG_CPU_BIG_ENDIAN
 #define compat_arg_u64(name)           u32  name##_lo, u32  name##_hi
 #define compat_arg_u64_dual(name)      u32, name##_lo, u32, name##_hi
 #else
index 80f3c1c..929d559 100644 (file)
@@ -1222,7 +1222,7 @@ efi_status_t efi_random_get_seed(void);
        arch_efi_call_virt_teardown();                                  \
 })
 
-#define EFI_RANDOM_SEED_SIZE           64U
+#define EFI_RANDOM_SEED_SIZE           32U // BLAKE2S_HASH_SIZE
 
 struct linux_efi_random_seed {
        u32     size;
index 18a31b1..1067a84 100644 (file)
@@ -454,13 +454,18 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size,
 
 #define __fortify_memcpy_chk(p, q, size, p_size, q_size,               \
                             p_size_field, q_size_field, op) ({         \
-       size_t __fortify_size = (size_t)(size);                         \
-       WARN_ONCE(fortify_memcpy_chk(__fortify_size, p_size, q_size,    \
-                                    p_size_field, q_size_field, #op),  \
+       const size_t __fortify_size = (size_t)(size);                   \
+       const size_t __p_size = (p_size);                               \
+       const size_t __q_size = (q_size);                               \
+       const size_t __p_size_field = (p_size_field);                   \
+       const size_t __q_size_field = (q_size_field);                   \
+       WARN_ONCE(fortify_memcpy_chk(__fortify_size, __p_size,          \
+                                    __q_size, __p_size_field,          \
+                                    __q_size_field, #op),              \
                  #op ": detected field-spanning write (size %zu) of single %s (size %zu)\n", \
                  __fortify_size,                                       \
                  "field \"" #p "\" at " __FILE__ ":" __stringify(__LINE__), \
-                 p_size_field);                                        \
+                 __p_size_field);                                      \
        __underlying_##op(p, q, __fortify_size);                        \
 })
 
index 4418b19..6bfa972 100644 (file)
@@ -181,6 +181,8 @@ enum {
        NLA_S64,
        NLA_BITFIELD32,
        NLA_REJECT,
+       NLA_BE16,
+       NLA_BE32,
        __NLA_TYPE_MAX,
 };
 
@@ -231,6 +233,7 @@ enum nla_policy_validation {
  *    NLA_U32, NLA_U64,
  *    NLA_S8, NLA_S16,
  *    NLA_S32, NLA_S64,
+ *    NLA_BE16, NLA_BE32,
  *    NLA_MSECS            Leaving the length field zero will verify the
  *                         given type fits, using it verifies minimum length
  *                         just like "All other"
@@ -261,6 +264,8 @@ enum nla_policy_validation {
  *    NLA_U16,
  *    NLA_U32,
  *    NLA_U64,
+ *    NLA_BE16,
+ *    NLA_BE32,
  *    NLA_S8,
  *    NLA_S16,
  *    NLA_S32,
@@ -317,19 +322,10 @@ struct nla_policy {
        u8              validation_type;
        u16             len;
        union {
-               const u32 bitfield32_valid;
-               const u32 mask;
-               const char *reject_message;
-               const struct nla_policy *nested_policy;
-               struct netlink_range_validation *range;
-               struct netlink_range_validation_signed *range_signed;
-               struct {
-                       s16 min, max;
-                       u8 network_byte_order:1;
-               };
-               int (*validate)(const struct nlattr *attr,
-                               struct netlink_ext_ack *extack);
-               /* This entry is special, and used for the attribute at index 0
+               /**
+                * @strict_start_type: first attribute to validate strictly
+                *
+                * This entry is special, and used for the attribute at index 0
                 * only, and specifies special data about the policy, namely it
                 * specifies the "boundary type" where strict length validation
                 * starts for any attribute types >= this value, also, strict
@@ -348,6 +344,19 @@ struct nla_policy {
                 * was added to enforce strict validation from thereon.
                 */
                u16 strict_start_type;
+
+               /* private: use NLA_POLICY_*() to set */
+               const u32 bitfield32_valid;
+               const u32 mask;
+               const char *reject_message;
+               const struct nla_policy *nested_policy;
+               struct netlink_range_validation *range;
+               struct netlink_range_validation_signed *range_signed;
+               struct {
+                       s16 min, max;
+               };
+               int (*validate)(const struct nlattr *attr,
+                               struct netlink_ext_ack *extack);
        };
 };
 
@@ -369,6 +378,8 @@ struct nla_policy {
        (tp == NLA_U8 || tp == NLA_U16 || tp == NLA_U32 || tp == NLA_U64)
 #define __NLA_IS_SINT_TYPE(tp)                                         \
        (tp == NLA_S8 || tp == NLA_S16 || tp == NLA_S32 || tp == NLA_S64)
+#define __NLA_IS_BEINT_TYPE(tp)                                                \
+       (tp == NLA_BE16 || tp == NLA_BE32)
 
 #define __NLA_ENSURE(condition) BUILD_BUG_ON_ZERO(!(condition))
 #define NLA_ENSURE_UINT_TYPE(tp)                       \
@@ -382,6 +393,7 @@ struct nla_policy {
 #define NLA_ENSURE_INT_OR_BINARY_TYPE(tp)              \
        (__NLA_ENSURE(__NLA_IS_UINT_TYPE(tp) ||         \
                      __NLA_IS_SINT_TYPE(tp) ||         \
+                     __NLA_IS_BEINT_TYPE(tp) ||        \
                      tp == NLA_MSECS ||                \
                      tp == NLA_BINARY) + tp)
 #define NLA_ENSURE_NO_VALIDATION_PTR(tp)               \
@@ -389,6 +401,8 @@ struct nla_policy {
                      tp != NLA_REJECT &&               \
                      tp != NLA_NESTED &&               \
                      tp != NLA_NESTED_ARRAY) + tp)
+#define NLA_ENSURE_BEINT_TYPE(tp)                      \
+       (__NLA_ENSURE(__NLA_IS_BEINT_TYPE(tp)) + tp)
 
 #define NLA_POLICY_RANGE(tp, _min, _max) {             \
        .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp),      \
@@ -419,14 +433,6 @@ struct nla_policy {
        .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp),      \
        .validation_type = NLA_VALIDATE_MAX,            \
        .max = _max,                                    \
-       .network_byte_order = 0,                        \
-}
-
-#define NLA_POLICY_MAX_BE(tp, _max) {                  \
-       .type = NLA_ENSURE_UINT_TYPE(tp),               \
-       .validation_type = NLA_VALIDATE_MAX,            \
-       .max = _max,                                    \
-       .network_byte_order = 1,                        \
 }
 
 #define NLA_POLICY_MASK(tp, _mask) {                   \
index 22f8bab..5db0254 100644 (file)
@@ -1889,6 +1889,13 @@ void sock_kfree_s(struct sock *sk, void *mem, int size);
 void sock_kzfree_s(struct sock *sk, void *mem, int size);
 void sk_send_sigurg(struct sock *sk);
 
+static inline void sock_replace_proto(struct sock *sk, struct proto *proto)
+{
+       if (sk->sk_socket)
+               clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
+       WRITE_ONCE(sk->sk_prot, proto);
+}
+
 struct sockcm_cookie {
        u64 transmit_time;
        u32 mark;
index 3220b0a..cd9f5a6 100644 (file)
@@ -2429,8 +2429,11 @@ int enable_kprobe(struct kprobe *kp)
        if (!kprobes_all_disarmed && kprobe_disabled(p)) {
                p->flags &= ~KPROBE_FLAG_DISABLED;
                ret = arm_kprobe(p);
-               if (ret)
+               if (ret) {
                        p->flags |= KPROBE_FLAG_DISABLED;
+                       if (p != kp)
+                               kp->flags |= KPROBE_FLAG_DISABLED;
+               }
        }
 out:
        mutex_unlock(&kprobe_mutex);
index aac63ca..e8143e3 100644 (file)
@@ -141,6 +141,8 @@ static int fprobe_init_rethook(struct fprobe *fp, int num)
                return -E2BIG;
 
        fp->rethook = rethook_alloc((void *)fp, fprobe_exit_handler);
+       if (!fp->rethook)
+               return -ENOMEM;
        for (i = 0; i < size; i++) {
                struct fprobe_rethook_node *node;
 
@@ -301,7 +303,8 @@ int unregister_fprobe(struct fprobe *fp)
 {
        int ret;
 
-       if (!fp || fp->ops.func != fprobe_handler)
+       if (!fp || (fp->ops.saved_func != fprobe_handler &&
+                   fp->ops.saved_func != fprobe_kprobe_handler))
                return -EINVAL;
 
        /*
index fbf2543..7dc0236 100644 (file)
@@ -3028,18 +3028,8 @@ int ftrace_shutdown(struct ftrace_ops *ops, int command)
                command |= FTRACE_UPDATE_TRACE_FUNC;
        }
 
-       if (!command || !ftrace_enabled) {
-               /*
-                * If these are dynamic or per_cpu ops, they still
-                * need their data freed. Since, function tracing is
-                * not currently active, we can just free them
-                * without synchronizing all CPUs.
-                */
-               if (ops->flags & FTRACE_OPS_FL_DYNAMIC)
-                       goto free_ops;
-
-               return 0;
-       }
+       if (!command || !ftrace_enabled)
+               goto out;
 
        /*
         * If the ops uses a trampoline, then it needs to be
@@ -3076,6 +3066,7 @@ int ftrace_shutdown(struct ftrace_ops *ops, int command)
        removed_ops = NULL;
        ops->flags &= ~FTRACE_OPS_FL_REMOVING;
 
+out:
        /*
         * Dynamic ops may be freed, we must make sure that all
         * callers are done before leaving this function.
@@ -3103,7 +3094,6 @@ int ftrace_shutdown(struct ftrace_ops *ops, int command)
                if (IS_ENABLED(CONFIG_PREEMPTION))
                        synchronize_rcu_tasks();
 
- free_ops:
                ftrace_trampoline_free(ops);
        }
 
index 80e04a1..d81f7c5 100644 (file)
@@ -100,20 +100,20 @@ static int __init test_gen_kprobe_cmd(void)
                                         KPROBE_GEN_TEST_FUNC,
                                         KPROBE_GEN_TEST_ARG0, KPROBE_GEN_TEST_ARG1);
        if (ret)
-               goto free;
+               goto out;
 
        /* Use kprobe_event_add_fields to add the rest of the fields */
 
        ret = kprobe_event_add_fields(&cmd, KPROBE_GEN_TEST_ARG2, KPROBE_GEN_TEST_ARG3);
        if (ret)
-               goto free;
+               goto out;
 
        /*
         * This actually creates the event.
         */
        ret = kprobe_event_gen_cmd_end(&cmd);
        if (ret)
-               goto free;
+               goto out;
 
        /*
         * Now get the gen_kprobe_test event file.  We need to prevent
@@ -136,13 +136,11 @@ static int __init test_gen_kprobe_cmd(void)
                goto delete;
        }
  out:
+       kfree(buf);
        return ret;
  delete:
        /* We got an error after creating the event, delete it */
        ret = kprobe_event_delete("gen_kprobe_test");
- free:
-       kfree(buf);
-
        goto out;
 }
 
@@ -170,14 +168,14 @@ static int __init test_gen_kretprobe_cmd(void)
                                            KPROBE_GEN_TEST_FUNC,
                                            "$retval");
        if (ret)
-               goto free;
+               goto out;
 
        /*
         * This actually creates the event.
         */
        ret = kretprobe_event_gen_cmd_end(&cmd);
        if (ret)
-               goto free;
+               goto out;
 
        /*
         * Now get the gen_kretprobe_test event file.  We need to
@@ -201,13 +199,11 @@ static int __init test_gen_kretprobe_cmd(void)
                goto delete;
        }
  out:
+       kfree(buf);
        return ret;
  delete:
        /* We got an error after creating the event, delete it */
        ret = kprobe_event_delete("gen_kretprobe_test");
- free:
-       kfree(buf);
-
        goto out;
 }
 
index 199759c..9712083 100644 (file)
@@ -937,6 +937,9 @@ void ring_buffer_wake_waiters(struct trace_buffer *buffer, int cpu)
        struct ring_buffer_per_cpu *cpu_buffer;
        struct rb_irq_work *rbwork;
 
+       if (!buffer)
+               return;
+
        if (cpu == RING_BUFFER_ALL_CPUS) {
 
                /* Wake up individual ones too. One level recursion */
@@ -945,7 +948,15 @@ void ring_buffer_wake_waiters(struct trace_buffer *buffer, int cpu)
 
                rbwork = &buffer->irq_work;
        } else {
+               if (WARN_ON_ONCE(!buffer->buffers))
+                       return;
+               if (WARN_ON_ONCE(cpu >= nr_cpu_ids))
+                       return;
+
                cpu_buffer = buffer->buffers[cpu];
+               /* The CPU buffer may not have been initialized yet */
+               if (!cpu_buffer)
+                       return;
                rbwork = &cpu_buffer->irq_work;
        }
 
index 40f22b1..b67a53e 100644 (file)
@@ -124,10 +124,12 @@ void nla_get_range_unsigned(const struct nla_policy *pt,
                range->max = U8_MAX;
                break;
        case NLA_U16:
+       case NLA_BE16:
        case NLA_BINARY:
                range->max = U16_MAX;
                break;
        case NLA_U32:
+       case NLA_BE32:
                range->max = U32_MAX;
                break;
        case NLA_U64:
@@ -159,31 +161,6 @@ void nla_get_range_unsigned(const struct nla_policy *pt,
        }
 }
 
-static u64 nla_get_attr_bo(const struct nla_policy *pt,
-                          const struct nlattr *nla)
-{
-       switch (pt->type) {
-       case NLA_U16:
-               if (pt->network_byte_order)
-                       return ntohs(nla_get_be16(nla));
-
-               return nla_get_u16(nla);
-       case NLA_U32:
-               if (pt->network_byte_order)
-                       return ntohl(nla_get_be32(nla));
-
-               return nla_get_u32(nla);
-       case NLA_U64:
-               if (pt->network_byte_order)
-                       return be64_to_cpu(nla_get_be64(nla));
-
-               return nla_get_u64(nla);
-       }
-
-       WARN_ON_ONCE(1);
-       return 0;
-}
-
 static int nla_validate_range_unsigned(const struct nla_policy *pt,
                                       const struct nlattr *nla,
                                       struct netlink_ext_ack *extack,
@@ -197,9 +174,13 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt,
                value = nla_get_u8(nla);
                break;
        case NLA_U16:
+               value = nla_get_u16(nla);
+               break;
        case NLA_U32:
+               value = nla_get_u32(nla);
+               break;
        case NLA_U64:
-               value = nla_get_attr_bo(pt, nla);
+               value = nla_get_u64(nla);
                break;
        case NLA_MSECS:
                value = nla_get_u64(nla);
@@ -207,6 +188,12 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt,
        case NLA_BINARY:
                value = nla_len(nla);
                break;
+       case NLA_BE16:
+               value = ntohs(nla_get_be16(nla));
+               break;
+       case NLA_BE32:
+               value = ntohl(nla_get_be32(nla));
+               break;
        default:
                return -EINVAL;
        }
@@ -334,6 +321,8 @@ static int nla_validate_int_range(const struct nla_policy *pt,
        case NLA_U64:
        case NLA_MSECS:
        case NLA_BINARY:
+       case NLA_BE16:
+       case NLA_BE32:
                return nla_validate_range_unsigned(pt, nla, extack, validate);
        case NLA_S8:
        case NLA_S16:
index 7a59c44..a6c1286 100644 (file)
@@ -1067,10 +1067,21 @@ int hci_conn_del(struct hci_conn *conn)
                        hdev->acl_cnt += conn->sent;
        } else {
                struct hci_conn *acl = conn->link;
+
                if (acl) {
                        acl->link = NULL;
                        hci_conn_drop(acl);
                }
+
+               /* Unacked ISO frames */
+               if (conn->type == ISO_LINK) {
+                       if (hdev->iso_pkts)
+                               hdev->iso_cnt += conn->sent;
+                       else if (hdev->le_pkts)
+                               hdev->le_cnt += conn->sent;
+                       else
+                               hdev->acl_cnt += conn->sent;
+               }
        }
 
        if (conn->amp_mgr)
@@ -1761,6 +1772,7 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
                if (!cis)
                        return ERR_PTR(-ENOMEM);
                cis->cleanup = cis_cleanup;
+               cis->dst_type = dst_type;
        }
 
        if (cis->state == BT_CONNECTED)
@@ -2140,12 +2152,6 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
        struct hci_conn *le;
        struct hci_conn *cis;
 
-       /* Convert from ISO socket address type to HCI address type  */
-       if (dst_type == BDADDR_LE_PUBLIC)
-               dst_type = ADDR_LE_DEV_PUBLIC;
-       else
-               dst_type = ADDR_LE_DEV_RANDOM;
-
        if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
                le = hci_connect_le(hdev, dst, dst_type, false,
                                    BT_SECURITY_LOW,
index 613039b..f825857 100644 (file)
@@ -235,6 +235,14 @@ static int iso_chan_add(struct iso_conn *conn, struct sock *sk,
        return err;
 }
 
+static inline u8 le_addr_type(u8 bdaddr_type)
+{
+       if (bdaddr_type == BDADDR_LE_PUBLIC)
+               return ADDR_LE_DEV_PUBLIC;
+       else
+               return ADDR_LE_DEV_RANDOM;
+}
+
 static int iso_connect_bis(struct sock *sk)
 {
        struct iso_conn *conn;
@@ -328,14 +336,16 @@ static int iso_connect_cis(struct sock *sk)
        /* Just bind if DEFER_SETUP has been set */
        if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
                hcon = hci_bind_cis(hdev, &iso_pi(sk)->dst,
-                                   iso_pi(sk)->dst_type, &iso_pi(sk)->qos);
+                                   le_addr_type(iso_pi(sk)->dst_type),
+                                   &iso_pi(sk)->qos);
                if (IS_ERR(hcon)) {
                        err = PTR_ERR(hcon);
                        goto done;
                }
        } else {
                hcon = hci_connect_cis(hdev, &iso_pi(sk)->dst,
-                                      iso_pi(sk)->dst_type, &iso_pi(sk)->qos);
+                                      le_addr_type(iso_pi(sk)->dst_type),
+                                      &iso_pi(sk)->qos);
                if (IS_ERR(hcon)) {
                        err = PTR_ERR(hcon);
                        goto done;
index 1f34b82..9c24947 100644 (file)
@@ -1990,7 +1990,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
                if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
                        continue;
 
-               if (c->psm == psm) {
+               if (c->chan_type != L2CAP_CHAN_FIXED && c->psm == psm) {
                        int src_match, dst_match;
                        int src_any, dst_any;
 
@@ -3764,7 +3764,8 @@ done:
                        l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
                                           sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
 
-                       if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
+                       if (remote_efs &&
+                           test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
                                chan->remote_id = efs.id;
                                chan->remote_stype = efs.stype;
                                chan->remote_msdu = le16_to_cpu(efs.msdu);
@@ -5813,6 +5814,19 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
        BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
               scid, mtu, mps);
 
+       /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
+        * page 1059:
+        *
+        * Valid range: 0x0001-0x00ff
+        *
+        * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
+        */
+       if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
+               result = L2CAP_CR_LE_BAD_PSM;
+               chan = NULL;
+               goto response;
+       }
+
        /* Check if we have socket listening on psm */
        pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
                                         &conn->hcon->dst, LE_LINK);
@@ -6001,6 +6015,18 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
 
        psm  = req->psm;
 
+       /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
+        * page 1059:
+        *
+        * Valid range: 0x0001-0x00ff
+        *
+        * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
+        */
+       if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
+               result = L2CAP_CR_LE_BAD_PSM;
+               goto response;
+       }
+
        BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps);
 
        memset(&pdu, 0, sizeof(pdu));
@@ -6885,6 +6911,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
                               struct l2cap_ctrl *control,
                               struct sk_buff *skb, u8 event)
 {
+       struct l2cap_ctrl local_control;
        int err = 0;
        bool skb_in_use = false;
 
@@ -6909,15 +6936,32 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
                        chan->buffer_seq = chan->expected_tx_seq;
                        skb_in_use = true;
 
+                       /* l2cap_reassemble_sdu may free skb, hence invalidate
+                        * control, so make a copy in advance to use it after
+                        * l2cap_reassemble_sdu returns and to avoid the race
+                        * condition, for example:
+                        *
+                        * The current thread calls:
+                        *   l2cap_reassemble_sdu
+                        *     chan->ops->recv == l2cap_sock_recv_cb
+                        *       __sock_queue_rcv_skb
+                        * Another thread calls:
+                        *   bt_sock_recvmsg
+                        *     skb_recv_datagram
+                        *     skb_free_datagram
+                        * Then the current thread tries to access control, but
+                        * it was freed by skb_free_datagram.
+                        */
+                       local_control = *control;
                        err = l2cap_reassemble_sdu(chan, skb, control);
                        if (err)
                                break;
 
-                       if (control->final) {
+                       if (local_control.final) {
                                if (!test_and_clear_bit(CONN_REJ_ACT,
                                                        &chan->conn_state)) {
-                                       control->final = 0;
-                                       l2cap_retransmit_all(chan, control);
+                                       local_control.final = 0;
+                                       l2cap_retransmit_all(chan, &local_control);
                                        l2cap_ertm_send(chan);
                                }
                        }
@@ -7297,11 +7341,27 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
 static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
                           struct sk_buff *skb)
 {
+       /* l2cap_reassemble_sdu may free skb, hence invalidate control, so store
+        * the txseq field in advance to use it after l2cap_reassemble_sdu
+        * returns and to avoid the race condition, for example:
+        *
+        * The current thread calls:
+        *   l2cap_reassemble_sdu
+        *     chan->ops->recv == l2cap_sock_recv_cb
+        *       __sock_queue_rcv_skb
+        * Another thread calls:
+        *   bt_sock_recvmsg
+        *     skb_recv_datagram
+        *     skb_free_datagram
+        * Then the current thread tries to access control, but it was freed by
+        * skb_free_datagram.
+        */
+       u16 txseq = control->txseq;
+
        BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
               chan->rx_state);
 
-       if (l2cap_classify_txseq(chan, control->txseq) ==
-           L2CAP_TXSEQ_EXPECTED) {
+       if (l2cap_classify_txseq(chan, txseq) == L2CAP_TXSEQ_EXPECTED) {
                l2cap_pass_to_tx(chan, control);
 
                BT_DBG("buffer_seq %u->%u", chan->buffer_seq,
@@ -7324,8 +7384,8 @@ static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
                }
        }
 
-       chan->last_acked_seq = control->txseq;
-       chan->expected_tx_seq = __next_seq(chan, control->txseq);
+       chan->last_acked_seq = txseq;
+       chan->expected_tx_seq = __next_seq(chan, txseq);
 
        return 0;
 }
@@ -7581,6 +7641,7 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
                                return;
                        }
 
+                       l2cap_chan_hold(chan);
                        l2cap_chan_lock(chan);
                } else {
                        BT_DBG("unknown cid 0x%4.4x", cid);
@@ -8426,9 +8487,8 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
                 * expected length.
                 */
                if (skb->len < L2CAP_LEN_SIZE) {
-                       if (l2cap_recv_frag(conn, skb, conn->mtu) < 0)
-                               goto drop;
-                       return;
+                       l2cap_recv_frag(conn, skb, conn->mtu);
+                       break;
                }
 
                len = get_unaligned_le16(skb->data) + L2CAP_HDR_SIZE;
@@ -8472,7 +8532,7 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 
                        /* Header still could not be read just continue */
                        if (conn->rx_skb->len < L2CAP_LEN_SIZE)
-                               return;
+                               break;
                }
 
                if (skb->len > conn->rx_len) {
index 5aeb364..d087fd4 100644 (file)
@@ -1332,7 +1332,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
 
        if (data[IFLA_BR_FDB_FLUSH]) {
                struct net_bridge_fdb_flush_desc desc = {
-                       .flags_mask = BR_FDB_STATIC
+                       .flags_mask = BIT(BR_FDB_STATIC)
                };
 
                br_fdb_flush(br, &desc);
index 612e367..ea73354 100644 (file)
@@ -345,7 +345,7 @@ static int set_flush(struct net_bridge *br, unsigned long val,
                     struct netlink_ext_ack *extack)
 {
        struct net_bridge_fdb_flush_desc desc = {
-               .flags_mask = BR_FDB_STATIC
+               .flags_mask = BIT(BR_FDB_STATIC)
        };
 
        br_fdb_flush(br, &desc);
index 3c4786b..a77a85e 100644 (file)
@@ -409,7 +409,7 @@ static int __neigh_ifdown(struct neigh_table *tbl, struct net_device *dev,
        write_lock_bh(&tbl->lock);
        neigh_flush_dev(tbl, dev, skip_perm);
        pneigh_ifdown_and_unlock(tbl, dev);
-       pneigh_queue_purge(&tbl->proxy_queue, dev_net(dev));
+       pneigh_queue_purge(&tbl->proxy_queue, dev ? dev_net(dev) : NULL);
        if (skb_queue_empty_lockless(&tbl->proxy_queue))
                del_timer_sync(&tbl->proxy_timer);
        return 0;
index af0e2c0..e504a18 100644 (file)
@@ -1409,9 +1409,9 @@ static enum dsa_tag_protocol dsa_get_tag_protocol(struct dsa_port *dp,
 static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master,
                              const char *user_protocol)
 {
+       const struct dsa_device_ops *tag_ops = NULL;
        struct dsa_switch *ds = dp->ds;
        struct dsa_switch_tree *dst = ds->dst;
-       const struct dsa_device_ops *tag_ops;
        enum dsa_tag_protocol default_proto;
 
        /* Find out which protocol the switch would prefer. */
@@ -1434,10 +1434,17 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master,
                }
 
                tag_ops = dsa_find_tagger_by_name(user_protocol);
-       } else {
-               tag_ops = dsa_tag_driver_get(default_proto);
+               if (IS_ERR(tag_ops)) {
+                       dev_warn(ds->dev,
+                                "Failed to find a tagging driver for protocol %s, using default\n",
+                                user_protocol);
+                       tag_ops = NULL;
+               }
        }
 
+       if (!tag_ops)
+               tag_ops = dsa_tag_driver_get(default_proto);
+
        if (IS_ERR(tag_ops)) {
                if (PTR_ERR(tag_ops) == -ENOPROTOOPT)
                        return -EPROBE_DEFER;
index 3dd0239..4728087 100644 (file)
@@ -754,6 +754,8 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags,
                  (TCPF_ESTABLISHED | TCPF_SYN_RECV |
                  TCPF_CLOSE_WAIT | TCPF_CLOSE)));
 
+       if (test_bit(SOCK_SUPPORT_ZC, &sock->flags))
+               set_bit(SOCK_SUPPORT_ZC, &newsock->flags);
        sock_graft(sk2, newsock);
 
        newsock->state = SS_CONNECTED;
index a1626af..c501c32 100644 (file)
@@ -607,7 +607,7 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
                } else {
                        sk->sk_write_space = psock->saved_write_space;
                        /* Pairs with lockless read in sk_clone_lock() */
-                       WRITE_ONCE(sk->sk_prot, psock->sk_proto);
+                       sock_replace_proto(sk, psock->sk_proto);
                }
                return 0;
        }
@@ -620,7 +620,7 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
        }
 
        /* Pairs with lockless read in sk_clone_lock() */
-       WRITE_ONCE(sk->sk_prot, &tcp_bpf_prots[family][config]);
+       sock_replace_proto(sk, &tcp_bpf_prots[family][config]);
        return 0;
 }
 EXPORT_SYMBOL_GPL(tcp_bpf_update_proto);
index 7c27aa6..9ae50b1 100644 (file)
@@ -136,6 +136,9 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)
        if (icsk->icsk_ulp_ops)
                goto out_err;
 
+       if (sk->sk_socket)
+               clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
+
        err = ulp_ops->init(sk);
        if (err)
                goto out_err;
index ff15918..e5dc91d 100644 (file)
@@ -141,14 +141,14 @@ int udp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
 
        if (restore) {
                sk->sk_write_space = psock->saved_write_space;
-               WRITE_ONCE(sk->sk_prot, psock->sk_proto);
+               sock_replace_proto(sk, psock->sk_proto);
                return 0;
        }
 
        if (sk->sk_family == AF_INET6)
                udp_bpf_check_v6_needs_rebuild(psock->sk_proto);
 
-       WRITE_ONCE(sk->sk_prot, &udp_bpf_prots[family]);
+       sock_replace_proto(sk, &udp_bpf_prots[family]);
        return 0;
 }
 EXPORT_SYMBOL_GPL(udp_bpf_update_proto);
index 69252eb..2f355f0 100644 (file)
@@ -6555,10 +6555,16 @@ static void __net_exit ip6_route_net_exit(struct net *net)
 static int __net_init ip6_route_net_init_late(struct net *net)
 {
 #ifdef CONFIG_PROC_FS
-       proc_create_net("ipv6_route", 0, net->proc_net, &ipv6_route_seq_ops,
-                       sizeof(struct ipv6_route_iter));
-       proc_create_net_single("rt6_stats", 0444, net->proc_net,
-                       rt6_stats_seq_show, NULL);
+       if (!proc_create_net("ipv6_route", 0, net->proc_net,
+                            &ipv6_route_seq_ops,
+                            sizeof(struct ipv6_route_iter)))
+               return -ENOMEM;
+
+       if (!proc_create_net_single("rt6_stats", 0444, net->proc_net,
+                                   rt6_stats_seq_show, NULL)) {
+               remove_proc_entry("ipv6_route", net->proc_net);
+               return -ENOMEM;
+       }
 #endif
        return 0;
 }
index 129ec5a..bc65e5b 100644 (file)
@@ -66,6 +66,7 @@ int udpv6_init_sock(struct sock *sk)
 {
        skb_queue_head_init(&udp_sk(sk)->reader_queue);
        sk->sk_destruct = udpv6_destruct_sock;
+       set_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
        return 0;
 }
 
index 6e39130..3adc291 100644 (file)
 #define AHASH_MAX_SIZE                 (6 * AHASH_INIT_SIZE)
 /* Max muber of elements in the array block when tuned */
 #define AHASH_MAX_TUNED                        64
-
 #define AHASH_MAX(h)                   ((h)->bucketsize)
 
-/* Max number of elements can be tuned */
-#ifdef IP_SET_HASH_WITH_MULTI
-static u8
-tune_bucketsize(u8 curr, u32 multi)
-{
-       u32 n;
-
-       if (multi < curr)
-               return curr;
-
-       n = curr + AHASH_INIT_SIZE;
-       /* Currently, at listing one hash bucket must fit into a message.
-        * Therefore we have a hard limit here.
-        */
-       return n > curr && n <= AHASH_MAX_TUNED ? n : curr;
-}
-#define TUNE_BUCKETSIZE(h, multi)      \
-       ((h)->bucketsize = tune_bucketsize((h)->bucketsize, multi))
-#else
-#define TUNE_BUCKETSIZE(h, multi)
-#endif
-
 /* A hash bucket */
 struct hbucket {
        struct rcu_head rcu;    /* for call_rcu */
@@ -936,7 +913,12 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                goto set_full;
        /* Create a new slot */
        if (n->pos >= n->size) {
-               TUNE_BUCKETSIZE(h, multi);
+#ifdef IP_SET_HASH_WITH_MULTI
+               if (h->bucketsize >= AHASH_MAX_TUNED)
+                       goto set_full;
+               else if (h->bucketsize < multi)
+                       h->bucketsize += AHASH_INIT_SIZE;
+#endif
                if (n->size >= AHASH_MAX(h)) {
                        /* Trigger rehashing */
                        mtype_data_next(&h->next, d);
index f9b16f2..fdacbc3 100644 (file)
@@ -599,13 +599,19 @@ static const struct seq_operations ip_vs_app_seq_ops = {
 int __net_init ip_vs_app_net_init(struct netns_ipvs *ipvs)
 {
        INIT_LIST_HEAD(&ipvs->app_list);
-       proc_create_net("ip_vs_app", 0, ipvs->net->proc_net, &ip_vs_app_seq_ops,
-                       sizeof(struct seq_net_private));
+#ifdef CONFIG_PROC_FS
+       if (!proc_create_net("ip_vs_app", 0, ipvs->net->proc_net,
+                            &ip_vs_app_seq_ops,
+                            sizeof(struct seq_net_private)))
+               return -ENOMEM;
+#endif
        return 0;
 }
 
 void __net_exit ip_vs_app_net_cleanup(struct netns_ipvs *ipvs)
 {
        unregister_ip_vs_app(ipvs, NULL /* all */);
+#ifdef CONFIG_PROC_FS
        remove_proc_entry("ip_vs_app", ipvs->net->proc_net);
+#endif
 }
index 8c04bb5..13534e0 100644 (file)
@@ -1265,8 +1265,8 @@ static inline int todrop_entry(struct ip_vs_conn *cp)
         * The drop rate array needs tuning for real environments.
         * Called from timer bh only => no locking
         */
-       static const char todrop_rate[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
-       static char todrop_counter[9] = {0};
+       static const signed char todrop_rate[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
+       static signed char todrop_counter[9] = {0};
        int i;
 
        /* if the conn entry hasn't lasted for 60 seconds, don't drop it.
@@ -1447,20 +1447,36 @@ int __net_init ip_vs_conn_net_init(struct netns_ipvs *ipvs)
 {
        atomic_set(&ipvs->conn_count, 0);
 
-       proc_create_net("ip_vs_conn", 0, ipvs->net->proc_net,
-                       &ip_vs_conn_seq_ops, sizeof(struct ip_vs_iter_state));
-       proc_create_net("ip_vs_conn_sync", 0, ipvs->net->proc_net,
-                       &ip_vs_conn_sync_seq_ops,
-                       sizeof(struct ip_vs_iter_state));
+#ifdef CONFIG_PROC_FS
+       if (!proc_create_net("ip_vs_conn", 0, ipvs->net->proc_net,
+                            &ip_vs_conn_seq_ops,
+                            sizeof(struct ip_vs_iter_state)))
+               goto err_conn;
+
+       if (!proc_create_net("ip_vs_conn_sync", 0, ipvs->net->proc_net,
+                            &ip_vs_conn_sync_seq_ops,
+                            sizeof(struct ip_vs_iter_state)))
+               goto err_conn_sync;
+#endif
+
        return 0;
+
+#ifdef CONFIG_PROC_FS
+err_conn_sync:
+       remove_proc_entry("ip_vs_conn", ipvs->net->proc_net);
+err_conn:
+       return -ENOMEM;
+#endif
 }
 
 void __net_exit ip_vs_conn_net_cleanup(struct netns_ipvs *ipvs)
 {
        /* flush all the connection entries first */
        ip_vs_conn_flush(ipvs);
+#ifdef CONFIG_PROC_FS
        remove_proc_entry("ip_vs_conn", ipvs->net->proc_net);
        remove_proc_entry("ip_vs_conn_sync", ipvs->net->proc_net);
+#endif
 }
 
 int __init ip_vs_conn_init(void)
index 18319a6..e29e4cc 100644 (file)
@@ -1152,7 +1152,16 @@ static int __init nf_nat_init(void)
        WARN_ON(nf_nat_hook != NULL);
        RCU_INIT_POINTER(nf_nat_hook, &nat_hook);
 
-       return register_nf_nat_bpf();
+       ret = register_nf_nat_bpf();
+       if (ret < 0) {
+               RCU_INIT_POINTER(nf_nat_hook, NULL);
+               nf_ct_helper_expectfn_unregister(&follow_master_nat);
+               synchronize_net();
+               unregister_pernet_subsys(&nat_net_ops);
+               kvfree(nf_nat_bysource);
+       }
+
+       return ret;
 }
 
 static void __exit nf_nat_cleanup(void)
index 58d9cbc..76bd4d0 100644 (file)
@@ -8465,9 +8465,6 @@ static void nft_commit_release(struct nft_trans *trans)
                nf_tables_chain_destroy(&trans->ctx);
                break;
        case NFT_MSG_DELRULE:
-               if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
-                       nft_flow_rule_destroy(nft_trans_flow_rule(trans));
-
                nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
                break;
        case NFT_MSG_DELSET:
@@ -8973,6 +8970,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
                        nft_rule_expr_deactivate(&trans->ctx,
                                                 nft_trans_rule(trans),
                                                 NFT_TRANS_COMMIT);
+
+                       if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
+                               nft_flow_rule_destroy(nft_trans_flow_rule(trans));
                        break;
                case NFT_MSG_NEWSET:
                        nft_clear(net, nft_trans_set(trans));
@@ -10030,6 +10030,8 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
        nft_net = nft_pernet(net);
        deleted = 0;
        mutex_lock(&nft_net->commit_mutex);
+       if (!list_empty(&nf_tables_destroy_list))
+               rcu_barrier();
 again:
        list_for_each_entry(table, &nft_net->tables, list) {
                if (nft_table_has_owner(table) &&
index 088244f..4edd899 100644 (file)
@@ -173,10 +173,10 @@ static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = {
        [NFTA_PAYLOAD_SREG]             = { .type = NLA_U32 },
        [NFTA_PAYLOAD_DREG]             = { .type = NLA_U32 },
        [NFTA_PAYLOAD_BASE]             = { .type = NLA_U32 },
-       [NFTA_PAYLOAD_OFFSET]           = NLA_POLICY_MAX_BE(NLA_U32, 255),
-       [NFTA_PAYLOAD_LEN]              = NLA_POLICY_MAX_BE(NLA_U32, 255),
+       [NFTA_PAYLOAD_OFFSET]           = NLA_POLICY_MAX(NLA_BE32, 255),
+       [NFTA_PAYLOAD_LEN]              = NLA_POLICY_MAX(NLA_BE32, 255),
        [NFTA_PAYLOAD_CSUM_TYPE]        = { .type = NLA_U32 },
-       [NFTA_PAYLOAD_CSUM_OFFSET]      = NLA_POLICY_MAX_BE(NLA_U32, 255),
+       [NFTA_PAYLOAD_CSUM_OFFSET]      = NLA_POLICY_MAX(NLA_BE32, 255),
        [NFTA_PAYLOAD_CSUM_FLAGS]       = { .type = NLA_U32 },
 };
 
index 155263e..8b84869 100644 (file)
@@ -2544,6 +2544,7 @@ struct genl_family dp_vport_genl_family __ro_after_init = {
        .parallel_ops = true,
        .small_ops = dp_vport_genl_ops,
        .n_small_ops = ARRAY_SIZE(dp_vport_genl_ops),
+       .resv_start_op = OVS_VPORT_CMD_SET + 1,
        .mcgrps = &ovs_dp_vport_multicast_group,
        .n_mcgrps = 1,
        .module = THIS_MODULE,
index 8b96a56..0f77ae8 100644 (file)
@@ -236,6 +236,9 @@ void rose_transmit_clear_request(struct rose_neigh *neigh, unsigned int lci, uns
        unsigned char *dptr;
        int len;
 
+       if (!neigh->dev)
+               return;
+
        len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 3;
 
        if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
index a5a401f..9812932 100644 (file)
@@ -72,6 +72,7 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 {
        struct red_sched_data *q = qdisc_priv(sch);
        struct Qdisc *child = q->qdisc;
+       unsigned int len;
        int ret;
 
        q->vars.qavg = red_calc_qavg(&q->parms,
@@ -126,9 +127,10 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                break;
        }
 
+       len = qdisc_pkt_len(skb);
        ret = qdisc_enqueue(skb, child, to_free);
        if (likely(ret == NET_XMIT_SUCCESS)) {
-               qdisc_qstats_backlog_inc(sch, skb);
+               sch->qstats.backlog += len;
                sch->q.qlen++;
        } else if (net_xmit_drop_count(ret)) {
                q->stats.pdrop++;
index 3ccbf3c..e12d4fa 100644 (file)
@@ -3380,14 +3380,14 @@ static int __init smc_init(void)
 
        rc = register_pernet_subsys(&smc_net_stat_ops);
        if (rc)
-               return rc;
+               goto out_pernet_subsys;
 
        smc_ism_init();
        smc_clc_init();
 
        rc = smc_nl_init();
        if (rc)
-               goto out_pernet_subsys;
+               goto out_pernet_subsys_stat;
 
        rc = smc_pnet_init();
        if (rc)
@@ -3480,6 +3480,8 @@ out_pnet:
        smc_pnet_exit();
 out_nl:
        smc_nl_exit();
+out_pernet_subsys_stat:
+       unregister_pernet_subsys(&smc_net_stat_ops);
 out_pernet_subsys:
        unregister_pernet_subsys(&smc_net_ops);
 
index 7cf14c6..e9bf155 100644 (file)
@@ -145,12 +145,12 @@ int unix_dgram_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool re
 
        if (restore) {
                sk->sk_write_space = psock->saved_write_space;
-               WRITE_ONCE(sk->sk_prot, psock->sk_proto);
+               sock_replace_proto(sk, psock->sk_proto);
                return 0;
        }
 
        unix_dgram_bpf_check_needs_rebuild(psock->sk_proto);
-       WRITE_ONCE(sk->sk_prot, &unix_dgram_bpf_prot);
+       sock_replace_proto(sk, &unix_dgram_bpf_prot);
        return 0;
 }
 
@@ -158,12 +158,12 @@ int unix_stream_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool r
 {
        if (restore) {
                sk->sk_write_space = psock->saved_write_space;
-               WRITE_ONCE(sk->sk_prot, psock->sk_proto);
+               sock_replace_proto(sk, psock->sk_proto);
                return 0;
        }
 
        unix_stream_bpf_check_needs_rebuild(psock->sk_proto);
-       WRITE_ONCE(sk->sk_prot, &unix_stream_bpf_prot);
+       sock_replace_proto(sk, &unix_stream_bpf_prot);
        return 0;
 }
 
index ee41870..884eca7 100644 (file)
@@ -1905,8 +1905,11 @@ static int vsock_connectible_wait_data(struct sock *sk,
        err = 0;
        transport = vsk->transport;
 
-       while ((data = vsock_connectible_has_data(vsk)) == 0) {
+       while (1) {
                prepare_to_wait(sk_sleep(sk), wait, TASK_INTERRUPTIBLE);
+               data = vsock_connectible_has_data(vsk);
+               if (data != 0)
+                       break;
 
                if (sk->sk_err != 0 ||
                    (sk->sk_shutdown & RCV_SHUTDOWN) ||
@@ -2092,8 +2095,6 @@ vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
        const struct vsock_transport *transport;
        int err;
 
-       DEFINE_WAIT(wait);
-
        sk = sock->sk;
        vsk = vsock_sk(sk);
        err = 0;
index 6632bff..348e2db 100644 (file)
@@ -3,7 +3,6 @@
 # First run: make -C ../../../.. headers_install
 
 CFLAGS += -Wall -O2 $(KHDR_INCLUDES)
-LDLIBS += -lcap
 
 LOCAL_HDRS += common.h
 
@@ -13,10 +12,12 @@ TEST_GEN_PROGS := $(src_test:.c=)
 
 TEST_GEN_PROGS_EXTENDED := true
 
-# Static linking for short targets:
+# Short targets:
+$(TEST_GEN_PROGS): LDLIBS += -lcap
 $(TEST_GEN_PROGS_EXTENDED): LDFLAGS += -static
 
 include ../lib.mk
 
-# Static linking for targets with $(OUTPUT)/ prefix:
+# Targets with $(OUTPUT)/ prefix:
+$(TEST_GEN_PROGS): LDLIBS += -lcap
 $(TEST_GEN_PROGS_EXTENDED): LDFLAGS += -static
index f4a2f28..778b6cd 100644 (file)
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
-CFLAGS += -g -I../../../../usr/include/ -pthread
+CFLAGS += -g -I../../../../usr/include/ -pthread -Wall
 
 TEST_GEN_PROGS := pidfd_test pidfd_fdinfo_test pidfd_open_test \
        pidfd_poll_test pidfd_wait pidfd_getfd_test pidfd_setns_test
index 9a2d649..e2dd4ed 100644 (file)
@@ -413,7 +413,7 @@ static void poll_pidfd(const char *test_name, int pidfd)
 
        c = epoll_wait(epoll_fd, events, MAX_EVENTS, 5000);
        if (c != 1 || !(events[0].events & EPOLLIN))
-               ksft_exit_fail_msg("%s test: Unexpected epoll_wait result (c=%d, events=%x) ",
+               ksft_exit_fail_msg("%s test: Unexpected epoll_wait result (c=%d, events=%x) "
                                   "(errno %d)\n",
                                   test_name, c, events[0].events, errno);
 
@@ -435,6 +435,8 @@ static int child_poll_exec_test(void *args)
         */
        while (1)
                sleep(1);
+
+       return 0;
 }
 
 static void test_pidfd_poll_exec(int use_waitpid)
index 070c1c8..0dcb836 100644 (file)
@@ -95,20 +95,28 @@ TEST(wait_states)
                .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
                .exit_signal = SIGCHLD,
        };
+       int pfd[2];
        pid_t pid;
        siginfo_t info = {
                .si_signo = 0,
        };
 
+       ASSERT_EQ(pipe(pfd), 0);
        pid = sys_clone3(&args);
        ASSERT_GE(pid, 0);
 
        if (pid == 0) {
+               char buf[2];
+
+               close(pfd[1]);
                kill(getpid(), SIGSTOP);
+               ASSERT_EQ(read(pfd[0], buf, 1), 1);
+               close(pfd[0]);
                kill(getpid(), SIGSTOP);
                exit(EXIT_SUCCESS);
        }
 
+       close(pfd[0]);
        ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
        ASSERT_EQ(info.si_signo, SIGCHLD);
        ASSERT_EQ(info.si_code, CLD_STOPPED);
@@ -117,6 +125,8 @@ TEST(wait_states)
        ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
 
        ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL), 0);
+       ASSERT_EQ(write(pfd[1], "C", 1), 1);
+       close(pfd[1]);
        ASSERT_EQ(info.si_signo, SIGCHLD);
        ASSERT_EQ(info.si_code, CLD_CONTINUED);
        ASSERT_EQ(info.si_pid, parent_tid);
@@ -138,7 +148,7 @@ TEST(wait_states)
 
 TEST(wait_nonblock)
 {
-       int pidfd, status = 0;
+       int pidfd;
        unsigned int flags = 0;
        pid_t parent_tid = -1;
        struct clone_args args = {