Merge tag 'dma-mapping-5.10-2' of git://git.infradead.org/users/hch/dma-mapping
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 31 Oct 2020 19:25:58 +0000 (12:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 31 Oct 2020 19:25:58 +0000 (12:25 -0700)
Pull dma-mapping fix from Christoph Hellwig:
 "Fix an integer overflow on 32-bit platforms in the new DMA range code
  (Geert Uytterhoeven)"

* tag 'dma-mapping-5.10-2' of git://git.infradead.org/users/hch/dma-mapping:
  dma-mapping: fix 32-bit overflow with CONFIG_ARM_LPAE=n

238 files changed:
CREDITS
Documentation/arm64/memory-tagging-extension.rst
Documentation/arm64/silicon-errata.rst
Documentation/devicetree/bindings/display/panel/mantix,mlaf057we51-x.yaml
Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
MAINTAINERS
arch/arm/boot/dts/mmp2-olpc-xo-1-75.dts
arch/arm/boot/dts/mmp3.dtsi
arch/arm/boot/dts/stm32mp157c-ed1.dts
arch/arm/boot/dts/stm32mp15xx-dkx.dtsi
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/configs/imx_v4_v5_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/multi_v5_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/mach-mvebu/coherency_ll.S
arch/arm64/Kconfig
arch/arm64/Kconfig.platforms
arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
arch/arm64/boot/dts/amlogic/meson-axg.dtsi
arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2-plus.dts
arch/arm64/boot/dts/amlogic/meson-gx.dtsi
arch/arm64/boot/dts/marvell/armada-3720-espressobin-v7-emmc.dts
arch/arm64/boot/dts/marvell/armada-3720-espressobin-v7.dts
arch/arm64/boot/dts/marvell/armada-3720-espressobin.dtsi
arch/arm64/configs/defconfig
arch/arm64/include/asm/cache.h
arch/arm64/include/asm/cpucaps.h
arch/arm64/include/asm/cputype.h
arch/arm64/include/asm/sysreg.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/cpuinfo.c
arch/arm64/kernel/efi-header.S
arch/arm64/kernel/entry.S
arch/arm64/kernel/proton-pack.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/vdso32/Makefile
arch/arm64/kernel/vmlinux.lds.S
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp/include/hyp/switch.h
arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
arch/arm64/kvm/hyp/nvhe/switch.c
arch/arm64/kvm/hyp/vhe/switch.c
arch/arm64/kvm/hypercalls.c
arch/arm64/kvm/sys_regs.c
arch/arm64/lib/memcpy.S
arch/arm64/lib/memmove.S
arch/arm64/lib/memset.S
arch/arm64/mm/fault.c
block/bio.c
block/blk-cgroup.c
block/blk-flush.c
drivers/acpi/button.c
drivers/acpi/dock.c
drivers/acpi/nfit/core.c
drivers/ata/sata_nv.c
drivers/base/core.c
drivers/block/nbd.c
drivers/block/null_blk.h
drivers/block/null_blk_zoned.c
drivers/block/xsysace.c
drivers/cpufreq/Kconfig
drivers/cpufreq/cpufreq.c
drivers/cpufreq/e_powersaver.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/longhaul.c
drivers/cpufreq/speedstep-lib.c
drivers/firmware/arm_scmi/base.c
drivers/firmware/arm_scmi/clock.c
drivers/firmware/arm_scmi/common.h
drivers/firmware/arm_scmi/driver.c
drivers/firmware/arm_scmi/notify.c
drivers/firmware/arm_scmi/perf.c
drivers/firmware/arm_scmi/reset.c
drivers/firmware/arm_scmi/sensors.c
drivers/firmware/arm_scmi/smc.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/display/Kconfig
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c
drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c
drivers/gpu/drm/amd/display/dc/os_types.h
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_gem_shmem_helper.c
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/intel_memory_region.c
drivers/gpu/drm/i915/selftests/intel_memory_region.c
drivers/gpu/drm/i915/selftests/mock_region.c
drivers/gpu/drm/nouveau/dispnv50/core.h
drivers/gpu/drm/nouveau/dispnv50/core507d.c
drivers/gpu/drm/nouveau/dispnv50/core907d.c
drivers/gpu/drm/nouveau/dispnv50/core917d.c
drivers/gpu/drm/nouveau/include/nvhw/class/cl507d.h
drivers/gpu/drm/nouveau/include/nvhw/class/cl907d.h
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_svm.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c
drivers/gpu/drm/sun4i/sun4i_frontend.c
drivers/gpu/drm/sun4i/sun4i_frontend.h
drivers/gpu/drm/v3d/v3d_gem.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vc4/vc4_drv.h
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/idle/intel_idle.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/uverbs_std_types_device.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/qedr/qedr_iw_cm.c
drivers/infiniband/sw/rxe/rxe_av.c
drivers/infiniband/sw/rxe/rxe_net.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/rtrs/rtrs-clt.c
drivers/message/fusion/mptscsih.c
drivers/mmc/host/sdhci-esdhc.h
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
drivers/net/ethernet/chelsio/cxgb4/t4_tcb.h
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
drivers/net/ethernet/pensando/ionic/ionic_dev.c
drivers/net/ethernet/pensando/ionic/ionic_dev.h
drivers/net/ethernet/pensando/ionic/ionic_fw.c
drivers/net/ethernet/pensando/ionic/ionic_lif.c
drivers/net/ethernet/pensando/ionic/ionic_main.c
drivers/net/ethernet/pensando/ionic/ionic_stats.h
drivers/net/ethernet/pensando/ionic/ionic_txrx.c
drivers/net/ethernet/pensando/ionic/ionic_txrx.h
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/gtp.c
drivers/net/ipa/gsi_trans.c
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/host/rdma.c
drivers/nvme/target/core.c
drivers/nvme/target/trace.h
drivers/pnp/core.c
drivers/s390/net/ism_drv.c
drivers/scsi/hisi_sas/hisi_sas_main.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/qla2xxx/qla_nvme.c
drivers/scsi/scsi_scan.c
drivers/soc/ti/ti_sci_pm_domains.c
drivers/tee/tee_core.c
fs/afs/cell.c
fs/afs/dir.c
fs/afs/dir_edit.c
fs/afs/file.c
fs/afs/internal.h
fs/afs/write.c
fs/afs/xattr.c
fs/btrfs/backref.c
fs/btrfs/block-group.c
fs/btrfs/ctree.h
fs/btrfs/dev-replace.c
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/qgroup.c
fs/btrfs/reada.c
fs/btrfs/tree-checker.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/fast_commit.c
fs/ext4/hash.c
fs/ext4/inode.c
fs/ext4/namei.c
fs/ext4/super.c
fs/ext4/sysfs.c
fs/io_uring.c
include/asm-generic/uaccess.h
include/drm/drm_dp_helper.h
include/drm/drm_edid.h
include/drm/drm_print.h
include/linux/arm-smccc.h
include/linux/cpufreq.h
include/linux/jbd2.h
include/linux/jhash.h
include/linux/mlx5/driver.h
include/linux/module.h
include/linux/signal.h
include/rdma/rdma_cm.h
include/trace/events/afs.h
kernel/power/process.c
kernel/sched/cpufreq_schedutil.c
kernel/trace/trace_events_synth.c
lib/scatterlist.c
net/core/devlink.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/mptcp/protocol.c
net/rds/ib_cm.c
net/sched/act_mpls.c
net/sched/cls_api.c
net/sched/sch_netem.c
net/smc/af_smc.c
net/smc/smc_core.c
net/tipc/msg.c
net/vmw_vsock/af_vsock.c
tools/testing/selftests/arm64/mte/check_buffer_fill.c
tools/testing/selftests/arm64/mte/check_child_memory.c
tools/testing/selftests/arm64/mte/check_ksm_options.c
tools/testing/selftests/arm64/mte/check_mmap_options.c
tools/testing/selftests/arm64/mte/check_tags_inclusion.c
tools/testing/selftests/arm64/mte/check_user_mem.c

diff --git a/CREDITS b/CREDITS
index cb02b99..8592e45 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1910,6 +1910,15 @@ S: 660 Harvard Ave. #7
 S: Santa Clara, CA 95051
 S: USA
 
+N: Kukjin Kim
+E: kgene@kernel.org
+D: Samsung S3C, S5P and Exynos ARM architectures
+
+N: Sangbeom Kim
+E: sbkim73@samsung.com
+D: Samsung SoC Audio (ASoC) drivers
+D: Samsung PMIC (RTC, regulators, MFD) drivers
+
 N: Russell King
 E: rmk@arm.linux.org.uk
 D: Linux/arm integrator, maintainer & hacker
index 034d37c..b540178 100644 (file)
@@ -102,7 +102,9 @@ applications.
 system call) are not checked if the user thread tag checking mode is
 ``PR_MTE_TCF_NONE`` or ``PR_MTE_TCF_ASYNC``. If the tag checking mode is
 ``PR_MTE_TCF_SYNC``, the kernel makes a best effort to check its user
-address accesses, however it cannot always guarantee it.
+address accesses, however it cannot always guarantee it. Kernel accesses
+to user addresses are always performed with an effective ``PSTATE.TCO``
+value of zero, regardless of the user configuration.
 
 Excluding Tags in the ``IRG``, ``ADDG`` and ``SUBG`` instructions
 -----------------------------------------------------------------
index d358780..7195102 100644 (file)
@@ -90,6 +90,8 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A76      | #1463225        | ARM64_ERRATUM_1463225       |
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A77      | #1508412        | ARM64_ERRATUM_1508412       |
++----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Neoverse-N1     | #1188873,1418040| ARM64_ERRATUM_1418040       |
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Neoverse-N1     | #1349291        | N/A                         |
index 937323c..51f4232 100644 (file)
@@ -37,6 +37,9 @@ properties:
 
   reset-gpios: true
 
+  'mantix,tp-rstn-gpios':
+    description: second reset line that triggers DSI config load
+
   backlight: true
 
 required:
@@ -63,6 +66,7 @@ examples:
             avee-supply = <&reg_avee>;
             vddi-supply = <&reg_1v8_p>;
             reset-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
+            mantix,tp-rstn-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
             backlight = <&backlight>;
         };
     };
index 6ebcbc1..b66a07e 100644 (file)
@@ -34,6 +34,9 @@ properties:
       - const: allwinner,sun8i-a23-system-control
       - const: allwinner,sun8i-h3-system-control
       - items:
+          - const: allwinner,sun8i-v3s-system-control
+          - const: allwinner,sun8i-h3-system-control
+      - items:
           - const: allwinner,sun8i-r40-system-control
           - const: allwinner,sun4i-a10-system-control
       - const: allwinner,sun50i-a64-sram-controller
index e73636b..608fc84 100644 (file)
@@ -2375,7 +2375,6 @@ F:        sound/soc/rockchip/
 N:     rockchip
 
 ARM/SAMSUNG EXYNOS ARM ARCHITECTURES
-M:     Kukjin Kim <kgene@kernel.org>
 M:     Krzysztof Kozlowski <krzk@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-samsung-soc@vger.kernel.org
@@ -2642,10 +2641,8 @@ F:       drivers/pinctrl/visconti/
 N:     visconti
 
 ARM/UNIPHIER ARCHITECTURE
-M:     Masahiro Yamada <yamada.masahiro@socionext.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-uniphier.git
+S:     Orphan
 F:     Documentation/devicetree/bindings/arm/socionext/uniphier.yaml
 F:     Documentation/devicetree/bindings/gpio/socionext,uniphier-gpio.yaml
 F:     Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.yaml
@@ -5006,9 +5003,8 @@ T:        git git://linuxtv.org/media_tree.git
 F:     drivers/media/platform/sti/delta
 
 DENALI NAND DRIVER
-M:     Masahiro Yamada <yamada.masahiro@socionext.com>
 L:     linux-mtd@lists.infradead.org
-S:     Supported
+S:     Orphan
 F:     drivers/mtd/nand/raw/denali*
 
 DESIGNWARE EDMA CORE IP DRIVER
@@ -15372,7 +15368,6 @@ F:      security/safesetid/
 
 SAMSUNG AUDIO (ASoC) DRIVERS
 M:     Krzysztof Kozlowski <krzk@kernel.org>
-M:     Sangbeom Kim <sbkim73@samsung.com>
 M:     Sylwester Nawrocki <s.nawrocki@samsung.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
@@ -15407,7 +15402,6 @@ S:      Maintained
 F:     drivers/platform/x86/samsung-laptop.c
 
 SAMSUNG MULTIFUNCTION PMIC DEVICE DRIVERS
-M:     Sangbeom Kim <sbkim73@samsung.com>
 M:     Krzysztof Kozlowski <krzk@kernel.org>
 M:     Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
 L:     linux-kernel@vger.kernel.org
@@ -15489,7 +15483,6 @@ F:      include/linux/clk/samsung.h
 F:     include/linux/platform_data/clk-s3c2410.h
 
 SAMSUNG SPI DRIVERS
-M:     Kukjin Kim <kgene@kernel.org>
 M:     Krzysztof Kozlowski <krzk@kernel.org>
 M:     Andi Shyti <andi@etezian.org>
 L:     linux-spi@vger.kernel.org
index f1a4115..adde62d 100644 (file)
        /delete-property/ #size-cells;
        spi-slave;
        status = "okay";
-       ready-gpio = <&gpio 125 GPIO_ACTIVE_HIGH>;
+       ready-gpios = <&gpio 125 GPIO_ACTIVE_HIGH>;
 
        slave {
                compatible = "olpc,xo1.75-ec";
                spi-cpha;
-               cmd-gpio = <&gpio 155 GPIO_ACTIVE_HIGH>;
+               cmd-gpios = <&gpio 155 GPIO_ACTIVE_HIGH>;
        };
 };
 
index cc4efd0..4ae630d 100644 (file)
                                interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&soc_clocks MMP2_CLK_CCIC0>;
                                clock-names = "axi";
+                               power-domains = <&soc_clocks MMP3_POWER_DOMAIN_CAMERA>;
                                #clock-cells = <0>;
                                clock-output-names = "mclk";
                                status = "disabled";
                                interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&soc_clocks MMP2_CLK_CCIC1>;
                                clock-names = "axi";
+                               power-domains = <&soc_clocks MMP3_POWER_DOMAIN_CAMERA>;
                                #clock-cells = <0>;
                                clock-output-names = "mclk";
                                status = "disabled";
index ca109dc..2e77cce 100644 (file)
                states = <1800000 0x1>,
                         <2900000 0x0>;
        };
