Merge tag 'amd-drm-fixes-6.2-2023-01-25' of https://gitlab.freedesktop.org/agd5f...
authorDave Airlie <airlied@redhat.com>
Fri, 27 Jan 2023 01:50:08 +0000 (11:50 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 27 Jan 2023 01:50:08 +0000 (11:50 +1000)
amd-drm-fixes-6.2-2023-01-25:

amdgpu:
- GC11.x fixes
- SMU13.0.0 fix
- Freesync video fix
- DP MST fixes

drm:
- DP MST kref fix

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230125220153.320248-1-alexander.deucher@amd.com
373 files changed:
.mailmap
Documentation/admin-guide/mm/zswap.rst
Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml
Documentation/devicetree/bindings/phy/amlogic,g12a-usb2-phy.yaml [moved from Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb2-phy.yaml with 85% similarity]
Documentation/devicetree/bindings/phy/amlogic,g12a-usb3-pcie-phy.yaml [moved from Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb3-pcie-phy.yaml with 82% similarity]
Documentation/devicetree/bindings/phy/qcom,usb-hs-28nm.yaml
Documentation/devicetree/bindings/soc/qcom/qcom,apr-services.yaml
Documentation/filesystems/erofs.rst
Documentation/kbuild/makefiles.rst
MAINTAINERS
Makefile
arch/arm/boot/dts/armada-38x.dtsi
arch/arm/boot/dts/armada-39x.dtsi
arch/arm/boot/dts/imx53-ppd.dts
arch/arm/boot/dts/imx6qdl-gw560x.dtsi
arch/arm/boot/dts/imx6ul-pico-dwarf.dts
arch/arm/boot/dts/imx7d-pico-dwarf.dts
arch/arm/boot/dts/imx7d-pico-nymph.dts
arch/arm/boot/dts/qcom-apq8084-ifc6540.dts
arch/arm/boot/dts/qcom-apq8084.dtsi
arch/arm/boot/dts/sam9x60.dtsi
arch/arm/boot/dts/stm32mp151a-prtt1l.dtsi
arch/arm/boot/dts/stm32mp157c-emstamp-argon.dtsi
arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi
arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi
arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
arch/arm/boot/dts/vf610-zii-dev-rev-c.dts
arch/arm/mach-footbridge/isa-rtc.c
arch/arm/mach-imx/cpu-imx25.c
arch/arm/mach-imx/cpu-imx27.c
arch/arm/mach-imx/cpu-imx31.c
arch/arm/mach-imx/cpu-imx35.c
arch/arm/mach-imx/cpu-imx5.c
arch/arm/mach-omap1/Kconfig
arch/arm/mach-omap1/Makefile
arch/arm/mach-omap1/gpio15xx.c
arch/arm/mach-omap1/io.c
arch/arm/mach-omap1/mcbsp.c
arch/arm/mach-omap1/pm.h
arch/arm/mach-pxa/Kconfig
arch/arm64/boot/dts/amlogic/meson-sm1-odroid-hc4.dts
arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts
arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi
arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi
arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts
arch/arm64/boot/dts/freescale/imx8mm-nitrogen-r2.dts
arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
arch/arm64/boot/dts/freescale/imx8mm-verdin-dahlia.dtsi
arch/arm64/boot/dts/freescale/imx8mm-verdin-dev.dtsi
arch/arm64/boot/dts/freescale/imx8mp-evk.dts
arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi
arch/arm64/boot/dts/freescale/imx8mp.dtsi
arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts
arch/arm64/boot/dts/freescale/imx8mq-thor96.dts
arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi
arch/arm64/boot/dts/qcom/msm8992-lg-bullhead.dtsi
arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
arch/arm64/boot/dts/qcom/msm8992.dtsi
arch/arm64/boot/dts/qcom/msm8994-huawei-angler-rev-101.dts
arch/arm64/boot/dts/qcom/sc8280xp.dtsi
arch/arm64/boot/dts/qcom/sm8250.dtsi
arch/arm64/boot/dts/qcom/sm8350.dtsi
arch/loongarch/include/asm/ftrace.h
arch/loongarch/include/asm/inst.h
arch/loongarch/include/asm/unwind.h
arch/loongarch/kernel/Makefile
arch/loongarch/kernel/alternative.c
arch/loongarch/kernel/cpu-probe.c
arch/loongarch/kernel/genex.S
arch/loongarch/kernel/inst.c
arch/loongarch/kernel/process.c
arch/loongarch/kernel/traps.c
arch/loongarch/kernel/unwind.c [new file with mode: 0644]
arch/loongarch/kernel/unwind_guess.c
arch/loongarch/kernel/unwind_prologue.c
arch/loongarch/mm/tlb.c
arch/riscv/boot/dts/sifive/fu740-c000.dtsi
arch/s390/kernel/setup.c
block/bfq-cgroup.c
block/bfq-iosched.h
block/blk-cgroup.c
block/blk-mq.c
drivers/accessibility/speakup/spk_ttyio.c
drivers/acpi/prmt.c
drivers/acpi/video_detect.c
drivers/base/property.c
drivers/base/test/test_async_driver_probe.c
drivers/block/pktcdvd.c
drivers/block/rnbd/rnbd-clt.c
drivers/bluetooth/hci_qca.c
drivers/comedi/drivers/adv_pci1760.c
drivers/dma/dmaengine.c
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
drivers/dma/idxd/device.c
drivers/dma/imx-sdma.c
drivers/dma/lgm/lgm-dma.c
drivers/dma/ptdma/ptdma-dev.c
drivers/dma/ptdma/ptdma.h
drivers/dma/qcom/gpi.c
drivers/dma/tegra186-gpc-dma.c
drivers/dma/tegra210-adma.c
drivers/dma/ti/k3-udma.c
drivers/dma/xilinx/xilinx_dma.c
drivers/firmware/arm_scmi/driver.c
drivers/firmware/arm_scmi/shmem.c
drivers/firmware/arm_scmi/virtio.c
drivers/firmware/google/gsmi.c
drivers/gpio/gpio-mxc.c
drivers/gpio/gpiolib-acpi.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c
drivers/hid/amd-sfh-hid/amd_sfh_client.c
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
drivers/hid/hid-betopff.c
drivers/hid/hid-bigbenff.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-playstation.c
drivers/hid/hid-quirks.c
drivers/hid/hid-uclogic-core.c
drivers/hid/hid-uclogic-params.c
drivers/hid/intel-ish-hid/ishtp/dma-if.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/hfi1/user_exp_rcv.c
drivers/infiniband/hw/hfi1/user_exp_rcv.h
drivers/infiniband/sw/rxe/rxe_param.h
drivers/infiniband/sw/rxe/rxe_pool.c
drivers/interconnect/qcom/icc-rpm.c
drivers/interconnect/qcom/msm8996.c
drivers/md/md.c
drivers/memory/atmel-sdramc.c
drivers/memory/mvebu-devbus.c
drivers/memory/omap-gpmc.c
drivers/memory/tegra/tegra186.c
drivers/misc/fastrpc.c
drivers/misc/mei/bus.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/pci-me.c
drivers/misc/vmw_vmci/vmci_guest.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sunxi-mmc.c
drivers/net/dsa/microchip/ksz9477.c
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
drivers/net/ethernet/amd/xgbe/xgbe.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/freescale/enetc/enetc.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/mellanox/mlx5/core/en/htb.c
drivers/net/ethernet/mellanox/mlx5/core/en/params.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/health.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/qos.c
drivers/net/ethernet/mellanox/mlx5/core/qos.h
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
drivers/net/ethernet/stmicro/stmmac/dwmac5.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ipa/ipa_interrupt.c
drivers/net/ipa/ipa_interrupt.h
drivers/net/ipa/ipa_power.c
drivers/net/phy/mdio_bus.c
drivers/net/team/team.c
drivers/net/usb/sr9700.c
drivers/net/virtio_net.c
drivers/net/wan/fsl_ucc_hdlc.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
drivers/net/wireless/mediatek/mt76/dma.c
drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
drivers/net/wireless/mediatek/mt76/tx.c
drivers/net/wireless/rndis_wlan.c
drivers/nvme/host/apple.c
drivers/nvme/host/pci.c
drivers/phy/freescale/phy-fsl-imx8m-pcie.c
drivers/phy/phy-can-transceiver.c
drivers/phy/qualcomm/phy-qcom-usb-hs-28nm.c
drivers/phy/renesas/r8a779f0-ether-serdes.c
drivers/phy/rockchip/phy-rockchip-inno-usb2.c
drivers/phy/sunplus/phy-sunplus-usb2.c
drivers/phy/ti/Kconfig
drivers/pinctrl/nomadik/pinctrl-ab8500.c
drivers/pinctrl/nomadik/pinctrl-ab8505.c
drivers/pinctrl/nomadik/pinctrl-abx500.c
drivers/pinctrl/nomadik/pinctrl-abx500.h
drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c
drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c
drivers/pinctrl/nomadik/pinctrl-nomadik.c
drivers/pinctrl/nomadik/pinctrl-nomadik.h
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/sunplus/sppctl.c
drivers/reset/Kconfig
drivers/reset/reset-uniphier-glue.c
drivers/soc/imx/imx8mp-blk-ctrl.c
drivers/soc/imx/soc-imx8m.c
drivers/soc/qcom/apr.c
drivers/soc/qcom/cpr.c
drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
drivers/thermal/thermal_core.c
drivers/thunderbolt/retimer.c
drivers/thunderbolt/tb.c
drivers/thunderbolt/tunnel.c
drivers/thunderbolt/xdomain.c
drivers/tty/serial/8250/8250_exar.c
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/kgdboc.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/qcom_geni_serial.c
drivers/tty/serial/serial_core.c
drivers/usb/cdns3/cdns3-gadget.c
drivers/usb/chipidea/core.c
drivers/usb/core/hub.c
drivers/usb/core/usb-acpi.c
drivers/usb/dwc3/Kconfig
drivers/usb/gadget/configfs.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_ncm.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/legacy/webcam.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/iowarrior.c
drivers/usb/misc/onboard_usb_hub.c
drivers/usb/musb/omap2430.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/option.c
drivers/usb/storage/uas-detect.h
drivers/usb/storage/unusual_uas.h
drivers/usb/typec/altmodes/displayport.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/ucsi.c
drivers/usb/typec/ucsi/ucsi.h
drivers/w1/w1.c
drivers/w1/w1_int.c
fs/affs/file.c
fs/btrfs/disk-io.c
fs/btrfs/file.c
fs/btrfs/fs.h
fs/btrfs/qgroup.c
fs/btrfs/space-info.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/zoned.c
fs/cifs/dfs_cache.c
fs/cifs/dfs_cache.h
fs/cifs/smb2pdu.c
fs/erofs/super.c
fs/erofs/zdata.c
fs/erofs/zmap.c
fs/ext4/xattr.c
fs/nfsd/netns.h
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsd.h
fs/nilfs2/btree.c
fs/userfaultfd.c
fs/zonefs/super.c
include/linux/bpf.h
include/linux/firmware/xlnx-zynqmp.h
include/linux/mm.h
include/linux/mm_inline.h
include/linux/mm_types.h
include/linux/page_ref.h
include/linux/soc/ti/omap1-io.h
include/linux/usb.h
include/net/mac80211.h
include/net/sch_generic.h
include/soc/bcm2835/raspberrypi-firmware.h
init/Kconfig
init/version-timestamp.c
io_uring/io_uring.c
io_uring/msg_ring.c
io_uring/poll.c
kernel/bpf/hashtab.c
kernel/bpf/offload.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/gen_kheaders.sh
kernel/printk/printk.c
kernel/sys.c
kernel/trace/bpf_trace.c
lib/scatterlist.c
lib/win_minmax.c
mm/hugetlb.c
mm/kasan/report.c
mm/khugepaged.c
mm/madvise.c
mm/mmap.c
mm/nommu.c
mm/shmem.c
mm/slab.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sync.c
net/bluetooth/iso.c
net/bluetooth/mgmt_util.h
net/bluetooth/rfcomm/sock.c
net/ethtool/rss.c
net/ipv4/inet_hashtables.c
net/ipv4/inet_timewait_sock.c
net/ipv4/tcp.c
net/ipv4/tcp_ulp.c
net/l2tp/l2tp_core.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/debugfs_sta.c
net/mac80211/driver-ops.c
net/mac80211/driver-ops.h
net/mac80211/ht.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/rx.c
net/mac80211/tx.c
net/mac80211/util.c
net/mptcp/pm.c
net/mptcp/pm_userspace.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netfilter/ipset/ip_set_bitmap_ip.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nft_payload.c
net/nfc/llcp_core.c
net/rxrpc/call_object.c
net/sched/sch_gred.c
net/sched/sch_htb.c
net/sched/sch_taprio.c
scripts/jobserver-exec
scripts/kconfig/.gitignore
scripts/kconfig/Makefile
scripts/package/mkspec
security/tomoyo/Kconfig
security/tomoyo/Makefile
tools/arch/arm64/include/asm/cputype.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/include/linux/build_bug.h
tools/include/uapi/linux/kvm.h
tools/perf/tests/shell/buildid.sh
tools/perf/trace/beauty/include/linux/socket.h
tools/perf/util/build-id.c
tools/perf/util/expr.l
tools/testing/selftests/lib.mk
tools/testing/selftests/net/mptcp/userspace_pm.sh
tools/testing/selftests/net/toeplitz.c
tools/testing/selftests/netfilter/nft_trans_stress.sh
tools/testing/selftests/netfilter/settings [new file with mode: 0644]
tools/testing/selftests/proc/proc-empty-vm.c
tools/testing/selftests/proc/proc-pid-vm.c

index 562f70d..8deff4c 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -371,6 +371,7 @@ Rémi Denis-Courmont <rdenis@simphalempin.com>
 Ricardo Ribalda <ribalda@kernel.org> <ricardo@ribalda.com>
 Ricardo Ribalda <ribalda@kernel.org> Ricardo Ribalda Delgado <ribalda@kernel.org>
 Ricardo Ribalda <ribalda@kernel.org> <ricardo.ribalda@gmail.com>
+Robert Foss <rfoss@kernel.org> <robert.foss@linaro.org>
 Roman Gushchin <roman.gushchin@linux.dev> <guro@fb.com>
 Roman Gushchin <roman.gushchin@linux.dev> <guroan@gmail.com>
 Roman Gushchin <roman.gushchin@linux.dev> <klamm@yandex-team.ru>
index f67de48..6dd74a1 100644 (file)
@@ -70,9 +70,7 @@ e.g. ``zswap.zpool=zbud``. It can also be changed at runtime using the sysfs
 The zbud type zpool allocates exactly 1 page to store 2 compressed pages, which
 means the compression ratio will always be 2:1 or worse (because of half-full
 zbud pages).  The zsmalloc type zpool has a more complex compressed page
-storage method, and it can achieve greater storage densities.  However,
-zsmalloc does not implement compressed page eviction, so once zswap fills it
-cannot evict the oldest page, it can only reject new pages.
+storage method, and it can achieve greater storage densities.
 
 When a swap page is passed from frontswap to zswap, zswap maintains a mapping
 of the swap entry, a combination of the swap type and swap offset, to the zpool
index 4b37aa8..5e6be4e 100644 (file)
@@ -84,7 +84,6 @@ allOf:
               - qcom,msm8939-pcnoc
               - qcom,msm8939-snoc
               - qcom,msm8996-a1noc
-              - qcom,msm8996-a2noc
               - qcom,msm8996-bimc
               - qcom,msm8996-cnoc
               - qcom,msm8996-pnoc
@@ -191,6 +190,29 @@ allOf:
         compatible:
           contains:
             enum:
+              - qcom,msm8996-a2noc
+
+    then:
+      properties:
+        clock-names:
+          items:
+            - const: bus
+            - const: bus_a
+            - const: aggre2_ufs_axi
+            - const: ufs_axi
+
+        clocks:
+          items:
+            - description: Bus Clock
+            - description: Bus A Clock
+            - description: Aggregate2 NoC UFS AXI Clock
+            - description: UFS AXI Clock
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
               - qcom,sdm660-a2noc
 
     then:
@@ -2,7 +2,7 @@
 # Copyright 2019 BayLibre, SAS
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/phy/amlogic,meson-g12a-usb2-phy.yaml#"
+$id: "http://devicetree.org/schemas/phy/amlogic,g12a-usb2-phy.yaml#"
 $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 
 title: Amlogic G12A USB2 PHY
@@ -13,8 +13,8 @@ maintainers:
 properties:
   compatible:
     enum:
-      - amlogic,meson-g12a-usb2-phy
-      - amlogic,meson-a1-usb2-phy
+      - amlogic,g12a-usb2-phy
+      - amlogic,a1-usb2-phy
 
   reg:
     maxItems: 1
@@ -68,7 +68,7 @@ additionalProperties: false
 examples:
   - |
     phy@36000 {
-          compatible = "amlogic,meson-g12a-usb2-phy";
+          compatible = "amlogic,g12a-usb2-phy";
           reg = <0x36000 0x2000>;
           clocks = <&xtal>;
           clock-names = "xtal";
@@ -2,7 +2,7 @@
 # Copyright 2019 BayLibre, SAS
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/phy/amlogic,meson-g12a-usb3-pcie-phy.yaml#"
+$id: "http://devicetree.org/schemas/phy/amlogic,g12a-usb3-pcie-phy.yaml#"
 $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 
 title: Amlogic G12A USB3 + PCIE Combo PHY
@@ -13,7 +13,7 @@ maintainers:
 properties:
   compatible:
     enum:
-      - amlogic,meson-g12a-usb3-pcie-phy
+      - amlogic,g12a-usb3-pcie-phy
 
   reg:
     maxItems: 1
@@ -49,7 +49,7 @@ additionalProperties: false
 examples:
   - |
     phy@46000 {
-          compatible = "amlogic,meson-g12a-usb3-pcie-phy";
+          compatible = "amlogic,g12a-usb3-pcie-phy";
           reg = <0x46000 0x2000>;
           clocks = <&ref_clk>;
           clock-names = "ref_clk";
index abcc437..ca6a083 100644 (file)
@@ -16,7 +16,6 @@ properties:
   compatible:
     enum:
       - qcom,usb-hs-28nm-femtophy
-      - qcom,usb-hs-28nm-mdm9607
 
   reg:
     maxItems: 1
index 2905554..bdf482d 100644 (file)
@@ -39,8 +39,8 @@ properties:
   qcom,protection-domain:
     $ref: /schemas/types.yaml#/definitions/string-array
     description: |
-      Protection domain service name and path for APR service
-      possible values are::
+      Protection domain service name and path for APR service (if supported).
+      Possible values are::
       "avs/audio", "msm/adsp/audio_pd".
       "kernel/elf_loader", "msm/modem/wlan_pd".
       "tms/servreg", "msm/adsp/audio_pd".
@@ -49,6 +49,5 @@ properties:
 
 required:
   - reg
-  - qcom,protection-domain
 
 additionalProperties: true
index 067fd16..a43aacf 100644 (file)
@@ -120,6 +120,8 @@ dax={always,never}     Use direct access (no page cache).  See
 dax                    A legacy option which is an alias for ``dax=always``.
 device=%s              Specify a path to an extra device to be used together.
 fsid=%s                Specify a filesystem image ID for Fscache back-end.
+domain_id=%s           Specify a domain ID in fscache mode so that different images
+                       with the same blobs under a given domain ID can share storage.
 ===================    =========================================================
 
 Sysfs Entries
index 6b7368d..38bc74e 100644 (file)
@@ -1042,7 +1042,7 @@ $(clean-files).
 
 When executing "make clean", the file "crc32table.h" will be deleted.
 Kbuild will assume files to be in the same relative directory as the
-Makefile, except if prefixed with $(objtree).
+Makefile.
 
 To exclude certain files or directories from make clean, use the
 $(no-clean-files) variable.
index 42fc47c..f781f93 100644 (file)
@@ -383,7 +383,7 @@ ACPI COMPONENT ARCHITECTURE (ACPICA)
 M:     Robert Moore <robert.moore@intel.com>
 M:     "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
 L:     linux-acpi@vger.kernel.org
-L:     devel@acpica.org
+L:     acpica-devel@lists.linuxfoundation.org
 S:     Supported
 W:     https://acpica.org/
 W:     https://github.com/acpica/acpica/
@@ -1104,7 +1104,6 @@ S:        Supported
 F:     arch/arm64/boot/dts/amd/
 
 AMD XGBE DRIVER
-M:     Tom Lendacky <thomas.lendacky@amd.com>
 M:     "Shyam Sundar S K" <Shyam-sundar.S-k@amd.com>
 L:     netdev@vger.kernel.org
 S:     Supported
@@ -6948,7 +6947,7 @@ F:        drivers/gpu/drm/atmel-hlcdc/
 DRM DRIVERS FOR BRIDGE CHIPS
 M:     Andrzej Hajda <andrzej.hajda@intel.com>
 M:     Neil Armstrong <neil.armstrong@linaro.org>
-M:     Robert Foss <robert.foss@linaro.org>
+M:     Robert Foss <rfoss@kernel.org>
 R:     Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
 R:     Jonas Karlman <jonas@kwiboo.se>
 R:     Jernej Skrabec <jernej.skrabec@gmail.com>
@@ -9299,7 +9298,7 @@ F:        net/dsa/tag_hellcreek.c
 
 HISILICON DMA DRIVER
 M:     Zhou Wang <wangzhou1@hisilicon.com>
-M:     Jie Hai <haijie1@hisilicon.com>
+M:     Jie Hai <haijie1@huawei.com>
 L:     dmaengine@vger.kernel.org
 S:     Maintained
 F:     drivers/dma/hisi_dma.c
@@ -15750,6 +15749,12 @@ S:     Maintained
 W:     https://wireless.wiki.kernel.org/en/users/Drivers/p54
 F:     drivers/net/wireless/intersil/p54/
 
+PACKET SOCKETS
+M:     Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+S:     Maintained
+F:     include/uapi/linux/if_packet.h
+F:     net/packet/af_packet.c
+
 PACKING
 M:     Vladimir Oltean <olteanv@gmail.com>
 L:     netdev@vger.kernel.org
@@ -17238,7 +17243,7 @@ F:      Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml
 F:     drivers/net/wwan/qcom_bam_dmux.c
 
 QUALCOMM CAMERA SUBSYSTEM DRIVER
-M:     Robert Foss <robert.foss@linaro.org>
+M:     Robert Foss <rfoss@kernel.org>
 M:     Todor Tomov <todor.too@gmail.com>
 L:     linux-media@vger.kernel.org
 S:     Maintained
@@ -17318,7 +17323,7 @@ F:      drivers/dma/qcom/hidma*
 
 QUALCOMM I2C CCI DRIVER
 M:     Loic Poulain <loic.poulain@linaro.org>
-M:     Robert Foss <robert.foss@linaro.org>
+M:     Robert Foss <rfoss@kernel.org>
 L:     linux-i2c@vger.kernel.org
 L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
@@ -19326,6 +19331,13 @@ L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Orphan
 F:     sound/soc/uniphier/
 
+SOCKET TIMESTAMPING
+M:     Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+S:     Maintained
+F:     Documentation/networking/timestamping.rst
+F:     include/uapi/linux/net_tstamp.h
+F:     tools/testing/selftests/net/so_txtime.c
+
 SOEKRIS NET48XX LED SUPPORT
 M:     Chris Boot <bootc@bootc.net>
 S:     Maintained
@@ -21746,6 +21758,13 @@ T:     git git://linuxtv.org/media_tree.git
 F:     Documentation/admin-guide/media/zr364xx*
 F:     drivers/staging/media/deprecated/zr364xx/
 
+USER DATAGRAM PROTOCOL (UDP)
+M:     Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+S:     Maintained
+F:     include/linux/udp.h
+F:     net/ipv4/udp.c
+F:     net/ipv6/udp.c
+
 USER-MODE LINUX (UML)
 M:     Richard Weinberger <richard@nod.at>
 M:     Anton Ivanov <anton.ivanov@cambridgegreys.com>
index e09fe10..c1ead4c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 2
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc5
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
@@ -549,7 +549,7 @@ LDFLAGS_MODULE  =
 CFLAGS_KERNEL  =
 RUSTFLAGS_KERNEL =
 AFLAGS_KERNEL  =
-export LDFLAGS_vmlinux =
+LDFLAGS_vmlinux =
 
 # Use USERINCLUDE when you must reference the UAPI directories only.
 USERINCLUDE    := \
@@ -1248,6 +1248,18 @@ vmlinux.o modules.builtin.modinfo modules.builtin: vmlinux_o
        @:
 
 PHONY += vmlinux
+# LDFLAGS_vmlinux in the top Makefile defines linker flags for the top vmlinux,
+# not for decompressors. LDFLAGS_vmlinux in arch/*/boot/compressed/Makefile is
+# unrelated; the decompressors just happen to have the same base name,
+# arch/*/boot/compressed/vmlinux.
+# Export LDFLAGS_vmlinux only to scripts/Makefile.vmlinux.
+#
+# _LDFLAGS_vmlinux is a workaround for the 'private export' bug:
+#   https://savannah.gnu.org/bugs/?61463
+# For Make > 4.4, the following simple code will work:
+#  vmlinux: private export LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
+vmlinux: private _LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
+vmlinux: export LDFLAGS_vmlinux = $(_LDFLAGS_vmlinux)
 vmlinux: vmlinux.o $(KBUILD_LDS) modpost
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.vmlinux
 
@@ -1533,6 +1545,7 @@ endif
 # *.ko are usually independent of vmlinux, but CONFIG_DEBUG_INFOBTF_MODULES
 # is an exception.
 ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+KBUILD_BUILTIN := 1
 modules: vmlinux
 endif
 
index 12933ef..446861b 100644 (file)
                        };
 
                        gpio0: gpio@18100 {
-                               compatible = "marvell,armadaxp-gpio",
+                               compatible = "marvell,armada-370-gpio",
                                             "marvell,orion-gpio";
                                reg = <0x18100 0x40>, <0x181c0 0x08>;
                                reg-names = "gpio", "pwm";
                        };
 
                        gpio1: gpio@18140 {
-                               compatible = "marvell,armadaxp-gpio",
+                               compatible = "marvell,armada-370-gpio",
                                             "marvell,orion-gpio";
                                reg = <0x18140 0x40>, <0x181c8 0x08>;
                                reg-names = "gpio", "pwm";
index 1e05208..9d1cac4 100644 (file)
                        };
 
                        gpio0: gpio@18100 {
-                               compatible = "marvell,armadaxp-gpio", "marvell,orion-gpio";
+                               compatible = "marvell,orion-gpio";
                                reg = <0x18100 0x40>;
                                ngpios = <32>;
                                gpio-controller;
                        };
 
                        gpio1: gpio@18140 {
-                               compatible = "marvell,armadaxp-gpio", "marvell,orion-gpio";
+                               compatible = "marvell,orion-gpio";
                                reg = <0x18140 0x40>;
                                ngpios = <28>;
                                gpio-controller;
index 37d0cff..70c4a48 100644 (file)
        scl-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
        status = "okay";
 
-       i2c-switch@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9547";
                #address-cells = <1>;
                #size-cells = <0>;
index 4bc4371..4b81a97 100644 (file)
 &uart1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart1>;
-       uart-has-rtscts;
        rts-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
        status = "okay";
 };
index 162dc25..5a74c7f 100644 (file)
@@ -32,7 +32,7 @@
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
index 5162fe2..fdc1056 100644 (file)
@@ -32,7 +32,7 @@
 };
 
 &i2c1 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
@@ -52,7 +52,7 @@
 };
 
 &i2c4 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
index 104a852..5afb167 100644 (file)
@@ -43,7 +43,7 @@
 };
 
 &i2c1 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
@@ -64,7 +64,7 @@
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
index 44cd72f..116e59a 100644 (file)
                serial@f995e000 {
                        status = "okay";
                };
+       };
+};
 
-               sdhci@f9824900 {
-                       bus-width = <8>;
-                       non-removable;
-                       status = "okay";
-               };
+&sdhc_1 {
+       bus-width = <8>;
+       non-removable;
+       status = "okay";
+};
 
-               sdhci@f98a4900 {
-                       cd-gpios = <&tlmm 122 GPIO_ACTIVE_LOW>;
-                       bus-width = <4>;
-               };
-       };
+&sdhc_2 {
+       cd-gpios = <&tlmm 122 GPIO_ACTIVE_LOW>;
+       bus-width = <4>;
 };
index fe30abf..4b0d2b4 100644 (file)
                        status = "disabled";
                };
 
-               mmc@f9824900 {
+               sdhc_1: mmc@f9824900 {
                        compatible = "qcom,apq8084-sdhci", "qcom,sdhci-msm-v4";
                        reg = <0xf9824900 0x11c>, <0xf9824000 0x800>;
                        reg-names = "hc", "core";
                        status = "disabled";
                };
 
-               mmc@f98a4900 {
+               sdhc_2: mmc@f98a4900 {
                        compatible = "qcom,apq8084-sdhci", "qcom,sdhci-msm-v4";
                        reg = <0xf98a4900 0x11c>, <0xf98a4000 0x800>;
                        reg-names = "hc", "core";
index 8f5477e..37a5d96 100644 (file)
                        mpddrc: mpddrc@ffffe800 {
                                compatible = "microchip,sam9x60-ddramc", "atmel,sama5d3-ddramc";
                                reg = <0xffffe800 0x200>;
-                               clocks = <&pmc PMC_TYPE_SYSTEM 2>, <&pmc PMC_TYPE_CORE PMC_MCK>;
+                               clocks = <&pmc PMC_TYPE_SYSTEM 2>, <&pmc PMC_TYPE_PERIPHERAL 49>;
                                clock-names = "ddrck", "mpddr";
                        };
 
index d865ab5..dd23de8 100644 (file)
 
 &qspi {
        pinctrl-names = "default", "sleep";
-       pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>;
-       pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>;
+       pinctrl-0 = <&qspi_clk_pins_a
+                    &qspi_bk1_pins_a
+                    &qspi_cs1_pins_a>;
+       pinctrl-1 = <&qspi_clk_sleep_pins_a
+                    &qspi_bk1_sleep_pins_a
+                    &qspi_cs1_sleep_pins_a>;
        reg = <0x58003000 0x1000>, <0x70000000 0x4000000>;
        #address-cells = <1>;
        #size-cells = <0>;
index aef02e6..7d11c50 100644 (file)
 
 &qspi {
        pinctrl-names = "default", "sleep";
-       pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>;
-       pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>;
+       pinctrl-0 = <&qspi_clk_pins_a
+                    &qspi_bk1_pins_a
+                    &qspi_cs1_pins_a>;
+       pinctrl-1 = <&qspi_clk_sleep_pins_a
+                    &qspi_bk1_sleep_pins_a
+                    &qspi_cs1_sleep_pins_a>;
        reg = <0x58003000 0x1000>, <0x70000000 0x4000000>;
        #address-cells = <1>;
        #size-cells = <0>;
index 002f221..c06edd2 100644 (file)
 
 &qspi {
        pinctrl-names = "default", "sleep";
-       pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>;
-       pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>;
+       pinctrl-0 = <&qspi_clk_pins_a
+                    &qspi_bk1_pins_a
+                    &qspi_cs1_pins_a>;
+       pinctrl-1 = <&qspi_clk_sleep_pins_a
+                    &qspi_bk1_sleep_pins_a
+                    &qspi_cs1_sleep_pins_a>;
        reg = <0x58003000 0x1000>, <0x70000000 0x4000000>;
        #address-cells = <1>;
        #size-cells = <0>;
index 134a798..bb40fb4 100644 (file)
 
 &qspi {
        pinctrl-names = "default", "sleep";
-       pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>;
-       pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>;
+       pinctrl-0 = <&qspi_clk_pins_a
+                    &qspi_bk1_pins_a
+                    &qspi_cs1_pins_a>;
+       pinctrl-1 = <&qspi_clk_sleep_pins_a
+                    &qspi_bk1_sleep_pins_a
+                    &qspi_cs1_sleep_pins_a>;
        reg = <0x58003000 0x1000>, <0x70000000 0x200000>;
        #address-cells = <1>;
        #size-cells = <0>;
index 42ed4a0..6280c5e 100644 (file)
 };
 
 &i2c2 {
-       tca9548@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9548";
                pinctrl-0 = <&pinctrl_i2c_mux_reset>;
                pinctrl-names = "default";
index f892977..c00d395 100644 (file)
 };
 
 &i2c2 {
-       tca9548@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9548";
                pinctrl-0 = <&pinctrl_i2c_mux_reset>;
                pinctrl-names = "default";
index b8f741a..237b828 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <linux/init.h>
 #include <linux/mc146818rtc.h>
-#include <linux/bcd.h>
 #include <linux/io.h>
 
 #include "common.h"
index 3e63445..cc86977 100644 (file)
@@ -23,6 +23,7 @@ static int mx25_read_cpu_rev(void)
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx25-iim");
        iim_base = of_iomap(np, 0);
+       of_node_put(np);
        BUG_ON(!iim_base);
        rev = readl(iim_base + MXC_IIMSREV);
        iounmap(iim_base);
index bf70e13..1d28939 100644 (file)
@@ -28,6 +28,7 @@ static int mx27_read_cpu_rev(void)
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx27-ccm");
        ccm_base = of_iomap(np, 0);
+       of_node_put(np);
        BUG_ON(!ccm_base);
        /*
         * now we have access to the IO registers. As we need
index b9c24b8..35c5449 100644 (file)
@@ -39,6 +39,7 @@ static int mx31_read_cpu_rev(void)
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx31-iim");
        iim_base = of_iomap(np, 0);
+       of_node_put(np);
        BUG_ON(!iim_base);
 
        /* read SREV register from IIM module */
index 80e7d8a..1fe75b3 100644 (file)
@@ -21,6 +21,7 @@ static int mx35_read_cpu_rev(void)
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx35-iim");
        iim_base = of_iomap(np, 0);
+       of_node_put(np);
        BUG_ON(!iim_base);
 
        rev = imx_readl(iim_base + MXC_IIMSREV);
index ad56263..a67c89b 100644 (file)
@@ -28,6 +28,7 @@ static u32 imx5_read_srev_reg(const char *compat)
 
        np = of_find_compatible_node(NULL, NULL, compat);
        iim_base = of_iomap(np, 0);
+       of_node_put(np);
        WARN_ON(!iim_base);
 
        srev = readl(iim_base + IIM_SREV) & 0xff;
index 538a960..7ec7ada 100644 (file)
@@ -4,6 +4,7 @@ menuconfig ARCH_OMAP1
        depends on ARCH_MULTI_V4T || ARCH_MULTI_V5
        depends on CPU_LITTLE_ENDIAN
        depends on ATAGS
+       select ARCH_OMAP
        select ARCH_HAS_HOLES_MEMORYMODEL
        select ARCH_OMAP
        select CLKSRC_MMIO
@@ -45,10 +46,6 @@ config ARCH_OMAP16XX
        select CPU_ARM926T
        select OMAP_DM_TIMER
 
-config ARCH_OMAP1_ANY
-       select ARCH_OMAP
-       def_bool ARCH_OMAP730 || ARCH_OMAP850 || ARCH_OMAP15XX || ARCH_OMAP16XX
-
 config ARCH_OMAP
        bool
 
index 506074b..0615cb0 100644 (file)
@@ -3,8 +3,6 @@
 # Makefile for the linux kernel.
 #
 
-ifdef CONFIG_ARCH_OMAP1_ANY
-
 # Common support
 obj-y := io.o id.o sram-init.o sram.o time.o irq.o mux.o flash.o \
         serial.o devices.o dma.o omap-dma.o fb.o
@@ -59,5 +57,3 @@ obj-$(CONFIG_ARCH_OMAP730)            += gpio7xx.o
 obj-$(CONFIG_ARCH_OMAP850)             += gpio7xx.o
 obj-$(CONFIG_ARCH_OMAP15XX)            += gpio15xx.o
 obj-$(CONFIG_ARCH_OMAP16XX)            += gpio16xx.o
-
-endif
index c675f11..61fa26e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/gpio.h>
 #include <linux/platform_data/gpio-omap.h>
 #include <linux/soc/ti/omap1-soc.h>
+#include <asm/irq.h>
 
 #include "irqs.h"
 
index d2db9b8..0074b01 100644 (file)
  * The machine specific code may provide the extra mapping besides the
  * default mapping provided here.
  */
-static struct map_desc omap_io_desc[] __initdata = {
+#if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
+static struct map_desc omap7xx_io_desc[] __initdata = {
        {
                .virtual        = OMAP1_IO_VIRT,
                .pfn            = __phys_to_pfn(OMAP1_IO_PHYS),
                .length         = OMAP1_IO_SIZE,
                .type           = MT_DEVICE
-       }
-};
-
-#if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
-static struct map_desc omap7xx_io_desc[] __initdata = {
+       },
        {
                .virtual        = OMAP7XX_DSP_BASE,
                .pfn            = __phys_to_pfn(OMAP7XX_DSP_START),
@@ -50,6 +47,12 @@ static struct map_desc omap7xx_io_desc[] __initdata = {
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct map_desc omap1510_io_desc[] __initdata = {
        {
+               .virtual        = OMAP1_IO_VIRT,
+               .pfn            = __phys_to_pfn(OMAP1_IO_PHYS),
+               .length         = OMAP1_IO_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
                .virtual        = OMAP1510_DSP_BASE,
                .pfn            = __phys_to_pfn(OMAP1510_DSP_START),
                .length         = OMAP1510_DSP_SIZE,
@@ -66,6 +69,12 @@ static struct map_desc omap1510_io_desc[] __initdata = {
 #if defined(CONFIG_ARCH_OMAP16XX)
 static struct map_desc omap16xx_io_desc[] __initdata = {
        {
+               .virtual        = OMAP1_IO_VIRT,
+               .pfn            = __phys_to_pfn(OMAP1_IO_PHYS),
+               .length         = OMAP1_IO_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
                .virtual        = OMAP16XX_DSP_BASE,
                .pfn            = __phys_to_pfn(OMAP16XX_DSP_START),
                .length         = OMAP16XX_DSP_SIZE,
@@ -79,18 +88,9 @@ static struct map_desc omap16xx_io_desc[] __initdata = {
 };
 #endif
 
-/*
- * Maps common IO regions for omap1
- */
-static void __init omap1_map_common_io(void)
-{
-       iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
-}
-
 #if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
 void __init omap7xx_map_io(void)
 {
-       omap1_map_common_io();
        iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc));
 }
 #endif
@@ -98,7 +98,6 @@ void __init omap7xx_map_io(void)
 #ifdef CONFIG_ARCH_OMAP15XX
 void __init omap15xx_map_io(void)
 {
-       omap1_map_common_io();
        iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
 }
 #endif
@@ -106,7 +105,6 @@ void __init omap15xx_map_io(void)
 #if defined(CONFIG_ARCH_OMAP16XX)
 void __init omap16xx_map_io(void)
 {
-       omap1_map_common_io();
        iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
 }
 #endif
index 05c25c4..b1632cb 100644 (file)
@@ -89,7 +89,6 @@ static struct omap_mcbsp_ops omap1_mcbsp_ops = {
 #define OMAP1610_MCBSP2_BASE   0xfffb1000
 #define OMAP1610_MCBSP3_BASE   0xe1017000
 
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
 struct resource omap7xx_mcbsp_res[][6] = {
        {
                {
@@ -159,14 +158,7 @@ static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
 };
 #define OMAP7XX_MCBSP_RES_SZ           ARRAY_SIZE(omap7xx_mcbsp_res[1])
 #define OMAP7XX_MCBSP_COUNT            ARRAY_SIZE(omap7xx_mcbsp_res)
-#else
-#define omap7xx_mcbsp_res_0            NULL
-#define omap7xx_mcbsp_pdata            NULL
-#define OMAP7XX_MCBSP_RES_SZ           0
-#define OMAP7XX_MCBSP_COUNT            0
-#endif
 
-#ifdef CONFIG_ARCH_OMAP15XX
 struct resource omap15xx_mcbsp_res[][6] = {
        {
                {
@@ -266,14 +258,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
 };
 #define OMAP15XX_MCBSP_RES_SZ          ARRAY_SIZE(omap15xx_mcbsp_res[1])
 #define OMAP15XX_MCBSP_COUNT           ARRAY_SIZE(omap15xx_mcbsp_res)
-#else
-#define omap15xx_mcbsp_res_0           NULL
-#define omap15xx_mcbsp_pdata           NULL
-#define OMAP15XX_MCBSP_RES_SZ          0
-#define OMAP15XX_MCBSP_COUNT           0
-#endif
 
-#ifdef CONFIG_ARCH_OMAP16XX
 struct resource omap16xx_mcbsp_res[][6] = {
        {
                {
@@ -373,12 +358,6 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
 };
 #define OMAP16XX_MCBSP_RES_SZ          ARRAY_SIZE(omap16xx_mcbsp_res[1])
 #define OMAP16XX_MCBSP_COUNT           ARRAY_SIZE(omap16xx_mcbsp_res)
-#else
-#define omap16xx_mcbsp_res_0           NULL
-#define omap16xx_mcbsp_pdata           NULL
-#define OMAP16XX_MCBSP_RES_SZ          0
-#define OMAP16XX_MCBSP_COUNT           0
-#endif
 
 static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
                        struct omap_mcbsp_platform_data *config, int size)
index d916570..0d1f092 100644 (file)
 #define OMAP7XX_IDLECT3                0xfffece24
 #define OMAP7XX_IDLE_LOOP_REQUEST      0x0C00
 
-#if     !defined(CONFIG_ARCH_OMAP730) && \
-       !defined(CONFIG_ARCH_OMAP850) && \
-       !defined(CONFIG_ARCH_OMAP15XX) && \
-       !defined(CONFIG_ARCH_OMAP16XX)
-#warning "Power management for this processor not implemented yet"
-#endif
-
 #ifndef __ASSEMBLER__
 
 #include <linux/clk.h>
index b90d98b..03e25af 100644 (file)
@@ -45,6 +45,8 @@ config MACH_PXA27X_DT
 config MACH_PXA3XX_DT
        bool "Support PXA3xx platforms from device tree"
        select CPU_PXA300
+       select CPU_PXA310
+       select CPU_PXA320
        select PINCTRL
        select POWER_SUPPLY
        select PXA3xx
index e3486f6..a1f0c38 100644 (file)
 };
 
 &usb {
-       phys = <&usb2_phy1>;
-       phy-names = "usb2-phy1";
-};
-
-&usb2_phy0 {
-       status = "disabled";
+       phys = <&usb2_phy0>, <&usb2_phy1>;
+       phy-names = "usb2-phy0", "usb2-phy1";
 };
index 5a8d85a..bbdf989 100644 (file)
 &i2c0 {
        status = "okay";
 
-       pca9547@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index 9b726c2..dda27ed 100644 (file)
@@ -89,7 +89,7 @@
 &i2c0 {
        status = "okay";
 
-       pca9547@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index b2fcbba..3b0ed93 100644 (file)
@@ -88,7 +88,7 @@
 &i2c0 {
        status = "okay";
 
-       pca9547@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index 41d8b15..aa52ff7 100644 (file)
@@ -53,7 +53,7 @@
 &i2c0 {
        status = "okay";
 
-       i2c-switch@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index 1bfbce6..ee8e932 100644 (file)
 &i2c0 {
        status = "okay";
 
-       i2c-switch@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index ef6c896..d4867d6 100644 (file)
 &i2c3 {
        status = "okay";
 
-       i2c-switch@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9540";
                #address-cells = <1>;
                #size-cells = <0>;
index f598669..52c5a43 100644 (file)
 
 &i2c0 {
        status = "okay";
-       pca9547@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index 3d9647b..537cecb 100644 (file)
@@ -44,7 +44,7 @@
 
 &i2c0 {
        status = "okay";
-       pca9547@75 {
+       i2c-mux@75 {
                compatible = "nxp,pca9547";
                reg = <0x75>;
                #address-cells = <1>;
index afb4552..d32a52a 100644 (file)
@@ -54,7 +54,7 @@
 &i2c0 {
        status = "okay";
 
-       i2c-switch@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                #address-cells = <1>;
                #size-cells = <0>;
index 03266bd..169f047 100644 (file)
 &ecspi2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_espi2>;
-       cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+       cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
        status = "okay";
 
        eeprom@0 {
                        MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK            0x82
                        MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI            0x82
                        MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO            0x82
-                       MX8MM_IOMUXC_ECSPI1_SS0_GPIO5_IO9               0x41
+                       MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13              0x41
                >;
        };
 
index 24f61db..752f409 100644 (file)
                compatible = "rohm,bd71847";
                reg = <0x4b>;
                #clock-cells = <0>;
-               clocks = <&clk_xtal32k 0>;
+               clocks = <&clk_xtal32k>;
                clock-output-names = "clk-32k-out";
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_pmic>;
index 74c0989..6357078 100644 (file)
        pinctrl-0 = <&pinctrl_i2c3>;
        status = "okay";
 
-       i2cmux@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9540";
                reg = <0x70>;
                #address-cells = <1>;
index 750a1f0..6433c20 100644 (file)
 &usbotg2 {
        dr_mode = "host";
        vbus-supply = <&reg_usb2_vbus>;
+       over-current-active-low;
        status = "okay";
 };
 
index c2a5c2f..7c3f5c5 100644 (file)
@@ -9,6 +9,7 @@
                simple-audio-card,bitclock-master = <&dailink_master>;
                simple-audio-card,format = "i2s";
                simple-audio-card,frame-master = <&dailink_master>;
+               simple-audio-card,mclk-fs = <256>;
                simple-audio-card,name = "imx8mm-wm8904";
                simple-audio-card,routing =
                        "Headphone Jack", "HPOUTL",
index 73cc3fa..b2bcd22 100644 (file)
@@ -11,6 +11,7 @@
                simple-audio-card,bitclock-master = <&dailink_master>;
                simple-audio-card,format = "i2s";
                simple-audio-card,frame-master = <&dailink_master>;
+               simple-audio-card,mclk-fs = <256>;
                simple-audio-card,name = "imx8mm-nau8822";
                simple-audio-card,routing =
                        "Headphones", "LHP",
index d4c7ca1..f2d9343 100644 (file)
@@ -36,8 +36,8 @@
 
        pcie0_refclk: pcie0-refclk {
                compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <100000000>;
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
        };
 
        reg_can1_stby: regulator-can1-stby {
index 79b290a..ecc4bce 100644 (file)
@@ -99,7 +99,6 @@
 
                regulators {
                        buck1: BUCK1 {
-                               regulator-compatible = "BUCK1";
                                regulator-min-microvolt = <600000>;
                                regulator-max-microvolt = <2187500>;
                                regulator-boot-on;
                        };
 
                        buck2: BUCK2 {
-                               regulator-compatible = "BUCK2";
                                regulator-min-microvolt = <600000>;
                                regulator-max-microvolt = <2187500>;
                                regulator-boot-on;
                        };
 
                        buck4: BUCK4 {
-                               regulator-compatible = "BUCK4";
                                regulator-min-microvolt = <600000>;
                                regulator-max-microvolt = <3400000>;
                                regulator-boot-on;
                        };
 
                        buck5: BUCK5 {
-                               regulator-compatible = "BUCK5";
                                regulator-min-microvolt = <600000>;
                                regulator-max-microvolt = <3400000>;
                                regulator-boot-on;
                        };
 
                        buck6: BUCK6 {
-                               regulator-compatible = "BUCK6";
                                regulator-min-microvolt = <600000>;
                                regulator-max-microvolt = <3400000>;
                                regulator-boot-on;
                        };
 
                        ldo1: LDO1 {
-                               regulator-compatible = "LDO1";
                                regulator-min-microvolt = <1600000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
                        };
 
                        ldo2: LDO2 {
-                               regulator-compatible = "LDO2";
                                regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <1150000>;
                                regulator-boot-on;
                        };
 
                        ldo3: LDO3 {
-                               regulator-compatible = "LDO3";
                                regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
                        };
 
                        ldo4: LDO4 {
-                               regulator-compatible = "LDO4";
                                regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
                        ldo5: LDO5 {
-                               regulator-compatible = "LDO5";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
index 7a6e622..03034b4 100644 (file)
                                compatible = "fsl,imx8mp-gpc";
                                reg = <0x303a0000 0x1000>;
                                interrupt-parent = <&gic>;
+                               interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
                                interrupt-controller;
                                #interrupt-cells = <3>;
 
                                                reg = <IMX8MP_POWER_DOMAIN_MIPI_PHY2>;
                                        };
 
-                                       pgc_hsiomix: power-domains@17 {
+                                       pgc_hsiomix: power-domain@17 {
                                                #power-domain-cells = <0>;
                                                reg = <IMX8MP_POWER_DOMAIN_HSIOMIX>;
                                                clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
                        reg = <0x32f10100 0x8>,
                              <0x381f0000 0x20>;
                        clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
-                                <&clk IMX8MP_CLK_USB_ROOT>;
+                                <&clk IMX8MP_CLK_USB_SUSP>;
                        clock-names = "hsio", "suspend";
                        interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
                        power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>;
                        usb_dwc3_0: usb@38100000 {
                                compatible = "snps,dwc3";
                                reg = <0x38100000 0x10000>;
-                               clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
+                               clocks = <&clk IMX8MP_CLK_USB_ROOT>,
                                         <&clk IMX8MP_CLK_USB_CORE_REF>,
-                                        <&clk IMX8MP_CLK_USB_ROOT>;
+                                        <&clk IMX8MP_CLK_USB_SUSP>;
                                clock-names = "bus_early", "ref", "suspend";
                                interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
                                phys = <&usb3_phy0>, <&usb3_phy0>;
                        reg = <0x32f10108 0x8>,
                              <0x382f0000 0x20>;
                        clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
-                                <&clk IMX8MP_CLK_USB_ROOT>;
+                                <&clk IMX8MP_CLK_USB_SUSP>;
                        clock-names = "hsio", "suspend";
                        interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
                        power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>;
                        usb_dwc3_1: usb@38200000 {
                                compatible = "snps,dwc3";
                                reg = <0x38200000 0x10000>;
-                               clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
+                               clocks = <&clk IMX8MP_CLK_USB_ROOT>,
                                         <&clk IMX8MP_CLK_USB_CORE_REF>,
-                                        <&clk IMX8MP_CLK_USB_ROOT>;
+                                        <&clk IMX8MP_CLK_USB_SUSP>;
                                clock-names = "bus_early", "ref", "suspend";
                                interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
                                phys = <&usb3_phy1>, <&usb3_phy1>;
index 9dda2a1..8614c18 100644 (file)
        pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
 
-       i2cmux@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9546";
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_i2c1_pca9546>;
        pinctrl-0 = <&pinctrl_i2c4>;
        status = "okay";
 
-       pca9546: i2cmux@70 {
+       pca9546: i2c-mux@70 {
                compatible = "nxp,pca9546";
                reg = <0x70>;
                #address-cells = <1>;
index 5d5aa65..6e61827 100644 (file)
        bus-width = <4>;
        non-removable;
        no-sd;
-       no-emmc;
+       no-mmc;
        status = "okay";
 
        brcmf: wifi@1 {
        cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
        bus-width = <4>;
        no-sdio;
-       no-emmc;
+       no-mmc;
        disable-wp;
        status = "okay";
 };
index 07d8dd8..afa8833 100644 (file)
@@ -61,7 +61,7 @@
        pinctrl-0 = <&pinctrl_lpi2c1 &pinctrl_ioexp_rst>;
        status = "okay";
 
-       i2c-switch@71 {
+       i2c-mux@71 {
                compatible = "nxp,pca9646", "nxp,pca9546";
                #address-cells = <1>;
                #size-cells = <0>;
index 69786c3..27f9a9f 100644 (file)
@@ -74,7 +74,7 @@
 
        pinctrl_usdhc1: usdhc1grp {
                fsl,pins = <
-                       MX93_PAD_SD1_CLK__USDHC1_CLK            0x17fe
+                       MX93_PAD_SD1_CLK__USDHC1_CLK            0x15fe
                        MX93_PAD_SD1_CMD__USDHC1_CMD            0x13fe
                        MX93_PAD_SD1_DATA0__USDHC1_DATA0        0x13fe
                        MX93_PAD_SD1_DATA1__USDHC1_DATA1        0x13fe
@@ -84,7 +84,7 @@
                        MX93_PAD_SD1_DATA5__USDHC1_DATA5        0x13fe
                        MX93_PAD_SD1_DATA6__USDHC1_DATA6        0x13fe
                        MX93_PAD_SD1_DATA7__USDHC1_DATA7        0x13fe
-                       MX93_PAD_SD1_STROBE__USDHC1_STROBE      0x17fe
+                       MX93_PAD_SD1_STROBE__USDHC1_STROBE      0x15fe
                >;
        };
 
 
        pinctrl_usdhc2: usdhc2grp {
                fsl,pins = <
-                       MX93_PAD_SD2_CLK__USDHC2_CLK            0x17fe
+                       MX93_PAD_SD2_CLK__USDHC2_CLK            0x15fe
                        MX93_PAD_SD2_CMD__USDHC2_CMD            0x13fe
                        MX93_PAD_SD2_DATA0__USDHC2_DATA0        0x13fe
                        MX93_PAD_SD2_DATA1__USDHC2_DATA1        0x13fe
index 7308f7b..8bce640 100644 (file)
@@ -98,7 +98,7 @@
 
                        uart1: serial@12100 {
                                compatible = "snps,dw-apb-uart";
-                               reg = <0x11000 0x100>;
+                               reg = <0x12100 0x100>;
                                reg-shift = <2>;
                                interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
                                reg-io-width = <1>;
index 87c90e9..79de9cc 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (c) 2015, LGE Inc. All rights reserved.
  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
  * Copyright (c) 2021, Petr Vorel <petr.vorel@gmail.com>
+ * Copyright (c) 2022, Dominik Kobinski <dominikkobinski314@gmail.com>
  */
 
 /dts-v1/;
                        reg = <0 0x03400000 0 0x1200000>;
                        no-map;
                };
+
+               removed_region: reserved@5000000 {
+                       reg = <0 0x05000000 0 0x2200000>;
+                       no-map;
+               };
        };
 };
 
index b242c27..fcca1ba 100644 (file)
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/gpio-keys.h>
 
+/delete-node/ &adsp_mem;
+/delete-node/ &audio_mem;
+/delete-node/ &mpss_mem;
+/delete-node/ &peripheral_region;
+/delete-node/ &rmtfs_mem;
+
 / {
        model = "Xiaomi Mi 4C";
        compatible = "xiaomi,libra", "qcom,msm8992";
                #size-cells = <2>;
                ranges;
 
-               /* This is for getting crash logs using Android downstream kernels */
-               ramoops@dfc00000 {
-                       compatible = "ramoops";
-                       reg = <0x0 0xdfc00000 0x0 0x40000>;
-                       console-size = <0x10000>;
-                       record-size = <0x10000>;
-                       ftrace-size = <0x10000>;
-                       pmsg-size = <0x20000>;
+               memory_hole: hole@6400000 {
+                       reg = <0 0x06400000 0 0x600000>;
+                       no-map;
+               };
+
+               memory_hole2: hole2@6c00000 {
+                       reg = <0 0x06c00000 0 0x2400000>;
+                       no-map;
+               };
+
+               mpss_mem: mpss@9000000 {
+                       reg = <0 0x09000000 0 0x5a00000>;
+                       no-map;
+               };
+
+               tzapp: tzapp@ea00000 {
+                       reg = <0 0x0ea00000 0 0x1900000>;
+                       no-map;
+               };
+
+               mdm_rfsa_mem: mdm-rfsa@ca0b0000 {
+                       reg = <0 0xca0b0000 0 0x10000>;
+                       no-map;
+               };
+
+               rmtfs_mem: rmtfs@ca100000 {
+                       compatible = "qcom,rmtfs-mem";
+                       reg = <0 0xca100000 0 0x180000>;
+                       no-map;
+
+                       qcom,client-id = <1>;
                };
 
-               modem_region: modem_region@9000000 {
-                       reg = <0x0 0x9000000 0x0 0x5a00000>;
+               audio_mem: audio@cb400000 {
+                       reg = <0 0xcb000000 0 0x400000>;
+                       no-mem;
+               };
+
+               qseecom_mem: qseecom@cb400000 {
+                       reg = <0 0xcb400000 0 0x1c00000>;
+                       no-mem;
+               };
+
+               adsp_rfsa_mem: adsp-rfsa@cd000000 {
+                       reg = <0 0xcd000000 0 0x10000>;
                        no-map;
                };
 
-               tzapp: modem_region@ea00000 {
-                       reg = <0x0 0xea00000 0x0 0x1900000>;
+               sensor_rfsa_mem: sensor-rfsa@cd010000 {
+                       reg = <0 0xcd010000 0 0x10000>;
                        no-map;
                };
+
+               ramoops@dfc00000 {
+                       compatible = "ramoops";
+                       reg = <0 0xdfc00000 0 0x40000>;
+                       console-size = <0x10000>;
+                       record-size = <0x10000>;
+                       ftrace-size = <0x10000>;
+                       pmsg-size = <0x20000>;
+               };
        };
 };
 
        status = "okay";
 };
 
-&peripheral_region {
-       reg = <0x0 0x7400000 0x0 0x1c00000>;
-       no-map;
-};
-
 &pm8994_spmi_regulators {
        VDD_APC0: s8 {
                regulator-min-microvolt = <680000>;
index 10adb49..02fc379 100644 (file)
        compatible = "qcom,rpmcc-msm8992", "qcom,rpmcc";
 };
 
-&tcsr_mutex {
-       compatible = "qcom,sfpb-mutex";
-};
-
 &timer {
        interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
                             <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
index 85abff0..7b0f621 100644 (file)
@@ -9,9 +9,6 @@
 
 #include "msm8994.dtsi"
 
-/* Angler's firmware does not report where the memory is allocated */
-/delete-node/ &cont_splash_mem;
-
 / {
        model = "Huawei Nexus 6P";
        compatible = "huawei,angler", "qcom,msm8994";
        chosen {
                stdout-path = "serial0:115200n8";
        };
+
+       reserved-memory {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               tzapp_mem: tzapp@4800000 {
+                       reg = <0 0x04800000 0 0x1900000>;
+                       no-map;
+               };
+
+               removed_region: reserved@6300000 {
+                       reg = <0 0x06300000 0 0xD00000>;
+                       no-map;
+               };
+       };
 };
 
 &blsp1_uart2 {
index 109c9d2..71cf81a 100644 (file)
@@ -10,6 +10,7 @@
 #include <dt-bindings/interconnect/qcom,sc8280xp.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/mailbox/qcom-ipcc.h>
+#include <dt-bindings/phy/phy-qcom-qmp.h>
 #include <dt-bindings/power/qcom-rpmpd.h>
 #include <dt-bindings/soc/qcom,rpmh-rsc.h>
 #include <dt-bindings/thermal/thermal.h>
                                 <0>,
                                 <0>,
                                 <0>,
-                                <&usb_0_ssphy>,
+                                <&usb_0_qmpphy QMP_USB43DP_USB3_PIPE_CLK>,
                                 <0>,
                                 <0>,
                                 <0>,
                                 <0>,
                                 <0>,
                                 <0>,
-                                <&usb_1_ssphy>,
+                                <&usb_1_qmpphy QMP_USB43DP_USB3_PIPE_CLK>,
                                 <0>,
                                 <0>,
                                 <0>,
                        };
                };
 
-               usb_0_qmpphy: phy-wrapper@88ec000 {
+               usb_0_qmpphy: phy@88eb000 {
                        compatible = "qcom,sc8280xp-qmp-usb43dp-phy";
-                       reg = <0 0x088ec000 0 0x1e4>,
-                             <0 0x088eb000 0 0x40>,
-                             <0 0x088ed000 0 0x1c8>;
-                       #address-cells = <2>;
-                       #size-cells = <2>;
-                       ranges;
+                       reg = <0 0x088eb000 0 0x4000>;
 
                        clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
-                                <&rpmhcc RPMH_CXO_CLK>,
                                 <&gcc GCC_USB4_EUD_CLKREF_CLK>,
-                                <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
-                       clock-names = "aux", "ref_clk_src", "ref", "com_aux";
+                                <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+                                <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+                       clock-names = "aux", "ref", "com_aux", "usb3_pipe";
+
+                       power-domains = <&gcc USB30_PRIM_GDSC>;
 
                        resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
-                                <&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
+                                <&gcc GCC_USB4_DP_PHY_PRIM_BCR>;
                        reset-names = "phy", "common";
 
-                       power-domains = <&gcc USB30_PRIM_GDSC>;
+                       #clock-cells = <1>;
+                       #phy-cells = <1>;
 
                        status = "disabled";
-
-                       usb_0_ssphy: usb3-phy@88eb400 {
-                               reg = <0 0x088eb400 0 0x100>,
-                                     <0 0x088eb600 0 0x3ec>,
-                                     <0 0x088ec400 0 0x364>,
-                                     <0 0x088eba00 0 0x100>,
-                                     <0 0x088ebc00 0 0x3ec>,
-                                     <0 0x088ec200 0 0x18>;
-                               #phy-cells = <0>;
-                               #clock-cells = <0>;
-                               clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
-                               clock-names = "pipe0";
-                               clock-output-names = "usb0_phy_pipe_clk_src";
-                       };
                };
 
                usb_1_hsphy: phy@8902000 {
                        status = "disabled";
                };
 
-               usb_1_qmpphy: phy-wrapper@8904000 {
+               usb_1_qmpphy: phy@8903000 {
                        compatible = "qcom,sc8280xp-qmp-usb43dp-phy";
-                       reg = <0 0x08904000 0 0x1e4>,
-                             <0 0x08903000 0 0x40>,
-                             <0 0x08905000 0 0x1c8>;
-                       #address-cells = <2>;
-                       #size-cells = <2>;
-                       ranges;
+                       reg = <0 0x08903000 0 0x4000>;
 
                        clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>,
-                                <&rpmhcc RPMH_CXO_CLK>,
                                 <&gcc GCC_USB4_CLKREF_CLK>,
-                                <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>;
-                       clock-names = "aux", "ref_clk_src", "ref", "com_aux";
+                                <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>,
+                                <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
+                       clock-names = "aux", "ref", "com_aux", "usb3_pipe";
+
+                       power-domains = <&gcc USB30_SEC_GDSC>;
 
                        resets = <&gcc GCC_USB3_PHY_SEC_BCR>,
                                 <&gcc GCC_USB4_1_DP_PHY_PRIM_BCR>;
                        reset-names = "phy", "common";
 
-                       power-domains = <&gcc USB30_SEC_GDSC>;
+                       #clock-cells = <1>;
+                       #phy-cells = <1>;
 
                        status = "disabled";
-
-                       usb_1_ssphy: usb3-phy@8903400 {
-                               reg = <0 0x08903400 0 0x100>,
-                                     <0 0x08903600 0 0x3ec>,
-                                     <0 0x08904400 0 0x364>,
-                                     <0 0x08903a00 0 0x100>,
-                                     <0 0x08903c00 0 0x3ec>,
-                                     <0 0x08904200 0 0x18>;
-                               #phy-cells = <0>;
-                               #clock-cells = <0>;
-                               clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
-                               clock-names = "pipe0";
-                               clock-output-names = "usb1_phy_pipe_clk_src";
-                       };
                };
 
                pmu@9091000 {
                                reg = <0 0x0a600000 0 0xcd00>;
                                interrupts = <GIC_SPI 803 IRQ_TYPE_LEVEL_HIGH>;
                                iommus = <&apps_smmu 0x820 0x0>;
-                               phys = <&usb_0_hsphy>, <&usb_0_ssphy>;
+                               phys = <&usb_0_hsphy>, <&usb_0_qmpphy QMP_USB43DP_USB3_PHY>;
                                phy-names = "usb2-phy", "usb3-phy";
                        };
                };
                                reg = <0 0x0a800000 0 0xcd00>;
                                interrupts = <GIC_SPI 810 IRQ_TYPE_LEVEL_HIGH>;
                                iommus = <&apps_smmu 0x860 0x0>;
-                               phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
+                               phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
                                phy-names = "usb2-phy", "usb3-phy";
                        };
                };
index dab5579..9270328 100644 (file)
                                exit-latency-us = <6562>;
                                min-residency-us = <9987>;
                                local-timer-stop;
-                               status = "disabled";
                        };
                };
        };
index 245dce2..fb3cd20 100644 (file)
                                 <&rpmhcc RPMH_CXO_CLK>;
                        clock-names = "iface", "core", "xo";
                        resets = <&gcc GCC_SDCC2_BCR>;
-                       interconnects = <&aggre2_noc MASTER_SDCC_2 0 &mc_virt SLAVE_EBI1 0>,
-                                       <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_SDCC_2 0>;
+                       interconnects = <&aggre2_noc MASTER_SDCC_2 &mc_virt SLAVE_EBI1>,
+                                       <&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_SDCC_2>;
                        interconnect-names = "sdhc-ddr","cpu-sdhc";
                        iommus = <&apps_smmu 0x4a0 0x0>;
                        power-domains = <&rpmhpd SM8350_CX>;
index 90f9d33..3418d32 100644 (file)
@@ -10,8 +10,6 @@
 #define FTRACE_REGS_PLT_IDX    1
 #define NR_FTRACE_PLTS         2
 
-#define GRAPH_FAKE_OFFSET (sizeof(struct pt_regs) - offsetof(struct pt_regs, regs[1]))
-
 #ifdef CONFIG_FUNCTION_TRACER
 
 #define MCOUNT_INSN_SIZE 4             /* sizeof mcount call */
index c00e151..7eedd83 100644 (file)
@@ -377,14 +377,6 @@ static inline bool unsigned_imm_check(unsigned long val, unsigned int bit)
        return val < (1UL << bit);
 }
 
-static inline unsigned long sign_extend(unsigned long val, unsigned int idx)
-{
-       if (!is_imm_negative(val, idx + 1))
-               return ((1UL << idx) - 1) & val;
-       else
-               return ~((1UL << idx) - 1) | val;
-}
-
 #define DEF_EMIT_REG0I26_FORMAT(NAME, OP)                              \
 static inline void emit_##NAME(union loongarch_instruction *insn,      \
                               int offset)                              \
@@ -401,6 +393,7 @@ static inline void emit_##NAME(union loongarch_instruction *insn,   \
 }
 
 DEF_EMIT_REG0I26_FORMAT(b, b_op)
+DEF_EMIT_REG0I26_FORMAT(bl, bl_op)
 
 #define DEF_EMIT_REG1I20_FORMAT(NAME, OP)                              \
 static inline void emit_##NAME(union loongarch_instruction *insn,      \
index f2b52b9..b9dce87 100644 (file)
@@ -8,7 +8,9 @@
 #define _ASM_UNWIND_H
 
 #include <linux/sched.h>
+#include <linux/ftrace.h>
 
+#include <asm/ptrace.h>
 #include <asm/stacktrace.h>
 
 enum unwinder_type {
@@ -20,11 +22,13 @@ struct unwind_state {
        char type; /* UNWINDER_XXX */
        struct stack_info stack_info;
        struct task_struct *task;
-       bool first, error, is_ftrace;
+       bool first, error, reset;
        int graph_idx;
        unsigned long sp, pc, ra;
 };
 
+bool default_next_frame(struct unwind_state *state);
+
 void unwind_start(struct unwind_state *state,
                  struct task_struct *task, struct pt_regs *regs);
 bool unwind_next_frame(struct unwind_state *state);
@@ -40,4 +44,39 @@ static inline bool unwind_error(struct unwind_state *state)
        return state->error;
 }
 
+#define GRAPH_FAKE_OFFSET (sizeof(struct pt_regs) - offsetof(struct pt_regs, regs[1]))
+
+static inline unsigned long unwind_graph_addr(struct unwind_state *state,
+                                       unsigned long pc, unsigned long cfa)
+{
+       return ftrace_graph_ret_addr(state->task, &state->graph_idx,
+                                    pc, (unsigned long *)(cfa - GRAPH_FAKE_OFFSET));
+}
+
+static __always_inline void __unwind_start(struct unwind_state *state,
+                                       struct task_struct *task, struct pt_regs *regs)
+{
+       memset(state, 0, sizeof(*state));
+       if (regs) {
+               state->sp = regs->regs[3];
+               state->pc = regs->csr_era;
+               state->ra = regs->regs[1];
+       } else if (task && task != current) {
+               state->sp = thread_saved_fp(task);
+               state->pc = thread_saved_ra(task);
+               state->ra = 0;
+       } else {
+               state->sp = (unsigned long)__builtin_frame_address(0);
+               state->pc = (unsigned long)__builtin_return_address(0);
+               state->ra = 0;
+       }
+       state->task = task;
+       get_stack_info(state->sp, state->task, &state->stack_info);
+       state->pc = unwind_graph_addr(state, state->pc, state->sp);
+}
+
+static __always_inline unsigned long __unwind_get_return_address(struct unwind_state *state)
+{
+       return unwind_done(state) ? 0 : state->pc;
+}
 #endif /* _ASM_UNWIND_H */
index fcaa024..c8cfbd5 100644 (file)
@@ -8,7 +8,7 @@ extra-y         := vmlinux.lds
 obj-y          += head.o cpu-probe.o cacheinfo.o env.o setup.o entry.o genex.o \
                   traps.o irq.o idle.o process.o dma.o mem.o io.o reset.o switch.o \
                   elf.o syscall.o signal.o time.o topology.o inst.o ptrace.o vdso.o \
-                  alternative.o unaligned.o
+                  alternative.o unaligned.o unwind.o
 
 obj-$(CONFIG_ACPI)             += acpi.o
 obj-$(CONFIG_EFI)              += efi.o
index c5aebea..4ad1384 100644 (file)
@@ -74,7 +74,7 @@ static void __init_or_module recompute_jump(union loongarch_instruction *buf,
        switch (src->reg0i26_format.opcode) {
        case b_op:
        case bl_op:
-               jump_addr = cur_pc + sign_extend((si_h << 16 | si_l) << 2, 27);
+               jump_addr = cur_pc + sign_extend64((si_h << 16 | si_l) << 2, 27);
                if (in_alt_jump(jump_addr, start, end))
                        return;
                offset = jump_addr - pc;
@@ -93,7 +93,7 @@ static void __init_or_module recompute_jump(union loongarch_instruction *buf,
                fallthrough;
        case beqz_op:
        case bnez_op:
-               jump_addr = cur_pc + sign_extend((si_h << 16 | si_l) << 2, 22);
+               jump_addr = cur_pc + sign_extend64((si_h << 16 | si_l) << 2, 22);
                if (in_alt_jump(jump_addr, start, end))
                        return;
                offset = jump_addr - pc;
@@ -112,7 +112,7 @@ static void __init_or_module recompute_jump(union loongarch_instruction *buf,
        case bge_op:
        case bltu_op:
        case bgeu_op:
-               jump_addr = cur_pc + sign_extend(si << 2, 17);
+               jump_addr = cur_pc + sign_extend64(si << 2, 17);
                if (in_alt_jump(jump_addr, start, end))
                        return;
                offset = jump_addr - pc;
index 255a098..3a3fce2 100644 (file)
@@ -94,7 +94,7 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
        c->options = LOONGARCH_CPU_CPUCFG | LOONGARCH_CPU_CSR |
                     LOONGARCH_CPU_TLB | LOONGARCH_CPU_VINT | LOONGARCH_CPU_WATCH;
 
-       elf_hwcap |= HWCAP_LOONGARCH_CRC32;
+       elf_hwcap = HWCAP_LOONGARCH_CPUCFG | HWCAP_LOONGARCH_CRC32;
 
        config = read_cpucfg(LOONGARCH_CPUCFG1);
        if (config & CPUCFG1_UAL) {
index 75e5be8..7e5c293 100644 (file)
@@ -67,14 +67,17 @@ SYM_FUNC_END(except_vec_cex)
        .macro  BUILD_HANDLER exception handler prep
        .align  5
        SYM_FUNC_START(handle_\exception)
+       666:
        BACKUP_T0T1
        SAVE_ALL
        build_prep_\prep
        move    a0, sp
        la.abs  t0, do_\handler
        jirl    ra, t0, 0
+       668:
        RESTORE_ALL_AND_RET
        SYM_FUNC_END(handle_\exception)
+       SYM_DATA(unwind_hint_\exception, .word 668b - 666b)
        .endm
 
        BUILD_HANDLER ade ade badv
index 512579d..badc590 100644 (file)
@@ -58,7 +58,6 @@ u32 larch_insn_gen_nop(void)
 u32 larch_insn_gen_b(unsigned long pc, unsigned long dest)
 {
        long offset = dest - pc;
-       unsigned int immediate_l, immediate_h;
        union loongarch_instruction insn;
 
        if ((offset & 3) || offset < -SZ_128M || offset >= SZ_128M) {
@@ -66,15 +65,7 @@ u32 larch_insn_gen_b(unsigned long pc, unsigned long dest)
                return INSN_BREAK;
        }
 
-       offset >>= 2;
-
-       immediate_l = offset & 0xffff;
-       offset >>= 16;
-       immediate_h = offset & 0x3ff;
-
-       insn.reg0i26_format.opcode = b_op;
-       insn.reg0i26_format.immediate_l = immediate_l;
-       insn.reg0i26_format.immediate_h = immediate_h;
+       emit_b(&insn, offset >> 2);
 
        return insn.word;
 }
@@ -82,7 +73,6 @@ u32 larch_insn_gen_b(unsigned long pc, unsigned long dest)
 u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest)
 {
        long offset = dest - pc;
-       unsigned int immediate_l, immediate_h;
        union loongarch_instruction insn;
 
        if ((offset & 3) || offset < -SZ_128M || offset >= SZ_128M) {
@@ -90,15 +80,7 @@ u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest)
                return INSN_BREAK;
        }
 
-       offset >>= 2;
-
-       immediate_l = offset & 0xffff;
-       offset >>= 16;
-       immediate_h = offset & 0x3ff;
-
-       insn.reg0i26_format.opcode = bl_op;
-       insn.reg0i26_format.immediate_l = immediate_l;
-       insn.reg0i26_format.immediate_h = immediate_h;
+       emit_bl(&insn, offset >> 2);
 
        return insn.word;
 }
@@ -107,10 +89,7 @@ u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongar
 {
        union loongarch_instruction insn;
 
-       insn.reg3_format.opcode = or_op;
-       insn.reg3_format.rd = rd;
-       insn.reg3_format.rj = rj;
-       insn.reg3_format.rk = rk;
+       emit_or(&insn, rd, rj, rk);
 
        return insn.word;
 }
@@ -124,9 +103,7 @@ u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm)
 {
        union loongarch_instruction insn;
 
-       insn.reg1i20_format.opcode = lu12iw_op;
-       insn.reg1i20_format.rd = rd;
-       insn.reg1i20_format.immediate = imm;
+       emit_lu12iw(&insn, rd, imm);
 
        return insn.word;
 }
@@ -135,9 +112,7 @@ u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm)
 {
        union loongarch_instruction insn;
 
-       insn.reg1i20_format.opcode = lu32id_op;
-       insn.reg1i20_format.rd = rd;
-       insn.reg1i20_format.immediate = imm;
+       emit_lu32id(&insn, rd, imm);
 
        return insn.word;
 }
@@ -146,10 +121,7 @@ u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm)
 {
        union loongarch_instruction insn;
 
-       insn.reg2i12_format.opcode = lu52id_op;
-       insn.reg2i12_format.rd = rd;
-       insn.reg2i12_format.rj = rj;
-       insn.reg2i12_format.immediate = imm;
+       emit_lu52id(&insn, rd, rj, imm);
 
        return insn.word;
 }
@@ -158,10 +130,7 @@ u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned l
 {
        union loongarch_instruction insn;
 
-       insn.reg2i16_format.opcode = jirl_op;
-       insn.reg2i16_format.rd = rd;
-       insn.reg2i16_format.rj = rj;
-       insn.reg2i16_format.immediate = (dest - pc) >> 2;
+       emit_jirl(&insn, rj, rd, (dest - pc) >> 2);
 
        return insn.word;
 }
index c583b1e..edfd220 100644 (file)
@@ -191,20 +191,14 @@ out:
 
 unsigned long __get_wchan(struct task_struct *task)
 {
-       unsigned long pc;
+       unsigned long pc = 0;
        struct unwind_state state;
 
        if (!try_get_task_stack(task))
                return 0;
 
-       unwind_start(&state, task, NULL);
-       state.sp = thread_saved_fp(task);
-       get_stack_info(state.sp, state.task, &state.stack_info);
-       state.pc = thread_saved_ra(task);
-#ifdef CONFIG_UNWINDER_PROLOGUE
-       state.type = UNWINDER_PROLOGUE;
-#endif
-       for (; !unwind_done(&state); unwind_next_frame(&state)) {
+       for (unwind_start(&state, task, NULL);
+            !unwind_done(&state); unwind_next_frame(&state)) {
                pc = unwind_get_return_address(&state);
                if (!pc)
                        break;
index 7ea62fa..c38a146 100644 (file)
@@ -72,9 +72,6 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs,
        if (!task)
                task = current;
 
-       if (user_mode(regs))
-               state.type = UNWINDER_GUESS;
-
        printk("%sCall Trace:", loglvl);
        for (unwind_start(&state, task, pregs);
              !unwind_done(&state); unwind_next_frame(&state)) {
diff --git a/arch/loongarch/kernel/unwind.c b/arch/loongarch/kernel/unwind.c
new file mode 100644 (file)
index 0000000..a463d69
--- /dev/null
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
+ */
+#include <linux/kernel.h>
+#include <linux/ftrace.h>
+
+#include <asm/unwind.h>
+
+bool default_next_frame(struct unwind_state *state)
+{
+       struct stack_info *info = &state->stack_info;
+       unsigned long addr;
+
+       if (unwind_done(state))
+               return false;
+
+       do {
+               for (state->sp += sizeof(unsigned long);
+                    state->sp < info->end; state->sp += sizeof(unsigned long)) {
+                       addr = *(unsigned long *)(state->sp);
+                       state->pc = unwind_graph_addr(state, addr, state->sp + 8);
+                       if (__kernel_text_address(state->pc))
+                               return true;
+               }
+
+               state->sp = info->next_sp;
+
+       } while (!get_stack_info(state->sp, state->task, info));
+
+       return false;
+}
index e2d2e4f..98379b7 100644 (file)
@@ -2,37 +2,18 @@
 /*
  * Copyright (C) 2022 Loongson Technology Corporation Limited
  */
-#include <linux/kernel.h>
-#include <linux/ftrace.h>
-
 #include <asm/unwind.h>
 
 unsigned long unwind_get_return_address(struct unwind_state *state)
 {
-       if (unwind_done(state))
-               return 0;
-       else if (state->first)
-               return state->pc;
-
-       return *(unsigned long *)(state->sp);
+       return __unwind_get_return_address(state);
 }
 EXPORT_SYMBOL_GPL(unwind_get_return_address);
 
 void unwind_start(struct unwind_state *state, struct task_struct *task,
                    struct pt_regs *regs)
 {
-       memset(state, 0, sizeof(*state));
-
-       if (regs) {
-               state->sp = regs->regs[3];
-               state->pc = regs->csr_era;
-       }
-
-       state->task = task;
-       state->first = true;
-
-       get_stack_info(state->sp, state->task, &state->stack_info);
-
+       __unwind_start(state, task, regs);
        if (!unwind_done(state) && !__kernel_text_address(state->pc))
                unwind_next_frame(state);
 }
@@ -40,30 +21,6 @@ EXPORT_SYMBOL_GPL(unwind_start);
 
 bool unwind_next_frame(struct unwind_state *state)
 {
-       struct stack_info *info = &state->stack_info;
-       unsigned long addr;
-
-       if (unwind_done(state))
-               return false;
-
-       if (state->first)
-               state->first = false;
-
-       do {
-               for (state->sp += sizeof(unsigned long);
-                    state->sp < info->end;
-                    state->sp += sizeof(unsigned long)) {
-                       addr = *(unsigned long *)(state->sp);
-                       state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
-                                       addr, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
-                       if (__kernel_text_address(addr))
-                               return true;
-               }
-
-               state->sp = info->next_sp;
-
-       } while (!get_stack_info(state->sp, state->task, info));
-
-       return false;
+       return default_next_frame(state);
 }
 EXPORT_SYMBOL_GPL(unwind_next_frame);
index 0f8d145..9095fde 100644 (file)
 /*
  * Copyright (C) 2022 Loongson Technology Corporation Limited
  */
+#include <linux/cpumask.h>
 #include <linux/ftrace.h>
 #include <linux/kallsyms.h>
 
 #include <asm/inst.h>
+#include <asm/loongson.h>
 #include <asm/ptrace.h>
+#include <asm/setup.h>
 #include <asm/unwind.h>
 
-static inline void unwind_state_fixup(struct unwind_state *state)
-{
-#ifdef CONFIG_DYNAMIC_FTRACE
-       static unsigned long ftrace = (unsigned long)ftrace_call + 4;
-
-       if (state->pc == ftrace)
-               state->is_ftrace = true;
+extern const int unwind_hint_ade;
+extern const int unwind_hint_ale;
+extern const int unwind_hint_bp;
+extern const int unwind_hint_fpe;
+extern const int unwind_hint_fpu;
+extern const int unwind_hint_lsx;
+extern const int unwind_hint_lasx;
+extern const int unwind_hint_lbt;
+extern const int unwind_hint_ri;
+extern const int unwind_hint_watch;
+extern unsigned long eentry;
+#ifdef CONFIG_NUMA
+extern unsigned long pcpu_handlers[NR_CPUS];
 #endif
-}
 
-unsigned long unwind_get_return_address(struct unwind_state *state)
+static inline bool scan_handlers(unsigned long entry_offset)
 {
+       int idx, offset;
 
-       if (unwind_done(state))
-               return 0;
-       else if (state->type)
-               return state->pc;
-       else if (state->first)
-               return state->pc;
-
-       return *(unsigned long *)(state->sp);
+       if (entry_offset >= EXCCODE_INT_START * VECSIZE)
+               return false;
 
+       idx = entry_offset / VECSIZE;
+       offset = entry_offset % VECSIZE;
+       switch (idx) {
+       case EXCCODE_ADE:
+               return offset == unwind_hint_ade;
+       case EXCCODE_ALE:
+               return offset == unwind_hint_ale;
+       case EXCCODE_BP:
+               return offset == unwind_hint_bp;
+       case EXCCODE_FPE:
+               return offset == unwind_hint_fpe;
+       case EXCCODE_FPDIS:
+               return offset == unwind_hint_fpu;
+       case EXCCODE_LSXDIS:
+               return offset == unwind_hint_lsx;
+       case EXCCODE_LASXDIS:
+               return offset == unwind_hint_lasx;
+       case EXCCODE_BTDIS:
+               return offset == unwind_hint_lbt;
+       case EXCCODE_INE:
+               return offset == unwind_hint_ri;
+       case EXCCODE_WATCH:
+               return offset == unwind_hint_watch;
+       default:
+               return false;
+       }
 }
-EXPORT_SYMBOL_GPL(unwind_get_return_address);
 
-static bool unwind_by_guess(struct unwind_state *state)
+static inline bool fix_exception(unsigned long pc)
 {
-       struct stack_info *info = &state->stack_info;
-       unsigned long addr;
-
-       for (state->sp += sizeof(unsigned long);
-            state->sp < info->end;
-            state->sp += sizeof(unsigned long)) {
-               addr = *(unsigned long *)(state->sp);
-               state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
-                               addr, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
-               if (__kernel_text_address(addr))
+#ifdef CONFIG_NUMA
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               if (!pcpu_handlers[cpu])
+                       continue;
+               if (scan_handlers(pc - pcpu_handlers[cpu]))
                        return true;
        }
+#endif
+       return scan_handlers(pc - eentry);
+}
 
+/*
+ * As we meet ftrace_regs_entry, reset first flag like first doing
+ * tracing. Prologue analysis will stop soon because PC is at entry.
+ */
+static inline bool fix_ftrace(unsigned long pc)
+{
+#ifdef CONFIG_DYNAMIC_FTRACE
+       return pc == (unsigned long)ftrace_call + LOONGARCH_INSN_SIZE;
+#else
        return false;
+#endif
 }
 
+static inline bool unwind_state_fixup(struct unwind_state *state)
+{
+       if (!fix_exception(state->pc) && !fix_ftrace(state->pc))
+               return false;
+
+       state->reset = true;
+       return true;
+}
+
+/*
+ * LoongArch function prologue is like follows,
+ *     [instructions not use stack var]
+ *     addi.d sp, sp, -imm
+ *     st.d   xx, sp, offset <- save callee saved regs and
+ *     st.d   yy, sp, offset    save ra if function is nest.
+ *     [others instructions]
+ */
 static bool unwind_by_prologue(struct unwind_state *state)
 {
        long frame_ra = -1;
        unsigned long frame_size = 0;
-       unsigned long size, offset, pc = state->pc;
+       unsigned long size, offset, pc;
        struct pt_regs *regs;
        struct stack_info *info = &state->stack_info;
        union loongarch_instruction *ip, *ip_end;
@@ -64,20 +119,21 @@ static bool unwind_by_prologue(struct unwind_state *state)
        if (state->sp >= info->end || state->sp < info->begin)
                return false;
 
-       if (state->is_ftrace) {
-               /*
-                * As we meet ftrace_regs_entry, reset first flag like first doing
-                * tracing. Prologue analysis will stop soon because PC is at entry.
-                */
+       if (state->reset) {
                regs = (struct pt_regs *)state->sp;
                state->first = true;
-               state->is_ftrace = false;
+               state->reset = false;
                state->pc = regs->csr_era;
                state->ra = regs->regs[1];
                state->sp = regs->regs[3];
                return true;
        }
 
+       /*
+        * When first is not set, the PC is a return address in the previous frame.
+        * We need to adjust its value in case overflow to the next symbol.
+        */
+       pc = state->pc - (state->first ? 0 : LOONGARCH_INSN_SIZE);
        if (!kallsyms_lookup_size_offset(pc, &size, &offset))
                return false;
 
@@ -93,6 +149,10 @@ static bool unwind_by_prologue(struct unwind_state *state)
                ip++;
        }
 
+       /*
+        * Can't find stack alloc action, PC may be in a leaf function. Only the
+        * first being true is reasonable, otherwise indicate analysis is broken.
+        */
        if (!frame_size) {
                if (state->first)
                        goto first;
@@ -110,6 +170,7 @@ static bool unwind_by_prologue(struct unwind_state *state)
                ip++;
        }
 
+       /* Can't find save $ra action, PC may be in a leaf function, too. */
        if (frame_ra < 0) {
                if (state->first) {
                        state->sp = state->sp + frame_size;
@@ -118,88 +179,47 @@ static bool unwind_by_prologue(struct unwind_state *state)
                return false;
        }
 
-       if (state->first)
-               state->first = false;
-
        state->pc = *(unsigned long *)(state->sp + frame_ra);
        state->sp = state->sp + frame_size;
        goto out;
 
 first:
-       state->first = false;
-       if (state->pc == state->ra)
-               return false;
-
        state->pc = state->ra;
 
 out:
-       unwind_state_fixup(state);
-       return !!__kernel_text_address(state->pc);
-}
-
-void unwind_start(struct unwind_state *state, struct task_struct *task,
-                   struct pt_regs *regs)
-{
-       memset(state, 0, sizeof(*state));
-
-       if (regs &&  __kernel_text_address(regs->csr_era)) {
-               state->pc = regs->csr_era;
-               state->sp = regs->regs[3];
-               state->ra = regs->regs[1];
-               state->type = UNWINDER_PROLOGUE;
-       }
-
-       state->task = task;
-       state->first = true;
-
-       get_stack_info(state->sp, state->task, &state->stack_info);
-
-       if (!unwind_done(state) && !__kernel_text_address(state->pc))
-               unwind_next_frame(state);
+       state->first = false;
+       return unwind_state_fixup(state) || __kernel_text_address(state->pc);
 }
-EXPORT_SYMBOL_GPL(unwind_start);
 
-bool unwind_next_frame(struct unwind_state *state)
+static bool next_frame(struct unwind_state *state)
 {
-       struct stack_info *info = &state->stack_info;
-       struct pt_regs *regs;
        unsigned long pc;
+       struct pt_regs *regs;
+       struct stack_info *info = &state->stack_info;
 
        if (unwind_done(state))
                return false;
 
        do {
-               switch (state->type) {
-               case UNWINDER_GUESS:
-                       state->first = false;
-                       if (unwind_by_guess(state))
-                               return true;
-                       break;
+               if (unwind_by_prologue(state)) {
+                       state->pc = unwind_graph_addr(state, state->pc, state->sp);
+                       return true;
+               }
+
+               if (info->type == STACK_TYPE_IRQ && info->end == state->sp) {
+                       regs = (struct pt_regs *)info->next_sp;
+                       pc = regs->csr_era;
+
+                       if (user_mode(regs) || !__kernel_text_address(pc))
+                               return false;
+
+                       state->first = true;
+                       state->pc = pc;
+                       state->ra = regs->regs[1];
+                       state->sp = regs->regs[3];
+                       get_stack_info(state->sp, state->task, info);
 
-               case UNWINDER_PROLOGUE:
-                       if (unwind_by_prologue(state)) {
-                               state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
-                                               state->pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
-                               return true;
-                       }
-
-                       if (info->type == STACK_TYPE_IRQ &&
-                               info->end == state->sp) {
-                               regs = (struct pt_regs *)info->next_sp;
-                               pc = regs->csr_era;
-
-                               if (user_mode(regs) || !__kernel_text_address(pc))
-                                       return false;
-
-                               state->first = true;
-                               state->ra = regs->regs[1];
-                               state->sp = regs->regs[3];
-                               state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
-                                               pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
-                               get_stack_info(state->sp, state->task, info);
-
-                               return true;
-                       }
+                       return true;
                }
 
                state->sp = info->next_sp;
@@ -208,4 +228,36 @@ bool unwind_next_frame(struct unwind_state *state)
 
        return false;
 }
+
+unsigned long unwind_get_return_address(struct unwind_state *state)
+{
+       return __unwind_get_return_address(state);
+}
+EXPORT_SYMBOL_GPL(unwind_get_return_address);
+
+void unwind_start(struct unwind_state *state, struct task_struct *task,
+                   struct pt_regs *regs)
+{
+       __unwind_start(state, task, regs);
+       state->type = UNWINDER_PROLOGUE;
+       state->first = true;
+
+       /*
+        * The current PC is not kernel text address, we cannot find its
+        * relative symbol. Thus, prologue analysis will be broken. Luckily,
+        * we can use the default_next_frame().
+        */
+       if (!__kernel_text_address(state->pc)) {
+               state->type = UNWINDER_GUESS;
+               if (!unwind_done(state))
+                       unwind_next_frame(state);
+       }
+}
+EXPORT_SYMBOL_GPL(unwind_start);
+
+bool unwind_next_frame(struct unwind_state *state)
+{
+       return state->type == UNWINDER_PROLOGUE ?
+                       next_frame(state) : default_next_frame(state);
+}
 EXPORT_SYMBOL_GPL(unwind_next_frame);
index da3681f..8bad6b0 100644 (file)
@@ -251,7 +251,7 @@ static void output_pgtable_bits_defines(void)
 }
 
 #ifdef CONFIG_NUMA
-static unsigned long pcpu_handlers[NR_CPUS];
+unsigned long pcpu_handlers[NR_CPUS];
 #endif
 extern long exception_handlers[VECSIZE * 128 / sizeof(long)];
 
index 43bed6c..5235fd1 100644 (file)
                        bus-range = <0x0 0xff>;
                        ranges = <0x81000000  0x0 0x60080000  0x0 0x60080000 0x0 0x10000>,      /* I/O */
                                 <0x82000000  0x0 0x60090000  0x0 0x60090000 0x0 0xff70000>,    /* mem */
-                                <0x82000000  0x0 0x70000000  0x0 0x70000000 0x0 0x1000000>,    /* mem */
+                                <0x82000000  0x0 0x70000000  0x0 0x70000000 0x0 0x10000000>,    /* mem */
                                 <0xc3000000 0x20 0x00000000 0x20 0x00000000 0x20 0x00000000>;  /* mem prefetchable */
                        num-lanes = <0x8>;
                        interrupts = <56>, <57>, <58>, <59>, <60>, <61>, <62>, <63>, <64>;
index 2b60913..696c9e0 100644 (file)
@@ -508,6 +508,7 @@ static void __init setup_lowcore_dat_on(void)
 {
        struct lowcore *abs_lc;
        unsigned long flags;
+       int i;
 
        __ctl_clear_bit(0, 28);
        S390_lowcore.external_new_psw.mask |= PSW_MASK_DAT;
@@ -523,8 +524,8 @@ static void __init setup_lowcore_dat_on(void)
        abs_lc = get_abs_lowcore(&flags);
        abs_lc->restart_flags = RESTART_FLAG_CTLREGS;
        abs_lc->program_new_psw = S390_lowcore.program_new_psw;
-       memcpy(abs_lc->cregs_save_area, S390_lowcore.cregs_save_area,
-              sizeof(abs_lc->cregs_save_area));
+       for (i = 0; i < 16; i++)
+               abs_lc->cregs_save_area[i] = S390_lowcore.cregs_save_area[i];
        put_abs_lowcore(abs_lc, flags);
 }
 
index 1b2829e..7d9b15f 100644 (file)
@@ -316,14 +316,12 @@ struct bfq_group *bfqq_group(struct bfq_queue *bfqq)
 
 static void bfqg_get(struct bfq_group *bfqg)
 {
-       bfqg->ref++;
+       refcount_inc(&bfqg->ref);
 }
 
 static void bfqg_put(struct bfq_group *bfqg)
 {
-       bfqg->ref--;
-
-       if (bfqg->ref == 0)
+       if (refcount_dec_and_test(&bfqg->ref))
                kfree(bfqg);
 }
 
@@ -530,7 +528,7 @@ static struct blkg_policy_data *bfq_pd_alloc(gfp_t gfp, struct request_queue *q,
        }
 
        /* see comments in bfq_bic_update_cgroup for why refcounting */
-       bfqg_get(bfqg);
+       refcount_set(&bfqg->ref, 1);
        return &bfqg->pd;
 }
 
index 41aa151..466e486 100644 (file)
@@ -928,7 +928,7 @@ struct bfq_group {
        char blkg_path[128];
 
        /* reference counter (see comments in bfq_bic_update_cgroup) */
-       int ref;
+       refcount_t ref;
        /* Is bfq_group still online? */
        bool online;
 
index ce6a2b7..4c94a65 100644 (file)
@@ -1455,6 +1455,10 @@ retry:
                list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
                        pol->pd_init_fn(blkg->pd[pol->plid]);
 
+       if (pol->pd_online_fn)
+               list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
+                       pol->pd_online_fn(blkg->pd[pol->plid]);
+
        __set_bit(pol->plid, q->blkcg_pols);
        ret = 0;
 
index 2c49b41..9d463f7 100644 (file)
@@ -2890,6 +2890,7 @@ static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
                struct blk_plug *plug, struct bio **bio, unsigned int nsegs)
 {
        struct request *rq;
+       enum hctx_type type, hctx_type;
 
        if (!plug)
                return NULL;
@@ -2902,7 +2903,10 @@ static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
                return NULL;
        }
 
-       if (blk_mq_get_hctx_type((*bio)->bi_opf) != rq->mq_hctx->type)
+       type = blk_mq_get_hctx_type((*bio)->bi_opf);
+       hctx_type = rq->mq_hctx->type;
+       if (type != hctx_type &&
+           !(type == HCTX_TYPE_READ && hctx_type == HCTX_TYPE_DEFAULT))
                return NULL;
        if (op_is_flush(rq->cmd_flags) != op_is_flush((*bio)->bi_opf))
                return NULL;
index 08cf8a1..07373b3 100644 (file)
@@ -354,6 +354,9 @@ void spk_ttyio_release(struct spk_synth *in_synth)
 {
        struct tty_struct *tty = in_synth->dev;
 
+       if (tty == NULL)
+               return;
+
        tty_lock(tty);
 
        if (tty->ops->close)
index 998101c..3d4c462 100644 (file)
@@ -236,6 +236,11 @@ static acpi_status acpi_platformrt_space_handler(u32 function,
        efi_status_t status;
        struct prm_context_buffer context;
 
+       if (!efi_enabled(EFI_RUNTIME_SERVICES)) {
+               pr_err_ratelimited("PRM: EFI runtime services no longer available\n");
+               return AE_NO_HANDLER;
+       }
+
        /*
         * The returned acpi_status will always be AE_OK. Error values will be
         * saved in the first byte of the PRM message buffer to be used by ASL.
@@ -325,6 +330,11 @@ void __init init_prmt(void)
 
        pr_info("PRM: found %u modules\n", mc);
 
+       if (!efi_enabled(EFI_RUNTIME_SERVICES)) {
+               pr_err("PRM: EFI runtime services unavailable\n");
+               return;
+       }
+
        status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
                                                    ACPI_ADR_SPACE_PLATFORM_RT,
                                                    &acpi_platformrt_space_handler,
index 8a541ef..65cec7b 100644 (file)
@@ -517,6 +517,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
        },
        {
         .callback = video_detect_force_native,
+        /* Acer Aspire 4810T */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 4810T"),
+               },
+       },
+       {
+        .callback = video_detect_force_native,
         /* Acer Aspire 5738z */
         .matches = {
                DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
index bbb3e49..083a957 100644 (file)
@@ -997,26 +997,32 @@ struct fwnode_handle *
 fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
                               struct fwnode_handle *prev)
 {
+       struct fwnode_handle *ep, *port_parent = NULL;
        const struct fwnode_handle *parent;
-       struct fwnode_handle *ep;
 
        /*
         * If this function is in a loop and the previous iteration returned
         * an endpoint from fwnode->secondary, then we need to use the secondary
         * as parent rather than @fwnode.
         */
-       if (prev)
-               parent = fwnode_graph_get_port_parent(prev);
-       else
+       if (prev) {
+               port_parent = fwnode_graph_get_port_parent(prev);
+               parent = port_parent;
+       } else {
                parent = fwnode;
+       }
        if (IS_ERR_OR_NULL(parent))
                return NULL;
 
        ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev);
        if (ep)
-               return ep;
+               goto out_put_port_parent;
+
+       ep = fwnode_graph_get_next_endpoint(parent->secondary, NULL);
 
-       return fwnode_graph_get_next_endpoint(parent->secondary, NULL);
+out_put_port_parent:
+       fwnode_handle_put(port_parent);
+       return ep;
 }
 EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
 
index 4d1976c..929410d 100644 (file)
@@ -145,7 +145,7 @@ static int __init test_async_probe_init(void)
        calltime = ktime_get();
        for_each_online_cpu(cpu) {
                nid = cpu_to_node(cpu);
-               pdev = &sync_dev[sync_id];
+               pdev = &async_dev[async_id];
 
                *pdev = test_platform_device_register_node("test_async_driver",
                                                           async_id,
index 4cea3b0..2f1a925 100644 (file)
@@ -2400,6 +2400,8 @@ static void pkt_submit_bio(struct bio *bio)
        struct bio *split;
 
        bio = bio_split_to_limits(bio);
+       if (!bio)
+               return;
 
        pkt_dbg(2, pd, "start = %6llx stop = %6llx\n",
                (unsigned long long)bio->bi_iter.bi_sector,
index 78334da..5eb8c78 100644 (file)
@@ -1440,7 +1440,7 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
                goto out_alloc;
        }
 
-       ret = ida_alloc_max(&index_ida, 1 << (MINORBITS - RNBD_PART_BITS),
+       ret = ida_alloc_max(&index_ida, (1 << (MINORBITS - RNBD_PART_BITS)) - 1,
                            GFP_KERNEL);
        if (ret < 0) {
                pr_err("Failed to initialize device '%s' from session %s, allocating idr failed, err: %d\n",
index 6eddc23..bbe9cf1 100644 (file)
@@ -2164,10 +2164,17 @@ static void qca_serdev_shutdown(struct device *dev)
        int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
        struct serdev_device *serdev = to_serdev_device(dev);
        struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
+       struct hci_uart *hu = &qcadev->serdev_hu;
+       struct hci_dev *hdev = hu->hdev;
+       struct qca_data *qca = hu->priv;
        const u8 ibs_wake_cmd[] = { 0xFD };
        const u8 edl_reset_soc_cmd[] = { 0x01, 0x00, 0xFC, 0x01, 0x05 };
 
        if (qcadev->btsoc_type == QCA_QCA6390) {
+               if (test_bit(QCA_BT_OFF, &qca->flags) ||
+                   !test_bit(HCI_RUNNING, &hdev->flags))
+                       return;
+
                serdev_device_write_flush(serdev);
                ret = serdev_device_write_buf(serdev, ibs_wake_cmd,
                                              sizeof(ibs_wake_cmd));
index fcfc2e2..27f3890 100644 (file)
@@ -58,7 +58,7 @@
 #define PCI1760_CMD_CLR_IMB2           0x00    /* Clears IMB2 */
 #define PCI1760_CMD_SET_DO             0x01    /* Set output state */
 #define PCI1760_CMD_GET_DO             0x02    /* Read output status */
-#define PCI1760_CMD_GET_STATUS         0x03    /* Read current status */
+#define PCI1760_CMD_GET_STATUS         0x07    /* Read current status */
 #define PCI1760_CMD_GET_FW_VER         0x0e    /* Read firmware version */
 #define PCI1760_CMD_GET_HW_VER         0x0f    /* Read hardware version */
 #define PCI1760_CMD_SET_PWM_HI(x)      (0x10 + (x) * 2) /* Set "hi" period */
index c741b64..8a6e6b6 100644 (file)
@@ -451,7 +451,8 @@ static int dma_chan_get(struct dma_chan *chan)
        /* The channel is already in use, update client count */
        if (chan->client_count) {
                __module_get(owner);
-               goto out;
+               chan->client_count++;
+               return 0;
        }
 
        if (!try_module_get(owner))
@@ -470,11 +471,11 @@ static int dma_chan_get(struct dma_chan *chan)
                        goto err_out;
        }
 
+       chan->client_count++;
+
        if (!dma_has_cap(DMA_PRIVATE, chan->device->cap_mask))
                balance_ref_count(chan);
 
-out:
-       chan->client_count++;
        return 0;
 
 err_out:
index a183d93..bf85aa0 100644 (file)
@@ -1018,6 +1018,11 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status)
 
        /* The bad descriptor currently is in the head of vc list */
        vd = vchan_next_desc(&chan->vc);
+       if (!vd) {
+               dev_err(chan2dev(chan), "BUG: %s, IRQ with no descriptors\n",
+                       axi_chan_name(chan));
+               goto out;
+       }
        /* Remove the completed descriptor from issued list */
        list_del(&vd->node);
 
@@ -1032,6 +1037,7 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status)
        /* Try to restart the controller */
        axi_chan_start_first_queued(chan);
 
+out:
        spin_unlock_irqrestore(&chan->vc.lock, flags);
 }
 
index 06f5d37..29dbb0f 100644 (file)
@@ -1172,8 +1172,19 @@ static void idxd_flush_pending_descs(struct idxd_irq_entry *ie)
        spin_unlock(&ie->list_lock);
 
        list_for_each_entry_safe(desc, itr, &flist, list) {
+               struct dma_async_tx_descriptor *tx;
+
                list_del(&desc->list);
                ctype = desc->completion->status ? IDXD_COMPLETE_NORMAL : IDXD_COMPLETE_ABORT;
+               /*
+                * wq is being disabled. Any remaining descriptors are
+                * likely to be stuck and can be dropped. callback could
+                * point to code that is no longer accessible, for example
+                * if dmatest module has been unloaded.
+                */
+               tx = &desc->txd;
+               tx->callback = NULL;
+               tx->callback_result = NULL;
                idxd_dma_complete_txd(desc, ctype, true);
        }
 }
@@ -1390,8 +1401,7 @@ err_res_alloc:
 err_irq:
        idxd_wq_unmap_portal(wq);
 err_map_portal:
-       rc = idxd_wq_disable(wq, false);
-       if (rc < 0)
+       if (idxd_wq_disable(wq, false))
                dev_dbg(dev, "wq %s disable failed\n", dev_name(wq_confdev(wq)));
 err:
        return rc;
@@ -1408,11 +1418,11 @@ void drv_disable_wq(struct idxd_wq *wq)
                dev_warn(dev, "Clients has claim on wq %d: %d\n",
                         wq->id, idxd_wq_refcount(wq));
 
-       idxd_wq_free_resources(wq);
        idxd_wq_unmap_portal(wq);
        idxd_wq_drain(wq);
        idxd_wq_free_irq(wq);
        idxd_wq_reset(wq);
+       idxd_wq_free_resources(wq);
        percpu_ref_exit(&wq->wq_active);
        wq->type = IDXD_WQT_NONE;
        wq->client_count = 0;
index fbea5f6..b926abe 100644 (file)
@@ -1521,10 +1521,12 @@ static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
                sdma_config_ownership(sdmac, false, true, false);
 
        if (sdma_load_context(sdmac))
-               goto err_desc_out;
+               goto err_bd_out;
 
        return desc;
 
+err_bd_out:
+       sdma_free_bd(desc);
 err_desc_out:
        kfree(desc);
 err_out:
index 9b9184f..1709d15 100644 (file)
@@ -914,7 +914,7 @@ static void ldma_dev_init(struct ldma_dev *d)
        }
 }
 
-static int ldma_cfg_init(struct ldma_dev *d)
+static int ldma_parse_dt(struct ldma_dev *d)
 {
        struct fwnode_handle *fwnode = dev_fwnode(d->dev);
        struct ldma_port *p;
@@ -1661,10 +1661,6 @@ static int intel_ldma_probe(struct platform_device *pdev)
                p->ldev = d;
        }
 
-       ret = ldma_cfg_init(d);
-       if (ret)
-               return ret;
-
        dma_dev->dev = &pdev->dev;
 
        ch_mask = (unsigned long)d->channels_mask;
@@ -1675,6 +1671,10 @@ static int intel_ldma_probe(struct platform_device *pdev)
                        ldma_dma_init_v3X(j, d);
        }
 
+       ret = ldma_parse_dt(d);
+       if (ret)
+               return ret;
+
        dma_dev->device_alloc_chan_resources = ldma_alloc_chan_resources;
        dma_dev->device_free_chan_resources = ldma_free_chan_resources;
        dma_dev->device_terminate_all = ldma_terminate_all;
index 377da23..a2bf13f 100644 (file)
@@ -71,12 +71,13 @@ static int pt_core_execute_cmd(struct ptdma_desc *desc, struct pt_cmd_queue *cmd
        bool soc = FIELD_GET(DWORD0_SOC, desc->dw0);
        u8 *q_desc = (u8 *)&cmd_q->qbase[cmd_q->qidx];
        u32 tail;
+       unsigned long flags;
 
        if (soc) {
                desc->dw0 |= FIELD_PREP(DWORD0_IOC, desc->dw0);
                desc->dw0 &= ~DWORD0_SOC;
        }
-       mutex_lock(&cmd_q->q_mutex);
+       spin_lock_irqsave(&cmd_q->q_lock, flags);
 
        /* Copy 32-byte command descriptor to hw queue. */
        memcpy(q_desc, desc, 32);
@@ -91,7 +92,7 @@ static int pt_core_execute_cmd(struct ptdma_desc *desc, struct pt_cmd_queue *cmd
 
        /* Turn the queue back on using our cached control register */
        pt_start_queue(cmd_q);
-       mutex_unlock(&cmd_q->q_mutex);
+       spin_unlock_irqrestore(&cmd_q->q_lock, flags);
 
        return 0;
 }
@@ -199,7 +200,7 @@ int pt_core_init(struct pt_device *pt)
 
        cmd_q->pt = pt;
        cmd_q->dma_pool = dma_pool;
-       mutex_init(&cmd_q->q_mutex);
+       spin_lock_init(&cmd_q->q_lock);
 
        /* Page alignment satisfies our needs for N <= 128 */
        cmd_q->qsize = Q_SIZE(Q_DESC_SIZE);
index d093c43..21b4bf8 100644 (file)
@@ -196,7 +196,7 @@ struct pt_cmd_queue {
        struct ptdma_desc *qbase;
 
        /* Aligned queue start address (per requirement) */
-       struct mutex q_mutex ____cacheline_aligned;
+       spinlock_t q_lock ____cacheline_aligned;
        unsigned int qidx;
 
        unsigned int qsize;
index 061add8..59a36cb 100644 (file)
@@ -1756,6 +1756,7 @@ static int gpi_create_spi_tre(struct gchan *chan, struct gpi_desc *desc,
                tre->dword[3] = u32_encode_bits(TRE_TYPE_GO, TRE_FLAGS_TYPE);
                if (spi->cmd == SPI_RX) {
                        tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB);
+                       tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_LINK);
                } else if (spi->cmd == SPI_TX) {
                        tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_CHAIN);
                } else { /* SPI_DUPLEX */
index 1d1180d..8f67f45 100644 (file)
@@ -711,6 +711,7 @@ static int tegra_dma_terminate_all(struct dma_chan *dc)
                        return err;
                }
 
+               vchan_terminate_vdesc(&tdc->dma_desc->vd);
                tegra_dma_disable(tdc);
                tdc->dma_desc = NULL;
        }
index ae39b52..79da93c 100644 (file)
@@ -221,7 +221,7 @@ static int tegra_adma_init(struct tegra_adma *tdma)
        int ret;
 
        /* Clear any interrupts */
-       tdma_write(tdma, tdma->cdata->global_int_clear, 0x1);
+       tdma_write(tdma, tdma->cdata->ch_base_offset + tdma->cdata->global_int_clear, 0x1);
 
        /* Assert soft reset */
        tdma_write(tdma, ADMA_GLOBAL_SOFT_RESET, 0x1);
index ce8b80b..4c62274 100644 (file)
@@ -762,11 +762,12 @@ static void udma_decrement_byte_counters(struct udma_chan *uc, u32 val)
        if (uc->desc->dir == DMA_DEV_TO_MEM) {
                udma_rchanrt_write(uc, UDMA_CHAN_RT_BCNT_REG, val);
                udma_rchanrt_write(uc, UDMA_CHAN_RT_SBCNT_REG, val);
-               udma_rchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val);
+               if (uc->config.ep_type != PSIL_EP_NATIVE)
+                       udma_rchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val);
        } else {
                udma_tchanrt_write(uc, UDMA_CHAN_RT_BCNT_REG, val);
                udma_tchanrt_write(uc, UDMA_CHAN_RT_SBCNT_REG, val);
-               if (!uc->bchan)
+               if (!uc->bchan && uc->config.ep_type != PSIL_EP_NATIVE)
                        udma_tchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val);
        }
 }
index a8d23cd..ac09f0e 100644 (file)
@@ -3143,8 +3143,10 @@ static int xilinx_dma_probe(struct platform_device *pdev)
        /* Initialize the channels */
        for_each_child_of_node(node, child) {
                err = xilinx_dma_child_probe(xdev, child);
-               if (err < 0)
+               if (err < 0) {
+                       of_node_put(child);
                        goto error;
+               }
        }
 
        if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
index f818d00..ffdad59 100644 (file)
@@ -910,6 +910,8 @@ static int do_xfer(const struct scmi_protocol_handle *ph,
                              xfer->hdr.protocol_id, xfer->hdr.seq,
                              xfer->hdr.poll_completion);
 
+       /* Clear any stale status */
+       xfer->hdr.status = SCMI_SUCCESS;
        xfer->state = SCMI_XFER_SENT_OK;
        /*
         * Even though spinlocking is not needed here since no race is possible
index 1dfe534..87b4f4d 100644 (file)
@@ -81,10 +81,11 @@ u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem)
 void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
                          struct scmi_xfer *xfer)
 {
+       size_t len = ioread32(&shmem->length);
+
        xfer->hdr.status = ioread32(shmem->msg_payload);
        /* Skip the length of header and status in shmem area i.e 8 bytes */
-       xfer->rx.len = min_t(size_t, xfer->rx.len,
-                            ioread32(&shmem->length) - 8);
+       xfer->rx.len = min_t(size_t, xfer->rx.len, len > 8 ? len - 8 : 0);
 
        /* Take a copy to the rx buffer.. */
        memcpy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len);
@@ -93,8 +94,10 @@ void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
 void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem,
                              size_t max_len, struct scmi_xfer *xfer)
 {
+       size_t len = ioread32(&shmem->length);
+
        /* Skip only the length of header in shmem area i.e 4 bytes */
-       xfer->rx.len = min_t(size_t, max_len, ioread32(&shmem->length) - 4);
+       xfer->rx.len = min_t(size_t, max_len, len > 4 ? len - 4 : 0);
 
        /* Take a copy to the rx buffer.. */
        memcpy_fromio(xfer->rx.buf, shmem->msg_payload, xfer->rx.len);
index 33c9b81..1db975c 100644 (file)
@@ -160,7 +160,6 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch)
        }
 
        vioch->shutdown_done = &vioch_shutdown_done;
-       virtio_break_device(vioch->vqueue->vdev);
        if (!vioch->is_rx && vioch->deferred_tx_wq)
                /* Cannot be kicked anymore after this...*/
                vioch->deferred_tx_wq = NULL;
@@ -482,6 +481,12 @@ static int virtio_chan_free(int id, void *p, void *data)
        struct scmi_chan_info *cinfo = p;
        struct scmi_vio_channel *vioch = cinfo->transport_info;
 
+       /*
+        * Break device to inhibit further traffic flowing while shutting down
+        * the channels: doing it later holding vioch->lock creates unsafe
+        * locking dependency chains as reported by LOCKDEP.
+        */
+       virtio_break_device(vioch->vqueue->vdev);
        scmi_vio_channel_cleanup_sync(vioch);
 
        scmi_free_channel(cinfo, data, id);
index 4e2575d..871bedf 100644 (file)
@@ -361,9 +361,10 @@ static efi_status_t gsmi_get_variable(efi_char16_t *name,
                memcpy(data, gsmi_dev.data_buf->start, *data_size);
 
                /* All variables are have the following attributes */
-               *attr = EFI_VARIABLE_NON_VOLATILE |
-                       EFI_VARIABLE_BOOTSERVICE_ACCESS |
-                       EFI_VARIABLE_RUNTIME_ACCESS;
+               if (attr)
+                       *attr = EFI_VARIABLE_NON_VOLATILE |
+                               EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                               EFI_VARIABLE_RUNTIME_ACCESS;
        }
 
        spin_unlock_irqrestore(&gsmi_dev.lock, flags);
index d5626c5..6f673b2 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 #include <linux/syscore_ops.h>
 #include <linux/gpio/driver.h>
 #include <linux/of.h>
@@ -159,6 +160,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mxc_gpio_port *port = gc->private;
+       unsigned long flags;
        u32 bit, val;
        u32 gpio_idx = d->hwirq;
        int edge;
@@ -197,6 +199,8 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
                return -EINVAL;
        }
 
+       raw_spin_lock_irqsave(&port->gc.bgpio_lock, flags);
+
        if (GPIO_EDGE_SEL >= 0) {
                val = readl(port->base + GPIO_EDGE_SEL);
                if (edge == GPIO_INT_BOTH_EDGES)
@@ -217,15 +221,20 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
        writel(1 << gpio_idx, port->base + GPIO_ISR);
        port->pad_type[gpio_idx] = type;
 
-       return 0;
+       raw_spin_unlock_irqrestore(&port->gc.bgpio_lock, flags);
+
+       return port->gc.direction_input(&port->gc, gpio_idx);
 }
 
 static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
 {
        void __iomem *reg = port->base;
+       unsigned long flags;
        u32 bit, val;
        int edge;
 
+       raw_spin_lock_irqsave(&port->gc.bgpio_lock, flags);
+
        reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
        bit = gpio & 0xf;
        val = readl(reg);
@@ -243,6 +252,8 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
                return;
        }
        writel(val | (edge << (bit << 1)), reg);
+
+       raw_spin_unlock_irqrestore(&port->gc.bgpio_lock, flags);
 }
 
 /* handle 32 interrupts in one status register */
index bed0380..9ef0f56 100644 (file)
@@ -385,7 +385,7 @@ err:
 }
 
 static bool acpi_gpio_irq_is_wake(struct device *parent,
-                                 struct acpi_resource_gpio *agpio)
+                                 const struct acpi_resource_gpio *agpio)
 {
        unsigned int pin = agpio->pin_table[0];
 
@@ -778,7 +778,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
                lookup->info.pin_config = agpio->pin_config;
                lookup->info.debounce = agpio->debounce_timeout;
                lookup->info.gpioint = gpioint;
-               lookup->info.wake_capable = agpio->wake_capable == ACPI_WAKE_CAPABLE;
+               lookup->info.wake_capable = acpi_gpio_irq_is_wake(&lookup->info.adev->dev, agpio);
 
                /*
                 * Polarity and triggering are only specified for GpioInt
@@ -1623,6 +1623,19 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
                        .ignore_interrupt = "AMDI0030:00@18",
                },
        },
+       {
+               /*
+                * Spurious wakeups from TP_ATTN# pin
+                * Found in BIOS 1.7.8
+                * https://gitlab.freedesktop.org/drm/amd/-/issues/1722#note_1720627
+                */
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
+               },
+               .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+                       .ignore_wake = "ELAN0415:00@9",
+               },
+       },
        {} /* Terminating entry */
 };
 
index 7771a19..bbeeb6d 100644 (file)
@@ -288,39 +288,6 @@ static const u8 dg2_xcs_offsets[] = {
        END
 };
 
-static const u8 mtl_xcs_offsets[] = {
-       NOP(1),
-       LRI(13, POSTED),
-       REG16(0x244),
-       REG(0x034),
-       REG(0x030),
-       REG(0x038),
-       REG(0x03c),
-       REG(0x168),
-       REG(0x140),
-       REG(0x110),
-       REG(0x1c0),
-       REG(0x1c4),
-       REG(0x1c8),
-       REG(0x180),
-       REG16(0x2b4),
-       NOP(4),
-
-       NOP(1),
-       LRI(9, POSTED),
-       REG16(0x3a8),
-       REG16(0x28c),
-       REG16(0x288),
-       REG16(0x284),
-       REG16(0x280),
-       REG16(0x27c),
-       REG16(0x278),
-       REG16(0x274),
-       REG16(0x270),
-
-       END
-};
-
 static const u8 gen8_rcs_offsets[] = {
        NOP(1),
        LRI(14, POSTED),
@@ -739,9 +706,7 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine)
                else
                        return gen8_rcs_offsets;
        } else {
-               if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 70))
-                       return mtl_xcs_offsets;
-               else if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55))
+               if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55))
                        return dg2_xcs_offsets;
                else if (GRAPHICS_VER(engine->i915) >= 12)
                        return gen12_xcs_offsets;
index 310fb83..2990dd4 100644 (file)
@@ -28,8 +28,7 @@ struct intel_engine_cs *intel_selftest_find_any_engine(struct intel_gt *gt)
 
 int intel_selftest_modify_policy(struct intel_engine_cs *engine,
                                 struct intel_selftest_saved_policy *saved,
-                                u32 modify_type)
-
+                                enum selftest_scheduler_modify modify_type)
 {
        int err;
 
index ab125f7..1fb0f71 100644 (file)
@@ -282,7 +282,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
                }
                rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]);
                if (rc)
-                       return rc;
+                       goto cleanup;
                mp2_ops->start(privdata, info);
                status = amd_sfh_wait_for_response
                                (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED);
index 4da2f9f..a1d6e08 100644 (file)
@@ -160,7 +160,7 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
                }
                rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]);
                if (rc)
-                       return rc;
+                       goto cleanup;
 
                writel(0, privdata->mmio + AMD_P2C_MSG(0));
                mp2_ops->start(privdata, info);
index 467d789..25ed7b9 100644 (file)
@@ -60,7 +60,6 @@ static int betopff_init(struct hid_device *hid)
        struct list_head *report_list =
                        &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct input_dev *dev;
-       int field_count = 0;
        int error;
        int i, j;
 
@@ -86,19 +85,21 @@ static int betopff_init(struct hid_device *hid)
         * -----------------------------------------
         * Do init them with default value.
         */
+       if (report->maxfield < 4) {
+               hid_err(hid, "not enough fields in the report: %d\n",
+                               report->maxfield);
+               return -ENODEV;
+       }
        for (i = 0; i < report->maxfield; i++) {
+               if (report->field[i]->report_count < 1) {
+                       hid_err(hid, "no values in the field\n");
+                       return -ENODEV;
+               }
                for (j = 0; j < report->field[i]->report_count; j++) {
                        report->field[i]->value[j] = 0x00;
-                       field_count++;
                }
        }
 
-       if (field_count < 4) {
-               hid_err(hid, "not enough fields in the report: %d\n",
-                               field_count);
-               return -ENODEV;
-       }
-
        betopff = kzalloc(sizeof(*betopff), GFP_KERNEL);
        if (!betopff)
                return -ENOMEM;
index e8c5e3a..e8b1666 100644 (file)
@@ -344,6 +344,11 @@ static int bigben_probe(struct hid_device *hid,
        }
 
        report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+       if (list_empty(report_list)) {
+               hid_err(hid, "no output report found\n");
+               error = -ENODEV;
+               goto error_hw_stop;
+       }
        bigben->report = list_entry(report_list->next,
                struct hid_report, list);
 
index bd47628..3e18035 100644 (file)
@@ -993,8 +993,8 @@ struct hid_report *hid_validate_values(struct hid_device *hid,
                 * Validating on id 0 means we should examine the first
                 * report in the list.
                 */
-               report = list_entry(
-                               hid->report_enum[type].report_list.next,
+               report = list_first_entry_or_null(
+                               &hid->report_enum[type].report_list,
                                struct hid_report, list);
        } else {
                report = hid->report_enum[type].report_id_hash[id];
index 82713ef..0f8c118 100644 (file)
 #define USB_DEVICE_ID_CH_AXIS_295      0x001c
 
 #define USB_VENDOR_ID_CHERRY           0x046a
-#define USB_DEVICE_ID_CHERRY_MOUSE_000C        0x000c
 #define USB_DEVICE_ID_CHERRY_CYMOTION  0x0023
 #define USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR    0x0027
 
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540   0x0075
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640   0x0094
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042
+#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2      0x0905
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L 0x0935
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S     0x0909
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078
index f399bf0..27c4089 100644 (file)
@@ -944,6 +944,7 @@ ATTRIBUTE_GROUPS(ps_device);
 
 static int dualsense_get_calibration_data(struct dualsense *ds)
 {
+       struct hid_device *hdev = ds->base.hdev;
        short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus;
        short gyro_yaw_bias, gyro_yaw_plus, gyro_yaw_minus;
        short gyro_roll_bias, gyro_roll_plus, gyro_roll_minus;
@@ -954,6 +955,7 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
        int speed_2x;
        int range_2g;
        int ret = 0;
+       int i;
        uint8_t *buf;
 
        buf = kzalloc(DS_FEATURE_REPORT_CALIBRATION_SIZE, GFP_KERNEL);
@@ -1006,6 +1008,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
        ds->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus;
 
        /*
+        * Sanity check gyro calibration data. This is needed to prevent crashes
+        * during report handling of virtual, clone or broken devices not implementing
+        * calibration data properly.
+        */
+       for (i = 0; i < ARRAY_SIZE(ds->gyro_calib_data); i++) {
+               if (ds->gyro_calib_data[i].sens_denom == 0) {
+                       hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
+                                       ds->gyro_calib_data[i].abs_code);
+                       ds->gyro_calib_data[i].bias = 0;
+                       ds->gyro_calib_data[i].sens_numer = DS_GYRO_RANGE;
+                       ds->gyro_calib_data[i].sens_denom = S16_MAX;
+               }
+       }
+
+       /*
         * Set accelerometer calibration and normalization parameters.
         * Data values will be normalized to 1/DS_ACC_RES_PER_G g.
         */
@@ -1027,6 +1044,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
        ds->accel_calib_data[2].sens_numer = 2*DS_ACC_RES_PER_G;
        ds->accel_calib_data[2].sens_denom = range_2g;
 
+       /*
+        * Sanity check accelerometer calibration data. This is needed to prevent crashes
+        * during report handling of virtual, clone or broken devices not implementing calibration
+        * data properly.
+        */
+       for (i = 0; i < ARRAY_SIZE(ds->accel_calib_data); i++) {
+               if (ds->accel_calib_data[i].sens_denom == 0) {
+                       hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
+                                       ds->accel_calib_data[i].abs_code);
+                       ds->accel_calib_data[i].bias = 0;
+                       ds->accel_calib_data[i].sens_numer = DS_ACC_RANGE;
+                       ds->accel_calib_data[i].sens_denom = S16_MAX;
+               }
+       }
+
 err_free:
        kfree(buf);
        return ret;
@@ -1737,6 +1769,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
        int speed_2x;
        int range_2g;
        int ret = 0;
+       int i;
        uint8_t *buf;
 
        if (ds4->base.hdev->bus == BUS_USB) {
@@ -1831,6 +1864,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
        ds4->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus;
 
        /*
+        * Sanity check gyro calibration data. This is needed to prevent crashes
+        * during report handling of virtual, clone or broken devices not implementing
+        * calibration data properly.
+        */
+       for (i = 0; i < ARRAY_SIZE(ds4->gyro_calib_data); i++) {
+               if (ds4->gyro_calib_data[i].sens_denom == 0) {
+                       hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
+                                       ds4->gyro_calib_data[i].abs_code);
+                       ds4->gyro_calib_data[i].bias = 0;
+                       ds4->gyro_calib_data[i].sens_numer = DS4_GYRO_RANGE;
+                       ds4->gyro_calib_data[i].sens_denom = S16_MAX;
+               }
+       }
+
+       /*
         * Set accelerometer calibration and normalization parameters.
         * Data values will be normalized to 1/DS4_ACC_RES_PER_G g.
         */
@@ -1852,6 +1900,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
        ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G;
        ds4->accel_calib_data[2].sens_denom = range_2g;
 
+       /*
+        * Sanity check accelerometer calibration data. This is needed to prevent crashes
+        * during report handling of virtual, clone or broken devices not implementing calibration
+        * data properly.
+        */
+       for (i = 0; i < ARRAY_SIZE(ds4->accel_calib_data); i++) {
+               if (ds4->accel_calib_data[i].sens_denom == 0) {
+                       hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
+                                       ds4->accel_calib_data[i].abs_code);
+                       ds4->accel_calib_data[i].bias = 0;
+                       ds4->accel_calib_data[i].sens_numer = DS4_ACC_RANGE;
+                       ds4->accel_calib_data[i].sens_denom = S16_MAX;
+               }
+       }
+
 err_free:
        kfree(buf);
        return ret;
index 0e9702c..be3ad02 100644 (file)
@@ -54,7 +54,6 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE), HID_QUIRK_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS), HID_QUIRK_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE), HID_QUIRK_NOGET },
-       { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_MOUSE_000C), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB), HID_QUIRK_NO_INIT_REPORTS },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB), HID_QUIRK_NO_INIT_REPORTS },
index 7fa6fe0..cfbbc39 100644 (file)
@@ -526,6 +526,8 @@ static const struct hid_device_id uclogic_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
                                USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
+                               USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
                                USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
                                USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S) },
index cd1233d..3c5eea3 100644 (file)
@@ -1656,6 +1656,8 @@ int uclogic_params_init(struct uclogic_params *params,
        case VID_PID(USB_VENDOR_ID_UGEE,
                     USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
        case VID_PID(USB_VENDOR_ID_UGEE,
+                    USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2):
+       case VID_PID(USB_VENDOR_ID_UGEE,
                     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
        case VID_PID(USB_VENDOR_ID_UGEE,
                     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S):
index 40554c8..00046cb 100644 (file)
@@ -104,6 +104,11 @@ void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev,
        int required_slots = (size / DMA_SLOT_SIZE)
                + 1 * (size % DMA_SLOT_SIZE != 0);
 
+       if (!dev->ishtp_dma_tx_map) {
+               dev_err(dev->devc, "Fail to allocate Tx map\n");
+               return NULL;
+       }
+
        spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
        for (i = 0; i <= (dev->ishtp_dma_num_slots - required_slots); i++) {
                free = 1;
@@ -150,6 +155,11 @@ void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev,
                return;
        }
 
+       if (!dev->ishtp_dma_tx_map) {
+               dev_err(dev->devc, "Fail to allocate Tx map\n");
+               return;
+       }
+
        i = (msg_addr - dev->ishtp_host_dma_tx_buf) / DMA_SLOT_SIZE;
        spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
        for (j = 0; j < acked_slots; j++) {
index 26b021f..11b1c16 100644 (file)
@@ -2957,15 +2957,18 @@ EXPORT_SYMBOL(__rdma_block_iter_start);
 bool __rdma_block_iter_next(struct ib_block_iter *biter)
 {
        unsigned int block_offset;
+       unsigned int sg_delta;
 
        if (!biter->__sg_nents || !biter->__sg)
                return false;
 
        biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
        block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
-       biter->__sg_advance += BIT_ULL(biter->__pg_bit) - block_offset;
+       sg_delta = BIT_ULL(biter->__pg_bit) - block_offset;
 
-       if (biter->__sg_advance >= sg_dma_len(biter->__sg)) {
+       if (sg_dma_len(biter->__sg) - biter->__sg_advance > sg_delta) {
+               biter->__sg_advance += sg_delta;
+       } else {
                biter->__sg_advance = 0;
                biter->__sg = sg_next(biter->__sg);
                biter->__sg_nents--;
index 186d302..b02f2f0 100644 (file)
@@ -23,18 +23,25 @@ static void cacheless_tid_rb_remove(struct hfi1_filedata *fdata,
 static bool tid_rb_invalidate(struct mmu_interval_notifier *mni,
                              const struct mmu_notifier_range *range,
                              unsigned long cur_seq);
+static bool tid_cover_invalidate(struct mmu_interval_notifier *mni,
+                                const struct mmu_notifier_range *range,
+                                unsigned long cur_seq);
 static int program_rcvarray(struct hfi1_filedata *fd, struct tid_user_buf *,
                            struct tid_group *grp,
                            unsigned int start, u16 count,
                            u32 *tidlist, unsigned int *tididx,
                            unsigned int *pmapped);
-static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
-                             struct tid_group **grp);
+static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo);
+static void __clear_tid_node(struct hfi1_filedata *fd,
+                            struct tid_rb_node *node);
 static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node);
 
 static const struct mmu_interval_notifier_ops tid_mn_ops = {
        .invalidate = tid_rb_invalidate,
 };
+static const struct mmu_interval_notifier_ops tid_cover_ops = {
+       .invalidate = tid_cover_invalidate,
+};
 
 /*
  * Initialize context and file private data needed for Expected
@@ -253,53 +260,65 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
                tididx = 0, mapped, mapped_pages = 0;
        u32 *tidlist = NULL;
        struct tid_user_buf *tidbuf;
+       unsigned long mmu_seq = 0;
 
        if (!PAGE_ALIGNED(tinfo->vaddr))
                return -EINVAL;
+       if (tinfo->length == 0)
+               return -EINVAL;
 
        tidbuf = kzalloc(sizeof(*tidbuf), GFP_KERNEL);
        if (!tidbuf)
                return -ENOMEM;
 
+       mutex_init(&tidbuf->cover_mutex);
        tidbuf->vaddr = tinfo->vaddr;
        tidbuf->length = tinfo->length;
        tidbuf->psets = kcalloc(uctxt->expected_count, sizeof(*tidbuf->psets),
                                GFP_KERNEL);
        if (!tidbuf->psets) {
-               kfree(tidbuf);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto fail_release_mem;
+       }
+
+       if (fd->use_mn) {
+               ret = mmu_interval_notifier_insert(
+                       &tidbuf->notifier, current->mm,
+                       tidbuf->vaddr, tidbuf->npages * PAGE_SIZE,
+                       &tid_cover_ops);
+               if (ret)
+                       goto fail_release_mem;
+               mmu_seq = mmu_interval_read_begin(&tidbuf->notifier);
        }
 
        pinned = pin_rcv_pages(fd, tidbuf);
        if (pinned <= 0) {
-               kfree(tidbuf->psets);
-               kfree(tidbuf);
-               return pinned;
+               ret = (pinned < 0) ? pinned : -ENOSPC;
+               goto fail_unpin;
        }
 
        /* Find sets of physically contiguous pages */
        tidbuf->n_psets = find_phys_blocks(tidbuf, pinned);
 
-       /*
-        * We don't need to access this under a lock since tid_used is per
-        * process and the same process cannot be in hfi1_user_exp_rcv_clear()
-        * and hfi1_user_exp_rcv_setup() at the same time.
-        */
+       /* Reserve the number of expected tids to be used. */
        spin_lock(&fd->tid_lock);
        if (fd->tid_used + tidbuf->n_psets > fd->tid_limit)
                pageset_count = fd->tid_limit - fd->tid_used;
        else
                pageset_count = tidbuf->n_psets;
+       fd->tid_used += pageset_count;
        spin_unlock(&fd->tid_lock);
 
-       if (!pageset_count)
-               goto bail;
+       if (!pageset_count) {
+               ret = -ENOSPC;
+               goto fail_unreserve;
+       }
 
        ngroups = pageset_count / dd->rcv_entries.group_size;
        tidlist = kcalloc(pageset_count, sizeof(*tidlist), GFP_KERNEL);
        if (!tidlist) {
                ret = -ENOMEM;
-               goto nomem;
+               goto fail_unreserve;
        }
 
        tididx = 0;
@@ -395,43 +414,78 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
        }
 unlock:
        mutex_unlock(&uctxt->exp_mutex);
-nomem:
        hfi1_cdbg(TID, "total mapped: tidpairs:%u pages:%u (%d)", tididx,
                  mapped_pages, ret);
-       if (tididx) {
-               spin_lock(&fd->tid_lock);
-               fd->tid_used += tididx;
-               spin_unlock(&fd->tid_lock);
-               tinfo->tidcnt = tididx;
-               tinfo->length = mapped_pages * PAGE_SIZE;
-
-               if (copy_to_user(u64_to_user_ptr(tinfo->tidlist),
-                                tidlist, sizeof(tidlist[0]) * tididx)) {
-                       /*
-                        * On failure to copy to the user level, we need to undo
-                        * everything done so far so we don't leak resources.
-                        */
-                       tinfo->tidlist = (unsigned long)&tidlist;
-                       hfi1_user_exp_rcv_clear(fd, tinfo);
-                       tinfo->tidlist = 0;
-                       ret = -EFAULT;
-                       goto bail;
+
+       /* fail if nothing was programmed, set error if none provided */
+       if (tididx == 0) {
+               if (ret >= 0)
+                       ret = -ENOSPC;
+               goto fail_unreserve;
+       }
+
+       /* adjust reserved tid_used to actual count */
+       spin_lock(&fd->tid_lock);
+       fd->tid_used -= pageset_count - tididx;
+       spin_unlock(&fd->tid_lock);
+
+       /* unpin all pages not covered by a TID */
+       unpin_rcv_pages(fd, tidbuf, NULL, mapped_pages, pinned - mapped_pages,
+                       false);
+
+       if (fd->use_mn) {
+               /* check for an invalidate during setup */
+               bool fail = false;
+
+               mutex_lock(&tidbuf->cover_mutex);
+               fail = mmu_interval_read_retry(&tidbuf->notifier, mmu_seq);
+               mutex_unlock(&tidbuf->cover_mutex);
+
+               if (fail) {
+                       ret = -EBUSY;
+                       goto fail_unprogram;
                }
        }
 
-       /*
-        * If not everything was mapped (due to insufficient RcvArray entries,
-        * for example), unpin all unmapped pages so we can pin them nex time.
-        */
-       if (mapped_pages != pinned)
-               unpin_rcv_pages(fd, tidbuf, NULL, mapped_pages,
-                               (pinned - mapped_pages), false);
-bail:
+       tinfo->tidcnt = tididx;
+       tinfo->length = mapped_pages * PAGE_SIZE;
+
+       if (copy_to_user(u64_to_user_ptr(tinfo->tidlist),
+                        tidlist, sizeof(tidlist[0]) * tididx)) {
+               ret = -EFAULT;
+               goto fail_unprogram;
+       }
+
+       if (fd->use_mn)
+               mmu_interval_notifier_remove(&tidbuf->notifier);
+       kfree(tidbuf->pages);
        kfree(tidbuf->psets);
+       kfree(tidbuf);
        kfree(tidlist);
+       return 0;
+
+fail_unprogram:
+       /* unprogram, unmap, and unpin all allocated TIDs */
+       tinfo->tidlist = (unsigned long)tidlist;
+       hfi1_user_exp_rcv_clear(fd, tinfo);
+       tinfo->tidlist = 0;
+       pinned = 0;             /* nothing left to unpin */
+       pageset_count = 0;      /* nothing left reserved */
+fail_unreserve:
+       spin_lock(&fd->tid_lock);
+       fd->tid_used -= pageset_count;
+       spin_unlock(&fd->tid_lock);
+fail_unpin:
+       if (fd->use_mn)
+               mmu_interval_notifier_remove(&tidbuf->notifier);
+       if (pinned > 0)
+               unpin_rcv_pages(fd, tidbuf, NULL, 0, pinned, false);
+fail_release_mem:
        kfree(tidbuf->pages);
+       kfree(tidbuf->psets);
        kfree(tidbuf);
-       return ret > 0 ? 0 : ret;
+       kfree(tidlist);
+       return ret;
 }
 
 int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
@@ -452,7 +506,7 @@ int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
 
        mutex_lock(&uctxt->exp_mutex);
        for (tididx = 0; tididx < tinfo->tidcnt; tididx++) {
-               ret = unprogram_rcvarray(fd, tidinfo[tididx], NULL);
+               ret = unprogram_rcvarray(fd, tidinfo[tididx]);
                if (ret) {
                        hfi1_cdbg(TID, "Failed to unprogram rcv array %d",
                                  ret);
@@ -706,6 +760,7 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
        }
 
        node->fdata = fd;
+       mutex_init(&node->invalidate_mutex);
        node->phys = page_to_phys(pages[0]);
        node->npages = npages;
        node->rcventry = rcventry;
@@ -721,11 +776,6 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
                        &tid_mn_ops);
                if (ret)
                        goto out_unmap;
-               /*
-                * FIXME: This is in the wrong order, the notifier should be
-                * established before the pages are pinned by pin_rcv_pages.
-                */
-               mmu_interval_read_begin(&node->notifier);
        }
        fd->entry_to_rb[node->rcventry - uctxt->expected_base] = node;
 
@@ -745,8 +795,7 @@ out_unmap:
        return -EFAULT;
 }
 
-static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
-                             struct tid_group **grp)
+static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo)
 {
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
@@ -769,9 +818,6 @@ static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
        if (!node || node->rcventry != (uctxt->expected_base + rcventry))
                return -EBADF;
 
-       if (grp)
-               *grp = node->grp;
-
        if (fd->use_mn)
                mmu_interval_notifier_remove(&node->notifier);
        cacheless_tid_rb_remove(fd, node);
@@ -779,23 +825,34 @@ static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
        return 0;
 }
 
-static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node)
+static void __clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node)
 {
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
 
+       mutex_lock(&node->invalidate_mutex);
+       if (node->freed)
+               goto done;
+       node->freed = true;
+
        trace_hfi1_exp_tid_unreg(uctxt->ctxt, fd->subctxt, node->rcventry,
                                 node->npages,
                                 node->notifier.interval_tree.start, node->phys,
                                 node->dma_addr);
 
-       /*
-        * Make sure device has seen the write before we unpin the
-        * pages.
-        */
+       /* Make sure device has seen the write before pages are unpinned */
        hfi1_put_tid(dd, node->rcventry, PT_INVALID_FLUSH, 0, 0);
 
        unpin_rcv_pages(fd, NULL, node, 0, node->npages, true);
+done:
+       mutex_unlock(&node->invalidate_mutex);
+}
+
+static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node)
+{
+       struct hfi1_ctxtdata *uctxt = fd->uctxt;
+
+       __clear_tid_node(fd, node);
 
        node->grp->used--;
        node->grp->map &= ~(1 << (node->rcventry - node->grp->base));
@@ -854,10 +911,16 @@ static bool tid_rb_invalidate(struct mmu_interval_notifier *mni,
        if (node->freed)
                return true;
 
+       /* take action only if unmapping */
+       if (range->event != MMU_NOTIFY_UNMAP)
+               return true;
+
        trace_hfi1_exp_tid_inval(uctxt->ctxt, fdata->subctxt,
                                 node->notifier.interval_tree.start,
                                 node->rcventry, node->npages, node->dma_addr);
-       node->freed = true;
+
+       /* clear the hardware rcvarray entry */
+       __clear_tid_node(fdata, node);
 
        spin_lock(&fdata->invalid_lock);
        if (fdata->invalid_tid_idx < uctxt->expected_count) {
@@ -887,6 +950,23 @@ static bool tid_rb_invalidate(struct mmu_interval_notifier *mni,
        return true;
 }
 
+static bool tid_cover_invalidate(struct mmu_interval_notifier *mni,
+                                const struct mmu_notifier_range *range,
+                                unsigned long cur_seq)
+{
+       struct tid_user_buf *tidbuf =
+               container_of(mni, struct tid_user_buf, notifier);
+
+       /* take action only if unmapping */
+       if (range->event == MMU_NOTIFY_UNMAP) {
+               mutex_lock(&tidbuf->cover_mutex);
+               mmu_interval_set_seq(mni, cur_seq);
+               mutex_unlock(&tidbuf->cover_mutex);
+       }
+
+       return true;
+}
+
 static void cacheless_tid_rb_remove(struct hfi1_filedata *fdata,
                                    struct tid_rb_node *tnode)
 {
index 8c53e41..f8ee997 100644 (file)
@@ -16,6 +16,8 @@ struct tid_pageset {
 };
 
 struct tid_user_buf {
+       struct mmu_interval_notifier notifier;
+       struct mutex cover_mutex;
        unsigned long vaddr;
        unsigned long length;
        unsigned int npages;
@@ -27,6 +29,7 @@ struct tid_user_buf {
 struct tid_rb_node {
        struct mmu_interval_notifier notifier;
        struct hfi1_filedata *fdata;
+       struct mutex invalidate_mutex; /* covers hw removal */
        unsigned long phys;
        struct tid_group *grp;
        u32 rcventry;
index a754fc9..7b41d79 100644 (file)
@@ -98,11 +98,11 @@ enum rxe_device_param {
        RXE_MAX_SRQ                     = DEFAULT_MAX_VALUE - RXE_MIN_SRQ_INDEX,
 
        RXE_MIN_MR_INDEX                = 0x00000001,
-       RXE_MAX_MR_INDEX                = DEFAULT_MAX_VALUE,
-       RXE_MAX_MR                      = DEFAULT_MAX_VALUE - RXE_MIN_MR_INDEX,
-       RXE_MIN_MW_INDEX                = 0x00010001,
-       RXE_MAX_MW_INDEX                = 0x00020000,
-       RXE_MAX_MW                      = 0x00001000,
+       RXE_MAX_MR_INDEX                = DEFAULT_MAX_VALUE >> 1,
+       RXE_MAX_MR                      = RXE_MAX_MR_INDEX - RXE_MIN_MR_INDEX,
+       RXE_MIN_MW_INDEX                = RXE_MAX_MR_INDEX + 1,
+       RXE_MAX_MW_INDEX                = DEFAULT_MAX_VALUE,
+       RXE_MAX_MW                      = RXE_MAX_MW_INDEX - RXE_MIN_MW_INDEX,
 
        RXE_MAX_PKT_PER_ACK             = 64,
 
index f50620f..1151c0b 100644 (file)
@@ -23,16 +23,16 @@ static const struct rxe_type_info {
                .size           = sizeof(struct rxe_ucontext),
                .elem_offset    = offsetof(struct rxe_ucontext, elem),
                .min_index      = 1,
-               .max_index      = UINT_MAX,
-               .max_elem       = UINT_MAX,
+               .max_index      = RXE_MAX_UCONTEXT,
+               .max_elem       = RXE_MAX_UCONTEXT,
        },
        [RXE_TYPE_PD] = {
                .name           = "pd",
                .size           = sizeof(struct rxe_pd),
                .elem_offset    = offsetof(struct rxe_pd, elem),
                .min_index      = 1,
-               .max_index      = UINT_MAX,
-               .max_elem       = UINT_MAX,
+               .max_index      = RXE_MAX_PD,
+               .max_elem       = RXE_MAX_PD,
        },
        [RXE_TYPE_AH] = {
                .name           = "ah",
@@ -40,7 +40,7 @@ static const struct rxe_type_info {
                .elem_offset    = offsetof(struct rxe_ah, elem),
                .min_index      = RXE_MIN_AH_INDEX,
                .max_index      = RXE_MAX_AH_INDEX,
-               .max_elem       = RXE_MAX_AH_INDEX - RXE_MIN_AH_INDEX + 1,
+               .max_elem       = RXE_MAX_AH,
        },
        [RXE_TYPE_SRQ] = {
                .name           = "srq",
@@ -49,7 +49,7 @@ static const struct rxe_type_info {
                .cleanup        = rxe_srq_cleanup,
                .min_index      = RXE_MIN_SRQ_INDEX,
                .max_index      = RXE_MAX_SRQ_INDEX,
-               .max_elem       = RXE_MAX_SRQ_INDEX - RXE_MIN_SRQ_INDEX + 1,
+               .max_elem       = RXE_MAX_SRQ,
        },
        [RXE_TYPE_QP] = {
                .name           = "qp",
@@ -58,7 +58,7 @@ static const struct rxe_type_info {
                .cleanup        = rxe_qp_cleanup,
                .min_index      = RXE_MIN_QP_INDEX,
                .max_index      = RXE_MAX_QP_INDEX,
-               .max_elem       = RXE_MAX_QP_INDEX - RXE_MIN_QP_INDEX + 1,
+               .max_elem       = RXE_MAX_QP,
        },
        [RXE_TYPE_CQ] = {
                .name           = "cq",
@@ -66,8 +66,8 @@ static const struct rxe_type_info {
                .elem_offset    = offsetof(struct rxe_cq, elem),
                .cleanup        = rxe_cq_cleanup,
                .min_index      = 1,
-               .max_index      = UINT_MAX,
-               .max_elem       = UINT_MAX,
+               .max_index      = RXE_MAX_CQ,
+               .max_elem       = RXE_MAX_CQ,
        },
        [RXE_TYPE_MR] = {
                .name           = "mr",
@@ -76,7 +76,7 @@ static const struct rxe_type_info {
                .cleanup        = rxe_mr_cleanup,
                .min_index      = RXE_MIN_MR_INDEX,
                .max_index      = RXE_MAX_MR_INDEX,
-               .max_elem       = RXE_MAX_MR_INDEX - RXE_MIN_MR_INDEX + 1,
+               .max_elem       = RXE_MAX_MR,
        },
        [RXE_TYPE_MW] = {
                .name           = "mw",
@@ -85,7 +85,7 @@ static const struct rxe_type_info {
                .cleanup        = rxe_mw_cleanup,
                .min_index      = RXE_MIN_MW_INDEX,
                .max_index      = RXE_MAX_MW_INDEX,
-               .max_elem       = RXE_MAX_MW_INDEX - RXE_MIN_MW_INDEX + 1,
+               .max_elem       = RXE_MAX_MW,
        },
 };
 
index ba6781f..df3196f 100644 (file)
@@ -488,7 +488,7 @@ int qnoc_probe(struct platform_device *pdev)
        }
 
 regmap_done:
-       ret = devm_clk_bulk_get(dev, qp->num_clks, qp->bus_clks);
+       ret = devm_clk_bulk_get_optional(dev, qp->num_clks, qp->bus_clks);
        if (ret)
                return ret;
 
index c2903ae..25a1a32 100644 (file)
@@ -33,6 +33,13 @@ static const char * const bus_a0noc_clocks[] = {
        "aggre0_noc_mpu_cfg"
 };
 
+static const char * const bus_a2noc_clocks[] = {
+       "bus",
+       "bus_a",
+       "aggre2_ufs_axi",
+       "ufs_axi"
+};
+
 static const u16 mas_a0noc_common_links[] = {
        MSM8996_SLAVE_A0NOC_SNOC
 };
@@ -1806,7 +1813,7 @@ static const struct regmap_config msm8996_a0noc_regmap_config = {
        .reg_bits       = 32,
        .reg_stride     = 4,
        .val_bits       = 32,
-       .max_register   = 0x9000,
+       .max_register   = 0x6000,
        .fast_io        = true
 };
 
@@ -1830,7 +1837,7 @@ static const struct regmap_config msm8996_a1noc_regmap_config = {
        .reg_bits       = 32,
        .reg_stride     = 4,
        .val_bits       = 32,
-       .max_register   = 0x7000,
+       .max_register   = 0x5000,
        .fast_io        = true
 };
 
@@ -1851,7 +1858,7 @@ static const struct regmap_config msm8996_a2noc_regmap_config = {
        .reg_bits       = 32,
        .reg_stride     = 4,
        .val_bits       = 32,
-       .max_register   = 0xa000,
+       .max_register   = 0x7000,
        .fast_io        = true
 };
 
@@ -1859,6 +1866,8 @@ static const struct qcom_icc_desc msm8996_a2noc = {
        .type = QCOM_ICC_NOC,
        .nodes = a2noc_nodes,
        .num_nodes = ARRAY_SIZE(a2noc_nodes),
+       .clocks = bus_a2noc_clocks,
+       .num_clocks = ARRAY_SIZE(bus_a2noc_clocks),
        .regmap_cfg = &msm8996_a2noc_regmap_config
 };
 
@@ -1877,7 +1886,7 @@ static const struct regmap_config msm8996_bimc_regmap_config = {
        .reg_bits       = 32,
        .reg_stride     = 4,
        .val_bits       = 32,
-       .max_register   = 0x62000,
+       .max_register   = 0x5a000,
        .fast_io        = true
 };
 
@@ -1988,7 +1997,7 @@ static const struct regmap_config msm8996_mnoc_regmap_config = {
        .reg_bits       = 32,
        .reg_stride     = 4,
        .val_bits       = 32,
-       .max_register   = 0x20000,
+       .max_register   = 0x1c000,
        .fast_io        = true
 };
 
index 8af6392..02b0240 100644 (file)
@@ -3644,7 +3644,7 @@ EXPORT_SYMBOL_GPL(md_rdev_init);
  */
 static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
 {
-       static struct md_rdev *claim_rdev; /* just for claiming the bdev */
+       static struct md_rdev claim_rdev; /* just for claiming the bdev */
        struct md_rdev *rdev;
        sector_t size;
        int err;
@@ -3662,7 +3662,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
 
        rdev->bdev = blkdev_get_by_dev(newdev,
                        FMODE_READ | FMODE_WRITE | FMODE_EXCL,
-                       super_format == -2 ? claim_rdev : rdev);
+                       super_format == -2 ? &claim_rdev : rdev);
        if (IS_ERR(rdev->bdev)) {
                pr_warn("md: could not open device unknown-block(%u,%u).\n",
                        MAJOR(newdev), MINOR(newdev));
index 9c49d00..ea6e9e1 100644 (file)
@@ -47,19 +47,17 @@ static int atmel_ramc_probe(struct platform_device *pdev)
        caps = of_device_get_match_data(&pdev->dev);
 
        if (caps->has_ddrck) {
-               clk = devm_clk_get(&pdev->dev, "ddrck");
+               clk = devm_clk_get_enabled(&pdev->dev, "ddrck");
                if (IS_ERR(clk))
                        return PTR_ERR(clk);
-               clk_prepare_enable(clk);
        }
 
        if (caps->has_mpddr_clk) {
-               clk = devm_clk_get(&pdev->dev, "mpddr");
+               clk = devm_clk_get_enabled(&pdev->dev, "mpddr");
                if (IS_ERR(clk)) {
                        pr_err("AT91 RAMC: couldn't get mpddr clock\n");
                        return PTR_ERR(clk);
                }
-               clk_prepare_enable(clk);
        }
 
        return 0;
index 8450638..efc6c08 100644 (file)
@@ -280,10 +280,9 @@ static int mvebu_devbus_probe(struct platform_device *pdev)
        if (IS_ERR(devbus->base))
                return PTR_ERR(devbus->base);
 
-       clk = devm_clk_get(&pdev->dev, NULL);
+       clk = devm_clk_get_enabled(&pdev->dev, NULL);
        if (IS_ERR(clk))
                return PTR_ERR(clk);
-       clk_prepare_enable(clk);
 
        /*
         * Obtain clock period in picoseconds,
index 57d9f91..d78f73d 100644 (file)
@@ -1918,7 +1918,8 @@ int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
                }
        }
 
-       if (p->wait_pin > gpmc_nr_waitpins) {
+       if (p->wait_pin != GPMC_WAITPIN_INVALID &&
+           p->wait_pin > gpmc_nr_waitpins) {
                pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
                return -EINVAL;
        }
index 62477e5..7bb73f0 100644 (file)
 #define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16)
 #define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8)
 
-static void tegra186_mc_program_sid(struct tegra_mc *mc)
-{
-       unsigned int i;
-
-       for (i = 0; i < mc->soc->num_clients; i++) {
-               const struct tegra_mc_client *client = &mc->soc->clients[i];
-               u32 override, security;
-
-               override = readl(mc->regs + client->regs.sid.override);
-               security = readl(mc->regs + client->regs.sid.security);
-
-               dev_dbg(mc->dev, "client %s: override: %x security: %x\n",
-                       client->name, override, security);
-
-               dev_dbg(mc->dev, "setting SID %u for %s\n", client->sid,
-                       client->name);
-               writel(client->sid, mc->regs + client->regs.sid.override);
-
-               override = readl(mc->regs + client->regs.sid.override);
-               security = readl(mc->regs + client->regs.sid.security);
-
-               dev_dbg(mc->dev, "client %s: override: %x security: %x\n",
-                       client->name, override, security);
-       }
-}
-
 static int tegra186_mc_probe(struct tegra_mc *mc)
 {
        struct platform_device *pdev = to_platform_device(mc->dev);
@@ -85,8 +59,6 @@ populate:
        if (err < 0)
                return err;
 
-       tegra186_mc_program_sid(mc);
-
        return 0;
 }
 
@@ -95,13 +67,6 @@ static void tegra186_mc_remove(struct tegra_mc *mc)
        of_platform_depopulate(mc->dev);
 }
 
-static int tegra186_mc_resume(struct tegra_mc *mc)
-{
-       tegra186_mc_program_sid(mc);
-
-       return 0;
-}
-
 #if IS_ENABLED(CONFIG_IOMMU_API)
 static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
                                            const struct tegra_mc_client *client,
@@ -173,7 +138,6 @@ static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
 const struct tegra_mc_ops tegra186_mc_ops = {
        .probe = tegra186_mc_probe,
        .remove = tegra186_mc_remove,
-       .resume = tegra186_mc_resume,
        .probe_device = tegra186_mc_probe_device,
        .handle_irq = tegra30_mc_handle_irq,
 };
index c9902a1..5310606 100644 (file)
@@ -321,7 +321,7 @@ static void fastrpc_free_map(struct kref *ref)
                        perm.vmid = QCOM_SCM_VMID_HLOS;
                        perm.perm = QCOM_SCM_PERM_RWX;
                        err = qcom_scm_assign_mem(map->phys, map->size,
-                               &(map->fl->cctx->vmperms[0].vmid), &perm, 1);
+                               &map->fl->cctx->perms, &perm, 1);
                        if (err) {
                                dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
                                                map->phys, map->size, err);
@@ -334,6 +334,13 @@ static void fastrpc_free_map(struct kref *ref)
                dma_buf_put(map->buf);
        }
 
+       if (map->fl) {
+               spin_lock(&map->fl->lock);
+               list_del(&map->node);
+               spin_unlock(&map->fl->lock);
+               map->fl = NULL;
+       }
+
        kfree(map);
 }
 
@@ -343,38 +350,41 @@ static void fastrpc_map_put(struct fastrpc_map *map)
                kref_put(&map->refcount, fastrpc_free_map);
 }
 
-static void fastrpc_map_get(struct fastrpc_map *map)
+static int fastrpc_map_get(struct fastrpc_map *map)
 {
-       if (map)
-               kref_get(&map->refcount);
+       if (!map)
+               return -ENOENT;
+
+       return kref_get_unless_zero(&map->refcount) ? 0 : -ENOENT;
 }
 
 
 static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
-                           struct fastrpc_map **ppmap)
+                           struct fastrpc_map **ppmap, bool take_ref)
 {
+       struct fastrpc_session_ctx *sess = fl->sctx;
        struct fastrpc_map *map = NULL;
+       int ret = -ENOENT;
 
-       mutex_lock(&fl->mutex);
+       spin_lock(&fl->lock);
        list_for_each_entry(map, &fl->maps, node) {
-               if (map->fd == fd) {
-                       *ppmap = map;
-                       mutex_unlock(&fl->mutex);
-                       return 0;
-               }
-       }
-       mutex_unlock(&fl->mutex);
-
-       return -ENOENT;
-}
+               if (map->fd != fd)
+                       continue;
 
-static int fastrpc_map_find(struct fastrpc_user *fl, int fd,
-                           struct fastrpc_map **ppmap)
-{
-       int ret = fastrpc_map_lookup(fl, fd, ppmap);
+               if (take_ref) {
+                       ret = fastrpc_map_get(map);
+                       if (ret) {
+                               dev_dbg(sess->dev, "%s: Failed to get map fd=%d ret=%d\n",
+                                       __func__, fd, ret);
+                               break;
+                       }
+               }
 
-       if (!ret)
-               fastrpc_map_get(*ppmap);
+               *ppmap = map;
+               ret = 0;
+               break;
+       }
+       spin_unlock(&fl->lock);
 
        return ret;
 }
@@ -746,7 +756,7 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
        struct fastrpc_map *map = NULL;
        int err = 0;
 
-       if (!fastrpc_map_find(fl, fd, ppmap))
+       if (!fastrpc_map_lookup(fl, fd, ppmap, true))
                return 0;
 
        map = kzalloc(sizeof(*map), GFP_KERNEL);
@@ -788,10 +798,8 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
                 * If subsystem VMIDs are defined in DTSI, then do
                 * hyp_assign from HLOS to those VM(s)
                 */
-               unsigned int perms = BIT(QCOM_SCM_VMID_HLOS);
-
                map->attr = attr;
-               err = qcom_scm_assign_mem(map->phys, (u64)map->size, &perms,
+               err = qcom_scm_assign_mem(map->phys, (u64)map->size, &fl->cctx->perms,
                                fl->cctx->vmperms, fl->cctx->vmcount);
                if (err) {
                        dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d",
@@ -1070,7 +1078,7 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
        for (i = 0; i < FASTRPC_MAX_FDLIST; i++) {
                if (!fdlist[i])
                        break;
-               if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap))
+               if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap, false))
                        fastrpc_map_put(mmap);
        }
 
@@ -1258,10 +1266,9 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
 
                /* Map if we have any heap VMIDs associated with this ADSP Static Process. */
                if (fl->cctx->vmcount) {
-                       unsigned int perms = BIT(QCOM_SCM_VMID_HLOS);
-
                        err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
-                                                       (u64)fl->cctx->remote_heap->size, &perms,
+                                                       (u64)fl->cctx->remote_heap->size,
+                                                       &fl->cctx->perms,
                                                        fl->cctx->vmperms, fl->cctx->vmcount);
                        if (err) {
                                dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d",
@@ -1309,7 +1316,7 @@ err_invoke:
                perm.perm = QCOM_SCM_PERM_RWX;
                err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
                                                (u64)fl->cctx->remote_heap->size,
-                                               &(fl->cctx->vmperms[0].vmid), &perm, 1);
+                                               &fl->cctx->perms, &perm, 1);
                if (err)
                        dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
                                fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
@@ -1433,12 +1440,7 @@ err_invoke:
        fl->init_mem = NULL;
        fastrpc_buf_free(imem);
 err_alloc:
-       if (map) {
-               spin_lock(&fl->lock);
-               list_del(&map->node);
-               spin_unlock(&fl->lock);
-               fastrpc_map_put(map);
-       }
+       fastrpc_map_put(map);
 err:
        kfree(args);
 
@@ -1514,10 +1516,8 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
                fastrpc_context_put(ctx);
        }
 
-       list_for_each_entry_safe(map, m, &fl->maps, node) {
-               list_del(&map->node);
+       list_for_each_entry_safe(map, m, &fl->maps, node)
                fastrpc_map_put(map);
-       }
 
        list_for_each_entry_safe(buf, b, &fl->mmaps, node) {
                list_del(&buf->node);
@@ -1894,12 +1894,11 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
        /* Add memory to static PD pool, protection thru hypervisor */
        if (req.flags != ADSP_MMAP_REMOTE_HEAP_ADDR && fl->cctx->vmcount) {
                struct qcom_scm_vmperm perm;
-               int err = 0;
 
                perm.vmid = QCOM_SCM_VMID_HLOS;
                perm.perm = QCOM_SCM_PERM_RWX;
                err = qcom_scm_assign_mem(buf->phys, buf->size,
-                       &(fl->cctx->vmperms[0].vmid), &perm, 1);
+                       &fl->cctx->perms, &perm, 1);
                if (err) {
                        dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
                                        buf->phys, buf->size, err);
index 4a08b62..a81b890 100644 (file)
@@ -702,13 +702,15 @@ void *mei_cldev_dma_map(struct mei_cl_device *cldev, u8 buffer_id, size_t size)
        if (cl->state == MEI_FILE_UNINITIALIZED) {
                ret = mei_cl_link(cl);
                if (ret)
-                       goto out;
+                       goto notlinked;
                /* update pointers */
                cl->cldev = cldev;
        }
 
        ret = mei_cl_dma_alloc_and_map(cl, NULL, buffer_id, size);
-out:
+       if (ret)
+               mei_cl_unlink(cl);
+notlinked:
        mutex_unlock(&bus->device_lock);
        if (ret)
                return ERR_PTR(ret);
@@ -758,7 +760,7 @@ int mei_cldev_enable(struct mei_cl_device *cldev)
        if (cl->state == MEI_FILE_UNINITIALIZED) {
                ret = mei_cl_link(cl);
                if (ret)
-                       goto out;
+                       goto notlinked;
                /* update pointers */
                cl->cldev = cldev;
        }
@@ -785,6 +787,9 @@ int mei_cldev_enable(struct mei_cl_device *cldev)
        }
 
 out:
+       if (ret)
+               mei_cl_unlink(cl);
+notlinked:
        mutex_unlock(&bus->device_lock);
 
        return ret;
@@ -1277,7 +1282,6 @@ static void mei_cl_bus_dev_release(struct device *dev)
        mei_cl_flush_queues(cldev->cl, NULL);
        mei_me_cl_put(cldev->me_cl);
        mei_dev_bus_put(cldev->bus);
-       mei_cl_unlink(cldev->cl);
        kfree(cldev->cl);
        kfree(cldev);
 }
index 99966cd..bdc65d5 100644 (file)
 
 #define MEI_DEV_ID_RPL_S      0x7A68  /* Raptor Lake Point S */
 
+#define MEI_DEV_ID_MTL_M      0x7E70  /* Meteor Lake Point M */
+
 /*
  * MEI HW Section
  */
index 704cd0c..5bf0d50 100644 (file)
@@ -118,6 +118,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_RPL_S, MEI_ME_PCH15_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_MTL_M, MEI_ME_PCH15_CFG)},
+
        /* required last entry */
        {0, }
 };
index aa7b05d..4f8d962 100644 (file)
@@ -56,8 +56,6 @@ struct vmci_guest_device {
 
        bool exclusive_vectors;
 
-       struct tasklet_struct datagram_tasklet;
-       struct tasklet_struct bm_tasklet;
        struct wait_queue_head inout_wq;
 
        void *data_buffer;
@@ -304,9 +302,8 @@ static int vmci_check_host_caps(struct pci_dev *pdev)
  * This function assumes that it has exclusive access to the data
  * in register(s) for the duration of the call.
  */
-static void vmci_dispatch_dgs(unsigned long data)
+static void vmci_dispatch_dgs(struct vmci_guest_device *vmci_dev)
 {
-       struct vmci_guest_device *vmci_dev = (struct vmci_guest_device *)data;
        u8 *dg_in_buffer = vmci_dev->data_buffer;
        struct vmci_datagram *dg;
        size_t dg_in_buffer_size = VMCI_MAX_DG_SIZE;
@@ -465,10 +462,8 @@ static void vmci_dispatch_dgs(unsigned long data)
  * Scans the notification bitmap for raised flags, clears them
  * and handles the notifications.
  */
-static void vmci_process_bitmap(unsigned long data)
+static void vmci_process_bitmap(struct vmci_guest_device *dev)
 {
-       struct vmci_guest_device *dev = (struct vmci_guest_device *)data;
-
        if (!dev->notification_bitmap) {
                dev_dbg(dev->dev, "No bitmap present in %s\n", __func__);
                return;
@@ -486,13 +481,13 @@ static irqreturn_t vmci_interrupt(int irq, void *_dev)
        struct vmci_guest_device *dev = _dev;
 
        /*
-        * If we are using MSI-X with exclusive vectors then we simply schedule
-        * the datagram tasklet, since we know the interrupt was meant for us.
+        * If we are using MSI-X with exclusive vectors then we simply call
+        * vmci_dispatch_dgs(), since we know the interrupt was meant for us.
         * Otherwise we must read the ICR to determine what to do.
         */
 
        if (dev->exclusive_vectors) {
-               tasklet_schedule(&dev->datagram_tasklet);
+               vmci_dispatch_dgs(dev);
        } else {
                unsigned int icr;
 
@@ -502,12 +497,12 @@ static irqreturn_t vmci_interrupt(int irq, void *_dev)
                        return IRQ_NONE;
 
                if (icr & VMCI_ICR_DATAGRAM) {
-                       tasklet_schedule(&dev->datagram_tasklet);
+                       vmci_dispatch_dgs(dev);
                        icr &= ~VMCI_ICR_DATAGRAM;
                }
 
                if (icr & VMCI_ICR_NOTIFICATION) {
-                       tasklet_schedule(&dev->bm_tasklet);
+                       vmci_process_bitmap(dev);
                        icr &= ~VMCI_ICR_NOTIFICATION;
                }
 
@@ -536,7 +531,7 @@ static irqreturn_t vmci_interrupt_bm(int irq, void *_dev)
        struct vmci_guest_device *dev = _dev;
 
        /* For MSI-X we can just assume it was meant for us. */
-       tasklet_schedule(&dev->bm_tasklet);
+       vmci_process_bitmap(dev);
 
        return IRQ_HANDLED;
 }
@@ -638,10 +633,6 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
        vmci_dev->iobase = iobase;
        vmci_dev->mmio_base = mmio_base;
 
-       tasklet_init(&vmci_dev->datagram_tasklet,
-                    vmci_dispatch_dgs, (unsigned long)vmci_dev);
-       tasklet_init(&vmci_dev->bm_tasklet,
-                    vmci_process_bitmap, (unsigned long)vmci_dev);
        init_waitqueue_head(&vmci_dev->inout_wq);
 
        if (mmio_base != NULL) {
@@ -808,8 +799,9 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
         * Request IRQ for legacy or MSI interrupts, or for first
         * MSI-X vector.
         */
-       error = request_irq(pci_irq_vector(pdev, 0), vmci_interrupt,
-                           IRQF_SHARED, KBUILD_MODNAME, vmci_dev);
+       error = request_threaded_irq(pci_irq_vector(pdev, 0), NULL,
+                                    vmci_interrupt, IRQF_SHARED,
+                                    KBUILD_MODNAME, vmci_dev);
        if (error) {
                dev_err(&pdev->dev, "Irq %u in use: %d\n",
                        pci_irq_vector(pdev, 0), error);
@@ -823,9 +815,9 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
         * between the vectors.
         */
        if (vmci_dev->exclusive_vectors) {
-               error = request_irq(pci_irq_vector(pdev, 1),
-                                   vmci_interrupt_bm, 0, KBUILD_MODNAME,
-                                   vmci_dev);
+               error = request_threaded_irq(pci_irq_vector(pdev, 1), NULL,
+                                            vmci_interrupt_bm, 0,
+                                            KBUILD_MODNAME, vmci_dev);
                if (error) {
                        dev_err(&pdev->dev,
                                "Failed to allocate irq %u: %d\n",
@@ -833,9 +825,11 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
                        goto err_free_irq;
                }
                if (caps_in_use & VMCI_CAPS_DMA_DATAGRAM) {
-                       error = request_irq(pci_irq_vector(pdev, 2),
-                                           vmci_interrupt_dma_datagram,
-                                           0, KBUILD_MODNAME, vmci_dev);
+                       error = request_threaded_irq(pci_irq_vector(pdev, 2),
+                                                    NULL,
+                                                   vmci_interrupt_dma_datagram,
+                                                    0, KBUILD_MODNAME,
+                                                    vmci_dev);
                        if (error) {
                                dev_err(&pdev->dev,
                                        "Failed to allocate irq %u: %d\n",
@@ -871,8 +865,6 @@ err_free_bm_irq:
 
 err_free_irq:
        free_irq(pci_irq_vector(pdev, 0), vmci_dev);
-       tasklet_kill(&vmci_dev->datagram_tasklet);
-       tasklet_kill(&vmci_dev->bm_tasklet);
 
 err_disable_msi:
        pci_free_irq_vectors(pdev);
@@ -943,9 +935,6 @@ static void vmci_guest_remove_device(struct pci_dev *pdev)
        free_irq(pci_irq_vector(pdev, 0), vmci_dev);
        pci_free_irq_vectors(pdev);
 
-       tasklet_kill(&vmci_dev->datagram_tasklet);
-       tasklet_kill(&vmci_dev->bm_tasklet);
-
        if (vmci_dev->notification_bitmap) {
                /*
                 * The device reset above cleared the bitmap state of the
index 89ef0c8..9e73c34 100644 (file)
 #define ESDHC_TUNING_START_TAP_DEFAULT 0x1
 #define ESDHC_TUNING_START_TAP_MASK    0x7f
 #define ESDHC_TUNING_CMD_CRC_CHECK_DISABLE     (1 << 7)
+#define ESDHC_TUNING_STEP_DEFAULT      0x1
 #define ESDHC_TUNING_STEP_MASK         0x00070000
 #define ESDHC_TUNING_STEP_SHIFT                16
 
@@ -1368,7 +1369,7 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
        struct cqhci_host *cq_host = host->mmc->cqe_private;
-       int tmp;
+       u32 tmp;
 
        if (esdhc_is_usdhc(imx_data)) {
                /*
@@ -1423,17 +1424,24 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
 
                if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
                        tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
-                       tmp |= ESDHC_STD_TUNING_EN |
-                               ESDHC_TUNING_START_TAP_DEFAULT;
-                       if (imx_data->boarddata.tuning_start_tap) {
-                               tmp &= ~ESDHC_TUNING_START_TAP_MASK;
+                       tmp |= ESDHC_STD_TUNING_EN;
+
+                       /*
+                        * ROM code or bootloader may config the start tap
+                        * and step, unmask them first.
+                        */
+                       tmp &= ~(ESDHC_TUNING_START_TAP_MASK | ESDHC_TUNING_STEP_MASK);
+                       if (imx_data->boarddata.tuning_start_tap)
                                tmp |= imx_data->boarddata.tuning_start_tap;
-                       }
+                       else
+                               tmp |= ESDHC_TUNING_START_TAP_DEFAULT;
 
                        if (imx_data->boarddata.tuning_step) {
-                               tmp &= ~ESDHC_TUNING_STEP_MASK;
                                tmp |= imx_data->boarddata.tuning_step
                                        << ESDHC_TUNING_STEP_SHIFT;
+                       } else {
+                               tmp |= ESDHC_TUNING_STEP_DEFAULT
+                                       << ESDHC_TUNING_STEP_SHIFT;
                        }
 
                        /* Disable the CMD CRC check for tuning, if not, need to
index b16e12e..3db9f32 100644 (file)
@@ -1492,9 +1492,11 @@ static int sunxi_mmc_remove(struct platform_device *pdev)
        struct sunxi_mmc_host *host = mmc_priv(mmc);
 
        mmc_remove_host(mmc);
-       pm_runtime_force_suspend(&pdev->dev);
-       disable_irq(host->irq);
-       sunxi_mmc_disable(host);
+       pm_runtime_disable(&pdev->dev);
+       if (!pm_runtime_status_suspended(&pdev->dev)) {
+               disable_irq(host->irq);
+               sunxi_mmc_disable(host);
+       }
        dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
        mmc_free_host(mmc);
 
index 47b54ec..6178a96 100644 (file)
@@ -540,10 +540,10 @@ int ksz9477_fdb_del(struct ksz_device *dev, int port,
                ksz_read32(dev, REG_SW_ALU_VAL_D, &alu_table[3]);
 
                /* clear forwarding port */
-               alu_table[2] &= ~BIT(port);
+               alu_table[1] &= ~BIT(port);
 
                /* if there is no port to forward, clear table */
-               if ((alu_table[2] & ALU_V_PORT_MAP) == 0) {
+               if ((alu_table[1] & ALU_V_PORT_MAP) == 0) {
                        alu_table[0] = 0;
                        alu_table[1] = 0;
                        alu_table[2] = 0;
index 3936543..4030d61 100644 (file)
@@ -524,19 +524,28 @@ static void xgbe_disable_vxlan(struct xgbe_prv_data *pdata)
        netif_dbg(pdata, drv, pdata->netdev, "VXLAN acceleration disabled\n");
 }
 
+static unsigned int xgbe_get_fc_queue_count(struct xgbe_prv_data *pdata)
+{
+       unsigned int max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
+
+       /* From MAC ver 30H the TFCR is per priority, instead of per queue */
+       if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) >= 0x30)
+               return max_q_count;
+       else
+               return min_t(unsigned int, pdata->tx_q_count, max_q_count);
+}
+
 static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata)
 {
-       unsigned int max_q_count, q_count;
        unsigned int reg, reg_val;
-       unsigned int i;
+       unsigned int i, q_count;
 
        /* Clear MTL flow control */
        for (i = 0; i < pdata->rx_q_count; i++)
                XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 0);
 
        /* Clear MAC flow control */
-       max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
-       q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
+       q_count = xgbe_get_fc_queue_count(pdata);
        reg = MAC_Q0TFCR;
        for (i = 0; i < q_count; i++) {
                reg_val = XGMAC_IOREAD(pdata, reg);
@@ -553,9 +562,8 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
 {
        struct ieee_pfc *pfc = pdata->pfc;
        struct ieee_ets *ets = pdata->ets;
-       unsigned int max_q_count, q_count;
        unsigned int reg, reg_val;
-       unsigned int i;
+       unsigned int i, q_count;
 
        /* Set MTL flow control */
        for (i = 0; i < pdata->rx_q_count; i++) {
@@ -579,8 +587,7 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
        }
 
        /* Set MAC flow control */
-       max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
-       q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
+       q_count = xgbe_get_fc_queue_count(pdata);
        reg = MAC_Q0TFCR;
        for (i = 0; i < q_count; i++) {
                reg_val = XGMAC_IOREAD(pdata, reg);
index 0c5c1b1..43fdd11 100644 (file)
@@ -496,6 +496,7 @@ static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata,
        reg |= XGBE_KR_TRAINING_ENABLE;
        reg |= XGBE_KR_TRAINING_START;
        XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+       pdata->kr_start_time = jiffies;
 
        netif_dbg(pdata, link, pdata->netdev,
                  "KR training initiated\n");
@@ -632,6 +633,8 @@ static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
 
        xgbe_switch_mode(pdata);
 
+       pdata->an_result = XGBE_AN_READY;
+
        xgbe_an_restart(pdata);
 
        return XGBE_AN_INCOMPAT_LINK;
@@ -1275,9 +1278,30 @@ static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata)
 static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
 {
        unsigned long link_timeout;
+       unsigned long kr_time;
+       int wait;
 
        link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ);
        if (time_after(jiffies, link_timeout)) {
+               if ((xgbe_cur_mode(pdata) == XGBE_MODE_KR) &&
+                   pdata->phy.autoneg == AUTONEG_ENABLE) {
+                       /* AN restart should not happen while KR training is in progress.
+                        * The while loop ensures no AN restart during KR training,
+                        * waits up to 500ms and AN restart is triggered only if KR
+                        * training is failed.
+                        */
+                       wait = XGBE_KR_TRAINING_WAIT_ITER;
+                       while (wait--) {
+                               kr_time = pdata->kr_start_time +
+                                         msecs_to_jiffies(XGBE_AN_MS_TIMEOUT);
+                               if (time_after(jiffies, kr_time))
+                                       break;
+                               /* AN restart is not required, if AN result is COMPLETE */
+                               if (pdata->an_result == XGBE_AN_COMPLETE)
+                                       return;
+                               usleep_range(10000, 11000);
+                       }
+               }
                netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n");
                xgbe_phy_config_aneg(pdata);
        }
index 71f24cb..7a41367 100644 (file)
 /* Auto-negotiation */
 #define XGBE_AN_MS_TIMEOUT             500
 #define XGBE_LINK_TIMEOUT              5
+#define XGBE_KR_TRAINING_WAIT_ITER     50
 
 #define XGBE_SGMII_AN_LINK_STATUS      BIT(1)
 #define XGBE_SGMII_AN_LINK_SPEED       (BIT(2) | BIT(3))
@@ -1280,6 +1281,7 @@ struct xgbe_prv_data {
        unsigned int parallel_detect;
        unsigned int fec_ability;
        unsigned long an_start;
+       unsigned long kr_start_time;
        enum xgbe_an_mode an_mode;
 
        /* I2C support */
index cbf17fc..ec57312 100644 (file)
@@ -3969,7 +3969,7 @@ void bnxt_ethtool_init(struct bnxt *bp)
                test_info->timeout = HWRM_CMD_TIMEOUT;
        for (i = 0; i < bp->num_tests; i++) {
                char *str = test_info->string[i];
-               char *fw_str = resp->test0_name + i * 32;
+               char *fw_str = resp->test_name[i];
 
                if (i == BNXT_MACLPBK_TEST_IDX) {
                        strcpy(str, "Mac loopback test (offline)");
@@ -3980,14 +3980,9 @@ void bnxt_ethtool_init(struct bnxt *bp)
                } else if (i == BNXT_IRQ_TEST_IDX) {
                        strcpy(str, "Interrupt_test (offline)");
                } else {
-                       strscpy(str, fw_str, ETH_GSTRING_LEN);
-                       strncat(str, " test", ETH_GSTRING_LEN - strlen(str));
-                       if (test_info->offline_mask & (1 << i))
-                               strncat(str, " (offline)",
-                                       ETH_GSTRING_LEN - strlen(str));
-                       else
-                               strncat(str, " (online)",
-                                       ETH_GSTRING_LEN - strlen(str));
+                       snprintf(str, ETH_GSTRING_LEN, "%s test (%s)",
+                                fw_str, test_info->offline_mask & (1 << i) ?
+                                       "offline" : "online");
                }
        }
 
index 2686a71..a540887 100644 (file)
@@ -10249,14 +10249,7 @@ struct hwrm_selftest_qlist_output {
        u8      unused_0;
        __le16  test_timeout;
        u8      unused_1[2];
-       char    test0_name[32];
-       char    test1_name[32];
-       char    test2_name[32];
-       char    test3_name[32];
-       char    test4_name[32];
-       char    test5_name[32];
-       char    test6_name[32];
-       char    test7_name[32];
+       char    test_name[8][32];
        u8      eyescope_target_BER_support;
        #define SELFTEST_QLIST_RESP_EYESCOPE_TARGET_BER_SUPPORT_BER_1E8_SUPPORTED  0x0UL
        #define SELFTEST_QLIST_RESP_EYESCOPE_TARGET_BER_SUPPORT_BER_1E9_SUPPORTED  0x1UL
index 95667b9..72e4282 100644 (file)
@@ -2187,7 +2187,6 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
        bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb) ||
                      skb_is_nonlinear(*skb);
        int padlen = ETH_ZLEN - (*skb)->len;
-       int headroom = skb_headroom(*skb);
        int tailroom = skb_tailroom(*skb);
        struct sk_buff *nskb;
        u32 fcs;
@@ -2201,9 +2200,6 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
                /* FCS could be appeded to tailroom. */
                if (tailroom >= ETH_FCS_LEN)
                        goto add_fcs;
-               /* FCS could be appeded by moving data to headroom. */
-               else if (!cloned && headroom + tailroom >= ETH_FCS_LEN)
-                       padlen = 0;
                /* No room for FCS, need to reallocate skb. */
                else
                        padlen = ETH_FCS_LEN;
@@ -2212,10 +2208,7 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
                padlen += ETH_FCS_LEN;
        }
 
-       if (!cloned && headroom + tailroom >= padlen) {
-               (*skb)->data = memmove((*skb)->head, (*skb)->data, (*skb)->len);
-               skb_set_tail_pointer(*skb, (*skb)->len);
-       } else {
+       if (cloned || tailroom < padlen) {
                nskb = skb_copy_expand(*skb, 0, padlen, GFP_ATOMIC);
                if (!nskb)
                        return -ENOMEM;
index 3a79ead..e96449e 100644 (file)
@@ -2290,14 +2290,14 @@ static void enetc_tx_onestep_tstamp(struct work_struct *work)
 
        priv = container_of(work, struct enetc_ndev_priv, tx_onestep_tstamp);
 
-       netif_tx_lock(priv->ndev);
+       netif_tx_lock_bh(priv->ndev);
 
        clear_bit_unlock(ENETC_TX_ONESTEP_TSTAMP_IN_PROGRESS, &priv->flags);
        skb = skb_dequeue(&priv->tx_skbs);
        if (skb)
                enetc_start_xmit(skb, priv->ndev);
 
-       netif_tx_unlock(priv->ndev);
+       netif_tx_unlock_bh(priv->ndev);
 }
 
 static void enetc_tx_onestep_tstamp_init(struct enetc_ndev_priv *priv)
index 88f8772..8a41ad8 100644 (file)
@@ -1012,7 +1012,6 @@ static void otx2_pool_refill_task(struct work_struct *work)
        rbpool = cq->rbpool;
        free_ptrs = cq->pool_ptrs;
 
-       get_cpu();
        while (cq->pool_ptrs) {
                if (otx2_alloc_rbuf(pfvf, rbpool, &bufptr)) {
                        /* Schedule a WQ if we fails to free atleast half of the
@@ -1032,7 +1031,6 @@ static void otx2_pool_refill_task(struct work_struct *work)
                pfvf->hw_ops->aura_freeptr(pfvf, qidx, bufptr + OTX2_HEAD_ROOM);
                cq->pool_ptrs--;
        }
-       put_cpu();
        cq->refill_task_sched = false;
 }
 
@@ -1370,7 +1368,6 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
        if (err)
                goto fail;
 
-       get_cpu();
        /* Allocate pointers and free them to aura/pool */
        for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) {
                pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx);
@@ -1394,7 +1391,6 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
        }
 
 err_mem:
-       put_cpu();
        return err ? -ENOMEM : 0;
 
 fail:
@@ -1435,21 +1431,18 @@ int otx2_rq_aura_pool_init(struct otx2_nic *pfvf)
        if (err)
                goto fail;
 
-       get_cpu();
        /* Allocate pointers and free them to aura/pool */
        for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) {
                pool = &pfvf->qset.pool[pool_id];
                for (ptr = 0; ptr < num_ptrs; ptr++) {
                        err = otx2_alloc_rbuf(pfvf, pool, &bufptr);
                        if (err)
-                               goto err_mem;
+                               return -ENOMEM;
                        pfvf->hw_ops->aura_freeptr(pfvf, pool_id,
                                                   bufptr + OTX2_HEAD_ROOM);
                }
        }
-err_mem:
-       put_cpu();
-       return err ? -ENOMEM : 0;
+       return 0;
 fail:
        otx2_mbox_reset(&pfvf->mbox.mbox, 0);
        otx2_aura_pool_free(pfvf);
index 5bee3c3..3d22cc6 100644 (file)
@@ -736,8 +736,10 @@ static inline void cn10k_aura_freeptr(void *dev, int aura, u64 buf)
        u64 ptrs[2];
 
        ptrs[1] = buf;
+       get_cpu();
        /* Free only one buffer at time during init and teardown */
        __cn10k_aura_freeptr(pfvf, aura, ptrs, 2);
+       put_cpu();
 }
 
 /* Alloc pointer from pool/aura */
index 6dac76f..09d441e 100644 (file)
@@ -637,7 +637,7 @@ mlx5e_htb_update_children(struct mlx5e_htb *htb, struct mlx5e_qos_node *node,
                if (child->bw_share == old_bw_share)
                        continue;
 
-               err_one = mlx5_qos_update_node(htb->mdev, child->hw_id, child->bw_share,
+               err_one = mlx5_qos_update_node(htb->mdev, child->bw_share,
                                               child->max_average_bw, child->hw_id);
                if (!err && err_one) {
                        err = err_one;
@@ -671,7 +671,7 @@ mlx5e_htb_node_modify(struct mlx5e_htb *htb, u16 classid, u64 rate, u64 ceil,
        mlx5e_htb_convert_rate(htb, rate, node->parent, &bw_share);
        mlx5e_htb_convert_ceil(htb, ceil, &max_average_bw);
 
-       err = mlx5_qos_update_node(htb->mdev, node->parent->hw_id, bw_share,
+       err = mlx5_qos_update_node(htb->mdev, bw_share,
                                   max_average_bw, node->hw_id);
        if (err) {
                NL_SET_ERR_MSG_MOD(extack, "Firmware error when modifying a node.");
index 585bdc8..4ad19c9 100644 (file)
@@ -578,7 +578,6 @@ int mlx5e_mpwrq_validate_xsk(struct mlx5_core_dev *mdev, struct mlx5e_params *pa
 {
        enum mlx5e_mpwrq_umr_mode umr_mode = mlx5e_mpwrq_umr_mode(mdev, xsk);
        u8 page_shift = mlx5e_mpwrq_page_shift(mdev, xsk);
-       bool unaligned = xsk ? xsk->unaligned : false;
        u16 max_mtu_pkts;
 
        if (!mlx5e_check_fragmented_striding_rq_cap(mdev, page_shift, umr_mode))
@@ -591,7 +590,7 @@ int mlx5e_mpwrq_validate_xsk(struct mlx5_core_dev *mdev, struct mlx5e_params *pa
         * needed number of WQEs exceeds the maximum.
         */
        max_mtu_pkts = min_t(u8, MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE,
-                            mlx5e_mpwrq_max_log_rq_pkts(mdev, page_shift, unaligned));
+                            mlx5e_mpwrq_max_log_rq_pkts(mdev, page_shift, xsk->unaligned));
        if (params->log_rq_mtu_frames > max_mtu_pkts) {
                mlx5_core_err(mdev, "Current RQ length %d is too big for XSK with given frame size %u\n",
                              1 << params->log_rq_mtu_frames, xsk->chunk_size);
index 1cbd2eb..f2c2c75 100644 (file)
@@ -477,7 +477,6 @@ mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample,
        struct mlx5e_sample_flow *sample_flow;
        struct mlx5e_sample_attr *sample_attr;
        struct mlx5_flow_attr *pre_attr;
-       u32 tunnel_id = attr->tunnel_id;
        struct mlx5_eswitch *esw;
        u32 default_tbl_id;
        u32 obj_id;
@@ -522,7 +521,7 @@ mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample,
        restore_obj.sample.group_id = sample_attr->group_num;
        restore_obj.sample.rate = sample_attr->rate;
        restore_obj.sample.trunc_size = sample_attr->trunc_size;
-       restore_obj.sample.tunnel_id = tunnel_id;
+       restore_obj.sample.tunnel_id = attr->tunnel_id;
        err = mapping_add(esw->offloads.reg_c0_obj_pool, &restore_obj, &obj_id);
        if (err)
                goto err_obj_id;
@@ -548,7 +547,7 @@ mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample,
        /* For decap action, do decap in the original flow table instead of the
         * default flow table.
         */
-       if (tunnel_id)
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
                pre_attr->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
        pre_attr->modify_hdr = sample_flow->restore->modify_hdr;
        pre_attr->flags = MLX5_ATTR_FLAG_SAMPLE;
index a92e19c..8bed9c3 100644 (file)
@@ -122,11 +122,8 @@ struct mlx5e_ipsec_aso {
        u8 ctx[MLX5_ST_SZ_BYTES(ipsec_aso)];
        dma_addr_t dma_addr;
        struct mlx5_aso *aso;
-       /* IPsec ASO caches data on every query call,
-        * so in nested calls, we can use this boolean to save
-        * recursive calls to mlx5e_ipsec_aso_query()
-        */
-       u8 use_cache : 1;
+       /* Protect ASO WQ access, as it is global to whole IPsec */
+       spinlock_t lock;
 };
 
 struct mlx5e_ipsec {
index 8e36142..2461462 100644 (file)
@@ -320,7 +320,6 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work)
        if (ret)
                goto unlock;
 
-       aso->use_cache = true;
        if (attrs->esn_trigger &&
            !MLX5_GET(ipsec_aso, aso->ctx, esn_event_arm)) {
                u32 mode_param = MLX5_GET(ipsec_aso, aso->ctx, mode_parameter);
@@ -333,7 +332,6 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work)
                    !MLX5_GET(ipsec_aso, aso->ctx, hard_lft_arm) ||
                    !MLX5_GET(ipsec_aso, aso->ctx, remove_flow_enable))
                        xfrm_state_check_expire(sa_entry->x);
-       aso->use_cache = false;
 
 unlock:
        spin_unlock(&sa_entry->x->lock);
@@ -398,6 +396,7 @@ int mlx5e_ipsec_aso_init(struct mlx5e_ipsec *ipsec)
                goto err_aso_create;
        }
 
+       spin_lock_init(&aso->lock);
        ipsec->nb.notifier_call = mlx5e_ipsec_event;
        mlx5_notifier_register(mdev, &ipsec->nb);
 
@@ -456,13 +455,12 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
        struct mlx5e_hw_objs *res;
        struct mlx5_aso_wqe *wqe;
        u8 ds_cnt;
+       int ret;
 
        lockdep_assert_held(&sa_entry->x->lock);
-       if (aso->use_cache)
-               return 0;
-
        res = &mdev->mlx5e_res.hw_objs;
 
+       spin_lock_bh(&aso->lock);
        memset(aso->ctx, 0, sizeof(aso->ctx));
        wqe = mlx5_aso_get_wqe(aso->aso);
        ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS);
@@ -477,7 +475,9 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
        mlx5e_ipsec_aso_copy(ctrl, data);
 
        mlx5_aso_post_wqe(aso->aso, false, &wqe->ctrl);
-       return mlx5_aso_poll_cq(aso->aso, false);
+       ret = mlx5_aso_poll_cq(aso->aso, false);
+       spin_unlock_bh(&aso->lock);
+       return ret;
 }
 
 void mlx5e_ipsec_aso_update_curlft(struct mlx5e_ipsec_sa_entry *sa_entry,
index dbadaf1..243d5d7 100644 (file)
@@ -166,6 +166,7 @@ struct mlx5_fs_chains *mlx5e_nic_chains(struct mlx5e_tc_table *tc)
  * it's different than the ht->mutex here.
  */
 static struct lock_class_key tc_ht_lock_key;
+static struct lock_class_key tc_ht_wq_key;
 
 static void mlx5e_put_flow_tunnel_id(struct mlx5e_tc_flow *flow);
 static void free_flow_post_acts(struct mlx5e_tc_flow *flow);
@@ -5182,6 +5183,7 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
                return err;
 
        lockdep_set_class(&tc->ht.mutex, &tc_ht_lock_key);
+       lockdep_init_map(&tc->ht.run_work.lockdep_map, "tc_ht_wq_key", &tc_ht_wq_key, 0);
 
        mapping_id = mlx5_query_nic_system_image_guid(dev);
 
@@ -5288,6 +5290,7 @@ int mlx5e_tc_ht_init(struct rhashtable *tc_ht)
                return err;
 
        lockdep_set_class(&tc_ht->mutex, &tc_ht_lock_key);
+       lockdep_init_map(&tc_ht->run_work.lockdep_map, "tc_ht_wq_key", &tc_ht_wq_key, 0);
 
        return 0;
 }
index 4f8a24d..75015d3 100644 (file)
@@ -22,15 +22,13 @@ struct mlx5_esw_rate_group {
 };
 
 static int esw_qos_tsar_config(struct mlx5_core_dev *dev, u32 *sched_ctx,
-                              u32 parent_ix, u32 tsar_ix,
-                              u32 max_rate, u32 bw_share)
+                              u32 tsar_ix, u32 max_rate, u32 bw_share)
 {
        u32 bitmask = 0;
 
        if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
                return -EOPNOTSUPP;
 
-       MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_ix);
        MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate);
        MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
        bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
@@ -51,7 +49,7 @@ static int esw_qos_group_config(struct mlx5_eswitch *esw, struct mlx5_esw_rate_g
        int err;
 
        err = esw_qos_tsar_config(dev, sched_ctx,
-                                 esw->qos.root_tsar_ix, group->tsar_ix,
+                                 group->tsar_ix,
                                  max_rate, bw_share);
        if (err)
                NL_SET_ERR_MSG_MOD(extack, "E-Switch modify group TSAR element failed");
@@ -67,23 +65,13 @@ static int esw_qos_vport_config(struct mlx5_eswitch *esw,
                                struct netlink_ext_ack *extack)
 {
        u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
-       struct mlx5_esw_rate_group *group = vport->qos.group;
        struct mlx5_core_dev *dev = esw->dev;
-       u32 parent_tsar_ix;
-       void *vport_elem;
        int err;
 
        if (!vport->qos.enabled)
                return -EIO;
 
-       parent_tsar_ix = group ? group->tsar_ix : esw->qos.root_tsar_ix;
-       MLX5_SET(scheduling_context, sched_ctx, element_type,
-                SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
-       vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx,
-                                 element_attributes);
-       MLX5_SET(vport_element, vport_elem, vport_number, vport->vport);
-
-       err = esw_qos_tsar_config(dev, sched_ctx, parent_tsar_ix, vport->qos.esw_tsar_ix,
+       err = esw_qos_tsar_config(dev, sched_ctx, vport->qos.esw_tsar_ix,
                                  max_rate, bw_share);
        if (err) {
                esw_warn(esw->dev,
index 0dfd574..9daf55e 100644 (file)
@@ -1464,6 +1464,7 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
        mlx5_lag_disable_change(esw->dev);
        down_write(&esw->mode_lock);
        mlx5_eswitch_disable_locked(esw);
+       esw->mode = MLX5_ESWITCH_LEGACY;
        up_write(&esw->mode_lock);
        mlx5_lag_enable_change(esw->dev);
 }
index 96417c5..879555b 100644 (file)
@@ -677,6 +677,7 @@ static void mlx5_fw_fatal_reporter_err_work(struct work_struct *work)
        mutex_lock(&dev->intf_state_mutex);
        if (test_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags)) {
                mlx5_core_err(dev, "health works are not permitted at this stage\n");
+               mutex_unlock(&dev->intf_state_mutex);
                return;
        }
        mutex_unlock(&dev->intf_state_mutex);
index df134f6..3d5f2a4 100644 (file)
@@ -2098,7 +2098,7 @@ static void mlx5_core_verify_params(void)
        }
 }
 
-static int __init init(void)
+static int __init mlx5_init(void)
 {
        int err;
 
@@ -2133,7 +2133,7 @@ err_debug:
        return err;
 }
 
-static void __exit cleanup(void)
+static void __exit mlx5_cleanup(void)
 {
        mlx5e_cleanup();
        mlx5_sf_driver_unregister();
@@ -2141,5 +2141,5 @@ static void __exit cleanup(void)
        mlx5_unregister_debugfs();
 }
 
-module_init(init);
-module_exit(cleanup);
+module_init(mlx5_init);
+module_exit(mlx5_cleanup);
index 0777be2..8bce730 100644 (file)
@@ -62,13 +62,12 @@ int mlx5_qos_create_root_node(struct mlx5_core_dev *mdev, u32 *id)
        return mlx5_qos_create_inner_node(mdev, MLX5_QOS_DEFAULT_DWRR_UID, 0, 0, id);
 }
 
-int mlx5_qos_update_node(struct mlx5_core_dev *mdev, u32 parent_id,
+int mlx5_qos_update_node(struct mlx5_core_dev *mdev,
                         u32 bw_share, u32 max_avg_bw, u32 id)
 {
        u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
        u32 bitmask = 0;
 
-       MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_id);
        MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
        MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_avg_bw);
 
index 125e4e4..624ce82 100644 (file)
@@ -23,7 +23,7 @@ int mlx5_qos_create_leaf_node(struct mlx5_core_dev *mdev, u32 parent_id,
 int mlx5_qos_create_inner_node(struct mlx5_core_dev *mdev, u32 parent_id,
                               u32 bw_share, u32 max_avg_bw, u32 *id);
 int mlx5_qos_create_root_node(struct mlx5_core_dev *mdev, u32 *id);
-int mlx5_qos_update_node(struct mlx5_core_dev *mdev, u32 parent_id, u32 bw_share,
+int mlx5_qos_update_node(struct mlx5_core_dev *mdev, u32 bw_share,
                         u32 max_avg_bw, u32 id);
 int mlx5_qos_destroy_node(struct mlx5_core_dev *mdev, u32 id);
 
index cadde20..580c91d 100644 (file)
@@ -1043,11 +1043,6 @@ static int lan966x_probe(struct platform_device *pdev)
                lan966x->base_mac[5] &= 0xf0;
        }
 
-       ports = device_get_named_child_node(&pdev->dev, "ethernet-ports");
-       if (!ports)
-               return dev_err_probe(&pdev->dev, -ENODEV,
-                                    "no ethernet-ports child found\n");
-
        err = lan966x_create_targets(pdev, lan966x);
        if (err)
                return dev_err_probe(&pdev->dev, err,
@@ -1125,6 +1120,11 @@ static int lan966x_probe(struct platform_device *pdev)
                }
        }
 
+       ports = device_get_named_child_node(&pdev->dev, "ethernet-ports");
+       if (!ports)
+               return dev_err_probe(&pdev->dev, -ENODEV,
+                                    "no ethernet-ports child found\n");
+
        /* init switch */
        lan966x_init(lan966x);
        lan966x_stats_init(lan966x);
@@ -1162,6 +1162,8 @@ static int lan966x_probe(struct platform_device *pdev)
                        goto cleanup_ports;
        }
 
+       fwnode_handle_put(ports);
+
        lan966x_mdb_init(lan966x);
        err = lan966x_fdb_init(lan966x);
        if (err)
@@ -1191,6 +1193,7 @@ cleanup_fdb:
        lan966x_fdb_deinit(lan966x);
 
 cleanup_ports:
+       fwnode_handle_put(ports);
        fwnode_handle_put(portnp);
 
        lan966x_cleanup_ports(lan966x);
index 9c2d40f..413f660 100644 (file)
@@ -186,11 +186,25 @@ static void dwmac5_handle_dma_err(struct net_device *ndev,
 int dwmac5_safety_feat_config(void __iomem *ioaddr, unsigned int asp,
                              struct stmmac_safety_feature_cfg *safety_feat_cfg)
 {
+       struct stmmac_safety_feature_cfg all_safety_feats = {
+               .tsoee = 1,
+               .mrxpee = 1,
+               .mestee = 1,
+               .mrxee = 1,
+               .mtxee = 1,
+               .epsi = 1,
+               .edpp = 1,
+               .prtyen = 1,
+               .tmouten = 1,
+       };
        u32 value;
 
        if (!asp)
                return -EINVAL;
 
+       if (!safety_feat_cfg)
+               safety_feat_cfg = &all_safety_feats;
+
        /* 1. Enable Safety Features */
        value = readl(ioaddr + MTL_ECC_CONTROL);
        value |= MEEAO; /* MTL ECC Error Addr Status Override */
index f453b0d..35c8dd9 100644 (file)
@@ -551,16 +551,16 @@ static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data)
                p = (char *)priv + offsetof(struct stmmac_priv,
                                            xstats.txq_stats[q].tx_pkt_n);
                for (stat = 0; stat < STMMAC_TXQ_STATS; stat++) {
-                       *data++ = (*(u64 *)p);
-                       p += sizeof(u64 *);
+                       *data++ = (*(unsigned long *)p);
+                       p += sizeof(unsigned long);
                }
        }
        for (q = 0; q < rx_cnt; q++) {
                p = (char *)priv + offsetof(struct stmmac_priv,
                                            xstats.rxq_stats[q].rx_pkt_n);
                for (stat = 0; stat < STMMAC_RXQ_STATS; stat++) {
-                       *data++ = (*(u64 *)p);
-                       p += sizeof(u64 *);
+                       *data++ = (*(unsigned long *)p);
+                       p += sizeof(unsigned long);
                }
        }
 }
index c6951c9..b7e5af5 100644 (file)
@@ -1150,6 +1150,11 @@ static int stmmac_init_phy(struct net_device *dev)
                int addr = priv->plat->phy_addr;
                struct phy_device *phydev;
 
+               if (addr < 0) {
+                       netdev_err(priv->dev, "no phy found\n");
+                       return -ENODEV;
+               }
+
                phydev = mdiobus_get_phy(priv->mii, addr);
                if (!phydev) {
                        netdev_err(priv->dev, "no phy at addr %d\n", addr);
index d458a35..c1b3977 100644 (file)
@@ -127,6 +127,16 @@ out_power_put:
        return IRQ_HANDLED;
 }
 
+void ipa_interrupt_irq_disable(struct ipa *ipa)
+{
+       disable_irq(ipa->interrupt->irq);
+}
+
+void ipa_interrupt_irq_enable(struct ipa *ipa)
+{
+       enable_irq(ipa->interrupt->irq);
+}
+
 /* Common function used to enable/disable TX_SUSPEND for an endpoint */
 static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
                                          u32 endpoint_id, bool enable)
index f31fd99..8a1bd5b 100644 (file)
@@ -86,6 +86,22 @@ void ipa_interrupt_suspend_clear_all(struct ipa_interrupt *interrupt);
 void ipa_interrupt_simulate_suspend(struct ipa_interrupt *interrupt);
 
 /**
+ * ipa_interrupt_irq_enable() - Enable IPA interrupts
+ * @ipa:       IPA pointer
+ *
+ * This enables the IPA interrupt line
+ */
+void ipa_interrupt_irq_enable(struct ipa *ipa);
+
+/**
+ * ipa_interrupt_irq_disable() - Disable IPA interrupts
+ * @ipa:       IPA pointer
+ *
+ * This disables the IPA interrupt line
+ */
+void ipa_interrupt_irq_disable(struct ipa *ipa);
+
+/**
  * ipa_interrupt_config() - Configure the IPA interrupt framework
  * @ipa:       IPA pointer
  *
index 8420f93..8057be8 100644 (file)
@@ -181,6 +181,17 @@ static int ipa_suspend(struct device *dev)
 
        __set_bit(IPA_POWER_FLAG_SYSTEM, ipa->power->flags);
 
+       /* Increment the disable depth to ensure that the IRQ won't
+        * be re-enabled until the matching _enable call in
+        * ipa_resume(). We do this to ensure that the interrupt
+        * handler won't run whilst PM runtime is disabled.
+        *
+        * Note that disabling the IRQ is NOT the same as disabling
+        * irq wake. If wakeup is enabled for the IPA then the IRQ
+        * will still cause the system to wake up, see irq_set_irq_wake().
+        */
+       ipa_interrupt_irq_disable(ipa);
+
        return pm_runtime_force_suspend(dev);
 }
 
@@ -193,6 +204,12 @@ static int ipa_resume(struct device *dev)
 
        __clear_bit(IPA_POWER_FLAG_SYSTEM, ipa->power->flags);
 
+       /* Now that PM runtime is enabled again it's safe
+        * to turn the IRQ back on and process any data
+        * that was received during suspend.
+        */
+       ipa_interrupt_irq_enable(ipa);
+
        return ret;
 }
 
index 1cd604c..16e021b 100644 (file)
@@ -108,7 +108,12 @@ EXPORT_SYMBOL(mdiobus_unregister_device);
 
 struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr)
 {
-       struct mdio_device *mdiodev = bus->mdio_map[addr];
+       struct mdio_device *mdiodev;
+
+       if (addr < 0 || addr >= ARRAY_SIZE(bus->mdio_map))
+               return NULL;
+
+       mdiodev = bus->mdio_map[addr];
 
        if (!mdiodev)
                return NULL;
index fcd43d6..d10606f 100644 (file)
@@ -1044,7 +1044,6 @@ static int team_port_enter(struct team *team, struct team_port *port)
                        goto err_port_enter;
                }
        }
-       port->dev->priv_flags |= IFF_NO_ADDRCONF;
 
        return 0;
 
@@ -1058,7 +1057,6 @@ static void team_port_leave(struct team *team, struct team_port *port)
 {
        if (team->ops.port_leave)
                team->ops.port_leave(team, port);
-       port->dev->priv_flags &= ~IFF_NO_ADDRCONF;
        dev_put(team->dev);
 }
 
index 5a53e63..3164451 100644 (file)
@@ -413,7 +413,7 @@ static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                /* ignore the CRC length */
                len = (skb->data[1] | (skb->data[2] << 8)) - 4;
 
-               if (len > ETH_FRAME_LEN || len > skb->len)
+               if (len > ETH_FRAME_LEN || len > skb->len || len < 0)
                        return 0;
 
                /* the last packet of current skb */
index 7723b2a..18b3de8 100644 (file)
@@ -1877,8 +1877,10 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
         */
        if (sq->vq->num_free < 2+MAX_SKB_FRAGS) {
                netif_stop_subqueue(dev, qnum);
-               if (!use_napi &&
-                   unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
+               if (use_napi) {
+                       if (unlikely(!virtqueue_enable_cb_delayed(sq->vq)))
+                               virtqueue_napi_schedule(&sq->napi, sq->vq);
+               } else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
                        /* More just got used, free them then recheck. */
                        free_old_xmit_skbs(sq, false);
                        if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
index 22edea6..1c53b55 100644 (file)
@@ -1243,9 +1243,11 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
 free_dev:
        free_netdev(dev);
 undo_uhdlc_init:
-       iounmap(utdm->siram);
+       if (utdm)
+               iounmap(utdm->siram);
 unmap_si_regs:
-       iounmap(utdm->si_regs);
+       if (utdm)
+               iounmap(utdm->si_regs);
 free_utdm:
        if (uhdlc_priv->tsa)
                kfree(utdm);
index bff3128..b115902 100644 (file)
@@ -7937,6 +7937,9 @@ cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
        struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
 
+       if (chan->flags & IEEE80211_CHAN_DISABLED)
+               return -EINVAL;
+
        /* set_channel */
        chspec = channel_to_chanspec(&cfg->d11inf, chan);
        if (chspec != INVCHANSPEC) {
@@ -7961,7 +7964,7 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
        struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
        struct brcmf_dump_survey survey = {};
        struct ieee80211_supported_band *band;
-       struct ieee80211_channel *chan;
+       enum nl80211_band band_id;
        struct cca_msrmnt_query req;
        u32 noise;
        int err;
@@ -7974,26 +7977,25 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
                return -EBUSY;
        }
 
-       band = wiphy->bands[NL80211_BAND_2GHZ];
-       if (band && idx >= band->n_channels) {
-               idx -= band->n_channels;
-               band = NULL;
-       }
+       for (band_id = 0; band_id < NUM_NL80211_BANDS; band_id++) {
+               band = wiphy->bands[band_id];
+               if (!band)
+                       continue;
+               if (idx >= band->n_channels) {
+                       idx -= band->n_channels;
+                       continue;
+               }
 
-       if (!band || idx >= band->n_channels) {
-               band = wiphy->bands[NL80211_BAND_5GHZ];
-               if (idx >= band->n_channels)
-                       return -ENOENT;
+               info->channel = &band->channels[idx];
+               break;
        }
+       if (band_id == NUM_NL80211_BANDS)
+               return -ENOENT;
 
        /* Setting current channel to the requested channel */
-       chan = &band->channels[idx];
-       err = cfg80211_set_channel(wiphy, ndev, chan, NL80211_CHAN_HT20);
-       if (err) {
-               info->channel = chan;
-               info->filled = 0;
+       info->filled = 0;
+       if (cfg80211_set_channel(wiphy, ndev, info->channel, NL80211_CHAN_HT20))
                return 0;
-       }
 
        /* Disable mpc */
        brcmf_set_mpc(ifp, 0);
@@ -8028,7 +8030,6 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
        if (err)
                goto exit;
 
-       info->channel = chan;
        info->noise = noise;
        info->time = ACS_MSRMNT_DELAY;
        info->time_busy = ACS_MSRMNT_DELAY - survey.idle;
@@ -8040,7 +8041,7 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
                SURVEY_INFO_TIME_TX;
 
        brcmf_dbg(INFO, "OBSS dump: channel %d: survey duration %d\n",
-                 ieee80211_frequency_to_channel(chan->center_freq),
+                 ieee80211_frequency_to_channel(info->channel->center_freq),
                  ACS_MSRMNT_DELAY);
        brcmf_dbg(INFO, "noise(%d) busy(%llu) rx(%llu) tx(%llu)\n",
                  info->noise, info->time_busy, info->time_rx, info->time_tx);
index ae57a9a..b67f6d0 100644 (file)
@@ -1228,7 +1228,7 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
                                BRCMF_NROF_H2D_COMMON_MSGRINGS;
                max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS;
        }
-       if (max_flowrings > 256) {
+       if (max_flowrings > 512) {
                brcmf_err(bus, "invalid max_flowrings(%d)\n", max_flowrings);
                return -EIO;
        }
index f795548..0616181 100644 (file)
@@ -206,71 +206,103 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
 }
 
 static int
+mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+                   struct mt76_queue_buf *buf, void *data)
+{
+       struct mt76_desc *desc = &q->desc[q->head];
+       struct mt76_queue_entry *entry = &q->entry[q->head];
+       struct mt76_txwi_cache *txwi = NULL;
+       u32 buf1 = 0, ctrl;
+       int idx = q->head;
+       int rx_token;
+
+       ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
+
+       if ((q->flags & MT_QFLAG_WED) &&
+           FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) {
+               txwi = mt76_get_rxwi(dev);
+               if (!txwi)
+                       return -ENOMEM;
+
+               rx_token = mt76_rx_token_consume(dev, data, txwi, buf->addr);
+               if (rx_token < 0) {
+                       mt76_put_rxwi(dev, txwi);
+                       return -ENOMEM;
+               }
+
+               buf1 |= FIELD_PREP(MT_DMA_CTL_TOKEN, rx_token);
+               ctrl |= MT_DMA_CTL_TO_HOST;
+       }
+
+       WRITE_ONCE(desc->buf0, cpu_to_le32(buf->addr));
+       WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
+       WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
+       WRITE_ONCE(desc->info, 0);
+
+       entry->dma_addr[0] = buf->addr;
+       entry->dma_len[0] = buf->len;
+       entry->txwi = txwi;
+       entry->buf = data;
+       entry->wcid = 0xffff;
+       entry->skip_buf1 = true;
+       q->head = (q->head + 1) % q->ndesc;
+       q->queued++;
+
+       return idx;
+}
+
+static int
 mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
                 struct mt76_queue_buf *buf, int nbufs, u32 info,
                 struct sk_buff *skb, void *txwi)
 {
        struct mt76_queue_entry *entry;
        struct mt76_desc *desc;
-       u32 ctrl;
        int i, idx = -1;
+       u32 ctrl, next;
+
+       if (txwi) {
+               q->entry[q->head].txwi = DMA_DUMMY_DATA;
+               q->entry[q->head].skip_buf0 = true;
+       }
 
        for (i = 0; i < nbufs; i += 2, buf += 2) {
                u32 buf0 = buf[0].addr, buf1 = 0;
 
                idx = q->head;
-               q->head = (q->head + 1) % q->ndesc;
+               next = (q->head + 1) % q->ndesc;
 
                desc = &q->desc[idx];
                entry = &q->entry[idx];
 
-               if ((q->flags & MT_QFLAG_WED) &&
-                   FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) {
-                       struct mt76_txwi_cache *t = txwi;
-                       int rx_token;
-
-                       if (!t)
-                               return -ENOMEM;
-
-                       rx_token = mt76_rx_token_consume(dev, (void *)skb, t,
-                                                        buf[0].addr);
-                       buf1 |= FIELD_PREP(MT_DMA_CTL_TOKEN, rx_token);
-                       ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len) |
-                              MT_DMA_CTL_TO_HOST;
-               } else {
-                       if (txwi) {
-                               q->entry[q->head].txwi = DMA_DUMMY_DATA;
-                               q->entry[q->head].skip_buf0 = true;
-                       }
-
-                       if (buf[0].skip_unmap)
-                               entry->skip_buf0 = true;
-                       entry->skip_buf1 = i == nbufs - 1;
-
-                       entry->dma_addr[0] = buf[0].addr;
-                       entry->dma_len[0] = buf[0].len;
-
-                       ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
-                       if (i < nbufs - 1) {
-                               entry->dma_addr[1] = buf[1].addr;
-                               entry->dma_len[1] = buf[1].len;
-                               buf1 = buf[1].addr;
-                               ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len);
-                               if (buf[1].skip_unmap)
-                                       entry->skip_buf1 = true;
-                       }
-
-                       if (i == nbufs - 1)
-                               ctrl |= MT_DMA_CTL_LAST_SEC0;
-                       else if (i == nbufs - 2)
-                               ctrl |= MT_DMA_CTL_LAST_SEC1;
+               if (buf[0].skip_unmap)
+                       entry->skip_buf0 = true;
+               entry->skip_buf1 = i == nbufs - 1;
+
+               entry->dma_addr[0] = buf[0].addr;
+               entry->dma_len[0] = buf[0].len;
+
+               ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
+               if (i < nbufs - 1) {
+                       entry->dma_addr[1] = buf[1].addr;
+                       entry->dma_len[1] = buf[1].len;
+                       buf1 = buf[1].addr;
+                       ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len);
+                       if (buf[1].skip_unmap)
+                               entry->skip_buf1 = true;
                }
 
+               if (i == nbufs - 1)
+                       ctrl |= MT_DMA_CTL_LAST_SEC0;
+               else if (i == nbufs - 2)
+                       ctrl |= MT_DMA_CTL_LAST_SEC1;
+
                WRITE_ONCE(desc->buf0, cpu_to_le32(buf0));
                WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
                WRITE_ONCE(desc->info, cpu_to_le32(info));
                WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
 
+               q->head = next;
                q->queued++;
        }
 
@@ -577,17 +609,9 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
        spin_lock_bh(&q->lock);
 
        while (q->queued < q->ndesc - 1) {
-               struct mt76_txwi_cache *t = NULL;
                struct mt76_queue_buf qbuf;
                void *buf = NULL;
 
-               if ((q->flags & MT_QFLAG_WED) &&
-                   FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) {
-                       t = mt76_get_rxwi(dev);
-                       if (!t)
-                               break;
-               }
-
                buf = page_frag_alloc(rx_page, q->buf_size, GFP_ATOMIC);
                if (!buf)
                        break;
@@ -601,7 +625,12 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
                qbuf.addr = addr + offset;
                qbuf.len = len - offset;
                qbuf.skip_unmap = false;
-               mt76_dma_add_buf(dev, q, &qbuf, 1, 0, buf, t);
+               if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) {
+                       dma_unmap_single(dev->dma_dev, addr, len,
+                                        DMA_FROM_DEVICE);
+                       skb_free_frag(buf);
+                       break;
+               }
                frames++;
        }
 
index 0a95c3d..8388e2a 100644 (file)
@@ -653,6 +653,13 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
 
                desc->buf0 = cpu_to_le32(phy_addr);
                token = mt76_rx_token_consume(&dev->mt76, ptr, t, phy_addr);
+               if (token < 0) {
+                       dma_unmap_single(dev->mt76.dma_dev, phy_addr,
+                                        wed->wlan.rx_size, DMA_TO_DEVICE);
+                       skb_free_frag(ptr);
+                       goto unmap;
+               }
+
                desc->token |= cpu_to_le32(FIELD_PREP(MT_DMA_CTL_TOKEN,
                                                      token));
                desc++;
index 24568b9..1f309d0 100644 (file)
@@ -764,11 +764,12 @@ int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
        spin_lock_bh(&dev->rx_token_lock);
        token = idr_alloc(&dev->rx_token, t, 0, dev->rx_token_size,
                          GFP_ATOMIC);
+       if (token >= 0) {
+               t->ptr = ptr;
+               t->dma_addr = phys;
+       }
        spin_unlock_bh(&dev->rx_token_lock);
 
-       t->ptr = ptr;
-       t->dma_addr = phys;
-
        return token;
 }
 EXPORT_SYMBOL_GPL(mt76_rx_token_consume);
index 82a7458..bf72e5f 100644 (file)
@@ -696,8 +696,8 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len)
                struct rndis_query      *get;
                struct rndis_query_c    *get_c;
        } u;
-       int ret, buflen;
-       int resplen, respoffs, copylen;
+       int ret;
+       size_t buflen, resplen, respoffs, copylen;
 
        buflen = *len + sizeof(*u.get);
        if (buflen < CONTROL_BUFFER_SIZE)
@@ -732,22 +732,15 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len)
 
                if (respoffs > buflen) {
                        /* Device returned data offset outside buffer, error. */
-                       netdev_dbg(dev->net, "%s(%s): received invalid "
-                               "data offset: %d > %d\n", __func__,
-                               oid_to_string(oid), respoffs, buflen);
+                       netdev_dbg(dev->net,
+                                  "%s(%s): received invalid data offset: %zu > %zu\n",
+                                  __func__, oid_to_string(oid), respoffs, buflen);
 
                        ret = -EINVAL;
                        goto exit_unlock;
                }
 
-               if ((resplen + respoffs) > buflen) {
-                       /* Device would have returned more data if buffer would
-                        * have been big enough. Copy just the bits that we got.
-                        */
-                       copylen = buflen - respoffs;
-               } else {
-                       copylen = resplen;
-               }
+               copylen = min(resplen, buflen - respoffs);
 
                if (copylen > *len)
                        copylen = *len;
index bf1c60e..b317ce6 100644 (file)
@@ -829,7 +829,23 @@ static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown)
                        apple_nvme_remove_cq(anv);
                }
 
-               nvme_disable_ctrl(&anv->ctrl, shutdown);
+               /*
+                * Always disable the NVMe controller after shutdown.
+                * We need to do this to bring it back up later anyway, and we
+                * can't do it while the firmware is not running (e.g. in the
+                * resume reset path before RTKit is initialized), so for Apple
+                * controllers it makes sense to unconditionally do it here.
+                * Additionally, this sequence of events is reliable, while
+                * others (like disabling after bringing back the firmware on
+                * resume) seem to run into trouble under some circumstances.
+                *
+                * Both U-Boot and m1n1 also use this convention (i.e. an ANS
+                * NVMe controller is handed off with firmware shut down, in an
+                * NVMe disabled state, after a clean shutdown).
+                */
+               if (shutdown)
+                       nvme_disable_ctrl(&anv->ctrl, shutdown);
+               nvme_disable_ctrl(&anv->ctrl, false);
        }
 
        WRITE_ONCE(anv->ioq.enabled, false);
@@ -985,11 +1001,11 @@ static void apple_nvme_reset_work(struct work_struct *work)
                goto out;
        }
 
-       if (anv->ctrl.ctrl_config & NVME_CC_ENABLE)
-               apple_nvme_disable(anv, false);
-
        /* RTKit must be shut down cleanly for the (soft)-reset to work */
        if (apple_rtkit_is_running(anv->rtk)) {
+               /* reset the controller if it is enabled */
+               if (anv->ctrl.ctrl_config & NVME_CC_ENABLE)
+                       apple_nvme_disable(anv, false);
                dev_dbg(anv->dev, "Trying to shut down RTKit before reset.");
                ret = apple_rtkit_shutdown(anv->rtk);
                if (ret)
index a2553b7..1ff8843 100644 (file)
@@ -1362,7 +1362,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
        else
                nvme_poll_irqdisable(nvmeq);
 
-       if (blk_mq_request_completed(req)) {
+       if (blk_mq_rq_state(req) != MQ_RQ_IN_FLIGHT) {
                dev_warn(dev->ctrl.device,
                         "I/O %d QID %d timeout, completion polled\n",
                         req->tag, nvmeq->qid);
index 7585e80..afc6355 100644 (file)
@@ -255,7 +255,7 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
                imx8_phy->perst =
                        devm_reset_control_get_exclusive(dev, "perst");
                if (IS_ERR(imx8_phy->perst))
-                       dev_err_probe(dev, PTR_ERR(imx8_phy->perst),
+                       return dev_err_probe(dev, PTR_ERR(imx8_phy->perst),
                                      "Failed to get PCIE PHY PERST control\n");
        }
 
index 95c6dbb..ce511ad 100644 (file)
@@ -99,6 +99,7 @@ static int can_transceiver_phy_probe(struct platform_device *pdev)
        struct gpio_desc *standby_gpio;
        struct gpio_desc *enable_gpio;
        u32 max_bitrate = 0;
+       int err;
 
        can_transceiver_phy = devm_kzalloc(dev, sizeof(struct can_transceiver_phy), GFP_KERNEL);
        if (!can_transceiver_phy)
@@ -124,8 +125,8 @@ static int can_transceiver_phy_probe(struct platform_device *pdev)
                return PTR_ERR(phy);
        }
 
-       device_property_read_u32(dev, "max-bitrate", &max_bitrate);
-       if (!max_bitrate)
+       err = device_property_read_u32(dev, "max-bitrate", &max_bitrate);
+       if ((err != -EINVAL) && !max_bitrate)
                dev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit\n");
        phy->attrs.max_link_rate = max_bitrate;
 
index 8807e59..a52a9bf 100644 (file)
@@ -401,26 +401,13 @@ static const struct hsphy_init_seq init_seq_femtophy[] = {
        HSPHY_INIT_CFG(0x90, 0x60, 0),
 };
 
-static const struct hsphy_init_seq init_seq_mdm9607[] = {
-       HSPHY_INIT_CFG(0x80, 0x44, 0),
-       HSPHY_INIT_CFG(0x81, 0x38, 0),
-       HSPHY_INIT_CFG(0x82, 0x24, 0),
-       HSPHY_INIT_CFG(0x83, 0x13, 0),
-};
-
 static const struct hsphy_data hsphy_data_femtophy = {
        .init_seq = init_seq_femtophy,
        .init_seq_num = ARRAY_SIZE(init_seq_femtophy),
 };
 
-static const struct hsphy_data hsphy_data_mdm9607 = {
-       .init_seq = init_seq_mdm9607,
-       .init_seq_num = ARRAY_SIZE(init_seq_mdm9607),
-};
-
 static const struct of_device_id qcom_snps_hsphy_match[] = {
        { .compatible = "qcom,usb-hs-28nm-femtophy", .data = &hsphy_data_femtophy, },
-       { .compatible = "qcom,usb-hs-28nm-mdm9607", .data = &hsphy_data_mdm9607, },
        { },
 };
 MODULE_DEVICE_TABLE(of, qcom_snps_hsphy_match);
index ec6594e..e7588a9 100644 (file)
@@ -126,7 +126,7 @@ r8a779f0_eth_serdes_chan_setting(struct r8a779f0_eth_serdes_channel *channel)
                r8a779f0_eth_serdes_write32(channel->addr, 0x0160, 0x180, 0x0007);
                r8a779f0_eth_serdes_write32(channel->addr, 0x01ac, 0x180, 0x0000);
                r8a779f0_eth_serdes_write32(channel->addr, 0x00c4, 0x180, 0x0310);
-               r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x380, 0x0101);
+               r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x180, 0x0101);
                ret = r8a779f0_eth_serdes_reg_wait(channel, 0x00c8, 0x0180, BIT(0), 0);
                if (ret)
                        return ret;
index e6ededc..a0bc10a 100644 (file)
@@ -485,8 +485,10 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
                return ret;
 
        ret = property_enable(base, &rport->port_cfg->phy_sus, false);
-       if (ret)
+       if (ret) {
+               clk_disable_unprepare(rphy->clk480m);
                return ret;
+       }
 
        /* waiting for the utmi_clk to become stable */
        usleep_range(1500, 2000);
index e827b79..56de410 100644 (file)
@@ -254,6 +254,9 @@ static int sp_usb_phy_probe(struct platform_device *pdev)
                return PTR_ERR(usbphy->phy_regs);
 
        usbphy->moon4_res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "moon4");
+       if (!usbphy->moon4_res_mem)
+               return -EINVAL;
+
        usbphy->moon4_regs = devm_ioremap(&pdev->dev, usbphy->moon4_res_mem->start,
                                          resource_size(usbphy->moon4_res_mem));
        if (!usbphy->moon4_regs)
index 15a3bcf..b905902 100644 (file)
@@ -23,7 +23,7 @@ config PHY_DM816X_USB
 
 config PHY_AM654_SERDES
        tristate "TI AM654 SERDES support"
-       depends on OF && ARCH_K3 || COMPILE_TEST
+       depends on OF && (ARCH_K3 || COMPILE_TEST)
        depends on COMMON_CLK
        select GENERIC_PHY
        select MULTIPLEXER
@@ -35,7 +35,7 @@ config PHY_AM654_SERDES
 
 config PHY_J721E_WIZ
        tristate "TI J721E WIZ (SERDES Wrapper) support"
-       depends on OF && ARCH_K3 || COMPILE_TEST
+       depends on OF && (ARCH_K3 || COMPILE_TEST)
        depends on HAS_IOMEM && OF_ADDRESS
        depends on COMMON_CLK
        select GENERIC_PHY
index 3106a21..d7b244d 100644 (file)
@@ -6,9 +6,10 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/gpio/driver.h>
 #include <linux/pinctrl/pinctrl.h>
+
 #include <linux/mfd/abx500/ab8500.h>
+
 #include "pinctrl-abx500.h"
 
 /* All the pins that can be used for GPIO and some other functions */
index b93af1f..45aa958 100644 (file)
@@ -6,9 +6,10 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/gpio/driver.h>
 #include <linux/pinctrl/pinctrl.h>
+
 #include <linux/mfd/abx500/ab8500.h>
+
 #include "pinctrl-abx500.h"
 
 /* All the pins that can be used for GPIO and some other functions */
index 7aa5345..28c3403 100644 (file)
@@ -6,33 +6,37 @@
  *
  * Driver allows to use AxB5xx unused pins to be used as GPIO
  */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/init.h>
+#include <linux/bitops.h>
 #include <linux/err.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
 #include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ab8500.h>
-#include <linux/pinctrl/pinctrl.h>
+
 #include <linux/pinctrl/consumer.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/pinconf-generic.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
 
-#include "pinctrl-abx500.h"
 #include "../core.h"
 #include "../pinconf.h"
 #include "../pinctrl-utils.h"
 
+#include "pinctrl-abx500.h"
+
 /*
  * GPIO registers offset
  * Bank: 0x10
index 90bb12f..d675220 100644 (file)
@@ -2,6 +2,10 @@
 #ifndef PINCTRL_PINCTRL_ABx500_H
 #define PINCTRL_PINCTRL_ABx500_H
 
+#include <linux/types.h>
+
+struct pinctrl_pin_desc;
+
 /* Package definitions */
 #define PINCTRL_AB8500 0
 #define PINCTRL_AB8505 1
index 758d21f..490e095 100644 (file)
@@ -1,6 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/kernel.h>
+#include <linux/types.h>
+
 #include <linux/pinctrl/pinctrl.h>
+
 #include "pinctrl-nomadik.h"
 
 /* All the pins that can be used for GPIO and some other functions */
index c0d7c86..1552222 100644 (file)
@@ -1,6 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/kernel.h>
+#include <linux/types.h>
+
 #include <linux/pinctrl/pinctrl.h>
+
 #include "pinctrl-nomadik.h"
 
 /* All the pins that can be used for GPIO and some other functions */
index f7d0251..86a6380 100644 (file)
@@ -7,30 +7,34 @@
  *   Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
  * Copyright (C) 2011-2013 Linus Walleij <linus.walleij@linaro.org>
  */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
+#include <linux/bitops.h>
 #include <linux/clk.h>
+#include <linux/device.h>
 #include <linux/err.h>
 #include <linux/gpio/driver.h>
-#include <linux/spinlock.h>
+#include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/of_device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
 #include <linux/of_address.h>
-#include <linux/bitops.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-/* Since we request GPIOs from ourself */
-#include <linux/pinctrl/consumer.h>
-#include "pinctrl-nomadik.h"
+
 #include "../core.h"
 #include "../pinctrl-utils.h"
 
+#include "pinctrl-nomadik.h"
+
 /*
  * The GPIO module in the Nomadik family of Systems-on-Chip is an
  * AMBA device, managing 32 pins and alternate functions.  The logic block
@@ -907,8 +911,6 @@ static int nmk_gpio_get_mode(struct nmk_gpio_chip *nmk_chip, int offset)
        return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
 }
 
-#include <linux/seq_file.h>
-
 static void nmk_gpio_dbg_show_one(struct seq_file *s,
        struct pinctrl_dev *pctldev, struct gpio_chip *chip,
        unsigned offset, unsigned gpio)
index 84e2977..1ef2559 100644 (file)
@@ -2,6 +2,11 @@
 #ifndef PINCTRL_PINCTRL_NOMADIK_H
 #define PINCTRL_PINCTRL_NOMADIK_H
 
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <linux/pinctrl/pinctrl.h>
+
 /* Package definitions */
 #define PINCTRL_NMK_STN8815    0
 #define PINCTRL_NMK_DB8500     1
index da974ff..5eeac92 100644 (file)
@@ -926,19 +926,19 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
        RK_MUXROUTE_PMU(0, RK_PB5, 4, 0x0110, WRITE_MASK_VAL(3, 2, 1)), /* PWM1 IO mux M1 */
        RK_MUXROUTE_PMU(0, RK_PC1, 1, 0x0110, WRITE_MASK_VAL(5, 4, 0)), /* PWM2 IO mux M0 */
        RK_MUXROUTE_PMU(0, RK_PB6, 4, 0x0110, WRITE_MASK_VAL(5, 4, 1)), /* PWM2 IO mux M1 */
-       RK_MUXROUTE_PMU(0, RK_PB3, 2, 0x0300, WRITE_MASK_VAL(0, 0, 0)), /* CAN0 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PB3, 2, 0x0300, WRITE_MASK_VAL(0, 0, 0)), /* CAN0 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PA1, 4, 0x0300, WRITE_MASK_VAL(0, 0, 1)), /* CAN0 IO mux M1 */
        RK_MUXROUTE_GRF(1, RK_PA1, 3, 0x0300, WRITE_MASK_VAL(2, 2, 0)), /* CAN1 IO mux M0 */
        RK_MUXROUTE_GRF(4, RK_PC3, 3, 0x0300, WRITE_MASK_VAL(2, 2, 1)), /* CAN1 IO mux M1 */
        RK_MUXROUTE_GRF(4, RK_PB5, 3, 0x0300, WRITE_MASK_VAL(4, 4, 0)), /* CAN2 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PB2, 4, 0x0300, WRITE_MASK_VAL(4, 4, 1)), /* CAN2 IO mux M1 */
        RK_MUXROUTE_GRF(4, RK_PC4, 1, 0x0300, WRITE_MASK_VAL(6, 6, 0)), /* HPDIN IO mux M0 */
-       RK_MUXROUTE_PMU(0, RK_PC2, 2, 0x0300, WRITE_MASK_VAL(6, 6, 1)), /* HPDIN IO mux M1 */
+       RK_MUXROUTE_GRF(0, RK_PC2, 2, 0x0300, WRITE_MASK_VAL(6, 6, 1)), /* HPDIN IO mux M1 */
        RK_MUXROUTE_GRF(3, RK_PB1, 3, 0x0300, WRITE_MASK_VAL(8, 8, 0)), /* GMAC1 IO mux M0 */
        RK_MUXROUTE_GRF(4, RK_PA7, 3, 0x0300, WRITE_MASK_VAL(8, 8, 1)), /* GMAC1 IO mux M1 */
        RK_MUXROUTE_GRF(4, RK_PD1, 1, 0x0300, WRITE_MASK_VAL(10, 10, 0)), /* HDMITX IO mux M0 */
-       RK_MUXROUTE_PMU(0, RK_PC7, 1, 0x0300, WRITE_MASK_VAL(10, 10, 1)), /* HDMITX IO mux M1 */
-       RK_MUXROUTE_PMU(0, RK_PB6, 1, 0x0300, WRITE_MASK_VAL(14, 14, 0)), /* I2C2 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PC7, 1, 0x0300, WRITE_MASK_VAL(10, 10, 1)), /* HDMITX IO mux M1 */
+       RK_MUXROUTE_GRF(0, RK_PB6, 1, 0x0300, WRITE_MASK_VAL(14, 14, 0)), /* I2C2 IO mux M0 */
        RK_MUXROUTE_GRF(4, RK_PB4, 1, 0x0300, WRITE_MASK_VAL(14, 14, 1)), /* I2C2 IO mux M1 */
        RK_MUXROUTE_GRF(1, RK_PA0, 1, 0x0304, WRITE_MASK_VAL(0, 0, 0)), /* I2C3 IO mux M0 */
        RK_MUXROUTE_GRF(3, RK_PB6, 4, 0x0304, WRITE_MASK_VAL(0, 0, 1)), /* I2C3 IO mux M1 */
@@ -964,7 +964,7 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
        RK_MUXROUTE_GRF(4, RK_PC3, 1, 0x0308, WRITE_MASK_VAL(12, 12, 1)), /* PWM15 IO mux M1 */
        RK_MUXROUTE_GRF(3, RK_PD2, 3, 0x0308, WRITE_MASK_VAL(14, 14, 0)), /* SDMMC2 IO mux M0 */
        RK_MUXROUTE_GRF(3, RK_PA5, 5, 0x0308, WRITE_MASK_VAL(14, 14, 1)), /* SDMMC2 IO mux M1 */
-       RK_MUXROUTE_PMU(0, RK_PB5, 2, 0x030c, WRITE_MASK_VAL(0, 0, 0)), /* SPI0 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PB5, 2, 0x030c, WRITE_MASK_VAL(0, 0, 0)), /* SPI0 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PD3, 3, 0x030c, WRITE_MASK_VAL(0, 0, 1)), /* SPI0 IO mux M1 */
        RK_MUXROUTE_GRF(2, RK_PB5, 3, 0x030c, WRITE_MASK_VAL(2, 2, 0)), /* SPI1 IO mux M0 */
        RK_MUXROUTE_GRF(3, RK_PC3, 3, 0x030c, WRITE_MASK_VAL(2, 2, 1)), /* SPI1 IO mux M1 */
@@ -973,8 +973,8 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
        RK_MUXROUTE_GRF(4, RK_PB3, 4, 0x030c, WRITE_MASK_VAL(6, 6, 0)), /* SPI3 IO mux M0 */
        RK_MUXROUTE_GRF(4, RK_PC2, 2, 0x030c, WRITE_MASK_VAL(6, 6, 1)), /* SPI3 IO mux M1 */
        RK_MUXROUTE_GRF(2, RK_PB4, 2, 0x030c, WRITE_MASK_VAL(8, 8, 0)), /* UART1 IO mux M0 */
-       RK_MUXROUTE_PMU(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(8, 8, 1)), /* UART1 IO mux M1 */
-       RK_MUXROUTE_PMU(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(10, 10, 0)), /* UART2 IO mux M0 */
+       RK_MUXROUTE_GRF(3, RK_PD6, 4, 0x030c, WRITE_MASK_VAL(8, 8, 1)), /* UART1 IO mux M1 */
+       RK_MUXROUTE_GRF(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(10, 10, 0)), /* UART2 IO mux M0 */
        RK_MUXROUTE_GRF(1, RK_PD5, 2, 0x030c, WRITE_MASK_VAL(10, 10, 1)), /* UART2 IO mux M1 */
        RK_MUXROUTE_GRF(1, RK_PA1, 2, 0x030c, WRITE_MASK_VAL(12, 12, 0)), /* UART3 IO mux M0 */
        RK_MUXROUTE_GRF(3, RK_PB7, 4, 0x030c, WRITE_MASK_VAL(12, 12, 1)), /* UART3 IO mux M1 */
@@ -1004,13 +1004,13 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
        RK_MUXROUTE_GRF(3, RK_PD6, 5, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */
        RK_MUXROUTE_GRF(4, RK_PA0, 4, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */
        RK_MUXROUTE_GRF(3, RK_PC4, 5, 0x0314, WRITE_MASK_VAL(1, 0, 2)), /* PDM IO mux M2 */
-       RK_MUXROUTE_PMU(0, RK_PA5, 3, 0x0314, WRITE_MASK_VAL(3, 2, 0)), /* PCIE20 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PA5, 3, 0x0314, WRITE_MASK_VAL(3, 2, 0)), /* PCIE20 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PD0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 1)), /* PCIE20 IO mux M1 */
        RK_MUXROUTE_GRF(1, RK_PB0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 2)), /* PCIE20 IO mux M2 */
-       RK_MUXROUTE_PMU(0, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PD2, 4, 0x0314, WRITE_MASK_VAL(5, 4, 1)), /* PCIE30X1 IO mux M1 */
        RK_MUXROUTE_GRF(1, RK_PA5, 4, 0x0314, WRITE_MASK_VAL(5, 4, 2)), /* PCIE30X1 IO mux M2 */
-       RK_MUXROUTE_PMU(0, RK_PA6, 2, 0x0314, WRITE_MASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PA6, 2, 0x0314, WRITE_MASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PD4, 4, 0x0314, WRITE_MASK_VAL(7, 6, 1)), /* PCIE30X2 IO mux M1 */
        RK_MUXROUTE_GRF(4, RK_PC2, 4, 0x0314, WRITE_MASK_VAL(7, 6, 2)), /* PCIE30X2 IO mux M2 */
 };
@@ -2436,10 +2436,19 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
        case RK3308:
        case RK3368:
        case RK3399:
+       case RK3568:
        case RK3588:
                pull_type = bank->pull_type[pin_num / 8];
                data >>= bit;
                data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
+               /*
+                * In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6,
+                * where that pull up value becomes 3.
+                */
+               if (ctrl->type == RK3568 && bank->bank_num == 0 && pin_num >= 27 && pin_num <= 30) {
+                       if (data == 3)
+                               data = 1;
+               }
 
                return rockchip_pull_list[pull_type][data];
        default:
@@ -2497,7 +2506,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
                        }
                }
                /*
-                * In the TRM, pull-up being 1 for everything except the GPIO0_D0-D6,
+                * In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6,
                 * where that pull up value becomes 3.
                 */
                if (ctrl->type == RK3568 && bank->bank_num == 0 && pin_num >= 27 && pin_num <= 30) {
index 2b3335a..2510129 100644 (file)
@@ -499,7 +499,6 @@ static int sppctl_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
        return 0;
 }
 
-#ifdef CONFIG_DEBUG_FS
 static void sppctl_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 {
        const char *label;
@@ -521,7 +520,6 @@ static void sppctl_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
                seq_puts(s, "\n");
        }
 }
-#endif
 
 static int sppctl_gpio_new(struct platform_device *pdev, struct sppctl_pdata *pctl)
 {
@@ -550,9 +548,8 @@ static int sppctl_gpio_new(struct platform_device *pdev, struct sppctl_pdata *pc
        gchip->get              = sppctl_gpio_get;
        gchip->set              = sppctl_gpio_set;
        gchip->set_config       = sppctl_gpio_set_config;
-#ifdef CONFIG_DEBUG_FS
-       gchip->dbg_show         = sppctl_gpio_dbg_show;
-#endif
+       gchip->dbg_show         = IS_ENABLED(CONFIG_DEBUG_FS) ?
+                                 sppctl_gpio_dbg_show : NULL;
        gchip->base             = -1;
        gchip->ngpio            = sppctl_gpio_list_sz;
        gchip->names            = sppctl_gpio_list_s;
index de176c2..2a52c99 100644 (file)
@@ -257,7 +257,7 @@ config RESET_SUNXI
 
 config RESET_TI_SCI
        tristate "TI System Control Interface (TI-SCI) reset driver"
-       depends on TI_SCI_PROTOCOL || COMPILE_TEST
+       depends on TI_SCI_PROTOCOL || (COMPILE_TEST && TI_SCI_PROTOCOL=n)
        help
          This enables the reset driver support over TI System Control Interface
          available on some new TI's SoCs. If you wish to use reset resources
index 146fd5d..15abac9 100644 (file)
@@ -47,7 +47,6 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct uniphier_glue_reset_priv *priv;
        struct resource *res;
-       resource_size_t size;
        int i, ret;
 
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -60,7 +59,6 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev)
                return -EINVAL;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       size = resource_size(res);
        priv->rdata.membase = devm_ioremap_resource(dev, res);
        if (IS_ERR(priv->rdata.membase))
                return PTR_ERR(priv->rdata.membase);
@@ -96,7 +94,7 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev)
 
        spin_lock_init(&priv->rdata.lock);
        priv->rdata.rcdev.owner = THIS_MODULE;
-       priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE;
+       priv->rdata.rcdev.nr_resets = resource_size(res) * BITS_PER_BYTE;
        priv->rdata.rcdev.ops = &reset_simple_ops;
        priv->rdata.rcdev.of_node = dev->of_node;
        priv->rdata.active_low = true;
index 0e3b6ba..0f13853 100644 (file)
@@ -212,7 +212,7 @@ static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
                break;
        case IMX8MP_HDMIBLK_PD_LCDIF:
                regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                               BIT(7) | BIT(16) | BIT(17) | BIT(18) |
+                               BIT(16) | BIT(17) | BIT(18) |
                                BIT(19) | BIT(20));
                regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
                regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
@@ -241,6 +241,7 @@ static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
                regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
                break;
        case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
                regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
                regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
                regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
@@ -270,7 +271,7 @@ static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
                                  BIT(4) | BIT(5) | BIT(6));
                regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
                regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                                 BIT(7) | BIT(16) | BIT(17) | BIT(18) |
+                                 BIT(16) | BIT(17) | BIT(18) |
                                  BIT(19) | BIT(20));
                break;
        case IMX8MP_HDMIBLK_PD_PAI:
@@ -298,6 +299,7 @@ static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
        case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
                regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
                regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
                regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
                break;
        case IMX8MP_HDMIBLK_PD_HDCP:
@@ -590,7 +592,6 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
                        ret = PTR_ERR(domain->power_dev);
                        goto cleanup_pds;
                }
-               dev_set_name(domain->power_dev, "%s", data->name);
 
                domain->genpd.name = data->name;
                domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
index 28144c6..32ed9dc 100644 (file)
@@ -66,8 +66,8 @@ static u32 __init imx8mq_soc_revision(void)
        ocotp_base = of_iomap(np, 0);
        WARN_ON(!ocotp_base);
        clk = of_clk_get_by_name(np, NULL);
-       if (!clk) {
-               WARN_ON(!clk);
+       if (IS_ERR(clk)) {
+               WARN_ON(IS_ERR(clk));
                return 0;
        }
 
index cd44f17..d51abb4 100644 (file)
@@ -461,9 +461,10 @@ static int apr_add_device(struct device *dev, struct device_node *np,
                goto out;
        }
 
+       /* Protection domain is optional, it does not exist on older platforms */
        ret = of_property_read_string_index(np, "qcom,protection-domain",
                                            1, &adev->service_path);
-       if (ret < 0) {
+       if (ret < 0 && ret != -EINVAL) {
                dev_err(dev, "Failed to read second value of qcom,protection-domain\n");
                goto out;
        }
index e9b854e..144ea68 100644 (file)
@@ -1708,12 +1708,16 @@ static int cpr_probe(struct platform_device *pdev)
 
        ret = of_genpd_add_provider_simple(dev->of_node, &drv->pd);
        if (ret)
-               return ret;
+               goto err_remove_genpd;
 
        platform_set_drvdata(pdev, drv);
        cpr_debugfs_init(drv);
 
        return 0;
+
+err_remove_genpd:
+       pm_genpd_remove(&drv->pd);
+       return ret;
 }
 
 static int cpr_remove(struct platform_device *pdev)
index db1441c..690ab71 100644 (file)
@@ -86,7 +86,7 @@ struct vchiq_service_params_kernel {
 
 struct vchiq_instance;
 
-extern enum vchiq_status vchiq_initialise(struct vchiq_instance **pinstance);
+extern int vchiq_initialise(struct vchiq_instance **pinstance);
 extern enum vchiq_status vchiq_shutdown(struct vchiq_instance *instance);
 extern enum vchiq_status vchiq_connect(struct vchiq_instance *instance);
 extern enum vchiq_status vchiq_open_service(struct vchiq_instance *instance,
index 2851ef6..cd20eb1 100644 (file)
@@ -100,10 +100,10 @@ vchiq_dump_platform_use_state(struct vchiq_state *state);
 extern void
 vchiq_dump_service_use_state(struct vchiq_state *state);
 
-extern enum vchiq_status
+extern int
 vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service,
                   enum USE_TYPE_E use_type);
-extern enum vchiq_status
+extern int
 vchiq_release_internal(struct vchiq_state *state,
                       struct vchiq_service *service);
 
index f17ab23..77bd47d 100644 (file)
@@ -909,15 +909,20 @@ __thermal_cooling_device_register(struct device_node *np,
        cdev->devdata = devdata;
 
        ret = cdev->ops->get_max_state(cdev, &cdev->max_state);
-       if (ret)
-               goto out_kfree_type;
+       if (ret) {
+               kfree(cdev->type);
+               goto out_ida_remove;
+       }
 
        thermal_cooling_device_setup_sysfs(cdev);
+
        ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
        if (ret) {
+               kfree(cdev->type);
                thermal_cooling_device_destroy_sysfs(cdev);
-               goto out_kfree_type;
+               goto out_ida_remove;
        }
+
        ret = device_register(&cdev->device);
        if (ret)
                goto out_kfree_type;
@@ -943,6 +948,8 @@ out_kfree_type:
        thermal_cooling_device_destroy_sysfs(cdev);
        kfree(cdev->type);
        put_device(&cdev->device);
+
+       /* thermal_release() takes care of the rest */
        cdev = NULL;
 out_ida_remove:
        ida_free(&thermal_cdev_ida, id);
index 81252e3..56008eb 100644 (file)
@@ -427,13 +427,6 @@ int tb_retimer_scan(struct tb_port *port, bool add)
 {
        u32 status[TB_MAX_RETIMER_INDEX + 1] = {};
        int ret, i, last_idx = 0;
-       struct usb4_port *usb4;
-
-       usb4 = port->usb4;
-       if (!usb4)
-               return 0;
-
-       pm_runtime_get_sync(&usb4->dev);
 
        /*
         * Send broadcast RT to make sure retimer indices facing this
@@ -441,7 +434,7 @@ int tb_retimer_scan(struct tb_port *port, bool add)
         */
        ret = usb4_port_enumerate_retimers(port);
        if (ret)
-               goto out;
+               return ret;
 
        /*
         * Enable sideband channel for each retimer. We can do this
@@ -471,12 +464,11 @@ int tb_retimer_scan(struct tb_port *port, bool add)
                        break;
        }
 
-       if (!last_idx) {
-               ret = 0;
-               goto out;
-       }
+       if (!last_idx)
+               return 0;
 
        /* Add on-board retimers if they do not exist already */
+       ret = 0;
        for (i = 1; i <= last_idx; i++) {
                struct tb_retimer *rt;
 
@@ -490,10 +482,6 @@ int tb_retimer_scan(struct tb_port *port, bool add)
                }
        }
 
-out:
-       pm_runtime_mark_last_busy(&usb4->dev);
-       pm_runtime_put_autosuspend(&usb4->dev);
-
        return ret;
 }
 
index 4628458..3f1ab30 100644 (file)
@@ -628,11 +628,15 @@ static void tb_scan_port(struct tb_port *port)
                         * Downstream switch is reachable through two ports.
                         * Only scan on the primary port (link_nr == 0).
                         */
+
+       if (port->usb4)
+               pm_runtime_get_sync(&port->usb4->dev);
+
        if (tb_wait_for_port(port, false) <= 0)
-               return;
+               goto out_rpm_put;
        if (port->remote) {
                tb_port_dbg(port, "port already has a remote\n");
-               return;
+               goto out_rpm_put;
        }
 
        tb_retimer_scan(port, true);
@@ -647,12 +651,12 @@ static void tb_scan_port(struct tb_port *port)
                 */
                if (PTR_ERR(sw) == -EIO || PTR_ERR(sw) == -EADDRNOTAVAIL)
                        tb_scan_xdomain(port);
-               return;
+               goto out_rpm_put;
        }
 
        if (tb_switch_configure(sw)) {
                tb_switch_put(sw);
-               return;
+               goto out_rpm_put;
        }
 
        /*
@@ -681,7 +685,7 @@ static void tb_scan_port(struct tb_port *port)
 
        if (tb_switch_add(sw)) {
                tb_switch_put(sw);
-               return;
+               goto out_rpm_put;
        }
 
        /* Link the switches using both links if available */
@@ -733,6 +737,12 @@ static void tb_scan_port(struct tb_port *port)
 
        tb_add_dp_resources(sw);
        tb_scan_switch(sw);
+
+out_rpm_put:
+       if (port->usb4) {
+               pm_runtime_mark_last_busy(&port->usb4->dev);
+               pm_runtime_put_autosuspend(&port->usb4->dev);
+       }
 }
 
 static void tb_deactivate_and_free_tunnel(struct tb_tunnel *tunnel)
index 2c3cf7f..1fc3c29 100644 (file)
@@ -1275,7 +1275,7 @@ static void tb_usb3_reclaim_available_bandwidth(struct tb_tunnel *tunnel,
                return;
        } else if (!ret) {
                /* Use maximum link rate if the link valid is not set */
-               ret = usb4_usb3_port_max_link_rate(tunnel->src_port);
+               ret = tb_usb3_max_link_rate(tunnel->dst_port, tunnel->src_port);
                if (ret < 0) {
                        tb_tunnel_warn(tunnel, "failed to read maximum link rate\n");
                        return;
index cfa8348..3c51e47 100644 (file)
@@ -1419,12 +1419,19 @@ static int tb_xdomain_get_properties(struct tb_xdomain *xd)
         * registered, we notify the userspace that it has changed.
         */
        if (!update) {
-               struct tb_port *port;
+               /*
+                * Now disable lane 1 if bonding was not enabled. Do
+                * this only if bonding was possible at the beginning
+                * (that is we are the connection manager and there are
+                * two lanes).
+                */
+               if (xd->bonding_possible) {
+                       struct tb_port *port;
 
-               /* Now disable lane 1 if bonding was not enabled */
-               port = tb_port_at(xd->route, tb_xdomain_parent(xd));
-               if (!port->bonded)
-                       tb_port_disable(port->dual_link_port);
+                       port = tb_port_at(xd->route, tb_xdomain_parent(xd));
+                       if (!port->bonded)
+                               tb_port_disable(port->dual_link_port);
+               }
 
                if (device_add(&xd->dev)) {
                        dev_err(&xd->dev, "failed to add XDomain device\n");
index 314a05e..64770c6 100644 (file)
 #define PCI_DEVICE_ID_EXAR_XR17V4358           0x4358
 #define PCI_DEVICE_ID_EXAR_XR17V8358           0x8358
 
+#define PCI_DEVICE_ID_SEALEVEL_710xC           0x1001
+#define PCI_DEVICE_ID_SEALEVEL_720xC           0x1002
+#define PCI_DEVICE_ID_SEALEVEL_740xC           0x1004
+#define PCI_DEVICE_ID_SEALEVEL_780xC           0x1008
+#define PCI_DEVICE_ID_SEALEVEL_716xC           0x1010
+
 #define UART_EXAR_INT0         0x80
 #define UART_EXAR_8XMODE       0x88    /* 8X sampling rate select */
 #define UART_EXAR_SLEEP                0x8b    /* Sleep mode */
@@ -638,6 +644,8 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
                nr_ports = BIT(((pcidev->device & 0x38) >> 3) - 1);
        else if (board->num_ports)
                nr_ports = board->num_ports;
+       else if (pcidev->vendor == PCI_VENDOR_ID_SEALEVEL)
+               nr_ports = pcidev->device & 0xff;
        else
                nr_ports = pcidev->device & 0x0f;
 
@@ -864,6 +872,12 @@ static const struct pci_device_id exar_pci_tbl[] = {
        EXAR_DEVICE(COMMTECH, 4224PCI335, pbn_fastcom335_4),
        EXAR_DEVICE(COMMTECH, 2324PCI335, pbn_fastcom335_4),
        EXAR_DEVICE(COMMTECH, 2328PCI335, pbn_fastcom335_8),
+
+       EXAR_DEVICE(SEALEVEL, 710xC, pbn_exar_XR17V35x),
+       EXAR_DEVICE(SEALEVEL, 720xC, pbn_exar_XR17V35x),
+       EXAR_DEVICE(SEALEVEL, 740xC, pbn_exar_XR17V35x),
+       EXAR_DEVICE(SEALEVEL, 780xC, pbn_exar_XR17V35x),
+       EXAR_DEVICE(SEALEVEL, 716xC, pbn_exar_XR17V35x),
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, exar_pci_tbl);
index d75c39f..d8c2f34 100644 (file)
@@ -1466,6 +1466,10 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
        struct circ_buf *xmit = &uap->port.state->xmit;
        int count = uap->fifosize >> 1;
 
+       if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
+           !uap->rs485_tx_started)
+               pl011_rs485_tx_start(uap);
+
        if (uap->port.x_char) {
                if (!pl011_tx_char(uap, uap->port.x_char, from_irq))
                        return true;
@@ -1477,10 +1481,6 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
                return false;
        }
 
-       if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
-           !uap->rs485_tx_started)
-               pl011_rs485_tx_start(uap);
-
        /* If we are using DMA mode, try to send some characters. */
        if (pl011_dma_tx_irq(uap))
                return true;
index f1c06e1..9cd7479 100644 (file)
@@ -2657,13 +2657,7 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
        else if (mr == ATMEL_US_PAR_ODD)
                *parity = 'o';
 
-       /*
-        * The serial core only rounds down when matching this to a
-        * supported baud rate. Make sure we don't end up slightly
-        * lower than one of those, as it would make us fall through
-        * to a much lower baud rate than we really want.
-        */
-       *baud = port->uartclk / (16 * (quot - 1));
+       *baud = port->uartclk / (16 * quot);
 }
 
 static int __init atmel_console_setup(struct console *co, char *options)
index a3ed9b3..7ce7bb1 100644 (file)
@@ -171,6 +171,7 @@ static int configure_kgdboc(void)
        int err = -ENODEV;
        char *cptr = config;
        struct console *cons;
+       int cookie;
 
        if (!strlen(config) || isspace(config[0])) {
                err = 0;
@@ -189,20 +190,9 @@ static int configure_kgdboc(void)
        if (kgdboc_register_kbd(&cptr))
                goto do_register;
 
-       /*
-        * tty_find_polling_driver() can call uart_set_options()
-        * (via poll_init) to configure the uart. Take the console_list_lock
-        * in order to synchronize against register_console(), which can also
-        * configure the uart via uart_set_options(). This also allows safe
-        * traversal of the console list.
-        */
-       console_list_lock();
-
        p = tty_find_polling_driver(cptr, &tty_line);
-       if (!p) {
-               console_list_unlock();
+       if (!p)
                goto noconfig;
-       }
 
        /*
         * Take console_lock to serialize device() callback with
@@ -211,7 +201,8 @@ static int configure_kgdboc(void)
         */
        console_lock();
 
-       for_each_console(cons) {
+       cookie = console_srcu_read_lock();
+       for_each_console_srcu(cons) {
                int idx;
                if (cons->device && cons->device(cons, &idx) == p &&
                    idx == tty_line) {
@@ -219,11 +210,10 @@ static int configure_kgdboc(void)
                        break;
                }
        }
+       console_srcu_read_unlock(cookie);
 
        console_unlock();
 
-       console_list_unlock();
-
        kgdb_tty_driver = p;
        kgdb_tty_line = tty_line;
 
index 3d54a43..9576ba8 100644 (file)
@@ -749,7 +749,7 @@ static void pch_dma_tx_complete(void *arg)
                uart_xmit_advance(port, sg_dma_len(sg));
 
        async_tx_ack(priv->desc_tx);
-       dma_unmap_sg(port->dev, sg, priv->orig_nent, DMA_TO_DEVICE);
+       dma_unmap_sg(port->dev, priv->sg_tx_p, priv->orig_nent, DMA_TO_DEVICE);
        priv->tx_dma_use = 0;
        priv->nent = 0;
        priv->orig_nent = 0;
index b487823..57f04f8 100644 (file)
@@ -864,9 +864,10 @@ out_unlock:
        return IRQ_HANDLED;
 }
 
-static void get_tx_fifo_size(struct qcom_geni_serial_port *port)
+static int setup_fifos(struct qcom_geni_serial_port *port)
 {
        struct uart_port *uport;
+       u32 old_rx_fifo_depth = port->rx_fifo_depth;
 
        uport = &port->uport;
        port->tx_fifo_depth = geni_se_get_tx_fifo_depth(&port->se);
@@ -874,6 +875,16 @@ static void get_tx_fifo_size(struct qcom_geni_serial_port *port)
        port->rx_fifo_depth = geni_se_get_rx_fifo_depth(&port->se);
        uport->fifosize =
                (port->tx_fifo_depth * port->tx_fifo_width) / BITS_PER_BYTE;
+
+       if (port->rx_fifo && (old_rx_fifo_depth != port->rx_fifo_depth) && port->rx_fifo_depth) {
+               port->rx_fifo = devm_krealloc(uport->dev, port->rx_fifo,
+                                             port->rx_fifo_depth * sizeof(u32),
+                                             GFP_KERNEL);
+               if (!port->rx_fifo)
+                       return -ENOMEM;
+       }
+
+       return 0;
 }
 
 
@@ -888,6 +899,7 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)
        u32 rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT;
        u32 proto;
        u32 pin_swap;
+       int ret;
 
        proto = geni_se_read_proto(&port->se);
        if (proto != GENI_SE_UART) {
@@ -897,7 +909,9 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)
 
        qcom_geni_serial_stop_rx(uport);
 
-       get_tx_fifo_size(port);
+       ret = setup_fifos(port);
+       if (ret)
+               return ret;
 
        writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT);
 
@@ -1516,7 +1530,7 @@ static int qcom_geni_serial_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev)
+static int qcom_geni_serial_sys_suspend(struct device *dev)
 {
        struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
        struct uart_port *uport = &port->uport;
@@ -1533,7 +1547,7 @@ static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev)
        return uart_suspend_port(private_data->drv, uport);
 }
 
-static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev)
+static int qcom_geni_serial_sys_resume(struct device *dev)
 {
        int ret;
        struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
@@ -1581,10 +1595,12 @@ static int qcom_geni_serial_sys_hib_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops qcom_geni_serial_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(qcom_geni_serial_sys_suspend,
-                                       qcom_geni_serial_sys_resume)
-       .restore = qcom_geni_serial_sys_hib_resume,
-       .thaw = qcom_geni_serial_sys_hib_resume,
+       .suspend = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
+       .resume = pm_sleep_ptr(qcom_geni_serial_sys_resume),
+       .freeze = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
+       .poweroff = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
+       .restore = pm_sleep_ptr(qcom_geni_serial_sys_hib_resume),
+       .thaw = pm_sleep_ptr(qcom_geni_serial_sys_hib_resume),
 };
 
 static const struct of_device_id qcom_geni_serial_match_table[] = {
index b9fbbee..ec874f3 100644 (file)
@@ -2212,6 +2212,9 @@ EXPORT_SYMBOL_GPL(uart_parse_options);
  * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even)
  * @bits: number of data bits
  * @flow: flow control character - 'r' (rts)
+ *
+ * Locking: Caller must hold console_list_lock in order to serialize
+ * early initialization of the serial-console lock.
  */
 int
 uart_set_options(struct uart_port *port, struct console *co,
@@ -2619,7 +2622,9 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
 
        if (!ret && options) {
                uart_parse_options(options, &baud, &parity, &bits, &flow);
+               console_list_lock();
                ret = uart_set_options(port, NULL, baud, parity, bits, flow);
+               console_list_unlock();
        }
 out:
        mutex_unlock(&tport->mutex);
index 5adcb34..ccfaebc 100644 (file)
@@ -2614,6 +2614,7 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep,
        u8 req_on_hw_ring = 0;
        unsigned long flags;
        int ret = 0;
+       int val;
 
        if (!ep || !request || !ep->desc)
                return -EINVAL;
@@ -2649,6 +2650,13 @@ found:
 
        /* Update ring only if removed request is on pending_req_list list */
        if (req_on_hw_ring && link_trb) {
+               /* Stop DMA */
+               writel(EP_CMD_DFLUSH, &priv_dev->regs->ep_cmd);
+
+               /* wait for DFLUSH cleared */
+               readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val,
+                                         !(val & EP_CMD_DFLUSH), 1, 1000);
+
                link_trb->buffer = cpu_to_le32(TRB_BUFFER(priv_ep->trb_pool_dma +
                        ((priv_req->end_trb + 1) * TRB_SIZE)));
                link_trb->control = cpu_to_le32((le32_to_cpu(link_trb->control) & TRB_CYCLE) |
@@ -2660,6 +2668,10 @@ found:
 
        cdns3_gadget_giveback(priv_ep, priv_req, -ECONNRESET);
 
+       req = cdns3_next_request(&priv_ep->pending_req_list);
+       if (req)
+               cdns3_rearm_transfer(priv_ep, 1);
+
 not_found:
        spin_unlock_irqrestore(&priv_dev->lock, flags);
        return ret;
index 484b1cd..27c6012 100644 (file)
@@ -1294,12 +1294,12 @@ static void ci_extcon_wakeup_int(struct ci_hdrc *ci)
        cable_id = &ci->platdata->id_extcon;
        cable_vbus = &ci->platdata->vbus_extcon;
 
-       if ((!IS_ERR(cable_id->edev) || !IS_ERR(ci->role_switch))
+       if ((!IS_ERR(cable_id->edev) || ci->role_switch)
                && ci->is_otg &&
                (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS))
                ci_irq(ci);
 
-       if ((!IS_ERR(cable_vbus->edev) || !IS_ERR(ci->role_switch))
+       if ((!IS_ERR(cable_vbus->edev) || ci->role_switch)
                && ci->is_otg &&
                (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS))
                ci_irq(ci);
index 77e73fc..9eca403 100644 (file)
@@ -44,6 +44,9 @@
 #define USB_PRODUCT_USB5534B                   0x5534
 #define USB_VENDOR_CYPRESS                     0x04b4
 #define USB_PRODUCT_CY7C65632                  0x6570
+#define USB_VENDOR_TEXAS_INSTRUMENTS           0x0451
+#define USB_PRODUCT_TUSB8041_USB3              0x8140
+#define USB_PRODUCT_TUSB8041_USB2              0x8142
 #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND       0x01
 #define HUB_QUIRK_DISABLE_AUTOSUSPEND          0x02
 
@@ -5854,6 +5857,16 @@ static const struct usb_device_id hub_id_table[] = {
       .idVendor = USB_VENDOR_GENESYS_LOGIC,
       .bInterfaceClass = USB_CLASS_HUB,
       .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND},
+    { .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+                       | USB_DEVICE_ID_MATCH_PRODUCT,
+      .idVendor = USB_VENDOR_TEXAS_INSTRUMENTS,
+      .idProduct = USB_PRODUCT_TUSB8041_USB2,
+      .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND},
+    { .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+                       | USB_DEVICE_ID_MATCH_PRODUCT,
+      .idVendor = USB_VENDOR_TEXAS_INSTRUMENTS,
+      .idProduct = USB_PRODUCT_TUSB8041_USB3,
+      .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND},
     { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS,
       .bDeviceClass = USB_CLASS_HUB},
     { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
index 6d93428..533baa8 100644 (file)
@@ -37,6 +37,71 @@ bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
 }
 EXPORT_SYMBOL_GPL(usb_acpi_power_manageable);
 
+#define UUID_USB_CONTROLLER_DSM "ce2ee385-00e6-48cb-9f05-2edb927c4899"
+#define USB_DSM_DISABLE_U1_U2_FOR_PORT 5
+
+/**
+ * usb_acpi_port_lpm_incapable - check if lpm should be disabled for a port.
+ * @hdev: USB device belonging to the usb hub
+ * @index: zero based port index
+ *
+ * Some USB3 ports may not support USB3 link power management U1/U2 states
+ * due to different retimer setup. ACPI provides _DSM method which returns 0x01
+ * if U1 and U2 states should be disabled. Evaluate _DSM with:
+ * Arg0: UUID = ce2ee385-00e6-48cb-9f05-2edb927c4899
+ * Arg1: Revision ID = 0
+ * Arg2: Function Index = 5
+ * Arg3: (empty)
+ *
+ * Return 1 if USB3 port is LPM incapable, negative on error, otherwise 0
+ */
+
+int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index)
+{
+       union acpi_object *obj;
+       acpi_handle port_handle;
+       int port1 = index + 1;
+       guid_t guid;
+       int ret;
+
+       ret = guid_parse(UUID_USB_CONTROLLER_DSM, &guid);
+       if (ret)
+               return ret;
+
+       port_handle = usb_get_hub_port_acpi_handle(hdev, port1);
+       if (!port_handle) {
+               dev_dbg(&hdev->dev, "port-%d no acpi handle\n", port1);
+               return -ENODEV;
+       }
+
+       if (!acpi_check_dsm(port_handle, &guid, 0,
+                           BIT(USB_DSM_DISABLE_U1_U2_FOR_PORT))) {
+               dev_dbg(&hdev->dev, "port-%d no _DSM function %d\n",
+                       port1, USB_DSM_DISABLE_U1_U2_FOR_PORT);
+               return -ENODEV;
+       }
+
+       obj = acpi_evaluate_dsm(port_handle, &guid, 0,
+                               USB_DSM_DISABLE_U1_U2_FOR_PORT, NULL);
+
+       if (!obj)
+               return -ENODEV;
+
+       if (obj->type != ACPI_TYPE_INTEGER) {
+               dev_dbg(&hdev->dev, "evaluate port-%d _DSM failed\n", port1);
+               ACPI_FREE(obj);
+               return -EINVAL;
+       }
+
+       if (obj->integer.value == 0x01)
+               ret = 1;
+
+       ACPI_FREE(obj);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usb_acpi_port_lpm_incapable);
+
 /**
  * usb_acpi_set_power_state - control usb port's power via acpi power
  * resource
index b2f72b0..be954a9 100644 (file)
@@ -3,6 +3,7 @@
 config USB_DWC3
        tristate "DesignWare USB3 DRD Core Support"
        depends on (USB || USB_GADGET) && HAS_DMA
+       depends on (EXTCON || EXTCON=n)
        select USB_XHCI_PLATFORM if USB_XHCI_HCD
        select USB_ROLE_SWITCH if USB_DWC3_DUAL_ROLE
        help
@@ -44,7 +45,6 @@ config USB_DWC3_GADGET
 config USB_DWC3_DUAL_ROLE
        bool "Dual Role mode"
        depends on ((USB=y || USB=USB_DWC3) && (USB_GADGET=y || USB_GADGET=USB_DWC3))
-       depends on (EXTCON=y || EXTCON=USB_DWC3)
        help
          This is the default mode of working of DWC3 controller where
          both host and gadget features are enabled.
index 96121d1..0853536 100644 (file)
@@ -393,6 +393,7 @@ static void gadget_info_attr_release(struct config_item *item)
        WARN_ON(!list_empty(&gi->string_list));
        WARN_ON(!list_empty(&gi->available_func));
        kfree(gi->composite.gadget_driver.function);
+       kfree(gi->composite.gadget_driver.driver.name);
        kfree(gi);
 }
 
@@ -1572,7 +1573,6 @@ static const struct usb_gadget_driver configfs_driver_template = {
        .max_speed      = USB_SPEED_SUPER_PLUS,
        .driver = {
                .owner          = THIS_MODULE,
-               .name           = "configfs-gadget",
        },
        .match_existing_only = 1,
 };
@@ -1623,13 +1623,21 @@ static struct config_group *gadgets_make(
 
        gi->composite.gadget_driver = configfs_driver_template;
 
+       gi->composite.gadget_driver.driver.name = kasprintf(GFP_KERNEL,
+                                                           "configfs-gadget.%s", name);
+       if (!gi->composite.gadget_driver.driver.name)
+               goto err;
+
        gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL);
        gi->composite.name = gi->composite.gadget_driver.function;
 
        if (!gi->composite.gadget_driver.function)
-               goto err;
+               goto out_free_driver_name;
 
        return &gi->group;
+
+out_free_driver_name:
+       kfree(gi->composite.gadget_driver.driver.name);
 err:
        kfree(gi);
        return ERR_PTR(-ENOMEM);
index 73dc10a..523a961 100644 (file)
@@ -279,6 +279,9 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
        struct usb_request *req = ffs->ep0req;
        int ret;
 
+       if (!req)
+               return -EINVAL;
+
        req->zero     = len < le16_to_cpu(ffs->ev.setup.wLength);
 
        spin_unlock_irq(&ffs->ev.waitq.lock);
@@ -1892,10 +1895,14 @@ static void functionfs_unbind(struct ffs_data *ffs)
        ENTER();
 
        if (!WARN_ON(!ffs->gadget)) {
+               /* dequeue before freeing ep0req */
+               usb_ep_dequeue(ffs->gadget->ep0, ffs->ep0req);
+               mutex_lock(&ffs->mutex);
                usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req);
                ffs->ep0req = NULL;
                ffs->gadget = NULL;
                clear_bit(FFS_FL_BOUND, &ffs->flags);
+               mutex_unlock(&ffs->mutex);
                ffs_data_put(ffs);
        }
 }
index c36bcfa..424bb3b 100644 (file)
@@ -83,7 +83,9 @@ static inline struct f_ncm *func_to_ncm(struct usb_function *f)
 /* peak (theoretical) bulk transfer rate in bits-per-second */
 static inline unsigned ncm_bitrate(struct usb_gadget *g)
 {
-       if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER_PLUS)
+       if (!g)
+               return 0;
+       else if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER_PLUS)
                return 4250000000U;
        else if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
                return 3750000000U;
index 01c3ead..d605bc2 100644 (file)
@@ -229,6 +229,7 @@ static void put_ep (struct ep_data *data)
  */
 
 static const char *CHIP;
+static DEFINE_MUTEX(sb_mutex);         /* Serialize superblock operations */
 
 /*----------------------------------------------------------------------*/
 
@@ -2010,13 +2011,20 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc)
 {
        struct inode    *inode;
        struct dev_data *dev;
+       int             rc;
 
-       if (the_device)
-               return -ESRCH;
+       mutex_lock(&sb_mutex);
+
+       if (the_device) {
+               rc = -ESRCH;
+               goto Done;
+       }
 
        CHIP = usb_get_gadget_udc_name();
-       if (!CHIP)
-               return -ENODEV;
+       if (!CHIP) {
+               rc = -ENODEV;
+               goto Done;
+       }
 
        /* superblock */
        sb->s_blocksize = PAGE_SIZE;
@@ -2053,13 +2061,17 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc)
         * from binding to a controller.
         */
        the_device = dev;
-       return 0;
+       rc = 0;
+       goto Done;
 
-Enomem:
+ Enomem:
        kfree(CHIP);
        CHIP = NULL;
+       rc = -ENOMEM;
 
-       return -ENOMEM;
+ Done:
+       mutex_unlock(&sb_mutex);
+       return rc;
 }
 
 /* "mount -t gadgetfs path /dev/gadget" ends up here */
@@ -2081,6 +2093,7 @@ static int gadgetfs_init_fs_context(struct fs_context *fc)
 static void
 gadgetfs_kill_sb (struct super_block *sb)
 {
+       mutex_lock(&sb_mutex);
        kill_litter_super (sb);
        if (the_device) {
                put_dev (the_device);
@@ -2088,6 +2101,7 @@ gadgetfs_kill_sb (struct super_block *sb)
        }
        kfree(CHIP);
        CHIP = NULL;
+       mutex_unlock(&sb_mutex);
 }
 
 /*----------------------------------------------------------------------*/
index 53e38f8..c06dd1a 100644 (file)
@@ -293,6 +293,7 @@ static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = {
        (const struct uvc_descriptor_header *) &uvc_format_yuv,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+       (const struct uvc_descriptor_header *) &uvc_color_matching,
        (const struct uvc_descriptor_header *) &uvc_format_mjpg,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
@@ -305,6 +306,7 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
        (const struct uvc_descriptor_header *) &uvc_format_yuv,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+       (const struct uvc_descriptor_header *) &uvc_color_matching,
        (const struct uvc_descriptor_header *) &uvc_format_mjpg,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
@@ -317,6 +319,7 @@ static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = {
        (const struct uvc_descriptor_header *) &uvc_format_yuv,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+       (const struct uvc_descriptor_header *) &uvc_color_matching,
        (const struct uvc_descriptor_header *) &uvc_format_mjpg,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
index 9cea785..38d06e5 100644 (file)
@@ -29,7 +29,7 @@
 #include "ehci-fsl.h"
 
 #define DRIVER_DESC "Freescale EHCI Host controller driver"
-#define DRV_NAME "ehci-fsl"
+#define DRV_NAME "fsl-ehci"
 
 static struct hc_driver __read_mostly fsl_ehci_hc_driver;
 
index 79d679b..fb988e4 100644 (file)
@@ -78,9 +78,12 @@ static const char hcd_name[] = "xhci_hcd";
 static struct hc_driver __read_mostly xhci_pci_hc_driver;
 
 static int xhci_pci_setup(struct usb_hcd *hcd);
+static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+                                     struct usb_tt *tt, gfp_t mem_flags);
 
 static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
        .reset = xhci_pci_setup,
+       .update_hub_device = xhci_pci_update_hub_device,
 };
 
 /* called after powerup, by probe or system-pm "wakeup" */
@@ -352,8 +355,38 @@ static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
                                NULL);
        ACPI_FREE(obj);
 }
+
+static void xhci_find_lpm_incapable_ports(struct usb_hcd *hcd, struct usb_device *hdev)
+{
+       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+       struct xhci_hub *rhub = &xhci->usb3_rhub;
+       int ret;
+       int i;
+
+       /* This is not the usb3 roothub we are looking for */
+       if (hcd != rhub->hcd)
+               return;
+
+       if (hdev->maxchild > rhub->num_ports) {
+               dev_err(&hdev->dev, "USB3 roothub port number mismatch\n");
+               return;
+       }
+
+       for (i = 0; i < hdev->maxchild; i++) {
+               ret = usb_acpi_port_lpm_incapable(hdev, i);
+
+               dev_dbg(&hdev->dev, "port-%d disable U1/U2 _DSM: %d\n", i + 1, ret);
+
+               if (ret >= 0) {
+                       rhub->ports[i]->lpm_incapable = ret;
+                       continue;
+               }
+       }
+}
+
 #else
 static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
+static void xhci_find_lpm_incapable_ports(struct usb_hcd *hcd, struct usb_device *hdev) { }
 #endif /* CONFIG_ACPI */
 
 /* called during probe() after chip reset completes */
@@ -386,6 +419,16 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
        return xhci_pci_reinit(xhci, pdev);
 }
 
+static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+                                     struct usb_tt *tt, gfp_t mem_flags)
+{
+       /* Check if acpi claims some USB3 roothub ports are lpm incapable */
+       if (!hdev->parent)
+               xhci_find_lpm_incapable_ports(hcd, hdev);
+
+       return xhci_update_hub_device(hcd, hdev, tt, mem_flags);
+}
+
 /*
  * We need to register our own PCI probe function (instead of the USB core's
  * function) in order to create a second roothub under xHCI.
@@ -455,6 +498,8 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
                pm_runtime_allow(&dev->dev);
 
+       dma_set_max_seg_size(&dev->dev, UINT_MAX);
+
        return 0;
 
 put_usb3_hcd:
index ddc3003..f5b0e1c 100644 (file)
@@ -1169,7 +1169,10 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
        struct xhci_virt_ep *ep;
        struct xhci_ring *ring;
 
-       ep = &xhci->devs[slot_id]->eps[ep_index];
+       ep = xhci_get_virt_ep(xhci, slot_id, ep_index);
+       if (!ep)
+               return;
+
        if ((ep->ep_state & EP_HAS_STREAMS) ||
                        (ep->ep_state & EP_GETTING_NO_STREAMS)) {
                int stream_id;
index 79d7931..2b280be 100644 (file)
@@ -3974,6 +3974,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        struct xhci_virt_device *virt_dev;
        struct xhci_slot_ctx *slot_ctx;
+       unsigned long flags;
        int i, ret;
 
        /*
@@ -4000,7 +4001,11 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
                virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING;
        virt_dev->udev = NULL;
        xhci_disable_slot(xhci, udev->slot_id);
+
+       spin_lock_irqsave(&xhci->lock, flags);
        xhci_free_virt_device(xhci, udev->slot_id);
+       spin_unlock_irqrestore(&xhci->lock, flags);
+
 }
 
 int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
@@ -5044,6 +5049,7 @@ static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
                        struct usb_device *udev, enum usb3_link_state state)
 {
        struct xhci_hcd *xhci;
+       struct xhci_port *port;
        u16 hub_encoded_timeout;
        int mel;
        int ret;
@@ -5060,6 +5066,13 @@ static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
        if (xhci_check_tier_policy(xhci, udev, state) < 0)
                return USB3_LPM_DISABLED;
 
+       /* If connected to root port then check port can handle lpm */
+       if (udev->parent && !udev->parent->parent) {
+               port = xhci->usb3_rhub.ports[udev->portnum - 1];
+               if (port->lpm_incapable)
+                       return USB3_LPM_DISABLED;
+       }
+
        hub_encoded_timeout = xhci_calculate_lpm_timeout(hcd, udev, state);
        mel = calculate_max_exit_latency(udev, state, hub_encoded_timeout);
        if (mel < 0) {
@@ -5119,7 +5132,7 @@ static int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
 /* Once a hub descriptor is fetched for a device, we need to update the xHC's
  * internal data structures for the device.
  */
-static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
                        struct usb_tt *tt, gfp_t mem_flags)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -5219,6 +5232,7 @@ static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
        xhci_free_command(xhci, config_cmd);
        return ret;
 }
+EXPORT_SYMBOL_GPL(xhci_update_hub_device);
 
 static int xhci_get_frame(struct usb_hcd *hcd)
 {
@@ -5502,6 +5516,8 @@ void xhci_init_driver(struct hc_driver *drv,
                        drv->check_bandwidth = over->check_bandwidth;
                if (over->reset_bandwidth)
                        drv->reset_bandwidth = over->reset_bandwidth;
+               if (over->update_hub_device)
+                       drv->update_hub_device = over->update_hub_device;
        }
 }
 EXPORT_SYMBOL_GPL(xhci_init_driver);
index c9f06c5..dcee7f3 100644 (file)
@@ -1735,6 +1735,7 @@ struct xhci_port {
        int                     hcd_portnum;
        struct xhci_hub         *rhub;
        struct xhci_port_cap    *port_cap;
+       unsigned int            lpm_incapable:1;
 };
 
 struct xhci_hub {
@@ -1943,6 +1944,8 @@ struct xhci_driver_overrides {
                             struct usb_host_endpoint *ep);
        int (*check_bandwidth)(struct usb_hcd *, struct usb_device *);
        void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
+       int (*update_hub_device)(struct usb_hcd *hcd, struct usb_device *hdev,
+                           struct usb_tt *tt, gfp_t mem_flags);
 };
 
 #define        XHCI_CFC_DELAY          10
@@ -2122,6 +2125,8 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
                       struct usb_host_endpoint *ep);
 int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
+int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+                          struct usb_tt *tt, gfp_t mem_flags);
 int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
 int xhci_ext_cap_init(struct xhci_hcd *xhci);
 
index f9427a6..1e3df27 100644 (file)
@@ -814,7 +814,7 @@ static int iowarrior_probe(struct usb_interface *interface,
                        break;
 
                case USB_DEVICE_ID_CODEMERCS_IOW100:
-                       dev->report_size = 13;
+                       dev->report_size = 12;
                        break;
                }
        }
index 94e7966..969c4c4 100644 (file)
 
 #include "onboard_usb_hub.h"
 
+static void onboard_hub_attach_usb_driver(struct work_struct *work);
+
 static struct usb_device_driver onboard_hub_usbdev_driver;
+static DECLARE_WORK(attach_usb_driver_work, onboard_hub_attach_usb_driver);
 
 /************************** Platform driver **************************/
 
@@ -45,7 +48,6 @@ struct onboard_hub {
        bool is_powered_on;
        bool going_away;
        struct list_head udev_list;
-       struct work_struct attach_usb_driver_work;
        struct mutex lock;
 };
 
@@ -271,8 +273,7 @@ static int onboard_hub_probe(struct platform_device *pdev)
         * This needs to be done deferred to avoid self-deadlocks on systems
         * with nested onboard hubs.
         */
-       INIT_WORK(&hub->attach_usb_driver_work, onboard_hub_attach_usb_driver);
-       schedule_work(&hub->attach_usb_driver_work);
+       schedule_work(&attach_usb_driver_work);
 
        return 0;
 }
@@ -285,9 +286,6 @@ static int onboard_hub_remove(struct platform_device *pdev)
 
        hub->going_away = true;
 
-       if (&hub->attach_usb_driver_work != current_work())
-               cancel_work_sync(&hub->attach_usb_driver_work);
-
        mutex_lock(&hub->lock);
 
        /* unbind the USB devices to avoid dangling references to this device */
@@ -433,13 +431,13 @@ static int __init onboard_hub_init(void)
 {
        int ret;
 
-       ret = platform_driver_register(&onboard_hub_driver);
+       ret = usb_register_device_driver(&onboard_hub_usbdev_driver, THIS_MODULE);
        if (ret)
                return ret;
 
-       ret = usb_register_device_driver(&onboard_hub_usbdev_driver, THIS_MODULE);
+       ret = platform_driver_register(&onboard_hub_driver);
        if (ret)
-               platform_driver_unregister(&onboard_hub_driver);
+               usb_deregister_device_driver(&onboard_hub_usbdev_driver);
 
        return ret;
 }
@@ -449,6 +447,8 @@ static void __exit onboard_hub_exit(void)
 {
        usb_deregister_device_driver(&onboard_hub_usbdev_driver);
        platform_driver_unregister(&onboard_hub_driver);
+
+       cancel_work_sync(&attach_usb_driver_work);
 }
 module_exit(onboard_hub_exit);
 
index 476f55d..44a21ec 100644 (file)
@@ -411,8 +411,10 @@ static int omap2430_probe(struct platform_device *pdev)
                memset(musb_res, 0, sizeof(*musb_res) * ARRAY_SIZE(musb_res));
 
                res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-               if (!res)
+               if (!res) {
+                       ret = -EINVAL;
                        goto err2;
+               }
 
                musb_res[i].start = res->start;
                musb_res[i].end = res->end;
index 67372ac..832ad59 100644 (file)
@@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */
        { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
        { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
+       { USB_DEVICE(0x0908, 0x0070) }, /* Siemens SCALANCE LPE-9000 USB Serial Console */
        { USB_DEVICE(0x0908, 0x01FF) }, /* Siemens RUGGEDCOM USB Serial Console */
        { USB_DEVICE(0x0988, 0x0578) }, /* Teraoka AD2000 */
        { USB_DEVICE(0x0B00, 0x3070) }, /* Ingenico 3070 */
index dee79c7..ee5ac4e 100644 (file)
@@ -255,10 +255,16 @@ static void option_instat_callback(struct urb *urb);
 #define QUECTEL_PRODUCT_EP06                   0x0306
 #define QUECTEL_PRODUCT_EM05G                  0x030a
 #define QUECTEL_PRODUCT_EM060K                 0x030b
+#define QUECTEL_PRODUCT_EM05G_CS               0x030c
+#define QUECTEL_PRODUCT_EM05CN_SG              0x0310
 #define QUECTEL_PRODUCT_EM05G_SG               0x0311
+#define QUECTEL_PRODUCT_EM05CN                 0x0312
+#define QUECTEL_PRODUCT_EM05G_GR               0x0313
+#define QUECTEL_PRODUCT_EM05G_RS               0x0314
 #define QUECTEL_PRODUCT_EM12                   0x0512
 #define QUECTEL_PRODUCT_RM500Q                 0x0800
 #define QUECTEL_PRODUCT_RM520N                 0x0801
+#define QUECTEL_PRODUCT_EC200U                 0x0901
 #define QUECTEL_PRODUCT_EC200S_CN              0x6002
 #define QUECTEL_PRODUCT_EC200T                 0x6026
 #define QUECTEL_PRODUCT_RM500K                 0x7001
@@ -1159,8 +1165,18 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
          .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
+       { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05CN, 0xff),
+         .driver_info = RSVD(6) | ZLP },
+       { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05CN_SG, 0xff),
+         .driver_info = RSVD(6) | ZLP },
        { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G, 0xff),
          .driver_info = RSVD(6) | ZLP },
+       { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_CS, 0xff),
+         .driver_info = RSVD(6) | ZLP },
+       { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_GR, 0xff),
+         .driver_info = RSVD(6) | ZLP },
+       { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_RS, 0xff),
+         .driver_info = RSVD(6) | ZLP },
        { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_SG, 0xff),
          .driver_info = RSVD(6) | ZLP },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) },
@@ -1180,6 +1196,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0xff, 0x30) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0x40) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) },
index 3f720fa..d73282c 100644 (file)
@@ -116,6 +116,19 @@ static int uas_use_uas_driver(struct usb_interface *intf,
        if (le16_to_cpu(udev->descriptor.idVendor) == 0x0bc2)
                flags |= US_FL_NO_ATA_1X;
 
+       /*
+        * RTL9210-based enclosure from HIKSEMI, MD202 reportedly have issues
+        * with UAS.  This isn't distinguishable with just idVendor and
+        * idProduct, use manufacturer and product too.
+        *
+        * Reported-by: Hongling Zeng <zenghongling@kylinos.cn>
+        */
+       if (le16_to_cpu(udev->descriptor.idVendor) == 0x0bda &&
+                       le16_to_cpu(udev->descriptor.idProduct) == 0x9210 &&
+                       (udev->manufacturer && !strcmp(udev->manufacturer, "HIKSEMI")) &&
+                       (udev->product && !strcmp(udev->product, "MD202")))
+               flags |= US_FL_IGNORE_UAS;
+
        usb_stor_adjust_quirks(udev, &flags);
 
        if (flags & US_FL_IGNORE_UAS) {
index 251778d..c7b763d 100644 (file)
@@ -83,13 +83,6 @@ UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_NO_REPORT_LUNS),
 
-/* Reported-by: Hongling Zeng <zenghongling@kylinos.cn> */
-UNUSUAL_DEV(0x0bda, 0x9210, 0x0000, 0x9999,
-               "Hiksemi",
-               "External HDD",
-               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
-               US_FL_IGNORE_UAS),
-
 /* Reported-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> */
 UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x9999,
                "Initio Corporation",
index de66a29..9a68602 100644 (file)
@@ -419,6 +419,18 @@ static const char * const pin_assignments[] = {
        [DP_PIN_ASSIGN_F] = "F",
 };
 
+/*
+ * Helper function to extract a peripheral's currently supported
+ * Pin Assignments from its DisplayPort alternate mode state.
+ */
+static u8 get_current_pin_assignments(struct dp_altmode *dp)
+{
+       if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_UFP_U_AS_DFP_D)
+               return DP_CAP_PIN_ASSIGN_DFP_D(dp->alt->vdo);
+       else
+               return DP_CAP_PIN_ASSIGN_UFP_D(dp->alt->vdo);
+}
+
 static ssize_t
 pin_assignment_store(struct device *dev, struct device_attribute *attr,
                     const char *buf, size_t size)
@@ -445,10 +457,7 @@ pin_assignment_store(struct device *dev, struct device_attribute *attr,
                goto out_unlock;
        }
 
-       if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_DFP_D)
-               assignments = DP_CAP_UFP_D_PIN_ASSIGN(dp->alt->vdo);
-       else
-               assignments = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo);
+       assignments = get_current_pin_assignments(dp);
 
        if (!(DP_CONF_GET_PIN_ASSIGN(conf) & assignments)) {
                ret = -EINVAL;
@@ -485,10 +494,7 @@ static ssize_t pin_assignment_show(struct device *dev,
 
        cur = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf));
 
-       if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_DFP_D)
-               assignments = DP_CAP_UFP_D_PIN_ASSIGN(dp->alt->vdo);
-       else
-               assignments = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo);
+       assignments = get_current_pin_assignments(dp);
 
        for (i = 0; assignments; assignments >>= 1, i++) {
                if (assignments & 1) {
index 904c7b4..59b366b 100644 (file)
@@ -4594,14 +4594,13 @@ static void run_state_machine(struct tcpm_port *port)
                tcpm_set_state(port, ready_state(port), 0);
                break;
        case DR_SWAP_CHANGE_DR:
-               if (port->data_role == TYPEC_HOST) {
-                       tcpm_unregister_altmodes(port);
+               tcpm_unregister_altmodes(port);
+               if (port->data_role == TYPEC_HOST)
                        tcpm_set_roles(port, true, port->pwr_role,
                                       TYPEC_DEVICE);
-               } else {
+               else
                        tcpm_set_roles(port, true, port->pwr_role,
                                       TYPEC_HOST);
-               }
                tcpm_ams_finish(port);
                tcpm_set_state(port, ready_state(port), 0);
                break;
index eabe519..1292241 100644 (file)
@@ -187,6 +187,7 @@ EXPORT_SYMBOL_GPL(ucsi_send_command);
 
 struct ucsi_work {
        struct delayed_work work;
+       struct list_head node;
        unsigned long delay;
        unsigned int count;
        struct ucsi_connector *con;
@@ -202,6 +203,7 @@ static void ucsi_poll_worker(struct work_struct *work)
        mutex_lock(&con->lock);
 
        if (!con->partner) {
+               list_del(&uwork->node);
                mutex_unlock(&con->lock);
                kfree(uwork);
                return;
@@ -209,10 +211,12 @@ static void ucsi_poll_worker(struct work_struct *work)
 
        ret = uwork->cb(con);
 
-       if (uwork->count-- && (ret == -EBUSY || ret == -ETIMEDOUT))
+       if (uwork->count-- && (ret == -EBUSY || ret == -ETIMEDOUT)) {
                queue_delayed_work(con->wq, &uwork->work, uwork->delay);
-       else
+       } else {
+               list_del(&uwork->node);
                kfree(uwork);
+       }
 
        mutex_unlock(&con->lock);
 }
@@ -236,6 +240,7 @@ static int ucsi_partner_task(struct ucsi_connector *con,
        uwork->con = con;
        uwork->cb = cb;
 
+       list_add_tail(&uwork->node, &con->partner_tasks);
        queue_delayed_work(con->wq, &uwork->work, delay);
 
        return 0;
@@ -1056,6 +1061,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
        INIT_WORK(&con->work, ucsi_handle_connector_change);
        init_completion(&con->complete);
        mutex_init(&con->lock);
+       INIT_LIST_HEAD(&con->partner_tasks);
        con->num = index + 1;
        con->ucsi = ucsi;
 
@@ -1420,8 +1426,20 @@ void ucsi_unregister(struct ucsi *ucsi)
                ucsi_unregister_altmodes(&ucsi->connector[i],
                                         UCSI_RECIPIENT_CON);
                ucsi_unregister_port_psy(&ucsi->connector[i]);
-               if (ucsi->connector[i].wq)
+
+               if (ucsi->connector[i].wq) {
+                       struct ucsi_work *uwork;
+
+                       mutex_lock(&ucsi->connector[i].lock);
+                       /*
+                        * queue delayed items immediately so they can execute
+                        * and free themselves before the wq is destroyed
+                        */
+                       list_for_each_entry(uwork, &ucsi->connector[i].partner_tasks, node)
+                               mod_delayed_work(ucsi->connector[i].wq, &uwork->work, 0);
+                       mutex_unlock(&ucsi->connector[i].lock);
                        destroy_workqueue(ucsi->connector[i].wq);
+               }
                typec_unregister_port(ucsi->connector[i].port);
        }
 
index c968474..60ce9fb 100644 (file)
@@ -322,6 +322,7 @@ struct ucsi_connector {
        struct work_struct work;
        struct completion complete;
        struct workqueue_struct *wq;
+       struct list_head partner_tasks;
 
        struct typec_port *port;
        struct typec_partner *partner;
index f2ae2e5..4a2ddf7 100644 (file)
@@ -1166,6 +1166,8 @@ int w1_process(void *data)
        /* remainder if it woke up early */
        unsigned long jremain = 0;
 
+       atomic_inc(&dev->refcnt);
+
        for (;;) {
 
                if (!jremain && dev->search_count) {
@@ -1193,8 +1195,10 @@ int w1_process(void *data)
                 */
                mutex_unlock(&dev->list_mutex);
 
-               if (kthread_should_stop())
+               if (kthread_should_stop()) {
+                       __set_current_state(TASK_RUNNING);
                        break;
+               }
 
                /* Only sleep when the search is active. */
                if (dev->search_count) {
index b3e1792..3a71c5e 100644 (file)
@@ -51,10 +51,9 @@ static struct w1_master *w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
        dev->search_count       = w1_search_count;
        dev->enable_pullup      = w1_enable_pullup;
 
-       /* 1 for w1_process to decrement
-        * 1 for __w1_remove_master_device to decrement
+       /* For __w1_remove_master_device to decrement
         */
-       atomic_set(&dev->refcnt, 2);
+       atomic_set(&dev->refcnt, 1);
 
        INIT_LIST_HEAD(&dev->slist);
        INIT_LIST_HEAD(&dev->async_list);
index cefa222..8daeed3 100644 (file)
@@ -880,7 +880,7 @@ affs_truncate(struct inode *inode)
        if (inode->i_size > AFFS_I(inode)->mmu_private) {
                struct address_space *mapping = inode->i_mapping;
                struct page *page;
-               void *fsdata;
+               void *fsdata = NULL;
                loff_t isize = inode->i_size;
                int res;
 
index 8aeaada..3aa0422 100644 (file)
@@ -367,7 +367,14 @@ error:
        btrfs_print_tree(eb, 0);
        btrfs_err(fs_info, "block=%llu write time tree block corruption detected",
                  eb->start);
-       WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
+       /*
+        * Be noisy if this is an extent buffer from a log tree. We don't abort
+        * a transaction in case there's a bad log tree extent buffer, we just
+        * fallback to a transaction commit. Still we want to know when there is
+        * a bad log tree extent buffer, as that may signal a bug somewhere.
+        */
+       WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG) ||
+               btrfs_header_owner(eb) == BTRFS_TREE_LOG_OBJECTID);
        return ret;
 }
 
index 834bbcb..af046d2 100644 (file)
@@ -3541,6 +3541,7 @@ static loff_t find_desired_extent(struct file *file, loff_t offset, int whence)
                struct extent_buffer *leaf = path->nodes[0];
                struct btrfs_file_extent_item *extent;
                u64 extent_end;
+               u8 type;
 
                if (path->slots[0] >= btrfs_header_nritems(leaf)) {
                        ret = btrfs_next_leaf(root, path);
@@ -3596,10 +3597,16 @@ static loff_t find_desired_extent(struct file *file, loff_t offset, int whence)
 
                extent = btrfs_item_ptr(leaf, path->slots[0],
                                        struct btrfs_file_extent_item);
+               type = btrfs_file_extent_type(leaf, extent);
 
-               if (btrfs_file_extent_disk_bytenr(leaf, extent) == 0 ||
-                   btrfs_file_extent_type(leaf, extent) ==
-                   BTRFS_FILE_EXTENT_PREALLOC) {
+               /*
+                * Can't access the extent's disk_bytenr field if this is an
+                * inline extent, since at that offset, it's where the extent
+                * data starts.
+                */
+               if (type == BTRFS_FILE_EXTENT_PREALLOC ||
+                   (type == BTRFS_FILE_EXTENT_REG &&
+                    btrfs_file_extent_disk_bytenr(leaf, extent) == 0)) {
                        /*
                         * Explicit hole or prealloc extent, search for delalloc.
                         * A prealloc extent is treated like a hole.
index a749367..37b86ac 100644 (file)
@@ -119,6 +119,12 @@ enum {
        /* Indicate that we want to commit the transaction. */
        BTRFS_FS_NEED_TRANS_COMMIT,
 
+       /*
+        * Indicate metadata over-commit is disabled. This is set when active
+        * zone tracking is needed.
+        */
+       BTRFS_FS_NO_OVERCOMMIT,
+
 #if BITS_PER_LONG == 32
        /* Indicate if we have error/warn message printed on 32bit systems */
        BTRFS_FS_32BIT_ERROR,
index d275bf2..af97413 100644 (file)
@@ -2765,9 +2765,19 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans)
 
                        /*
                         * Old roots should be searched when inserting qgroup
-                        * extent record
+                        * extent record.
+                        *
+                        * But for INCONSISTENT (NO_ACCOUNTING) -> rescan case,
+                        * we may have some record inserted during
+                        * NO_ACCOUNTING (thus no old_roots populated), but
+                        * later we start rescan, which clears NO_ACCOUNTING,
+                        * leaving some inserted records without old_roots
+                        * populated.
+                        *
+                        * Those cases are rare and should not cause too much
+                        * time spent during commit_transaction().
                         */
-                       if (WARN_ON(!record->old_roots)) {
+                       if (!record->old_roots) {
                                /* Search commit root to find old_roots */
                                ret = btrfs_find_all_roots(&ctx, false);
                                if (ret < 0)
@@ -3357,6 +3367,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
        int err = -ENOMEM;
        int ret = 0;
        bool stopped = false;
+       bool did_leaf_rescans = false;
 
        path = btrfs_alloc_path();
        if (!path)
@@ -3377,6 +3388,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
                }
 
                err = qgroup_rescan_leaf(trans, path);
+               did_leaf_rescans = true;
 
                if (err > 0)
                        btrfs_commit_transaction(trans);
@@ -3397,16 +3409,23 @@ out:
        mutex_unlock(&fs_info->qgroup_rescan_lock);
 
        /*
-        * only update status, since the previous part has already updated the
-        * qgroup info.
+        * Only update status, since the previous part has already updated the
+        * qgroup info, and only if we did any actual work. This also prevents
+        * race with a concurrent quota disable, which has already set
+        * fs_info->quota_root to NULL and cleared BTRFS_FS_QUOTA_ENABLED at
+        * btrfs_quota_disable().
         */
-       trans = btrfs_start_transaction(fs_info->quota_root, 1);
-       if (IS_ERR(trans)) {
-               err = PTR_ERR(trans);
+       if (did_leaf_rescans) {
+               trans = btrfs_start_transaction(fs_info->quota_root, 1);
+               if (IS_ERR(trans)) {
+                       err = PTR_ERR(trans);
+                       trans = NULL;
+                       btrfs_err(fs_info,
+                                 "fail to start transaction for status update: %d",
+                                 err);
+               }
+       } else {
                trans = NULL;
-               btrfs_err(fs_info,
-                         "fail to start transaction for status update: %d",
-                         err);
        }
 
        mutex_lock(&fs_info->qgroup_rescan_lock);
index d28ee4e..69c0950 100644 (file)
@@ -407,7 +407,8 @@ int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
                return 0;
 
        used = btrfs_space_info_used(space_info, true);
-       if (btrfs_is_zoned(fs_info) && (space_info->flags & BTRFS_BLOCK_GROUP_METADATA))
+       if (test_bit(BTRFS_FS_NO_OVERCOMMIT, &fs_info->flags) &&
+           (space_info->flags & BTRFS_BLOCK_GROUP_METADATA))
                avail = 0;
        else
                avail = calc_available_free_space(fs_info, space_info, flush);
index fb52aa0..d432615 100644 (file)
@@ -2980,7 +2980,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
                ret = 0;
        if (ret) {
                blk_finish_plug(&plug);
-               btrfs_abort_transaction(trans, ret);
                btrfs_set_log_full_commit(trans);
                mutex_unlock(&root->log_mutex);
                goto out;
@@ -3045,15 +3044,12 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
 
                blk_finish_plug(&plug);
                btrfs_set_log_full_commit(trans);
-
-               if (ret != -ENOSPC) {
-                       btrfs_abort_transaction(trans, ret);
-                       mutex_unlock(&log_root_tree->log_mutex);
-                       goto out;
-               }
+               if (ret != -ENOSPC)
+                       btrfs_err(fs_info,
+                                 "failed to update log for root %llu ret %d",
+                                 root->root_key.objectid, ret);
                btrfs_wait_tree_log_extents(log, mark);
                mutex_unlock(&log_root_tree->log_mutex);
-               ret = BTRFS_LOG_FORCE_COMMIT;
                goto out;
        }
 
@@ -3112,7 +3108,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
                goto out_wake_log_root;
        } else if (ret) {
                btrfs_set_log_full_commit(trans);
-               btrfs_abort_transaction(trans, ret);
                mutex_unlock(&log_root_tree->log_mutex);
                goto out_wake_log_root;
        }
@@ -3826,7 +3821,10 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,
                                              path->slots[0]);
                        if (tmp.type == BTRFS_DIR_INDEX_KEY)
                                last_old_dentry_offset = tmp.offset;
+               } else if (ret < 0) {
+                       err = ret;
                }
+
                goto done;
        }
 
@@ -3846,19 +3844,34 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,
                 */
                if (tmp.type == BTRFS_DIR_INDEX_KEY)
                        last_old_dentry_offset = tmp.offset;
+       } else if (ret < 0) {
+               err = ret;
+               goto done;
        }
+
        btrfs_release_path(path);
 
        /*
-        * Find the first key from this transaction again.  See the note for
-        * log_new_dir_dentries, if we're logging a directory recursively we
-        * won't be holding its i_mutex, which means we can modify the directory
-        * while we're logging it.  If we remove an entry between our first
-        * search and this search we'll not find the key again and can just
-        * bail.
+        * Find the first key from this transaction again or the one we were at
+        * in the loop below in case we had to reschedule. We may be logging the
+        * directory without holding its VFS lock, which happen when logging new
+        * dentries (through log_new_dir_dentries()) or in some cases when we
+        * need to log the parent directory of an inode. This means a dir index
+        * key might be deleted from the inode's root, and therefore we may not
+        * find it anymore. If we can't find it, just move to the next key. We
+        * can not bail out and ignore, because if we do that we will simply
+        * not log dir index keys that come after the one that was just deleted
+        * and we can end up logging a dir index range that ends at (u64)-1
+        * (@last_offset is initialized to that), resulting in removing dir
+        * entries we should not remove at log replay time.
         */
 search:
        ret = btrfs_search_slot(NULL, root, &min_key, path, 0, 0);
+       if (ret > 0)
+               ret = btrfs_next_item(root, path);
+       if (ret < 0)
+               err = ret;
+       /* If ret is 1, there are no more keys in the inode's root. */
        if (ret != 0)
                goto done;
 
@@ -5580,8 +5593,10 @@ static int add_conflicting_inode(struct btrfs_trans_handle *trans,
         * LOG_INODE_EXISTS mode) and slow down other fsyncs or transaction
         * commits.
         */
-       if (ctx->num_conflict_inodes >= MAX_CONFLICT_INODES)
+       if (ctx->num_conflict_inodes >= MAX_CONFLICT_INODES) {
+               btrfs_set_log_full_commit(trans);
                return BTRFS_LOG_FORCE_COMMIT;
+       }
 
        inode = btrfs_iget(root->fs_info->sb, ino, root);
        /*
index aa25fa3..bcfef75 100644 (file)
@@ -768,8 +768,11 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                                        BTRFS_SUPER_FLAG_CHANGING_FSID_V2);
 
        error = lookup_bdev(path, &path_devt);
-       if (error)
+       if (error) {
+               btrfs_err(NULL, "failed to lookup block device for path %s: %d",
+                         path, error);
                return ERR_PTR(error);
+       }
 
        if (fsid_change_in_progress) {
                if (!has_metadata_uuid)
@@ -836,6 +839,9 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                unsigned int nofs_flag;
 
                if (fs_devices->opened) {
+                       btrfs_err(NULL,
+               "device %s belongs to fsid %pU, and the fs is already mounted",
+                                 path, fs_devices->fsid);
                        mutex_unlock(&fs_devices->device_list_mutex);
                        return ERR_PTR(-EBUSY);
                }
@@ -905,6 +911,9 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                         * generation are equal.
                         */
                        mutex_unlock(&fs_devices->device_list_mutex);
+                       btrfs_err(NULL,
+"device %s already registered with a higher generation, found %llu expect %llu",
+                                 path, found_transid, device->generation);
                        return ERR_PTR(-EEXIST);
                }
 
@@ -2005,42 +2014,42 @@ static u64 btrfs_num_devices(struct btrfs_fs_info *fs_info)
        return num_devices;
 }
 
+static void btrfs_scratch_superblock(struct btrfs_fs_info *fs_info,
+                                    struct block_device *bdev, int copy_num)
+{
+       struct btrfs_super_block *disk_super;
+       const size_t len = sizeof(disk_super->magic);
+       const u64 bytenr = btrfs_sb_offset(copy_num);
+       int ret;
+
+       disk_super = btrfs_read_disk_super(bdev, bytenr, bytenr);
+       if (IS_ERR(disk_super))
+               return;
+
+       memset(&disk_super->magic, 0, len);
+       folio_mark_dirty(virt_to_folio(disk_super));
+       btrfs_release_disk_super(disk_super);
+
+       ret = sync_blockdev_range(bdev, bytenr, bytenr + len - 1);
+       if (ret)
+               btrfs_warn(fs_info, "error clearing superblock number %d (%d)",
+                       copy_num, ret);
+}
+
 void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
                               struct block_device *bdev,
                               const char *device_path)
 {
-       struct btrfs_super_block *disk_super;
        int copy_num;
 
        if (!bdev)
                return;
 
        for (copy_num = 0; copy_num < BTRFS_SUPER_MIRROR_MAX; copy_num++) {
-               struct page *page;
-               int ret;
-
-               disk_super = btrfs_read_dev_one_super(bdev, copy_num, false);
-               if (IS_ERR(disk_super))
-                       continue;
-
-               if (bdev_is_zoned(bdev)) {
+               if (bdev_is_zoned(bdev))
                        btrfs_reset_sb_log_zones(bdev, copy_num);
-                       continue;
-               }
-
-               memset(&disk_super->magic, 0, sizeof(disk_super->magic));
-
-               page = virt_to_page(disk_super);
-               set_page_dirty(page);
-               lock_page(page);
-               /* write_on_page() unlocks the page */
-               ret = write_one_page(page);
-               if (ret)
-                       btrfs_warn(fs_info,
-                               "error clearing superblock number %d (%d)",
-                               copy_num, ret);
-               btrfs_release_disk_super(disk_super);
-
+               else
+                       btrfs_scratch_superblock(fs_info, bdev, copy_num);
        }
 
        /* Notify udev that device has changed */
index a759668..1f503e8 100644 (file)
@@ -539,6 +539,8 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
                }
                atomic_set(&zone_info->active_zones_left,
                           max_active_zones - nactive);
+               /* Overcommit does not work well with active zone tacking. */
+               set_bit(BTRFS_FS_NO_OVERCOMMIT, &fs_info->flags);
        }
 
        /* Validate superblock log */
index e20f888..ac86bd0 100644 (file)
@@ -269,7 +269,7 @@ static int dfscache_proc_show(struct seq_file *m, void *v)
                        list_for_each_entry(t, &ce->tlist, list) {
                                seq_printf(m, "  %s%s\n",
                                           t->name,
-                                          ce->tgthint == t ? " (target hint)" : "");
+                                          READ_ONCE(ce->tgthint) == t ? " (target hint)" : "");
                        }
                }
        }
@@ -321,7 +321,7 @@ static inline void dump_tgts(const struct cache_entry *ce)
        cifs_dbg(FYI, "target list:\n");
        list_for_each_entry(t, &ce->tlist, list) {
                cifs_dbg(FYI, "  %s%s\n", t->name,
-                        ce->tgthint == t ? " (target hint)" : "");
+                        READ_ONCE(ce->tgthint) == t ? " (target hint)" : "");
        }
 }
 
@@ -427,7 +427,7 @@ static int cache_entry_hash(const void *data, int size, unsigned int *hash)
 /* Return target hint of a DFS cache entry */
 static inline char *get_tgt_name(const struct cache_entry *ce)
 {
-       struct cache_dfs_tgt *t = ce->tgthint;
+       struct cache_dfs_tgt *t = READ_ONCE(ce->tgthint);
 
        return t ? t->name : ERR_PTR(-ENOENT);
 }
@@ -470,6 +470,7 @@ static struct cache_dfs_tgt *alloc_target(const char *name, int path_consumed)
 static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs,
                         struct cache_entry *ce, const char *tgthint)
 {
+       struct cache_dfs_tgt *target;
        int i;
 
        ce->ttl = max_t(int, refs[0].ttl, CACHE_MIN_TTL);
@@ -496,8 +497,9 @@ static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs,
                ce->numtgts++;
        }
 
-       ce->tgthint = list_first_entry_or_null(&ce->tlist,
-                                              struct cache_dfs_tgt, list);
+       target = list_first_entry_or_null(&ce->tlist, struct cache_dfs_tgt,
+                                         list);
+       WRITE_ONCE(ce->tgthint, target);
 
        return 0;
 }
@@ -558,7 +560,8 @@ static void remove_oldest_entry_locked(void)
 }
 
 /* Add a new DFS cache entry */
-static int add_cache_entry_locked(struct dfs_info3_param *refs, int numrefs)
+static struct cache_entry *add_cache_entry_locked(struct dfs_info3_param *refs,
+                                                 int numrefs)
 {
        int rc;
        struct cache_entry *ce;
@@ -573,11 +576,11 @@ static int add_cache_entry_locked(struct dfs_info3_param *refs, int numrefs)
 
        rc = cache_entry_hash(refs[0].path_name, strlen(refs[0].path_name), &hash);
        if (rc)
-               return rc;
+               return ERR_PTR(rc);
 
        ce = alloc_cache_entry(refs, numrefs);
        if (IS_ERR(ce))
-               return PTR_ERR(ce);
+               return ce;
 
        spin_lock(&cache_ttl_lock);
        if (!cache_ttl) {
@@ -594,7 +597,7 @@ static int add_cache_entry_locked(struct dfs_info3_param *refs, int numrefs)
 
        atomic_inc(&cache_count);
 
-       return 0;
+       return ce;
 }
 
 /* Check if two DFS paths are equal.  @s1 and @s2 are expected to be in @cache_cp's charset */
@@ -641,7 +644,9 @@ static struct cache_entry *__lookup_cache_entry(const char *path, unsigned int h
  *
  * Use whole path components in the match.  Must be called with htable_rw_lock held.
  *
+ * Return cached entry if successful.
  * Return ERR_PTR(-ENOENT) if the entry is not found.
+ * Return error ptr otherwise.
  */
 static struct cache_entry *lookup_cache_entry(const char *path)
 {
@@ -711,14 +716,15 @@ void dfs_cache_destroy(void)
 static int update_cache_entry_locked(struct cache_entry *ce, const struct dfs_info3_param *refs,
                                     int numrefs)
 {
+       struct cache_dfs_tgt *target;
+       char *th = NULL;
        int rc;
-       char *s, *th = NULL;
 
        WARN_ON(!rwsem_is_locked(&htable_rw_lock));
 
-       if (ce->tgthint) {
-               s = ce->tgthint->name;
-               th = kstrdup(s, GFP_ATOMIC);
+       target = READ_ONCE(ce->tgthint);
+       if (target) {
+               th = kstrdup(target->name, GFP_ATOMIC);
                if (!th)
                        return -ENOMEM;
        }
@@ -767,51 +773,75 @@ static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses, const
  *
  * For interlinks, cifs_mount() and expand_dfs_referral() are supposed to
  * handle them properly.
+ *
+ * On success, return entry with acquired lock for reading, otherwise error ptr.
  */
-static int cache_refresh_path(const unsigned int xid, struct cifs_ses *ses, const char *path)
+static struct cache_entry *cache_refresh_path(const unsigned int xid,
+                                             struct cifs_ses *ses,
+                                             const char *path,
+                                             bool force_refresh)
 {
-       int rc;
-       struct cache_entry *ce;
        struct dfs_info3_param *refs = NULL;
+       struct cache_entry *ce;
        int numrefs = 0;
-       bool newent = false;
+       int rc;
 
        cifs_dbg(FYI, "%s: search path: %s\n", __func__, path);
 
-       down_write(&htable_rw_lock);
+       down_read(&htable_rw_lock);
 
        ce = lookup_cache_entry(path);
        if (!IS_ERR(ce)) {
-               if (!cache_entry_expired(ce)) {
-                       dump_ce(ce);
-                       up_write(&htable_rw_lock);
-                       return 0;
-               }
-       } else {
-               newent = true;
+               if (!force_refresh && !cache_entry_expired(ce))
+                       return ce;
+       } else if (PTR_ERR(ce) != -ENOENT) {
+               up_read(&htable_rw_lock);
+               return ce;
        }
 
        /*
-        * Either the entry was not found, or it is expired.
+        * Unlock shared access as we don't want to hold any locks while getting
+        * a new referral.  The @ses used for performing the I/O could be
+        * reconnecting and it acquires @htable_rw_lock to look up the dfs cache
+        * in order to failover -- if necessary.
+        */
+       up_read(&htable_rw_lock);
+
+       /*
+        * Either the entry was not found, or it is expired, or it is a forced
+        * refresh.
         * Request a new DFS referral in order to create or update a cache entry.
         */
        rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
-       if (rc)
-               goto out_unlock;
+       if (rc) {
+               ce = ERR_PTR(rc);
+               goto out;
+       }
 
        dump_refs(refs, numrefs);
 
-       if (!newent) {
-               rc = update_cache_entry_locked(ce, refs, numrefs);
-               goto out_unlock;
+       down_write(&htable_rw_lock);
+       /* Re-check as another task might have it added or refreshed already */
+       ce = lookup_cache_entry(path);
+       if (!IS_ERR(ce)) {
+               if (force_refresh || cache_entry_expired(ce)) {
+                       rc = update_cache_entry_locked(ce, refs, numrefs);
+                       if (rc)
+                               ce = ERR_PTR(rc);
+               }
+       } else if (PTR_ERR(ce) == -ENOENT) {
+               ce = add_cache_entry_locked(refs, numrefs);
        }
 
-       rc = add_cache_entry_locked(refs, numrefs);
+       if (IS_ERR(ce)) {
+               up_write(&htable_rw_lock);
+               goto out;
+       }
 
-out_unlock:
-       up_write(&htable_rw_lock);
+       downgrade_write(&htable_rw_lock);
+out:
        free_dfs_info_array(refs, numrefs);
-       return rc;
+       return ce;
 }
 
 /*
@@ -878,7 +908,7 @@ static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl)
                }
                it->it_path_consumed = t->path_consumed;
 
-               if (ce->tgthint == t)
+               if (READ_ONCE(ce->tgthint) == t)
                        list_add(&it->it_list, head);
                else
                        list_add_tail(&it->it_list, head);
@@ -931,15 +961,8 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nl
        if (IS_ERR(npath))
                return PTR_ERR(npath);
 
-       rc = cache_refresh_path(xid, ses, npath);
-       if (rc)
-               goto out_free_path;
-
-       down_read(&htable_rw_lock);
-
-       ce = lookup_cache_entry(npath);
+       ce = cache_refresh_path(xid, ses, npath, false);
        if (IS_ERR(ce)) {
-               up_read(&htable_rw_lock);
                rc = PTR_ERR(ce);
                goto out_free_path;
        }
@@ -1003,72 +1026,6 @@ out_unlock:
 }
 
 /**
- * dfs_cache_update_tgthint - update target hint of a DFS cache entry
- *
- * If it doesn't find the cache entry, then it will get a DFS referral for @path
- * and create a new entry.
- *
- * In case the cache entry exists but expired, it will get a DFS referral
- * for @path and then update the respective cache entry.
- *
- * @xid: syscall id
- * @ses: smb session
- * @cp: codepage
- * @remap: type of character remapping for paths
- * @path: path to lookup in DFS referral cache
- * @it: DFS target iterator
- *
- * Return zero if the target hint was updated successfully, otherwise non-zero.
- */
-int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
-                            const struct nls_table *cp, int remap, const char *path,
-                            const struct dfs_cache_tgt_iterator *it)
-{
-       int rc;
-       const char *npath;
-       struct cache_entry *ce;
-       struct cache_dfs_tgt *t;
-
-       npath = dfs_cache_canonical_path(path, cp, remap);
-       if (IS_ERR(npath))
-               return PTR_ERR(npath);
-
-       cifs_dbg(FYI, "%s: update target hint - path: %s\n", __func__, npath);
-
-       rc = cache_refresh_path(xid, ses, npath);
-       if (rc)
-               goto out_free_path;
-
-       down_write(&htable_rw_lock);
-
-       ce = lookup_cache_entry(npath);
-       if (IS_ERR(ce)) {
-               rc = PTR_ERR(ce);
-               goto out_unlock;
-       }
-
-       t = ce->tgthint;
-
-       if (likely(!strcasecmp(it->it_name, t->name)))
-               goto out_unlock;
-
-       list_for_each_entry(t, &ce->tlist, list) {
-               if (!strcasecmp(t->name, it->it_name)) {
-                       ce->tgthint = t;
-                       cifs_dbg(FYI, "%s: new target hint: %s\n", __func__,
-                                it->it_name);
-                       break;
-               }
-       }
-
-out_unlock:
-       up_write(&htable_rw_lock);
-out_free_path:
-       kfree(npath);
-       return rc;
-}
-
-/**
  * dfs_cache_noreq_update_tgthint - update target hint of a DFS cache entry
  * without sending any requests to the currently connected server.
  *
@@ -1092,21 +1049,20 @@ void dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt
 
        cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
 
-       if (!down_write_trylock(&htable_rw_lock))
-               return;
+       down_read(&htable_rw_lock);
 
        ce = lookup_cache_entry(path);
        if (IS_ERR(ce))
                goto out_unlock;
 
-       t = ce->tgthint;
+       t = READ_ONCE(ce->tgthint);
 
        if (unlikely(!strcasecmp(it->it_name, t->name)))
                goto out_unlock;
 
        list_for_each_entry(t, &ce->tlist, list) {
                if (!strcasecmp(t->name, it->it_name)) {
-                       ce->tgthint = t;
+                       WRITE_ONCE(ce->tgthint, t);
                        cifs_dbg(FYI, "%s: new target hint: %s\n", __func__,
                                 it->it_name);
                        break;
@@ -1114,7 +1070,7 @@ void dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt
        }
 
 out_unlock:
-       up_write(&htable_rw_lock);
+       up_read(&htable_rw_lock);
 }
 
 /**
@@ -1320,35 +1276,37 @@ static bool target_share_equal(struct TCP_Server_Info *server, const char *s1, c
  * Mark dfs tcon for reconnecting when the currently connected tcon does not match any of the new
  * target shares in @refs.
  */
-static void mark_for_reconnect_if_needed(struct cifs_tcon *tcon, struct dfs_cache_tgt_list *tl,
-                                        const struct dfs_info3_param *refs, int numrefs)
+static void mark_for_reconnect_if_needed(struct TCP_Server_Info *server,
+                                        struct dfs_cache_tgt_list *old_tl,
+                                        struct dfs_cache_tgt_list *new_tl)
 {
-       struct dfs_cache_tgt_iterator *it;
-       int i;
-
-       for (it = dfs_cache_get_tgt_iterator(tl); it; it = dfs_cache_get_next_tgt(tl, it)) {
-               for (i = 0; i < numrefs; i++) {
-                       if (target_share_equal(tcon->ses->server, dfs_cache_get_tgt_name(it),
-                                              refs[i].node_name))
+       struct dfs_cache_tgt_iterator *oit, *nit;
+
+       for (oit = dfs_cache_get_tgt_iterator(old_tl); oit;
+            oit = dfs_cache_get_next_tgt(old_tl, oit)) {
+               for (nit = dfs_cache_get_tgt_iterator(new_tl); nit;
+                    nit = dfs_cache_get_next_tgt(new_tl, nit)) {
+                       if (target_share_equal(server,
+                                              dfs_cache_get_tgt_name(oit),
+                                              dfs_cache_get_tgt_name(nit)))
                                return;
                }
        }
 
        cifs_dbg(FYI, "%s: no cached or matched targets. mark dfs share for reconnect.\n", __func__);
-       cifs_signal_cifsd_for_reconnect(tcon->ses->server, true);
+       cifs_signal_cifsd_for_reconnect(server, true);
 }
 
 /* Refresh dfs referral of tcon and mark it for reconnect if needed */
 static int __refresh_tcon(const char *path, struct cifs_tcon *tcon, bool force_refresh)
 {
-       struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
+       struct dfs_cache_tgt_list old_tl = DFS_CACHE_TGT_LIST_INIT(old_tl);
+       struct dfs_cache_tgt_list new_tl = DFS_CACHE_TGT_LIST_INIT(new_tl);
        struct cifs_ses *ses = CIFS_DFS_ROOT_SES(tcon->ses);
        struct cifs_tcon *ipc = ses->tcon_ipc;
-       struct dfs_info3_param *refs = NULL;
        bool needs_refresh = false;
        struct cache_entry *ce;
        unsigned int xid;
-       int numrefs = 0;
        int rc = 0;
 
        xid = get_xid();
@@ -1357,9 +1315,8 @@ static int __refresh_tcon(const char *path, struct cifs_tcon *tcon, bool force_r
        ce = lookup_cache_entry(path);
        needs_refresh = force_refresh || IS_ERR(ce) || cache_entry_expired(ce);
        if (!IS_ERR(ce)) {
-               rc = get_targets(ce, &tl);
-               if (rc)
-                       cifs_dbg(FYI, "%s: could not get dfs targets: %d\n", __func__, rc);
+               rc = get_targets(ce, &old_tl);
+               cifs_dbg(FYI, "%s: get_targets: %d\n", __func__, rc);
        }
        up_read(&htable_rw_lock);
 
@@ -1376,26 +1333,18 @@ static int __refresh_tcon(const char *path, struct cifs_tcon *tcon, bool force_r
        }
        spin_unlock(&ipc->tc_lock);
 
-       rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
-       if (!rc) {
-               /* Create or update a cache entry with the new referral */
-               dump_refs(refs, numrefs);
-
-               down_write(&htable_rw_lock);
-               ce = lookup_cache_entry(path);
-               if (IS_ERR(ce))
-                       add_cache_entry_locked(refs, numrefs);
-               else if (force_refresh || cache_entry_expired(ce))
-                       update_cache_entry_locked(ce, refs, numrefs);
-               up_write(&htable_rw_lock);
-
-               mark_for_reconnect_if_needed(tcon, &tl, refs, numrefs);
+       ce = cache_refresh_path(xid, ses, path, true);
+       if (!IS_ERR(ce)) {
+               rc = get_targets(ce, &new_tl);
+               up_read(&htable_rw_lock);
+               cifs_dbg(FYI, "%s: get_targets: %d\n", __func__, rc);
+               mark_for_reconnect_if_needed(tcon->ses->server, &old_tl, &new_tl);
        }
 
 out:
        free_xid(xid);
-       dfs_cache_free_tgts(&tl);
-       free_dfs_info_array(refs, numrefs);
+       dfs_cache_free_tgts(&old_tl);
+       dfs_cache_free_tgts(&new_tl);
        return rc;
 }
 
index f7cff0b..be3b5a4 100644 (file)
@@ -35,9 +35,6 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nl
                   struct dfs_cache_tgt_list *tgt_list);
 int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
                         struct dfs_cache_tgt_list *tgt_list);
-int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
-                            const struct nls_table *cp, int remap, const char *path,
-                            const struct dfs_cache_tgt_iterator *it);
 void dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt_iterator *it);
 int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iterator *it,
                               struct dfs_info3_param *ref);
index 4b71f4a..2c9ffa9 100644 (file)
@@ -4163,12 +4163,15 @@ smb2_readv_callback(struct mid_q_entry *mid)
                                (struct smb2_hdr *)rdata->iov[0].iov_base;
        struct cifs_credits credits = { .value = 0, .instance = 0 };
        struct smb_rqst rqst = { .rq_iov = &rdata->iov[1],
-                                .rq_nvec = 1,
-                                .rq_pages = rdata->pages,
-                                .rq_offset = rdata->page_offset,
-                                .rq_npages = rdata->nr_pages,
-                                .rq_pagesz = rdata->pagesz,
-                                .rq_tailsz = rdata->tailsz };
+                                .rq_nvec = 1, };
+
+       if (rdata->got_bytes) {
+               rqst.rq_pages = rdata->pages;
+               rqst.rq_offset = rdata->page_offset;
+               rqst.rq_npages = rdata->nr_pages;
+               rqst.rq_pagesz = rdata->pagesz;
+               rqst.rq_tailsz = rdata->tailsz;
+       }
 
        WARN_ONCE(rdata->server != mid->server,
                  "rdata server %p != mid server %p",
index 481788c..626a615 100644 (file)
@@ -577,26 +577,25 @@ static int erofs_fc_parse_param(struct fs_context *fc,
                }
                ++ctx->devs->extra_devices;
                break;
-       case Opt_fsid:
 #ifdef CONFIG_EROFS_FS_ONDEMAND
+       case Opt_fsid:
                kfree(ctx->fsid);
                ctx->fsid = kstrdup(param->string, GFP_KERNEL);
                if (!ctx->fsid)
                        return -ENOMEM;
-#else
-               errorfc(fc, "fsid option not supported");
-#endif
                break;
        case Opt_domain_id:
-#ifdef CONFIG_EROFS_FS_ONDEMAND
                kfree(ctx->domain_id);
                ctx->domain_id = kstrdup(param->string, GFP_KERNEL);
                if (!ctx->domain_id)
                        return -ENOMEM;
+               break;
 #else
-               errorfc(fc, "domain_id option not supported");
-#endif
+       case Opt_fsid:
+       case Opt_domain_id:
+               errorfc(fc, "%s option not supported", erofs_fs_parameters[opt].name);
                break;
+#endif
        default:
                return -ENOPARAM;
        }
index ccf7c55..5200bb8 100644 (file)
@@ -1032,12 +1032,12 @@ static int z_erofs_decompress_pcluster(struct z_erofs_decompress_backend *be,
 
        if (!be->decompressed_pages)
                be->decompressed_pages =
-                       kvcalloc(be->nr_pages, sizeof(struct page *),
-                                GFP_KERNEL | __GFP_NOFAIL);
+                       kcalloc(be->nr_pages, sizeof(struct page *),
+                               GFP_KERNEL | __GFP_NOFAIL);
        if (!be->compressed_pages)
                be->compressed_pages =
-                       kvcalloc(pclusterpages, sizeof(struct page *),
-                                GFP_KERNEL | __GFP_NOFAIL);
+                       kcalloc(pclusterpages, sizeof(struct page *),
+                               GFP_KERNEL | __GFP_NOFAIL);
 
        z_erofs_parse_out_bvecs(be);
        err2 = z_erofs_parse_in_bvecs(be, &overlapped);
@@ -1085,7 +1085,7 @@ out:
        }
        if (be->compressed_pages < be->onstack_pages ||
            be->compressed_pages >= be->onstack_pages + Z_EROFS_ONSTACK_PAGES)
-               kvfree(be->compressed_pages);
+               kfree(be->compressed_pages);
        z_erofs_fill_other_copies(be, err);
 
        for (i = 0; i < be->nr_pages; ++i) {
@@ -1104,7 +1104,7 @@ out:
        }
 
        if (be->decompressed_pages != be->onstack_pages)
-               kvfree(be->decompressed_pages);
+               kfree(be->decompressed_pages);
 
        pcl->length = 0;
        pcl->partial = true;
index 0150570..98fb90b 100644 (file)
@@ -793,12 +793,16 @@ static int z_erofs_iomap_begin_report(struct inode *inode, loff_t offset,
                iomap->type = IOMAP_HOLE;
                iomap->addr = IOMAP_NULL_ADDR;
                /*
-                * No strict rule how to describe extents for post EOF, yet
-                * we need do like below. Otherwise, iomap itself will get
+                * No strict rule on how to describe extents for post EOF, yet
+                * we need to do like below. Otherwise, iomap itself will get
                 * into an endless loop on post EOF.
+                *
+                * Calculate the effective offset by subtracting extent start
+                * (map.m_la) from the requested offset, and add it to length.
+                * (NB: offset >= map.m_la always)
                 */
                if (iomap->offset >= inode->i_size)
-                       iomap->length = length + map.m_la - offset;
+                       iomap->length = length + offset - map.m_la;
        }
        iomap->flags = 0;
        return 0;
index 7decaaf..69a1b8c 100644 (file)
@@ -81,6 +81,8 @@ ext4_xattr_block_cache_find(struct inode *, struct ext4_xattr_header *,
                            struct mb_cache_entry **);
 static __le32 ext4_xattr_hash_entry(char *name, size_t name_len, __le32 *value,
                                    size_t value_count);
+static __le32 ext4_xattr_hash_entry_signed(char *name, size_t name_len, __le32 *value,
+                                   size_t value_count);
 static void ext4_xattr_rehash(struct ext4_xattr_header *);
 
 static const struct xattr_handler * const ext4_xattr_handler_map[] = {
@@ -470,8 +472,21 @@ ext4_xattr_inode_verify_hashes(struct inode *ea_inode,
                tmp_data = cpu_to_le32(hash);
                e_hash = ext4_xattr_hash_entry(entry->e_name, entry->e_name_len,
                                               &tmp_data, 1);
-               if (e_hash != entry->e_hash)
-                       return -EFSCORRUPTED;
+               /* All good? */
+               if (e_hash == entry->e_hash)
+                       return 0;
+
+               /*
+                * Not good. Maybe the entry hash was calculated
+                * using the buggy signed char version?
+                */
+               e_hash = ext4_xattr_hash_entry_signed(entry->e_name, entry->e_name_len,
+                                                       &tmp_data, 1);
+               if (e_hash == entry->e_hash)
+                       return 0;
+
+               /* Still no match - bad */
+               return -EFSCORRUPTED;
        }
        return 0;
 }
@@ -3091,6 +3106,28 @@ static __le32 ext4_xattr_hash_entry(char *name, size_t name_len, __le32 *value,
        return cpu_to_le32(hash);
 }
 
+/*
+ * ext4_xattr_hash_entry_signed()
+ *
+ * Compute the hash of an extended attribute incorrectly.
+ */
+static __le32 ext4_xattr_hash_entry_signed(char *name, size_t name_len, __le32 *value, size_t value_count)
+{
+       __u32 hash = 0;
+
+       while (name_len--) {
+               hash = (hash << NAME_HASH_SHIFT) ^
+                      (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
+                      (signed char)*name++;
+       }
+       while (value_count--) {
+               hash = (hash << VALUE_HASH_SHIFT) ^
+                      (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
+                      le32_to_cpu(*value++);
+       }
+       return cpu_to_le32(hash);
+}
+
 #undef NAME_HASH_SHIFT
 #undef VALUE_HASH_SHIFT
 
index 8c854ba..51a4b78 100644 (file)
@@ -195,7 +195,7 @@ struct nfsd_net {
 
        atomic_t                nfsd_courtesy_clients;
        struct shrinker         nfsd_client_shrinker;
-       struct delayed_work     nfsd_shrinker_work;
+       struct work_struct      nfsd_shrinker_work;
 };
 
 /* Simple check to find out if a given net was properly initialized */
index 9b81d01..f189ba7 100644 (file)
@@ -1318,6 +1318,7 @@ try_again:
                        /* allow 20secs for mount/unmount for now - revisit */
                        if (signal_pending(current) ||
                                        (schedule_timeout(20*HZ) == 0)) {
+                               finish_wait(&nn->nfsd_ssc_waitq, &wait);
                                kfree(work);
                                return nfserr_eagain;
                        }
index 4809ae0..4ef5293 100644 (file)
@@ -4411,7 +4411,7 @@ nfsd4_state_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
        if (!count)
                count = atomic_long_read(&num_delegations);
        if (count)
-               mod_delayed_work(laundry_wq, &nn->nfsd_shrinker_work, 0);
+               queue_work(laundry_wq, &nn->nfsd_shrinker_work);
        return (unsigned long)count;
 }
 
@@ -4421,7 +4421,7 @@ nfsd4_state_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
        return SHRINK_STOP;
 }
 
-int
+void
 nfsd4_init_leases_net(struct nfsd_net *nn)
 {
        struct sysinfo si;
@@ -4443,16 +4443,6 @@ nfsd4_init_leases_net(struct nfsd_net *nn)
        nn->nfs4_max_clients = max_t(int, max_clients, NFS4_CLIENTS_PER_GB);
 
        atomic_set(&nn->nfsd_courtesy_clients, 0);
-       nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
-       nn->nfsd_client_shrinker.count_objects = nfsd4_state_shrinker_count;
-       nn->nfsd_client_shrinker.seeks = DEFAULT_SEEKS;
-       return register_shrinker(&nn->nfsd_client_shrinker, "nfsd-client");
-}
-
-void
-nfsd4_leases_net_shutdown(struct nfsd_net *nn)
-{
-       unregister_shrinker(&nn->nfsd_client_shrinker);
 }
 
 static void init_nfs4_replay(struct nfs4_replay *rp)
@@ -6235,8 +6225,7 @@ deleg_reaper(struct nfsd_net *nn)
 static void
 nfsd4_state_shrinker_worker(struct work_struct *work)
 {
-       struct delayed_work *dwork = to_delayed_work(work);
-       struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
+       struct nfsd_net *nn = container_of(work, struct nfsd_net,
                                nfsd_shrinker_work);
 
        courtesy_client_reaper(nn);
@@ -8066,11 +8055,20 @@ static int nfs4_state_create_net(struct net *net)
        INIT_LIST_HEAD(&nn->blocked_locks_lru);
 
        INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
-       INIT_DELAYED_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker);
+       INIT_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker);
        get_net(net);
 
+       nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
+       nn->nfsd_client_shrinker.count_objects = nfsd4_state_shrinker_count;
+       nn->nfsd_client_shrinker.seeks = DEFAULT_SEEKS;
+
+       if (register_shrinker(&nn->nfsd_client_shrinker, "nfsd-client"))
+               goto err_shrinker;
        return 0;
 
+err_shrinker:
+       put_net(net);
+       kfree(nn->sessionid_hashtbl);
 err_sessionid:
        kfree(nn->unconf_id_hashtbl);
 err_unconf_id:
@@ -8163,6 +8161,8 @@ nfs4_state_shutdown_net(struct net *net)
        struct list_head *pos, *next, reaplist;
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
+       unregister_shrinker(&nn->nfsd_client_shrinker);
+       cancel_work(&nn->nfsd_shrinker_work);
        cancel_delayed_work_sync(&nn->laundromat_work);
        locks_end_grace(&nn->nfsd4_manager);
 
index d1e581a..c2577ee 100644 (file)
@@ -1457,9 +1457,7 @@ static __net_init int nfsd_init_net(struct net *net)
                goto out_idmap_error;
        nn->nfsd_versions = NULL;
        nn->nfsd4_minorversions = NULL;
-       retval = nfsd4_init_leases_net(nn);
-       if (retval)
-               goto out_drc_error;
+       nfsd4_init_leases_net(nn);
        retval = nfsd_reply_cache_init(nn);
        if (retval)
                goto out_cache_error;
@@ -1469,8 +1467,6 @@ static __net_init int nfsd_init_net(struct net *net)
        return 0;
 
 out_cache_error:
-       nfsd4_leases_net_shutdown(nn);
-out_drc_error:
        nfsd_idmap_shutdown(net);
 out_idmap_error:
        nfsd_export_shutdown(net);
@@ -1486,7 +1482,6 @@ static __net_exit void nfsd_exit_net(struct net *net)
        nfsd_idmap_shutdown(net);
        nfsd_export_shutdown(net);
        nfsd_netns_free_versions(net_generic(net, nfsd_net_id));
-       nfsd4_leases_net_shutdown(nn);
 }
 
 static struct pernet_operations nfsd_net_ops = {
index 93b42ef..fa0144a 100644 (file)
@@ -504,8 +504,7 @@ extern void unregister_cld_notifier(void);
 extern void nfsd4_ssc_init_umount_work(struct nfsd_net *nn);
 #endif
 
-extern int nfsd4_init_leases_net(struct nfsd_net *nn);
-extern void nfsd4_leases_net_shutdown(struct nfsd_net *nn);
+extern void nfsd4_init_leases_net(struct nfsd_net *nn);
 
 #else /* CONFIG_NFSD_V4 */
 static inline int nfsd4_is_junction(struct dentry *dentry)
@@ -513,8 +512,7 @@ static inline int nfsd4_is_junction(struct dentry *dentry)
        return 0;
 }
 
-static inline int nfsd4_init_leases_net(struct nfsd_net *nn) { return 0; };
-static inline void nfsd4_leases_net_shutdown(struct nfsd_net *nn) {};
+static inline void nfsd4_init_leases_net(struct nfsd_net *nn) { };
 
 #define register_cld_notifier() 0
 #define unregister_cld_notifier() do { } while(0)
index b9d15c3..40ce92a 100644 (file)
@@ -480,9 +480,18 @@ static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
        ret = nilfs_btnode_submit_block(btnc, ptr, 0, REQ_OP_READ, &bh,
                                        &submit_ptr);
        if (ret) {
-               if (ret != -EEXIST)
-                       return ret;
-               goto out_check;
+               if (likely(ret == -EEXIST))
+                       goto out_check;
+               if (ret == -ENOENT) {
+                       /*
+                        * Block address translation failed due to invalid
+                        * value of 'ptr'.  In this case, return internal code
+                        * -EINVAL (broken bmap) to notify bmap layer of fatal
+                        * metadata corruption.
+                        */
+                       ret = -EINVAL;
+               }
+               return ret;
        }
 
        if (ra) {
index 98ac37e..cc69484 100644 (file)
@@ -108,6 +108,21 @@ static bool userfaultfd_is_initialized(struct userfaultfd_ctx *ctx)
        return ctx->features & UFFD_FEATURE_INITIALIZED;
 }
 
+static void userfaultfd_set_vm_flags(struct vm_area_struct *vma,
+                                    vm_flags_t flags)
+{
+       const bool uffd_wp_changed = (vma->vm_flags ^ flags) & VM_UFFD_WP;
+
+       vma->vm_flags = flags;
+       /*
+        * For shared mappings, we want to enable writenotify while
+        * userfaultfd-wp is enabled (see vma_wants_writenotify()). We'll simply
+        * recalculate vma->vm_page_prot whenever userfaultfd-wp changes.
+        */
+       if ((vma->vm_flags & VM_SHARED) && uffd_wp_changed)
+               vma_set_page_prot(vma);
+}
+
 static int userfaultfd_wake_function(wait_queue_entry_t *wq, unsigned mode,
                                     int wake_flags, void *key)
 {
@@ -618,7 +633,8 @@ static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
                for_each_vma(vmi, vma) {
                        if (vma->vm_userfaultfd_ctx.ctx == release_new_ctx) {
                                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
-                               vma->vm_flags &= ~__VM_UFFD_FLAGS;
+                               userfaultfd_set_vm_flags(vma,
+                                                        vma->vm_flags & ~__VM_UFFD_FLAGS);
                        }
                }
                mmap_write_unlock(mm);
@@ -652,7 +668,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs)
        octx = vma->vm_userfaultfd_ctx.ctx;
        if (!octx || !(octx->features & UFFD_FEATURE_EVENT_FORK)) {
                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
-               vma->vm_flags &= ~__VM_UFFD_FLAGS;
+               userfaultfd_set_vm_flags(vma, vma->vm_flags & ~__VM_UFFD_FLAGS);
                return 0;
        }
 
@@ -733,7 +749,7 @@ void mremap_userfaultfd_prep(struct vm_area_struct *vma,
        } else {
                /* Drop uffd context if remap feature not enabled */
                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
-               vma->vm_flags &= ~__VM_UFFD_FLAGS;
+               userfaultfd_set_vm_flags(vma, vma->vm_flags & ~__VM_UFFD_FLAGS);
        }
 }
 
@@ -895,7 +911,7 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
                        prev = vma;
                }
 
-               vma->vm_flags = new_flags;
+               userfaultfd_set_vm_flags(vma, new_flags);
                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
        }
        mmap_write_unlock(mm);
@@ -1463,7 +1479,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
                 * the next vma was merged into the current one and
                 * the current one has not been updated yet.
                 */
-               vma->vm_flags = new_flags;
+               userfaultfd_set_vm_flags(vma, new_flags);
                vma->vm_userfaultfd_ctx.ctx = ctx;
 
                if (is_vm_hugetlb_page(vma) && uffd_disable_huge_pmd_share(vma))
@@ -1651,7 +1667,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
                 * the next vma was merged into the current one and
                 * the current one has not been updated yet.
                 */
-               vma->vm_flags = new_flags;
+               userfaultfd_set_vm_flags(vma, new_flags);
                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
 
        skip:
index 2c53fbb..a9c5c3f 100644 (file)
@@ -442,6 +442,10 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
                        data_size = zonefs_check_zone_condition(inode, zone,
                                                                false, false);
                }
+       } else if (sbi->s_mount_opts & ZONEFS_MNTOPT_ERRORS_RO &&
+                  data_size > isize) {
+               /* Do not expose garbage data */
+               data_size = isize;
        }
 
        /*
@@ -805,6 +809,24 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
 
        ret = submit_bio_wait(bio);
 
+       /*
+        * If the file zone was written underneath the file system, the zone
+        * write pointer may not be where we expect it to be, but the zone
+        * append write can still succeed. So check manually that we wrote where
+        * we intended to, that is, at zi->i_wpoffset.
+        */
+       if (!ret) {
+               sector_t wpsector =
+                       zi->i_zsector + (zi->i_wpoffset >> SECTOR_SHIFT);
+
+               if (bio->bi_iter.bi_sector != wpsector) {
+                       zonefs_warn(inode->i_sb,
+                               "Corrupted write pointer %llu for zone at %llu\n",
+                               wpsector, zi->i_zsector);
+                       ret = -EIO;
+               }
+       }
+
        zonefs_file_write_dio_end_io(iocb, size, ret, 0);
        trace_zonefs_file_dio_append(inode, size, ret);
 
index 3de24cf..634d37a 100644 (file)
@@ -1832,7 +1832,7 @@ void bpf_prog_inc(struct bpf_prog *prog);
 struct bpf_prog * __must_check bpf_prog_inc_not_zero(struct bpf_prog *prog);
 void bpf_prog_put(struct bpf_prog *prog);
 
-void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock);
+void bpf_prog_free_id(struct bpf_prog *prog);
 void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock);
 
 struct btf_field *btf_record_find(const struct btf_record *rec,
index b986e26..b09f443 100644 (file)
@@ -545,8 +545,8 @@ int zynqmp_pm_request_wake(const u32 node,
                           const u64 address,
                           const enum zynqmp_pm_request_ack ack);
 int zynqmp_pm_get_rpu_mode(u32 node_id, enum rpu_oper_mode *rpu_mode);
-int zynqmp_pm_set_rpu_mode(u32 node_id, u32 arg1);
-int zynqmp_pm_set_tcm_config(u32 node_id, u32 arg1);
+int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode);
+int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode);
 int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value);
 int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
                             u32 value);
@@ -845,12 +845,12 @@ static inline int zynqmp_pm_get_rpu_mode(u32 node_id, enum rpu_oper_mode *rpu_mo
        return -ENODEV;
 }
 
-static inline int zynqmp_pm_set_rpu_mode(u32 node_id, u32 arg1)
+static inline int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode)
 {
        return -ENODEV;
 }
 
-static inline int zynqmp_pm_set_tcm_config(u32 node_id, u32 arg1)
+static inline int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode)
 {
        return -ENODEV;
 }
index f3f196e..8f85716 100644 (file)
@@ -1270,10 +1270,10 @@ static inline void folio_put_refs(struct folio *folio, int refs)
                __folio_put(folio);
 }
 
-/**
- * release_pages - release an array of pages or folios
+/*
+ * union release_pages_arg - an array of pages or folios
  *
- * This just releases a simple array of multiple pages, and
+ * release_pages() releases a simple array of multiple pages, and
  * accepts various different forms of said page array: either
  * a regular old boring array of pages, an array of folios, or
  * an array of encoded page pointers.
index e8ed225..ff3f3f2 100644 (file)
@@ -413,8 +413,7 @@ static inline void free_anon_vma_name(struct vm_area_struct *vma)
         * Not using anon_vma_name because it generates a warning if mmap_lock
         * is not held, which might be the case here.
         */
-       if (!vma->vm_file)
-               anon_vma_name_put(vma->anon_name);
+       anon_vma_name_put(vma->anon_name);
 }
 
 static inline bool anon_vma_name_eq(struct anon_vma_name *anon_name1,
index 3b84750..9757067 100644 (file)
@@ -581,7 +581,7 @@ struct vm_area_struct {
        /*
         * For private and shared anonymous mappings, a pointer to a null
         * terminated string containing the name given to the vma, or NULL if
-        * unnamed. Serialized by mmap_sem. Use anon_vma_name to access.
+        * unnamed. Serialized by mmap_lock. Use anon_vma_name to access.
         */
        struct anon_vma_name *anon_name;
 #endif
index 2e677e6..d7c2d33 100644 (file)
@@ -301,7 +301,7 @@ static inline bool folio_ref_try_add_rcu(struct folio *folio, int count)
  *
  * You can also use this function if you're holding a lock that prevents
  * pages being frozen & removed; eg the i_pages lock for the page cache
- * or the mmap_sem or page table lock for page tables.  In this case,
+ * or the mmap_lock or page table lock for page tables.  In this case,
  * it will always succeed, and you could have used a plain folio_get(),
  * but it's sometimes more convenient to have a common function called
  * from both locked and RCU-protected contexts.
index f7f1272..9a60f45 100644 (file)
@@ -5,7 +5,7 @@
 #ifndef __ASSEMBLER__
 #include <linux/types.h>
 
-#ifdef CONFIG_ARCH_OMAP1_ANY
+#ifdef CONFIG_ARCH_OMAP1
 /*
  * NOTE: Please use ioremap + __raw_read/write where possible instead of these
  */
@@ -15,7 +15,7 @@ extern u32 omap_readl(u32 pa);
 extern void omap_writeb(u8 v, u32 pa);
 extern void omap_writew(u16 v, u32 pa);
 extern void omap_writel(u32 v, u32 pa);
-#else
+#elif defined(CONFIG_COMPILE_TEST)
 static inline u8 omap_readb(u32 pa)  { return 0; }
 static inline u16 omap_readw(u32 pa) { return 0; }
 static inline u32 omap_readl(u32 pa) { return 0; }
index 7d5325d..86d1c8e 100644 (file)
@@ -267,16 +267,15 @@ static inline void *usb_get_intfdata(struct usb_interface *intf)
 }
 
 /**
- * usb_set_intfdata() - associate driver-specific data with the interface
- * @intf: the usb interface
- * @data: pointer to the device priv structure or %NULL
+ * usb_set_intfdata() - associate driver-specific data with an interface
+ * @intf: USB interface
+ * @data: driver data
  *
- * Drivers should use this function in their probe() to associate their
- * driver-specific data with the usb interface.
+ * Drivers can use this function in their probe() callbacks to associate
+ * driver-specific data with an interface.
  *
- * When disconnecting, the core will take care of setting @intf back to %NULL,
- * so no actions are needed on the driver side. The interface should not be set
- * to %NULL before all actions completed (e.g. no outsanding URB remaining).
+ * Note that there is generally no need to clear the driver-data pointer even
+ * if some drivers do so for historical or implementation-specific reasons.
  */
 static inline void usb_set_intfdata(struct usb_interface *intf, void *data)
 {
@@ -774,11 +773,14 @@ extern struct device *usb_intf_get_dma_device(struct usb_interface *intf);
 extern int usb_acpi_set_power_state(struct usb_device *hdev, int index,
        bool enable);
 extern bool usb_acpi_power_manageable(struct usb_device *hdev, int index);
+extern int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index);
 #else
 static inline int usb_acpi_set_power_state(struct usb_device *hdev, int index,
        bool enable) { return 0; }
 static inline bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
        { return true; }
+static inline int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index)
+       { return 0; }
 #endif
 
 /* USB autosuspend and autoresume */
index 689da32..e3235b9 100644 (file)
@@ -1832,8 +1832,6 @@ struct ieee80211_vif_cfg {
  * @drv_priv: data area for driver use, will always be aligned to
  *     sizeof(void \*).
  * @txq: the multicast data TX queue
- * @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped,
- *     protected by fq->lock.
  * @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
  *     &enum ieee80211_offload_flags.
  * @mbssid_tx_vif: Pointer to the transmitting interface if MBSSID is enabled.
@@ -1863,8 +1861,6 @@ struct ieee80211_vif {
        bool probe_req_reg;
        bool rx_mcast_action_reg;
 
-       bool txqs_stopped[IEEE80211_NUM_ACS];
-
        struct ieee80211_vif *mbssid_tx_vif;
 
        /* must be last */
index d551771..af4aa66 100644 (file)
@@ -1288,4 +1288,11 @@ void mq_change_real_num_tx(struct Qdisc *sch, unsigned int new_real_tx);
 
 int sch_frag_xmit_hook(struct sk_buff *skb, int (*xmit)(struct sk_buff *skb));
 
+/* Make sure qdisc is no longer in SCHED state. */
+static inline void qdisc_synchronize(const struct Qdisc *q)
+{
+       while (test_bit(__QDISC_STATE_SCHED, &q->state))
+               msleep(1);
+}
+
 #endif
index ab95559..73cac8d 100644 (file)
@@ -170,7 +170,7 @@ struct rpi_firmware_clk_rate_request {
 
 #define RPI_FIRMWARE_CLK_RATE_REQUEST(_id)     \
        {                                       \
-               .id = _id,                      \
+               .id = cpu_to_le32(_id),         \
        }
 
 #if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
index 0958846..44e90b2 100644 (file)
@@ -204,7 +204,7 @@ config LOCALVERSION_AUTO
          appended after any matching localversion* files, and after the value
          set in CONFIG_LOCALVERSION.
 
-         (The actual string used here is the first eight characters produced
+         (The actual string used here is the first 12 characters produced
          by running the command:
 
            $ git rev-parse --verify HEAD
@@ -776,7 +776,7 @@ config PRINTK_SAFE_LOG_BUF_SHIFT
        depends on PRINTK
        help
          Select the size of an alternate printk per-CPU buffer where messages
-         printed from usafe contexts are temporary stored. One example would
+         printed from unsafe contexts are temporary stored. One example would
          be NMI messages, another one - printk recursion. The messages are
          copied to the main log buffer in a safe context to avoid a deadlock.
          The value defines the size as a power of 2.
index 179e93b..043cbf8 100644 (file)
@@ -2,7 +2,6 @@
 
 #include <generated/compile.h>
 #include <generated/utsrelease.h>
-#include <linux/version.h>
 #include <linux/proc_ns.h>
 #include <linux/refcount.h>
 #include <linux/uts.h>
index 2ac1cd8..0a4efad 100644 (file)
@@ -3674,7 +3674,7 @@ static __cold int io_uring_create(unsigned entries, struct io_uring_params *p,
 
        if (ctx->flags & IORING_SETUP_SINGLE_ISSUER
            && !(ctx->flags & IORING_SETUP_R_DISABLED))
-               ctx->submitter_task = get_task_struct(current);
+               WRITE_ONCE(ctx->submitter_task, get_task_struct(current));
 
        file = io_uring_get_file(ctx);
        if (IS_ERR(file)) {
@@ -3868,7 +3868,7 @@ static int io_register_enable_rings(struct io_ring_ctx *ctx)
                return -EBADFD;
 
        if (ctx->flags & IORING_SETUP_SINGLE_ISSUER && !ctx->submitter_task)
-               ctx->submitter_task = get_task_struct(current);
+               WRITE_ONCE(ctx->submitter_task, get_task_struct(current));
 
        if (ctx->restrictions.registered)
                ctx->restricted = 1;
index 2d3cd94..15602a1 100644 (file)
@@ -25,6 +25,28 @@ struct io_msg {
        u32 flags;
 };
 
+static void io_double_unlock_ctx(struct io_ring_ctx *octx)
+{
+       mutex_unlock(&octx->uring_lock);
+}
+
+static int io_double_lock_ctx(struct io_ring_ctx *octx,
+                             unsigned int issue_flags)
+{
+       /*
+        * To ensure proper ordering between the two ctxs, we can only
+        * attempt a trylock on the target. If that fails and we already have
+        * the source ctx lock, punt to io-wq.
+        */
+       if (!(issue_flags & IO_URING_F_UNLOCKED)) {
+               if (!mutex_trylock(&octx->uring_lock))
+                       return -EAGAIN;
+               return 0;
+       }
+       mutex_lock(&octx->uring_lock);
+       return 0;
+}
+
 void io_msg_ring_cleanup(struct io_kiocb *req)
 {
        struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
@@ -36,6 +58,29 @@ void io_msg_ring_cleanup(struct io_kiocb *req)
        msg->src_file = NULL;
 }
 
+static inline bool io_msg_need_remote(struct io_ring_ctx *target_ctx)
+{
+       if (!target_ctx->task_complete)
+               return false;
+       return current != target_ctx->submitter_task;
+}
+
+static int io_msg_exec_remote(struct io_kiocb *req, task_work_func_t func)
+{
+       struct io_ring_ctx *ctx = req->file->private_data;
+       struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
+       struct task_struct *task = READ_ONCE(ctx->submitter_task);
+
+       if (unlikely(!task))
+               return -EOWNERDEAD;
+
+       init_task_work(&msg->tw, func);
+       if (task_work_add(ctx->submitter_task, &msg->tw, TWA_SIGNAL))
+               return -EOWNERDEAD;
+
+       return IOU_ISSUE_SKIP_COMPLETE;
+}
+
 static void io_msg_tw_complete(struct callback_head *head)
 {
        struct io_msg *msg = container_of(head, struct io_msg, tw);
@@ -43,61 +88,54 @@ static void io_msg_tw_complete(struct callback_head *head)
        struct io_ring_ctx *target_ctx = req->file->private_data;
        int ret = 0;
 
-       if (current->flags & PF_EXITING)
+       if (current->flags & PF_EXITING) {
                ret = -EOWNERDEAD;
-       else if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
-               ret = -EOVERFLOW;
+       } else {
+               /*
+                * If the target ring is using IOPOLL mode, then we need to be
+                * holding the uring_lock for posting completions. Other ring
+                * types rely on the regular completion locking, which is
+                * handled while posting.
+                */
+               if (target_ctx->flags & IORING_SETUP_IOPOLL)
+                       mutex_lock(&target_ctx->uring_lock);
+               if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
+                       ret = -EOVERFLOW;
+               if (target_ctx->flags & IORING_SETUP_IOPOLL)
+                       mutex_unlock(&target_ctx->uring_lock);
+       }
 
        if (ret < 0)
                req_set_fail(req);
        io_req_queue_tw_complete(req, ret);
 }
 
-static int io_msg_ring_data(struct io_kiocb *req)
+static int io_msg_ring_data(struct io_kiocb *req, unsigned int issue_flags)
 {
        struct io_ring_ctx *target_ctx = req->file->private_data;
        struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
+       int ret;
 
        if (msg->src_fd || msg->dst_fd || msg->flags)
                return -EINVAL;
+       if (target_ctx->flags & IORING_SETUP_R_DISABLED)
+               return -EBADFD;
 
-       if (target_ctx->task_complete && current != target_ctx->submitter_task) {
-               init_task_work(&msg->tw, io_msg_tw_complete);
-               if (task_work_add(target_ctx->submitter_task, &msg->tw,
-                                 TWA_SIGNAL_NO_IPI))
-                       return -EOWNERDEAD;
-
-               atomic_or(IORING_SQ_TASKRUN, &target_ctx->rings->sq_flags);
-               return IOU_ISSUE_SKIP_COMPLETE;
-       }
-
-       if (io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
-               return 0;
+       if (io_msg_need_remote(target_ctx))
+               return io_msg_exec_remote(req, io_msg_tw_complete);
 
-       return -EOVERFLOW;
-}
-
-static void io_double_unlock_ctx(struct io_ring_ctx *octx,
-                                unsigned int issue_flags)
-{
-       mutex_unlock(&octx->uring_lock);
-}
-
-static int io_double_lock_ctx(struct io_ring_ctx *octx,
-                             unsigned int issue_flags)
-{
-       /*
-        * To ensure proper ordering between the two ctxs, we can only
-        * attempt a trylock on the target. If that fails and we already have
-        * the source ctx lock, punt to io-wq.
-        */
-       if (!(issue_flags & IO_URING_F_UNLOCKED)) {
-               if (!mutex_trylock(&octx->uring_lock))
+       ret = -EOVERFLOW;
+       if (target_ctx->flags & IORING_SETUP_IOPOLL) {
+               if (unlikely(io_double_lock_ctx(target_ctx, issue_flags)))
                        return -EAGAIN;
-               return 0;
+               if (io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
+                       ret = 0;
+               io_double_unlock_ctx(target_ctx);
+       } else {
+               if (io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
+                       ret = 0;
        }
-       mutex_lock(&octx->uring_lock);
-       return 0;
+       return ret;
 }
 
 static struct file *io_msg_grab_file(struct io_kiocb *req, unsigned int issue_flags)
@@ -148,7 +186,7 @@ static int io_msg_install_complete(struct io_kiocb *req, unsigned int issue_flag
        if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
                ret = -EOVERFLOW;
 out_unlock:
-       io_double_unlock_ctx(target_ctx, issue_flags);
+       io_double_unlock_ctx(target_ctx);
        return ret;
 }
 
@@ -174,6 +212,8 @@ static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags)
 
        if (target_ctx == ctx)
                return -EINVAL;
+       if (target_ctx->flags & IORING_SETUP_R_DISABLED)
+               return -EBADFD;
        if (!src_file) {
                src_file = io_msg_grab_file(req, issue_flags);
                if (!src_file)
@@ -182,14 +222,8 @@ static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags)
                req->flags |= REQ_F_NEED_CLEANUP;
        }
 
-       if (target_ctx->task_complete && current != target_ctx->submitter_task) {
-               init_task_work(&msg->tw, io_msg_tw_fd_complete);
-               if (task_work_add(target_ctx->submitter_task, &msg->tw,
-                                 TWA_SIGNAL))
-                       return -EOWNERDEAD;
-
-               return IOU_ISSUE_SKIP_COMPLETE;
-       }
+       if (io_msg_need_remote(target_ctx))
+               return io_msg_exec_remote(req, io_msg_tw_fd_complete);
        return io_msg_install_complete(req, issue_flags);
 }
 
@@ -224,7 +258,7 @@ int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags)
 
        switch (msg->cmd) {
        case IORING_MSG_DATA:
-               ret = io_msg_ring_data(req);
+               ret = io_msg_ring_data(req, issue_flags);
                break;
        case IORING_MSG_SEND_FD:
                ret = io_msg_send_fd(req, issue_flags);
index 32e5fc8..2ac1366 100644 (file)
@@ -283,8 +283,12 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
                         * to the waitqueue, so if we get nothing back, we
                         * should be safe and attempt a reissue.
                         */
-                       if (unlikely(!req->cqe.res))
+                       if (unlikely(!req->cqe.res)) {
+                               /* Multishot armed need not reissue */
+                               if (!(req->apoll_events & EPOLLONESHOT))
+                                       continue;
                                return IOU_POLL_REISSUE;
+                       }
                }
                if (req->apoll_events & EPOLLONESHOT)
                        return IOU_POLL_DONE;
index 5aa2b55..66bded1 100644 (file)
@@ -152,7 +152,7 @@ static inline int htab_lock_bucket(const struct bpf_htab *htab,
 {
        unsigned long flags;
 
-       hash = hash & HASHTAB_MAP_LOCK_MASK;
+       hash = hash & min_t(u32, HASHTAB_MAP_LOCK_MASK, htab->n_buckets - 1);
 
        preempt_disable();
        if (unlikely(__this_cpu_inc_return(*(htab->map_locked[hash])) != 1)) {
@@ -171,7 +171,7 @@ static inline void htab_unlock_bucket(const struct bpf_htab *htab,
                                      struct bucket *b, u32 hash,
                                      unsigned long flags)
 {
-       hash = hash & HASHTAB_MAP_LOCK_MASK;
+       hash = hash & min_t(u32, HASHTAB_MAP_LOCK_MASK, htab->n_buckets - 1);
        raw_spin_unlock_irqrestore(&b->raw_lock, flags);
        __this_cpu_dec(*(htab->map_locked[hash]));
        preempt_enable();
index 13e4efc..190d9f9 100644 (file)
@@ -216,9 +216,6 @@ static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
        if (offload->dev_state)
                offload->offdev->ops->destroy(prog);
 
-       /* Make sure BPF_PROG_GET_NEXT_ID can't find this dead program */
-       bpf_prog_free_id(prog, true);
-
        list_del_init(&offload->offloads);
        kfree(offload);
        prog->aux->offload = NULL;
index 64131f8..ecca936 100644 (file)
@@ -1972,7 +1972,7 @@ static void bpf_audit_prog(const struct bpf_prog *prog, unsigned int op)
                return;
        if (audit_enabled == AUDIT_OFF)
                return;
-       if (op == BPF_AUDIT_LOAD)
+       if (!in_irq() && !irqs_disabled())
                ctx = audit_context();
        ab = audit_log_start(ctx, GFP_ATOMIC, AUDIT_BPF);
        if (unlikely(!ab))
@@ -2001,7 +2001,7 @@ static int bpf_prog_alloc_id(struct bpf_prog *prog)
        return id > 0 ? 0 : id;
 }
 
-void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock)
+void bpf_prog_free_id(struct bpf_prog *prog)
 {
        unsigned long flags;
 
@@ -2013,18 +2013,10 @@ void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock)
        if (!prog->aux->id)
                return;
 
-       if (do_idr_lock)
-               spin_lock_irqsave(&prog_idr_lock, flags);
-       else
-               __acquire(&prog_idr_lock);
-
+       spin_lock_irqsave(&prog_idr_lock, flags);
        idr_remove(&prog_idr, prog->aux->id);
        prog->aux->id = 0;
-
-       if (do_idr_lock)
-               spin_unlock_irqrestore(&prog_idr_lock, flags);
-       else
-               __release(&prog_idr_lock);
+       spin_unlock_irqrestore(&prog_idr_lock, flags);
 }
 
 static void __bpf_prog_put_rcu(struct rcu_head *rcu)
@@ -2067,17 +2059,15 @@ static void bpf_prog_put_deferred(struct work_struct *work)
        prog = aux->prog;
        perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0);
        bpf_audit_prog(prog, BPF_AUDIT_UNLOAD);
+       bpf_prog_free_id(prog);
        __bpf_prog_put_noref(prog, true);
 }
 
-static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
+static void __bpf_prog_put(struct bpf_prog *prog)
 {
        struct bpf_prog_aux *aux = prog->aux;
 
        if (atomic64_dec_and_test(&aux->refcnt)) {
-               /* bpf_prog_free_id() must be called first */
-               bpf_prog_free_id(prog, do_idr_lock);
-
                if (in_irq() || irqs_disabled()) {
                        INIT_WORK(&aux->work, bpf_prog_put_deferred);
                        schedule_work(&aux->work);
@@ -2089,7 +2079,7 @@ static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
 
 void bpf_prog_put(struct bpf_prog *prog)
 {
-       __bpf_prog_put(prog, true);
+       __bpf_prog_put(prog);
 }
 EXPORT_SYMBOL_GPL(bpf_prog_put);
 
index 85f96c1..dbef0b0 100644 (file)
@@ -2748,6 +2748,12 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx,
                         */
                        if (insn->src_reg == 0 && is_callback_calling_function(insn->imm))
                                return -ENOTSUPP;
+                       /* kfunc with imm==0 is invalid and fixup_kfunc_call will
+                        * catch this error later. Make backtracking conservative
+                        * with ENOTSUPP.
+                        */
+                       if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL && insn->imm == 0)
+                               return -ENOTSUPP;
                        /* regular helper call sets R0 */
                        *reg_mask &= ~1;
                        if (*reg_mask & 0x3f) {
@@ -3289,7 +3295,9 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
                bool sanitize = reg && is_spillable_regtype(reg->type);
 
                for (i = 0; i < size; i++) {
-                       if (state->stack[spi].slot_type[i] == STACK_INVALID) {
+                       u8 type = state->stack[spi].slot_type[i];
+
+                       if (type != STACK_MISC && type != STACK_ZERO) {
                                sanitize = true;
                                break;
                        }
index 473036b..81b97f0 100755 (executable)
@@ -14,6 +14,8 @@ include/
 arch/$SRCARCH/include/
 "
 
+type cpio > /dev/null
+
 # Support incremental builds by skipping archive generation
 # if timestamps of files being archived are not changed.
 
index 7decf1e..a5ed2e5 100644 (file)
@@ -123,6 +123,7 @@ bool console_srcu_read_lock_is_held(void)
 {
        return srcu_read_lock_held(&console_srcu);
 }
+EXPORT_SYMBOL(console_srcu_read_lock_is_held);
 #endif
 
 enum devkmsg_log_bits {
@@ -1891,6 +1892,7 @@ static void console_lock_spinning_enable(void)
 /**
  * console_lock_spinning_disable_and_check - mark end of code where another
  *     thread was able to busy wait and check if there is a waiter
+ * @cookie: cookie returned from console_srcu_read_lock()
  *
  * This is called at the end of the section where spinning is allowed.
  * It has two functions. First, it is a signal that it is no longer
index 5fd54bf..88b31f0 100644 (file)
@@ -1442,6 +1442,8 @@ static int do_prlimit(struct task_struct *tsk, unsigned int resource,
 
        if (resource >= RLIM_NLIMITS)
                return -EINVAL;
+       resource = array_index_nospec(resource, RLIM_NLIMITS);
+
        if (new_rlim) {
                if (new_rlim->rlim_cur > new_rlim->rlim_max)
                        return -EINVAL;
index 3bbd3f0..f47274d 100644 (file)
@@ -848,6 +848,9 @@ static int bpf_send_signal_common(u32 sig, enum pid_type type)
                return -EPERM;
        if (unlikely(!nmi_uaccess_okay()))
                return -EPERM;
+       /* Task should not be pid=1 to avoid kernel panic. */
+       if (unlikely(is_global_init(current)))
+               return -EPERM;
 
        if (irqs_disabled()) {
                /* Do an early check on signal validity. Otherwise,
index f72aa50..8d7519a 100644 (file)
@@ -470,22 +470,27 @@ int sg_alloc_append_table_from_pages(struct sg_append_table *sgt_append,
                return -EOPNOTSUPP;
 
        if (sgt_append->prv) {
+               unsigned long next_pfn = (page_to_phys(sg_page(sgt_append->prv)) +
+                       sgt_append->prv->offset + sgt_append->prv->length) / PAGE_SIZE;
+
                if (WARN_ON(offset))
                        return -EINVAL;
 
                /* Merge contiguous pages into the last SG */
                prv_len = sgt_append->prv->length;
-               last_pg = sg_page(sgt_append->prv);
-               while (n_pages && pages_are_mergeable(pages[0], last_pg)) {
-                       if (sgt_append->prv->length + PAGE_SIZE > max_segment)
-                               break;
-                       sgt_append->prv->length += PAGE_SIZE;
-                       last_pg = pages[0];
-                       pages++;
-                       n_pages--;
+               if (page_to_pfn(pages[0]) == next_pfn) {
+                       last_pg = pfn_to_page(next_pfn - 1);
+                       while (n_pages && pages_are_mergeable(pages[0], last_pg)) {
+                               if (sgt_append->prv->length + PAGE_SIZE > max_segment)
+                                       break;
+                               sgt_append->prv->length += PAGE_SIZE;
+                               last_pg = pages[0];
+                               pages++;
+                               n_pages--;
+                       }
+                       if (!n_pages)
+                               goto out;
                }
-               if (!n_pages)
-                       goto out;
        }
 
        /* compute number of contiguous chunks */
index 6bdc1cd..ec10506 100644 (file)
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
-/**
+/*
  * lib/minmax.c: windowed min/max tracker
  *
  * Kathleen Nichols' algorithm for tracking the minimum (or maximum)
index db89523..7fcdb98 100644 (file)
@@ -94,6 +94,8 @@ static int hugetlb_acct_memory(struct hstate *h, long delta);
 static void hugetlb_vma_lock_free(struct vm_area_struct *vma);
 static void hugetlb_vma_lock_alloc(struct vm_area_struct *vma);
 static void __hugetlb_vma_unlock_write_free(struct vm_area_struct *vma);
+static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
+               unsigned long start, unsigned long end);
 
 static inline bool subpool_is_free(struct hugepage_subpool *spool)
 {
@@ -1181,7 +1183,7 @@ void hugetlb_dup_vma_private(struct vm_area_struct *vma)
 
 /*
  * Reset and decrement one ref on hugepage private reservation.
- * Called with mm->mmap_sem writer semaphore held.
+ * Called with mm->mmap_lock writer semaphore held.
  * This function should be only used by move_vma() and operate on
  * same sized vma. It should never come here with last ref on the
  * reservation.
@@ -4834,6 +4836,25 @@ static int hugetlb_vm_op_split(struct vm_area_struct *vma, unsigned long addr)
 {
        if (addr & ~(huge_page_mask(hstate_vma(vma))))
                return -EINVAL;
+
+       /*
+        * PMD sharing is only possible for PUD_SIZE-aligned address ranges
+        * in HugeTLB VMAs. If we will lose PUD_SIZE alignment due to this
+        * split, unshare PMDs in the PUD_SIZE interval surrounding addr now.
+        */
+       if (addr & ~PUD_MASK) {
+               /*
+                * hugetlb_vm_op_split is called right before we attempt to
+                * split the VMA. We will need to unshare PMDs in the old and
+                * new VMAs, so let's unshare before we split.
+                */
+               unsigned long floor = addr & PUD_MASK;
+               unsigned long ceil = floor + PUD_SIZE;
+
+               if (floor >= vma->vm_start && ceil <= vma->vm_end)
+                       hugetlb_unshare_pmds(vma, floor, ceil);
+       }
+
        return 0;
 }
 
@@ -5131,7 +5152,7 @@ static void move_huge_pte(struct vm_area_struct *vma, unsigned long old_addr,
 
        /*
         * We don't have to worry about the ordering of src and dst ptlocks
-        * because exclusive mmap_sem (or the i_mmap_lock) prevents deadlock.
+        * because exclusive mmap_lock (or the i_mmap_lock) prevents deadlock.
         */
        if (src_ptl != dst_ptl)
                spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
@@ -6639,8 +6660,17 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
                spinlock_t *ptl;
                ptep = huge_pte_offset(mm, address, psize);
                if (!ptep) {
-                       address |= last_addr_mask;
-                       continue;
+                       if (!uffd_wp) {
+                               address |= last_addr_mask;
+                               continue;
+                       }
+                       /*
+                        * Userfaultfd wr-protect requires pgtable
+                        * pre-allocations to install pte markers.
+                        */
+                       ptep = huge_pte_alloc(mm, vma, address, psize);
+                       if (!ptep)
+                               break;
                }
                ptl = huge_pte_lock(h, mm, ptep);
                if (huge_pmd_unshare(mm, vma, address, ptep)) {
@@ -6658,16 +6688,13 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
                }
                pte = huge_ptep_get(ptep);
                if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) {
-                       spin_unlock(ptl);
-                       continue;
-               }
-               if (unlikely(is_hugetlb_entry_migration(pte))) {
+                       /* Nothing to do. */
+               } else if (unlikely(is_hugetlb_entry_migration(pte))) {
                        swp_entry_t entry = pte_to_swp_entry(pte);
                        struct page *page = pfn_swap_entry_to_page(entry);
+                       pte_t newpte = pte;
 
-                       if (!is_readable_migration_entry(entry)) {
-                               pte_t newpte;
-
+                       if (is_writable_migration_entry(entry)) {
                                if (PageAnon(page))
                                        entry = make_readable_exclusive_migration_entry(
                                                                swp_offset(entry));
@@ -6675,25 +6702,22 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
                                        entry = make_readable_migration_entry(
                                                                swp_offset(entry));
                                newpte = swp_entry_to_pte(entry);
-                               if (uffd_wp)
-                                       newpte = pte_swp_mkuffd_wp(newpte);
-                               else if (uffd_wp_resolve)
-                                       newpte = pte_swp_clear_uffd_wp(newpte);
-                               set_huge_pte_at(mm, address, ptep, newpte);
                                pages++;
                        }
-                       spin_unlock(ptl);
-                       continue;
-               }
-               if (unlikely(pte_marker_uffd_wp(pte))) {
-                       /*
-                        * This is changing a non-present pte into a none pte,
-                        * no need for huge_ptep_modify_prot_start/commit().
-                        */
+
+                       if (uffd_wp)
+                               newpte = pte_swp_mkuffd_wp(newpte);
+                       else if (uffd_wp_resolve)
+                               newpte = pte_swp_clear_uffd_wp(newpte);
+                       if (!pte_same(pte, newpte))
+                               set_huge_pte_at(mm, address, ptep, newpte);
+               } else if (unlikely(is_pte_marker(pte))) {
+                       /* No other markers apply for now. */
+                       WARN_ON_ONCE(!pte_marker_uffd_wp(pte));
                        if (uffd_wp_resolve)
+                               /* Safe to modify directly (non-present->none). */
                                huge_pte_clear(mm, address, ptep, psize);
-               }
-               if (!huge_pte_none(pte)) {
+               } else if (!huge_pte_none(pte)) {
                        pte_t old_pte;
                        unsigned int shift = huge_page_shift(hstate_vma(vma));
 
@@ -7328,26 +7352,21 @@ void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio, int re
        }
 }
 
-/*
- * This function will unconditionally remove all the shared pmd pgtable entries
- * within the specific vma for a hugetlbfs memory range.
- */
-void hugetlb_unshare_all_pmds(struct vm_area_struct *vma)
+static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
+                                  unsigned long start,
+                                  unsigned long end)
 {
        struct hstate *h = hstate_vma(vma);
        unsigned long sz = huge_page_size(h);
        struct mm_struct *mm = vma->vm_mm;
        struct mmu_notifier_range range;
-       unsigned long address, start, end;
+       unsigned long address;
        spinlock_t *ptl;
        pte_t *ptep;
 
        if (!(vma->vm_flags & VM_MAYSHARE))
                return;
 
-       start = ALIGN(vma->vm_start, PUD_SIZE);
-       end = ALIGN_DOWN(vma->vm_end, PUD_SIZE);
-
        if (start >= end)
                return;
 
@@ -7379,6 +7398,16 @@ void hugetlb_unshare_all_pmds(struct vm_area_struct *vma)
        mmu_notifier_invalidate_range_end(&range);
 }
 
+/*
+ * This function will unconditionally remove all the shared pmd pgtable entries
+ * within the specific vma for a hugetlbfs memory range.
+ */
+void hugetlb_unshare_all_pmds(struct vm_area_struct *vma)
+{
+       hugetlb_unshare_pmds(vma, ALIGN(vma->vm_start, PUD_SIZE),
+                       ALIGN_DOWN(vma->vm_end, PUD_SIZE));
+}
+
 #ifdef CONFIG_CMA
 static bool cma_reserve_called __initdata;
 
index 1d02757..22598b2 100644 (file)
@@ -119,7 +119,7 @@ EXPORT_SYMBOL_GPL(kasan_restore_multi_shot);
  * Whether the KASAN KUnit test suite is currently being executed.
  * Updated in kasan_test.c.
  */
-bool kasan_kunit_executing;
+static bool kasan_kunit_executing;
 
 void kasan_kunit_test_suite_start(void)
 {
index 5cb401a..79be131 100644 (file)
@@ -1460,14 +1460,6 @@ int collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
        if (!hugepage_vma_check(vma, vma->vm_flags, false, false, false))
                return SCAN_VMA_CHECK;
 
-       /*
-        * Symmetry with retract_page_tables(): Exclude MAP_PRIVATE mappings
-        * that got written to. Without this, we'd have to also lock the
-        * anon_vma if one exists.
-        */
-       if (vma->anon_vma)
-               return SCAN_VMA_CHECK;
-
        /* Keep pmd pgtable for uffd-wp; see comment in retract_page_tables() */
        if (userfaultfd_wp(vma))
                return SCAN_PTE_UFFD_WP;
@@ -1567,8 +1559,14 @@ int collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
        }
 
        /* step 4: remove pte entries */
+       /* we make no change to anon, but protect concurrent anon page lookup */
+       if (vma->anon_vma)
+               anon_vma_lock_write(vma->anon_vma);
+
        collapse_and_free_pmd(mm, vma, haddr, pmd);
 
+       if (vma->anon_vma)
+               anon_vma_unlock_write(vma->anon_vma);
        i_mmap_unlock_write(vma->vm_file->f_mapping);
 
 maybe_install_pmd:
@@ -2649,7 +2647,7 @@ int madvise_collapse(struct vm_area_struct *vma, struct vm_area_struct **prev,
                                goto out_nolock;
                        }
 
-                       hend = vma->vm_end & HPAGE_PMD_MASK;
+                       hend = min(hend, vma->vm_end & HPAGE_PMD_MASK);
                }
                mmap_assert_locked(mm);
                memset(cc->node_load, 0, sizeof(cc->node_load));
index a56a6d1..b6ea204 100644 (file)
@@ -130,7 +130,7 @@ static int replace_anon_vma_name(struct vm_area_struct *vma,
 #endif /* CONFIG_ANON_VMA_NAME */
 /*
  * Update the vm_flags on region of a vma, splitting it or merging it as
- * necessary.  Must be called with mmap_sem held for writing;
+ * necessary.  Must be called with mmap_lock held for writing;
  * Caller should ensure anon_name stability by raising its refcount even when
  * anon_name belongs to a valid vma because this function might free that vma.
  */
index 87d9293..425a934 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1524,6 +1524,10 @@ int vma_wants_writenotify(struct vm_area_struct *vma, pgprot_t vm_page_prot)
        if (vma_soft_dirty_enabled(vma) && !is_vm_hugetlb_page(vma))
                return 1;
 
+       /* Do we need write faults for uffd-wp tracking? */
+       if (userfaultfd_wp(vma))
+               return 1;
+
        /* Specialty mapping? */
        if (vm_flags & VM_PFNMAP)
                return 0;
@@ -2290,7 +2294,7 @@ static inline int munmap_sidetree(struct vm_area_struct *vma,
  * @start: The aligned start address to munmap.
  * @end: The aligned end address to munmap.
  * @uf: The userfaultfd list_head
- * @downgrade: Set to true to attempt a write downgrade of the mmap_sem
+ * @downgrade: Set to true to attempt a write downgrade of the mmap_lock
  *
  * If @downgrade is true, check return code for potential release of the lock.
  */
@@ -2465,7 +2469,7 @@ map_count_exceeded:
  * @len: The length of the range to munmap
  * @uf: The userfaultfd list_head
  * @downgrade: set to true if the user wants to attempt to write_downgrade the
- * mmap_sem
+ * mmap_lock
  *
  * This function takes a @mas that is either pointing to the previous VMA or set
  * to MA_START and sets it up to remove the mapping(s).  The @len will be
index 214c70e..5b83938 100644 (file)
@@ -559,7 +559,6 @@ void vma_mas_remove(struct vm_area_struct *vma, struct ma_state *mas)
 
 static void setup_vma_to_mm(struct vm_area_struct *vma, struct mm_struct *mm)
 {
-       mm->map_count++;
        vma->vm_mm = mm;
 
        /* add the VMA to the mapping */
@@ -587,6 +586,7 @@ static void mas_add_vma_to_mm(struct ma_state *mas, struct mm_struct *mm,
        BUG_ON(!vma->vm_region);
 
        setup_vma_to_mm(vma, mm);
+       mm->map_count++;
 
        /* add the VMA to the tree */
        vma_mas_store(vma, mas);
@@ -1240,6 +1240,7 @@ share:
 error_just_free:
        up_write(&nommu_region_sem);
 error:
+       mas_destroy(&mas);
        if (region->vm_file)
                fput(region->vm_file);
        kmem_cache_free(vm_region_jar, region);
@@ -1250,7 +1251,6 @@ error:
 
 sharing_violation:
        up_write(&nommu_region_sem);
-       mas_destroy(&mas);
        pr_warn("Attempt to share mismatched mappings\n");
        ret = -EINVAL;
        goto error;
@@ -1347,6 +1347,7 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
        if (vma->vm_file)
                return -ENOMEM;
 
+       mm = vma->vm_mm;
        if (mm->map_count >= sysctl_max_map_count)
                return -ENOMEM;
 
@@ -1398,6 +1399,7 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
        mas_set_range(&mas, vma->vm_start, vma->vm_end - 1);
        mas_store(&mas, vma);
        vma_mas_store(new, &mas);
+       mm->map_count++;
        return 0;
 
 err_mas_preallocate:
@@ -1509,7 +1511,8 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len, struct list
 erase_whole_vma:
        if (delete_vma_from_mm(vma))
                ret = -ENOMEM;
-       delete_vma(mm, vma);
+       else
+               delete_vma(mm, vma);
        return ret;
 }
 
index c301487..0005ab2 100644 (file)
@@ -478,12 +478,10 @@ bool shmem_is_huge(struct vm_area_struct *vma, struct inode *inode,
        if (vma && ((vma->vm_flags & VM_NOHUGEPAGE) ||
            test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags)))
                return false;
-       if (shmem_huge_force)
-               return true;
-       if (shmem_huge == SHMEM_HUGE_FORCE)
-               return true;
        if (shmem_huge == SHMEM_HUGE_DENY)
                return false;
+       if (shmem_huge_force || shmem_huge == SHMEM_HUGE_FORCE)
+               return true;
 
        switch (SHMEM_SB(inode->i_sb)->huge) {
        case SHMEM_HUGE_ALWAYS:
index 7a269db..29300fc 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2211,6 +2211,8 @@ static int drain_freelist(struct kmem_cache *cache,
                raw_spin_unlock_irq(&n->list_lock);
                slab_destroy(cache, slab);
                nr_freed++;
+
+               cond_resched();
        }
 out:
        return nr_freed;
index d3e542c..acf563f 100644 (file)
@@ -821,6 +821,7 @@ static void terminate_big_destroy(struct hci_dev *hdev, void *data, int err)
 static int hci_le_terminate_big(struct hci_dev *hdev, u8 big, u8 bis)
 {
        struct iso_list_data *d;
+       int ret;
 
        bt_dev_dbg(hdev, "big 0x%2.2x bis 0x%2.2x", big, bis);
 
@@ -831,8 +832,12 @@ static int hci_le_terminate_big(struct hci_dev *hdev, u8 big, u8 bis)
        d->big = big;
        d->bis = bis;
 
-       return hci_cmd_sync_queue(hdev, terminate_big_sync, d,
-                                 terminate_big_destroy);
+       ret = hci_cmd_sync_queue(hdev, terminate_big_sync, d,
+                                terminate_big_destroy);
+       if (ret)
+               kfree(d);
+
+       return ret;
 }
 
 static int big_terminate_sync(struct hci_dev *hdev, void *data)
@@ -857,6 +862,7 @@ static int big_terminate_sync(struct hci_dev *hdev, void *data)
 static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, u16 sync_handle)
 {
        struct iso_list_data *d;
+       int ret;
 
        bt_dev_dbg(hdev, "big 0x%2.2x sync_handle 0x%4.4x", big, sync_handle);
 
@@ -867,8 +873,12 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, u16 sync_handle)
        d->big = big;
        d->sync_handle = sync_handle;
 
-       return hci_cmd_sync_queue(hdev, big_terminate_sync, d,
-                                 terminate_big_destroy);
+       ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
+                                terminate_big_destroy);
+       if (ret)
+               kfree(d);
+
+       return ret;
 }
 
 /* Cleanup BIS connection
index 0594af4..ad92a4b 100644 (file)
@@ -3848,8 +3848,11 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
                           conn->handle, conn->link);
 
                /* Create CIS if LE is already connected */
-               if (conn->link && conn->link->state == BT_CONNECTED)
+               if (conn->link && conn->link->state == BT_CONNECTED) {
+                       rcu_read_unlock();
                        hci_le_create_cis(conn->link);
+                       rcu_read_lock();
+               }
 
                if (i == rp->num_handles)
                        break;
index 9e2d7e4..117eedb 100644 (file)
@@ -3572,7 +3572,7 @@ static const struct hci_init_stage hci_init2[] = {
 static int hci_le_read_buffer_size_sync(struct hci_dev *hdev)
 {
        /* Use Read LE Buffer Size V2 if supported */
-       if (hdev->commands[41] & 0x20)
+       if (iso_capable(hdev) && hdev->commands[41] & 0x20)
                return __hci_cmd_sync_status(hdev,
                                             HCI_OP_LE_READ_BUFFER_SIZE_V2,
                                             0, NULL, HCI_CMD_TIMEOUT);
@@ -3597,10 +3597,10 @@ static int hci_le_read_supported_states_sync(struct hci_dev *hdev)
 
 /* LE Controller init stage 2 command sequence */
 static const struct hci_init_stage le_init2[] = {
-       /* HCI_OP_LE_READ_BUFFER_SIZE */
-       HCI_INIT(hci_le_read_buffer_size_sync),
        /* HCI_OP_LE_READ_LOCAL_FEATURES */
        HCI_INIT(hci_le_read_local_features_sync),
+       /* HCI_OP_LE_READ_BUFFER_SIZE */
+       HCI_INIT(hci_le_read_buffer_size_sync),
        /* HCI_OP_LE_READ_SUPPORTED_STATES */
        HCI_INIT(hci_le_read_supported_states_sync),
        {}
@@ -6187,20 +6187,13 @@ int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
 
 static int _update_adv_data_sync(struct hci_dev *hdev, void *data)
 {
-       u8 instance = *(u8 *)data;
-
-       kfree(data);
+       u8 instance = PTR_ERR(data);
 
        return hci_update_adv_data_sync(hdev, instance);
 }
 
 int hci_update_adv_data(struct hci_dev *hdev, u8 instance)
 {
-       u8 *inst_ptr = kmalloc(1, GFP_KERNEL);
-
-       if (!inst_ptr)
-               return -ENOMEM;
-
-       *inst_ptr = instance;
-       return hci_cmd_sync_queue(hdev, _update_adv_data_sync, inst_ptr, NULL);
+       return hci_cmd_sync_queue(hdev, _update_adv_data_sync,
+                                 ERR_PTR(instance), NULL);
 }
index 035bb5d..24444b5 100644 (file)
@@ -289,15 +289,15 @@ static int iso_connect_bis(struct sock *sk)
        hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
+       err = iso_chan_add(conn, sk, NULL);
+       if (err)
+               return err;
+
        lock_sock(sk);
 
        /* Update source addr of the socket */
        bacpy(&iso_pi(sk)->src, &hcon->src);
 
-       err = iso_chan_add(conn, sk, NULL);
-       if (err)
-               goto release;
-
        if (hcon->state == BT_CONNECTED) {
                iso_sock_clear_timer(sk);
                sk->sk_state = BT_CONNECTED;
@@ -306,7 +306,6 @@ static int iso_connect_bis(struct sock *sk)
                iso_sock_set_timer(sk, sk->sk_sndtimeo);
        }
 
-release:
        release_sock(sk);
        return err;
 
@@ -372,15 +371,15 @@ static int iso_connect_cis(struct sock *sk)
        hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
+       err = iso_chan_add(conn, sk, NULL);
+       if (err)
+               return err;
+
        lock_sock(sk);
 
        /* Update source addr of the socket */
        bacpy(&iso_pi(sk)->src, &hcon->src);
 
-       err = iso_chan_add(conn, sk, NULL);
-       if (err)
-               goto release;
-
        if (hcon->state == BT_CONNECTED) {
                iso_sock_clear_timer(sk);
                sk->sk_state = BT_CONNECTED;
@@ -392,7 +391,6 @@ static int iso_connect_cis(struct sock *sk)
                iso_sock_set_timer(sk, sk->sk_sndtimeo);
        }
 
-release:
        release_sock(sk);
        return err;
 
@@ -895,13 +893,10 @@ static int iso_listen_bis(struct sock *sk)
        if (!hdev)
                return -EHOSTUNREACH;
 
-       hci_dev_lock(hdev);
-
        err = hci_pa_create_sync(hdev, &iso_pi(sk)->dst,
                                 le_addr_type(iso_pi(sk)->dst_type),
                                 iso_pi(sk)->bc_sid);
 
-       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1432,33 +1427,29 @@ static void iso_conn_ready(struct iso_conn *conn)
        struct sock *parent;
        struct sock *sk = conn->sk;
        struct hci_ev_le_big_sync_estabilished *ev;
+       struct hci_conn *hcon;
 
        BT_DBG("conn %p", conn);
 
        if (sk) {
                iso_sock_ready(conn->sk);
        } else {
-               iso_conn_lock(conn);
-
-               if (!conn->hcon) {
-                       iso_conn_unlock(conn);
+               hcon = conn->hcon;
+               if (!hcon)
                        return;
-               }
 
-               ev = hci_recv_event_data(conn->hcon->hdev,
+               ev = hci_recv_event_data(hcon->hdev,
                                         HCI_EVT_LE_BIG_SYNC_ESTABILISHED);
                if (ev)
-                       parent = iso_get_sock_listen(&conn->hcon->src,
-                                                    &conn->hcon->dst,
+                       parent = iso_get_sock_listen(&hcon->src,
+                                                    &hcon->dst,
                                                     iso_match_big, ev);
                else
-                       parent = iso_get_sock_listen(&conn->hcon->src,
+                       parent = iso_get_sock_listen(&hcon->src,
                                                     BDADDR_ANY, NULL, NULL);
 
-               if (!parent) {
-                       iso_conn_unlock(conn);
+               if (!parent)
                        return;
-               }
 
                lock_sock(parent);
 
@@ -1466,30 +1457,29 @@ static void iso_conn_ready(struct iso_conn *conn)
                                    BTPROTO_ISO, GFP_ATOMIC, 0);
                if (!sk) {
                        release_sock(parent);
-                       iso_conn_unlock(conn);
                        return;
                }
 
                iso_sock_init(sk, parent);
 
-               bacpy(&iso_pi(sk)->src, &conn->hcon->src);
-               iso_pi(sk)->src_type = conn->hcon->src_type;
+               bacpy(&iso_pi(sk)->src, &hcon->src);
+               iso_pi(sk)->src_type = hcon->src_type;
 
                /* If hcon has no destination address (BDADDR_ANY) it means it
                 * was created by HCI_EV_LE_BIG_SYNC_ESTABILISHED so we need to
                 * initialize using the parent socket destination address.
                 */
-               if (!bacmp(&conn->hcon->dst, BDADDR_ANY)) {
-                       bacpy(&conn->hcon->dst, &iso_pi(parent)->dst);
-                       conn->hcon->dst_type = iso_pi(parent)->dst_type;
-                       conn->hcon->sync_handle = iso_pi(parent)->sync_handle;
+               if (!bacmp(&hcon->dst, BDADDR_ANY)) {
+                       bacpy(&hcon->dst, &iso_pi(parent)->dst);
+                       hcon->dst_type = iso_pi(parent)->dst_type;
+                       hcon->sync_handle = iso_pi(parent)->sync_handle;
                }
 
-               bacpy(&iso_pi(sk)->dst, &conn->hcon->dst);
-               iso_pi(sk)->dst_type = conn->hcon->dst_type;
+               bacpy(&iso_pi(sk)->dst, &hcon->dst);
+               iso_pi(sk)->dst_type = hcon->dst_type;
 
-               hci_conn_hold(conn->hcon);
-               __iso_chan_add(conn, sk, parent);
+               hci_conn_hold(hcon);
+               iso_chan_add(conn, sk, parent);
 
                if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
                        sk->sk_state = BT_CONNECT2;
@@ -1500,8 +1490,6 @@ static void iso_conn_ready(struct iso_conn *conn)
                parent->sk_data_ready(parent);
 
                release_sock(parent);
-
-               iso_conn_unlock(conn);
        }
 }
 
index 6a8b7e8..bdf9786 100644 (file)
@@ -27,7 +27,7 @@ struct mgmt_mesh_tx {
        struct sock *sk;
        u8 handle;
        u8 instance;
-       u8 param[sizeof(struct mgmt_cp_mesh_send) + 29];
+       u8 param[sizeof(struct mgmt_cp_mesh_send) + 31];
 };
 
 struct mgmt_pending_cmd {
index 21e24da..4397e14 100644 (file)
@@ -391,6 +391,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
            addr->sa_family != AF_BLUETOOTH)
                return -EINVAL;
 
+       sock_hold(sk);
        lock_sock(sk);
 
        if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
@@ -410,14 +411,18 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
        d->sec_level = rfcomm_pi(sk)->sec_level;
        d->role_switch = rfcomm_pi(sk)->role_switch;
 
+       /* Drop sock lock to avoid potential deadlock with the RFCOMM lock */
+       release_sock(sk);
        err = rfcomm_dlc_open(d, &rfcomm_pi(sk)->src, &sa->rc_bdaddr,
                              sa->rc_channel);
-       if (!err)
+       lock_sock(sk);
+       if (!err && !sock_flag(sk, SOCK_ZAPPED))
                err = bt_sock_wait_state(sk, BT_CONNECTED,
                                sock_sndtimeo(sk, flags & O_NONBLOCK));
 
 done:
        release_sock(sk);
+       sock_put(sk);
        return err;
 }
 
index ebe6145..be260ab 100644 (file)
@@ -122,10 +122,13 @@ rss_fill_reply(struct sk_buff *skb, const struct ethnl_req_info *req_base,
 {
        const struct rss_reply_data *data = RSS_REPDATA(reply_base);
 
-       if (nla_put_u32(skb, ETHTOOL_A_RSS_HFUNC, data->hfunc) ||
-           nla_put(skb, ETHTOOL_A_RSS_INDIR,
-                   sizeof(u32) * data->indir_size, data->indir_table) ||
-           nla_put(skb, ETHTOOL_A_RSS_HKEY, data->hkey_size, data->hkey))
+       if ((data->hfunc &&
+            nla_put_u32(skb, ETHTOOL_A_RSS_HFUNC, data->hfunc)) ||
+           (data->indir_size &&
+            nla_put(skb, ETHTOOL_A_RSS_INDIR,
+                    sizeof(u32) * data->indir_size, data->indir_table)) ||
+           (data->hkey_size &&
+            nla_put(skb, ETHTOOL_A_RSS_HKEY, data->hkey_size, data->hkey)))
                return -EMSGSIZE;
 
        return 0;
index 24a38b5..f58d738 100644 (file)
@@ -650,8 +650,20 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
        spin_lock(lock);
        if (osk) {
                WARN_ON_ONCE(sk->sk_hash != osk->sk_hash);
-               ret = sk_nulls_del_node_init_rcu(osk);
-       } else if (found_dup_sk) {
+               ret = sk_hashed(osk);
+               if (ret) {
+                       /* Before deleting the node, we insert a new one to make
+                        * sure that the look-up-sk process would not miss either
+                        * of them and that at least one node would exist in ehash
+                        * table all the time. Otherwise there's a tiny chance
+                        * that lookup process could find nothing in ehash table.
+                        */
+                       __sk_nulls_add_node_tail_rcu(sk, list);
+                       sk_nulls_del_node_init_rcu(osk);
+               }
+               goto unlock;
+       }
+       if (found_dup_sk) {
                *found_dup_sk = inet_ehash_lookup_by_sk(sk, list);
                if (*found_dup_sk)
                        ret = false;
@@ -660,6 +672,7 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
        if (ret)
                __sk_nulls_add_node_rcu(sk, list);
 
+unlock:
        spin_unlock(lock);
 
        return ret;
index 1d77d99..beed32f 100644 (file)
@@ -91,10 +91,10 @@ void inet_twsk_put(struct inet_timewait_sock *tw)
 }
 EXPORT_SYMBOL_GPL(inet_twsk_put);
 
-static void inet_twsk_add_node_rcu(struct inet_timewait_sock *tw,
-                                  struct hlist_nulls_head *list)
+static void inet_twsk_add_node_tail_rcu(struct inet_timewait_sock *tw,
+                                       struct hlist_nulls_head *list)
 {
-       hlist_nulls_add_head_rcu(&tw->tw_node, list);
+       hlist_nulls_add_tail_rcu(&tw->tw_node, list);
 }
 
 static void inet_twsk_add_bind_node(struct inet_timewait_sock *tw,
@@ -147,7 +147,7 @@ void inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
 
        spin_lock(lock);
 
-       inet_twsk_add_node_rcu(tw, &ehead->chain);
+       inet_twsk_add_node_tail_rcu(tw, &ehead->chain);
 
        /* Step 3: Remove SK from hash chain */
        if (__sk_nulls_del_node_init_rcu(sk))
index c567d5e..33f559f 100644 (file)
@@ -435,6 +435,7 @@ void tcp_init_sock(struct sock *sk)
 
        /* There's a bubble in the pipe until at least the first ACK. */
        tp->app_limited = ~0U;
+       tp->rate_app_limited = 1;
 
        /* See draft-stevens-tcpca-spec-01 for discussion of the
         * initialization of these values.
@@ -3178,6 +3179,7 @@ int tcp_disconnect(struct sock *sk, int flags)
        tp->plb_rehash = 0;
        /* There's a bubble in the pipe until at least the first ACK. */
        tp->app_limited = ~0U;
+       tp->rate_app_limited = 1;
        tp->rack.mstamp = 0;
        tp->rack.advanced = 0;
        tp->rack.reo_wnd_steps = 1;
index 05b6077..2aa4421 100644 (file)
@@ -139,7 +139,7 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)
        if (sk->sk_socket)
                clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
 
-       err = -EINVAL;
+       err = -ENOTCONN;
        if (!ulp_ops->clone && sk->sk_state == TCP_LISTEN)
                goto out_err;
 
index 9a1415f..03608d3 100644 (file)
@@ -104,9 +104,9 @@ static struct workqueue_struct *l2tp_wq;
 /* per-net private data for this module */
 static unsigned int l2tp_net_id;
 struct l2tp_net {
-       struct list_head l2tp_tunnel_list;
-       /* Lock for write access to l2tp_tunnel_list */
-       spinlock_t l2tp_tunnel_list_lock;
+       /* Lock for write access to l2tp_tunnel_idr */
+       spinlock_t l2tp_tunnel_idr_lock;
+       struct idr l2tp_tunnel_idr;
        struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2];
        /* Lock for write access to l2tp_session_hlist */
        spinlock_t l2tp_session_hlist_lock;
@@ -208,13 +208,10 @@ struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, u32 tunnel_id)
        struct l2tp_tunnel *tunnel;
 
        rcu_read_lock_bh();
-       list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
-               if (tunnel->tunnel_id == tunnel_id &&
-                   refcount_inc_not_zero(&tunnel->ref_count)) {
-                       rcu_read_unlock_bh();
-
-                       return tunnel;
-               }
+       tunnel = idr_find(&pn->l2tp_tunnel_idr, tunnel_id);
+       if (tunnel && refcount_inc_not_zero(&tunnel->ref_count)) {
+               rcu_read_unlock_bh();
+               return tunnel;
        }
        rcu_read_unlock_bh();
 
@@ -224,13 +221,14 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_get);
 
 struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth)
 {
-       const struct l2tp_net *pn = l2tp_pernet(net);
+       struct l2tp_net *pn = l2tp_pernet(net);
+       unsigned long tunnel_id, tmp;
        struct l2tp_tunnel *tunnel;
        int count = 0;
 
        rcu_read_lock_bh();
-       list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
-               if (++count > nth &&
+       idr_for_each_entry_ul(&pn->l2tp_tunnel_idr, tunnel, tmp, tunnel_id) {
+               if (tunnel && ++count > nth &&
                    refcount_inc_not_zero(&tunnel->ref_count)) {
                        rcu_read_unlock_bh();
                        return tunnel;
@@ -1043,7 +1041,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns
        IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
        nf_reset_ct(skb);
 
-       bh_lock_sock(sk);
+       bh_lock_sock_nested(sk);
        if (sock_owned_by_user(sk)) {
                kfree_skb(skb);
                ret = NET_XMIT_DROP;
@@ -1227,6 +1225,15 @@ static void l2tp_udp_encap_destroy(struct sock *sk)
                l2tp_tunnel_delete(tunnel);
 }
 
+static void l2tp_tunnel_remove(struct net *net, struct l2tp_tunnel *tunnel)
+{
+       struct l2tp_net *pn = l2tp_pernet(net);
+
+       spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
+       idr_remove(&pn->l2tp_tunnel_idr, tunnel->tunnel_id);
+       spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
+}
+
 /* Workqueue tunnel deletion function */
 static void l2tp_tunnel_del_work(struct work_struct *work)
 {
@@ -1234,7 +1241,6 @@ static void l2tp_tunnel_del_work(struct work_struct *work)
                                                  del_work);
        struct sock *sk = tunnel->sock;
        struct socket *sock = sk->sk_socket;
-       struct l2tp_net *pn;
 
        l2tp_tunnel_closeall(tunnel);
 
@@ -1248,12 +1254,7 @@ static void l2tp_tunnel_del_work(struct work_struct *work)
                }
        }
 
-       /* Remove the tunnel struct from the tunnel list */
-       pn = l2tp_pernet(tunnel->l2tp_net);
-       spin_lock_bh(&pn->l2tp_tunnel_list_lock);
-       list_del_rcu(&tunnel->list);
-       spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
-
+       l2tp_tunnel_remove(tunnel->l2tp_net, tunnel);
        /* drop initial ref */
        l2tp_tunnel_dec_refcount(tunnel);
 
@@ -1384,8 +1385,6 @@ out:
        return err;
 }
 
-static struct lock_class_key l2tp_socket_class;
-
 int l2tp_tunnel_create(int fd, int version, u32 tunnel_id, u32 peer_tunnel_id,
                       struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp)
 {
@@ -1455,12 +1454,19 @@ static int l2tp_validate_socket(const struct sock *sk, const struct net *net,
 int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
                         struct l2tp_tunnel_cfg *cfg)
 {
-       struct l2tp_tunnel *tunnel_walk;
-       struct l2tp_net *pn;
+       struct l2tp_net *pn = l2tp_pernet(net);
+       u32 tunnel_id = tunnel->tunnel_id;
        struct socket *sock;
        struct sock *sk;
        int ret;
 
+       spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
+       ret = idr_alloc_u32(&pn->l2tp_tunnel_idr, NULL, &tunnel_id, tunnel_id,
+                           GFP_ATOMIC);
+       spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
+       if (ret)
+               return ret == -ENOSPC ? -EEXIST : ret;
+
        if (tunnel->fd < 0) {
                ret = l2tp_tunnel_sock_create(net, tunnel->tunnel_id,
                                              tunnel->peer_tunnel_id, cfg,
@@ -1474,6 +1480,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
        }
 
        sk = sock->sk;
+       lock_sock(sk);
        write_lock_bh(&sk->sk_callback_lock);
        ret = l2tp_validate_socket(sk, net, tunnel->encap);
        if (ret < 0)
@@ -1481,24 +1488,6 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
        rcu_assign_sk_user_data(sk, tunnel);
        write_unlock_bh(&sk->sk_callback_lock);
 
-       tunnel->l2tp_net = net;
-       pn = l2tp_pernet(net);
-
-       sock_hold(sk);
-       tunnel->sock = sk;
-
-       spin_lock_bh(&pn->l2tp_tunnel_list_lock);
-       list_for_each_entry(tunnel_walk, &pn->l2tp_tunnel_list, list) {
-               if (tunnel_walk->tunnel_id == tunnel->tunnel_id) {
-                       spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
-                       sock_put(sk);
-                       ret = -EEXIST;
-                       goto err_sock;
-               }
-       }
-       list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
-       spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
-
        if (tunnel->encap == L2TP_ENCAPTYPE_UDP) {
                struct udp_tunnel_sock_cfg udp_cfg = {
                        .sk_user_data = tunnel,
@@ -1512,9 +1501,16 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
 
        tunnel->old_sk_destruct = sk->sk_destruct;
        sk->sk_destruct = &l2tp_tunnel_destruct;
-       lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class,
-                                  "l2tp_sock");
        sk->sk_allocation = GFP_ATOMIC;
+       release_sock(sk);
+
+       sock_hold(sk);
+       tunnel->sock = sk;
+       tunnel->l2tp_net = net;
+
+       spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
+       idr_replace(&pn->l2tp_tunnel_idr, tunnel, tunnel->tunnel_id);
+       spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
 
        trace_register_tunnel(tunnel);
 
@@ -1523,17 +1519,16 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
 
        return 0;
 
-err_sock:
-       write_lock_bh(&sk->sk_callback_lock);
-       rcu_assign_sk_user_data(sk, NULL);
 err_inval_sock:
        write_unlock_bh(&sk->sk_callback_lock);
+       release_sock(sk);
 
        if (tunnel->fd < 0)
                sock_release(sock);
        else
                sockfd_put(sock);
 err:
+       l2tp_tunnel_remove(net, tunnel);
        return ret;
 }
 EXPORT_SYMBOL_GPL(l2tp_tunnel_register);
@@ -1647,8 +1642,8 @@ static __net_init int l2tp_init_net(struct net *net)
        struct l2tp_net *pn = net_generic(net, l2tp_net_id);
        int hash;
 
-       INIT_LIST_HEAD(&pn->l2tp_tunnel_list);
-       spin_lock_init(&pn->l2tp_tunnel_list_lock);
+       idr_init(&pn->l2tp_tunnel_idr);
+       spin_lock_init(&pn->l2tp_tunnel_idr_lock);
 
        for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++)
                INIT_HLIST_HEAD(&pn->l2tp_session_hlist[hash]);
@@ -1662,11 +1657,13 @@ static __net_exit void l2tp_exit_net(struct net *net)
 {
        struct l2tp_net *pn = l2tp_pernet(net);
        struct l2tp_tunnel *tunnel = NULL;
+       unsigned long tunnel_id, tmp;
        int hash;
 
        rcu_read_lock_bh();
-       list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
-               l2tp_tunnel_delete(tunnel);
+       idr_for_each_entry_ul(&pn->l2tp_tunnel_idr, tunnel, tmp, tunnel_id) {
+               if (tunnel)
+                       l2tp_tunnel_delete(tunnel);
        }
        rcu_read_unlock_bh();
 
@@ -1676,6 +1673,7 @@ static __net_exit void l2tp_exit_net(struct net *net)
 
        for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++)
                WARN_ON_ONCE(!hlist_empty(&pn->l2tp_session_hlist[hash]));
+       idr_destroy(&pn->l2tp_tunnel_idr);
 }
 
 static struct pernet_operations l2tp_net_ops = {
index 9c40f8d..f9514ba 100644 (file)
@@ -491,7 +491,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
 {
        struct tid_ampdu_tx *tid_tx;
        struct ieee80211_local *local = sta->local;
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
+       struct ieee80211_sub_if_data *sdata;
        struct ieee80211_ampdu_params params = {
                .sta = &sta->sta,
                .action = IEEE80211_AMPDU_TX_START,
@@ -511,8 +511,6 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
         */
        clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
 
-       ieee80211_agg_stop_txq(sta, tid);
-
        /*
         * Make sure no packets are being processed. This ensures that
         * we have a valid starting sequence number and that in-flight
@@ -521,6 +519,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
         */
        synchronize_net();
 
+       sdata = sta->sdata;
        params.ssn = sta->tid_seq[tid] >> 4;
        ret = drv_ampdu_action(local, sdata, &params);
        tid_tx->ssn = params.ssn;
@@ -534,6 +533,9 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
                 */
                set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state);
        } else if (ret) {
+               if (!sdata)
+                       return;
+
                ht_dbg(sdata,
                       "BA request denied - HW unavailable for %pM tid %d\n",
                       sta->sta.addr, tid);
index 8f9a2ab..672eff6 100644 (file)
@@ -147,6 +147,7 @@ static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata,
        link_conf->bssid_index = 0;
        link_conf->nontransmitted = false;
        link_conf->ema_ap = false;
+       link_conf->bssid_indicator = 0;
 
        if (sdata->vif.type != NL80211_IFTYPE_AP || !params.tx_wdev)
                return -EINVAL;
@@ -1511,6 +1512,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
        kfree(link_conf->ftmr_params);
        link_conf->ftmr_params = NULL;
 
+       sdata->vif.mbssid_tx_vif = NULL;
+       link_conf->bssid_index = 0;
+       link_conf->nontransmitted = false;
+       link_conf->ema_ap = false;
+       link_conf->bssid_indicator = 0;
+
        __sta_info_flush(sdata, true);
        ieee80211_free_keys(sdata, true);
 
index 7a3d789..f1914bf 100644 (file)
@@ -167,7 +167,7 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
                        continue;
                txqi = to_txq_info(sta->sta.txq[i]);
                p += scnprintf(p, bufsz + buf - p,
-                              "%d %d %u %u %u %u %u %u %u %u %u 0x%lx(%s%s%s)\n",
+                              "%d %d %u %u %u %u %u %u %u %u %u 0x%lx(%s%s%s%s)\n",
                               txqi->txq.tid,
                               txqi->txq.ac,
                               txqi->tin.backlog_bytes,
@@ -182,7 +182,8 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
                               txqi->flags,
                               test_bit(IEEE80211_TXQ_STOP, &txqi->flags) ? "STOP" : "RUN",
                               test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags) ? " AMPDU" : "",
-                              test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags) ? " NO-AMSDU" : "");
+                              test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags) ? " NO-AMSDU" : "",
+                              test_bit(IEEE80211_TXQ_DIRTY, &txqi->flags) ? " DIRTY" : "");
        }
 
        rcu_read_unlock();
index d737db4..cfb09e4 100644 (file)
@@ -392,6 +392,9 @@ int drv_ampdu_action(struct ieee80211_local *local,
 
        might_sleep();
 
+       if (!sdata)
+               return -EIO;
+
        sdata = get_bss_sdata(sdata);
        if (!check_sdata_in_driver(sdata))
                return -EIO;
index 809bad5..5d13a3d 100644 (file)
@@ -1199,7 +1199,7 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local,
 
        /* In reconfig don't transmit now, but mark for waking later */
        if (local->in_reconfig) {
-               set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txq->flags);
+               set_bit(IEEE80211_TXQ_DIRTY, &txq->flags);
                return;
        }
 
index 83bc413..5315ab7 100644 (file)
@@ -391,6 +391,37 @@ void ieee80211_ba_session_work(struct work_struct *work)
 
                tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
                if (!blocked && tid_tx) {
+                       struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
+                       struct ieee80211_sub_if_data *sdata =
+                               vif_to_sdata(txqi->txq.vif);
+                       struct fq *fq = &sdata->local->fq;
+
+                       spin_lock_bh(&fq->lock);
+
+                       /* Allow only frags to be dequeued */
+                       set_bit(IEEE80211_TXQ_STOP, &txqi->flags);
+
+                       if (!skb_queue_empty(&txqi->frags)) {
+                               /* Fragmented Tx is ongoing, wait for it to
+                                * finish. Reschedule worker to retry later.
+                                */
+
+                               spin_unlock_bh(&fq->lock);
+                               spin_unlock_bh(&sta->lock);
+
+                               /* Give the task working on the txq a chance
+                                * to send out the queued frags
+                                */
+                               synchronize_net();
+
+                               mutex_unlock(&sta->ampdu_mlme.mtx);
+
+                               ieee80211_queue_work(&sdata->local->hw, work);
+                               return;
+                       }
+
+                       spin_unlock_bh(&fq->lock);
+
                        /*
                         * Assign it over to the normal tid_tx array
                         * where it "goes live".
index 63ff0d2..d16606e 100644 (file)
@@ -838,7 +838,7 @@ enum txq_info_flags {
        IEEE80211_TXQ_STOP,
        IEEE80211_TXQ_AMPDU,
        IEEE80211_TXQ_NO_AMSDU,
-       IEEE80211_TXQ_STOP_NETIF_TX,
+       IEEE80211_TXQ_DIRTY,
 };
 
 /**
index d49a590..23ed13f 100644 (file)
@@ -364,7 +364,9 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
 
                        /* No support for VLAN with MLO yet */
                        if (iftype == NL80211_IFTYPE_AP_VLAN &&
-                           nsdata->wdev.use_4addr)
+                           sdata->wdev.use_4addr &&
+                           nsdata->vif.type == NL80211_IFTYPE_AP &&
+                           nsdata->vif.valid_links)
                                return -EOPNOTSUPP;
 
                        /*
@@ -2195,7 +2197,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
                ret = cfg80211_register_netdevice(ndev);
                if (ret) {
-                       ieee80211_if_free(ndev);
                        free_netdev(ndev);
                        return ret;
                }
index 7e3ab6e..c6562a6 100644 (file)
@@ -4049,6 +4049,58 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
 #undef CALL_RXH
 }
 
+static bool
+ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id)
+{
+       if (!sta->mlo)
+               return false;
+
+       return !!(sta->valid_links & BIT(link_id));
+}
+
+static bool ieee80211_rx_data_set_link(struct ieee80211_rx_data *rx,
+                                      u8 link_id)
+{
+       rx->link_id = link_id;
+       rx->link = rcu_dereference(rx->sdata->link[link_id]);
+
+       if (!rx->sta)
+               return rx->link;
+
+       if (!ieee80211_rx_is_valid_sta_link_id(&rx->sta->sta, link_id))
+               return false;
+
+       rx->link_sta = rcu_dereference(rx->sta->link[link_id]);
+
+       return rx->link && rx->link_sta;
+}
+
+static bool ieee80211_rx_data_set_sta(struct ieee80211_rx_data *rx,
+                                     struct ieee80211_sta *pubsta,
+                                     int link_id)
+{
+       struct sta_info *sta;
+
+       sta = container_of(pubsta, struct sta_info, sta);
+
+       rx->link_id = link_id;
+       rx->sta = sta;
+
+       if (sta) {
+               rx->local = sta->sdata->local;
+               if (!rx->sdata)
+                       rx->sdata = sta->sdata;
+               rx->link_sta = &sta->deflink;
+       }
+
+       if (link_id < 0)
+               rx->link = &rx->sdata->deflink;
+       else if (!ieee80211_rx_data_set_link(rx, link_id))
+               return false;
+
+       return true;
+}
+
 /*
  * This function makes calls into the RX path, therefore
  * it has to be invoked under RCU read lock.
@@ -4057,16 +4109,19 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
 {
        struct sk_buff_head frames;
        struct ieee80211_rx_data rx = {
-               .sta = sta,
-               .sdata = sta->sdata,
-               .local = sta->local,
                /* This is OK -- must be QoS data frame */
                .security_idx = tid,
                .seqno_idx = tid,
-               .link_id = -1,
        };
        struct tid_ampdu_rx *tid_agg_rx;
-       u8 link_id;
+       int link_id = -1;
+
+       /* FIXME: statistics won't be right with this */
+       if (sta->sta.valid_links)
+               link_id = ffs(sta->sta.valid_links) - 1;
+
+       if (!ieee80211_rx_data_set_sta(&rx, &sta->sta, link_id))
+               return;
 
        tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
        if (!tid_agg_rx)
@@ -4086,10 +4141,6 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
                };
                drv_event_callback(rx.local, rx.sdata, &event);
        }
-       /* FIXME: statistics won't be right with this */
-       link_id = sta->sta.valid_links ? ffs(sta->sta.valid_links) - 1 : 0;
-       rx.link = rcu_dereference(sta->sdata->link[link_id]);
-       rx.link_sta = rcu_dereference(sta->link[link_id]);
 
        ieee80211_rx_handlers(&rx, &frames);
 }
@@ -4105,7 +4156,6 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
                /* This is OK -- must be QoS data frame */
                .security_idx = tid,
                .seqno_idx = tid,
-               .link_id = -1,
        };
        int i, diff;
 
@@ -4116,10 +4166,8 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
 
        sta = container_of(pubsta, struct sta_info, sta);
 
-       rx.sta = sta;
-       rx.sdata = sta->sdata;
-       rx.link = &rx.sdata->deflink;
-       rx.local = sta->local;
+       if (!ieee80211_rx_data_set_sta(&rx, pubsta, -1))
+               return;
 
        rcu_read_lock();
        tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
@@ -4506,15 +4554,6 @@ void ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata)
        mutex_unlock(&local->sta_mtx);
 }
 
-static bool
-ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id)
-{
-       if (!sta->mlo)
-               return false;
-
-       return !!(sta->valid_links & BIT(link_id));
-}
-
 static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
                              struct ieee80211_fast_rx *fast_rx,
                              int orig_len)
@@ -4625,7 +4664,6 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
        struct sk_buff *skb = rx->skb;
        struct ieee80211_hdr *hdr = (void *)skb->data;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-       struct sta_info *sta = rx->sta;
        int orig_len = skb->len;
        int hdrlen = ieee80211_hdrlen(hdr->frame_control);
        int snap_offs = hdrlen;
@@ -4637,7 +4675,6 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
                u8 da[ETH_ALEN];
                u8 sa[ETH_ALEN];
        } addrs __aligned(2);
-       struct link_sta_info *link_sta;
        struct ieee80211_sta_rx_stats *stats;
 
        /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write
@@ -4740,18 +4777,10 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
  drop:
        dev_kfree_skb(skb);
 
-       if (rx->link_id >= 0) {
-               link_sta = rcu_dereference(sta->link[rx->link_id]);
-               if (!link_sta)
-                       return true;
-       } else {
-               link_sta = &sta->deflink;
-       }
-
        if (fast_rx->uses_rss)
-               stats = this_cpu_ptr(link_sta->pcpu_rx_stats);
+               stats = this_cpu_ptr(rx->link_sta->pcpu_rx_stats);
        else
-               stats = &link_sta->rx_stats;
+               stats = &rx->link_sta->rx_stats;
 
        stats->dropped++;
        return true;
@@ -4769,8 +4798,8 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
        struct ieee80211_local *local = rx->local;
        struct ieee80211_sub_if_data *sdata = rx->sdata;
        struct ieee80211_hdr *hdr = (void *)skb->data;
-       struct link_sta_info *link_sta = NULL;
-       struct ieee80211_link_data *link;
+       struct link_sta_info *link_sta = rx->link_sta;
+       struct ieee80211_link_data *link = rx->link;
 
        rx->skb = skb;
 
@@ -4792,35 +4821,6 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
        if (!ieee80211_accept_frame(rx))
                return false;
 
-       if (rx->link_id >= 0) {
-               link = rcu_dereference(rx->sdata->link[rx->link_id]);
-
-               /* we might race link removal */
-               if (!link)
-                       return true;
-               rx->link = link;
-
-               if (rx->sta) {
-                       rx->link_sta =
-                               rcu_dereference(rx->sta->link[rx->link_id]);
-                       if (!rx->link_sta)
-                               return true;
-               }
-       } else {
-               if (rx->sta)
-                       rx->link_sta = &rx->sta->deflink;
-
-               rx->link = &sdata->deflink;
-       }
-
-       if (unlikely(!is_multicast_ether_addr(hdr->addr1) &&
-                    rx->link_id >= 0 && rx->sta && rx->sta->sta.mlo)) {
-               link_sta = rcu_dereference(rx->sta->link[rx->link_id]);
-
-               if (WARN_ON_ONCE(!link_sta))
-                       return true;
-       }
-
        if (!consume) {
                struct skb_shared_hwtstamps *shwt;
 
@@ -4838,9 +4838,12 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
                 */
                shwt = skb_hwtstamps(rx->skb);
                shwt->hwtstamp = skb_hwtstamps(skb)->hwtstamp;
+
+               /* Update the hdr pointer to the new skb for translation below */
+               hdr = (struct ieee80211_hdr *)rx->skb->data;
        }
 
-       if (unlikely(link_sta)) {
+       if (unlikely(rx->sta && rx->sta->sta.mlo)) {
                /* translate to MLD addresses */
                if (ether_addr_equal(link->conf->addr, hdr->addr1))
                        ether_addr_copy(hdr->addr1, rx->sdata->vif.addr);
@@ -4870,6 +4873,7 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_fast_rx *fast_rx;
        struct ieee80211_rx_data rx;
+       int link_id = -1;
 
        memset(&rx, 0, sizeof(rx));
        rx.skb = skb;
@@ -4886,12 +4890,8 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
        if (!pubsta)
                goto drop;
 
-       rx.sta = container_of(pubsta, struct sta_info, sta);
-       rx.sdata = rx.sta->sdata;
-
-       if (status->link_valid &&
-           !ieee80211_rx_is_valid_sta_link_id(pubsta, status->link_id))
-               goto drop;
+       if (status->link_valid)
+               link_id = status->link_id;
 
        /*
         * TODO: Should the frame be dropped if the right link_id is not
@@ -4900,19 +4900,8 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
         * link_id is used only for stats purpose and updating the stats on
         * the deflink is fine?
         */
-       if (status->link_valid)
-               rx.link_id = status->link_id;
-
-       if (rx.link_id >= 0) {
-               struct ieee80211_link_data *link;
-
-               link =  rcu_dereference(rx.sdata->link[rx.link_id]);
-               if (!link)
-                       goto drop;
-               rx.link = link;
-       } else {
-               rx.link = &rx.sdata->deflink;
-       }
+       if (!ieee80211_rx_data_set_sta(&rx, pubsta, link_id))
+               goto drop;
 
        fast_rx = rcu_dereference(rx.sta->fast_rx);
        if (!fast_rx)
@@ -4930,6 +4919,8 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
 {
        struct link_sta_info *link_sta;
        struct ieee80211_hdr *hdr = (void *)skb->data;
+       struct sta_info *sta;
+       int link_id = -1;
 
        /*
         * Look up link station first, in case there's a
@@ -4939,24 +4930,19 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
         */
        link_sta = link_sta_info_get_bss(rx->sdata, hdr->addr2);
        if (link_sta) {
-               rx->sta = link_sta->sta;
-               rx->link_id = link_sta->link_id;
+               sta = link_sta->sta;
+               link_id = link_sta->link_id;
        } else {
                struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
-               rx->sta = sta_info_get_bss(rx->sdata, hdr->addr2);
-               if (rx->sta) {
-                       if (status->link_valid &&
-                           !ieee80211_rx_is_valid_sta_link_id(&rx->sta->sta,
-                                                              status->link_id))
-                               return false;
-
-                       rx->link_id = status->link_valid ? status->link_id : -1;
-               } else {
-                       rx->link_id = -1;
-               }
+               sta = sta_info_get_bss(rx->sdata, hdr->addr2);
+               if (status->link_valid)
+                       link_id = status->link_id;
        }
 
+       if (!ieee80211_rx_data_set_sta(rx, &sta->sta, link_id))
+               return false;
+
        return ieee80211_prepare_and_rx_handle(rx, skb, consume);
 }
 
@@ -5015,19 +5001,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 
        if (ieee80211_is_data(fc)) {
                struct sta_info *sta, *prev_sta;
-               u8 link_id = status->link_id;
+               int link_id = -1;
 
-               if (pubsta) {
-                       rx.sta = container_of(pubsta, struct sta_info, sta);
-                       rx.sdata = rx.sta->sdata;
+               if (status->link_valid)
+                       link_id = status->link_id;
 
-                       if (status->link_valid &&
-                           !ieee80211_rx_is_valid_sta_link_id(pubsta, link_id))
+               if (pubsta) {
+                       if (!ieee80211_rx_data_set_sta(&rx, pubsta, link_id))
                                goto out;
 
-                       if (status->link_valid)
-                               rx.link_id = status->link_id;
-
                        /*
                         * In MLO connection, fetch the link_id using addr2
                         * when the driver does not pass link_id in status.
@@ -5045,7 +5027,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                                if (!link_sta)
                                        goto out;
 
-                               rx.link_id = link_sta->link_id;
+                               ieee80211_rx_data_set_link(&rx, link_sta->link_id);
                        }
 
                        if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
@@ -5061,30 +5043,27 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                                continue;
                        }
 
-                       if ((status->link_valid &&
-                            !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta,
-                                                               link_id)) ||
-                           (!status->link_valid && prev_sta->sta.mlo))
+                       rx.sdata = prev_sta->sdata;
+                       if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta,
+                                                      link_id))
+                               goto out;
+
+                       if (!status->link_valid && prev_sta->sta.mlo)
                                continue;
 
-                       rx.link_id = status->link_valid ? link_id : -1;
-                       rx.sta = prev_sta;
-                       rx.sdata = prev_sta->sdata;
                        ieee80211_prepare_and_rx_handle(&rx, skb, false);
 
                        prev_sta = sta;
                }
 
                if (prev_sta) {
-                       if ((status->link_valid &&
-                            !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta,
-                                                               link_id)) ||
-                           (!status->link_valid && prev_sta->sta.mlo))
+                       rx.sdata = prev_sta->sdata;
+                       if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta,
+                                                      link_id))
                                goto out;
 
-                       rx.link_id = status->link_valid ? link_id : -1;
-                       rx.sta = prev_sta;
-                       rx.sdata = prev_sta->sdata;
+                       if (!status->link_valid && prev_sta->sta.mlo)
+                               goto out;
 
                        if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
                                return;
index 2171cd1..defe97a 100644 (file)
@@ -1129,7 +1129,6 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
        struct sk_buff *purge_skb = NULL;
 
        if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
-               info->flags |= IEEE80211_TX_CTL_AMPDU;
                reset_agg_timer = true;
        } else if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
                /*
@@ -1161,7 +1160,6 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
                if (!tid_tx) {
                        /* do nothing, let packet pass through */
                } else if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
-                       info->flags |= IEEE80211_TX_CTL_AMPDU;
                        reset_agg_timer = true;
                } else {
                        queued = true;
@@ -3677,8 +3675,7 @@ static void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
        info->band = fast_tx->band;
        info->control.vif = &sdata->vif;
        info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
-                     IEEE80211_TX_CTL_DONTFRAG |
-                     (ampdu ? IEEE80211_TX_CTL_AMPDU : 0);
+                     IEEE80211_TX_CTL_DONTFRAG;
        info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT |
                              u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
                                              IEEE80211_TX_CTRL_MLO_LINK);
@@ -3783,6 +3780,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
        struct ieee80211_tx_data tx;
        ieee80211_tx_result r;
        struct ieee80211_vif *vif = txq->vif;
+       int q = vif->hw_queue[txq->ac];
+       bool q_stopped;
 
        WARN_ON_ONCE(softirq_count() == 0);
 
@@ -3790,17 +3789,18 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
                return NULL;
 
 begin:
-       spin_lock_bh(&fq->lock);
-
-       if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags) ||
-           test_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags))
-               goto out;
+       spin_lock(&local->queue_stop_reason_lock);
+       q_stopped = local->queue_stop_reasons[q];
+       spin_unlock(&local->queue_stop_reason_lock);
 
-       if (vif->txqs_stopped[txq->ac]) {
-               set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags);
-               goto out;
+       if (unlikely(q_stopped)) {
+               /* mark for waking later */
+               set_bit(IEEE80211_TXQ_DIRTY, &txqi->flags);
+               return NULL;
        }
 
+       spin_lock_bh(&fq->lock);
+
        /* Make sure fragments stay together. */
        skb = __skb_dequeue(&txqi->frags);
        if (unlikely(skb)) {
@@ -3810,6 +3810,9 @@ begin:
                IEEE80211_SKB_CB(skb)->control.flags &=
                        ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
        } else {
+               if (unlikely(test_bit(IEEE80211_TXQ_STOP, &txqi->flags)))
+                       goto out;
+
                skb = fq_tin_dequeue(fq, tin, fq_tin_dequeue_func);
        }
 
@@ -3860,9 +3863,8 @@ begin:
        }
 
        if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
-               info->flags |= IEEE80211_TX_CTL_AMPDU;
-       else
-               info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+               info->flags |= (IEEE80211_TX_CTL_AMPDU |
+                               IEEE80211_TX_CTL_DONTFRAG);
 
        if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
                if (!ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
@@ -4596,8 +4598,6 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
 
        info = IEEE80211_SKB_CB(skb);
        memset(info, 0, sizeof(*info));
-       if (tid_tx)
-               info->flags |= IEEE80211_TX_CTL_AMPDU;
 
        info->hw_queue = sdata->vif.hw_queue[queue];
 
index 6f54070..261ac66 100644 (file)
@@ -292,22 +292,12 @@ static void wake_tx_push_queue(struct ieee80211_local *local,
                               struct ieee80211_sub_if_data *sdata,
                               struct ieee80211_txq *queue)
 {
-       int q = sdata->vif.hw_queue[queue->ac];
        struct ieee80211_tx_control control = {
                .sta = queue->sta,
        };
        struct sk_buff *skb;
-       unsigned long flags;
-       bool q_stopped;
 
        while (1) {
-               spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-               q_stopped = local->queue_stop_reasons[q];
-               spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
-
-               if (q_stopped)
-                       break;
-
                skb = ieee80211_tx_dequeue(&local->hw, queue);
                if (!skb)
                        break;
@@ -347,8 +337,6 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
        local_bh_disable();
        spin_lock(&fq->lock);
 
-       sdata->vif.txqs_stopped[ac] = false;
-
        if (!test_bit(SDATA_STATE_RUNNING, &sdata->state))
                goto out;
 
@@ -370,7 +358,7 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
                        if (ac != txq->ac)
                                continue;
 
-                       if (!test_and_clear_bit(IEEE80211_TXQ_STOP_NETIF_TX,
+                       if (!test_and_clear_bit(IEEE80211_TXQ_DIRTY,
                                                &txqi->flags))
                                continue;
 
@@ -385,7 +373,7 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
 
        txqi = to_txq_info(vif->txq);
 
-       if (!test_and_clear_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags) ||
+       if (!test_and_clear_bit(IEEE80211_TXQ_DIRTY, &txqi->flags) ||
            (ps && atomic_read(&ps->num_sta_ps)) || ac != vif->txq->ac)
                goto out;
 
@@ -517,8 +505,6 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
                                   bool refcounted)
 {
        struct ieee80211_local *local = hw_to_local(hw);
-       struct ieee80211_sub_if_data *sdata;
-       int n_acs = IEEE80211_NUM_ACS;
 
        trace_stop_queue(local, queue, reason);
 
@@ -530,29 +516,7 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
        else
                local->q_stop_reasons[queue][reason]++;
 
-       if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue]))
-               return;
-
-       if (local->hw.queues < IEEE80211_NUM_ACS)
-               n_acs = 1;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-               int ac;
-
-               if (!sdata->dev)
-                       continue;
-
-               for (ac = 0; ac < n_acs; ac++) {
-                       if (sdata->vif.hw_queue[ac] == queue ||
-                           sdata->vif.cab_queue == queue) {
-                               spin_lock(&local->fq.lock);
-                               sdata->vif.txqs_stopped[ac] = true;
-                               spin_unlock(&local->fq.lock);
-                       }
-               }
-       }
-       rcu_read_unlock();
+       set_bit(reason, &local->queue_stop_reasons[queue]);
 }
 
 void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
index 45e2a48..70f0ced 100644 (file)
@@ -420,6 +420,31 @@ void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
        }
 }
 
+/* if sk is ipv4 or ipv6_only allows only same-family local and remote addresses,
+ * otherwise allow any matching local/remote pair
+ */
+bool mptcp_pm_addr_families_match(const struct sock *sk,
+                                 const struct mptcp_addr_info *loc,
+                                 const struct mptcp_addr_info *rem)
+{
+       bool mptcp_is_v4 = sk->sk_family == AF_INET;
+
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+       bool loc_is_v4 = loc->family == AF_INET || ipv6_addr_v4mapped(&loc->addr6);
+       bool rem_is_v4 = rem->family == AF_INET || ipv6_addr_v4mapped(&rem->addr6);
+
+       if (mptcp_is_v4)
+               return loc_is_v4 && rem_is_v4;
+
+       if (ipv6_only_sock(sk))
+               return !loc_is_v4 && !rem_is_v4;
+
+       return loc_is_v4 == rem_is_v4;
+#else
+       return mptcp_is_v4 && loc->family == AF_INET && rem->family == AF_INET;
+#endif
+}
+
 void mptcp_pm_data_reset(struct mptcp_sock *msk)
 {
        u8 pm_type = mptcp_get_pm_type(sock_net((struct sock *)msk));
index 65dcc55..ea6ad9d 100644 (file)
@@ -294,6 +294,13 @@ int mptcp_nl_cmd_sf_create(struct sk_buff *skb, struct genl_info *info)
        }
 
        sk = (struct sock *)msk;
+
+       if (!mptcp_pm_addr_families_match(sk, &addr_l, &addr_r)) {
+               GENL_SET_ERR_MSG(info, "families mismatch");
+               err = -EINVAL;
+               goto create_err;
+       }
+
        lock_sock(sk);
 
        err = __mptcp_subflow_connect(sk, &addr_l, &addr_r);
index b7ad030..8cd6cc6 100644 (file)
@@ -98,7 +98,7 @@ static int __mptcp_socket_create(struct mptcp_sock *msk)
        struct socket *ssock;
        int err;
 
-       err = mptcp_subflow_create_socket(sk, &ssock);
+       err = mptcp_subflow_create_socket(sk, sk->sk_family, &ssock);
        if (err)
                return err;
 
index a0d1658..6014692 100644 (file)
@@ -641,7 +641,8 @@ bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
 /* called with sk socket lock held */
 int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
                            const struct mptcp_addr_info *remote);
-int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock);
+int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,
+                               struct socket **new_sock);
 void mptcp_info2sockaddr(const struct mptcp_addr_info *info,
                         struct sockaddr_storage *addr,
                         unsigned short family);
@@ -776,6 +777,9 @@ int mptcp_pm_parse_addr(struct nlattr *attr, struct genl_info *info,
 int mptcp_pm_parse_entry(struct nlattr *attr, struct genl_info *info,
                         bool require_family,
                         struct mptcp_pm_addr_entry *entry);
+bool mptcp_pm_addr_families_match(const struct sock *sk,
+                                 const struct mptcp_addr_info *loc,
+                                 const struct mptcp_addr_info *rem);
 void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk);
 void mptcp_pm_nl_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk);
 void mptcp_pm_new_connection(struct mptcp_sock *msk, const struct sock *ssk, int server_side);
index bd387d4..ec54413 100644 (file)
@@ -1547,7 +1547,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
        if (!mptcp_is_fully_established(sk))
                goto err_out;
 
-       err = mptcp_subflow_create_socket(sk, &sf);
+       err = mptcp_subflow_create_socket(sk, loc->family, &sf);
        if (err)
                goto err_out;
 
@@ -1660,7 +1660,9 @@ static void mptcp_subflow_ops_undo_override(struct sock *ssk)
 #endif
                ssk->sk_prot = &tcp_prot;
 }
-int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)
+
+int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,
+                               struct socket **new_sock)
 {
        struct mptcp_subflow_context *subflow;
        struct net *net = sock_net(sk);
@@ -1673,8 +1675,7 @@ int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)
        if (unlikely(!sk->sk_socket))
                return -EINVAL;
 
-       err = sock_create_kern(net, sk->sk_family, SOCK_STREAM, IPPROTO_TCP,
-                              &sf);
+       err = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP, &sf);
        if (err)
                return err;
 
index a8ce04a..e4fa00a 100644 (file)
@@ -308,8 +308,8 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
                        return -IPSET_ERR_BITMAP_RANGE;
 
                pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
-               hosts = 2 << (32 - netmask - 1);
-               elements = 2 << (netmask - mask_bits - 1);
+               hosts = 2U << (32 - netmask - 1);
+               elements = 2UL << (netmask - mask_bits - 1);
        }
        if (elements > IPSET_BITMAP_MAX_RANGE + 1)
                return -IPSET_ERR_BITMAP_RANGE_SIZE;
index 6566310..3ac1af6 100644 (file)
@@ -1068,6 +1068,13 @@ int nf_conntrack_tcp_packet(struct nf_conn *ct,
                                ct->proto.tcp.last_flags |=
                                        IP_CT_EXP_CHALLENGE_ACK;
                }
+
+               /* possible challenge ack reply to syn */
+               if (old_state == TCP_CONNTRACK_SYN_SENT &&
+                   index == TCP_ACK_SET &&
+                   dir == IP_CT_DIR_REPLY)
+                       ct->proto.tcp.last_ack = ntohl(th->ack_seq);
+
                spin_unlock_bh(&ct->lock);
                nf_ct_l4proto_log_invalid(skb, ct, state,
                                          "packet (index %d) in dir %d ignored, state %s",
@@ -1193,6 +1200,14 @@ int nf_conntrack_tcp_packet(struct nf_conn *ct,
                         * segments we ignored. */
                        goto in_window;
                }
+
+               /* Reset in response to a challenge-ack we let through earlier */
+               if (old_state == TCP_CONNTRACK_SYN_SENT &&
+                   ct->proto.tcp.last_index == TCP_ACK_SET &&
+                   ct->proto.tcp.last_dir == IP_CT_DIR_REPLY &&
+                   ntohl(th->seq) == ct->proto.tcp.last_ack)
+                       goto in_window;
+
                break;
        default:
                /* Keep compilers happy. */
index 17b418a..3a3c774 100644 (file)
@@ -63,7 +63,7 @@ nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len)
                        return false;
 
                if (offset + len > VLAN_ETH_HLEN + vlan_hlen)
-                       ethlen -= offset + len - VLAN_ETH_HLEN + vlan_hlen;
+                       ethlen -= offset + len - VLAN_ETH_HLEN - vlan_hlen;
 
                memcpy(dst_u8, vlanh + offset - vlan_hlen, ethlen);
 
index 3364caa..a27e184 100644 (file)
@@ -157,6 +157,7 @@ static void local_cleanup(struct nfc_llcp_local *local)
        cancel_work_sync(&local->rx_work);
        cancel_work_sync(&local->timeout_work);
        kfree_skb(local->rx_pending);
+       local->rx_pending = NULL;
        del_timer_sync(&local->sdreq_timer);
        cancel_work_sync(&local->sdreq_timeout_work);
        nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs);
index 3ded5a2..f3c9f02 100644 (file)
@@ -294,7 +294,7 @@ static void rxrpc_put_call_slot(struct rxrpc_call *call)
 static int rxrpc_connect_call(struct rxrpc_call *call, gfp_t gfp)
 {
        struct rxrpc_local *local = call->local;
-       int ret = 0;
+       int ret = -ENOMEM;
 
        _enter("{%d,%lx},", call->debug_id, call->user_call_ID);
 
index a661b06..872d127 100644 (file)
@@ -377,6 +377,7 @@ static int gred_offload_dump_stats(struct Qdisc *sch)
        /* Even if driver returns failure adjust the stats - in case offload
         * ended but driver still wants to adjust the values.
         */
+       sch_tree_lock(sch);
        for (i = 0; i < MAX_DPs; i++) {
                if (!table->tab[i])
                        continue;
@@ -393,6 +394,7 @@ static int gred_offload_dump_stats(struct Qdisc *sch)
                sch->qstats.overlimits += hw_stats->stats.qstats[i].overlimits;
        }
        _bstats_update(&sch->bstats, bytes, packets);
+       sch_tree_unlock(sch);
 
        kfree(hw_stats);
        return ret;
index 2238ede..f466438 100644 (file)
@@ -1549,7 +1549,7 @@ static int htb_destroy_class_offload(struct Qdisc *sch, struct htb_class *cl,
        struct tc_htb_qopt_offload offload_opt;
        struct netdev_queue *dev_queue;
        struct Qdisc *q = cl->leaf.q;
-       struct Qdisc *old = NULL;
+       struct Qdisc *old;
        int err;
 
        if (cl->level)
@@ -1557,14 +1557,17 @@ static int htb_destroy_class_offload(struct Qdisc *sch, struct htb_class *cl,
 
        WARN_ON(!q);
        dev_queue = htb_offload_get_queue(cl);
-       old = htb_graft_helper(dev_queue, NULL);
-       if (destroying)
-               /* Before HTB is destroyed, the kernel grafts noop_qdisc to
-                * all queues.
+       /* When destroying, caller qdisc_graft grafts the new qdisc and invokes
+        * qdisc_put for the qdisc being destroyed. htb_destroy_class_offload
+        * does not need to graft or qdisc_put the qdisc being destroyed.
+        */
+       if (!destroying) {
+               old = htb_graft_helper(dev_queue, NULL);
+               /* Last qdisc grafted should be the same as cl->leaf.q when
+                * calling htb_delete.
                 */
-               WARN_ON(!(old->flags & TCQ_F_BUILTIN));
-       else
                WARN_ON(old != q);
+       }
 
        if (cl->parent) {
                _bstats_update(&cl->parent->bstats_bias,
@@ -1581,10 +1584,12 @@ static int htb_destroy_class_offload(struct Qdisc *sch, struct htb_class *cl,
        };
        err = htb_offload(qdisc_dev(sch), &offload_opt);
 
-       if (!err || destroying)
-               qdisc_put(old);
-       else
-               htb_graft_helper(dev_queue, old);
+       if (!destroying) {
+               if (!err)
+                       qdisc_put(old);
+               else
+                       htb_graft_helper(dev_queue, old);
+       }
 
        if (last_child)
                return err;
index 570389f..9a11a49 100644 (file)
@@ -1700,6 +1700,8 @@ static void taprio_reset(struct Qdisc *sch)
        int i;
 
        hrtimer_cancel(&q->advance_timer);
+       qdisc_synchronize(sch);
+
        if (q->qdiscs) {
                for (i = 0; i < dev->num_tx_queues; i++)
                        if (q->qdiscs[i])
@@ -1720,6 +1722,7 @@ static void taprio_destroy(struct Qdisc *sch)
         * happens in qdisc_create(), after taprio_init() has been called.
         */
        hrtimer_cancel(&q->advance_timer);
+       qdisc_synchronize(sch);
 
        taprio_disable_offload(dev, q, NULL);
 
index 4192855..7eca035 100755 (executable)
@@ -26,11 +26,20 @@ try:
        # If the MAKEFLAGS variable contains multiple instances of the
        # --jobserver-auth= option, the last one is relevant.
        fds = opts[-1].split("=", 1)[1]
-       reader, writer = [int(x) for x in fds.split(",", 1)]
-       # Open a private copy of reader to avoid setting nonblocking
-       # on an unexpecting process with the same reader fd.
-       reader = os.open("/proc/self/fd/%d" % (reader),
-                        os.O_RDONLY | os.O_NONBLOCK)
+
+       # Starting with GNU Make 4.4, named pipes are used for reader and writer.
+       # Example argument: --jobserver-auth=fifo:/tmp/GMfifo8134
+       _, _, path = fds.partition('fifo:')
+
+       if path:
+               reader = os.open(path, os.O_RDONLY | os.O_NONBLOCK)
+               writer = os.open(path, os.O_WRONLY)
+       else:
+               reader, writer = [int(x) for x in fds.split(",", 1)]
+               # Open a private copy of reader to avoid setting nonblocking
+               # on an unexpecting process with the same reader fd.
+               reader = os.open("/proc/self/fd/%d" % (reader),
+                                os.O_RDONLY | os.O_NONBLOCK)
 
        # Read out as many jobserver slots as possible.
        while True:
index c8a3f9c..0b2ff77 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 /conf
 /[gmnq]conf
+/[gmnq]conf-bin
 /[gmnq]conf-cflags
 /[gmnq]conf-libs
-/qconf-bin
 /qconf-moc.cc
index 0b1d15e..af1c961 100644 (file)
@@ -209,7 +209,7 @@ $(obj)/gconf: | $(obj)/gconf-libs
 $(obj)/gconf.o: | $(obj)/gconf-cflags
 
 # check if necessary packages are available, and configure build flags
-cmd_conf_cfg = $< $(addprefix $(obj)/$*conf-, cflags libs bin)
+cmd_conf_cfg = $< $(addprefix $(obj)/$*conf-, cflags libs bin); touch $(obj)/$*conf-bin
 
 $(obj)/%conf-cflags $(obj)/%conf-libs $(obj)/%conf-bin: $(src)/%conf-cfg.sh
        $(call cmd,conf_cfg)
index adab28f..094e52c 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 #
 #      Output a simple RPM spec file.
-#      This version assumes a minimum of RPM 4.0.3.
+#      This version assumes a minimum of RPM 4.13
 #
 #      The only gothic bit here is redefining install_post to avoid
 #      stripping the symbols from files in the kernel which we want
index b9f8671..fad75be 100644 (file)
@@ -6,13 +6,11 @@ config SECURITY_TOMOYO
        select SECURITYFS
        select SECURITY_PATH
        select SECURITY_NETWORK
-       select SRCU
-       select BUILD_BIN2C
        default n
        help
          This selects TOMOYO Linux, pathname-based access control.
          Required userspace tools and further information may be
-         found at <http://tomoyo.sourceforge.jp/>.
+         found at <https://tomoyo.osdn.jp/>.
          If you are unsure how to answer this question, answer N.
 
 config SECURITY_TOMOYO_MAX_ACCEPT_ENTRY
index cca5a30..884ff15 100644 (file)
@@ -2,15 +2,18 @@
 obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o network.o realpath.o securityfs_if.o tomoyo.o util.o
 
 targets += builtin-policy.h
-define do_policy
-echo "static char tomoyo_builtin_$(1)[] __initdata ="; \
-$(objtree)/scripts/bin2c <$(firstword $(wildcard $(obj)/policy/$(1).conf $(srctree)/$(src)/policy/$(1).conf.default) /dev/null); \
-echo ";"
-endef
-quiet_cmd_policy  = POLICY  $@
-      cmd_policy  = ($(call do_policy,profile); $(call do_policy,exception_policy); $(call do_policy,domain_policy); $(call do_policy,manager); $(call do_policy,stat)) >$@
 
-$(obj)/builtin-policy.h: $(wildcard $(obj)/policy/*.conf $(src)/policy/*.conf.default) FORCE
+quiet_cmd_policy = POLICY  $@
+      cmd_policy = { \
+       $(foreach x, profile exception_policy domain_policy manager stat, \
+       printf 'static char tomoyo_builtin_$x[] __initdata =\n'; \
+       sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/\t"\1\\n"/' -- $(firstword $(filter %/$x.conf %/$x.conf.default, $^) /dev/null);  \
+       printf '\t"";\n';) \
+       } > $@
+
+$(obj)/builtin-policy.h: $(wildcard $(obj)/policy/*.conf $(srctree)/$(src)/policy/*.conf.default) FORCE
        $(call if_changed,policy)
 
+ifndef CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING
 $(obj)/common.o: $(obj)/builtin-policy.h
+endif
index abc4186..683ca3a 100644 (file)
@@ -41,7 +41,7 @@
        (((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
 
 #define MIDR_CPU_MODEL(imp, partnum) \
-       (((imp)                 << MIDR_IMPLEMENTOR_SHIFT) | \
+       ((_AT(u32, imp)         << MIDR_IMPLEMENTOR_SHIFT) | \
        (0xf                    << MIDR_ARCHITECTURE_SHIFT) | \
        ((partnum)              << MIDR_PARTNUM_SHIFT))
 
@@ -80,6 +80,7 @@
 #define ARM_CPU_PART_CORTEX_X1         0xD44
 #define ARM_CPU_PART_CORTEX_A510       0xD46
 #define ARM_CPU_PART_CORTEX_A710       0xD47
+#define ARM_CPU_PART_CORTEX_A715       0xD4D
 #define ARM_CPU_PART_CORTEX_X2         0xD48
 #define ARM_CPU_PART_NEOVERSE_N2       0xD49
 #define ARM_CPU_PART_CORTEX_A78C       0xD4B
 #define APPLE_CPU_PART_M1_FIRESTORM_PRO        0x025
 #define APPLE_CPU_PART_M1_ICESTORM_MAX 0x028
 #define APPLE_CPU_PART_M1_FIRESTORM_MAX        0x029
+#define APPLE_CPU_PART_M2_BLIZZARD     0x032
+#define APPLE_CPU_PART_M2_AVALANCHE    0x033
 
 #define AMPERE_CPU_PART_AMPERE1                0xAC3
 
 #define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
 #define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510)
 #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
+#define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715)
 #define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
 #define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
 #define MIDR_CORTEX_A78C       MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C)
 #define MIDR_APPLE_M1_FIRESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO)
 #define MIDR_APPLE_M1_ICESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_MAX)
 #define MIDR_APPLE_M1_FIRESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX)
+#define MIDR_APPLE_M2_BLIZZARD MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD)
+#define MIDR_APPLE_M2_AVALANCHE MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE)
 #define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1)
 
 /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
index 316917b..a7a857f 100644 (file)
@@ -43,6 +43,7 @@
 #define __KVM_HAVE_VCPU_EVENTS
 
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#define KVM_DIRTY_LOG_PAGE_OFFSET 64
 
 #define KVM_REG_SIZE(id)                                               \
        (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
index 649e50a..e48deab 100644 (file)
@@ -206,6 +206,8 @@ struct kvm_msr_list {
 struct kvm_msr_filter_range {
 #define KVM_MSR_FILTER_READ  (1 << 0)
 #define KVM_MSR_FILTER_WRITE (1 << 1)
+#define KVM_MSR_FILTER_RANGE_VALID_MASK (KVM_MSR_FILTER_READ | \
+                                        KVM_MSR_FILTER_WRITE)
        __u32 flags;
        __u32 nmsrs; /* number of msrs in bitmap */
        __u32 base;  /* MSR index the bitmap starts at */
@@ -214,8 +216,11 @@ struct kvm_msr_filter_range {
 
 #define KVM_MSR_FILTER_MAX_RANGES 16
 struct kvm_msr_filter {
+#ifndef __KERNEL__
 #define KVM_MSR_FILTER_DEFAULT_ALLOW (0 << 0)
+#endif
 #define KVM_MSR_FILTER_DEFAULT_DENY  (1 << 0)
+#define KVM_MSR_FILTER_VALID_MASK (KVM_MSR_FILTER_DEFAULT_DENY)
        __u32 flags;
        struct kvm_msr_filter_range ranges[KVM_MSR_FILTER_MAX_RANGES];
 };
index cc7070c..b4898ff 100644 (file)
 #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
 #endif // static_assert
 
+
+/*
+ * Compile time check that field has an expected offset
+ */
+#define ASSERT_STRUCT_OFFSET(type, field, expected_offset)     \
+       BUILD_BUG_ON_MSG(offsetof(type, field) != (expected_offset),    \
+               "Offset of " #field " in " #type " has changed.")
+
+
 #endif /* _LINUX_BUILD_BUG_H */
index 20522d4..55155e2 100644 (file)
@@ -1767,6 +1767,7 @@ struct kvm_xen_hvm_attr {
                __u8 runstate_update_flag;
                struct {
                        __u64 gfn;
+#define KVM_XEN_INVALID_GFN ((__u64)-1)
                } shared_info;
                struct {
                        __u32 send_port;
@@ -1798,6 +1799,7 @@ struct kvm_xen_hvm_attr {
        } u;
 };
 
+
 /* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
 #define KVM_XEN_ATTR_TYPE_LONG_MODE            0x0
 #define KVM_XEN_ATTR_TYPE_SHARED_INFO          0x1
@@ -1823,6 +1825,7 @@ struct kvm_xen_vcpu_attr {
        __u16 pad[3];
        union {
                __u64 gpa;
+#define KVM_XEN_INVALID_GPA ((__u64)-1)
                __u64 pad[8];
                struct {
                        __u64 state;
index f05670d..aaf8511 100755 (executable)
@@ -77,7 +77,20 @@ check()
        file=${build_id_dir}/.build-id/${id:0:2}/`readlink ${link}`/elf
        echo "file: ${file}"
 
-       if [ ! -x $file ]; then
+       # Check for file permission of original file
+       # in case of pe-file.exe file
+       echo $1 | grep ".exe"
+       if [ $? -eq 0 ]; then
+               if [ -x $1  -a ! -x $file ]; then
+                       echo "failed: file ${file} executable does not exist"
+                       exit 1
+               fi
+
+               if [ ! -x $file -a ! -e $file ]; then
+                       echo "failed: file ${file} does not exist"
+                       exit 1
+               fi
+       elif [ ! -x $file ]; then
                echo "failed: file ${file} does not exist"
                exit 1
        fi
index de3701a..13c3a23 100644 (file)
@@ -33,7 +33,10 @@ typedef __kernel_sa_family_t sa_family_t;
 
 struct sockaddr {
        sa_family_t     sa_family;      /* address family, AF_xxx       */
-       char            sa_data[14];    /* 14 bytes of protocol address */
+       union {
+               char sa_data_min[14];           /* Minimum 14 bytes of protocol address */
+               DECLARE_FLEX_ARRAY(char, sa_data);
+       };
 };
 
 struct linger {
index a839b30..ea9c083 100644 (file)
@@ -715,9 +715,13 @@ build_id_cache__add(const char *sbuild_id, const char *name, const char *realnam
                } else if (nsi && nsinfo__need_setns(nsi)) {
                        if (copyfile_ns(name, filename, nsi))
                                goto out_free;
-               } else if (link(realname, filename) && errno != EEXIST &&
-                               copyfile(name, filename))
-                       goto out_free;
+               } else if (link(realname, filename) && errno != EEXIST) {
+                       struct stat f_stat;
+
+                       if (!(stat(name, &f_stat) < 0) &&
+                                       copyfile_mode(name, filename, f_stat.st_mode))
+                               goto out_free;
+               }
        }
 
        /* Some binaries are stripped, but have .debug files with their symbol
index 0168a96..d47de5f 100644 (file)
@@ -42,8 +42,11 @@ static char *normalize(char *str, int runtime)
        char *dst = str;
 
        while (*str) {
-               if (*str == '\\')
+               if (*str == '\\') {
                        *dst++ = *++str;
+                       if (!*str)
+                               break;
+               }
                else if (*str == '?') {
                        char *paramval;
                        int i = 0;
index 291144c..f7900e7 100644 (file)
@@ -20,7 +20,7 @@ CLANG_TARGET_FLAGS              := $(CLANG_TARGET_FLAGS_$(ARCH))
 
 ifeq ($(CROSS_COMPILE),)
 ifeq ($(CLANG_TARGET_FLAGS),)
-$(error Specify CROSS_COMPILE or add '--target=' option to lib.mk
+$(error Specify CROSS_COMPILE or add '--target=' option to lib.mk)
 else
 CLANG_FLAGS     += --target=$(CLANG_TARGET_FLAGS)
 endif # CLANG_TARGET_FLAGS
index a29deb9..ab2d581 100755 (executable)
@@ -752,6 +752,52 @@ test_subflows()
           "$server4_token" > /dev/null 2>&1
 }
 
+test_subflows_v4_v6_mix()
+{
+       # Attempt to add a listener at 10.0.2.1:<subflow-port>
+       ip netns exec "$ns1" ./pm_nl_ctl listen 10.0.2.1\
+          $app6_port > /dev/null 2>&1 &
+       local listener_pid=$!
+
+       # ADD_ADDR4 from server to client machine reusing the subflow port on
+       # the established v6 connection
+       :>"$client_evts"
+       ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server6_token" id\
+          $server_addr_id dev ns1eth2 > /dev/null 2>&1
+       stdbuf -o0 -e0 printf "ADD_ADDR4 id:%d 10.0.2.1 (ns1) => ns2, reuse port\t\t" $server_addr_id
+       sleep 0.5
+       verify_announce_event "$client_evts" "$ANNOUNCED" "$client6_token" "10.0.2.1"\
+                             "$server_addr_id" "$app6_port"
+
+       # CREATE_SUBFLOW from client to server machine
+       :>"$client_evts"
+       ip netns exec "$ns2" ./pm_nl_ctl csf lip 10.0.2.2 lid 23 rip 10.0.2.1 rport\
+          $app6_port token "$client6_token" > /dev/null 2>&1
+       sleep 0.5
+       verify_subflow_events "$client_evts" "$SUB_ESTABLISHED" "$client6_token"\
+                             "$AF_INET" "10.0.2.2" "10.0.2.1" "$app6_port" "23"\
+                             "$server_addr_id" "ns2" "ns1"
+
+       # Delete the listener from the server ns, if one was created
+       kill_wait $listener_pid
+
+       sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$client_evts")
+
+       # DESTROY_SUBFLOW from client to server machine
+       :>"$client_evts"
+       ip netns exec "$ns2" ./pm_nl_ctl dsf lip 10.0.2.2 lport "$sport" rip 10.0.2.1 rport\
+          $app6_port token "$client6_token" > /dev/null 2>&1
+       sleep 0.5
+       verify_subflow_events "$client_evts" "$SUB_CLOSED" "$client6_token" \
+                             "$AF_INET" "10.0.2.2" "10.0.2.1" "$app6_port" "23"\
+                             "$server_addr_id" "ns2" "ns1"
+
+       # RM_ADDR from server to client machine
+       ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
+          "$server6_token" > /dev/null 2>&1
+       sleep 0.5
+}
+
 test_prio()
 {
        local count
@@ -861,6 +907,7 @@ make_connection "v6"
 test_announce
 test_remove
 test_subflows
+test_subflows_v4_v6_mix
 test_prio
 test_listener
 
index 90026a2..9ba0316 100644 (file)
@@ -215,7 +215,7 @@ static char *recv_frame(const struct ring_state *ring, char *frame)
 }
 
 /* A single TPACKET_V3 block can hold multiple frames */
-static void recv_block(struct ring_state *ring)
+static bool recv_block(struct ring_state *ring)
 {
        struct tpacket_block_desc *block;
        char *frame;
@@ -223,7 +223,7 @@ static void recv_block(struct ring_state *ring)
 
        block = (void *)(ring->mmap + ring->idx * ring_block_sz);
        if (!(block->hdr.bh1.block_status & TP_STATUS_USER))
-               return;
+               return false;
 
        frame = (char *)block;
        frame += block->hdr.bh1.offset_to_first_pkt;
@@ -235,6 +235,8 @@ static void recv_block(struct ring_state *ring)
 
        block->hdr.bh1.block_status = TP_STATUS_KERNEL;
        ring->idx = (ring->idx + 1) % ring_block_nr;
+
+       return true;
 }
 
 /* simple test: sleep once unconditionally and then process all rings */
@@ -245,7 +247,7 @@ static void process_rings(void)
        usleep(1000 * cfg_timeout_msec);
 
        for (i = 0; i < num_cpus; i++)
-               recv_block(&rings[i]);
+               do {} while (recv_block(&rings[i]));
 
        fprintf(stderr, "count: pass=%u nohash=%u fail=%u\n",
                frames_received - frames_nohash - frames_error,
@@ -257,12 +259,12 @@ static char *setup_ring(int fd)
        struct tpacket_req3 req3 = {0};
        void *ring;
 
-       req3.tp_retire_blk_tov = cfg_timeout_msec;
+       req3.tp_retire_blk_tov = cfg_timeout_msec / 8;
        req3.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH;
 
        req3.tp_frame_size = 2048;
        req3.tp_frame_nr = 1 << 10;
-       req3.tp_block_nr = 2;
+       req3.tp_block_nr = 16;
 
        req3.tp_block_size = req3.tp_frame_size * req3.tp_frame_nr;
        req3.tp_block_size /= req3.tp_block_nr;
index a7f62ad..2ffba45 100755 (executable)
 ksft_skip=4
 
 testns=testns-$(mktemp -u "XXXXXXXX")
+tmp=""
 
 tables="foo bar baz quux"
 global_ret=0
 eret=0
 lret=0
 
+cleanup() {
+       ip netns pids "$testns" | xargs kill 2>/dev/null
+       ip netns del "$testns"
+
+       rm -f "$tmp"
+}
+
 check_result()
 {
        local r=$1
@@ -43,6 +51,7 @@ if [ $? -ne 0 ];then
        exit $ksft_skip
 fi
 
+trap cleanup EXIT
 tmp=$(mktemp)
 
 for table in $tables; do
@@ -139,11 +148,4 @@ done
 
 check_result $lret "add/delete with nftrace enabled"
 
-pkill -9 ping
-
-wait
-
-rm -f "$tmp"
-ip netns del "$testns"
-
 exit $global_ret
diff --git a/tools/testing/selftests/netfilter/settings b/tools/testing/selftests/netfilter/settings
new file mode 100644 (file)
index 0000000..6091b45
--- /dev/null
@@ -0,0 +1 @@
+timeout=120
index d95b1cb..7588428 100644 (file)
@@ -25,6 +25,7 @@
 #undef NDEBUG
 #include <assert.h>
 #include <errno.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -41,7 +42,7 @@
  * 1: vsyscall VMA is --xp             vsyscall=xonly
  * 2: vsyscall VMA is r-xp             vsyscall=emulate
  */
-static int g_vsyscall;
+static volatile int g_vsyscall;
 static const char *g_proc_pid_maps_vsyscall;
 static const char *g_proc_pid_smaps_vsyscall;
 
@@ -147,11 +148,12 @@ static void vsyscall(void)
 
                g_vsyscall = 0;
                /* gettimeofday(NULL, NULL); */
+               uint64_t rax = 0xffffffffff600000;
                asm volatile (
-                       "call %P0"
-                       :
-                       : "i" (0xffffffffff600000), "D" (NULL), "S" (NULL)
-                       : "rax", "rcx", "r11"
+                       "call *%[rax]"
+                       : [rax] "+a" (rax)
+                       : "D" (NULL), "S" (NULL)
+                       : "rcx", "r11"
                );
 
                g_vsyscall = 1;
index 69551bf..cacbd2a 100644 (file)
@@ -257,11 +257,12 @@ static void vsyscall(void)
 
                g_vsyscall = 0;
                /* gettimeofday(NULL, NULL); */
+               uint64_t rax = 0xffffffffff600000;
                asm volatile (
-                       "call %P0"
-                       :
-                       : "i" (0xffffffffff600000), "D" (NULL), "S" (NULL)
-                       : "rax", "rcx", "r11"
+                       "call *%[rax]"
+                       : [rax] "+a" (rax)
+                       : "D" (NULL), "S" (NULL)
+                       : "rcx", "r11"
                );
 
                g_vsyscall = 1;