+
+       vin: vin {
+               compatible = "regulator-fixed";
+               regulator-name = "vin";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
 };
 
 &adc {
 
                regulators {
                        compatible = "st,stpmic1-regulators";
+                       buck1-supply = <&vin>;
+                       buck2-supply = <&vin>;
+                       buck3-supply = <&vin>;
+                       buck4-supply = <&vin>;
                        ldo1-supply = <&v3v3>;
                        ldo2-supply = <&v3v3>;
                        ldo3-supply = <&vdd_ddr>;
+                       ldo4-supply = <&vin>;
                        ldo5-supply = <&v3v3>;
                        ldo6-supply = <&v3v3>;
+                       vref_ddr-supply = <&vin>;
+                       boost-supply = <&vin>;
                        pwr_sw1-supply = <&bst_out>;
                        pwr_sw2-supply = <&bst_out>;
 
index a530774..93398cf 100644 (file)
                dais = <&sai2a_port &sai2b_port &i2s2_port>;
                status = "okay";
        };
+
+       vin: vin {
+               compatible = "regulator-fixed";
+               regulator-name = "vin";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
 };
 
 &adc {
 
                regulators {
                        compatible = "st,stpmic1-regulators";
+                       buck1-supply = <&vin>;
+                       buck2-supply = <&vin>;
+                       buck3-supply = <&vin>;
+                       buck4-supply = <&vin>;
                        ldo1-supply = <&v3v3>;
+                       ldo2-supply = <&vin>;
                        ldo3-supply = <&vdd_ddr>;
+                       ldo4-supply = <&vin>;
+                       ldo5-supply = <&vin>;
                        ldo6-supply = <&v3v3>;
+                       vref_ddr-supply = <&vin>;
+                       boost-supply = <&vin>;
                        pwr_sw1-supply = <&bst_out>;
                        pwr_sw2-supply = <&bst_out>;
 
index 0f95a6e..1c5a666 100644 (file)
                        trips {
                                cpu_alert0: cpu-alert0 {
                                        /* milliCelsius */
-                                       temperature = <850000>;
+                                       temperature = <85000>;
                                        hysteresis = <2000>;
                                        type = "passive";
                                };
index aeb1209..bb70acc 100644 (file)
@@ -93,6 +93,7 @@ CONFIG_SPI=y
 CONFIG_SPI_IMX=y
 CONFIG_SPI_SPIDEV=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MXC=y
 CONFIG_W1=y
 CONFIG_W1_MASTER_MXC=y
 CONFIG_W1_SLAVE_THERM=y
index 0fa79bd..221f5c3 100644 (file)
@@ -217,6 +217,7 @@ CONFIG_GPIO_PCA953X=y
 CONFIG_GPIO_PCF857X=y
 CONFIG_GPIO_STMPE=y
 CONFIG_GPIO_74X164=y
+CONFIG_GPIO_MXC=y
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_SYSCON=y
 CONFIG_POWER_RESET_SYSCON_POWEROFF=y
index 70b709a..e00be9f 100644 (file)
@@ -166,6 +166,7 @@ CONFIG_SPI_IMX=y
 CONFIG_SPI_ORION=y
 CONFIG_GPIO_ASPEED=m
 CONFIG_GPIO_ASPEED_SGPIO=y
+CONFIG_GPIO_MXC=y
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_POWER_RESET_QNAP=y
index e731cdf..a611b0c 100644 (file)
@@ -465,6 +465,7 @@ CONFIG_GPIO_PALMAS=y
 CONFIG_GPIO_TPS6586X=y
 CONFIG_GPIO_TPS65910=y
 CONFIG_GPIO_TWL4030=y
+CONFIG_GPIO_MXC=y
 CONFIG_POWER_AVS=y
 CONFIG_ROCKCHIP_IODOMAIN=y
 CONFIG_POWER_RESET_AS3722=y
index 2d962fe..a3a64bf 100644 (file)
@@ -35,13 +35,8 @@ ENTRY(ll_get_coherency_base)
 
        /*
         * MMU is disabled, use the physical address of the coherency
-        * base address. However, if the coherency fabric isn't mapped
-        * (i.e its virtual address is zero), it means coherency is
-        * not enabled, so we return 0.
+        * base address, (or 0x0 if the coherency fabric is not mapped)
         */
-       ldr     r1, =coherency_base
-       cmp     r1, #0
-       beq     2f
        adr     r1, 3f
        ldr     r3, [r1]
        ldr     r1, [r1, r3]
index f858c35..1d466ad 100644 (file)
@@ -636,6 +636,26 @@ config ARM64_ERRATUM_1542419
 
          If unsure, say Y.
 
+config ARM64_ERRATUM_1508412
+       bool "Cortex-A77: 1508412: workaround deadlock on sequence of NC/Device load and store exclusive or PAR read"
+       default y
+       help
+         This option adds a workaround for Arm Cortex-A77 erratum 1508412.
+
+         Affected Cortex-A77 cores (r0p0, r1p0) could deadlock on a sequence
+         of a store-exclusive or read of PAR_EL1 and a load with device or
+         non-cacheable memory attributes. The workaround depends on a firmware
+         counterpart.
+
+         KVM guests must also have the workaround implemented or they can
+         deadlock the system.
+
+         Work around the issue by inserting DMB SY barriers around PAR_EL1
+         register reads and warning KVM users. The DMB barrier is sufficient
+         to prevent a speculative PAR_EL1 read.
+
+         If unsure, say Y.
+
 config CAVIUM_ERRATUM_22375
        bool "Cavium erratum 22375, 24313"
        default y
index 6f2494d..5c4ac1c 100644 (file)
@@ -54,6 +54,7 @@ config ARCH_BCM_IPROC
 config ARCH_BERLIN
        bool "Marvell Berlin SoC Family"
        select DW_APB_ICTL
+       select DW_APB_TIMER_OF
        select GPIOLIB
        select PINCTRL
        help
index cb1360a..7740f97 100644 (file)
        pinctrl-0 = <&uart_ao_a_pins>;
        pinctrl-names = "default";
 };
+
+&usb {
+       status = "okay";
+       dr_mode = "otg";
+       vbus-supply = <&usb_pwr>;
+};
index b9efc84..724ee17 100644 (file)
                #size-cells = <2>;
                ranges;
 
+               usb: usb@ffe09080 {
+                       compatible = "amlogic,meson-axg-usb-ctrl";
+                       reg = <0x0 0xffe09080 0x0 0x20>;
+                       interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1_DDR_BRIDGE>;
+                       clock-names = "usb_ctrl", "ddr";
+                       resets = <&reset RESET_USB_OTG>;
+
+                       dr_mode = "otg";
+
+                       phys = <&usb2_phy1>;
+                       phy-names = "usb2-phy1";
+
+                       dwc2: usb@ff400000 {
+                               compatible = "amlogic,meson-g12a-usb", "snps,dwc2";
+                               reg = <0x0 0xff400000 0x0 0x40000>;
+                               interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clkc CLKID_USB1>;
+                               clock-names = "otg";
+                               phys = <&usb2_phy1>;
+                               dr_mode = "peripheral";
+                               g-rx-fifo-size = <192>;
+                               g-np-tx-fifo-size = <128>;
+                               g-tx-fifo-size = <128 128 16 16 16>;
+                       };
+
+                       dwc3: usb@ff500000 {
+                               compatible = "snps,dwc3";
+                               reg = <0x0 0xff500000 0x0 0x100000>;
+                               interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+                               dr_mode = "host";
+                               maximum-speed = "high-speed";
+                               snps,dis_u2_susphy_quirk;
+                       };
+               };
+
                ethmac: ethernet@ff3f0000 {
                        compatible = "amlogic,meson-axg-dwmac",
                                     "snps,dwmac-3.70a",
                                      "timing-adjustment";
                        rx-fifo-depth = <4096>;
                        tx-fifo-depth = <2048>;
+                       resets = <&reset RESET_ETHERNET>;
+                       reset-names = "stmmaceth";
                        status = "disabled";
                };
 
                                clock-names = "core", "clkin0", "clkin1";
                                resets = <&reset RESET_SD_EMMC_C>;
                        };
+
+                       usb2_phy1: phy@9020 {
+                               compatible = "amlogic,meson-gxl-usb2-phy";
+                               #phy-cells = <0>;
+                               reg = <0x0 0x9020 0x0 0x20>;
+                               clocks = <&clkc CLKID_USB>;
+                               clock-names = "phy";
+                               resets = <&reset RESET_USB_OTG>;
+                               reset-names = "phy";
+                       };
                };
 
                sram: sram@fffc0000 {
index 1e83ec5..8514fe6 100644 (file)
                };
 
                ethmac: ethernet@ff3f0000 {
-                       compatible = "amlogic,meson-axg-dwmac",
+                       compatible = "amlogic,meson-g12a-dwmac",
                                     "snps,dwmac-3.70a",
                                     "snps,dwmac";
                        reg = <0x0 0xff3f0000 0x0 0x10000>,
                                      "timing-adjustment";
                        rx-fifo-depth = <4096>;
                        tx-fifo-depth = <2048>;
+                       resets = <&reset RESET_ETHERNET>;
+                       reset-names = "stmmaceth";
                        status = "disabled";
 
                        mdio0: mdio {
                                hwrng: rng@218 {
                                        compatible = "amlogic,meson-rng";
                                        reg = <0x0 0x218 0x0 0x4>;
+                                       clocks = <&clkc CLKID_RNG0>;
+                                       clock-names = "core";
                                };
                        };
 
index 5de2815..ce1198a 100644 (file)
@@ -19,7 +19,7 @@
        regulator-min-microvolt = <680000>;
        regulator-max-microvolt = <1040000>;
 
-       pwms = <&pwm_AO_cd 1 1500 0>;
+       pwms = <&pwm_ab 0 1500 0>;
 };
 
 &vddcpu_b {
index 0edd137..726b91d 100644 (file)
@@ -13,6 +13,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/power/meson-gxbb-power.h>
+#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
 #include <dt-bindings/thermal/thermal.h>
 
 / {
                        interrupt-names = "macirq";
                        rx-fifo-depth = <4096>;
                        tx-fifo-depth = <2048>;
+                       resets = <&reset RESET_ETHERNET>;
+                       reset-names = "stmmaceth";
                        power-domains = <&pwrc PWRC_GXBB_ETHERNET_MEM_ID>;
                        status = "disabled";
                };
index 03733fd..215d2f7 100644 (file)
        compatible = "globalscale,espressobin-v7-emmc", "globalscale,espressobin-v7",
                     "globalscale,espressobin", "marvell,armada3720",
                     "marvell,armada3710";
+
+       aliases {
+               /* ethernet1 is wan port */
+               ethernet1 = &switch0port3;
+               ethernet3 = &switch0port1;
+       };
 };
 
 &switch0 {
        ports {
-               port@1 {
+               switch0port1: port@1 {
                        reg = <1>;
                        label = "lan1";
                        phy-handle = <&switch0phy0>;
                };
 
-               port@3 {
+               switch0port3: port@3 {
                        reg = <3>;
                        label = "wan";
                        phy-handle = <&switch0phy2>;
index 8570c5f..b6f4af8 100644 (file)
        model = "Globalscale Marvell ESPRESSOBin Board V7";
        compatible = "globalscale,espressobin-v7", "globalscale,espressobin",
                     "marvell,armada3720", "marvell,armada3710";
+
+       aliases {
+               /* ethernet1 is wan port */
+               ethernet1 = &switch0port3;
+               ethernet3 = &switch0port1;
+       };
 };
 
 &switch0 {
        ports {
-               port@1 {
+               switch0port1: port@1 {
                        reg = <1>;
                        label = "lan1";
                        phy-handle = <&switch0phy0>;
                };
 
-               port@3 {
+               switch0port3: port@3 {
                        reg = <3>;
                        label = "wan";
                        phy-handle = <&switch0phy2>;
index b97218c..0775c16 100644 (file)
 / {
        aliases {
                ethernet0 = &eth0;
+               /* for dsa slave device */
+               ethernet1 = &switch0port1;
+               ethernet2 = &switch0port2;
+               ethernet3 = &switch0port3;
                serial0 = &uart0;
                serial1 = &uart1;
        };
                        #address-cells = <1>;
                        #size-cells = <0>;
 
-                       port@0 {
+                       switch0port0: port@0 {
                                reg = <0>;
                                label = "cpu";
                                ethernet = <&eth0>;
                                };
                        };
 
-                       port@1 {
+                       switch0port1: port@1 {
                                reg = <1>;
                                label = "wan";
                                phy-handle = <&switch0phy0>;
                        };
 
-                       port@2 {
+                       switch0port2: port@2 {
                                reg = <2>;
                                label = "lan0";
                                phy-handle = <&switch0phy1>;
                        };
 
-                       port@3 {
+                       switch0port3: port@3 {
                                reg = <3>;
                                label = "lan1";
                                phy-handle = <&switch0phy2>;
index 17a2df6..5cfe3cf 100644 (file)
@@ -500,6 +500,7 @@ CONFIG_GPIO_ALTERA=m
 CONFIG_GPIO_DWAPB=y
 CONFIG_GPIO_MB86S7X=y
 CONFIG_GPIO_MPC8XXX=y
+CONFIG_GPIO_MXC=y
 CONFIG_GPIO_PL061=y
 CONFIG_GPIO_RCAR=y
 CONFIG_GPIO_UNIPHIER=y
index 0ac3e06..63d43b5 100644 (file)
@@ -24,6 +24,7 @@
 #define CTR_L1IP(ctr)          (((ctr) >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK)
 
 #define ICACHE_POLICY_VPIPT    0
+#define ICACHE_POLICY_RESERVED 1
 #define ICACHE_POLICY_VIPT     2
 #define ICACHE_POLICY_PIPT     3
 
index 42868db..e7d9899 100644 (file)
@@ -65,7 +65,8 @@
 #define ARM64_HAS_ARMv8_4_TTL                  55
 #define ARM64_HAS_TLB_RANGE                    56
 #define ARM64_MTE                              57
+#define ARM64_WORKAROUND_1508412               58
 
-#define ARM64_NCAPS                            58
+#define ARM64_NCAPS                            59
 
 #endif /* __ASM_CPUCAPS_H */
index 7219cdd..9e2e9a6 100644 (file)
@@ -71,6 +71,7 @@
 #define ARM_CPU_PART_CORTEX_A55                0xD05
 #define ARM_CPU_PART_CORTEX_A76                0xD0B
 #define ARM_CPU_PART_NEOVERSE_N1       0xD0C
+#define ARM_CPU_PART_CORTEX_A77                0xD0D
 
 #define APM_CPU_PART_POTENZA           0x000
 
 #define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55)
 #define MIDR_CORTEX_A76        MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
 #define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
+#define MIDR_CORTEX_A77        MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)
 #define MIDR_THUNDERX  MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
 #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
 #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
index d52c1b3..174817b 100644 (file)
 
 #include <linux/build_bug.h>
 #include <linux/types.h>
+#include <asm/alternative.h>
 
 #define __DEFINE_MRS_MSR_S_REGNUM                              \
 "      .irp    num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n" \
                write_sysreg_s(__scs_new, sysreg);                      \
 } while (0)
 
+#define read_sysreg_par() ({                                           \
+       u64 par;                                                        \
+       asm(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412));    \
+       par = read_sysreg(par_el1);                                     \
+       asm(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412));    \
+       par;                                                            \
+})
+
 #endif
 
 #endif /* __ASM_SYSREG_H */
index 24d75af..61314fd 100644 (file)
@@ -523,6 +523,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                .cpu_enable = cpu_enable_trap_ctr_access,
        },
 #endif
+#ifdef CONFIG_ARM64_ERRATUM_1508412
+       {
+               /* we depend on the firmware portion for correctness */
+               .desc = "ARM erratum 1508412 (kernel portion)",
+               .capability = ARM64_WORKAROUND_1508412,
+               ERRATA_MIDR_RANGE(MIDR_CORTEX_A77,
+                                 0, 0,
+                                 1, 0),
+       },
+#endif
        {
        }
 };
index 6a7bb37..77605ae 100644 (file)
@@ -34,10 +34,10 @@ DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
 static struct cpuinfo_arm64 boot_cpu_data;
 
 static const char *icache_policy_str[] = {
-       [0 ... ICACHE_POLICY_PIPT]      = "RESERVED/UNKNOWN",
+       [ICACHE_POLICY_VPIPT]           = "VPIPT",
+       [ICACHE_POLICY_RESERVED]        = "RESERVED/UNKNOWN",
        [ICACHE_POLICY_VIPT]            = "VIPT",
        [ICACHE_POLICY_PIPT]            = "PIPT",
-       [ICACHE_POLICY_VPIPT]           = "VPIPT",
 };
 
 unsigned long __icache_flags;
@@ -334,10 +334,11 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
        case ICACHE_POLICY_VPIPT:
                set_bit(ICACHEF_VPIPT, &__icache_flags);
                break;
-       default:
+       case ICACHE_POLICY_RESERVED:
        case ICACHE_POLICY_VIPT:
                /* Assume aliasing */
                set_bit(ICACHEF_ALIASING, &__icache_flags);
+               break;
        }
 
        pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
index df67c0f..a71844f 100644 (file)
@@ -147,6 +147,6 @@ efi_debug_entry:
         * correctly at this alignment, we must ensure that .text is
         * placed at a 4k boundary in the Image to begin with.
         */
-       .align 12
+       .balign SEGMENT_ALIGN
 efi_header_end:
        .endm
index f30007d..b295fb9 100644 (file)
@@ -365,6 +365,9 @@ alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
        br      x30
 #endif
        .else
+       /* Ensure any device/NC reads complete */
+       alternative_insn nop, "dmb sy", ARM64_WORKAROUND_1508412
+
        eret
        .endif
        sb
index 25f3c80..c18eb7d 100644 (file)
@@ -135,8 +135,6 @@ static enum mitigation_state spectre_v2_get_cpu_hw_mitigation_state(void)
        return SPECTRE_VULNERABLE;
 }
 
-#define SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED   (1)
-
 static enum mitigation_state spectre_v2_get_cpu_fw_mitigation_state(void)
 {
        int ret;
index 82e75fc..09c96f5 100644 (file)
@@ -222,6 +222,7 @@ asmlinkage notrace void secondary_start_kernel(void)
        if (system_uses_irq_prio_masking())
                init_gic_priority_masking();
 
+       rcu_cpu_starting(cpu);
        preempt_disable();
        trace_hardirqs_off();
 
index 7f96a1a..79280c5 100644 (file)
@@ -22,16 +22,21 @@ endif
 
 CC_COMPAT ?= $(CC)
 CC_COMPAT += $(CC_COMPAT_CLANG_FLAGS)
+
+ifneq ($(LLVM),)
+LD_COMPAT ?= $(LD)
+else
+LD_COMPAT ?= $(CROSS_COMPILE_COMPAT)ld
+endif
 else
 CC_COMPAT ?= $(CROSS_COMPILE_COMPAT)gcc
+LD_COMPAT ?= $(CROSS_COMPILE_COMPAT)ld
 endif
 
 cc32-option = $(call try-run,\
         $(CC_COMPAT) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
 cc32-disable-warning = $(call try-run,\
        $(CC_COMPAT) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
-cc32-ldoption = $(call try-run,\
-        $(CC_COMPAT) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
 cc32-as-instr = $(call try-run,\
        printf "%b\n" "$(1)" | $(CC_COMPAT) $(VDSO_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
 
@@ -122,14 +127,10 @@ dmbinstr := $(call cc32-as-instr,dmb ishld,-DCONFIG_AS_DMB_ISHLD=1)
 VDSO_CFLAGS += $(dmbinstr)
 VDSO_AFLAGS += $(dmbinstr)
 
-VDSO_LDFLAGS := $(VDSO_CPPFLAGS)
 # From arm vDSO Makefile
-VDSO_LDFLAGS += -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1
-VDSO_LDFLAGS += -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
-VDSO_LDFLAGS += -nostdlib -shared -mfloat-abi=soft
-VDSO_LDFLAGS += -Wl,--hash-style=sysv
-VDSO_LDFLAGS += -Wl,--build-id=sha1
-VDSO_LDFLAGS += $(call cc32-ldoption,-fuse-ld=bfd)
+VDSO_LDFLAGS += -Bsymbolic --no-undefined -soname=linux-vdso.so.1
+VDSO_LDFLAGS += -z max-page-size=4096 -z common-page-size=4096
+VDSO_LDFLAGS += -nostdlib -shared --hash-style=sysv --build-id=sha1
 
 
 # Borrow vdsomunge.c from the arm vDSO
@@ -189,8 +190,8 @@ quiet_cmd_vdsold_and_vdso_check = LD32    $@
       cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check)
 
 quiet_cmd_vdsold = LD32    $@
-      cmd_vdsold = $(CC_COMPAT) -Wp,-MD,$(depfile) $(VDSO_LDFLAGS) \
-                   -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@
+      cmd_vdsold = $(LD_COMPAT) $(VDSO_LDFLAGS) \
+                   -T $(filter %.lds,$^) $(filter %.o,$^) -o $@
 quiet_cmd_vdsocc = CC32    $@
       cmd_vdsocc = $(CC_COMPAT) -Wp,-MD,$(depfile) $(VDSO_CFLAGS) -c -o $@ $<
 quiet_cmd_vdsocc_gettimeofday = CC32    $@
index 6d78c04..1bda604 100644 (file)
@@ -278,7 +278,7 @@ SECTIONS
         * explicitly check instead of blindly discarding.
         */
        .plt : {
-               *(.plt) *(.plt.*) *(.iplt) *(.igot)
+               *(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt)
        }
        ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!")
 
index f56122e..8f8fca4 100644 (file)
@@ -1719,7 +1719,8 @@ int kvm_arch_init(void *opaque)
                return -ENODEV;
        }
 
-       if (cpus_have_final_cap(ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE))
+       if (cpus_have_final_cap(ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) ||
+           cpus_have_final_cap(ARM64_WORKAROUND_1508412))
                kvm_info("Guests without required CPU erratum workarounds can deadlock system!\n" \
                         "Only trusted guests should be used on this system.\n");
 
index 313a8fa..1f875a8 100644 (file)
@@ -140,9 +140,9 @@ static inline bool __translate_far_to_hpfar(u64 far, u64 *hpfar)
         * We do need to save/restore PAR_EL1 though, as we haven't
         * saved the guest context yet, and we may return early...
         */
-       par = read_sysreg(par_el1);
+       par = read_sysreg_par();
        if (!__kvm_at("s1e1r", far))
-               tmp = read_sysreg(par_el1);
+               tmp = read_sysreg_par();
        else
                tmp = SYS_PAR_EL1_F; /* back to the guest */
        write_sysreg(par, par_el1);
@@ -421,7 +421,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
        if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) &&
            kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 &&
            handle_tx2_tvm(vcpu))
-               return true;
+               goto guest;
 
        /*
         * We trap the first access to the FP/SIMD to save the host context
@@ -431,13 +431,13 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
         * Similarly for trapped SVE accesses.
         */
        if (__hyp_handle_fpsimd(vcpu))
-               return true;
+               goto guest;
 
        if (__hyp_handle_ptrauth(vcpu))
-               return true;
+               goto guest;
 
        if (!__populate_fault_info(vcpu))
-               return true;
+               goto guest;
 
        if (static_branch_unlikely(&vgic_v2_cpuif_trap)) {
                bool valid;
@@ -452,7 +452,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
                        int ret = __vgic_v2_perform_cpuif_access(vcpu);
 
                        if (ret == 1)
-                               return true;
+                               goto guest;
 
                        /* Promote an illegal access to an SError.*/
                        if (ret == -1)
@@ -468,12 +468,17 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
                int ret = __vgic_v3_perform_cpuif_access(vcpu);
 
                if (ret == 1)
-                       return true;
+                       goto guest;
        }
 
 exit:
        /* Return to the host kernel and handle the exit */
        return false;
+
+guest:
+       /* Re-enter the guest */
+       asm(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412));
+       return true;
 }
 
 static inline void __kvm_unexpected_el2_exception(void)
index 7a98603..cce43bf 100644 (file)
@@ -43,7 +43,7 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
        ctxt_sys_reg(ctxt, CONTEXTIDR_EL1) = read_sysreg_el1(SYS_CONTEXTIDR);
        ctxt_sys_reg(ctxt, AMAIR_EL1)   = read_sysreg_el1(SYS_AMAIR);
        ctxt_sys_reg(ctxt, CNTKCTL_EL1) = read_sysreg_el1(SYS_CNTKCTL);
-       ctxt_sys_reg(ctxt, PAR_EL1)     = read_sysreg(par_el1);
+       ctxt_sys_reg(ctxt, PAR_EL1)     = read_sysreg_par();
        ctxt_sys_reg(ctxt, TPIDR_EL1)   = read_sysreg(tpidr_el1);
 
        ctxt_sys_reg(ctxt, SP_EL1)      = read_sysreg(sp_el1);
index a457a03..8ae8160 100644 (file)
@@ -250,7 +250,7 @@ void __noreturn hyp_panic(void)
 {
        u64 spsr = read_sysreg_el2(SYS_SPSR);
        u64 elr = read_sysreg_el2(SYS_ELR);
-       u64 par = read_sysreg(par_el1);
+       u64 par = read_sysreg_par();
        bool restore_host = true;
        struct kvm_cpu_context *host_ctxt;
        struct kvm_vcpu *vcpu;
index fe69de1..62546e2 100644 (file)
@@ -215,7 +215,7 @@ void __noreturn hyp_panic(void)
 {
        u64 spsr = read_sysreg_el2(SYS_SPSR);
        u64 elr = read_sysreg_el2(SYS_ELR);
-       u64 par = read_sysreg(par_el1);
+       u64 par = read_sysreg_par();
 
        __hyp_call_panic(spsr, elr, par);
        unreachable();
index 9824025..25ea4ec 100644 (file)
@@ -31,7 +31,7 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
                                val = SMCCC_RET_SUCCESS;
                                break;
                        case SPECTRE_UNAFFECTED:
-                               val = SMCCC_RET_NOT_REQUIRED;
+                               val = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED;
                                break;
                        }
                        break;
index d9117bc..41348a7 100644 (file)
@@ -95,7 +95,7 @@ static bool __vcpu_read_sys_reg_from_cpu(int reg, u64 *val)
        case AMAIR_EL1:         *val = read_sysreg_s(SYS_AMAIR_EL12);   break;
        case CNTKCTL_EL1:       *val = read_sysreg_s(SYS_CNTKCTL_EL12); break;
        case ELR_EL1:           *val = read_sysreg_s(SYS_ELR_EL12);     break;
-       case PAR_EL1:           *val = read_sysreg_s(SYS_PAR_EL1);      break;
+       case PAR_EL1:           *val = read_sysreg_par();               break;
        case DACR32_EL2:        *val = read_sysreg_s(SYS_DACR32_EL2);   break;
        case IFSR32_EL2:        *val = read_sysreg_s(SYS_IFSR32_EL2);   break;
        case DBGVCR32_EL2:      *val = read_sysreg_s(SYS_DBGVCR32_EL2); break;
index e0bf83d..dc8d2a2 100644 (file)
@@ -56,9 +56,8 @@
        stp \reg1, \reg2, [\ptr], \val
        .endm
 
-       .weak memcpy
 SYM_FUNC_START_ALIAS(__memcpy)
-SYM_FUNC_START_PI(memcpy)
+SYM_FUNC_START_WEAK_PI(memcpy)
 #include "copy_template.S"
        ret
 SYM_FUNC_END_PI(memcpy)
index 02cda2e..1035dce 100644 (file)
@@ -45,9 +45,8 @@ C_h   .req    x12
 D_l    .req    x13
 D_h    .req    x14
 
-       .weak memmove
 SYM_FUNC_START_ALIAS(__memmove)
-SYM_FUNC_START_PI(memmove)
+SYM_FUNC_START_WEAK_PI(memmove)
        cmp     dstin, src
        b.lo    __memcpy
        add     tmp1, src, count
index 77c3c7b..a9c1c9a 100644 (file)
@@ -42,9 +42,8 @@ dst           .req    x8
 tmp3w          .req    w9
 tmp3           .req    x9
 
-       .weak memset
 SYM_FUNC_START_ALIAS(__memset)
-SYM_FUNC_START_PI(memset)
+SYM_FUNC_START_WEAK_PI(memset)
        mov     dst, dstin      /* Preserve return value.  */
        and     A_lw, val, #255
        orr     A_lw, A_lw, A_lw, lsl #8
index 94c99c1..1ee9400 100644 (file)
@@ -262,7 +262,7 @@ static bool __kprobes is_spurious_el1_translation_fault(unsigned long addr,
        local_irq_save(flags);
        asm volatile("at s1e1r, %0" :: "r" (addr));
        isb();
-       par = read_sysreg(par_el1);
+       par = read_sysreg_par();
        local_irq_restore(flags);
 
        /*
index e6e26d7..fa01bef 100644 (file)
@@ -1044,6 +1044,7 @@ static int __bio_iov_append_get_pages(struct bio *bio, struct iov_iter *iter)
        ssize_t size, left;
        unsigned len, i;
        size_t offset;
+       int ret = 0;
 
        if (WARN_ON_ONCE(!max_append_sectors))
                return 0;
@@ -1066,15 +1067,17 @@ static int __bio_iov_append_get_pages(struct bio *bio, struct iov_iter *iter)
 
                len = min_t(size_t, PAGE_SIZE - offset, left);
                if (bio_add_hw_page(q, bio, page, len, offset,
-                               max_append_sectors, &same_page) != len)
-                       return -EINVAL;
+                               max_append_sectors, &same_page) != len) {
+                       ret = -EINVAL;
+                       break;
+               }
                if (same_page)
                        put_page(page);
                offset = 0;
        }
 
-       iov_iter_advance(iter, size);
-       return 0;
+       iov_iter_advance(iter, size - left);
+       return ret;
 }
 
 /**
index f9b5561..c68bdf5 100644 (file)
@@ -657,13 +657,20 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
                        goto fail;
                }
 
+               if (radix_tree_preload(GFP_KERNEL)) {
+                       blkg_free(new_blkg);
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+
                rcu_read_lock();
                spin_lock_irq(&q->queue_lock);
 
                blkg = blkg_lookup_check(pos, pol, q);
                if (IS_ERR(blkg)) {
                        ret = PTR_ERR(blkg);
-                       goto fail_unlock;
+                       blkg_free(new_blkg);
+                       goto fail_preloaded;
                }
 
                if (blkg) {
@@ -672,10 +679,12 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
                        blkg = blkg_create(pos, q, new_blkg);
                        if (IS_ERR(blkg)) {
                                ret = PTR_ERR(blkg);
-                               goto fail_unlock;
+                               goto fail_preloaded;
                        }
                }
 
+               radix_tree_preload_end();
+
                if (pos == blkcg)
                        goto success;
        }
@@ -685,6 +694,8 @@ success:
        ctx->body = input;
        return 0;
 
+fail_preloaded:
+       radix_tree_preload_end();
 fail_unlock:
        spin_unlock_irq(&q->queue_lock);
        rcu_read_unlock();
index 53abb5c..e32958f 100644 (file)
@@ -225,6 +225,7 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error)
        /* release the tag's ownership to the req cloned from */
        spin_lock_irqsave(&fq->mq_flush_lock, flags);
 
+       WRITE_ONCE(flush_rq->state, MQ_RQ_IDLE);
        if (!refcount_dec_and_test(&flush_rq->ref)) {
                fq->rq_status = error;
                spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
index da4b125..0761529 100644 (file)
@@ -74,19 +74,6 @@ MODULE_DEVICE_TABLE(acpi, button_device_ids);
 /* Please keep this list sorted alphabetically by vendor and model */
 static const struct dmi_system_id dmi_lid_quirks[] = {
        {
-               /*
-                * Acer Switch 10 SW5-012. _LID method messes with home and
-                * power button GPIO IRQ settings causing an interrupt storm on
-                * both GPIOs. This is unfixable without a DSDT override, so we
-                * have to disable the lid-switch functionality altogether :|
-                */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
-               },
-               .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_DISABLED,
-       },
-       {
                /* GP-electronic T701, _LID method points to a floating GPIO */
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
index 45d4b7b..24e076f 100644 (file)
@@ -231,7 +231,8 @@ static void hot_remove_dock_devices(struct dock_station *ds)
         * between them).
         */
        list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
-               dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false);
+               dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST,
+                                  DOCK_CALL_HANDLER);
 
        list_for_each_entry_reverse(dd, &ds->dependent_devices, list)
                acpi_bus_trim(dd->adev);
index 7562278..3a3c209 100644 (file)
@@ -1564,7 +1564,7 @@ static ssize_t format1_show(struct device *dev,
                                        le16_to_cpu(nfit_dcr->dcr->code));
                        break;
                }
-               if (rc != ENXIO)
+               if (rc != -ENXIO)
                        break;
        }
        mutex_unlock(&acpi_desc->init_mutex);
index eb9dc14..20190f6 100644 (file)
@@ -2100,7 +2100,7 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
        pp->dhfis_bits &= ~done_mask;
        pp->dmafis_bits &= ~done_mask;
        pp->sdbfis_bits |= done_mask;
-       ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+       ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
 
        if (!ap->qc_active) {
                DPRINTK("over\n");
index c852f16..78114dd 100644 (file)
@@ -4264,6 +4264,7 @@ static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
  */
 void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
 {
+       struct device *parent = dev->parent;
        struct fwnode_handle *fn = dev->fwnode;
 
        if (fwnode) {
@@ -4278,7 +4279,8 @@ void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
        } else {
                if (fwnode_is_primary(fn)) {
                        dev->fwnode = fn->secondary;
-                       fn->secondary = NULL;
+                       if (!(parent && fn == parent->fwnode))
+                               fn->secondary = ERR_PTR(-ENODEV);
                } else {
                        dev->fwnode = NULL;
                }
index 0bed21c..c4f9ccf 100644 (file)
@@ -296,7 +296,7 @@ static void nbd_size_clear(struct nbd_device *nbd)
        }
 }
 
-static void nbd_size_update(struct nbd_device *nbd)
+static void nbd_size_update(struct nbd_device *nbd, bool start)
 {
        struct nbd_config *config = nbd->config;
        struct block_device *bdev = bdget_disk(nbd->disk, 0);
@@ -313,7 +313,8 @@ static void nbd_size_update(struct nbd_device *nbd)
        if (bdev) {
                if (bdev->bd_disk) {
                        bd_set_nr_sectors(bdev, nr_sectors);
-                       set_blocksize(bdev, config->blksize);
+                       if (start)
+                               set_blocksize(bdev, config->blksize);
                } else
                        set_bit(GD_NEED_PART_SCAN, &nbd->disk->state);
                bdput(bdev);
@@ -328,7 +329,7 @@ static void nbd_size_set(struct nbd_device *nbd, loff_t blocksize,
        config->blksize = blocksize;
        config->bytesize = blocksize * nr_blocks;
        if (nbd->task_recv != NULL)
-               nbd_size_update(nbd);
+               nbd_size_update(nbd, false);
 }
 
 static void nbd_complete_rq(struct request *req)
@@ -1308,7 +1309,7 @@ static int nbd_start_device(struct nbd_device *nbd)
                args->index = i;
                queue_work(nbd->recv_workq, &args->work);
        }
-       nbd_size_update(nbd);
+       nbd_size_update(nbd, true);
        return error;
 }
 
index d2e7db4..cfd00ad 100644 (file)
@@ -47,6 +47,8 @@ struct nullb_device {
        unsigned int nr_zones_closed;
        struct blk_zone *zones;
        sector_t zone_size_sects;
+       spinlock_t zone_dev_lock;
+       unsigned long *zone_locks;
 
        unsigned long size; /* device size in MB */
        unsigned long completion_nsec; /* time in ns to complete a request */
index 7d94f2d..8775acb 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/vmalloc.h>
+#include <linux/bitmap.h>
 #include "null_blk.h"
 
 #define CREATE_TRACE_POINTS
@@ -45,6 +46,13 @@ int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q)
        if (!dev->zones)
                return -ENOMEM;
 
+       spin_lock_init(&dev->zone_dev_lock);
+       dev->zone_locks = bitmap_zalloc(dev->nr_zones, GFP_KERNEL);
+       if (!dev->zone_locks) {
+               kvfree(dev->zones);
+               return -ENOMEM;
+       }
+
        if (dev->zone_nr_conv >= dev->nr_zones) {
                dev->zone_nr_conv = dev->nr_zones - 1;
                pr_info("changed the number of conventional zones to %u",
@@ -123,15 +131,26 @@ int null_register_zoned_dev(struct nullb *nullb)
 
 void null_free_zoned_dev(struct nullb_device *dev)
 {
+       bitmap_free(dev->zone_locks);
        kvfree(dev->zones);
 }
 
+static inline void null_lock_zone(struct nullb_device *dev, unsigned int zno)
+{
+       wait_on_bit_lock_io(dev->zone_locks, zno, TASK_UNINTERRUPTIBLE);
+}
+
+static inline void null_unlock_zone(struct nullb_device *dev, unsigned int zno)
+{
+       clear_and_wake_up_bit(zno, dev->zone_locks);
+}
+
 int null_report_zones(struct gendisk *disk, sector_t sector,
                unsigned int nr_zones, report_zones_cb cb, void *data)
 {
        struct nullb *nullb = disk->private_data;
        struct nullb_device *dev = nullb->dev;
-       unsigned int first_zone, i;
+       unsigned int first_zone, i, zno;
        struct blk_zone zone;
        int error;
 
@@ -142,15 +161,18 @@ int null_report_zones(struct gendisk *disk, sector_t sector,
        nr_zones = min(nr_zones, dev->nr_zones - first_zone);
        trace_nullb_report_zones(nullb, nr_zones);
 
-       for (i = 0; i < nr_zones; i++) {
+       zno = first_zone;
+       for (i = 0; i < nr_zones; i++, zno++) {
                /*
                 * Stacked DM target drivers will remap the zone information by
                 * modifying the zone information passed to the report callback.
                 * So use a local copy to avoid corruption of the device zone
                 * array.
                 */
-               memcpy(&zone, &dev->zones[first_zone + i],
-                      sizeof(struct blk_zone));
+               null_lock_zone(dev, zno);
+               memcpy(&zone, &dev->zones[zno], sizeof(struct blk_zone));
+               null_unlock_zone(dev, zno);
+
                error = cb(&zone, i, data);
                if (error)
                        return error;
@@ -159,6 +181,10 @@ int null_report_zones(struct gendisk *disk, sector_t sector,
        return nr_zones;
 }
 
+/*
+ * This is called in the case of memory backing from null_process_cmd()
+ * with the target zone already locked.
+ */
 size_t null_zone_valid_read_len(struct nullb *nullb,
                                sector_t sector, unsigned int len)
 {
@@ -295,22 +321,27 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
        if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
                return null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
 
+       null_lock_zone(dev, zno);
+       spin_lock(&dev->zone_dev_lock);
+
        switch (zone->cond) {
        case BLK_ZONE_COND_FULL:
                /* Cannot write to a full zone */
-               return BLK_STS_IOERR;
+               ret = BLK_STS_IOERR;
+               goto unlock;
        case BLK_ZONE_COND_EMPTY:
        case BLK_ZONE_COND_CLOSED:
                ret = null_check_zone_resources(dev, zone);
                if (ret != BLK_STS_OK)
-                       return ret;
+                       goto unlock;
                break;
        case BLK_ZONE_COND_IMP_OPEN:
        case BLK_ZONE_COND_EXP_OPEN:
                break;
        default:
                /* Invalid zone condition */
-               return BLK_STS_IOERR;
+               ret = BLK_STS_IOERR;
+               goto unlock;
        }
 
        /*
@@ -326,11 +357,14 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
                else
                        cmd->rq->__sector = sector;
        } else if (sector != zone->wp) {
-               return BLK_STS_IOERR;
+               ret = BLK_STS_IOERR;
+               goto unlock;
        }
 
-       if (zone->wp + nr_sectors > zone->start + zone->capacity)
-               return BLK_STS_IOERR;
+       if (zone->wp + nr_sectors > zone->start + zone->capacity) {
+               ret = BLK_STS_IOERR;
+               goto unlock;
+       }
 
        if (zone->cond == BLK_ZONE_COND_CLOSED) {
                dev->nr_zones_closed--;
@@ -341,9 +375,11 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
        if (zone->cond != BLK_ZONE_COND_EXP_OPEN)
                zone->cond = BLK_ZONE_COND_IMP_OPEN;
 
+       spin_unlock(&dev->zone_dev_lock);
        ret = null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
+       spin_lock(&dev->zone_dev_lock);
        if (ret != BLK_STS_OK)
-               return ret;
+               goto unlock;
 
        zone->wp += nr_sectors;
        if (zone->wp == zone->start + zone->capacity) {
@@ -353,7 +389,13 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
                        dev->nr_zones_imp_open--;
                zone->cond = BLK_ZONE_COND_FULL;
        }
-       return BLK_STS_OK;
+       ret = BLK_STS_OK;
+
+unlock:
+       spin_unlock(&dev->zone_dev_lock);
+       null_unlock_zone(dev, zno);
+
+       return ret;
 }
 
 static blk_status_t null_open_zone(struct nullb_device *dev, struct blk_zone *zone)
@@ -464,16 +506,33 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
                                   sector_t sector)
 {
        struct nullb_device *dev = cmd->nq->dev;
-       unsigned int zone_no = null_zone_no(dev, sector);
-       struct blk_zone *zone = &dev->zones[zone_no];
-       blk_status_t ret = BLK_STS_OK;
+       unsigned int zone_no;
+       struct blk_zone *zone;
+       blk_status_t ret;
        size_t i;
 
+       if (op == REQ_OP_ZONE_RESET_ALL) {
+               for (i = dev->zone_nr_conv; i < dev->nr_zones; i++) {
+                       null_lock_zone(dev, i);
+                       zone = &dev->zones[i];
+                       if (zone->cond != BLK_ZONE_COND_EMPTY) {
+                               spin_lock(&dev->zone_dev_lock);
+                               null_reset_zone(dev, zone);
+                               spin_unlock(&dev->zone_dev_lock);
+                               trace_nullb_zone_op(cmd, i, zone->cond);
+                       }
+                       null_unlock_zone(dev, i);
+               }
+               return BLK_STS_OK;
+       }
+
+       zone_no = null_zone_no(dev, sector);
+       zone = &dev->zones[zone_no];
+
+       null_lock_zone(dev, zone_no);
+       spin_lock(&dev->zone_dev_lock);
+
        switch (op) {
-       case REQ_OP_ZONE_RESET_ALL:
-               for (i = dev->zone_nr_conv; i < dev->nr_zones; i++)
-                       null_reset_zone(dev, &dev->zones[i]);
-               break;
        case REQ_OP_ZONE_RESET:
                ret = null_reset_zone(dev, zone);
                break;
@@ -487,30 +546,46 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
                ret = null_finish_zone(dev, zone);
                break;
        default:
-               return BLK_STS_NOTSUPP;
+               ret = BLK_STS_NOTSUPP;
+               break;
        }
 
+       spin_unlock(&dev->zone_dev_lock);
+
        if (ret == BLK_STS_OK)
                trace_nullb_zone_op(cmd, zone_no, zone->cond);
 
+       null_unlock_zone(dev, zone_no);
+
        return ret;
 }
 
 blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd, enum req_opf op,
                                    sector_t sector, sector_t nr_sectors)
 {
+       struct nullb_device *dev = cmd->nq->dev;
+       unsigned int zno = null_zone_no(dev, sector);
+       blk_status_t sts;
+
        switch (op) {
        case REQ_OP_WRITE:
-               return null_zone_write(cmd, sector, nr_sectors, false);
+               sts = null_zone_write(cmd, sector, nr_sectors, false);
+               break;
        case REQ_OP_ZONE_APPEND:
-               return null_zone_write(cmd, sector, nr_sectors, true);
+               sts = null_zone_write(cmd, sector, nr_sectors, true);
+               break;
        case REQ_OP_ZONE_RESET:
        case REQ_OP_ZONE_RESET_ALL:
        case REQ_OP_ZONE_OPEN:
        case REQ_OP_ZONE_CLOSE:
        case REQ_OP_ZONE_FINISH:
-               return null_zone_mgmt(cmd, op, sector);
+               sts = null_zone_mgmt(cmd, op, sector);
+               break;
        default:
-               return null_process_cmd(cmd, op, sector, nr_sectors);
+               null_lock_zone(dev, zno);
+               sts = null_process_cmd(cmd, op, sector, nr_sectors);
+               null_unlock_zone(dev, zno);
        }
+
+       return sts;
 }
index 8d581c7..eb8ef65 100644 (file)
@@ -443,22 +443,27 @@ static void ace_fix_driveid(u16 *id)
 #define ACE_FSM_NUM_STATES              11
 
 /* Set flag to exit FSM loop and reschedule tasklet */
-static inline void ace_fsm_yield(struct ace_device *ace)
+static inline void ace_fsm_yieldpoll(struct ace_device *ace)
 {
-       dev_dbg(ace->dev, "ace_fsm_yield()\n");
        tasklet_schedule(&ace->fsm_tasklet);
        ace->fsm_continue_flag = 0;
 }
 
+static inline void ace_fsm_yield(struct ace_device *ace)
+{
+       dev_dbg(ace->dev, "%s()\n", __func__);
+       ace_fsm_yieldpoll(ace);
+}
+
 /* Set flag to exit FSM loop and wait for IRQ to reschedule tasklet */
 static inline void ace_fsm_yieldirq(struct ace_device *ace)
 {
        dev_dbg(ace->dev, "ace_fsm_yieldirq()\n");
 
-       if (!ace->irq)
-               /* No IRQ assigned, so need to poll */
-               tasklet_schedule(&ace->fsm_tasklet);
-       ace->fsm_continue_flag = 0;
+       if (ace->irq > 0)
+               ace->fsm_continue_flag = 0;
+       else
+               ace_fsm_yieldpoll(ace);
 }
 
 static bool ace_has_next_request(struct request_queue *q)
@@ -1053,12 +1058,12 @@ static int ace_setup(struct ace_device *ace)
                ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ);
 
        /* Now we can hook up the irq handler */
-       if (ace->irq) {
+       if (ace->irq > 0) {
                rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace);
                if (rc) {
                        /* Failure - fall back to polled mode */
                        dev_err(ace->dev, "request_irq failed\n");
-                       ace->irq = 0;
+                       ace->irq = rc;
                }
        }
 
@@ -1110,7 +1115,7 @@ static void ace_teardown(struct ace_device *ace)
 
        tasklet_kill(&ace->fsm_tasklet);
 
-       if (ace->irq)
+       if (ace->irq > 0)
                free_irq(ace->irq, ace);
 
        iounmap(ace->baseaddr);
@@ -1123,11 +1128,6 @@ static int ace_alloc(struct device *dev, int id, resource_size_t physaddr,
        int rc;
        dev_dbg(dev, "ace_alloc(%p)\n", dev);
 
-       if (!physaddr) {
-               rc = -ENODEV;
-               goto err_noreg;
-       }
-
        /* Allocate and initialize the ace device structure */
        ace = kzalloc(sizeof(struct ace_device), GFP_KERNEL);
        if (!ace) {
@@ -1153,7 +1153,6 @@ err_setup:
        dev_set_drvdata(dev, NULL);
        kfree(ace);
 err_alloc:
-err_noreg:
        dev_err(dev, "could not initialize device, err=%i\n", rc);
        return rc;
 }
@@ -1176,10 +1175,11 @@ static void ace_free(struct device *dev)
 
 static int ace_probe(struct platform_device *dev)
 {
-       resource_size_t physaddr = 0;
        int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
+       resource_size_t physaddr;
+       struct resource *res;
        u32 id = dev->id;
-       int irq = 0;
+       int irq;
        int i;
 
        dev_dbg(&dev->dev, "ace_probe(%p)\n", dev);
@@ -1190,12 +1190,15 @@ static int ace_probe(struct platform_device *dev)
        if (of_find_property(dev->dev.of_node, "8-bit", NULL))
                bus_width = ACE_BUS_WIDTH_8;
 
-       for (i = 0; i < dev->num_resources; i++) {
-               if (dev->resource[i].flags & IORESOURCE_MEM)
-                       physaddr = dev->resource[i].start;
-               if (dev->resource[i].flags & IORESOURCE_IRQ)
-                       irq = dev->resource[i].start;
-       }
+       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -EINVAL;
+
+       physaddr = res->start;
+       if (!physaddr)
+               return -ENODEV;
+
+       irq = platform_get_irq_optional(dev, 0);
 
        /* Call the bus-independent setup code */
        return ace_alloc(&dev->dev, id, physaddr, irq, bus_width);
index 2c7171e..85de313 100644 (file)
@@ -71,6 +71,7 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE
 
 config CPU_FREQ_DEFAULT_GOV_ONDEMAND
        bool "ondemand"
+       depends on !(X86_INTEL_PSTATE && SMP)
        select CPU_FREQ_GOV_ONDEMAND
        select CPU_FREQ_GOV_PERFORMANCE
        help
@@ -83,6 +84,7 @@ config CPU_FREQ_DEFAULT_GOV_ONDEMAND
 
 config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
        bool "conservative"
+       depends on !(X86_INTEL_PSTATE && SMP)
        select CPU_FREQ_GOV_CONSERVATIVE
        select CPU_FREQ_GOV_PERFORMANCE
        help
index f4b6066..336b5e9 100644 (file)
@@ -1908,6 +1908,18 @@ void cpufreq_resume(void)
 }
 
 /**
+ * cpufreq_driver_test_flags - Test cpufreq driver's flags against given ones.
+ * @flags: Flags to test against the current cpufreq driver's flags.
+ *
+ * Assumes that the driver is there, so callers must ensure that this is the
+ * case.
+ */
+bool cpufreq_driver_test_flags(u16 flags)
+{
+       return !!(cpufreq_driver->flags & flags);
+}
+
+/**
  *     cpufreq_get_current_driver - return current driver's name
  *
  *     Return the name string of the currently loaded cpufreq driver
@@ -2187,7 +2199,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
         * exactly same freq is called again and so we can save on few function
         * calls.
         */
-       if (target_freq == policy->cur)
+       if (target_freq == policy->cur &&
+           !(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS))
                return 0;
 
        /* Save last value to restore later on errors */
index 776a58b..ab93bce 100644 (file)
@@ -223,7 +223,6 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
        case EPS_BRAND_C3:
                pr_cont("C3\n");
                return -ENODEV;
-               break;
        }
        /* Enable Enhanced PowerSaver */
        rdmsrl(MSR_IA32_MISC_ENABLE, val);
index 3c14555..b7a9779 100644 (file)
@@ -2568,14 +2568,12 @@ static int intel_cpufreq_update_pstate(struct cpudata *cpu, int target_pstate,
        int old_pstate = cpu->pstate.current_pstate;
 
        target_pstate = intel_pstate_prepare_request(cpu, target_pstate);
-       if (target_pstate != old_pstate) {
+       if (hwp_active) {
+               intel_cpufreq_adjust_hwp(cpu, target_pstate, fast_switch);
+               cpu->pstate.current_pstate = target_pstate;
+       } else if (target_pstate != old_pstate) {
+               intel_cpufreq_adjust_perf_ctl(cpu, target_pstate, fast_switch);
                cpu->pstate.current_pstate = target_pstate;
-               if (hwp_active)
-                       intel_cpufreq_adjust_hwp(cpu, target_pstate,
-                                                fast_switch);
-               else
-                       intel_cpufreq_adjust_perf_ctl(cpu, target_pstate,
-                                                     fast_switch);
        }
 
        intel_cpufreq_trace(cpu, fast_switch ? INTEL_PSTATE_TRACE_FAST_SWITCH :
@@ -3032,6 +3030,7 @@ static int __init intel_pstate_init(void)
                        hwp_mode_bdw = id->driver_data;
                        intel_pstate.attr = hwp_cpufreq_attrs;
                        intel_cpufreq.attr = hwp_cpufreq_attrs;
+                       intel_cpufreq.flags |= CPUFREQ_NEED_UPDATE_LIMITS;
                        if (!default_driver)
                                default_driver = &intel_pstate;
 
index 123fb00..182a4db 100644 (file)
@@ -593,7 +593,6 @@ static void longhaul_setup_voltagescaling(void)
                break;
        default:
                return;
-               break;
        }
        if (min_vid_speed >= highest_speed)
                return;
index a13a2d1..0b66df4 100644 (file)
@@ -240,7 +240,7 @@ unsigned int speedstep_get_frequency(enum speedstep_processor processor)
                return pentium3_get_frequency(processor);
        default:
                return 0;
-       };
+       }
        return 0;
 }
 EXPORT_SYMBOL_GPL(speedstep_get_frequency);
index 9853bd3..017e5d8 100644 (file)
@@ -197,6 +197,8 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
                        protocols_imp[tot_num_ret + loop] = *(list + loop);
 
                tot_num_ret += loop_num_ret;
+
+               scmi_reset_rx_to_maxsz(handle, t);
        } while (loop_num_ret);
 
        scmi_xfer_put(handle, t);
index c1cfe3e..4645677 100644 (file)
@@ -192,6 +192,8 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id,
                }
 
                tot_rate_cnt += num_returned;
+
+               scmi_reset_rx_to_maxsz(handle, t);
                /*
                 * check for both returned and remaining to avoid infinite
                 * loop due to buggy firmware
index 37fb583..65063fa 100644 (file)
@@ -147,6 +147,8 @@ int scmi_do_xfer_with_response(const struct scmi_handle *h,
                               struct scmi_xfer *xfer);
 int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
                       size_t tx_size, size_t rx_size, struct scmi_xfer **p);
+void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle,
+                           struct scmi_xfer *xfer);
 int scmi_handle_put(const struct scmi_handle *handle);
 struct scmi_handle *scmi_handle_get(struct device *dev);
 void scmi_set_handle(struct scmi_device *scmi_dev);
index c5dea87..3dfd8b6 100644 (file)
@@ -402,6 +402,14 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
        return ret;
 }
 
+void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle,
+                           struct scmi_xfer *xfer)
+{
+       struct scmi_info *info = handle_to_scmi_info(handle);
+
+       xfer->rx.len = info->desc->max_msg_size;
+}
+
 #define SCMI_MAX_RESPONSE_TIMEOUT      (2 * MSEC_PER_SEC)
 
 /**
index 2754f9d..ce33689 100644 (file)
@@ -1403,15 +1403,21 @@ static void scmi_protocols_late_init(struct work_struct *work)
                                "finalized PENDING handler - key:%X\n",
                                hndl->key);
                        ret = scmi_event_handler_enable_events(hndl);
+                       if (ret) {
+                               dev_dbg(ni->handle->dev,
+                                       "purging INVALID handler - key:%X\n",
+                                       hndl->key);
+                               scmi_put_active_handler(ni, hndl);
+                       }
                } else {
                        ret = scmi_valid_pending_handler(ni, hndl);
-               }
-               if (ret) {
-                       dev_dbg(ni->handle->dev,
-                               "purging PENDING handler - key:%X\n",
-                               hndl->key);
-                       /* this hndl can be only a pending one */
-                       scmi_put_handler_unlocked(ni, hndl);
+                       if (ret) {
+                               dev_dbg(ni->handle->dev,
+                                       "purging PENDING handler - key:%X\n",
+                                       hndl->key);
+                               /* this hndl can be only a pending one */
+                               scmi_put_handler_unlocked(ni, hndl);
+                       }
                }
        }
        mutex_unlock(&ni->pending_mtx);
@@ -1468,7 +1474,7 @@ int scmi_notification_init(struct scmi_handle *handle)
        ni->gid = gid;
        ni->handle = handle;
 
-       ni->notify_wq = alloc_workqueue("scmi_notify",
+       ni->notify_wq = alloc_workqueue(dev_name(handle->dev),
                                        WQ_UNBOUND | WQ_FREEZABLE | WQ_SYSFS,
                                        0);
        if (!ni->notify_wq)
index ed475b4..82fb3ba 100644 (file)
@@ -304,6 +304,8 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain,
                }
 
                tot_opp_cnt += num_returned;
+
+               scmi_reset_rx_to_maxsz(handle, t);
                /*
                 * check for both returned and remaining to avoid infinite
                 * loop due to buggy firmware
index f063cfe..a981a22 100644 (file)
@@ -36,9 +36,7 @@ struct scmi_msg_reset_domain_reset {
 #define EXPLICIT_RESET_ASSERT  BIT(1)
 #define ASYNCHRONOUS_RESET     BIT(2)
        __le32 reset_state;
-#define ARCH_RESET_TYPE                BIT(31)
-#define COLD_RESET_STATE       BIT(0)
-#define ARCH_COLD_RESET                (ARCH_RESET_TYPE | COLD_RESET_STATE)
+#define ARCH_COLD_RESET                0
 };
 
 struct scmi_msg_reset_notify {
index 9703cf6..b4232d6 100644 (file)
@@ -166,6 +166,8 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
                }
 
                desc_index += num_returned;
+
+               scmi_reset_rx_to_maxsz(handle, t);
                /*
                 * check for both returned and remaining to avoid infinite
                 * loop due to buggy firmware
index 1a03c3e..82a82a5 100644 (file)
@@ -149,6 +149,6 @@ static const struct scmi_transport_ops scmi_smc_ops = {
 const struct scmi_desc scmi_smc_desc = {
        .ops = &scmi_smc_ops,
        .max_rx_timeout_ms = 30,
-       .max_msg = 1,
+       .max_msg = 20,
        .max_msg_size = 128,
 };
index c241317..42d9748 100644 (file)
@@ -1066,6 +1066,7 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x7319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
        {0x1002, 0x731A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
        {0x1002, 0x731B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
+       {0x1002, 0x731E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
        {0x1002, 0x731F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
        /* Navi14 */
        {0x1002, 0x7340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14},
index aa7f230..7e8265d 100644 (file)
@@ -596,6 +596,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
        struct ww_acquire_ctx ticket;
        struct list_head list, duplicates;
        uint64_t va_flags;
+       uint64_t vm_size;
        int r = 0;
 
        if (args->va_address < AMDGPU_VA_RESERVED_SIZE) {
@@ -616,6 +617,15 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
 
        args->va_address &= AMDGPU_GMC_HOLE_MASK;
 
+       vm_size = adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE;
+       vm_size -= AMDGPU_VA_RESERVED_SIZE;
+       if (args->va_address + args->map_size > vm_size) {
+               dev_dbg(&dev->pdev->dev,
+                       "va_address 0x%llx is in top reserved area 0x%llx\n",
+                       args->va_address + args->map_size, vm_size);
+               return -EINVAL;
+       }
+
        if ((args->flags & ~valid_flags) && (args->flags & ~prt_flags)) {
                dev_dbg(&dev->pdev->dev, "invalid flags combination 0x%08X\n",
                        args->flags);
index c6abb16..58c83a7 100644 (file)
@@ -112,8 +112,8 @@ struct amdgpu_bo_list_entry;
 #define AMDGPU_MMHUB_0                         1
 #define AMDGPU_MMHUB_1                         2
 
-/* hardcode that limit for now */
-#define AMDGPU_VA_RESERVED_SIZE                        (1ULL << 20)
+/* Reserve 2MB at top/bottom of address space for kernel use */
+#define AMDGPU_VA_RESERVED_SIZE                        (2ULL << 20)
 
 /* max vmids dedicated for process */
 #define AMDGPU_VM_MAX_RESERVED_VMID    1
index 1ce741a..03462c8 100644 (file)
@@ -455,6 +455,14 @@ void nv_set_virt_ops(struct amdgpu_device *adev)
        adev->virt.ops = &xgpu_nv_virt_ops;
 }
 
+static bool nv_is_blockchain_sku(struct pci_dev *pdev)
+{
+       if (pdev->device == 0x731E &&
+           (pdev->revision == 0xC6 || pdev->revision == 0xC7))
+               return true;
+       return false;
+}
+
 int nv_set_ip_blocks(struct amdgpu_device *adev)
 {
        int r;
@@ -483,7 +491,8 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
                if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
                        amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
-               else if (amdgpu_device_has_dc_support(adev))
+               else if (amdgpu_device_has_dc_support(adev) &&
+                        !nv_is_blockchain_sku(adev->pdev))
                        amdgpu_device_ip_block_add(adev, &dm_ip_block);
 #endif
                amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
@@ -491,7 +500,8 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
                if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT &&
                    !amdgpu_sriov_vf(adev))
                        amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
-               amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
+               if (!nv_is_blockchain_sku(adev->pdev))
+                       amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
                amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
                if (adev->enable_mes)
                        amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
index f24abf4..60dfdd4 100644 (file)
@@ -42,6 +42,7 @@ config DRM_AMD_DC_SI
 config DEBUG_KERNEL_DC
        bool "Enable kgdb break in DC"
        depends on DRM_AMD_DC
+       depends on KGDB
        help
          Choose this option if you want to hit kdgb_break in assert.
 
index 1eb29c3..45ad05f 100644 (file)
@@ -1571,8 +1571,8 @@ static void init_state(struct dc *dc, struct dc_state *context)
 
 struct dc_state *dc_create_state(struct dc *dc)
 {
-       struct dc_state *context = kzalloc(sizeof(struct dc_state),
-                                          GFP_KERNEL);
+       struct dc_state *context = kvzalloc(sizeof(struct dc_state),
+                                           GFP_KERNEL);
 
        if (!context)
                return NULL;
index 9cc65dc..49ae5ff 100644 (file)
@@ -1149,7 +1149,8 @@ static uint32_t dcn3_get_pix_clk_dividers(
 static const struct clock_source_funcs dcn3_clk_src_funcs = {
        .cs_power_down = dce110_clock_source_power_down,
        .program_pix_clk = dcn3_program_pix_clk,
-       .get_pix_clk_dividers = dcn3_get_pix_clk_dividers
+       .get_pix_clk_dividers = dcn3_get_pix_clk_dividers,
+       .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
 };
 #endif
 /*****************************************/
index 24fb39a..2455d21 100644 (file)
@@ -2105,12 +2105,12 @@ static bool dcn30_internal_validate_bw(
 
                if (split[i]) {
                        if (odm) {
-                               if (split[i] == 4 && old_pipe->next_odm_pipe->next_odm_pipe)
+                               if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe)
                                        old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
                                else if (old_pipe->next_odm_pipe)
                                        old_index = old_pipe->next_odm_pipe->pipe_idx;
                        } else {
-                               if (split[i] == 4 && old_pipe->bottom_pipe->bottom_pipe &&
+                               if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
                                                old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
                                        old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx;
                                else if (old_pipe->bottom_pipe &&
@@ -2150,10 +2150,12 @@ static bool dcn30_internal_validate_bw(
                                goto validate_fail;
                        newly_split[pipe_4to1->pipe_idx] = true;
 
-                       if (odm && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe)
+                       if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe
+                                       && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe)
                                old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx;
-                       else if (!odm && old_pipe->bottom_pipe->bottom_pipe->bottom_pipe &&
-                                               old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
+                       else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe &&
+                                       old_pipe->bottom_pipe->bottom_pipe->bottom_pipe &&
+                                       old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state)
                                old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx;
                        else
                                old_index = -1;
index 3be2c90..2158369 100644 (file)
@@ -117,6 +117,12 @@ static const struct ddc_registers ddc_data_regs_dcn[] = {
        ddc_data_regs_dcn2(4),
        ddc_data_regs_dcn2(5),
        ddc_data_regs_dcn2(6),
+       {
+                       DDC_GPIO_VGA_REG_LIST(DATA),
+                       .ddc_setup = 0,
+                       .phy_aux_cntl = 0,
+                       .dc_gpio_aux_ctrl_5 = 0
+       }
 };
 
 static const struct ddc_registers ddc_clk_regs_dcn[] = {
@@ -126,6 +132,12 @@ static const struct ddc_registers ddc_clk_regs_dcn[] = {
        ddc_clk_regs_dcn2(4),
        ddc_clk_regs_dcn2(5),
        ddc_clk_regs_dcn2(6),
+       {
+                       DDC_GPIO_VGA_REG_LIST(CLK),
+                       .ddc_setup = 0,
+                       .phy_aux_cntl = 0,
+                       .dc_gpio_aux_ctrl_5 = 0
+       }
 };
 
 static const struct ddc_sh_mask ddc_shift[] = {
index f67c183..dac427b 100644 (file)
@@ -63,13 +63,13 @@ enum gpio_result dal_gpio_open_ex(
        enum gpio_mode mode)
 {
        if (gpio->pin) {
-               ASSERT_CRITICAL(false);
+               BREAK_TO_DEBUGGER();
                return GPIO_RESULT_ALREADY_OPENED;
        }
 
        // No action if allocation failed during gpio construct
        if (!gpio->hw_container.ddc) {
-               ASSERT_CRITICAL(false);
+               BREAK_TO_DEBUGGER();
                return GPIO_RESULT_NON_SPECIFIC_ERROR;
        }
        gpio->mode = mode;
index 330acaa..95cb569 100644 (file)
  * general debug capabilities
  *
  */
-#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB)
-#define ASSERT_CRITICAL(expr) do {     \
-       if (WARN_ON(!(expr))) { \
-               kgdb_breakpoint(); \
-       } \
-} while (0)
+#ifdef CONFIG_DEBUG_KERNEL_DC
+#define dc_breakpoint()                kgdb_breakpoint()
 #else
-#define ASSERT_CRITICAL(expr) do {     \
-       if (WARN_ON(!(expr))) { \
-               ; \
-       } \
-} while (0)
+#define dc_breakpoint()                do {} while (0)
 #endif
 
-#if defined(CONFIG_DEBUG_KERNEL_DC)
-#define ASSERT(expr) ASSERT_CRITICAL(expr)
+#define ASSERT_CRITICAL(expr) do {             \
+               if (WARN_ON(!(expr)))           \
+                       dc_breakpoint();        \
+       } while (0)
 
-#else
-#define ASSERT(expr) WARN_ON_ONCE(!(expr))
-#endif
+#define ASSERT(expr) do {                      \
+               if (WARN_ON_ONCE(!(expr)))      \
+                       dc_breakpoint();        \
+       } while (0)
 
-#if defined(CONFIG_DEBUG_KERNEL_DC) && (defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB))
 #define BREAK_TO_DEBUGGER() \
        do { \
                DRM_DEBUG_DRIVER("%s():%d\n", __func__, __LINE__); \
-               kgdb_breakpoint(); \
+               dc_breakpoint(); \
        } while (0)
-#else
-#define BREAK_TO_DEBUGGER() DRM_DEBUG_DRIVER("%s():%d\n", __func__, __LINE__)
-#endif
 
 #define DC_ERR(...)  do { \
        dm_error(__VA_ARGS__); \
index 8d8081c..ef1a62e 100644 (file)
@@ -1361,14 +1361,9 @@ static int navi10_get_fan_speed_rpm(struct smu_context *smu,
        if (!speed)
                return -EINVAL;
 
-       switch (smu_v11_0_get_fan_control_mode(smu)) {
-       case AMD_FAN_CTRL_AUTO:
-               return navi10_get_smu_metrics_data(smu,
-                                                  METRICS_CURR_FANSPEED,
-                                                  speed);
-       default:
-               return smu_v11_0_get_fan_speed_rpm(smu, speed);
-       }
+       return navi10_get_smu_metrics_data(smu,
+                                          METRICS_CURR_FANSPEED,
+                                          speed);
 }
 
 static int navi10_get_fan_parameters(struct smu_context *smu)
@@ -2534,29 +2529,6 @@ static const struct i2c_algorithm navi10_i2c_algo = {
        .functionality = navi10_i2c_func,
 };
 
-static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
-{
-       struct amdgpu_device *adev = to_amdgpu_device(control);
-       int res;
-
-       control->owner = THIS_MODULE;
-       control->class = I2C_CLASS_SPD;
-       control->dev.parent = &adev->pdev->dev;
-       control->algo = &navi10_i2c_algo;
-       snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
-
-       res = i2c_add_adapter(control);
-       if (res)
-               DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
-
-       return res;
-}
-
-static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
-{
-       i2c_del_adapter(control);
-}
-
 static ssize_t navi10_get_gpu_metrics(struct smu_context *smu,
                                      void **table)
 {
@@ -2687,8 +2659,6 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .set_default_dpm_table = navi10_set_default_dpm_table,
        .dpm_set_vcn_enable = navi10_dpm_set_vcn_enable,
        .dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable,
-       .i2c_init = navi10_i2c_control_init,
-       .i2c_fini = navi10_i2c_control_fini,
        .print_clk_levels = navi10_print_clk_levels,
        .force_clk_levels = navi10_force_clk_levels,
        .populate_umd_state_clk = navi10_populate_umd_state_clk,
index 685a8a3..895d89b 100644 (file)
@@ -1177,14 +1177,9 @@ static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu,
        if (!speed)
                return -EINVAL;
 
-       switch (smu_v11_0_get_fan_control_mode(smu)) {
-       case AMD_FAN_CTRL_AUTO:
-               return sienna_cichlid_get_smu_metrics_data(smu,
-                                                          METRICS_CURR_FANSPEED,
-                                                          speed);
-       default:
-               return smu_v11_0_get_fan_speed_rpm(smu, speed);
-       }
+       return sienna_cichlid_get_smu_metrics_data(smu,
+                                               METRICS_CURR_FANSPEED,
+                                               speed);
 }
 
 static int sienna_cichlid_get_fan_parameters(struct smu_context *smu)
index 90807a6..deeed73 100644 (file)
@@ -374,6 +374,10 @@ static bool is_edid_digital_input_dp(const struct edid *edid)
  * drm_dp_downstream_is_type() - is the downstream facing port of certain type?
  * @dpcd: DisplayPort configuration data
  * @port_cap: port capabilities
+ * @type: port type to be checked. Can be:
+ *       %DP_DS_PORT_TYPE_DP, %DP_DS_PORT_TYPE_VGA, %DP_DS_PORT_TYPE_DVI,
+ *       %DP_DS_PORT_TYPE_HDMI, %DP_DS_PORT_TYPE_NON_EDID,
+ *       %DP_DS_PORT_TYPE_DP_DUALMODE or %DP_DS_PORT_TYPE_WIRELESS.
  *
  * Caveat: Only works with DPCD 1.1+ port caps.
  *
@@ -870,6 +874,7 @@ EXPORT_SYMBOL(drm_dp_downstream_444_to_420_conversion);
 
 /**
  * drm_dp_downstream_mode() - return a mode for downstream facing port
+ * @dev: DRM device
  * @dpcd: DisplayPort configuration data
  * @port_cap: port capabilities
  *
@@ -1028,7 +1033,8 @@ EXPORT_SYMBOL(drm_dp_downstream_debug);
 
 /**
  * drm_dp_subconnector_type() - get DP branch device type
- *
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
  */
 enum drm_mode_subconnector
 drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
@@ -1079,6 +1085,10 @@ EXPORT_SYMBOL(drm_dp_subconnector_type);
 
 /**
  * drm_mode_set_dp_subconnector_property - set subconnector for DP connector
+ * @connector: connector to set property on
+ * @status: connector status
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
  *
  * Called by a driver on every detect event.
  */
index a82f37d..631125b 100644 (file)
@@ -3741,7 +3741,7 @@ drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)
 /**
  * drm_display_mode_from_cea_vic() - return a mode for CEA VIC
  * @dev: DRM device
- * @vic: CEA VIC of the mode
+ * @video_code: CEA VIC of the mode
  *
  * Creates a new mode matching the specified CEA VIC.
  *
index 19d7386..69c2c07 100644 (file)
@@ -1085,6 +1085,8 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
         */
        drm_gem_object_get(obj);
 
+       vma->vm_private_data = obj;
+
        if (obj->funcs && obj->funcs->mmap) {
                ret = obj->funcs->mmap(obj, vma);
                if (ret) {
@@ -1107,8 +1109,6 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
                vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
        }
 
-       vma->vm_private_data = obj;
-
        return 0;
 }
 EXPORT_SYMBOL(drm_gem_mmap_obj);
index d77c9f8..e00616d 100644 (file)
@@ -593,8 +593,13 @@ int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
        /* Remove the fake offset */
        vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
 
-       if (obj->import_attach)
+       if (obj->import_attach) {
+               /* Drop the reference drm_gem_mmap_obj() acquired.*/
+               drm_gem_object_put(obj);
+               vma->vm_private_data = NULL;
+
                return dma_buf_mmap(obj->dma_buf, vma, 0);
+       }
 
        shmem = to_drm_gem_shmem_obj(obj);
 
index d6808f6..9f955f2 100644 (file)
@@ -794,6 +794,7 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
 
 /**
  * drm_prime_pages_to_sg - converts a page array into an sg list
+ * @dev: DRM device
  * @pages: pointer to the array of page pointers to convert
  * @nr_pages: length of the page vector
  *
index 829b2a4..31337d2 100644 (file)
@@ -10636,6 +10636,10 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
            val & PLANE_CTL_FLIP_HORIZONTAL)
                plane_config->rotation |= DRM_MODE_REFLECT_X;
 
+       /* 90/270 degree rotation would require extra work */
+       if (drm_rotation_90_or_270(plane_config->rotation))
+               goto error;
+
        base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000;
        plane_config->base = base;
 
index 366ddfc..fb5e30d 100644 (file)
@@ -389,6 +389,7 @@ static const struct intel_device_info ilk_m_info = {
        GEN5_FEATURES,
        PLATFORM(INTEL_IRONLAKE),
        .is_mobile = 1,
+       .has_rps = true,
        .display.has_fbc = 1,
 };
 
index 6b5e9d8..180e107 100644 (file)
@@ -87,7 +87,7 @@ __intel_memory_region_get_pages_buddy(struct intel_memory_region *mem,
                min_order = ilog2(size) - ilog2(mem->mm.chunk_size);
        }
 
-       if (size > BIT(mem->mm.max_order) * mem->mm.chunk_size)
+       if (size > mem->mm.size)
                return -E2BIG;
 
        n_pages = size >> ilog2(mem->mm.chunk_size);
index 334b064..0aeba8e 100644 (file)
@@ -261,6 +261,82 @@ err_close_objects:
        return err;
 }
 
+static int igt_mock_splintered_region(void *arg)
+{
+       struct intel_memory_region *mem = arg;
+       struct drm_i915_private *i915 = mem->i915;
+       struct drm_i915_gem_object *obj;
+       unsigned int expected_order;
+       LIST_HEAD(objects);
+       u64 size;
+       int err = 0;
+
+       /*
+        * Sanity check we can still allocate everything even if the
+        * mm.max_order != mm.size. i.e our starting address space size is not a
+        * power-of-two.
+        */
+
+       size = (SZ_4G - 1) & PAGE_MASK;
+       mem = mock_region_create(i915, 0, size, PAGE_SIZE, 0);
+       if (IS_ERR(mem))
+               return PTR_ERR(mem);
+
+       if (mem->mm.size != size) {
+               pr_err("%s size mismatch(%llu != %llu)\n",
+                      __func__, mem->mm.size, size);
+               err = -EINVAL;
+               goto out_put;
+       }
+
+       expected_order = get_order(rounddown_pow_of_two(size));
+       if (mem->mm.max_order != expected_order) {
+               pr_err("%s order mismatch(%u != %u)\n",
+                      __func__, mem->mm.max_order, expected_order);
+               err = -EINVAL;
+               goto out_put;
+       }
+
+       obj = igt_object_create(mem, &objects, size, 0);
+       if (IS_ERR(obj)) {
+               err = PTR_ERR(obj);
+               goto out_close;
+       }
+
+       close_objects(mem, &objects);
+
+       /*
+        * While we should be able allocate everything without any flag
+        * restrictions, if we consider I915_BO_ALLOC_CONTIGUOUS then we are
+        * actually limited to the largest power-of-two for the region size i.e
+        * max_order, due to the inner workings of the buddy allocator. So make
+        * sure that does indeed hold true.
+        */
+
+       obj = igt_object_create(mem, &objects, size, I915_BO_ALLOC_CONTIGUOUS);
+       if (!IS_ERR(obj)) {
+               pr_err("%s too large contiguous allocation was not rejected\n",
+                      __func__);
+               err = -EINVAL;
+               goto out_close;
+       }
+
+       obj = igt_object_create(mem, &objects, rounddown_pow_of_two(size),
+                               I915_BO_ALLOC_CONTIGUOUS);
+       if (IS_ERR(obj)) {
+               pr_err("%s largest possible contiguous allocation failed\n",
+                      __func__);
+               err = PTR_ERR(obj);
+               goto out_close;
+       }
+
+out_close:
+       close_objects(mem, &objects);
+out_put:
+       intel_memory_region_put(mem);
+       return err;
+}
+
 static int igt_gpu_write_dw(struct intel_context *ce,
                            struct i915_vma *vma,
                            u32 dword,
@@ -771,6 +847,7 @@ int intel_memory_region_mock_selftests(void)
        static const struct i915_subtest tests[] = {
                SUBTEST(igt_mock_fill),
                SUBTEST(igt_mock_contiguous),
+               SUBTEST(igt_mock_splintered_region),
        };
        struct intel_memory_region *mem;
        struct drm_i915_private *i915;
index 09660f5..979d96f 100644 (file)
@@ -24,7 +24,7 @@ mock_object_create(struct intel_memory_region *mem,
        struct drm_i915_private *i915 = mem->i915;
        struct drm_i915_gem_object *obj;
 
-       if (size > BIT(mem->mm.max_order) * mem->mm.chunk_size)
+       if (size > mem->mm.size)
                return ERR_PTR(-E2BIG);
 
        obj = i915_gem_object_alloc();
index 498622c..f750881 100644 (file)
@@ -44,6 +44,7 @@ int core507d_new_(const struct nv50_core_func *, struct nouveau_drm *, s32,
                  struct nv50_core **);
 int core507d_init(struct nv50_core *);
 void core507d_ntfy_init(struct nouveau_bo *, u32);
+int core507d_read_caps(struct nv50_disp *disp);
 int core507d_caps_init(struct nouveau_drm *, struct nv50_disp *);
 int core507d_ntfy_wait_done(struct nouveau_bo *, u32, struct nvif_device *);
 int core507d_update(struct nv50_core *, u32 *, bool);
@@ -55,6 +56,7 @@ extern const struct nv50_outp_func pior507d;
 int core827d_new(struct nouveau_drm *, s32, struct nv50_core **);
 
 int core907d_new(struct nouveau_drm *, s32, struct nv50_core **);
+int core907d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp);
 extern const struct nv50_outp_func dac907d;
 extern const struct nv50_outp_func sor907d;
 
index 248edf6..e6f16a7 100644 (file)
@@ -78,19 +78,56 @@ core507d_ntfy_init(struct nouveau_bo *bo, u32 offset)
 }
 
 int
-core507d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp)
+core507d_read_caps(struct nv50_disp *disp)
 {
        struct nvif_push *push = disp->core->chan.push;
        int ret;
 
-       if ((ret = PUSH_WAIT(push, 2)))
+       ret = PUSH_WAIT(push, 6);
+       if (ret)
                return ret;
 
+       PUSH_MTHD(push, NV507D, SET_NOTIFIER_CONTROL,
+                 NVDEF(NV507D, SET_NOTIFIER_CONTROL, MODE, WRITE) |
+                 NVVAL(NV507D, SET_NOTIFIER_CONTROL, OFFSET, NV50_DISP_CORE_NTFY >> 2) |
+                 NVDEF(NV507D, SET_NOTIFIER_CONTROL, NOTIFY, ENABLE));
+
        PUSH_MTHD(push, NV507D, GET_CAPABILITIES, 0x00000000);
+
+       PUSH_MTHD(push, NV507D, SET_NOTIFIER_CONTROL,
+                 NVDEF(NV507D, SET_NOTIFIER_CONTROL, NOTIFY, DISABLE));
+
        return PUSH_KICK(push);
 }
 
 int
+core507d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp)
+{
+       struct nv50_core *core = disp->core;
+       struct nouveau_bo *bo = disp->sync;
+       s64 time;
+       int ret;
+
+       NVBO_WR32(bo, NV50_DISP_CORE_NTFY, NV_DISP_CORE_NOTIFIER_1, CAPABILITIES_1,
+                                    NVDEF(NV_DISP_CORE_NOTIFIER_1, CAPABILITIES_1, DONE, FALSE));
+
+       ret = core507d_read_caps(disp);
+       if (ret < 0)
+               return ret;
+
+       time = nvif_msec(core->chan.base.device, 2000ULL,
+                        if (NVBO_TD32(bo, NV50_DISP_CORE_NTFY,
+                                      NV_DISP_CORE_NOTIFIER_1, CAPABILITIES_1, DONE, ==, TRUE))
+                                break;
+                        usleep_range(1, 2);
+                        );
+       if (time < 0)
+               NV_ERROR(drm, "core caps notifier timeout\n");
+
+       return 0;
+}
+
+int
 core507d_init(struct nv50_core *core)
 {
        struct nvif_push *push = core->chan.push;
index b17c035..8564d4d 100644 (file)
 #include "core.h"
 #include "head.h"
 
+#include <nvif/push507c.h>
+#include <nvif/timer.h>
+
+#include <nvhw/class/cl907d.h>
+
+#include "nouveau_bo.h"
+
+int
+core907d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp)
+{
+       struct nv50_core *core = disp->core;
+       struct nouveau_bo *bo = disp->sync;
+       s64 time;
+       int ret;
+
+       NVBO_WR32(bo, NV50_DISP_CORE_NTFY, NV907D_CORE_NOTIFIER_3, CAPABILITIES_4,
+                                    NVDEF(NV907D_CORE_NOTIFIER_3, CAPABILITIES_4, DONE, FALSE));
+
+       ret = core507d_read_caps(disp);
+       if (ret < 0)
+               return ret;
+
+       time = nvif_msec(core->chan.base.device, 2000ULL,
+                        if (NVBO_TD32(bo, NV50_DISP_CORE_NTFY,
+                                      NV907D_CORE_NOTIFIER_3, CAPABILITIES_4, DONE, ==, TRUE))
+                                break;
+                        usleep_range(1, 2);
+                        );
+       if (time < 0)
+               NV_ERROR(drm, "core caps notifier timeout\n");
+
+       return 0;
+}
+
 static const struct nv50_core_func
 core907d = {
        .init = core507d_init,
        .ntfy_init = core507d_ntfy_init,
-       .caps_init = core507d_caps_init,
+       .caps_init = core907d_caps_init,
        .ntfy_wait_done = core507d_ntfy_wait_done,
        .update = core507d_update,
        .head = &head907d,
index 66846f3..1cd3a2a 100644 (file)
@@ -26,7 +26,7 @@ static const struct nv50_core_func
 core917d = {
        .init = core507d_init,
        .ntfy_init = core507d_ntfy_init,
-       .caps_init = core507d_caps_init,
+       .caps_init = core907d_caps_init,
        .ntfy_wait_done = core507d_ntfy_wait_done,
        .update = core507d_update,
        .head = &head917d,
index 2e444ba..6a463f3 100644 (file)
 #define NV_DISP_CORE_NOTIFIER_1_COMPLETION_0_DONE_TRUE                               0x00000001
 #define NV_DISP_CORE_NOTIFIER_1_COMPLETION_0_R0                                      15:1
 #define NV_DISP_CORE_NOTIFIER_1_COMPLETION_0_TIMESTAMP                               29:16
-
+#define NV_DISP_CORE_NOTIFIER_1_CAPABILITIES_1                                       0x00000001
+#define NV_DISP_CORE_NOTIFIER_1_CAPABILITIES_1_DONE                                  0:0
+#define NV_DISP_CORE_NOTIFIER_1_CAPABILITIES_1_DONE_FALSE                            0x00000000
+#define NV_DISP_CORE_NOTIFIER_1_CAPABILITIES_1_DONE_TRUE                             0x00000001
 
 // class methods
 #define NV507D_UPDATE                                                           (0x00000080)
index 34bc3ea..79aff6f 100644 (file)
 #ifndef _cl907d_h_
 #define _cl907d_h_
 
+#define NV907D_CORE_NOTIFIER_3_CAPABILITIES_4                                       0x00000004
+#define NV907D_CORE_NOTIFIER_3_CAPABILITIES_4_DONE                                  0:0
+#define NV907D_CORE_NOTIFIER_3_CAPABILITIES_4_DONE_FALSE                            0x00000000
+#define NV907D_CORE_NOTIFIER_3_CAPABILITIES_4_DONE_TRUE                             0x00000001
 #define NV907D_CORE_NOTIFIER_3_CAPABILITIES_CAP_SOR0_20                             0x00000014
 #define NV907D_CORE_NOTIFIER_3_CAPABILITIES_CAP_SOR0_20_SINGLE_LVDS18               0:0
 #define NV907D_CORE_NOTIFIER_3_CAPABILITIES_CAP_SOR0_20_SINGLE_LVDS18_FALSE         0x00000000
index 49dd0cb..6f21f36 100644 (file)
@@ -1023,29 +1023,6 @@ get_tmds_link_bandwidth(struct drm_connector *connector)
                return 112000 * duallink_scale;
 }
 
-enum drm_mode_status
-nouveau_conn_mode_clock_valid(const struct drm_display_mode *mode,
-                             const unsigned min_clock,
-                             const unsigned max_clock,
-                             unsigned int *clock_out)
-{
-       unsigned int clock = mode->clock;
-
-       if ((mode->flags & DRM_MODE_FLAG_3D_MASK) ==
-           DRM_MODE_FLAG_3D_FRAME_PACKING)
-               clock *= 2;
-
-       if (clock < min_clock)
-               return MODE_CLOCK_LOW;
-       if (clock > max_clock)
-               return MODE_CLOCK_HIGH;
-
-       if (clock_out)
-               *clock_out = clock;
-
-       return MODE_OK;
-}
-
 static enum drm_mode_status
 nouveau_connector_mode_valid(struct drm_connector *connector,
                             struct drm_display_mode *mode)
@@ -1053,7 +1030,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
        struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
        struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
-       unsigned min_clock = 25000, max_clock = min_clock;
+       unsigned int min_clock = 25000, max_clock = min_clock, clock = mode->clock;
 
        switch (nv_encoder->dcb->type) {
        case DCB_OUTPUT_LVDS:
@@ -1082,8 +1059,15 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
                return MODE_BAD;
        }
 
-       return nouveau_conn_mode_clock_valid(mode, min_clock, max_clock,
-                                            NULL);
+       if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
+               clock *= 2;
+
+       if (clock < min_clock)
+               return MODE_CLOCK_LOW;
+       if (clock > max_clock)
+               return MODE_CLOCK_HIGH;
+
+       return MODE_OK;
 }
 
 static struct drm_encoder *
index 7b640e0..040ed88 100644 (file)
@@ -231,23 +231,30 @@ nv50_dp_mode_valid(struct drm_connector *connector,
                   const struct drm_display_mode *mode,
                   unsigned *out_clock)
 {
-       const unsigned min_clock = 25000;
-       unsigned max_clock, ds_clock, clock;
-       enum drm_mode_status ret;
+       const unsigned int min_clock = 25000;
+       unsigned int max_rate, mode_rate, ds_max_dotclock, clock = mode->clock;
+       const u8 bpp = connector->display_info.bpc * 3;
 
        if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace)
                return MODE_NO_INTERLACE;
 
-       max_clock = outp->dp.link_nr * outp->dp.link_bw;
-       ds_clock = drm_dp_downstream_max_dotclock(outp->dp.dpcd,
-                                                 outp->dp.downstream_ports);
-       if (ds_clock)
-               max_clock = min(max_clock, ds_clock);
+       if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
+               clock *= 2;
+
+       max_rate = outp->dp.link_nr * outp->dp.link_bw;
+       mode_rate = DIV_ROUND_UP(clock * bpp, 8);
+       if (mode_rate > max_rate)
+               return MODE_CLOCK_HIGH;
+
+       ds_max_dotclock = drm_dp_downstream_max_dotclock(outp->dp.dpcd, outp->dp.downstream_ports);
+       if (ds_max_dotclock && clock > ds_max_dotclock)
+               return MODE_CLOCK_HIGH;
+
+       if (clock < min_clock)
+               return MODE_CLOCK_LOW;
 
-       clock = mode->clock * (connector->display_info.bpc * 3) / 10;
-       ret = nouveau_conn_mode_clock_valid(mode, min_clock, max_clock,
-                                           &clock);
        if (out_clock)
                *out_clock = clock;
-       return ret;
+
+       return MODE_OK;
 }
index 89adadf..549bc67 100644 (file)
@@ -190,7 +190,8 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain,
         * to the caller, instead of a normal nouveau_bo ttm reference. */
        ret = drm_gem_object_init(drm->dev, &nvbo->bo.base, size);
        if (ret) {
-               nouveau_bo_ref(NULL, &nvbo);
+               drm_gem_object_release(&nvbo->bo.base);
+               kfree(nvbo);
                return ret;
        }
 
index 2df1c04..4f69e4c 100644 (file)
@@ -105,11 +105,11 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
        struct nouveau_cli *cli = nouveau_cli(file_priv);
        struct drm_nouveau_svm_bind *args = data;
        unsigned target, cmd, priority;
-       unsigned long addr, end, size;
+       unsigned long addr, end;
        struct mm_struct *mm;
 
        args->va_start &= PAGE_MASK;
-       args->va_end &= PAGE_MASK;
+       args->va_end = ALIGN(args->va_end, PAGE_SIZE);
 
        /* Sanity check arguments */
        if (args->reserved0 || args->reserved1)
@@ -118,8 +118,6 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
                return -EINVAL;
        if (args->va_start >= args->va_end)
                return -EINVAL;
-       if (!args->npages)
-               return -EINVAL;
 
        cmd = args->header >> NOUVEAU_SVM_BIND_COMMAND_SHIFT;
        cmd &= NOUVEAU_SVM_BIND_COMMAND_MASK;
@@ -151,12 +149,6 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
        if (args->stride)
                return -EINVAL;
 
-       size = ((unsigned long)args->npages) << PAGE_SHIFT;
-       if ((args->va_start + size) <= args->va_start)
-               return -EINVAL;
-       if ((args->va_start + size) > args->va_end)
-               return -EINVAL;
-
        /*
         * Ok we are ask to do something sane, for now we only support migrate
         * commands but we will add things like memory policy (what to do on
@@ -171,7 +163,7 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       for (addr = args->va_start, end = args->va_start + size; addr < end;) {
+       for (addr = args->va_start, end = args->va_end; addr < end;) {
                struct vm_area_struct *vma;
                unsigned long next;
 
index dcb7067..7851bec 100644 (file)
@@ -2924,17 +2924,34 @@ nvkm_device_del(struct nvkm_device **pdevice)
        }
 }
 
+/* returns true if the GPU is in the CPU native byte order */
 static inline bool
 nvkm_device_endianness(struct nvkm_device *device)
 {
-       u32 boot1 = nvkm_rd32(device, 0x000004) & 0x01000001;
 #ifdef __BIG_ENDIAN
-       if (!boot1)
-               return false;
+       const bool big_endian = true;
 #else
-       if (boot1)
-               return false;
+       const bool big_endian = false;
 #endif
+
+       /* Read NV_PMC_BOOT_1, and assume non-functional endian switch if it
+        * doesn't contain the expected values.
+        */
+       u32 pmc_boot_1 = nvkm_rd32(device, 0x000004);
+       if (pmc_boot_1 && pmc_boot_1 != 0x01000001)
+               return !big_endian; /* Assume GPU is LE in this case. */
+
+       /* 0 means LE and 0x01000001 means BE GPU. Condition is true when
+        * GPU/CPU endianness don't match.
+        */
+       if (big_endian == !pmc_boot_1) {
+               nvkm_wr32(device, 0x000004, 0x01000001);
+               nvkm_rd32(device, 0x000000);
+               if (nvkm_rd32(device, 0x000004) != (big_endian ? 0x01000001 : 0x00000000))
+                       return !big_endian; /* Assume GPU is LE on any unexpected read-back. */
+       }
+
+       /* CPU/GPU endianness should (hopefully) match. */
        return true;
 }
 
@@ -2987,14 +3004,10 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
        if (detect) {
                /* switch mmio to cpu's native endianness */
                if (!nvkm_device_endianness(device)) {
-                       nvkm_wr32(device, 0x000004, 0x01000001);
-                       nvkm_rd32(device, 0x000000);
-                       if (!nvkm_device_endianness(device)) {
-                               nvdev_error(device,
-                                           "GPU not supported on big-endian\n");
-                               ret = -ENOSYS;
-                               goto done;
-                       }
+                       nvdev_error(device,
+                                   "Couldn't switch GPU to CPUs endianess\n");
+                       ret = -ENOSYS;
+                       goto done;
                }
 
                boot0 = nvkm_rd32(device, 0x000000);
index 3482e28..0c5f22e 100644 (file)
@@ -26,7 +26,9 @@
 struct mantix {
        struct device *dev;
        struct drm_panel panel;
+
        struct gpio_desc *reset_gpio;
+       struct gpio_desc *tp_rstn_gpio;
 
        struct regulator *avdd;
        struct regulator *avee;
@@ -124,6 +126,10 @@ static int mantix_unprepare(struct drm_panel *panel)
 {
        struct mantix *ctx = panel_to_mantix(panel);
 
+       gpiod_set_value_cansleep(ctx->tp_rstn_gpio, 1);
+       usleep_range(5000, 6000);
+       gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
        regulator_disable(ctx->avee);
        regulator_disable(ctx->avdd);
        /* T11 */
@@ -165,13 +171,10 @@ static int mantix_prepare(struct drm_panel *panel)
                return ret;
        }
 
-       /* T3+T5 */
-       usleep_range(10000, 12000);
-
-       gpiod_set_value_cansleep(ctx->reset_gpio, 1);
-       usleep_range(5150, 7000);
-
+       /* T3 + T4 + time for voltage to become stable: */
+       usleep_range(6000, 7000);
        gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+       gpiod_set_value_cansleep(ctx->tp_rstn_gpio, 0);
 
        /* T6 */
        msleep(50);
@@ -204,7 +207,7 @@ static int mantix_get_modes(struct drm_panel *panel,
        if (!mode) {
                dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
                        default_mode.hdisplay, default_mode.vdisplay,
-                       drm_mode_vrefresh(mode));
+                       drm_mode_vrefresh(&default_mode));
                return -ENOMEM;
        }
 
@@ -236,12 +239,18 @@ static int mantix_probe(struct mipi_dsi_device *dsi)
        if (!ctx)
                return -ENOMEM;
 
-       ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+       ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(ctx->reset_gpio)) {
                dev_err(dev, "cannot get reset gpio\n");
                return PTR_ERR(ctx->reset_gpio);
        }
 
+       ctx->tp_rstn_gpio = devm_gpiod_get(dev, "mantix,tp-rstn", GPIOD_OUT_HIGH);
+       if (IS_ERR(ctx->tp_rstn_gpio)) {
+               dev_err(dev, "cannot get tp-rstn gpio\n");
+               return PTR_ERR(ctx->tp_rstn_gpio);
+       }
+
        mipi_dsi_set_drvdata(dsi, ctx);
        ctx->dev = dev;
 
index b51cc68..edb60ae 100644 (file)
@@ -407,6 +407,7 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
        struct drm_framebuffer *fb = state->fb;
        const struct drm_format_info *format = fb->format;
        uint64_t modifier = fb->modifier;
+       unsigned int ch1_phase_idx;
        u32 out_fmt_val;
        u32 in_fmt_val, in_mod_val, in_ps_val;
        unsigned int i;
@@ -442,18 +443,19 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
         * I have no idea what this does exactly, but it seems to be
         * related to the scaler FIR filter phase parameters.
         */
+       ch1_phase_idx = (format->num_planes > 1) ? 1 : 0;
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZPHASE_REG,
-                    frontend->data->ch_phase[0].horzphase);
+                    frontend->data->ch_phase[0]);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZPHASE_REG,
-                    frontend->data->ch_phase[1].horzphase);
+                    frontend->data->ch_phase[ch1_phase_idx]);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE0_REG,
-                    frontend->data->ch_phase[0].vertphase[0]);
+                    frontend->data->ch_phase[0]);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE0_REG,
-                    frontend->data->ch_phase[1].vertphase[0]);
+                    frontend->data->ch_phase[ch1_phase_idx]);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG,
-                    frontend->data->ch_phase[0].vertphase[1]);
+                    frontend->data->ch_phase[0]);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG,
-                    frontend->data->ch_phase[1].vertphase[1]);
+                    frontend->data->ch_phase[ch1_phase_idx]);
 
        /*
         * Checking the input format is sufficient since we currently only
@@ -687,30 +689,12 @@ static const struct dev_pm_ops sun4i_frontend_pm_ops = {
 };
 
 static const struct sun4i_frontend_data sun4i_a10_frontend = {
-       .ch_phase               = {
-               {
-                       .horzphase = 0,
-                       .vertphase = { 0, 0 },
-               },
-               {
-                       .horzphase = 0xfc000,
-                       .vertphase = { 0xfc000, 0xfc000 },
-               },
-       },
+       .ch_phase               = { 0x000, 0xfc000 },
        .has_coef_rdy           = true,
 };
 
 static const struct sun4i_frontend_data sun8i_a33_frontend = {
-       .ch_phase               = {
-               {
-                       .horzphase = 0x400,
-                       .vertphase = { 0x400, 0x400 },
-               },
-               {
-                       .horzphase = 0x400,
-                       .vertphase = { 0x400, 0x400 },
-               },
-       },
+       .ch_phase               = { 0x400, 0xfc400 },
        .has_coef_access_ctrl   = true,
 };
 
index 0c382c1..2e7b76e 100644 (file)
@@ -115,11 +115,7 @@ struct reset_control;
 struct sun4i_frontend_data {
        bool    has_coef_access_ctrl;
        bool    has_coef_rdy;
-
-       struct {
-               u32     horzphase;
-               u32     vertphase[2];
-       } ch_phase[2];
+       u32     ch_phase[2];
 };
 
 struct sun4i_frontend {
index 915f8bf..182c586 100644 (file)
@@ -568,7 +568,6 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
                ret = v3d_job_init(v3d, file_priv, &bin->base,
                                   v3d_job_free, args->in_sync_bcl);
                if (ret) {
-                       kfree(bin);
                        v3d_job_put(&render->base);
                        kfree(bin);
                        return ret;
index f1a5fd5..a17aa1d 100644 (file)
@@ -314,6 +314,7 @@ unbind_all:
        component_unbind_all(dev, drm);
 gem_destroy:
        vc4_gem_destroy(drm);
+       drm_mode_config_cleanup(drm);
        vc4_bo_cache_destroy(drm);
 dev_put:
        drm_dev_put(drm);
index 90b911f..66d4fb1 100644 (file)
@@ -287,7 +287,7 @@ struct vc4_bo {
 static inline struct vc4_bo *
 to_vc4_bo(struct drm_gem_object *bo)
 {
-       return (struct vc4_bo *)bo;
+       return container_of(to_drm_gem_cma_obj(bo), struct vc4_bo, base);
 }
 
 struct vc4_fence {
@@ -300,7 +300,7 @@ struct vc4_fence {
 static inline struct vc4_fence *
 to_vc4_fence(struct dma_fence *fence)
 {
-       return (struct vc4_fence *)fence;
+       return container_of(fence, struct vc4_fence, base);
 }
 
 struct vc4_seqno_cb {
@@ -347,7 +347,7 @@ struct vc4_plane {
 static inline struct vc4_plane *
 to_vc4_plane(struct drm_plane *plane)
 {
-       return (struct vc4_plane *)plane;
+       return container_of(plane, struct vc4_plane, base);
 }
 
 enum vc4_scaling_mode {
@@ -423,7 +423,7 @@ struct vc4_plane_state {
 static inline struct vc4_plane_state *
 to_vc4_plane_state(struct drm_plane_state *state)
 {
-       return (struct vc4_plane_state *)state;
+       return container_of(state, struct vc4_plane_state, base);
 }
 
 enum vc4_encoder_type {
@@ -499,7 +499,7 @@ struct vc4_crtc {
 static inline struct vc4_crtc *
 to_vc4_crtc(struct drm_crtc *crtc)
 {
-       return (struct vc4_crtc *)crtc;
+       return container_of(crtc, struct vc4_crtc, base);
 }
 
 static inline const struct vc4_crtc_data *
@@ -537,7 +537,7 @@ struct vc4_crtc_state {
 static inline struct vc4_crtc_state *
 to_vc4_crtc_state(struct drm_crtc_state *crtc_state)
 {
-       return (struct vc4_crtc_state *)crtc_state;
+       return container_of(crtc_state, struct vc4_crtc_state, base);
 }
 
 #define V3D_READ(offset) readl(vc4->v3d->regs + offset)
index e8f99e2..95779d5 100644 (file)
@@ -922,6 +922,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
                                    struct snd_soc_dai *dai)
 {
        struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+       struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
        struct device *dev = &vc4_hdmi->pdev->dev;
        u32 audio_packet_config, channel_mask;
        u32 channel_map;
@@ -981,6 +982,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
        HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
        vc4_hdmi_set_n_cts(vc4_hdmi);
 
+       vc4_hdmi_set_audio_infoframe(encoder);
+
        return 0;
 }
 
@@ -988,11 +991,9 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
                                  struct snd_soc_dai *dai)
 {
        struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
-       struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               vc4_hdmi_set_audio_infoframe(encoder);
                vc4_hdmi->audio.streaming = true;
 
                if (vc4_hdmi->variant->phy_rng_enable)
@@ -1076,6 +1077,7 @@ static const struct snd_soc_dapm_route vc4_hdmi_audio_routes[] = {
 };
 
 static const struct snd_soc_component_driver vc4_hdmi_audio_component_drv = {
+       .name                   = "vc4-hdmi-codec-dai-component",
        .controls               = vc4_hdmi_audio_controls,
        .num_controls           = ARRAY_SIZE(vc4_hdmi_audio_controls),
        .dapm_widgets           = vc4_hdmi_audio_widgets,
index 56f5b80..01bace4 100644 (file)
@@ -1239,7 +1239,7 @@ static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
                struct acpi_processor_cx *cx;
                struct cpuidle_state *state;
 
-               if (intel_idle_max_cstate_reached(cstate))
+               if (intel_idle_max_cstate_reached(cstate - 1))
                        break;
 
                cx = &acpi_state_table.states[cstate];
index 7c2ab1f..a77750b 100644 (file)
@@ -405,10 +405,10 @@ static int cma_comp_exch(struct rdma_id_private *id_priv,
        /*
         * The FSM uses a funny double locking where state is protected by both
         * the handler_mutex and the spinlock. State is not allowed to change
-        * away from a handler_mutex protected value without also holding
+        * to/from a handler_mutex protected value without also holding
         * handler_mutex.
         */
-       if (comp == RDMA_CM_CONNECT)
+       if (comp == RDMA_CM_CONNECT || exch == RDMA_CM_CONNECT)
                lockdep_assert_held(&id_priv->handler_mutex);
 
        spin_lock_irqsave(&id_priv->lock, flags);
@@ -4038,17 +4038,23 @@ out:
        return ret;
 }
 
-int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
+/**
+ * rdma_connect_locked - Initiate an active connection request.
+ * @id: Connection identifier to connect.
+ * @conn_param: Connection information used for connected QPs.
+ *
+ * Same as rdma_connect() but can only be called from the
+ * RDMA_CM_EVENT_ROUTE_RESOLVED handler callback.
+ */
+int rdma_connect_locked(struct rdma_cm_id *id,
+                       struct rdma_conn_param *conn_param)
 {
        struct rdma_id_private *id_priv =
                container_of(id, struct rdma_id_private, id);
        int ret;
 
-       mutex_lock(&id_priv->handler_mutex);
-       if (!cma_comp_exch(id_priv, RDMA_CM_ROUTE_RESOLVED, RDMA_CM_CONNECT)) {
-               ret = -EINVAL;
-               goto err_unlock;
-       }
+       if (!cma_comp_exch(id_priv, RDMA_CM_ROUTE_RESOLVED, RDMA_CM_CONNECT))
+               return -EINVAL;
 
        if (!id->qp) {
                id_priv->qp_num = conn_param->qp_num;
@@ -4066,11 +4072,33 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
                ret = -ENOSYS;
        if (ret)
                goto err_state;
-       mutex_unlock(&id_priv->handler_mutex);
        return 0;
 err_state:
        cma_comp_exch(id_priv, RDMA_CM_CONNECT, RDMA_CM_ROUTE_RESOLVED);
-err_unlock:
+       return ret;
+}
+EXPORT_SYMBOL(rdma_connect_locked);
+
+/**
+ * rdma_connect - Initiate an active connection request.
+ * @id: Connection identifier to connect.
+ * @conn_param: Connection information used for connected QPs.
+ *
+ * Users must have resolved a route for the rdma_cm_id to connect with by having
+ * called rdma_resolve_route before calling this routine.
+ *
+ * This call will either connect to a remote QP or obtain remote QP information
+ * for unconnected rdma_cm_id's.  The actual operation is based on the
+ * rdma_cm_id's port space.
+ */
+int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
+{
+       struct rdma_id_private *id_priv =
+               container_of(id, struct rdma_id_private, id);
+       int ret;
+
+       mutex_lock(&id_priv->handler_mutex);
+       ret = rdma_connect_locked(id, conn_param);
        mutex_unlock(&id_priv->handler_mutex);
        return ret;
 }
index f367d52..302f898 100644 (file)
@@ -401,9 +401,6 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_GID_ENTRY)(
        if (!rdma_is_port_valid(ib_dev, port_num))
                return -EINVAL;
 
-       if (!rdma_ib_or_roce(ib_dev, port_num))
-               return -EOPNOTSUPP;
-
        gid_attr = rdma_get_gid_attr(ib_dev, port_num, gid_index);
        if (IS_ERR(gid_attr))
                return PTR_ERR(gid_attr);
index 89e04ca..246e3cb 100644 (file)
@@ -3305,7 +3305,8 @@ static int mlx5_add_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num)
        int err;
 
        dev->port[port_num].roce.nb.notifier_call = mlx5_netdev_event;
-       err = register_netdevice_notifier(&dev->port[port_num].roce.nb);
+       err = register_netdevice_notifier_net(mlx5_core_net(dev->mdev),
+                                             &dev->port[port_num].roce.nb);
        if (err) {
                dev->port[port_num].roce.nb.notifier_call = NULL;
                return err;
@@ -3317,7 +3318,8 @@ static int mlx5_add_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num)
 static void mlx5_remove_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num)
 {
        if (dev->port[port_num].roce.nb.notifier_call) {
-               unregister_netdevice_notifier(&dev->port[port_num].roce.nb);
+               unregister_netdevice_notifier_net(mlx5_core_net(dev->mdev),
+                                                 &dev->port[port_num].roce.nb);
                dev->port[port_num].roce.nb.notifier_call = NULL;
        }
 }
index c7169d2..c4bc587 100644 (file)
@@ -727,6 +727,7 @@ int qedr_iw_destroy_listen(struct iw_cm_id *cm_id)
                                                    listener->qed_handle);
 
        cm_id->rem_ref(cm_id);
+       kfree(listener);
        return rc;
 }
 
index 38021e2..df0d173 100644 (file)
@@ -16,15 +16,24 @@ void rxe_init_av(struct rdma_ah_attr *attr, struct rxe_av *av)
 
 int rxe_av_chk_attr(struct rxe_dev *rxe, struct rdma_ah_attr *attr)
 {
+       const struct ib_global_route *grh = rdma_ah_read_grh(attr);
        struct rxe_port *port;
+       int type;
 
        port = &rxe->port;
 
        if (rdma_ah_get_ah_flags(attr) & IB_AH_GRH) {
-               u8 sgid_index = rdma_ah_read_grh(attr)->sgid_index;
+               if (grh->sgid_index > port->attr.gid_tbl_len) {
+                       pr_warn("invalid sgid index = %d\n",
+                                       grh->sgid_index);
+                       return -EINVAL;
+               }
 
-               if (sgid_index > port->attr.gid_tbl_len) {
-                       pr_warn("invalid sgid index = %d\n", sgid_index);
+               type = rdma_gid_attr_network_type(grh->sgid_attr);
+               if (type < RDMA_NETWORK_IPV4 ||
+                   type > RDMA_NETWORK_IPV6) {
+                       pr_warn("invalid network type for rdma_rxe = %d\n",
+                                       type);
                        return -EINVAL;
                }
        }
@@ -65,11 +74,29 @@ void rxe_av_to_attr(struct rxe_av *av, struct rdma_ah_attr *attr)
 void rxe_av_fill_ip_info(struct rxe_av *av, struct rdma_ah_attr *attr)
 {
        const struct ib_gid_attr *sgid_attr = attr->grh.sgid_attr;
+       int ibtype;
+       int type;
 
        rdma_gid2ip((struct sockaddr *)&av->sgid_addr, &sgid_attr->gid);
        rdma_gid2ip((struct sockaddr *)&av->dgid_addr,
                    &rdma_ah_read_grh(attr)->dgid);
-       av->network_type = rdma_gid_attr_network_type(sgid_attr);
+
+       ibtype = rdma_gid_attr_network_type(sgid_attr);
+
+       switch (ibtype) {
+       case RDMA_NETWORK_IPV4:
+               type = RXE_NETWORK_TYPE_IPV4;
+               break;
+       case RDMA_NETWORK_IPV6:
+               type = RXE_NETWORK_TYPE_IPV4;
+               break;
+       default:
+               /* not reached - checked in rxe_av_chk_attr */
+               type = 0;
+               break;
+       }
+
+       av->network_type = type;
 }
 
 struct rxe_av *rxe_get_av(struct rxe_pkt_info *pkt)
index 575e1a4..34bef7d 100644 (file)
@@ -442,7 +442,7 @@ struct sk_buff *rxe_init_packet(struct rxe_dev *rxe, struct rxe_av *av,
        if (IS_ERR(attr))
                return NULL;
 
-       if (av->network_type == RXE_NETWORK_TYPE_IPV6)
+       if (av->network_type == RXE_NETWORK_TYPE_IPV4)
                hdr_len = ETH_HLEN + sizeof(struct udphdr) +
                        sizeof(struct iphdr);
        else
index 2f3ebc0..2bd18b0 100644 (file)
@@ -620,7 +620,7 @@ static void iser_route_handler(struct rdma_cm_id *cma_id)
        conn_param.private_data = (void *)&req_hdr;
        conn_param.private_data_len = sizeof(struct iser_cm_hdr);
 
-       ret = rdma_connect(cma_id, &conn_param);
+       ret = rdma_connect_locked(cma_id, &conn_param);
        if (ret) {
                iser_err("failure connecting: %d\n", ret);
                goto failure;
index 776e892..f298adc 100644 (file)
@@ -1674,9 +1674,9 @@ static int rtrs_rdma_route_resolved(struct rtrs_clt_con *con)
        uuid_copy(&msg.sess_uuid, &sess->s.uuid);
        uuid_copy(&msg.paths_uuid, &clt->paths_uuid);
 
-       err = rdma_connect(con->c.cm_id, &param);
+       err = rdma_connect_locked(con->c.cm_id, &param);
        if (err)
-               rtrs_err(clt, "rdma_connect(): %d\n", err);
+               rtrs_err(clt, "rdma_connect_locked(): %d\n", err);
 
        return err;
 }
index a5ef9fa..e7f0d4a 100644 (file)
@@ -1176,8 +1176,10 @@ mptscsih_remove(struct pci_dev *pdev)
        MPT_SCSI_HOST           *hd;
        int sz1;
 
-       if((hd = shost_priv(host)) == NULL)
-               return;
+       if (host == NULL)
+               hd = NULL;
+       else
+               hd = shost_priv(host);
 
        mptscsih_shutdown(pdev);
 
@@ -1193,14 +1195,15 @@ mptscsih_remove(struct pci_dev *pdev)
            "Free'd ScsiLookup (%d) memory\n",
            ioc->name, sz1));
 
-       kfree(hd->info_kbuf);
+       if (hd)
+               kfree(hd->info_kbuf);
 
        /* NULL the Scsi_Host pointer
         */
        ioc->sh = NULL;
 
-       scsi_host_put(host);
-
+       if (host)
+               scsi_host_put(host);
        mpt_detach(pdev);
 
 }
index a30796e..6de02f0 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (c) 2007 Freescale Semiconductor, Inc.
  * Copyright (c) 2009 MontaVista Software, Inc.
  * Copyright (c) 2010 Pengutronix e.K.
+ * Copyright 2020 NXP
  *   Author: Wolfram Sang <kernel@pengutronix.de>
  */
 
@@ -88,6 +89,7 @@
 /* DLL Config 0 Register */
 #define ESDHC_DLLCFG0                  0x160
 #define ESDHC_DLL_ENABLE               0x80000000
+#define ESDHC_DLL_RESET                        0x40000000
 #define ESDHC_DLL_FREQ_SEL             0x08000000
 
 /* DLL Config 1 Register */
index 0b45eff..bb09445 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright (c) 2007, 2010, 2012 Freescale Semiconductor, Inc.
  * Copyright (c) 2009 MontaVista Software, Inc.
+ * Copyright 2020 NXP
  *
  * Authors: Xiaobo Xie <X.Xie@freescale.com>
  *         Anton Vorontsov <avorontsov@ru.mvista.com>
@@ -19,6 +20,7 @@
 #include <linux/clk.h>
 #include <linux/ktime.h>
 #include <linux/dma-mapping.h>
+#include <linux/iopoll.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include "sdhci-pltfm.h"
@@ -743,6 +745,21 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
                if (host->mmc->actual_clock == MMC_HS200_MAX_DTR)
                        temp |= ESDHC_DLL_FREQ_SEL;
                sdhci_writel(host, temp, ESDHC_DLLCFG0);
+
+               temp |= ESDHC_DLL_RESET;
+               sdhci_writel(host, temp, ESDHC_DLLCFG0);
+               udelay(1);
+               temp &= ~ESDHC_DLL_RESET;
+               sdhci_writel(host, temp, ESDHC_DLLCFG0);
+
+               /* Wait max 20 ms */
+               if (read_poll_timeout(sdhci_readl, temp,
+                                     temp & ESDHC_DLL_STS_SLV_LOCK,
+                                     10, 20000, false,
+                                     host, ESDHC_DLLSTAT0))
+                       pr_err("%s: timeout for delay chain lock.\n",
+                              mmc_hostname(host->mmc));
+
                temp = sdhci_readl(host, ESDHC_TBCTL);
                sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL);
 
@@ -1052,6 +1069,17 @@ static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 
        esdhc_tuning_block_enable(host, true);
 
+       /*
+        * The eSDHC controller takes the data timeout value into account
+        * during tuning. If the SD card is too slow sending the response, the
+        * timer will expire and a "Buffer Read Ready" interrupt without data
+        * is triggered. This leads to tuning errors.
+        *
+        * Just set the timeout to the maximum value because the core will
+        * already take care of it in sdhci_send_tuning().
+        */
+       sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL);
+
        hs400_tuning = host->flags & SDHCI_HS400_TUNING;
 
        do {
index 592a55a..3561ae8 100644 (file)
@@ -1384,9 +1384,11 @@ static inline void sdhci_auto_cmd_select(struct sdhci_host *host,
        /*
         * In case of Version 4.10 or later, use of 'Auto CMD Auto
         * Select' is recommended rather than use of 'Auto CMD12
-        * Enable' or 'Auto CMD23 Enable'.
+        * Enable' or 'Auto CMD23 Enable'. We require Version 4 Mode
+        * here because some controllers (e.g sdhci-of-dwmshc) expect it.
         */
-       if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) {
+       if (host->version >= SDHCI_SPEC_410 && host->v4_mode &&
+           (use_cmd12 || use_cmd23)) {
                *mode |= SDHCI_TRNS_AUTO_SEL;
 
                ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
index fa14786..7975f59 100644 (file)
@@ -1160,16 +1160,6 @@ static void bnxt_queue_sp_work(struct bnxt *bp)
                schedule_work(&bp->sp_task);
 }
 
-static void bnxt_cancel_sp_work(struct bnxt *bp)
-{
-       if (BNXT_PF(bp)) {
-               flush_workqueue(bnxt_pf_wq);
-       } else {
-               cancel_work_sync(&bp->sp_task);
-               cancel_delayed_work_sync(&bp->fw_reset_task);
-       }
-}
-
 static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
 {
        if (!rxr->bnapi->in_reset) {
@@ -4362,7 +4352,8 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
        u32 bar_offset = BNXT_GRCPF_REG_CHIMP_COMM;
        u16 dst = BNXT_HWRM_CHNL_CHIMP;
 
-       if (BNXT_NO_FW_ACCESS(bp))
+       if (BNXT_NO_FW_ACCESS(bp) &&
+           le16_to_cpu(req->req_type) != HWRM_FUNC_RESET)
                return -EBUSY;
 
        if (msg_len > BNXT_HWRM_MAX_REQ_LEN) {
@@ -9789,7 +9780,10 @@ int bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
 {
        int rc = 0;
 
-       rc = __bnxt_open_nic(bp, irq_re_init, link_re_init);
+       if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state))
+               rc = -EIO;
+       if (!rc)
+               rc = __bnxt_open_nic(bp, irq_re_init, link_re_init);
        if (rc) {
                netdev_err(bp->dev, "nic open fail (rc: %x)\n", rc);
                dev_close(bp->dev);
@@ -12108,15 +12102,17 @@ static void bnxt_remove_one(struct pci_dev *pdev)
        if (BNXT_PF(bp))
                bnxt_sriov_disable(bp);
 
-       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
-       bnxt_cancel_sp_work(bp);
-       bp->sp_event = 0;
-
-       bnxt_dl_fw_reporters_destroy(bp, true);
        if (BNXT_PF(bp))
                devlink_port_type_clear(&bp->dl_port);
        pci_disable_pcie_error_reporting(pdev);
        unregister_netdev(dev);
+       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+       /* Flush any pending tasks */
+       cancel_work_sync(&bp->sp_task);
+       cancel_delayed_work_sync(&bp->fw_reset_task);
+       bp->sp_event = 0;
+
+       bnxt_dl_fw_reporters_destroy(bp, true);
        bnxt_dl_unregister(bp);
        bnxt_shutdown_tc(bp);
 
@@ -12860,6 +12856,9 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
                return PCI_ERS_RESULT_DISCONNECT;
        }
 
+       if (state == pci_channel_io_frozen)
+               set_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state);
+
        if (netif_running(netdev))
                bnxt_close(netdev);
 
@@ -12886,7 +12885,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct bnxt *bp = netdev_priv(netdev);
-       int err = 0;
+       int err = 0, off;
        pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT;
 
        netdev_info(bp->dev, "PCI Slot Reset\n");
@@ -12898,6 +12897,20 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
                        "Cannot re-enable PCI device after reset.\n");
        } else {
                pci_set_master(pdev);
+               /* Upon fatal error, our device internal logic that latches to
+                * BAR value is getting reset and will restore only upon
+                * rewritting the BARs.
+                *
+                * As pci_restore_state() does not re-write the BARs if the
+                * value is same as saved value earlier, driver needs to
+                * write the BARs to 0 to force restore, in case of fatal error.
+                */
+               if (test_and_clear_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN,
+                                      &bp->state)) {
+                       for (off = PCI_BASE_ADDRESS_0;
+                            off <= PCI_BASE_ADDRESS_5; off += 4)
+                               pci_write_config_dword(bp->pdev, off, 0);
+               }
                pci_restore_state(pdev);
                pci_save_state(pdev);
 
index 21ef1c2..47b3c31 100644 (file)
@@ -1781,6 +1781,7 @@ struct bnxt {
 #define BNXT_STATE_ABORT_ERR   5
 #define BNXT_STATE_FW_FATAL_COND       6
 #define BNXT_STATE_DRV_REGISTERED      7
+#define BNXT_STATE_PCI_CHANNEL_IO_FROZEN       8
 
 #define BNXT_NO_FW_ACCESS(bp)                                  \
        (test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) ||    \
index 6ec5f2f..4e55f70 100644 (file)
@@ -145,13 +145,13 @@ static int configure_filter_smac(struct adapter *adap, struct filter_entry *f)
        int err;
 
        /* do a set-tcb for smac-sel and CWR bit.. */
-       err = set_tcb_tflag(adap, f, f->tid, TF_CCTRL_CWR_S, 1, 1);
-       if (err)
-               goto smac_err;
-
        err = set_tcb_field(adap, f, f->tid, TCB_SMAC_SEL_W,
                            TCB_SMAC_SEL_V(TCB_SMAC_SEL_M),
                            TCB_SMAC_SEL_V(f->smt->idx), 1);
+       if (err)
+               goto smac_err;
+
+       err = set_tcb_tflag(adap, f, f->tid, TF_CCTRL_CWR_S, 1, 1);
        if (!err)
                return 0;
 
@@ -862,6 +862,7 @@ int set_filter_wr(struct adapter *adapter, int fidx)
                      FW_FILTER_WR_DIRSTEERHASH_V(f->fs.dirsteerhash) |
                      FW_FILTER_WR_LPBK_V(f->fs.action == FILTER_SWITCH) |
                      FW_FILTER_WR_DMAC_V(f->fs.newdmac) |
+                     FW_FILTER_WR_SMAC_V(f->fs.newsmac) |
                      FW_FILTER_WR_INSVLAN_V(f->fs.newvlan == VLAN_INSERT ||
                                             f->fs.newvlan == VLAN_REWRITE) |
                      FW_FILTER_WR_RMVLAN_V(f->fs.newvlan == VLAN_REMOVE ||
@@ -879,7 +880,7 @@ int set_filter_wr(struct adapter *adapter, int fidx)
                 FW_FILTER_WR_OVLAN_VLD_V(f->fs.val.ovlan_vld) |
                 FW_FILTER_WR_IVLAN_VLDM_V(f->fs.mask.ivlan_vld) |
                 FW_FILTER_WR_OVLAN_VLDM_V(f->fs.mask.ovlan_vld));
-       fwr->smac_sel = 0;
+       fwr->smac_sel = f->smt->idx;
        fwr->rx_chan_rx_rpl_iq =
                htons(FW_FILTER_WR_RX_CHAN_V(0) |
                      FW_FILTER_WR_RX_RPL_IQ_V(adapter->sge.fw_evtq.abs_id));
@@ -1323,11 +1324,8 @@ static void mk_act_open_req6(struct filter_entry *f, struct sk_buff *skb,
                            TX_QUEUE_V(f->fs.nat_mode) |
                            T5_OPT_2_VALID_F |
                            RX_CHANNEL_V(cxgb4_port_e2cchan(f->dev)) |
-                           CONG_CNTRL_V((f->fs.action == FILTER_DROP) |
-                                        (f->fs.dirsteer << 1)) |
                            PACE_V((f->fs.maskhash) |
-                                  ((f->fs.dirsteerhash) << 1)) |
-                           CCTRL_ECN_V(f->fs.action == FILTER_SWITCH));
+                                  ((f->fs.dirsteerhash) << 1)));
 }
 
 static void mk_act_open_req(struct filter_entry *f, struct sk_buff *skb,
@@ -1363,11 +1361,8 @@ static void mk_act_open_req(struct filter_entry *f, struct sk_buff *skb,
                            TX_QUEUE_V(f->fs.nat_mode) |
                            T5_OPT_2_VALID_F |
                            RX_CHANNEL_V(cxgb4_port_e2cchan(f->dev)) |
-                           CONG_CNTRL_V((f->fs.action == FILTER_DROP) |
-                                        (f->fs.dirsteer << 1)) |
                            PACE_V((f->fs.maskhash) |
-                                  ((f->fs.dirsteerhash) << 1)) |
-                           CCTRL_ECN_V(f->fs.action == FILTER_SWITCH));
+                                  ((f->fs.dirsteerhash) << 1)));
 }
 
 static int cxgb4_set_hash_filter(struct net_device *dev,
@@ -2039,6 +2034,20 @@ void hash_filter_rpl(struct adapter *adap, const struct cpl_act_open_rpl *rpl)
                        }
                        return;
                }
+               switch (f->fs.action) {
+               case FILTER_PASS:
+                       if (f->fs.dirsteer)
+                               set_tcb_tflag(adap, f, tid,
+                                             TF_DIRECT_STEER_S, 1, 1);
+                       break;
+               case FILTER_DROP:
+                       set_tcb_tflag(adap, f, tid, TF_DROP_S, 1, 1);
+                       break;
+               case FILTER_SWITCH:
+                       set_tcb_tflag(adap, f, tid, TF_LPBK_S, 1, 1);
+                       break;
+               }
+
                break;
 
        default:
@@ -2106,22 +2115,11 @@ void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl)
                        if (ctx)
                                ctx->result = 0;
                } else if (ret == FW_FILTER_WR_FLT_ADDED) {
-                       int err = 0;
-
-                       if (f->fs.newsmac)
-                               err = configure_filter_smac(adap, f);
-
-                       if (!err) {
-                               f->pending = 0;  /* async setup completed */
-                               f->valid = 1;
-                               if (ctx) {
-                                       ctx->result = 0;
-                                       ctx->tid = idx;
-                               }
-                       } else {
-                               clear_filter(adap, f);
-                               if (ctx)
-                                       ctx->result = err;
+                       f->pending = 0;  /* async setup completed */
+                       f->valid = 1;
+                       if (ctx) {
+                               ctx->result = 0;
+                               ctx->tid = idx;
                        }
                } else {
                        /* Something went wrong.  Issue a warning about the
index 50232e0..92473dd 100644 (file)
 #define TCB_T_FLAGS_M          0xffffffffffffffffULL
 #define TCB_T_FLAGS_V(x)       ((__u64)(x) << TCB_T_FLAGS_S)
 
+#define TF_DROP_S              22
+#define TF_DIRECT_STEER_S      23
+#define TF_LPBK_S              59
+
 #define TF_CCTRL_ECE_S         60
 #define TF_CCTRL_CWR_S         61
 #define TF_CCTRL_RFR_S         62
index ec4f790..d581c4e 100644 (file)
@@ -772,14 +772,13 @@ static int chtls_pass_open_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
        if (rpl->status != CPL_ERR_NONE) {
                pr_info("Unexpected PASS_OPEN_RPL status %u for STID %u\n",
                        rpl->status, stid);
-               return CPL_RET_BUF_DONE;
+       } else {
+               cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
+               sock_put(listen_ctx->lsk);
+               kfree(listen_ctx);
+               module_put(THIS_MODULE);
        }
-       cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
-       sock_put(listen_ctx->lsk);
-       kfree(listen_ctx);
-       module_put(THIS_MODULE);
-
-       return 0;
+       return CPL_RET_BUF_DONE;
 }
 
 static int chtls_close_listsrv_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
@@ -796,15 +795,13 @@ static int chtls_close_listsrv_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
        if (rpl->status != CPL_ERR_NONE) {
                pr_info("Unexpected CLOSE_LISTSRV_RPL status %u for STID %u\n",
                        rpl->status, stid);
-               return CPL_RET_BUF_DONE;
+       } else {
+               cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
+               sock_put(listen_ctx->lsk);
+               kfree(listen_ctx);
+               module_put(THIS_MODULE);
        }
-
-       cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
-       sock_put(listen_ctx->lsk);
-       kfree(listen_ctx);
-       module_put(THIS_MODULE);
-
-       return 0;
+       return CPL_RET_BUF_DONE;
 }
 
 static void chtls_purge_wr_queue(struct sock *sk)
@@ -1514,7 +1511,6 @@ static void add_to_reap_list(struct sock *sk)
        struct chtls_sock *csk = sk->sk_user_data;
 
        local_bh_disable();
-       bh_lock_sock(sk);
        release_tcp_port(sk); /* release the port immediately */
 
        spin_lock(&reap_list_lock);
@@ -1523,7 +1519,6 @@ static void add_to_reap_list(struct sock *sk)
        if (!csk->passive_reap_next)
                schedule_work(&reap_task);
        spin_unlock(&reap_list_lock);
-       bh_unlock_sock(sk);
        local_bh_enable();
 }
 
index 9fb5ca6..188d871 100644 (file)
@@ -1585,6 +1585,7 @@ skip_copy:
                        tp->urg_data = 0;
 
                if ((avail + offset) >= skb->len) {
+                       struct sk_buff *next_skb;
                        if (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_TLS_HDR) {
                                tp->copied_seq += skb->len;
                                hws->rcvpld = skb->hdr_len;
@@ -1595,8 +1596,10 @@ skip_copy:
                        chtls_free_skb(sk, skb);
                        buffers_freed++;
                        hws->copied_seq = 0;
-                       if (copied >= target &&
-                           !skb_peek(&sk->sk_receive_queue))
+                       next_skb = skb_peek(&sk->sk_receive_queue);
+                       if (copied >= target && !next_skb)
+                               break;
+                       if (ULP_SKB_CB(next_skb)->flags & ULPCB_FLAG_TLS_HDR)
                                break;
                }
        } while (len > 0);
index 714b501..ba8869c 100644 (file)
@@ -1358,7 +1358,7 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
            (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
                upsmr |= UCC_GETH_UPSMR_TBIM;
        }
-       if ((ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII))
+       if (ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII)
                upsmr |= UCC_GETH_UPSMR_SGMM;
 
        out_be32(&uf_regs->upsmr, upsmr);
index 15f69fa..e8495f5 100644 (file)
@@ -1373,7 +1373,7 @@ static int hclge_tm_bp_setup(struct hclge_dev *hdev)
                        return ret;
        }
 
-       return ret;
+       return 0;
 }
 
 int hclge_pause_setup_hw(struct hclge_dev *hdev, bool init)
index 50c84c5..c8e3fdd 100644 (file)
@@ -3262,8 +3262,8 @@ static void hclgevf_uninit_hdev(struct hclgevf_dev *hdev)
                hclgevf_uninit_msi(hdev);
        }
 
-       hclgevf_pci_uninit(hdev);
        hclgevf_cmd_uninit(hdev);
+       hclgevf_pci_uninit(hdev);
        hclgevf_uninit_mac_list(hdev);
 }
 
index 7ef3369..c3ec9ce 100644 (file)
@@ -1031,12 +1031,6 @@ static int ibmveth_is_packet_unsupported(struct sk_buff *skb,
                ret = -EOPNOTSUPP;
        }
 
-       if (!ether_addr_equal(ether_header->h_source, netdev->dev_addr)) {
-               netdev_dbg(netdev, "source packet MAC address does not match veth device's, dropping packet.\n");
-               netdev->stats.tx_dropped++;
-               ret = -EOPNOTSUPP;
-       }
-
        return ret;
 }
 
index 8148f79..af4dfbe 100644 (file)
@@ -1815,9 +1815,13 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p)
        int rc;
 
        rc = 0;
-       ether_addr_copy(adapter->mac_addr, addr->sa_data);
-       if (adapter->state != VNIC_PROBED)
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       if (adapter->state != VNIC_PROBED) {
+               ether_addr_copy(adapter->mac_addr, addr->sa_data);
                rc = __ibmvnic_set_mac(netdev, addr->sa_data);
+       }
 
        return rc;
 }
index d046db7..3a9fa62 100644 (file)
@@ -90,9 +90,4 @@ int mlx5_create_encryption_key(struct mlx5_core_dev *mdev,
                               u32 key_type, u32 *p_key_id);
 void mlx5_destroy_encryption_key(struct mlx5_core_dev *mdev, u32 key_id);
 
-static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev)
-{
-       return devlink_net(priv_to_devlink(dev));
-}
-
 #endif
index 7f77c2a..937b8e4 100644 (file)
@@ -620,6 +620,9 @@ static void mlxsw_emad_transmit_retry(struct mlxsw_core *mlxsw_core,
                err = mlxsw_emad_transmit(trans->core, trans);
                if (err == 0)
                        return;
+
+               if (!atomic_dec_and_test(&trans->active))
+                       return;
        } else {
                err = -EIO;
        }
@@ -2064,6 +2067,8 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
        if (!reload)
                devlink_resources_unregister(devlink, NULL);
        mlxsw_core->bus->fini(mlxsw_core->bus_priv);
+       if (!reload)
+               devlink_free(devlink);
 
        return;
 
index 16b47fc..b08853f 100644 (file)
@@ -1174,11 +1174,14 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port)
        u32 eth_proto_cap, eth_proto_admin, eth_proto_oper;
        const struct mlxsw_sp_port_type_speed_ops *ops;
        char ptys_pl[MLXSW_REG_PTYS_LEN];
+       u32 eth_proto_cap_masked;
        int err;
 
        ops = mlxsw_sp->port_type_speed_ops;
 
-       /* Set advertised speeds to supported speeds. */
+       /* Set advertised speeds to speeds supported by both the driver
+        * and the device.
+        */
        ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
                               0, false);
        err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
@@ -1187,8 +1190,10 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port)
 
        ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap,
                                 &eth_proto_admin, &eth_proto_oper);
+       eth_proto_cap_masked = ops->ptys_proto_cap_masked_get(eth_proto_cap);
        ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
-                              eth_proto_cap, mlxsw_sp_port->link.autoneg);
+                              eth_proto_cap_masked,
+                              mlxsw_sp_port->link.autoneg);
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
 }
 
index 3e26eb6..74b3959 100644 (file)
@@ -342,6 +342,7 @@ struct mlxsw_sp_port_type_speed_ops {
                                    u32 *p_eth_proto_cap,
                                    u32 *p_eth_proto_admin,
                                    u32 *p_eth_proto_oper);
+       u32 (*ptys_proto_cap_masked_get)(u32 eth_proto_cap);
 };
 
 static inline struct net_device *
index 2096b64..5406164 100644 (file)
@@ -1303,6 +1303,20 @@ mlxsw_sp1_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
                                  p_eth_proto_oper);
 }
 
+static u32 mlxsw_sp1_ptys_proto_cap_masked_get(u32 eth_proto_cap)
+{
+       u32 ptys_proto_cap_masked = 0;
+       int i;
+
+       for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
+               if (mlxsw_sp1_port_link_mode[i].mask & eth_proto_cap)
+                       ptys_proto_cap_masked |=
+                               mlxsw_sp1_port_link_mode[i].mask;
+       }
+
+       return ptys_proto_cap_masked;
+}
+
 const struct mlxsw_sp_port_type_speed_ops mlxsw_sp1_port_type_speed_ops = {
        .from_ptys_supported_port       = mlxsw_sp1_from_ptys_supported_port,
        .from_ptys_link                 = mlxsw_sp1_from_ptys_link,
@@ -1313,6 +1327,7 @@ const struct mlxsw_sp_port_type_speed_ops mlxsw_sp1_port_type_speed_ops = {
        .to_ptys_speed                  = mlxsw_sp1_to_ptys_speed,
        .reg_ptys_eth_pack              = mlxsw_sp1_reg_ptys_eth_pack,
        .reg_ptys_eth_unpack            = mlxsw_sp1_reg_ptys_eth_unpack,
+       .ptys_proto_cap_masked_get      = mlxsw_sp1_ptys_proto_cap_masked_get,
 };
 
 static const enum ethtool_link_mode_bit_indices
@@ -1731,6 +1746,20 @@ mlxsw_sp2_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
                                      p_eth_proto_admin, p_eth_proto_oper);
 }
 
+static u32 mlxsw_sp2_ptys_proto_cap_masked_get(u32 eth_proto_cap)
+{
+       u32 ptys_proto_cap_masked = 0;
+       int i;
+
+       for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
+               if (mlxsw_sp2_port_link_mode[i].mask & eth_proto_cap)
+                       ptys_proto_cap_masked |=
+                               mlxsw_sp2_port_link_mode[i].mask;
+       }
+
+       return ptys_proto_cap_masked;
+}
+
 const struct mlxsw_sp_port_type_speed_ops mlxsw_sp2_port_type_speed_ops = {
        .from_ptys_supported_port       = mlxsw_sp2_from_ptys_supported_port,
        .from_ptys_link                 = mlxsw_sp2_from_ptys_link,
@@ -1741,4 +1770,5 @@ const struct mlxsw_sp_port_type_speed_ops mlxsw_sp2_port_type_speed_ops = {
        .to_ptys_speed                  = mlxsw_sp2_to_ptys_speed,
        .reg_ptys_eth_pack              = mlxsw_sp2_reg_ptys_eth_pack,
        .reg_ptys_eth_unpack            = mlxsw_sp2_reg_ptys_eth_unpack,
+       .ptys_proto_cap_masked_get      = mlxsw_sp2_ptys_proto_cap_masked_get,
 };
index 545c99b..dc5fbc2 100644 (file)
@@ -333,7 +333,7 @@ int ionic_set_vf_config(struct ionic *ionic, int vf, u8 attr, u8 *data)
        union ionic_dev_cmd cmd = {
                .vf_setattr.opcode = IONIC_CMD_VF_SETATTR,
                .vf_setattr.attr = attr,
-               .vf_setattr.vf_index = vf,
+               .vf_setattr.vf_index = cpu_to_le16(vf),
        };
        int err;
 
@@ -391,7 +391,7 @@ void ionic_dev_cmd_queue_identify(struct ionic_dev *idev,
 {
        union ionic_dev_cmd cmd = {
                .q_identify.opcode = IONIC_CMD_Q_IDENTIFY,
-               .q_identify.lif_type = lif_type,
+               .q_identify.lif_type = cpu_to_le16(lif_type),
                .q_identify.type = qtype,
                .q_identify.ver = qver,
        };
index c109cd5..6c243b1 100644 (file)
@@ -29,6 +29,7 @@ struct ionic_dev_bar {
        int res_index;
 };
 
+#ifndef __CHECKER__
 /* Registers */
 static_assert(sizeof(struct ionic_intr) == 32);
 
@@ -119,6 +120,7 @@ static_assert(sizeof(struct ionic_vf_setattr_cmd) == 64);
 static_assert(sizeof(struct ionic_vf_setattr_comp) == 16);
 static_assert(sizeof(struct ionic_vf_getattr_cmd) == 64);
 static_assert(sizeof(struct ionic_vf_getattr_comp) == 16);
+#endif /* __CHECKER__ */
 
 struct ionic_devinfo {
        u8 asic_type;
index f492ae4..d7bbf33 100644 (file)
@@ -27,9 +27,9 @@ static void ionic_dev_cmd_firmware_download(struct ionic_dev *idev, u64 addr,
 {
        union ionic_dev_cmd cmd = {
                .fw_download.opcode = IONIC_CMD_FW_DOWNLOAD,
-               .fw_download.offset = offset,
-               .fw_download.addr = addr,
-               .fw_download.length = length
+               .fw_download.offset = cpu_to_le32(offset),
+               .fw_download.addr = cpu_to_le64(addr),
+               .fw_download.length = cpu_to_le32(length),
        };
 
        ionic_dev_cmd_go(idev, &cmd);
index d655a7a..a12df39 100644 (file)
@@ -1656,7 +1656,6 @@ static void ionic_txrx_deinit(struct ionic_lif *lif)
        if (lif->rxqcqs) {
                for (i = 0; i < lif->nxqs && lif->rxqcqs[i]; i++) {
                        ionic_lif_qcq_deinit(lif, lif->rxqcqs[i]);
-                       ionic_rx_flush(&lif->rxqcqs[i]->cq);
                        ionic_rx_empty(&lif->rxqcqs[i]->q);
                }
        }
@@ -1915,11 +1914,11 @@ static int ionic_get_vf_config(struct net_device *netdev,
                ret = -EINVAL;
        } else {
                ivf->vf           = vf;
-               ivf->vlan         = ionic->vfs[vf].vlanid;
+               ivf->vlan         = le16_to_cpu(ionic->vfs[vf].vlanid);
                ivf->qos          = 0;
                ivf->spoofchk     = ionic->vfs[vf].spoofchk;
                ivf->linkstate    = ionic->vfs[vf].linkstate;
-               ivf->max_tx_rate  = ionic->vfs[vf].maxrate;
+               ivf->max_tx_rate  = le32_to_cpu(ionic->vfs[vf].maxrate);
                ivf->trusted      = ionic->vfs[vf].trusted;
                ether_addr_copy(ivf->mac, ionic->vfs[vf].macaddr);
        }
@@ -2019,7 +2018,7 @@ static int ionic_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
                ret = ionic_set_vf_config(ionic, vf,
                                          IONIC_VF_ATTR_VLAN, (u8 *)&vlan);
                if (!ret)
-                       ionic->vfs[vf].vlanid = vlan;
+                       ionic->vfs[vf].vlanid = cpu_to_le16(vlan);
        }
 
        up_write(&ionic->vf_op_lock);
@@ -2048,7 +2047,7 @@ static int ionic_set_vf_rate(struct net_device *netdev, int vf,
                ret = ionic_set_vf_config(ionic, vf,
                                          IONIC_VF_ATTR_RATE, (u8 *)&tx_max);
                if (!ret)
-                       lif->ionic->vfs[vf].maxrate = tx_max;
+                       lif->ionic->vfs[vf].maxrate = cpu_to_le32(tx_max);
        }
 
        up_write(&ionic->vf_op_lock);
@@ -2981,14 +2980,14 @@ void ionic_lif_unregister(struct ionic_lif *lif)
 
 static void ionic_lif_queue_identify(struct ionic_lif *lif)
 {
+       union ionic_q_identity __iomem *q_ident;
        struct ionic *ionic = lif->ionic;
-       union ionic_q_identity *q_ident;
        struct ionic_dev *idev;
        int qtype;
        int err;
 
        idev = &lif->ionic->idev;
-       q_ident = (union ionic_q_identity *)&idev->dev_cmd_regs->data;
+       q_ident = (union ionic_q_identity __iomem *)&idev->dev_cmd_regs->data;
 
        for (qtype = 0; qtype < ARRAY_SIZE(ionic_qtype_versions); qtype++) {
                struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
@@ -3011,14 +3010,14 @@ static void ionic_lif_queue_identify(struct ionic_lif *lif)
                                             ionic_qtype_versions[qtype]);
                err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
                if (!err) {
-                       qti->version   = q_ident->version;
-                       qti->supported = q_ident->supported;
-                       qti->features  = le64_to_cpu(q_ident->features);
-                       qti->desc_sz   = le16_to_cpu(q_ident->desc_sz);
-                       qti->comp_sz   = le16_to_cpu(q_ident->comp_sz);
-                       qti->sg_desc_sz   = le16_to_cpu(q_ident->sg_desc_sz);
-                       qti->max_sg_elems = le16_to_cpu(q_ident->max_sg_elems);
-                       qti->sg_desc_stride = le16_to_cpu(q_ident->sg_desc_stride);
+                       qti->version   = readb(&q_ident->version);
+                       qti->supported = readb(&q_ident->supported);
+                       qti->features  = readq(&q_ident->features);
+                       qti->desc_sz   = readw(&q_ident->desc_sz);
+                       qti->comp_sz   = readw(&q_ident->comp_sz);
+                       qti->sg_desc_sz   = readw(&q_ident->sg_desc_sz);
+                       qti->max_sg_elems = readw(&q_ident->max_sg_elems);
+                       qti->sg_desc_stride = readw(&q_ident->sg_desc_stride);
                }
                mutex_unlock(&ionic->dev_cmd_lock);
 
index ee07408..d355676 100644 (file)
@@ -311,7 +311,7 @@ int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
 
 static void ionic_dev_cmd_clean(struct ionic *ionic)
 {
-       union ionic_dev_cmd_regs *regs = ionic->idev.dev_cmd_regs;
+       union __iomem ionic_dev_cmd_regs *regs = ionic->idev.dev_cmd_regs;
 
        iowrite32(0, &regs->doorbell);
        memset_io(&regs->cmd, 0, sizeof(regs->cmd));
@@ -333,7 +333,7 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds)
         */
        max_wait = jiffies + (max_seconds * HZ);
 try_again:
-       opcode = idev->dev_cmd_regs->cmd.cmd.opcode;
+       opcode = readb(&idev->dev_cmd_regs->cmd.cmd.opcode);
        start_time = jiffies;
        do {
                done = ionic_dev_cmd_done(idev);
index 3f54351..2a72583 100644 (file)
@@ -49,7 +49,7 @@ extern const int ionic_num_stats_grps;
        (*((u64 *)(((u8 *)(base_ptr)) + (desc_ptr)->offset)))
 
 #define IONIC_READ_STAT_LE64(base_ptr, desc_ptr) \
-       __le64_to_cpu(*((u64 *)(((u8 *)(base_ptr)) + (desc_ptr)->offset)))
+       __le64_to_cpu(*((__le64 *)(((u8 *)(base_ptr)) + (desc_ptr)->offset)))
 
 struct ionic_stat_desc {
        char name[ETH_GSTRING_LEN];
index 169ac4f..b3d2250 100644 (file)
@@ -200,7 +200,7 @@ static void ionic_rx_clean(struct ionic_queue *q,
        if (likely(netdev->features & NETIF_F_RXCSUM)) {
                if (comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_CALC) {
                        skb->ip_summed = CHECKSUM_COMPLETE;
-                       skb->csum = (__wsum)le16_to_cpu(comp->csum);
+                       skb->csum = (__force __wsum)le16_to_cpu(comp->csum);
                        stats->csum_complete++;
                }
        } else {
@@ -253,19 +253,6 @@ static bool ionic_rx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info)
        return true;
 }
 
-void ionic_rx_flush(struct ionic_cq *cq)
-{
-       struct ionic_dev *idev = &cq->lif->ionic->idev;
-       u32 work_done;
-
-       work_done = ionic_cq_service(cq, cq->num_descs,
-                                    ionic_rx_service, NULL, NULL);
-
-       if (work_done)
-               ionic_intr_credits(idev->intr_ctrl, cq->bound_intr->index,
-                                  work_done, IONIC_INTR_CRED_RESET_COALESCE);
-}
-
 static int ionic_rx_page_alloc(struct ionic_queue *q,
                               struct ionic_page_info *page_info)
 {
@@ -413,22 +400,20 @@ static void ionic_rx_fill_cb(void *arg)
 void ionic_rx_empty(struct ionic_queue *q)
 {
        struct ionic_desc_info *desc_info;
-       struct ionic_rxq_desc *desc;
-       unsigned int i;
-       u16 idx;
-
-       idx = q->tail_idx;
-       while (idx != q->head_idx) {
-               desc_info = &q->info[idx];
-               desc = desc_info->desc;
-               desc->addr = 0;
-               desc->len = 0;
+       struct ionic_page_info *page_info;
+       unsigned int i, j;
 
-               for (i = 0; i < desc_info->npages; i++)
-                       ionic_rx_page_free(q, &desc_info->pages[i]);
+       for (i = 0; i < q->num_descs; i++) {
+               desc_info = &q->info[i];
+               for (j = 0; j < IONIC_RX_MAX_SG_ELEMS + 1; j++) {
+                       page_info = &desc_info->pages[j];
+                       if (page_info->page)
+                               ionic_rx_page_free(q, page_info);
+               }
 
+               desc_info->npages = 0;
+               desc_info->cb = NULL;
                desc_info->cb_arg = NULL;
-               idx = (idx + 1) & (q->num_descs - 1);
        }
 }
 
@@ -812,6 +797,7 @@ static int ionic_tx_tso(struct ionic_queue *q, struct sk_buff *skb)
        skb_frag_t *frag;
        bool start, done;
        bool outer_csum;
+       dma_addr_t addr;
        bool has_vlan;
        u16 desc_len;
        u8 desc_nsge;
@@ -893,11 +879,10 @@ static int ionic_tx_tso(struct ionic_queue *q, struct sk_buff *skb)
                        if (frag_left > 0) {
                                len = min(frag_left, left);
                                frag_left -= len;
-                               elem->addr =
-                                   cpu_to_le64(ionic_tx_map_frag(q, frag,
-                                                                 offset, len));
-                               if (dma_mapping_error(dev, elem->addr))
+                               addr = ionic_tx_map_frag(q, frag, offset, len);
+                               if (dma_mapping_error(dev, addr))
                                        goto err_out_abort;
+                               elem->addr = cpu_to_le64(addr);
                                elem->len = cpu_to_le16(len);
                                elem++;
                                desc_nsge++;
index a5883be..7667b72 100644 (file)
@@ -4,7 +4,6 @@
 #ifndef _IONIC_TXRX_H_
 #define _IONIC_TXRX_H_
 
-void ionic_rx_flush(struct ionic_cq *cq);
 void ionic_tx_flush(struct ionic_cq *cq);
 
 void ionic_rx_fill(struct ionic_queue *q);
index 3b6ddc7..00f1380 100644 (file)
@@ -4573,7 +4573,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
        }
 
        rtl_irq_disable(tp);
-       napi_schedule_irqoff(&tp->napi);
+       napi_schedule(&tp->napi);
 out:
        rtl_ack_events(tp, status);
 
@@ -4746,7 +4746,7 @@ static int rtl_open(struct net_device *dev)
        rtl_request_firmware(tp);
 
        retval = request_irq(pci_irq_vector(pdev, 0), rtl8169_interrupt,
-                            IRQF_NO_THREAD | IRQF_SHARED, dev->name, tp);
+                            IRQF_SHARED, dev->name, tp);
        if (retval < 0)
                goto err_release_fw_2;
 
index 9c4df4e..bd30505 100644 (file)
@@ -1744,12 +1744,16 @@ static int ravb_hwtstamp_get(struct net_device *ndev, struct ifreq *req)
        config.flags = 0;
        config.tx_type = priv->tstamp_tx_ctrl ? HWTSTAMP_TX_ON :
                                                HWTSTAMP_TX_OFF;
-       if (priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE_V2_L2_EVENT)
+       switch (priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE) {
+       case RAVB_RXTSTAMP_TYPE_V2_L2_EVENT:
                config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
-       else if (priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE_ALL)
+               break;
+       case RAVB_RXTSTAMP_TYPE_ALL:
                config.rx_filter = HWTSTAMP_FILTER_ALL;
-       else
+               break;
+       default:
                config.rx_filter = HWTSTAMP_FILTER_NONE;
+       }
 
        return copy_to_user(req->ifr_data, &config, sizeof(config)) ?
                -EFAULT : 0;
index 030a1a5..dc668ed 100644 (file)
@@ -657,10 +657,6 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 
        gtp = netdev_priv(dev);
 
-       err = gtp_encap_enable(gtp, data);
-       if (err < 0)
-               return err;
-
        if (!data[IFLA_GTP_PDP_HASHSIZE]) {
                hashsize = 1024;
        } else {
@@ -671,12 +667,16 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 
        err = gtp_hashtable_new(gtp, hashsize);
        if (err < 0)
-               goto out_encap;
+               return err;
+
+       err = gtp_encap_enable(gtp, data);
+       if (err < 0)
+               goto out_hashtable;
 
        err = register_netdevice(dev);
        if (err < 0) {
                netdev_dbg(dev, "failed to register new netdev %d\n", err);
-               goto out_hashtable;
+               goto out_encap;
        }
 
        gn = net_generic(dev_net(dev), gtp_net_id);
@@ -687,11 +687,11 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 
        return 0;
 
+out_encap:
+       gtp_encap_disable(gtp);
 out_hashtable:
        kfree(gtp->addr_hash);
        kfree(gtp->tid_hash);
-out_encap:
-       gtp_encap_disable(gtp);
        return err;
 }
 
index 43f5f5d..9264203 100644 (file)
@@ -397,15 +397,24 @@ void gsi_trans_cmd_add(struct gsi_trans *trans, void *buf, u32 size,
 
        /* assert(which < trans->tre_count); */
 
-       /* Set the page information for the buffer.  We also need to fill in
-        * the DMA address and length for the buffer (something dma_map_sg()
-        * normally does).
+       /* Commands are quite different from data transfer requests.
+        * Their payloads come from a pool whose memory is allocated
+        * using dma_alloc_coherent().  We therefore do *not* map them
+        * for DMA (unlike what we do for pages and skbs).
+        *
+        * When a transaction completes, the SGL is normally unmapped.
+        * A command transaction has direction DMA_NONE, which tells
+        * gsi_trans_complete() to skip the unmapping step.
+        *
+        * The only things we use directly in a command scatter/gather
+        * entry are the DMA address and length.  We still need the SG
+        * table flags to be maintained though, so assign a NULL page
+        * pointer for that purpose.
         */
        sg = &trans->sgl[which];
-
-       sg_set_buf(sg, buf, size);
+       sg_assign_page(sg, NULL);
        sg_dma_address(sg) = addr;
-       sg_dma_len(sg) = sg->length;
+       sg_dma_len(sg) = size;
 
        info = &trans->info[which];
        info->opcode = opcode;
index 95ef494..376096b 100644 (file)
@@ -2125,7 +2125,7 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
 
        if (blk_queue_is_zoned(ns->queue)) {
                ret = nvme_revalidate_zones(ns);
-               if (ret)
+               if (ret && !nvme_first_scan(ns->disk))
                        return ret;
        }
 
index 3c002bd..f4c2464 100644 (file)
@@ -146,7 +146,8 @@ struct nvme_fc_rport {
 
 /* fc_ctrl flags values - specified as bit positions */
 #define ASSOC_ACTIVE           0
-#define FCCTRL_TERMIO          1
+#define ASSOC_FAILED           1
+#define FCCTRL_TERMIO          2
 
 struct nvme_fc_ctrl {
        spinlock_t              lock;
@@ -157,7 +158,6 @@ struct nvme_fc_ctrl {
        u32                     cnum;
 
        bool                    ioq_live;
-       atomic_t                err_work_active;
        u64                     association_id;
        struct nvmefc_ls_rcv_op *rcv_disconn;
 
@@ -167,7 +167,6 @@ struct nvme_fc_ctrl {
        struct blk_mq_tag_set   tag_set;
 
        struct delayed_work     connect_work;
-       struct work_struct      err_work;
 
        struct kref             ref;
        unsigned long           flags;
@@ -2414,24 +2413,97 @@ nvme_fc_nvme_ctrl_freed(struct nvme_ctrl *nctrl)
        nvme_fc_ctrl_put(ctrl);
 }
 
+/*
+ * This routine is used by the transport when it needs to find active
+ * io on a queue that is to be terminated. The transport uses
+ * blk_mq_tagset_busy_itr() to find the busy requests, which then invoke
+ * this routine to kill them on a 1 by 1 basis.
+ *
+ * As FC allocates FC exchange for each io, the transport must contact
+ * the LLDD to terminate the exchange, thus releasing the FC exchange.
+ * After terminating the exchange the LLDD will call the transport's
+ * normal io done path for the request, but it will have an aborted
+ * status. The done path will return the io request back to the block
+ * layer with an error status.
+ */
+static bool
+nvme_fc_terminate_exchange(struct request *req, void *data, bool reserved)
+{
+       struct nvme_ctrl *nctrl = data;
+       struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
+       struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(req);
+
+       __nvme_fc_abort_op(ctrl, op);
+       return true;
+}
+
+/*
+ * This routine runs through all outstanding commands on the association
+ * and aborts them.  This routine is typically be called by the
+ * delete_association routine. It is also called due to an error during
+ * reconnect. In that scenario, it is most likely a command that initializes
+ * the controller, including fabric Connect commands on io queues, that
+ * may have timed out or failed thus the io must be killed for the connect
+ * thread to see the error.
+ */
 static void
-nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
+__nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, bool start_queues)
 {
-       int active;
+       /*
+        * If io queues are present, stop them and terminate all outstanding
+        * ios on them. As FC allocates FC exchange for each io, the
+        * transport must contact the LLDD to terminate the exchange,
+        * thus releasing the FC exchange. We use blk_mq_tagset_busy_itr()
+        * to tell us what io's are busy and invoke a transport routine
+        * to kill them with the LLDD.  After terminating the exchange
+        * the LLDD will call the transport's normal io done path, but it
+        * will have an aborted status. The done path will return the
+        * io requests back to the block layer as part of normal completions
+        * (but with error status).
+        */
+       if (ctrl->ctrl.queue_count > 1) {
+               nvme_stop_queues(&ctrl->ctrl);
+               blk_mq_tagset_busy_iter(&ctrl->tag_set,
+                               nvme_fc_terminate_exchange, &ctrl->ctrl);
+               blk_mq_tagset_wait_completed_request(&ctrl->tag_set);
+               if (start_queues)
+                       nvme_start_queues(&ctrl->ctrl);
+       }
+
+       /*
+        * Other transports, which don't have link-level contexts bound
+        * to sqe's, would try to gracefully shutdown the controller by
+        * writing the registers for shutdown and polling (call
+        * nvme_shutdown_ctrl()). Given a bunch of i/o was potentially
+        * just aborted and we will wait on those contexts, and given
+        * there was no indication of how live the controlelr is on the
+        * link, don't send more io to create more contexts for the
+        * shutdown. Let the controller fail via keepalive failure if
+        * its still present.
+        */
 
        /*
-        * if an error (io timeout, etc) while (re)connecting,
-        * it's an error on creating the new association.
-        * Start the error recovery thread if it hasn't already
-        * been started. It is expected there could be multiple
-        * ios hitting this path before things are cleaned up.
+        * clean up the admin queue. Same thing as above.
+        */
+       blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
+       blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
+                               nvme_fc_terminate_exchange, &ctrl->ctrl);
+       blk_mq_tagset_wait_completed_request(&ctrl->admin_tag_set);
+}
+
+static void
+nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
+{
+       /*
+        * if an error (io timeout, etc) while (re)connecting, the remote
+        * port requested terminating of the association (disconnect_ls)
+        * or an error (timeout or abort) occurred on an io while creating
+        * the controller.  Abort any ios on the association and let the
+        * create_association error path resolve things.
         */
        if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) {
-               active = atomic_xchg(&ctrl->err_work_active, 1);
-               if (!active && !queue_work(nvme_fc_wq, &ctrl->err_work)) {
-                       atomic_set(&ctrl->err_work_active, 0);
-                       WARN_ON(1);
-               }
+               __nvme_fc_abort_outstanding_ios(ctrl, true);
+               set_bit(ASSOC_FAILED, &ctrl->flags);
                return;
        }
 
@@ -2745,30 +2817,6 @@ nvme_fc_complete_rq(struct request *rq)
        nvme_fc_ctrl_put(ctrl);
 }
 
-/*
- * This routine is used by the transport when it needs to find active
- * io on a queue that is to be terminated. The transport uses
- * blk_mq_tagset_busy_itr() to find the busy requests, which then invoke
- * this routine to kill them on a 1 by 1 basis.
- *
- * As FC allocates FC exchange for each io, the transport must contact
- * the LLDD to terminate the exchange, thus releasing the FC exchange.
- * After terminating the exchange the LLDD will call the transport's
- * normal io done path for the request, but it will have an aborted
- * status. The done path will return the io request back to the block
- * layer with an error status.
- */
-static bool
-nvme_fc_terminate_exchange(struct request *req, void *data, bool reserved)
-{
-       struct nvme_ctrl *nctrl = data;
-       struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
-       struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(req);
-
-       __nvme_fc_abort_op(ctrl, op);
-       return true;
-}
-
 
 static const struct blk_mq_ops nvme_fc_mq_ops = {
        .queue_rq       = nvme_fc_queue_rq,
@@ -2988,6 +3036,8 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
                ctrl->cnum, ctrl->lport->localport.port_name,
                ctrl->rport->remoteport.port_name, ctrl->ctrl.opts->subsysnqn);
 
+       clear_bit(ASSOC_FAILED, &ctrl->flags);
+
        /*
         * Create the admin queue
         */
@@ -3016,7 +3066,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
         */
 
        ret = nvme_enable_ctrl(&ctrl->ctrl);
-       if (ret)
+       if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
                goto out_disconnect_admin_queue;
 
        ctrl->ctrl.max_segments = ctrl->lport->ops->max_sgl_segments;
@@ -3026,7 +3076,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
        blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
 
        ret = nvme_init_identify(&ctrl->ctrl);
-       if (ret)
+       if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
                goto out_disconnect_admin_queue;
 
        /* sanity checks */
@@ -3071,9 +3121,9 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
                        ret = nvme_fc_create_io_queues(ctrl);
                else
                        ret = nvme_fc_recreate_io_queues(ctrl);
-               if (ret)
-                       goto out_term_aen_ops;
        }
+       if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
+               goto out_term_aen_ops;
 
        changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
 
@@ -3108,60 +3158,6 @@ out_free_queue:
 
 
 /*
- * This routine runs through all outstanding commands on the association
- * and aborts them.  This routine is typically be called by the
- * delete_association routine. It is also called due to an error during
- * reconnect. In that scenario, it is most likely a command that initializes
- * the controller, including fabric Connect commands on io queues, that
- * may have timed out or failed thus the io must be killed for the connect
- * thread to see the error.
- */
-static void
-__nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, bool start_queues)
-{
-       /*
-        * If io queues are present, stop them and terminate all outstanding
-        * ios on them. As FC allocates FC exchange for each io, the
-        * transport must contact the LLDD to terminate the exchange,
-        * thus releasing the FC exchange. We use blk_mq_tagset_busy_itr()
-        * to tell us what io's are busy and invoke a transport routine
-        * to kill them with the LLDD.  After terminating the exchange
-        * the LLDD will call the transport's normal io done path, but it
-        * will have an aborted status. The done path will return the
-        * io requests back to the block layer as part of normal completions
-        * (but with error status).
-        */
-       if (ctrl->ctrl.queue_count > 1) {
-               nvme_stop_queues(&ctrl->ctrl);
-               blk_mq_tagset_busy_iter(&ctrl->tag_set,
-                               nvme_fc_terminate_exchange, &ctrl->ctrl);
-               blk_mq_tagset_wait_completed_request(&ctrl->tag_set);
-               if (start_queues)
-                       nvme_start_queues(&ctrl->ctrl);
-       }
-
-       /*
-        * Other transports, which don't have link-level contexts bound
-        * to sqe's, would try to gracefully shutdown the controller by
-        * writing the registers for shutdown and polling (call
-        * nvme_shutdown_ctrl()). Given a bunch of i/o was potentially
-        * just aborted and we will wait on those contexts, and given
-        * there was no indication of how live the controlelr is on the
-        * link, don't send more io to create more contexts for the
-        * shutdown. Let the controller fail via keepalive failure if
-        * its still present.
-        */
-
-       /*
-        * clean up the admin queue. Same thing as above.
-        */
-       blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
-       blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
-                               nvme_fc_terminate_exchange, &ctrl->ctrl);
-       blk_mq_tagset_wait_completed_request(&ctrl->admin_tag_set);
-}
-
-/*
  * This routine stops operation of the controller on the host side.
  * On the host os stack side: Admin and IO queues are stopped,
  *   outstanding ios on them terminated via FC ABTS.
@@ -3237,7 +3233,6 @@ nvme_fc_delete_ctrl(struct nvme_ctrl *nctrl)
 {
        struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
 
-       cancel_work_sync(&ctrl->err_work);
        cancel_delayed_work_sync(&ctrl->connect_work);
        /*
         * kill the association on the link side.  this will block
@@ -3292,78 +3287,34 @@ nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
 }
 
 static void
-__nvme_fc_terminate_io(struct nvme_fc_ctrl *ctrl)
+nvme_fc_reset_ctrl_work(struct work_struct *work)
 {
-       /*
-        * if state is CONNECTING - the error occurred as part of a
-        * reconnect attempt. Abort any ios on the association and
-        * let the create_association error paths resolve things.
-        */
-       if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) {
-               __nvme_fc_abort_outstanding_ios(ctrl, true);
-               return;
-       }
-
-       /*
-        * For any other state, kill the association. As this routine
-        * is a common io abort routine for resetting and such, after
-        * the association is terminated, ensure that the state is set
-        * to CONNECTING.
-        */
+       struct nvme_fc_ctrl *ctrl =
+               container_of(work, struct nvme_fc_ctrl, ctrl.reset_work);
 
-       nvme_stop_keep_alive(&ctrl->ctrl);
+       nvme_stop_ctrl(&ctrl->ctrl);
 
        /* will block will waiting for io to terminate */
        nvme_fc_delete_association(ctrl);
 
-       if (ctrl->ctrl.state != NVME_CTRL_CONNECTING &&
-           !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
+       if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
                dev_err(ctrl->ctrl.device,
                        "NVME-FC{%d}: error_recovery: Couldn't change state "
                        "to CONNECTING\n", ctrl->cnum);
-}
-
-static void
-nvme_fc_reset_ctrl_work(struct work_struct *work)
-{
-       struct nvme_fc_ctrl *ctrl =
-               container_of(work, struct nvme_fc_ctrl, ctrl.reset_work);
-       int ret;
 
-       __nvme_fc_terminate_io(ctrl);
-
-       nvme_stop_ctrl(&ctrl->ctrl);
-
-       if (ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE)
-               ret = nvme_fc_create_association(ctrl);
-       else
-               ret = -ENOTCONN;
-
-       if (ret)
-               nvme_fc_reconnect_or_delete(ctrl, ret);
-       else
-               dev_info(ctrl->ctrl.device,
-                       "NVME-FC{%d}: controller reset complete\n",
-                       ctrl->cnum);
+       if (ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE) {
+               if (!queue_delayed_work(nvme_wq, &ctrl->connect_work, 0)) {
+                       dev_err(ctrl->ctrl.device,
+                               "NVME-FC{%d}: failed to schedule connect "
+                               "after reset\n", ctrl->cnum);
+               } else {
+                       flush_delayed_work(&ctrl->connect_work);
+               }
+       } else {
+               nvme_fc_reconnect_or_delete(ctrl, -ENOTCONN);
+       }
 }
 
-static void
-nvme_fc_connect_err_work(struct work_struct *work)
-{
-       struct nvme_fc_ctrl *ctrl =
-                       container_of(work, struct nvme_fc_ctrl, err_work);
-
-       __nvme_fc_terminate_io(ctrl);
-
-       atomic_set(&ctrl->err_work_active, 0);
-
-       /*
-        * Rescheduling the connection after recovering
-        * from the io error is left to the reconnect work
-        * item, which is what should have stalled waiting on
-        * the io that had the error that scheduled this work.
-        */
-}
 
 static const struct nvme_ctrl_ops nvme_fc_ctrl_ops = {
        .name                   = "fc",
@@ -3491,7 +3442,6 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
        ctrl->dev = lport->dev;
        ctrl->cnum = idx;
        ctrl->ioq_live = false;
-       atomic_set(&ctrl->err_work_active, 0);
        init_waitqueue_head(&ctrl->ioabort_wait);
 
        get_device(ctrl->dev);
@@ -3499,7 +3449,6 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
 
        INIT_WORK(&ctrl->ctrl.reset_work, nvme_fc_reset_ctrl_work);
        INIT_DELAYED_WORK(&ctrl->connect_work, nvme_fc_connect_ctrl_work);
-       INIT_WORK(&ctrl->err_work, nvme_fc_connect_err_work);
        spin_lock_init(&ctrl->lock);
 
        /* io queue count */
@@ -3592,7 +3541,6 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
 fail_ctrl:
        nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING);
        cancel_work_sync(&ctrl->ctrl.reset_work);
-       cancel_work_sync(&ctrl->err_work);
        cancel_delayed_work_sync(&ctrl->connect_work);
 
        ctrl->ctrl.opts = NULL;
index aad829a..541b0cb 100644 (file)
@@ -1768,6 +1768,14 @@ static void nvme_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc)
                return;
        }
 
+       /* sanity checking for received data length */
+       if (unlikely(wc->byte_len < len)) {
+               dev_err(queue->ctrl->ctrl.device,
+                       "Unexpected nvme completion length(%d)\n", wc->byte_len);
+               nvme_rdma_error_recovery(queue->ctrl);
+               return;
+       }
+
        ib_dma_sync_single_for_cpu(ibdev, qe->dma, len, DMA_FROM_DEVICE);
        /*
         * AEN requests are special as they don't time out and can
@@ -1890,10 +1898,10 @@ static int nvme_rdma_route_resolved(struct nvme_rdma_queue *queue)
                priv.hsqsize = cpu_to_le16(queue->ctrl->ctrl.sqsize);
        }
 
-       ret = rdma_connect(queue->cm_id, &param);
+       ret = rdma_connect_locked(queue->cm_id, &param);
        if (ret) {
                dev_err(ctrl->ctrl.device,
-                       "rdma_connect failed (%d).\n", ret);
+                       "rdma_connect_locked failed (%d).\n", ret);
                goto out_destroy_queue_ib;
        }
 
index aafcbc4..957b39a 100644 (file)
@@ -907,8 +907,6 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
        req->error_loc = NVMET_NO_ERROR_LOC;
        req->error_slba = 0;
 
-       trace_nvmet_req_init(req, req->cmd);
-
        /* no support for fused commands yet */
        if (unlikely(flags & (NVME_CMD_FUSE_FIRST | NVME_CMD_FUSE_SECOND))) {
                req->error_loc = offsetof(struct nvme_common_command, flags);
@@ -938,6 +936,8 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
        if (status)
                goto fail;
 
+       trace_nvmet_req_init(req, req->cmd);
+
        if (unlikely(!percpu_ref_tryget_live(&sq->ref))) {
                status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
                goto fail;
index 0458046..c14e324 100644 (file)
@@ -46,19 +46,12 @@ static inline struct nvmet_ctrl *nvmet_req_to_ctrl(struct nvmet_req *req)
        return req->sq->ctrl;
 }
 
-static inline void __assign_disk_name(char *name, struct nvmet_req *req,
-               bool init)
+static inline void __assign_req_name(char *name, struct nvmet_req *req)
 {
-       struct nvmet_ctrl *ctrl = nvmet_req_to_ctrl(req);
-       struct nvmet_ns *ns;
-
-       if ((init && req->sq->qid) || (!init && req->cq->qid)) {
-               ns = nvmet_find_namespace(ctrl, req->cmd->rw.nsid);
-               strncpy(name, ns->device_path, DISK_NAME_LEN);
-               return;
-       }
-
-       memset(name, 0, DISK_NAME_LEN);
+       if (req->ns)
+               strncpy(name, req->ns->device_path, DISK_NAME_LEN);
+       else
+               memset(name, 0, DISK_NAME_LEN);
 }
 #endif
 
@@ -81,7 +74,7 @@ TRACE_EVENT(nvmet_req_init,
        TP_fast_assign(
                __entry->cmd = cmd;
                __entry->ctrl = nvmet_req_to_ctrl(req);
-               __assign_disk_name(__entry->disk, req, true);
+               __assign_req_name(__entry->disk, req);
                __entry->qid = req->sq->qid;
                __entry->cid = cmd->common.command_id;
                __entry->opcode = cmd->common.opcode;
@@ -121,7 +114,7 @@ TRACE_EVENT(nvmet_req_complete,
                __entry->cid = req->cqe->command_id;
                __entry->result = le64_to_cpu(req->cqe->result.u64);
                __entry->status = le16_to_cpu(req->cqe->status) >> 1;
-               __assign_disk_name(__entry->disk, req, false);
+               __assign_req_name(__entry->disk, req);
        ),
        TP_printk("nvmet%s: %sqid=%d, cmdid=%u, res=%#llx, status=%#x",
                __print_ctrl_name(__entry->ctrl),
index 3bf18d7..a50ab00 100644 (file)
@@ -51,7 +51,7 @@ static void pnp_remove_protocol(struct pnp_protocol *protocol)
 }
 
 /**
- * pnp_protocol_register - adds a pnp protocol to the pnp layer
+ * pnp_register_protocol - adds a pnp protocol to the pnp layer
  * @protocol: pointer to the corresponding pnp_protocol structure
  *
  *  Ex protocols: ISAPNP, PNPBIOS, etc
@@ -91,7 +91,7 @@ int pnp_register_protocol(struct pnp_protocol *protocol)
 }
 
 /**
- * pnp_protocol_unregister - removes a pnp protocol from the pnp layer
+ * pnp_unregister_protocol - removes a pnp protocol from the pnp layer
  * @protocol: pointer to the corresponding pnp_protocol structure
  */
 void pnp_unregister_protocol(struct pnp_protocol *protocol)
index fe96ca3..26cc943 100644 (file)
@@ -390,7 +390,7 @@ static int ism_move(struct smcd_dev *smcd, u64 dmb_tok, unsigned int idx,
 }
 
 static struct ism_systemeid SYSTEM_EID = {
-       .seid_string = "IBM-SYSZ-IBMSEID00000000",
+       .seid_string = "IBM-SYSZ-ISMSEID00000000",
        .serial_number = "0000",
        .type = "0000",
 };
index 128583d..c8dd858 100644 (file)
@@ -445,7 +445,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
                }
        }
 
-       if (scmd) {
+       if (scmd && hisi_hba->shost->nr_hw_queues) {
                unsigned int dq_index;
                u32 blk_tag;
 
index b1f3017..29fcc44 100644 (file)
@@ -807,13 +807,29 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
 }
 
 /**
+ * ibmvscsi_set_request_limit - Set the adapter request_limit in response to
+ * an adapter failure, reset, or SRP Login. Done under host lock to prevent
+ * race with SCSI command submission.
+ * @hostdata:  adapter to adjust
+ * @limit:     new request limit
+ */
+static void ibmvscsi_set_request_limit(struct ibmvscsi_host_data *hostdata, int limit)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(hostdata->host->host_lock, flags);
+       atomic_set(&hostdata->request_limit, limit);
+       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+}
+
+/**
  * ibmvscsi_reset_host - Reset the connection to the server
  * @hostdata:  struct ibmvscsi_host_data to reset
 */
 static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
 {
        scsi_block_requests(hostdata->host);
-       atomic_set(&hostdata->request_limit, 0);
+       ibmvscsi_set_request_limit(hostdata, 0);
 
        purge_requests(hostdata, DID_ERROR);
        hostdata->action = IBMVSCSI_HOST_ACTION_RESET;
@@ -1146,13 +1162,13 @@ static void login_rsp(struct srp_event_struct *evt_struct)
                dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n",
                         evt_struct->xfer_iu->srp.login_rej.reason);
                /* Login failed.  */
-               atomic_set(&hostdata->request_limit, -1);
+               ibmvscsi_set_request_limit(hostdata, -1);
                return;
        default:
                dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n",
                        evt_struct->xfer_iu->srp.login_rsp.opcode);
                /* Login failed.  */
-               atomic_set(&hostdata->request_limit, -1);
+               ibmvscsi_set_request_limit(hostdata, -1);
                return;
        }
 
@@ -1163,7 +1179,7 @@ static void login_rsp(struct srp_event_struct *evt_struct)
         * This value is set rather than added to request_limit because
         * request_limit could have been set to -1 by this client.
         */
-       atomic_set(&hostdata->request_limit,
+       ibmvscsi_set_request_limit(hostdata,
                   be32_to_cpu(evt_struct->xfer_iu->srp.login_rsp.req_lim_delta));
 
        /* If we had any pending I/Os, kick them */
@@ -1195,13 +1211,13 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
        login->req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
                                         SRP_BUF_FORMAT_INDIRECT);
 
-       spin_lock_irqsave(hostdata->host->host_lock, flags);
        /* Start out with a request limit of 0, since this is negotiated in
         * the login request we are just sending and login requests always
         * get sent by the driver regardless of request_limit.
         */
-       atomic_set(&hostdata->request_limit, 0);
+       ibmvscsi_set_request_limit(hostdata, 0);
 
+       spin_lock_irqsave(hostdata->host->host_lock, flags);
        rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2);
        spin_unlock_irqrestore(hostdata->host->host_lock, flags);
        dev_info(hostdata->dev, "sent SRP login\n");
@@ -1781,7 +1797,7 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq,
                return;
        case VIOSRP_CRQ_XPORT_EVENT:    /* Hypervisor telling us the connection is closed */
                scsi_block_requests(hostdata->host);
-               atomic_set(&hostdata->request_limit, 0);
+               ibmvscsi_set_request_limit(hostdata, 0);
                if (crq->format == 0x06) {
                        /* We need to re-setup the interpartition connection */
                        dev_info(hostdata->dev, "Re-enabling adapter!\n");
@@ -2137,12 +2153,12 @@ static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata)
        }
 
        hostdata->action = IBMVSCSI_HOST_ACTION_NONE;
+       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 
        if (rc) {
-               atomic_set(&hostdata->request_limit, -1);
+               ibmvscsi_set_request_limit(hostdata, -1);
                dev_err(hostdata->dev, "error after %s\n", action);
        }
-       spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 
        scsi_unblock_requests(hostdata->host);
 }
@@ -2226,7 +2242,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        init_waitqueue_head(&hostdata->work_wait_q);
        hostdata->host = host;
        hostdata->dev = dev;
-       atomic_set(&hostdata->request_limit, -1);
+       ibmvscsi_set_request_limit(hostdata, -1);
        hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT;
 
        if (map_persist_bufs(hostdata)) {
index 1f90051..b7a1dc2 100644 (file)
@@ -554,10 +554,12 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
 
        fcport = qla_rport->fcport;
 
-       if (!qpair || !fcport || (qpair && !qpair->fw_started) ||
-           (fcport && fcport->deleted))
+       if (!qpair || !fcport)
                return -ENODEV;
 
+       if (!qpair->fw_started || fcport->deleted)
+               return -EBUSY;
+
        vha = fcport->vha;
 
        if (!(fcport->nvme_flag & NVME_FLAG_REGISTERED))
index f2437a7..9af50e6 100644 (file)
@@ -1714,15 +1714,16 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
  */
 static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
 {
-       struct async_scan_data *data;
+       struct async_scan_data *data = NULL;
        unsigned long flags;
 
        if (strncmp(scsi_scan_type, "sync", 4) == 0)
                return NULL;
 
+       mutex_lock(&shost->scan_mutex);
        if (shost->async_scan) {
                shost_printk(KERN_DEBUG, shost, "%s called twice\n", __func__);
-               return NULL;
+               goto err;
        }
 
        data = kmalloc(sizeof(*data), GFP_KERNEL);
@@ -1733,7 +1734,6 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
                goto err;
        init_completion(&data->prev_finished);
 
-       mutex_lock(&shost->scan_mutex);
        spin_lock_irqsave(shost->host_lock, flags);
        shost->async_scan = 1;
        spin_unlock_irqrestore(shost->host_lock, flags);
@@ -1748,6 +1748,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
        return data;
 
  err:
+       mutex_unlock(&shost->scan_mutex);
        kfree(data);
        return NULL;
 }
index af2126d..8afb3f4 100644 (file)
@@ -91,7 +91,7 @@ static struct generic_pm_domain *ti_sci_pd_xlate(
        struct genpd_onecell_data *genpd_data = data;
        unsigned int idx = genpdspec->args[0];
 
-       if (genpdspec->args_count < 2)
+       if (genpdspec->args_count != 1 && genpdspec->args_count != 2)
                return ERR_PTR(-EINVAL);
 
        if (idx >= genpd_data->num_domains) {
index f53bf33..6ade4a5 100644 (file)
@@ -200,7 +200,8 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
        int name_len;
        int rc;
 
-       if (connection_method == TEE_IOCTL_LOGIN_PUBLIC) {
+       if (connection_method == TEE_IOCTL_LOGIN_PUBLIC ||
+           connection_method == TEE_IOCTL_LOGIN_REE_KERNEL) {
                /* Nil UUID to be passed to TEE environment */
                uuid_copy(uuid, &uuid_null);
                return 0;
index 52233fa..887b673 100644 (file)
@@ -589,7 +589,7 @@ struct afs_cell *afs_use_cell(struct afs_cell *cell, enum afs_cell_trace reason)
  */
 void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_trace reason)
 {
-       unsigned int debug_id = cell->debug_id;
+       unsigned int debug_id;
        time64_t now, expire_delay;
        int u, a;
 
@@ -604,6 +604,7 @@ void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_tr
        if (cell->vl_servers->nr_servers)
                expire_delay = afs_cell_gc_delay;
 
+       debug_id = cell->debug_id;
        u = atomic_read(&cell->ref);
        a = atomic_dec_return(&cell->active);
        trace_afs_cell(debug_id, u, a, reason);
index 1d2e61e..1bb5b9d 100644 (file)
@@ -281,8 +281,7 @@ retry:
                        if (ret < 0)
                                goto error;
 
-                       set_page_private(req->pages[i], 1);
-                       SetPagePrivate(req->pages[i]);
+                       attach_page_private(req->pages[i], (void *)1);
                        unlock_page(req->pages[i]);
                        i++;
                } else {
@@ -1975,8 +1974,7 @@ static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags)
 
        _enter("{{%llx:%llu}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index);
 
-       set_page_private(page, 0);
-       ClearPagePrivate(page);
+       detach_page_private(page);
 
        /* The directory will need reloading. */
        if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
@@ -2003,8 +2001,6 @@ static void afs_dir_invalidatepage(struct page *page, unsigned int offset,
                afs_stat_v(dvnode, n_inval);
 
        /* we clean up only if the entire page is being invalidated */
-       if (offset == 0 && length == PAGE_SIZE) {
-               set_page_private(page, 0);
-               ClearPagePrivate(page);
-       }
+       if (offset == 0 && length == PAGE_SIZE)
+               detach_page_private(page);
 }
index b108528..2ffe09a 100644 (file)
@@ -243,10 +243,8 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
                                                   index, gfp);
                        if (!page)
                                goto error;
-                       if (!PagePrivate(page)) {
-                               set_page_private(page, 1);
-                               SetPagePrivate(page);
-                       }
+                       if (!PagePrivate(page))
+                               attach_page_private(page, (void *)1);
                        dir_page = kmap(page);
                }
 
index 371d148..85f5adf 100644 (file)
@@ -33,6 +33,7 @@ const struct file_operations afs_file_operations = {
        .write_iter     = afs_file_write,
        .mmap           = afs_file_mmap,
        .splice_read    = generic_file_splice_read,
+       .splice_write   = iter_file_splice_write,
        .fsync          = afs_fsync,
        .lock           = afs_lock,
        .flock          = afs_flock,
@@ -601,6 +602,63 @@ static int afs_readpages(struct file *file, struct address_space *mapping,
 }
 
 /*
+ * Adjust the dirty region of the page on truncation or full invalidation,
+ * getting rid of the markers altogether if the region is entirely invalidated.
+ */
+static void afs_invalidate_dirty(struct page *page, unsigned int offset,
+                                unsigned int length)
+{
+       struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
+       unsigned long priv;
+       unsigned int f, t, end = offset + length;
+
+       priv = page_private(page);
+
+       /* we clean up only if the entire page is being invalidated */
+       if (offset == 0 && length == thp_size(page))
+               goto full_invalidate;
+
+        /* If the page was dirtied by page_mkwrite(), the PTE stays writable
+         * and we don't get another notification to tell us to expand it
+         * again.
+         */
+       if (afs_is_page_dirty_mmapped(priv))
+               return;
+
+       /* We may need to shorten the dirty region */
+       f = afs_page_dirty_from(priv);
+       t = afs_page_dirty_to(priv);
+
+       if (t <= offset || f >= end)
+               return; /* Doesn't overlap */
+
+       if (f < offset && t > end)
+               return; /* Splits the dirty region - just absorb it */
+
+       if (f >= offset && t <= end)
+               goto undirty;
+
+       if (f < offset)
+               t = offset;
+       else
+               f = end;
+       if (f == t)
+               goto undirty;
+
+       priv = afs_page_dirty(f, t);
+       set_page_private(page, priv);
+       trace_afs_page_dirty(vnode, tracepoint_string("trunc"), page->index, priv);
+       return;
+
+undirty:
+       trace_afs_page_dirty(vnode, tracepoint_string("undirty"), page->index, priv);
+       clear_page_dirty_for_io(page);
+full_invalidate:
+       priv = (unsigned long)detach_page_private(page);
+       trace_afs_page_dirty(vnode, tracepoint_string("inval"), page->index, priv);
+}
+
+/*
  * invalidate part or all of a page
  * - release a page and clean up its private data if offset is 0 (indicating
  *   the entire page)
@@ -608,31 +666,23 @@ static int afs_readpages(struct file *file, struct address_space *mapping,
 static void afs_invalidatepage(struct page *page, unsigned int offset,
                               unsigned int length)
 {
-       struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
-       unsigned long priv;
-
        _enter("{%lu},%u,%u", page->index, offset, length);
 
        BUG_ON(!PageLocked(page));
 
+#ifdef CONFIG_AFS_FSCACHE
        /* we clean up only if the entire page is being invalidated */
        if (offset == 0 && length == PAGE_SIZE) {
-#ifdef CONFIG_AFS_FSCACHE
                if (PageFsCache(page)) {
                        struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
                        fscache_wait_on_page_write(vnode->cache, page);
                        fscache_uncache_page(vnode->cache, page);
                }
+       }
 #endif
 
-               if (PagePrivate(page)) {
-                       priv = page_private(page);
-                       trace_afs_page_dirty(vnode, tracepoint_string("inval"),
-                                            page->index, priv);
-                       set_page_private(page, 0);
-                       ClearPagePrivate(page);
-               }
-       }
+       if (PagePrivate(page))
+               afs_invalidate_dirty(page, offset, length);
 
        _leave("");
 }
@@ -660,11 +710,9 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags)
 #endif
 
        if (PagePrivate(page)) {
-               priv = page_private(page);
+               priv = (unsigned long)detach_page_private(page);
                trace_afs_page_dirty(vnode, tracepoint_string("rel"),
                                     page->index, priv);
-               set_page_private(page, 0);
-               ClearPagePrivate(page);
        }
 
        /* indicate that the page can be released */
index 81b0485..14d5d75 100644 (file)
@@ -812,6 +812,7 @@ struct afs_operation {
                        pgoff_t         last;           /* last page in mapping to deal with */
                        unsigned        first_offset;   /* offset into mapping[first] */
                        unsigned        last_to;        /* amount of mapping[last] */
+                       bool            laundering;     /* Laundering page, PG_writeback not set */
                } store;
                struct {
                        struct iattr    *attr;
@@ -857,6 +858,62 @@ struct afs_vnode_cache_aux {
        u64                     data_version;
 } __packed;
 
+/*
+ * We use page->private to hold the amount of the page that we've written to,
+ * splitting the field into two parts.  However, we need to represent a range
+ * 0...PAGE_SIZE, so we reduce the resolution if the size of the page
+ * exceeds what we can encode.
+ */
+#ifdef CONFIG_64BIT
+#define __AFS_PAGE_PRIV_MASK   0x7fffffffUL
+#define __AFS_PAGE_PRIV_SHIFT  32
+#define __AFS_PAGE_PRIV_MMAPPED        0x80000000UL
+#else
+#define __AFS_PAGE_PRIV_MASK   0x7fffUL
+#define __AFS_PAGE_PRIV_SHIFT  16
+#define __AFS_PAGE_PRIV_MMAPPED        0x8000UL
+#endif
+
+static inline unsigned int afs_page_dirty_resolution(void)
+{
+       int shift = PAGE_SHIFT - (__AFS_PAGE_PRIV_SHIFT - 1);
+       return (shift > 0) ? shift : 0;
+}
+
+static inline size_t afs_page_dirty_from(unsigned long priv)
+{
+       unsigned long x = priv & __AFS_PAGE_PRIV_MASK;
+
+       /* The lower bound is inclusive */
+       return x << afs_page_dirty_resolution();
+}
+
+static inline size_t afs_page_dirty_to(unsigned long priv)
+{
+       unsigned long x = (priv >> __AFS_PAGE_PRIV_SHIFT) & __AFS_PAGE_PRIV_MASK;
+
+       /* The upper bound is immediately beyond the region */
+       return (x + 1) << afs_page_dirty_resolution();
+}
+
+static inline unsigned long afs_page_dirty(size_t from, size_t to)
+{
+       unsigned int res = afs_page_dirty_resolution();
+       from >>= res;
+       to = (to - 1) >> res;
+       return (to << __AFS_PAGE_PRIV_SHIFT) | from;
+}
+
+static inline unsigned long afs_page_dirty_mmapped(unsigned long priv)
+{
+       return priv | __AFS_PAGE_PRIV_MMAPPED;
+}
+
+static inline bool afs_is_page_dirty_mmapped(unsigned long priv)
+{
+       return priv & __AFS_PAGE_PRIV_MMAPPED;
+}
+
 #include <trace/events/afs.h>
 
 /*****************************************************************************/
index da12abd..5037120 100644 (file)
@@ -76,7 +76,7 @@ static int afs_fill_page(struct afs_vnode *vnode, struct key *key,
  */
 int afs_write_begin(struct file *file, struct address_space *mapping,
                    loff_t pos, unsigned len, unsigned flags,
-                   struct page **pagep, void **fsdata)
+                   struct page **_page, void **fsdata)
 {
        struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
        struct page *page;
@@ -90,11 +90,6 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
        _enter("{%llx:%llu},{%lx},%u,%u",
               vnode->fid.vid, vnode->fid.vnode, index, from, to);
 
-       /* We want to store information about how much of a page is altered in
-        * page->private.
-        */
-       BUILD_BUG_ON(PAGE_SIZE > 32768 && sizeof(page->private) < 8);
-
        page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page)
                return -ENOMEM;
@@ -110,9 +105,6 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
                SetPageUptodate(page);
        }
 
-       /* page won't leak in error case: it eventually gets cleaned off LRU */
-       *pagep = page;
-
 try_again:
        /* See if this page is already partially written in a way that we can
         * merge the new write with.
@@ -120,8 +112,8 @@ try_again:
        t = f = 0;
        if (PagePrivate(page)) {
                priv = page_private(page);
-               f = priv & AFS_PRIV_MAX;
-               t = priv >> AFS_PRIV_SHIFT;
+               f = afs_page_dirty_from(priv);
+               t = afs_page_dirty_to(priv);
                ASSERTCMP(f, <=, t);
        }
 
@@ -138,21 +130,9 @@ try_again:
                if (!test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags) &&
                    (to < f || from > t))
                        goto flush_conflicting_write;
-               if (from < f)
-                       f = from;
-               if (to > t)
-                       t = to;
-       } else {
-               f = from;
-               t = to;
        }
 
-       priv = (unsigned long)t << AFS_PRIV_SHIFT;
-       priv |= f;
-       trace_afs_page_dirty(vnode, tracepoint_string("begin"),
-                            page->index, priv);
-       SetPagePrivate(page);
-       set_page_private(page, priv);
+       *_page = page;
        _leave(" = 0");
        return 0;
 
@@ -162,17 +142,18 @@ try_again:
 flush_conflicting_write:
        _debug("flush conflict");
        ret = write_one_page(page);
-       if (ret < 0) {
-               _leave(" = %d", ret);
-               return ret;
-       }
+       if (ret < 0)
+               goto error;
 
        ret = lock_page_killable(page);
-       if (ret < 0) {
-               _leave(" = %d", ret);
-               return ret;
-       }
+       if (ret < 0)
+               goto error;
        goto try_again;
+
+error:
+       put_page(page);
+       _leave(" = %d", ret);
+       return ret;
 }
 
 /*
@@ -184,6 +165,9 @@ int afs_write_end(struct file *file, struct address_space *mapping,
 {
        struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
        struct key *key = afs_file_key(file);
+       unsigned long priv;
+       unsigned int f, from = pos & (PAGE_SIZE - 1);
+       unsigned int t, to = from + copied;
        loff_t i_size, maybe_i_size;
        int ret;
 
@@ -215,6 +199,25 @@ int afs_write_end(struct file *file, struct address_space *mapping,
                SetPageUptodate(page);
        }
 
+       if (PagePrivate(page)) {
+               priv = page_private(page);
+               f = afs_page_dirty_from(priv);
+               t = afs_page_dirty_to(priv);
+               if (from < f)
+                       f = from;
+               if (to > t)
+                       t = to;
+               priv = afs_page_dirty(f, t);
+               set_page_private(page, priv);
+               trace_afs_page_dirty(vnode, tracepoint_string("dirty+"),
+                                    page->index, priv);
+       } else {
+               priv = afs_page_dirty(from, to);
+               attach_page_private(page, (void *)priv);
+               trace_afs_page_dirty(vnode, tracepoint_string("dirty"),
+                                    page->index, priv);
+       }
+
        set_page_dirty(page);
        if (PageDirty(page))
                _debug("dirtied");
@@ -334,10 +337,9 @@ static void afs_pages_written_back(struct afs_vnode *vnode,
                ASSERTCMP(pv.nr, ==, count);
 
                for (loop = 0; loop < count; loop++) {
-                       priv = page_private(pv.pages[loop]);
+                       priv = (unsigned long)detach_page_private(pv.pages[loop]);
                        trace_afs_page_dirty(vnode, tracepoint_string("clear"),
                                             pv.pages[loop]->index, priv);
-                       set_page_private(pv.pages[loop], 0);
                        end_page_writeback(pv.pages[loop]);
                }
                first += count;
@@ -396,7 +398,8 @@ static void afs_store_data_success(struct afs_operation *op)
        op->ctime = op->file[0].scb.status.mtime_client;
        afs_vnode_commit_status(op, &op->file[0]);
        if (op->error == 0) {
-               afs_pages_written_back(vnode, op->store.first, op->store.last);
+               if (!op->store.laundering)
+                       afs_pages_written_back(vnode, op->store.first, op->store.last);
                afs_stat_v(vnode, n_stores);
                atomic_long_add((op->store.last * PAGE_SIZE + op->store.last_to) -
                                (op->store.first * PAGE_SIZE + op->store.first_offset),
@@ -415,7 +418,7 @@ static const struct afs_operation_ops afs_store_data_operation = {
  */
 static int afs_store_data(struct address_space *mapping,
                          pgoff_t first, pgoff_t last,
-                         unsigned offset, unsigned to)
+                         unsigned offset, unsigned to, bool laundering)
 {
        struct afs_vnode *vnode = AFS_FS_I(mapping->host);
        struct afs_operation *op;
@@ -448,6 +451,7 @@ static int afs_store_data(struct address_space *mapping,
        op->store.last = last;
        op->store.first_offset = offset;
        op->store.last_to = to;
+       op->store.laundering = laundering;
        op->mtime = vnode->vfs_inode.i_mtime;
        op->flags |= AFS_OPERATION_UNINTR;
        op->ops = &afs_store_data_operation;
@@ -509,8 +513,8 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
         */
        start = primary_page->index;
        priv = page_private(primary_page);
-       offset = priv & AFS_PRIV_MAX;
-       to = priv >> AFS_PRIV_SHIFT;
+       offset = afs_page_dirty_from(priv);
+       to = afs_page_dirty_to(priv);
        trace_afs_page_dirty(vnode, tracepoint_string("store"),
                             primary_page->index, priv);
 
@@ -555,8 +559,8 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
                        }
 
                        priv = page_private(page);
-                       f = priv & AFS_PRIV_MAX;
-                       t = priv >> AFS_PRIV_SHIFT;
+                       f = afs_page_dirty_from(priv);
+                       t = afs_page_dirty_to(priv);
                        if (f != 0 &&
                            !test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags)) {
                                unlock_page(page);
@@ -601,7 +605,7 @@ no_more:
        if (end > i_size)
                to = i_size & ~PAGE_MASK;
 
-       ret = afs_store_data(mapping, first, last, offset, to);
+       ret = afs_store_data(mapping, first, last, offset, to, false);
        switch (ret) {
        case 0:
                ret = count;
@@ -857,12 +861,14 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf)
         */
        wait_on_page_writeback(vmf->page);
 
-       priv = (unsigned long)PAGE_SIZE << AFS_PRIV_SHIFT; /* To */
-       priv |= 0; /* From */
+       priv = afs_page_dirty(0, PAGE_SIZE);
+       priv = afs_page_dirty_mmapped(priv);
        trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"),
                             vmf->page->index, priv);
-       SetPagePrivate(vmf->page);
-       set_page_private(vmf->page, priv);
+       if (PagePrivate(vmf->page))
+               set_page_private(vmf->page, priv);
+       else
+               attach_page_private(vmf->page, (void *)priv);
        file_update_time(file);
 
        sb_end_pagefault(inode->i_sb);
@@ -915,19 +921,18 @@ int afs_launder_page(struct page *page)
                f = 0;
                t = PAGE_SIZE;
                if (PagePrivate(page)) {
-                       f = priv & AFS_PRIV_MAX;
-                       t = priv >> AFS_PRIV_SHIFT;
+                       f = afs_page_dirty_from(priv);
+                       t = afs_page_dirty_to(priv);
                }
 
                trace_afs_page_dirty(vnode, tracepoint_string("launder"),
                                     page->index, priv);
-               ret = afs_store_data(mapping, page->index, page->index, t, f);
+               ret = afs_store_data(mapping, page->index, page->index, t, f, true);
        }
 
+       priv = (unsigned long)detach_page_private(page);
        trace_afs_page_dirty(vnode, tracepoint_string("laundered"),
                             page->index, priv);
-       set_page_private(page, 0);
-       ClearPagePrivate(page);
 
 #ifdef CONFIG_AFS_FSCACHE
        if (PageFsCache(page)) {
index 84f3c4f..38884d6 100644 (file)
@@ -85,7 +85,7 @@ static int afs_xattr_get_acl(const struct xattr_handler *handler,
                        if (acl->size <= size)
                                memcpy(buffer, acl->data, acl->size);
                        else
-                               op->error = -ERANGE;
+                               ret = -ERANGE;
                }
        }
 
index b3268f4..771a036 100644 (file)
@@ -544,7 +544,18 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info,
        int level = ref->level;
        struct btrfs_key search_key = ref->key_for_search;
 
-       root = btrfs_get_fs_root(fs_info, ref->root_id, false);
+       /*
+        * If we're search_commit_root we could possibly be holding locks on
+        * other tree nodes.  This happens when qgroups does backref walks when
+        * adding new delayed refs.  To deal with this we need to look in cache
+        * for the root, and if we don't find it then we need to search the
+        * tree_root's commit root, thus the btrfs_get_fs_root_commit_root usage
+        * here.
+        */
+       if (path->search_commit_root)
+               root = btrfs_get_fs_root_commit_root(fs_info, path, ref->root_id);
+       else
+               root = btrfs_get_fs_root(fs_info, ref->root_id, false);
        if (IS_ERR(root)) {
                ret = PTR_ERR(root);
                goto out_free;
index c0f1d68..3ba6f38 100644 (file)
@@ -2024,6 +2024,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
                key.offset = 0;
                btrfs_release_path(path);
        }
+       btrfs_release_path(path);
 
        list_for_each_entry(space_info, &info->space_info, list) {
                int i;
index aac3d6f..0378933 100644 (file)
@@ -3564,6 +3564,8 @@ struct reada_control *btrfs_reada_add(struct btrfs_root *root,
 int btrfs_reada_wait(void *handle);
 void btrfs_reada_detach(void *handle);
 int btree_readahead_hook(struct extent_buffer *eb, int err);
+void btrfs_reada_remove_dev(struct btrfs_device *dev);
+void btrfs_reada_undo_remove_dev(struct btrfs_device *dev);
 
 static inline int is_fstree(u64 rootid)
 {
index 4a0243c..5b9e3f3 100644 (file)
@@ -688,6 +688,9 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
        }
        btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
 
+       if (!scrub_ret)
+               btrfs_reada_remove_dev(src_device);
+
        /*
         * We have to use this loop approach because at this point src_device
         * has to be available for transaction commit to complete, yet new
@@ -696,6 +699,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
        while (1) {
                trans = btrfs_start_transaction(root, 0);
                if (IS_ERR(trans)) {
+                       btrfs_reada_undo_remove_dev(src_device);
                        mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
                        return PTR_ERR(trans);
                }
@@ -746,6 +750,7 @@ error:
                up_write(&dev_replace->rwsem);
                mutex_unlock(&fs_info->chunk_mutex);
                mutex_unlock(&fs_info->fs_devices->device_list_mutex);
+               btrfs_reada_undo_remove_dev(src_device);
                btrfs_rm_dev_replace_blocked(fs_info);
                if (tgt_device)
                        btrfs_destroy_dev_replace_tgtdev(tgt_device);
index 8e34386..af97ddc 100644 (file)
@@ -1281,32 +1281,26 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
-                                       struct btrfs_key *key)
+static struct btrfs_root *read_tree_root_path(struct btrfs_root *tree_root,
+                                             struct btrfs_path *path,
+                                             struct btrfs_key *key)
 {
        struct btrfs_root *root;
        struct btrfs_fs_info *fs_info = tree_root->fs_info;
-       struct btrfs_path *path;
        u64 generation;
        int ret;
        int level;
 
-       path = btrfs_alloc_path();
-       if (!path)
-               return ERR_PTR(-ENOMEM);
-
        root = btrfs_alloc_root(fs_info, key->objectid, GFP_NOFS);
-       if (!root) {
-               ret = -ENOMEM;
-               goto alloc_fail;
-       }
+       if (!root)
+               return ERR_PTR(-ENOMEM);
 
        ret = btrfs_find_root(tree_root, key, path,
                              &root->root_item, &root->root_key);
        if (ret) {
                if (ret > 0)
                        ret = -ENOENT;
-               goto find_fail;
+               goto fail;
        }
 
        generation = btrfs_root_generation(&root->root_item);
@@ -1317,21 +1311,31 @@ struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
        if (IS_ERR(root->node)) {
                ret = PTR_ERR(root->node);
                root->node = NULL;
-               goto find_fail;
+               goto fail;
        } else if (!btrfs_buffer_uptodate(root->node, generation, 0)) {
                ret = -EIO;
-               goto find_fail;
+               goto fail;
        }
        root->commit_root = btrfs_root_node(root);
-out:
-       btrfs_free_path(path);
        return root;
-
-find_fail:
+fail:
        btrfs_put_root(root);
-alloc_fail:
-       root = ERR_PTR(ret);
-       goto out;
+       return ERR_PTR(ret);
+}
+
+struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
+                                       struct btrfs_key *key)
+{
+       struct btrfs_root *root;
+       struct btrfs_path *path;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return ERR_PTR(-ENOMEM);
+       root = read_tree_root_path(tree_root, path, key);
+       btrfs_free_path(path);
+
+       return root;
 }
 
 /*
@@ -1419,6 +1423,31 @@ static struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info,
        return root;
 }
 
+static struct btrfs_root *btrfs_get_global_root(struct btrfs_fs_info *fs_info,
+                                               u64 objectid)
+{
+       if (objectid == BTRFS_ROOT_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->tree_root);
+       if (objectid == BTRFS_EXTENT_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->extent_root);
+       if (objectid == BTRFS_CHUNK_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->chunk_root);
+       if (objectid == BTRFS_DEV_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->dev_root);
+       if (objectid == BTRFS_CSUM_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->csum_root);
+       if (objectid == BTRFS_QUOTA_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->quota_root) ?
+                       fs_info->quota_root : ERR_PTR(-ENOENT);
+       if (objectid == BTRFS_UUID_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->uuid_root) ?
+                       fs_info->uuid_root : ERR_PTR(-ENOENT);
+       if (objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
+               return btrfs_grab_root(fs_info->free_space_root) ?
+                       fs_info->free_space_root : ERR_PTR(-ENOENT);
+       return NULL;
+}
+
 int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,
                         struct btrfs_root *root)
 {
@@ -1518,25 +1547,9 @@ static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info,
        struct btrfs_key key;
        int ret;
 
-       if (objectid == BTRFS_ROOT_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->tree_root);
-       if (objectid == BTRFS_EXTENT_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->extent_root);
-       if (objectid == BTRFS_CHUNK_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->chunk_root);
-       if (objectid == BTRFS_DEV_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->dev_root);
-       if (objectid == BTRFS_CSUM_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->csum_root);
-       if (objectid == BTRFS_QUOTA_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->quota_root) ?
-                       fs_info->quota_root : ERR_PTR(-ENOENT);
-       if (objectid == BTRFS_UUID_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->uuid_root) ?
-                       fs_info->uuid_root : ERR_PTR(-ENOENT);
-       if (objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
-               return btrfs_grab_root(fs_info->free_space_root) ?
-                       fs_info->free_space_root : ERR_PTR(-ENOENT);
+       root = btrfs_get_global_root(fs_info, objectid);
+       if (root)
+               return root;
 again:
        root = btrfs_lookup_fs_root(fs_info, objectid);
        if (root) {
@@ -1622,6 +1635,52 @@ struct btrfs_root *btrfs_get_new_fs_root(struct btrfs_fs_info *fs_info,
 }
 
 /*
+ * btrfs_get_fs_root_commit_root - return a root for the given objectid
+ * @fs_info:   the fs_info
+ * @objectid:  the objectid we need to lookup
+ *
+ * This is exclusively used for backref walking, and exists specifically because
+ * of how qgroups does lookups.  Qgroups will do a backref lookup at delayed ref
+ * creation time, which means we may have to read the tree_root in order to look
+ * up a fs root that is not in memory.  If the root is not in memory we will
+ * read the tree root commit root and look up the fs root from there.  This is a
+ * temporary root, it will not be inserted into the radix tree as it doesn't
+ * have the most uptodate information, it'll simply be discarded once the
+ * backref code is finished using the root.
+ */
+struct btrfs_root *btrfs_get_fs_root_commit_root(struct btrfs_fs_info *fs_info,
+                                                struct btrfs_path *path,
+                                                u64 objectid)
+{
+       struct btrfs_root *root;
+       struct btrfs_key key;
+
+       ASSERT(path->search_commit_root && path->skip_locking);
+
+       /*
+        * This can return -ENOENT if we ask for a root that doesn't exist, but
+        * since this is called via the backref walking code we won't be looking
+        * up a root that doesn't exist, unless there's corruption.  So if root
+        * != NULL just return it.
+        */
+       root = btrfs_get_global_root(fs_info, objectid);
+       if (root)
+               return root;
+
+       root = btrfs_lookup_fs_root(fs_info, objectid);
+       if (root)
+               return root;
+
+       key.objectid = objectid;
+       key.type = BTRFS_ROOT_ITEM_KEY;
+       key.offset = (u64)-1;
+       root = read_tree_root_path(fs_info->tree_root, path, &key);
+       btrfs_release_path(path);
+
+       return root;
+}
+
+/*
  * called by the kthread helper functions to finally call the bio end_io
  * functions.  This is where read checksum verification actually happens
  */
index fee69ce..182540b 100644 (file)
@@ -69,6 +69,9 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
                                     u64 objectid, bool check_ref);
 struct btrfs_root *btrfs_get_new_fs_root(struct btrfs_fs_info *fs_info,
                                         u64 objectid, dev_t anon_dev);
+struct btrfs_root *btrfs_get_fs_root_commit_root(struct btrfs_fs_info *fs_info,
+                                                struct btrfs_path *path,
+                                                u64 objectid);
 
 void btrfs_free_fs_info(struct btrfs_fs_info *fs_info);
 int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info);
index 3b21fee..5fd60b1 100644 (file)
@@ -3185,7 +3185,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                struct btrfs_tree_block_info *bi;
                if (item_size < sizeof(*ei) + sizeof(*bi)) {
                        btrfs_crit(info,
-"invalid extent item size for key (%llu, %u, %llu) owner %llu, has %u expect >= %lu",
+"invalid extent item size for key (%llu, %u, %llu) owner %llu, has %u expect >= %zu",
                                   key.objectid, key.type, key.offset,
                                   owner_objectid, item_size,
                                   sizeof(*ei) + sizeof(*bi));
index 0ff6594..87355a3 100644 (file)
@@ -3628,7 +3628,8 @@ static ssize_t btrfs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
                inode_lock_shared(inode);
                ret = btrfs_direct_IO(iocb, to);
                inode_unlock_shared(inode);
-               if (ret < 0)
+               if (ret < 0 || !iov_iter_count(to) ||
+                   iocb->ki_pos >= i_size_read(file_inode(iocb->ki_filp)))
                        return ret;
        }
 
index 936c313..da58c58 100644 (file)
@@ -9672,10 +9672,16 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
                 * clear_offset by our extent size.
                 */
                clear_offset += ins.offset;
-               btrfs_dec_block_group_reservations(fs_info, ins.objectid);
 
                last_alloc = ins.offset;
                trans = insert_prealloc_file_extent(trans, inode, &ins, cur_offset);
+               /*
+                * Now that we inserted the prealloc extent we can finally
+                * decrement the number of reservations in the block group.
+                * If we did it before, we could race with relocation and have
+                * relocation miss the reserved extent, making it fail later.
+                */
+               btrfs_dec_block_group_reservations(fs_info, ins.objectid);
                if (IS_ERR(trans)) {
                        ret = PTR_ERR(trans);
                        btrfs_free_reserved_extent(fs_info, ins.objectid,
index 580899b..c54ea65 100644 (file)
@@ -1026,6 +1026,10 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
                btrfs_item_key_to_cpu(leaf, &found_key, slot);
 
                if (found_key.type == BTRFS_ROOT_REF_KEY) {
+
+                       /* Release locks on tree_root before we access quota_root */
+                       btrfs_release_path(path);
+
                        ret = add_qgroup_item(trans, quota_root,
                                              found_key.offset);
                        if (ret) {
@@ -1044,6 +1048,20 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
                                btrfs_abort_transaction(trans, ret);
                                goto out_free_path;
                        }
+                       ret = btrfs_search_slot_for_read(tree_root, &found_key,
+                                                        path, 1, 0);
+                       if (ret < 0) {
+                               btrfs_abort_transaction(trans, ret);
+                               goto out_free_path;
+                       }
+                       if (ret > 0) {
+                               /*
+                                * Shouldn't happen, but in case it does we
+                                * don't need to do the btrfs_next_item, just
+                                * continue.
+                                */
+                               continue;
+                       }
                }
                ret = btrfs_next_item(tree_root, path);
                if (ret < 0) {
index 9d4f531..d9a166e 100644 (file)
@@ -421,6 +421,9 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
                if (!dev->bdev)
                        continue;
 
+               if (test_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state))
+                       continue;
+
                if (dev_replace_is_ongoing &&
                    dev == fs_info->dev_replace.tgtdev) {
                        /*
@@ -445,6 +448,8 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
                }
                have_zone = 1;
        }
+       if (!have_zone)
+               radix_tree_delete(&fs_info->reada_tree, index);
        spin_unlock(&fs_info->reada_lock);
        up_read(&fs_info->dev_replace.rwsem);
 
@@ -1020,3 +1025,45 @@ void btrfs_reada_detach(void *handle)
 
        kref_put(&rc->refcnt, reada_control_release);
 }
+
+/*
+ * Before removing a device (device replace or device remove ioctls), call this
+ * function to wait for all existing readahead requests on the device and to
+ * make sure no one queues more readahead requests for the device.
+ *
+ * Must be called without holding neither the device list mutex nor the device
+ * replace semaphore, otherwise it will deadlock.
+ */
+void btrfs_reada_remove_dev(struct btrfs_device *dev)
+{
+       struct btrfs_fs_info *fs_info = dev->fs_info;
+
+       /* Serialize with readahead extent creation at reada_find_extent(). */
+       spin_lock(&fs_info->reada_lock);
+       set_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state);
+       spin_unlock(&fs_info->reada_lock);
+
+       /*
+        * There might be readahead requests added to the radix trees which
+        * were not yet added to the readahead work queue. We need to start
+        * them and wait for their completion, otherwise we can end up with
+        * use-after-free problems when dropping the last reference on the
+        * readahead extents and their zones, as they need to access the
+        * device structure.
+        */
+       reada_start_machine(fs_info);
+       btrfs_flush_workqueue(fs_info->readahead_workers);
+}
+
+/*
+ * If when removing a device (device replace or device remove ioctls) an error
+ * happens after calling btrfs_reada_remove_dev(), call this to undo what that
+ * function did. This is safe to call even if btrfs_reada_remove_dev() was not
+ * called before.
+ */
+void btrfs_reada_undo_remove_dev(struct btrfs_device *dev)
+{
+       spin_lock(&dev->fs_info->reada_lock);
+       clear_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state);
+       spin_unlock(&dev->fs_info->reada_lock);
+}
index f0ffd5e..8784b74 100644 (file)
@@ -760,18 +760,36 @@ int btrfs_check_chunk_valid(struct extent_buffer *leaf,
        u64 type;
        u64 features;
        bool mixed = false;
+       int raid_index;
+       int nparity;
+       int ncopies;
 
        length = btrfs_chunk_length(leaf, chunk);
        stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
        num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
        sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
        type = btrfs_chunk_type(leaf, chunk);
+       raid_index = btrfs_bg_flags_to_raid_index(type);
+       ncopies = btrfs_raid_array[raid_index].ncopies;
+       nparity = btrfs_raid_array[raid_index].nparity;
 
        if (!num_stripes) {
                chunk_err(leaf, chunk, logical,
                          "invalid chunk num_stripes, have %u", num_stripes);
                return -EUCLEAN;
        }
+       if (num_stripes < ncopies) {
+               chunk_err(leaf, chunk, logical,
+                         "invalid chunk num_stripes < ncopies, have %u < %d",
+                         num_stripes, ncopies);
+               return -EUCLEAN;
+       }
+       if (nparity && num_stripes == nparity) {
+               chunk_err(leaf, chunk, logical,
+                         "invalid chunk num_stripes == nparity, have %u == %d",
+                         num_stripes, nparity);
+               return -EUCLEAN;
+       }
        if (!IS_ALIGNED(logical, fs_info->sectorsize)) {
                chunk_err(leaf, chunk, logical,
                "invalid chunk logical, have %llu should aligned to %u",
index 58b9c41..b1e4807 100644 (file)
@@ -431,7 +431,7 @@ static struct btrfs_device *__alloc_device(struct btrfs_fs_info *fs_info)
 
        atomic_set(&dev->reada_in_flight, 0);
        atomic_set(&dev->dev_stats_ccnt, 0);
-       btrfs_device_data_ordered_init(dev);
+       btrfs_device_data_ordered_init(dev, fs_info);
        INIT_RADIX_TREE(&dev->reada_zones, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
        INIT_RADIX_TREE(&dev->reada_extents, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
        extent_io_tree_init(fs_info, &dev->alloc_state,
@@ -2099,6 +2099,8 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
 
        mutex_unlock(&uuid_mutex);
        ret = btrfs_shrink_device(device, 0);
+       if (!ret)
+               btrfs_reada_remove_dev(device);
        mutex_lock(&uuid_mutex);
        if (ret)
                goto error_undo;
@@ -2179,6 +2181,7 @@ out:
        return ret;
 
 error_undo:
+       btrfs_reada_undo_remove_dev(device);
        if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) {
                mutex_lock(&fs_info->chunk_mutex);
                list_add(&device->dev_alloc_list,
index bf27ac0..232f02b 100644 (file)
@@ -39,10 +39,10 @@ struct btrfs_io_geometry {
 #if BITS_PER_LONG==32 && defined(CONFIG_SMP)
 #include <linux/seqlock.h>
 #define __BTRFS_NEED_DEVICE_DATA_ORDERED
-#define btrfs_device_data_ordered_init(device) \
-       seqcount_init(&device->data_seqcount)
+#define btrfs_device_data_ordered_init(device, info)                           \
+       seqcount_mutex_init(&device->data_seqcount, &info->chunk_mutex)
 #else
-#define btrfs_device_data_ordered_init(device) do { } while (0)
+#define btrfs_device_data_ordered_init(device, info) do { } while (0)
 #endif
 
 #define BTRFS_DEV_STATE_WRITEABLE      (0)
@@ -50,6 +50,7 @@ struct btrfs_io_geometry {
 #define BTRFS_DEV_STATE_MISSING                (2)
 #define BTRFS_DEV_STATE_REPLACE_TGT    (3)
 #define BTRFS_DEV_STATE_FLUSH_SENT     (4)
+#define BTRFS_DEV_STATE_NO_READA       (5)
 
 struct btrfs_device {
        struct list_head dev_list; /* device_list_mutex */
@@ -71,7 +72,8 @@ struct btrfs_device {
        blk_status_t last_flush_error;
 
 #ifdef __BTRFS_NEED_DEVICE_DATA_ORDERED
-       seqcount_t data_seqcount;
+       /* A seqcount_t with associated chunk_mutex (for lockdep) */
+       seqcount_mutex_t data_seqcount;
 #endif
 
        /* the internal btrfs device id */
@@ -162,11 +164,9 @@ btrfs_device_get_##name(const struct btrfs_device *dev)                    \
 static inline void                                                     \
 btrfs_device_set_##name(struct btrfs_device *dev, u64 size)            \
 {                                                                      \
-       preempt_disable();                                              \
        write_seqcount_begin(&dev->data_seqcount);                      \
        dev->name = size;                                               \
        write_seqcount_end(&dev->data_seqcount);                        \
-       preempt_enable();                                               \
 }
 #elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPTION)
 #define BTRFS_DEVICE_GETSET_FUNCS(name)                                        \
index 5b81f3b..ca50c90 100644 (file)
@@ -669,68 +669,8 @@ const struct file_operations ext4_dir_operations = {
 };
 
 #ifdef CONFIG_UNICODE
-static int ext4_d_compare(const struct dentry *dentry, unsigned int len,
-                         const char *str, const struct qstr *name)
-{
-       struct qstr qstr = {.name = str, .len = len };
-       const struct dentry *parent = READ_ONCE(dentry->d_parent);
-       const struct inode *inode = d_inode_rcu(parent);
-       char strbuf[DNAME_INLINE_LEN];
-
-       if (!inode || !IS_CASEFOLDED(inode) ||
-           !EXT4_SB(inode->i_sb)->s_encoding) {
-               if (len != name->len)
-                       return -1;
-               return memcmp(str, name->name, len);
-       }
-
-       /*
-        * If the dentry name is stored in-line, then it may be concurrently
-        * modified by a rename.  If this happens, the VFS will eventually retry
-        * the lookup, so it doesn't matter what ->d_compare() returns.
-        * However, it's unsafe to call utf8_strncasecmp() with an unstable
-        * string.  Therefore, we have to copy the name into a temporary buffer.
-        */
-       if (len <= DNAME_INLINE_LEN - 1) {
-               memcpy(strbuf, str, len);
-               strbuf[len] = 0;
-               qstr.name = strbuf;
-               /* prevent compiler from optimizing out the temporary buffer */
-               barrier();
-       }
-
-       return ext4_ci_compare(inode, name, &qstr, false);
-}
-
-static int ext4_d_hash(const struct dentry *dentry, struct qstr *str)
-{
-       const struct ext4_sb_info *sbi = EXT4_SB(dentry->d_sb);
-       const struct unicode_map *um = sbi->s_encoding;
-       const struct inode *inode = d_inode_rcu(dentry);
-       unsigned char *norm;
-       int len, ret = 0;
-
-       if (!inode || !IS_CASEFOLDED(inode) || !um)
-               return 0;
-
-       norm = kmalloc(PATH_MAX, GFP_ATOMIC);
-       if (!norm)
-               return -ENOMEM;
-
-       len = utf8_casefold(um, str, norm, PATH_MAX);
-       if (len < 0) {
-               if (ext4_has_strict_mode(sbi))
-                       ret = -EINVAL;
-               goto out;
-       }
-       str->hash = full_name_hash(dentry, norm, len);
-out:
-       kfree(norm);
-       return ret;
-}
-
 const struct dentry_operations ext4_dentry_ops = {
-       .d_hash = ext4_d_hash,
-       .d_compare = ext4_d_compare,
+       .d_hash = generic_ci_d_hash,
+       .d_compare = generic_ci_d_compare,
 };
 #endif
index 254d1c2..45fcdbf 100644 (file)
@@ -1166,10 +1166,6 @@ struct ext4_inode_info {
 #define        EXT4_VALID_FS                   0x0001  /* Unmounted cleanly */
 #define        EXT4_ERROR_FS                   0x0002  /* Errors detected */
 #define        EXT4_ORPHAN_FS                  0x0004  /* Orphans being recovered */
-#define EXT4_FC_INELIGIBLE             0x0008  /* Fast commit ineligible */
-#define EXT4_FC_COMMITTING             0x0010  /* File system underoing a fast
-                                                * commit.
-                                                */
 #define EXT4_FC_REPLAY                 0x0020  /* Fast commit replay ongoing */
 
 /*
@@ -1431,6 +1427,10 @@ struct ext4_super_block {
  */
 #define EXT4_MF_MNTDIR_SAMPLED         0x0001
 #define EXT4_MF_FS_ABORTED             0x0002  /* Fatal error detected */
+#define EXT4_MF_FC_INELIGIBLE          0x0004  /* Fast commit ineligible */
+#define EXT4_MF_FC_COMMITTING          0x0008  /* File system underoing a fast
+                                                * commit.
+                                                */
 
 #ifdef CONFIG_FS_ENCRYPTION
 #define DUMMY_ENCRYPTION_ENABLED(sbi) ((sbi)->s_dummy_enc_policy.policy != NULL)
@@ -1444,14 +1444,6 @@ struct ext4_super_block {
 #define EXT4_ENC_UTF8_12_1     1
 
 /*
- * Flags for ext4_sb_info.s_encoding_flags.
- */
-#define EXT4_ENC_STRICT_MODE_FL        (1 << 0)
-
-#define ext4_has_strict_mode(sbi) \
-       (sbi->s_encoding_flags & EXT4_ENC_STRICT_MODE_FL)
-
-/*
  * fourth extended-fs super-block data in memory
  */
 struct ext4_sb_info {
@@ -1500,10 +1492,6 @@ struct ext4_sb_info {
        struct kobject s_kobj;
        struct completion s_kobj_unregister;
        struct super_block *s_sb;
-#ifdef CONFIG_UNICODE
-       struct unicode_map *s_encoding;
-       __u16 s_encoding_flags;
-#endif
 
        /* Journaling */
        struct journal_s *s_journal;
index 559100f..57cfa28 100644 (file)
@@ -1471,16 +1471,16 @@ static int ext4_ext_search_left(struct inode *inode,
 }
 
 /*
- * search the closest allocated block to the right for *logical
- * and returns it at @logical + it's physical address at @phys
- * if *logical is the largest allocated block, the function
- * returns 0 at @phys
- * return value contains 0 (success) or error code
+ * Search the closest allocated block to the right for *logical
+ * and returns it at @logical + it's physical address at @phys.
+ * If not exists, return 0 and @phys is set to 0. We will return
+ * 1 which means we found an allocated block and ret_ex is valid.
+ * Or return a (< 0) error code.
  */
 static int ext4_ext_search_right(struct inode *inode,
                                 struct ext4_ext_path *path,
                                 ext4_lblk_t *logical, ext4_fsblk_t *phys,
-                                struct ext4_extent **ret_ex)
+                                struct ext4_extent *ret_ex)
 {
        struct buffer_head *bh = NULL;
        struct ext4_extent_header *eh;
@@ -1574,10 +1574,11 @@ got_index:
 found_extent:
        *logical = le32_to_cpu(ex->ee_block);
        *phys = ext4_ext_pblock(ex);
-       *ret_ex = ex;
+       if (ret_ex)
+               *ret_ex = *ex;
        if (bh)
                put_bh(bh);
-       return 0;
+       return 1;
 }
 
 /*
@@ -2868,8 +2869,8 @@ again:
                         */
                        lblk = ex_end + 1;
                        err = ext4_ext_search_right(inode, path, &lblk, &pblk,
-                                                   &ex);
-                       if (err)
+                                                   NULL);
+                       if (err < 0)
                                goto out;
                        if (pblk) {
                                partial.pclu = EXT4_B2C(sbi, pblk);
@@ -4039,7 +4040,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
                        struct ext4_map_blocks *map, int flags)
 {
        struct ext4_ext_path *path = NULL;
-       struct ext4_extent newex, *ex, *ex2;
+       struct ext4_extent newex, *ex, ex2;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        ext4_fsblk_t newblock = 0, pblk;
        int err = 0, depth, ret;
@@ -4175,15 +4176,14 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
        if (err)
                goto out;
        ar.lright = map->m_lblk;
-       ex2 = NULL;
        err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright, &ex2);
-       if (err)
+       if (err < 0)
                goto out;
 
        /* Check if the extent after searching to the right implies a
         * cluster we can use. */
-       if ((sbi->s_cluster_ratio > 1) && ex2 &&
-           get_implied_cluster_alloc(inode->i_sb, map, ex2, path)) {
+       if ((sbi->s_cluster_ratio > 1) && err &&
+           get_implied_cluster_alloc(inode->i_sb, map, &ex2, path)) {
                ar.len = allocated = map->m_len;
                newblock = map->m_pblk;
                goto got_allocated_blocks;
index 447c8d9..8d43058 100644 (file)
@@ -269,7 +269,7 @@ void ext4_fc_mark_ineligible(struct super_block *sb, int reason)
            (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY))
                return;
 
-       sbi->s_mount_state |= EXT4_FC_INELIGIBLE;
+       sbi->s_mount_flags |= EXT4_MF_FC_INELIGIBLE;
        WARN_ON(reason >= EXT4_FC_REASON_MAX);
        sbi->s_fc_stats.fc_ineligible_reason_count[reason]++;
 }
@@ -292,7 +292,7 @@ void ext4_fc_start_ineligible(struct super_block *sb, int reason)
 }
 
 /*
- * Stop a fast commit ineligible update. We set EXT4_FC_INELIGIBLE flag here
+ * Stop a fast commit ineligible update. We set EXT4_MF_FC_INELIGIBLE flag here
  * to ensure that after stopping the ineligible update, at least one full
  * commit takes place.
  */
@@ -302,13 +302,13 @@ void ext4_fc_stop_ineligible(struct super_block *sb)
            (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY))
                return;
 
-       EXT4_SB(sb)->s_mount_state |= EXT4_FC_INELIGIBLE;
+       EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FC_INELIGIBLE;
        atomic_dec(&EXT4_SB(sb)->s_fc_ineligible_updates);
 }
 
 static inline int ext4_fc_is_ineligible(struct super_block *sb)
 {
-       return (EXT4_SB(sb)->s_mount_state & EXT4_FC_INELIGIBLE) ||
+       return (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FC_INELIGIBLE) ||
                atomic_read(&EXT4_SB(sb)->s_fc_ineligible_updates);
 }
 
@@ -358,7 +358,7 @@ static int ext4_fc_track_template(
        spin_lock(&sbi->s_fc_lock);
        if (list_empty(&EXT4_I(inode)->i_fc_list))
                list_add_tail(&EXT4_I(inode)->i_fc_list,
-                               (sbi->s_mount_state & EXT4_FC_COMMITTING) ?
+                               (sbi->s_mount_flags & EXT4_MF_FC_COMMITTING) ?
                                &sbi->s_fc_q[FC_Q_STAGING] :
                                &sbi->s_fc_q[FC_Q_MAIN]);
        spin_unlock(&sbi->s_fc_lock);
@@ -411,7 +411,7 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update)
        node->fcd_name.len = dentry->d_name.len;
 
        spin_lock(&sbi->s_fc_lock);
-       if (sbi->s_mount_state & EXT4_FC_COMMITTING)
+       if (sbi->s_mount_flags & EXT4_MF_FC_COMMITTING)
                list_add_tail(&node->fcd_list,
                                &sbi->s_fc_dentry_q[FC_Q_STAGING]);
        else
@@ -846,7 +846,7 @@ static int ext4_fc_submit_inode_data_all(journal_t *journal)
        int ret = 0;
 
        spin_lock(&sbi->s_fc_lock);
-       sbi->s_mount_state |= EXT4_FC_COMMITTING;
+       sbi->s_mount_flags |= EXT4_MF_FC_COMMITTING;
        list_for_each(pos, &sbi->s_fc_q[FC_Q_MAIN]) {
                ei = list_entry(pos, struct ext4_inode_info, i_fc_list);
                ext4_set_inode_state(&ei->vfs_inode, EXT4_STATE_FC_COMMITTING);
@@ -964,7 +964,6 @@ static int ext4_fc_commit_dentry_updates(journal_t *journal, u32 *crc)
                        fc_dentry->fcd_parent, fc_dentry->fcd_ino,
                        fc_dentry->fcd_name.len,
                        fc_dentry->fcd_name.name, crc)) {
-                       spin_lock(&sbi->s_fc_lock);
                        ret = -ENOSPC;
                        goto lock_and_exit;
                }
@@ -1191,8 +1190,8 @@ static void ext4_fc_cleanup(journal_t *journal, int full)
        list_splice_init(&sbi->s_fc_q[FC_Q_STAGING],
                                &sbi->s_fc_q[FC_Q_STAGING]);
 
-       sbi->s_mount_state &= ~EXT4_FC_COMMITTING;
-       sbi->s_mount_state &= ~EXT4_FC_INELIGIBLE;
+       sbi->s_mount_flags &= ~EXT4_MF_FC_COMMITTING;
+       sbi->s_mount_flags &= ~EXT4_MF_FC_INELIGIBLE;
 
        if (full)
                sbi->s_fc_bytes = 0;
@@ -1617,8 +1616,10 @@ static int ext4_fc_replay_add_range(struct super_block *sb,
                if (ret == 0) {
                        /* Range is not mapped */
                        path = ext4_find_extent(inode, cur, NULL, 0);
-                       if (!path)
-                               continue;
+                       if (IS_ERR(path)) {
+                               iput(inode);
+                               return 0;
+                       }
                        memset(&newex, 0, sizeof(newex));
                        newex.ee_block = cpu_to_le32(cur);
                        ext4_ext_store_pblock(
@@ -2078,6 +2079,8 @@ static int ext4_fc_replay(journal_t *journal, struct buffer_head *bh,
 
 void ext4_fc_init(struct super_block *sb, journal_t *journal)
 {
+       int num_fc_blocks;
+
        /*
         * We set replay callback even if fast commit disabled because we may
         * could still have fast commit blocks that need to be replayed even if
@@ -2087,7 +2090,15 @@ void ext4_fc_init(struct super_block *sb, journal_t *journal)
        if (!test_opt2(sb, JOURNAL_FAST_COMMIT))
                return;
        journal->j_fc_cleanup_callback = ext4_fc_cleanup;
-       if (jbd2_fc_init(journal, EXT4_NUM_FC_BLKS)) {
+       if (!buffer_uptodate(journal->j_sb_buffer)
+               && ext4_read_bh_lock(journal->j_sb_buffer, REQ_META | REQ_PRIO,
+                                       true)) {
+               ext4_msg(sb, KERN_ERR, "I/O error on journal");
+               return;
+       }
+       num_fc_blocks = be32_to_cpu(journal->j_superblock->s_num_fc_blks);
+       if (jbd2_fc_init(journal, num_fc_blocks ? num_fc_blocks :
+                                       EXT4_NUM_FC_BLKS)) {
                pr_warn("Error while enabling fast commits, turning off.");
                ext4_clear_feature_fast_commit(sb);
        }
index 2924261..a92eb79 100644 (file)
@@ -275,7 +275,7 @@ int ext4fs_dirhash(const struct inode *dir, const char *name, int len,
                   struct dx_hash_info *hinfo)
 {
 #ifdef CONFIG_UNICODE
-       const struct unicode_map *um = EXT4_SB(dir->i_sb)->s_encoding;
+       const struct unicode_map *um = dir->i_sb->s_encoding;
        int r, dlen;
        unsigned char *buff;
        struct qstr qstr = {.name = name, .len = len };
index 03c2253..b96a186 100644 (file)
@@ -1918,7 +1918,7 @@ static int __ext4_journalled_writepage(struct page *page,
        }
        if (ret == 0)
                ret = err;
-       err = ext4_jbd2_inode_add_write(handle, inode, 0, len);
+       err = ext4_jbd2_inode_add_write(handle, inode, page_offset(page), len);
        if (ret == 0)
                ret = err;
        EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid;
@@ -3307,10 +3307,12 @@ static bool ext4_inode_datasync_dirty(struct inode *inode)
 
        if (journal) {
                if (jbd2_transaction_committed(journal,
-                                       EXT4_I(inode)->i_datasync_tid))
-                       return true;
-               return atomic_read(&EXT4_SB(inode->i_sb)->s_fc_subtid) >=
-                       EXT4_I(inode)->i_fc_committed_subtid;
+                       EXT4_I(inode)->i_datasync_tid))
+                       return false;
+               if (test_opt2(inode->i_sb, JOURNAL_FAST_COMMIT))
+                       return atomic_read(&EXT4_SB(inode->i_sb)->s_fc_subtid) <
+                               EXT4_I(inode)->i_fc_committed_subtid;
+               return true;
        }
 
        /* Any metadata buffers to write? */
@@ -6157,7 +6159,8 @@ retry_alloc:
                        if (ext4_walk_page_buffers(handle, page_buffers(page),
                                        0, len, NULL, write_end_fn))
                                goto out_error;
-                       if (ext4_jbd2_inode_add_write(handle, inode, 0, len))
+                       if (ext4_jbd2_inode_add_write(handle, inode,
+                                                     page_offset(page), len))
                                goto out_error;
                        ext4_set_inode_state(inode, EXT4_STATE_JDATA);
                } else {
index 5159830..f458d1d 100644 (file)
@@ -1285,8 +1285,8 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)
 int ext4_ci_compare(const struct inode *parent, const struct qstr *name,
                    const struct qstr *entry, bool quick)
 {
-       const struct ext4_sb_info *sbi = EXT4_SB(parent->i_sb);
-       const struct unicode_map *um = sbi->s_encoding;
+       const struct super_block *sb = parent->i_sb;
+       const struct unicode_map *um = sb->s_encoding;
        int ret;
 
        if (quick)
@@ -1298,7 +1298,7 @@ int ext4_ci_compare(const struct inode *parent, const struct qstr *name,
                /* Handle invalid character sequence as either an error
                 * or as an opaque byte sequence.
                 */
-               if (ext4_has_strict_mode(sbi))
+               if (sb_has_strict_encoding(sb))
                        return -EINVAL;
 
                if (name->len != entry->len)
@@ -1315,7 +1315,7 @@ void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
 {
        int len;
 
-       if (!IS_CASEFOLDED(dir) || !EXT4_SB(dir->i_sb)->s_encoding) {
+       if (!IS_CASEFOLDED(dir) || !dir->i_sb->s_encoding) {
                cf_name->name = NULL;
                return;
        }
@@ -1324,7 +1324,7 @@ void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
        if (!cf_name->name)
                return;
 
-       len = utf8_casefold(EXT4_SB(dir->i_sb)->s_encoding,
+       len = utf8_casefold(dir->i_sb->s_encoding,
                            iname, cf_name->name,
                            EXT4_NAME_LEN);
        if (len <= 0) {
@@ -1361,7 +1361,7 @@ static inline bool ext4_match(const struct inode *parent,
 #endif
 
 #ifdef CONFIG_UNICODE
-       if (EXT4_SB(parent->i_sb)->s_encoding && IS_CASEFOLDED(parent)) {
+       if (parent->i_sb->s_encoding && IS_CASEFOLDED(parent)) {
                if (fname->cf_name.name) {
                        struct qstr cf = {.name = fname->cf_name.name,
                                          .len = fname->cf_name.len};
@@ -2180,9 +2180,6 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
        struct buffer_head *bh = NULL;
        struct ext4_dir_entry_2 *de;
        struct super_block *sb;
-#ifdef CONFIG_UNICODE
-       struct ext4_sb_info *sbi;
-#endif
        struct ext4_filename fname;
        int     retval;
        int     dx_fallback=0;
@@ -2199,9 +2196,8 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                return -EINVAL;
 
 #ifdef CONFIG_UNICODE
-       sbi = EXT4_SB(sb);
-       if (ext4_has_strict_mode(sbi) && IS_CASEFOLDED(dir) &&
-           sbi->s_encoding && utf8_validate(sbi->s_encoding, &dentry->d_name))
+       if (sb_has_strict_encoding(sb) && IS_CASEFOLDED(dir) &&
+           sb->s_encoding && utf8_validate(sb->s_encoding, &dentry->d_name))
                return -EINVAL;
 #endif
 
index 2fe141f..ef4734b 100644 (file)
@@ -1288,7 +1288,7 @@ static void ext4_put_super(struct super_block *sb)
        fs_put_dax(sbi->s_daxdev);
        fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy);
 #ifdef CONFIG_UNICODE
-       utf8_unload(sbi->s_encoding);
+       utf8_unload(sb->s_encoding);
 #endif
        kfree(sbi);
 }
@@ -4303,7 +4303,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount;
 
 #ifdef CONFIG_UNICODE
-       if (ext4_has_feature_casefold(sb) && !sbi->s_encoding) {
+       if (ext4_has_feature_casefold(sb) && !sb->s_encoding) {
                const struct ext4_sb_encodings *encoding_info;
                struct unicode_map *encoding;
                __u16 encoding_flags;
@@ -4334,8 +4334,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                         "%s-%s with flags 0x%hx", encoding_info->name,
                         encoding_info->version?:"\b", encoding_flags);
 
-               sbi->s_encoding = encoding;
-               sbi->s_encoding_flags = encoding_flags;
+               sb->s_encoding = encoding;
+               sb->s_encoding_flags = encoding_flags;
        }
 #endif
 
@@ -4777,8 +4777,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_MAIN]);
        INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_STAGING]);
        sbi->s_fc_bytes = 0;
-       sbi->s_mount_state &= ~EXT4_FC_INELIGIBLE;
-       sbi->s_mount_state &= ~EXT4_FC_COMMITTING;
+       sbi->s_mount_flags &= ~EXT4_MF_FC_INELIGIBLE;
+       sbi->s_mount_flags &= ~EXT4_MF_FC_COMMITTING;
        spin_lock_init(&sbi->s_fc_lock);
        memset(&sbi->s_fc_stats, 0, sizeof(sbi->s_fc_stats));
        sbi->s_fc_replay_state.fc_regions = NULL;
@@ -4975,7 +4975,7 @@ no_journal:
        }
 
 #ifdef CONFIG_UNICODE
-       if (sbi->s_encoding)
+       if (sb->s_encoding)
                sb->s_d_op = &ext4_dentry_ops;
 #endif
 
@@ -5184,7 +5184,7 @@ failed_mount:
                crypto_free_shash(sbi->s_chksum_driver);
 
 #ifdef CONFIG_UNICODE
-       utf8_unload(sbi->s_encoding);
+       utf8_unload(sb->s_encoding);
 #endif
 
 #ifdef CONFIG_QUOTA
index 5ff33d1..4e27fe6 100644 (file)
@@ -315,6 +315,7 @@ EXT4_ATTR_FEATURE(casefold);
 EXT4_ATTR_FEATURE(verity);
 #endif
 EXT4_ATTR_FEATURE(metadata_csum_seed);
+EXT4_ATTR_FEATURE(fast_commit);
 
 static struct attribute *ext4_feat_attrs[] = {
        ATTR_LIST(lazy_itable_init),
@@ -331,6 +332,7 @@ static struct attribute *ext4_feat_attrs[] = {
        ATTR_LIST(verity),
 #endif
        ATTR_LIST(metadata_csum_seed),
+       ATTR_LIST(fast_commit),
        NULL,
 };
 ATTRIBUTE_GROUPS(ext4_feat);
index b42dfa0..a7429c9 100644 (file)
@@ -1365,6 +1365,9 @@ static void io_prep_async_work(struct io_kiocb *req)
        io_req_init_async(req);
        id = req->work.identity;
 
+       if (req->flags & REQ_F_FORCE_ASYNC)
+               req->work.flags |= IO_WQ_WORK_CONCURRENT;
+
        if (req->flags & REQ_F_ISREG) {
                if (def->hash_reg_file || (ctx->flags & IORING_SETUP_IOPOLL))
                        io_wq_hash_work(&req->work, file_inode(req->file));
@@ -1846,59 +1849,39 @@ static void __io_free_req(struct io_kiocb *req)
        percpu_ref_put(&ctx->refs);
 }
 
-static bool io_link_cancel_timeout(struct io_kiocb *req)
+static void io_kill_linked_timeout(struct io_kiocb *req)
 {
-       struct io_timeout_data *io = req->async_data;
        struct io_ring_ctx *ctx = req->ctx;
-       int ret;
-
-       ret = hrtimer_try_to_cancel(&io->timer);
-       if (ret != -1) {
-               io_cqring_fill_event(req, -ECANCELED);
-               io_commit_cqring(ctx);
-               req->flags &= ~REQ_F_LINK_HEAD;
-               io_put_req_deferred(req, 1);
-               return true;
-       }
-
-       return false;
-}
-
-static bool __io_kill_linked_timeout(struct io_kiocb *req)
-{
        struct io_kiocb *link;
-       bool wake_ev;
+       bool cancelled = false;
+       unsigned long flags;
 
-       if (list_empty(&req->link_list))
-               return false;
-       link = list_first_entry(&req->link_list, struct io_kiocb, link_list);
-       if (link->opcode != IORING_OP_LINK_TIMEOUT)
-               return false;
+       spin_lock_irqsave(&ctx->completion_lock, flags);
+       link = list_first_entry_or_null(&req->link_list, struct io_kiocb,
+                                       link_list);
        /*
         * Can happen if a linked timeout fired and link had been like
         * req -> link t-out -> link t-out [-> ...]
         */
-       if (!(link->flags & REQ_F_LTIMEOUT_ACTIVE))
-               return false;
+       if (link && (link->flags & REQ_F_LTIMEOUT_ACTIVE)) {
+               struct io_timeout_data *io = link->async_data;
+               int ret;
 
-       list_del_init(&link->link_list);
-       wake_ev = io_link_cancel_timeout(link);
+               list_del_init(&link->link_list);
+               ret = hrtimer_try_to_cancel(&io->timer);
+               if (ret != -1) {
+                       io_cqring_fill_event(link, -ECANCELED);
+                       io_commit_cqring(ctx);
+                       cancelled = true;
+               }
+       }
        req->flags &= ~REQ_F_LINK_TIMEOUT;
-       return wake_ev;
-}
-
-static void io_kill_linked_timeout(struct io_kiocb *req)
-{
-       struct io_ring_ctx *ctx = req->ctx;
-       unsigned long flags;
-       bool wake_ev;
-
-       spin_lock_irqsave(&ctx->completion_lock, flags);
-       wake_ev = __io_kill_linked_timeout(req);
        spin_unlock_irqrestore(&ctx->completion_lock, flags);
 
-       if (wake_ev)
+       if (cancelled) {
                io_cqring_ev_posted(ctx);
+               io_put_req(link);
+       }
 }
 
 static struct io_kiocb *io_req_link_next(struct io_kiocb *req)
@@ -4977,8 +4960,10 @@ static int io_poll_double_wake(struct wait_queue_entry *wait, unsigned mode,
                /* make sure double remove sees this as being gone */
                wait->private = NULL;
                spin_unlock(&poll->head->lock);
-               if (!done)
-                       __io_async_wake(req, poll, mask, io_poll_task_func);
+               if (!done) {
+                       /* use wait func handler, so it matches the rq type */
+                       poll->wait.func(&poll->wait, mode, sync, key);
+               }
        }
        refcount_dec(&req->refs);
        return 1;
@@ -6180,7 +6165,6 @@ static struct io_kiocb *io_prep_linked_timeout(struct io_kiocb *req)
 static void __io_queue_sqe(struct io_kiocb *req, struct io_comp_state *cs)
 {
        struct io_kiocb *linked_timeout;
-       struct io_kiocb *nxt;
        const struct cred *old_creds = NULL;
        int ret;
 
@@ -6206,7 +6190,6 @@ again:
         */
        if (ret == -EAGAIN && !(req->flags & REQ_F_NOWAIT)) {
                if (!io_arm_poll_handler(req)) {
-punt:
                        /*
                         * Queued up for async execution, worker will release
                         * submit reference when the iocb is actually submitted.
@@ -6216,33 +6199,25 @@ punt:
 
                if (linked_timeout)
                        io_queue_linked_timeout(linked_timeout);
-               goto exit;
-       }
+       } else if (likely(!ret)) {
+               /* drop submission reference */
+               req = io_put_req_find_next(req);
+               if (linked_timeout)
+                       io_queue_linked_timeout(linked_timeout);
 
-       if (unlikely(ret)) {
+               if (req) {
+                       if (!(req->flags & REQ_F_FORCE_ASYNC))
+                               goto again;
+                       io_queue_async_work(req);
+               }
+       } else {
                /* un-prep timeout, so it'll be killed as any other linked */
                req->flags &= ~REQ_F_LINK_TIMEOUT;
                req_set_fail_links(req);
                io_put_req(req);
                io_req_complete(req, ret);
-               goto exit;
        }
 
-       /* drop submission reference */
-       nxt = io_put_req_find_next(req);
-       if (linked_timeout)
-               io_queue_linked_timeout(linked_timeout);
-
-       if (nxt) {
-               req = nxt;
-
-               if (req->flags & REQ_F_FORCE_ASYNC) {
-                       linked_timeout = NULL;
-                       goto punt;
-               }
-               goto again;
-       }
-exit:
        if (old_creds)
                revert_creds(old_creds);
 }
@@ -6266,13 +6241,6 @@ fail_req:
                        if (unlikely(ret))
                                goto fail_req;
                }
-
-               /*
-                * Never try inline submit of IOSQE_ASYNC is set, go straight
-                * to async execution.
-                */
-               io_req_init_async(req);
-               req->work.flags |= IO_WQ_WORK_CONCURRENT;
                io_queue_async_work(req);
        } else {
                if (sqe) {
index 45f9872..4973328 100644 (file)
@@ -12,7 +12,8 @@
 #ifdef CONFIG_UACCESS_MEMCPY
 #include <asm/unaligned.h>
 
-static inline int __get_user_fn(size_t size, const void __user *from, void *to)
+static __always_inline int
+__get_user_fn(size_t size, const void __user *from, void *to)
 {
        BUILD_BUG_ON(!__builtin_constant_p(size));
 
@@ -37,7 +38,8 @@ static inline int __get_user_fn(size_t size, const void __user *from, void *to)
 }
 #define __get_user_fn(sz, u, k)        __get_user_fn(sz, u, k)
 
-static inline int __put_user_fn(size_t size, void __user *to, void *from)
+static __always_inline int
+__put_user_fn(size_t size, void __user *to, void *from)
 {
        BUILD_BUG_ON(!__builtin_constant_p(size));
 
index da53aeb..a53243a 100644 (file)
@@ -1836,7 +1836,7 @@ static inline void drm_dp_cec_unset_edid(struct drm_dp_aux *aux)
  * @link_rate: Requested Link rate from DPCD 0x219
  * @num_lanes: Number of lanes requested by sing through DPCD 0x220
  * @phy_pattern: DP Phy test pattern from DPCD 0x248
- * @hb2_reset: DP HBR2_COMPLIANCE_SCRAMBLER_RESET from DCPD 0x24A and 0x24B
+ * @hbr2_reset: DP HBR2_COMPLIANCE_SCRAMBLER_RESET from DCPD 0x24A and 0x24B
  * @custom80: DP Test_80BIT_CUSTOM_PATTERN from DPCDs 0x250 through 0x259
  * @enhanced_frame_cap: flag for enhanced frame capability.
  */
index b27a0e2..e97daf6 100644 (file)
@@ -359,13 +359,6 @@ drm_load_edid_firmware(struct drm_connector *connector)
 }
 #endif
 
-/**
- * drm_edid_are_equal - compare two edid blobs.
- * @edid1: pointer to first blob
- * @edid2: pointer to second blob
- * This helper can be used during probing to determine if
- * edid had changed.
- */
 bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2);
 
 int
index 1c94174..f32d179 100644 (file)
@@ -338,7 +338,7 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category,
                 const char *format, ...);
 
 /**
- * Error output.
+ * DRM_DEV_ERROR() - Error output.
  *
  * @dev: device pointer
  * @fmt: printf() like format string.
@@ -347,10 +347,12 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category,
        drm_dev_printk(dev, KERN_ERR, "*ERROR* " fmt, ##__VA_ARGS__)
 
 /**
- * Rate limited error output.  Like DRM_ERROR() but won't flood the log.
+ * DRM_DEV_ERROR_RATELIMITED() - Rate limited error output.
  *
  * @dev: device pointer
  * @fmt: printf() like format string.
+ *
+ * Like DRM_ERROR() but won't flood the log.
  */
 #define DRM_DEV_ERROR_RATELIMITED(dev, fmt, ...)                       \
 ({                                                                     \
@@ -375,15 +377,27 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category,
 })
 
 /**
- * Debug output.
+ * DRM_DEV_DEBUG() - Debug output for generic drm code
  *
  * @dev: device pointer
  * @fmt: printf() like format string.
  */
 #define DRM_DEV_DEBUG(dev, fmt, ...)                                   \
        drm_dev_dbg(dev, DRM_UT_CORE, fmt, ##__VA_ARGS__)
+/**
+ * DRM_DEV_DEBUG_DRIVER() - Debug output for vendor specific part of the driver
+ *
+ * @dev: device pointer
+ * @fmt: printf() like format string.
+ */
 #define DRM_DEV_DEBUG_DRIVER(dev, fmt, ...)                            \
        drm_dev_dbg(dev, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
+/**
+ * DRM_DEV_DEBUG_KMS() - Debug output for modesetting code
+ *
+ * @dev: device pointer
+ * @fmt: printf() like format string.
+ */
 #define DRM_DEV_DEBUG_KMS(dev, fmt, ...)                               \
        drm_dev_dbg(dev, DRM_UT_KMS, fmt, ##__VA_ARGS__)
 
index 885c9ff..f860645 100644 (file)
@@ -87,6 +87,8 @@
                           ARM_SMCCC_SMC_32,                            \
                           0, 0x7fff)
 
+#define SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED   1
+
 /* Paravirtualised time calls (defined by ARM DEN0057A) */
 #define ARM_SMCCC_HV_PV_TIME_FEATURES                          \
        ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,                 \
index fa37b1c..1eaa04f 100644 (file)
@@ -298,7 +298,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
 
 struct cpufreq_driver {
        char            name[CPUFREQ_NAME_LEN];
-       u             flags;
+       u16             flags;
        void            *driver_data;
 
        /* needed by all drivers */
@@ -422,9 +422,18 @@ struct cpufreq_driver {
  */
 #define CPUFREQ_IS_COOLING_DEV                 BIT(7)
 
+/*
+ * Set by drivers that need to update internale upper and lower boundaries along
+ * with the target frequency and so the core and governors should also invoke
+ * the diver if the target frequency does not change, but the policy min or max
+ * may have changed.
+ */
+#define CPUFREQ_NEED_UPDATE_LIMITS             BIT(8)
+
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
 
+bool cpufreq_driver_test_flags(u16 flags);
 const char *cpufreq_get_current_driver(void);
 void *cpufreq_get_driver_data(void);
 
index fb3d71a..1d5566a 100644 (file)
@@ -263,7 +263,10 @@ typedef struct journal_superblock_s
 /* 0x0050 */
        __u8    s_checksum_type;        /* checksum type */
        __u8    s_padding2[3];
-       __u32   s_padding[42];
+/* 0x0054 */
+       __be32  s_num_fc_blks;          /* Number of fast commit blocks */
+/* 0x0058 */
+       __u32   s_padding[41];
        __be32  s_checksum;             /* crc32c(superblock) */
 
 /* 0x0100 */
@@ -1253,7 +1256,7 @@ struct journal_s
         */
        void (*j_fc_cleanup_callback)(struct journal_s *journal, int);
 
-       /*
+       /**
         * @j_fc_replay_callback:
         *
         * File-system specific function that performs replay of a fast
index cfb62e9..ab7f8c1 100644 (file)
@@ -99,6 +99,7 @@ static inline u32 jhash(const void *key, u32 length, u32 initval)
        case 2:  a += (u32)k[1]<<8;     fallthrough;
        case 1:  a += k[0];
                 __jhash_final(a, b, c);
+                break;
        case 0: /* Nothing left to add */
                break;
        }
@@ -136,6 +137,7 @@ static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
        case 2: b += k[1];      fallthrough;
        case 1: a += k[0];
                __jhash_final(a, b, c);
+               break;
        case 0: /* Nothing left to add */
                break;
        }
index add8509..0f23e1e 100644 (file)
@@ -1213,4 +1213,22 @@ static inline bool mlx5_is_roce_enabled(struct mlx5_core_dev *dev)
        return val.vbool;
 }
 
+/**
+ * mlx5_core_net - Provide net namespace of the mlx5_core_dev
+ * @dev: mlx5 core device
+ *
+ * mlx5_core_net() returns the net namespace of mlx5 core device.
+ * This can be called only in below described limited context.
+ * (a) When a devlink instance for mlx5_core is registered and
+ *     when devlink reload operation is disabled.
+ *     or
+ * (b) during devlink reload reload_down() and reload_up callbacks
+ *     where it is ensured that devlink instance's net namespace is
+ *     stable.
+ */
+static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev)
+{
+       return devlink_net(priv_to_devlink(dev));
+}
+
 #endif /* MLX5_DRIVER_H */
index 7ccdf87..6264617 100644 (file)
@@ -740,7 +740,7 @@ static inline bool within_module(unsigned long addr, const struct module *mod)
 }
 
 /* Get/put a kernel symbol (calls should be symmetric) */
-#define symbol_get(x) ({ extern typeof(x) x __attribute__((weak)); &(x); })
+#define symbol_get(x) ({ extern typeof(x) x __attribute__((weak,visibility("hidden"))); &(x); })
 #define symbol_put(x) do { } while (0)
 #define symbol_put_addr(x) do { } while (0)
 
index 7bbc0e9..b256f9c 100644 (file)
@@ -238,6 +238,7 @@ static inline void siginitset(sigset_t *set, unsigned long mask)
                memset(&set->sig[1], 0, sizeof(long)*(_NSIG_WORDS-1));
                break;
        case 2: set->sig[1] = 0;
+               break;
        case 1: ;
        }
 }
@@ -250,6 +251,7 @@ static inline void siginitsetinv(sigset_t *set, unsigned long mask)
                memset(&set->sig[1], -1, sizeof(long)*(_NSIG_WORDS-1));
                break;
        case 2: set->sig[1] = -1;
+               break;
        case 1: ;
        }
 }
index c672ae1..32a67af 100644 (file)
@@ -227,19 +227,9 @@ void rdma_destroy_qp(struct rdma_cm_id *id);
 int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
                       int *qp_attr_mask);
 
-/**
- * rdma_connect - Initiate an active connection request.
- * @id: Connection identifier to connect.
- * @conn_param: Connection information used for connected QPs.
- *
- * Users must have resolved a route for the rdma_cm_id to connect with
- * by having called rdma_resolve_route before calling this routine.
- *
- * This call will either connect to a remote QP or obtain remote QP
- * information for unconnected rdma_cm_id's.  The actual operation is
- * based on the rdma_cm_id's port space.
- */
 int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
+int rdma_connect_locked(struct rdma_cm_id *id,
+                       struct rdma_conn_param *conn_param);
 
 int rdma_connect_ece(struct rdma_cm_id *id, struct rdma_conn_param *conn_param,
                     struct rdma_ucm_ece *ece);
index 8eb4923..4eef374 100644 (file)
@@ -966,19 +966,6 @@ TRACE_EVENT(afs_dir_check_failed,
                      __entry->vnode, __entry->off, __entry->i_size)
            );
 
-/*
- * We use page->private to hold the amount of the page that we've written to,
- * splitting the field into two parts.  However, we need to represent a range
- * 0...PAGE_SIZE inclusive, so we can't support 64K pages on a 32-bit system.
- */
-#if PAGE_SIZE > 32768
-#define AFS_PRIV_MAX   0xffffffff
-#define AFS_PRIV_SHIFT 32
-#else
-#define AFS_PRIV_MAX   0xffff
-#define AFS_PRIV_SHIFT 16
-#endif
-
 TRACE_EVENT(afs_page_dirty,
            TP_PROTO(struct afs_vnode *vnode, const char *where,
                     pgoff_t page, unsigned long priv),
@@ -999,10 +986,11 @@ TRACE_EVENT(afs_page_dirty,
                    __entry->priv = priv;
                           ),
 
-           TP_printk("vn=%p %lx %s %lu-%lu",
+           TP_printk("vn=%p %lx %s %zx-%zx%s",
                      __entry->vnode, __entry->page, __entry->where,
-                     __entry->priv & AFS_PRIV_MAX,
-                     __entry->priv >> AFS_PRIV_SHIFT)
+                     afs_page_dirty_from(__entry->priv),
+                     afs_page_dirty_to(__entry->priv),
+                     afs_is_page_dirty_mmapped(__entry->priv) ? " M" : "")
            );
 
 TRACE_EVENT(afs_call_state,
index 4b6a54d..45b054b 100644 (file)
@@ -146,7 +146,7 @@ int freeze_processes(void)
        BUG_ON(in_atomic());
 
        /*
-        * Now that the whole userspace is frozen we need to disbale
+        * Now that the whole userspace is frozen we need to disable
         * the OOM killer to disallow any further interference with
         * killable tasks. There is no guarantee oom victims will
         * ever reach a point they go away we have to wait with a timeout.
index e254745..c03a577 100644 (file)
@@ -102,7 +102,8 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
 static bool sugov_update_next_freq(struct sugov_policy *sg_policy, u64 time,
                                   unsigned int next_freq)
 {
-       if (sg_policy->next_freq == next_freq)
+       if (sg_policy->next_freq == next_freq &&
+           !cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS))
                return false;
 
        sg_policy->next_freq = next_freq;
@@ -161,7 +162,8 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy,
 
        freq = map_util_freq(util, freq, max);
 
-       if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update)
+       if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update &&
+           !cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS))
                return sg_policy->next_freq;
 
        sg_policy->need_freq_update = false;
index 3212e2c..84b7cab 100644 (file)
@@ -585,6 +585,7 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
        struct synth_field *field;
        const char *prefix = NULL, *field_type = argv[0], *field_name, *array;
        int len, ret = 0;
+       struct seq_buf s;
        ssize_t size;
 
        if (field_type[0] == ';')
@@ -630,13 +631,9 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
                field_type++;
        len = strlen(field_type) + 1;
 
-        if (array) {
-                int l = strlen(array);
+       if (array)
+               len += strlen(array);
 
-                if (l && array[l - 1] == ';')
-                        l--;
-                len += l;
-        }
        if (prefix)
                len += strlen(prefix);
 
@@ -645,14 +642,18 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
                ret = -ENOMEM;
                goto free;
        }
+       seq_buf_init(&s, field->type, len);
        if (prefix)
-               strcat(field->type, prefix);
-       strcat(field->type, field_type);
+               seq_buf_puts(&s, prefix);
+       seq_buf_puts(&s, field_type);
        if (array) {
-               strcat(field->type, array);
-               if (field->type[len - 1] == ';')
-                       field->type[len - 1] = '\0';
+               seq_buf_puts(&s, array);
+               if (s.buffer[s.len - 1] == ';')
+                       s.len--;
        }
+       if (WARN_ON_ONCE(!seq_buf_buffer_left(&s)))
+               goto free;
+       s.buffer[s.len] = '\0';
 
        size = synth_field_size(field->type);
        if (size < 0) {
@@ -663,14 +664,21 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
                if (synth_field_is_string(field->type)) {
                        char *type;
 
-                       type = kzalloc(sizeof("__data_loc ") + strlen(field->type) + 1, GFP_KERNEL);
+                       len = sizeof("__data_loc ") + strlen(field->type) + 1;
+                       type = kzalloc(len, GFP_KERNEL);
                        if (!type) {
                                ret = -ENOMEM;
                                goto free;
                        }
 
-                       strcat(type, "__data_loc ");
-                       strcat(type, field->type);
+                       seq_buf_init(&s, type, len);
+                       seq_buf_puts(&s, "__data_loc ");
+                       seq_buf_puts(&s, field->type);
+
+                       if (WARN_ON_ONCE(!seq_buf_buffer_left(&s)))
+                               goto free;
+                       s.buffer[s.len] = '\0';
+
                        kfree(field->type);
                        field->type = type;
 
index 0a482ef..a597789 100644 (file)
@@ -933,7 +933,7 @@ size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf,
        sg_miter_start(&miter, sgl, nents, sg_flags);
 
        if (!sg_miter_skip(&miter, skip))
-               return false;
+               return 0;
 
        while ((offset < buflen) && sg_miter_next(&miter)) {
                unsigned int len;
index a578634..a932d95 100644 (file)
@@ -4213,10 +4213,12 @@ static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
        if (err)
                goto nla_put_failure;
 
-       if (region->port)
-               if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
-                               region->port->index))
+       if (region->port) {
+               err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
+                                 region->port->index);
+               if (err)
                        goto nla_put_failure;
+       }
 
        err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name);
        if (err)
@@ -4265,10 +4267,12 @@ devlink_nl_region_notify_build(struct devlink_region *region,
        if (err)
                goto out_cancel_msg;
 
-       if (region->port)
-               if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
-                               region->port->index))
+       if (region->port) {
+               err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
+                                 region->port->index);
+               if (err)
                        goto out_cancel_msg;
+       }
 
        err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
                             region->ops->name);
@@ -4915,8 +4919,10 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
                index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
 
                port = devlink_port_get_by_index(devlink, index);
-               if (!port)
-                       return -ENODEV;
+               if (!port) {
+                       err = -ENODEV;
+                       goto out_unlock;
+               }
        }
 
        region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]);
@@ -4962,10 +4968,12 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
        if (err)
                goto nla_put_failure;
 
-       if (region->port)
-               if (nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
-                               region->port->index))
+       if (region->port) {
+               err = nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
+                                 region->port->index);
+               if (err)
                        goto nla_put_failure;
+       }
 
        err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
        if (err)
index bae4284..b2bc3d7 100644 (file)
@@ -485,6 +485,8 @@ static inline bool tcp_stream_is_readable(const struct tcp_sock *tp,
                        return true;
                if (tcp_rmem_pressure(sk))
                        return true;
+               if (tcp_receive_window(tp) <= inet_csk(sk)->icsk_ack.rcv_mss)
+                       return true;
        }
        if (sk->sk_prot->stream_memory_read)
                return sk->sk_prot->stream_memory_read(sk);
index fc44583..389d1b3 100644 (file)
@@ -4908,7 +4908,8 @@ void tcp_data_ready(struct sock *sk)
        int avail = tp->rcv_nxt - tp->copied_seq;
 
        if (avail < sk->sk_rcvlowat && !tcp_rmem_pressure(sk) &&
-           !sock_flag(sk, SOCK_DONE))
+           !sock_flag(sk, SOCK_DONE) &&
+           tcp_receive_window(tp) > inet_csk(sk)->icsk_ack.rcv_mss)
                return;
 
        sk->sk_data_ready(sk);
index 185dacb..e7419fd 100644 (file)
@@ -274,6 +274,15 @@ static bool __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk,
        skb_ext_reset(skb);
        skb_orphan(skb);
 
+       /* try to fetch required memory from subflow */
+       if (!sk_rmem_schedule(sk, skb, skb->truesize)) {
+               if (ssk->sk_forward_alloc < skb->truesize)
+                       goto drop;
+               __sk_mem_reclaim(ssk, skb->truesize);
+               if (!sk_rmem_schedule(sk, skb, skb->truesize))
+                       goto drop;
+       }
+
        /* the skb map_seq accounts for the skb offset:
         * mptcp_subflow_get_mapped_dsn() is based on the current tp->copied_seq
         * value
@@ -301,6 +310,7 @@ static bool __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk,
         * will retransmit as needed, if needed.
         */
        MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA);
+drop:
        mptcp_drop(sk, skb);
        return false;
 }
index 06603dd..b36b606 100644 (file)
@@ -956,9 +956,10 @@ int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id, bool isv6)
        rds_ib_cm_fill_conn_param(conn, &conn_param, &dp,
                                  conn->c_proposed_version,
                                  UINT_MAX, UINT_MAX, isv6);
-       ret = rdma_connect(cm_id, &conn_param);
+       ret = rdma_connect_locked(cm_id, &conn_param);
        if (ret)
-               rds_ib_conn_error(conn, "rdma_connect failed (%d)\n", ret);
+               rds_ib_conn_error(conn, "rdma_connect_locked failed (%d)\n",
+                                 ret);
 
 out:
        /* Beware - returning non-zero tells the rdma_cm to destroy
index f40bf97..5c7456e 100644 (file)
@@ -426,6 +426,7 @@ static void __exit mpls_cleanup_module(void)
 module_init(mpls_init_module);
 module_exit(mpls_cleanup_module);
 
+MODULE_SOFTDEP("post: mpls_gso");
 MODULE_AUTHOR("Netronome Systems <oss-drivers@netronome.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MPLS manipulation actions");
index faeabff..838b3fd 100644 (file)
@@ -652,12 +652,12 @@ static void tc_block_indr_cleanup(struct flow_block_cb *block_cb)
                               block_cb->indr.binder_type,
                               &block->flow_block, tcf_block_shared(block),
                               &extack);
+       rtnl_lock();
        down_write(&block->cb_lock);
        list_del(&block_cb->driver_list);
        list_move(&block_cb->list, &bo.cb_list);
-       up_write(&block->cb_lock);
-       rtnl_lock();
        tcf_block_unbind(block, &bo);
+       up_write(&block->cb_lock);
        rtnl_unlock();
 }
 
index 84f8277..0c345e4 100644 (file)
@@ -330,7 +330,7 @@ static s64 tabledist(s64 mu, s32 sigma,
 
        /* default uniform distribution */
        if (dist == NULL)
-               return ((rnd % (2 * sigma)) + mu) - sigma;
+               return ((rnd % (2 * (u32)sigma)) + mu) - sigma;
 
        t = dist->table[rnd % dist->size];
        x = (sigma % NETEM_DIST_SCALE) * t;
@@ -812,6 +812,10 @@ static void get_slot(struct netem_sched_data *q, const struct nlattr *attr)
                q->slot_config.max_packets = INT_MAX;
        if (q->slot_config.max_bytes == 0)
                q->slot_config.max_bytes = INT_MAX;
+
+       /* capping dist_jitter to the range acceptable by tabledist() */
+       q->slot_config.dist_jitter = min_t(__s64, INT_MAX, abs(q->slot_config.dist_jitter));
+
        q->slot.packets_left = q->slot_config.max_packets;
        q->slot.bytes_left = q->slot_config.max_bytes;
        if (q->slot_config.min_delay | q->slot_config.max_delay |
@@ -1037,6 +1041,9 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
        if (tb[TCA_NETEM_SLOT])
                get_slot(q, tb[TCA_NETEM_SLOT]);
 
+       /* capping jitter to the range acceptable by tabledist() */
+       q->jitter = min_t(s64, abs(q->jitter), INT_MAX);
+
        return ret;
 
 get_table_failure:
index 82be0bd..e9f487c 100644 (file)
@@ -1317,10 +1317,10 @@ static void smc_listen_out_err(struct smc_sock *new_smc)
 
 /* listen worker: decline and fall back if possible */
 static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
-                              struct smc_init_info *ini, u8 version)
+                              int local_first, u8 version)
 {
        /* RDMA setup failed, switch back to TCP */
-       if (ini->first_contact_local)
+       if (local_first)
                smc_lgr_cleanup_early(&new_smc->conn);
        else
                smc_conn_free(&new_smc->conn);
@@ -1768,7 +1768,8 @@ static void smc_listen_work(struct work_struct *work)
 out_unlock:
        mutex_unlock(&smc_server_lgr_pending);
 out_decl:
-       smc_listen_decline(new_smc, rc, ini, version);
+       smc_listen_decline(new_smc, rc, ini ? ini->first_contact_local : 0,
+                          version);
 out_free:
        kfree(ini);
        kfree(buf);
index d790c43..2b19863 100644 (file)
@@ -1615,8 +1615,11 @@ static struct smc_buf_desc *smcd_new_buf_create(struct smc_link_group *lgr,
                rc = smc_ism_register_dmb(lgr, bufsize, buf_desc);
                if (rc) {
                        kfree(buf_desc);
-                       return (rc == -ENOMEM) ? ERR_PTR(-EAGAIN) :
-                                                ERR_PTR(-EIO);
+                       if (rc == -ENOMEM)
+                               return ERR_PTR(-EAGAIN);
+                       if (rc == -ENOSPC)
+                               return ERR_PTR(-ENOSPC);
+                       return ERR_PTR(-EIO);
                }
                buf_desc->pages = virt_to_page(buf_desc->cpu_addr);
                /* CDC header stored in buf. So, pretend it was smaller */
index 2a78aa7..32c79c5 100644 (file)
@@ -150,12 +150,11 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
        if (fragid == FIRST_FRAGMENT) {
                if (unlikely(head))
                        goto err;
-               if (skb_cloned(frag))
-                       frag = skb_copy(frag, GFP_ATOMIC);
+               *buf = NULL;
+               frag = skb_unshare(frag, GFP_ATOMIC);
                if (unlikely(!frag))
                        goto err;
                head = *headbuf = frag;
-               *buf = NULL;
                TIPC_SKB_CB(head)->tail = NULL;
                if (skb_is_nonlinear(head)) {
                        skb_walk_frags(head, tail) {
index 9e93bc2..b4d7b8a 100644 (file)
@@ -739,7 +739,7 @@ static struct sock *__vsock_create(struct net *net,
                vsk->buffer_min_size = psk->buffer_min_size;
                vsk->buffer_max_size = psk->buffer_max_size;
        } else {
-               vsk->trusted = capable(CAP_NET_ADMIN);
+               vsk->trusted = ns_capable_noaudit(&init_user_ns, CAP_NET_ADMIN);
                vsk->owner = get_current_cred();
                vsk->connect_timeout = VSOCK_DEFAULT_CONNECT_TIMEOUT;
                vsk->buffer_size = VSOCK_DEFAULT_BUFFER_SIZE;
index 242635d..c9fa141 100644 (file)
@@ -417,6 +417,9 @@ int main(int argc, char *argv[])
        /* Register SIGSEGV handler */
        mte_register_signal(SIGSEGV, mte_default_handler);
 
+       /* Set test plan */
+       ksft_set_plan(20);
+
        /* Buffer by byte tests */
        evaluate_test(check_buffer_by_byte(USE_MMAP, MTE_SYNC_ERR),
        "Check buffer correctness by byte with sync err mode and mmap memory\n");
index 97bebde..43bd94f 100644 (file)
@@ -163,6 +163,9 @@ int main(int argc, char *argv[])
        mte_register_signal(SIGSEGV, mte_default_handler);
        mte_register_signal(SIGBUS, mte_default_handler);
 
+       /* Set test plan */
+       ksft_set_plan(12);
+
        evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
                "Check child anonymous memory with private mapping, precise mode and mmap memory\n");
        evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),
index bc41ae6..3b23c4d 100644 (file)
@@ -140,6 +140,10 @@ int main(int argc, char *argv[])
        /* Register signal handlers */
        mte_register_signal(SIGBUS, mte_default_handler);
        mte_register_signal(SIGSEGV, mte_default_handler);
+
+       /* Set test plan */
+       ksft_set_plan(4);
+
        /* Enable KSM */
        mte_ksm_setup();
 
index 33b13b8..a04b12c 100644 (file)
@@ -205,7 +205,11 @@ int main(int argc, char *argv[])
        mte_register_signal(SIGBUS, mte_default_handler);
        mte_register_signal(SIGSEGV, mte_default_handler);
 
+       /* Set test plan */
+       ksft_set_plan(22);
+
        mte_enable_pstate_tco();
+
        evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
        "Check anonymous memory with private mapping, sync error mode, mmap memory and tag check off\n");
        evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
index 94d245a..deaef1f 100644 (file)
@@ -170,6 +170,9 @@ int main(int argc, char *argv[])
        /* Register SIGSEGV handler */
        mte_register_signal(SIGSEGV, mte_default_handler);
 
+       /* Set test plan */
+       ksft_set_plan(4);
+
        evaluate_test(check_single_included_tags(USE_MMAP, MTE_SYNC_ERR),
                      "Check an included tag value with sync mode\n");
        evaluate_test(check_multiple_included_tags(USE_MMAP, MTE_SYNC_ERR),
index 594e98e..4bfa80f 100644 (file)
@@ -92,9 +92,13 @@ int main(int argc, char *argv[])
        err = mte_default_setup();
        if (err)
                return err;
+
        /* Register signal handlers */
        mte_register_signal(SIGSEGV, mte_default_handler);
 
+       /* Set test plan */
+       ksft_set_plan(4);
+
        evaluate_test(check_usermem_access_fault(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
                "Check memory access from kernel in sync mode, private mapping and mmap memory\n");
        evaluate_test(check_usermem_access_fault(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),