Merge tag 'amd-drm-fixes-5.19-2022-07-06' of https://gitlab.freedesktop.org/agd5f...
authorDave Airlie <airlied@redhat.com>
Tue, 12 Jul 2022 00:34:42 +0000 (10:34 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 12 Jul 2022 00:34:43 +0000 (10:34 +1000)
amd-drm-fixes-5.19-2022-07-06:

amdgpu:
- Hibernation fix

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220707024421.5773-1-alexander.deucher@amd.com
398 files changed:
.mailmap
Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
Documentation/process/maintainer-netdev.rst
MAINTAINERS
Makefile
arch/arm/boot/dts/at91-sam9x60ek.dts
arch/arm/boot/dts/at91-sama5d2_icp.dts
arch/arm/boot/dts/imx7d-smegw01.dts
arch/arm/boot/dts/stm32mp15-scmi.dtsi
arch/arm/boot/dts/stm32mp151.dtsi
arch/arm/boot/dts/stm32mp157a-dk1-scmi.dts
arch/arm/boot/dts/stm32mp157c-dk2-scmi.dts
arch/arm/boot/dts/stm32mp157c-ed1-scmi.dts
arch/arm/boot/dts/stm32mp157c-ev1-scmi.dts
arch/arm/configs/mxs_defconfig
arch/arm/mach-at91/pm.c
arch/arm/mach-meson/platsmp.c
arch/arm/xen/p2m.c
arch/arm64/boot/dts/freescale/imx8mp-evk.dts
arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp-edimm2.2.dts
arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-rdk.dts
arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
arch/arm64/boot/dts/freescale/imx8mp.dtsi
arch/arm64/boot/dts/qcom/msm8992-lg-bullhead.dtsi
arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
arch/arm64/boot/dts/qcom/msm8994.dtsi
arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi
arch/arm64/boot/dts/qcom/sdm845.dtsi
arch/arm64/boot/dts/qcom/sm8450.dtsi
arch/arm64/mm/hugetlbpage.c
arch/loongarch/Kconfig
arch/loongarch/include/asm/fpregdef.h
arch/loongarch/include/asm/page.h
arch/loongarch/include/asm/processor.h
arch/loongarch/kernel/asm-offsets.c
arch/loongarch/kernel/fpu.S
arch/loongarch/kernel/numa.c
arch/loongarch/vdso/Makefile
arch/openrisc/kernel/unwinder.c
arch/parisc/kernel/asm-offsets.c
arch/parisc/kernel/unaligned.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/bpf_perf_event.h [new file with mode: 0644]
arch/powerpc/include/uapi/asm/bpf_perf_event.h [deleted file]
arch/powerpc/kernel/prom_init_check.sh
arch/powerpc/mm/mem.c
arch/powerpc/mm/nohash/book3e_pgtable.c
arch/powerpc/platforms/powernv/rng.c
arch/powerpc/sysdev/xive/spapr.c
arch/s390/Kconfig
arch/s390/crypto/arch_random.c
arch/s390/include/asm/archrandom.h
arch/s390/include/asm/qdio.h
arch/s390/kernel/setup.c
arch/s390/purgatory/Makefile
arch/x86/boot/compressed/ident_map_64.c
arch/x86/include/asm/setup.h
arch/x86/include/uapi/asm/bootparam.h
arch/x86/kernel/acpi/cppc.c
arch/x86/kernel/head64.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/xen/enlighten_pv.c
arch/x86/xen/xen-head.S
crypto/Kconfig
drivers/acpi/acpi_video.c
drivers/acpi/bus.c
drivers/acpi/cppc_acpi.c
drivers/ata/pata_cs5535.c
drivers/base/core.c
drivers/base/power/runtime.c
drivers/block/xen-blkfront.c
drivers/clk/stm32/reset-stm32.c
drivers/cpufreq/amd-pstate.c
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/cpufreq/pmac32-cpufreq.c
drivers/cpufreq/qcom-cpufreq-hw.c
drivers/cpufreq/qoriq-cpufreq.c
drivers/crypto/Kconfig
drivers/crypto/ccp/sp-platform.c
drivers/cxl/core/hdm.c
drivers/cxl/core/mbox.c
drivers/cxl/core/port.c
drivers/cxl/cxl.h
drivers/cxl/cxlmem.h
drivers/cxl/mem.c
drivers/cxl/pmem.c
drivers/devfreq/devfreq.c
drivers/devfreq/event/exynos-ppmu.c
drivers/devfreq/exynos-bus.c
drivers/devfreq/governor_passive.c
drivers/dma/at_xdmac.c
drivers/dma/dmatest.c
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
drivers/dma/idxd/device.c
drivers/dma/idxd/init.c
drivers/dma/imx-sdma.c
drivers/dma/lgm/lgm-dma.c
drivers/dma/pl330.c
drivers/dma/qcom/bam_dma.c
drivers/dma/ti/dma-crossbar.c
drivers/firmware/arm_scmi/bus.c
drivers/firmware/arm_scmi/clock.c
drivers/firmware/arm_scmi/driver.c
drivers/firmware/arm_scmi/optee.c
drivers/firmware/arm_scmi/protocols.h
drivers/gpio/gpio-vf610.c
drivers/gpio/gpiolib-cdev.c
drivers/gpu/drm/drm_aperture.c
drivers/hwmon/ibmaem.c
drivers/hwmon/occ/common.c
drivers/hwmon/occ/common.h
drivers/hwmon/occ/p8_i2c.c
drivers/hwmon/occ/p9_sbe.c
drivers/hwmon/pmbus/ucd9200.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-piix4.c
drivers/infiniband/core/cm.c
drivers/infiniband/hw/qedr/qedr.h
drivers/infiniband/hw/qedr/verbs.c
drivers/iommu/intel/dmar.c
drivers/iommu/intel/iommu.c
drivers/iommu/intel/pasid.c
drivers/iommu/intel/pasid.h
drivers/irqchip/Kconfig
drivers/irqchip/irq-apple-aic.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-or1k-pic.c
drivers/md/dm-raid.c
drivers/md/raid5.c
drivers/misc/cardreader/rtsx_usb.c
drivers/misc/eeprom/at25.c
drivers/net/Kconfig
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_alb.c
drivers/net/caif/caif_virtio.c
drivers/net/can/grcan.c
drivers/net/can/m_can/m_can.c
drivers/net/can/rcar/rcar_canfd.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
drivers/net/can/usb/gs_usb.c
drivers/net/can/usb/kvaser_usb/kvaser_usb.h
drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
drivers/net/can/xilinx_can.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/hirschmann/hellcreek_ptp.c
drivers/net/dsa/ocelot/felix_vsc9959.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_register.h
drivers/net/ethernet/intel/i40e/i40e_type.h
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.h
drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/smsc/epic100.c
drivers/net/phy/ax88796b.c
drivers/net/phy/dp83822.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/sfp.c
drivers/net/tun.c
drivers/net/usb/asix.h
drivers/net/usb/asix_common.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/catc.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/net/xen-netfront.c
drivers/nfc/nfcmrvl/i2c.c
drivers/nfc/nfcmrvl/spi.c
drivers/nfc/nxp-nci/i2c.c
drivers/nvdimm/bus.c
drivers/nvme/host/core.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/host/tcp.c
drivers/nvme/host/trace.h
drivers/nvme/target/configfs.c
drivers/nvme/target/core.c
drivers/nvme/target/nvmet.h
drivers/nvme/target/passthru.c
drivers/nvme/target/tcp.c
drivers/pinctrl/aspeed/pinctrl-aspeed.c
drivers/pinctrl/freescale/pinctrl-imx93.c
drivers/pinctrl/stm32/pinctrl-stm32.c
drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
drivers/pinctrl/sunxi/pinctrl-sunxi.c
drivers/platform/mellanox/nvsw-sn2201.c
drivers/platform/x86/Kconfig
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel/pmc/core.c
drivers/platform/x86/panasonic-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/s390/char/sclp.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
drivers/soc/atmel/soc.c
drivers/soc/ixp4xx/ixp4xx-npe.c
drivers/soc/qcom/smem.c
drivers/staging/wlan-ng/hfa384x_usb.c
drivers/thermal/intel/intel_tcc_cooling.c
drivers/vdpa/mlx5/net/mlx5_vnet.c
drivers/vdpa/vdpa_user/vduse_dev.c
drivers/vhost/vdpa.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbmem.c
drivers/virtio/Kconfig
drivers/virtio/virtio.c
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci_modern_dev.c
drivers/virtio/virtio_ring.c
fs/cachefiles/ondemand.c
fs/ceph/caps.c
fs/fscache/cookie.c
fs/fscache/volume.c
fs/io_uring.c
fs/ksmbd/smb2pdu.c
fs/ksmbd/transport_rdma.c
fs/ksmbd/transport_tcp.c
fs/ksmbd/vfs.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfsd/vfs.c
fs/notify/fanotify/fanotify_user.c
fs/read_write.c
fs/xfs/libxfs/xfs_attr.c
fs/xfs/libxfs/xfs_attr.h
fs/xfs/libxfs/xfs_attr_leaf.c
fs/xfs/libxfs/xfs_attr_leaf.h
fs/xfs/xfs_attr_item.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_icache.h
fs/xfs/xfs_inode.c
fs/xfs/xfs_log.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_qm_syscalls.c
fs/xfs/xfs_super.c
fs/xfs/xfs_trace.h
include/acpi/cppc_acpi.h
include/linux/acpi.h
include/linux/compiler_types.h
include/linux/devfreq.h
include/linux/dim.h
include/linux/fanotify.h
include/linux/fbcon.h
include/linux/fscache.h
include/linux/intel-iommu.h
include/linux/lockref.h
include/linux/memregion.h
include/linux/netdevice.h
include/linux/nvme.h
include/linux/phy.h
include/linux/pm_runtime.h
include/linux/refcount.h
include/linux/rtsx_usb.h
include/linux/virtio_config.h
include/net/flow_offload.h
include/net/netfilter/nf_tables.h
include/sound/soc.h
include/uapi/linux/io_uring.h
include/uapi/linux/mptcp.h
include/video/of_display_timing.h
kernel/bpf/verifier.c
kernel/ptrace.c
kernel/signal.c
kernel/time/tick-sched.c
lib/idr.c
lib/lockref.c
lib/sbitmap.c
net/bluetooth/hci_core.c
net/bluetooth/hci_sync.c
net/bridge/br_netfilter_hooks.c
net/can/bcm.c
net/ipv4/ip_tunnel_core.c
net/ipv4/tcp_ipv4.c
net/ipv6/addrconf.c
net/ipv6/route.c
net/ipv6/seg6_hmac.c
net/ipv6/sit.c
net/mptcp/options.c
net/mptcp/pm.c
net/mptcp/pm_netlink.c
net/mptcp/pm_userspace.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/ncsi/ncsi-manage.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_core.c
net/netfilter/nf_tables_trace.c
net/netfilter/nft_set_hash.c
net/netfilter/nft_set_pipapo.c
net/rose/rose_route.c
net/rose/rose_timer.c
net/sched/act_api.c
net/sched/act_police.c
net/socket.c
net/sunrpc/xdr.c
net/tipc/node.c
net/tipc/socket.c
net/tls/tls_sw.c
net/xdp/xsk_buff_pool.c
samples/fprobe/fprobe_example.c
scripts/Makefile.modinst
scripts/clang-tools/gen_compile_commands.py
sound/pci/cs46xx/cs46xx.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/ak4613.c
sound/soc/codecs/cs35l41-lib.c
sound/soc/codecs/cs35l41.c
sound/soc/codecs/cs47l15.c
sound/soc/codecs/madera.c
sound/soc/codecs/max98373-sdw.c
sound/soc/codecs/rt1308-sdw.c
sound/soc/codecs/rt1316-sdw.c
sound/soc/codecs/rt5682-sdw.c
sound/soc/codecs/rt700-sdw.c
sound/soc/codecs/rt700.c
sound/soc/codecs/rt711-sdca-sdw.c
sound/soc/codecs/rt711-sdca.c
sound/soc/codecs/rt711-sdw.c
sound/soc/codecs/rt711.c
sound/soc/codecs/rt715-sdca-sdw.c
sound/soc/codecs/rt715-sdw.c
sound/soc/codecs/wcd9335.c
sound/soc/codecs/wcd938x.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm_adsp.c
sound/soc/intel/avs/topology.c
sound/soc/intel/boards/bytcr_wm5102.c
sound/soc/intel/boards/sof_sdw.c
sound/soc/qcom/qdsp6/q6apm-dai.c
sound/soc/rockchip/rockchip_i2s.c
sound/soc/soc-dapm.c
sound/soc/soc-ops.c
sound/soc/sof/intel/hda-dsp.c
sound/soc/sof/intel/hda-loader.c
sound/soc/sof/intel/hda-pcm.c
sound/soc/sof/intel/hda-stream.c
sound/soc/sof/intel/hda.h
sound/soc/sof/ipc3-topology.c
sound/soc/sof/mediatek/mt8186/mt8186.c
sound/soc/sof/pm.c
sound/soc/sof/sof-priv.h
sound/usb/quirks-table.h
sound/usb/quirks.c
tools/arch/arm64/include/uapi/asm/kvm.h
tools/include/uapi/linux/kvm.h
tools/objtool/check.c
tools/perf/util/bpf-utils.c
tools/perf/util/bpf_off_cpu.c
tools/perf/util/bpf_skel/off_cpu.bpf.c
tools/perf/util/evsel.c
tools/perf/util/off_cpu.h
tools/perf/util/synthetic-events.c
tools/perf/util/unwind-libunwind-local.c
tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c
tools/testing/selftests/bpf/verifier/jmp32.c
tools/testing/selftests/bpf/verifier/jump.c
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/bpf/Makefile
tools/testing/selftests/net/forwarding/lib.sh
tools/testing/selftests/net/mptcp/diag.sh
tools/testing/selftests/net/mptcp/mptcp_connect.c
tools/testing/selftests/net/mptcp/mptcp_inq.c
tools/testing/selftests/net/mptcp/mptcp_sockopt.c
tools/testing/selftests/net/mptcp/pm_nl_ctl.c
tools/testing/selftests/net/mptcp/userspace_pm.sh
tools/testing/selftests/net/tun.c [new file with mode: 0644]
tools/testing/selftests/net/udpgro.sh
tools/testing/selftests/net/udpgro_bench.sh
tools/testing/selftests/net/udpgro_frglist.sh
tools/testing/selftests/net/udpgro_fwd.sh
tools/testing/selftests/net/udpgso_bench.sh
tools/testing/selftests/net/veth.sh
tools/testing/selftests/tc-testing/tc-tests/actions/gact.json
tools/testing/selftests/wireguard/qemu/Makefile
tools/testing/selftests/wireguard/qemu/arch/arm.config
tools/testing/selftests/wireguard/qemu/arch/armeb.config
tools/testing/selftests/wireguard/qemu/arch/i686.config
tools/testing/selftests/wireguard/qemu/arch/m68k.config
tools/testing/selftests/wireguard/qemu/arch/mips.config
tools/testing/selftests/wireguard/qemu/arch/mipsel.config
tools/testing/selftests/wireguard/qemu/arch/powerpc.config
tools/testing/selftests/wireguard/qemu/arch/x86_64.config
tools/testing/selftests/wireguard/qemu/init.c

index 2ed1cf8..13e4f50 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -64,6 +64,9 @@ Bart Van Assche <bvanassche@acm.org> <bart.vanassche@sandisk.com>
 Bart Van Assche <bvanassche@acm.org> <bart.vanassche@wdc.com>
 Ben Gardner <bgardner@wabtec.com>
 Ben M Cahill <ben.m.cahill@intel.com>
+Ben Widawsky <bwidawsk@kernel.org> <ben@bwidawsk.net>
+Ben Widawsky <bwidawsk@kernel.org> <ben.widawsky@intel.com>
+Ben Widawsky <bwidawsk@kernel.org> <benjamin.widawsky@intel.com>
 Björn Steinbrink <B.Steinbrink@gmx.de>
 Björn Töpel <bjorn@kernel.org> <bjorn.topel@gmail.com>
 Björn Töpel <bjorn@kernel.org> <bjorn.topel@intel.com>
index ff0a5c5..e712444 100644 (file)
@@ -67,7 +67,7 @@ if:
 then:
   properties:
     clocks:
-      maxItems: 2
+      minItems: 2
 
   required:
     - clock-names
index c456b52..d140070 100644 (file)
@@ -6,6 +6,15 @@
 netdev FAQ
 ==========
 
+tl;dr
+-----
+
+ - designate your patch to a tree - ``[PATCH net]`` or ``[PATCH net-next]``
+ - for fixes the ``Fixes:`` tag is required, regardless of the tree
+ - don't post large series (> 15 patches), break them up
+ - don't repost your patches within one 24h period
+ - reverse xmas tree
+
 What is netdev?
 ---------------
 It is a mailing list for all network-related Linux stuff.  This
@@ -136,6 +145,20 @@ it to the maintainer to figure out what is the most recent and current
 version that should be applied. If there is any doubt, the maintainer
 will reply and ask what should be done.
 
+How do I divide my work into patches?
+-------------------------------------
+
+Put yourself in the shoes of the reviewer. Each patch is read separately
+and therefore should constitute a comprehensible step towards your stated
+goal.
+
+Avoid sending series longer than 15 patches. Larger series takes longer
+to review as reviewers will defer looking at it until they find a large
+chunk of time. A small series can be reviewed in a short time, so Maintainers
+just do it. As a result, a sequence of smaller series gets merged quicker and
+with better review coverage. Re-posting large series also increases the mailing
+list traffic.
+
 I made changes to only a few patches in a patch series should I resend only those changed?
 ------------------------------------------------------------------------------------------
 No, please resend the entire patch series and make sure you do number your
@@ -183,6 +206,19 @@ it is requested that you make it look like this::
    * another line of text
    */
 
+What is "reverse xmas tree"?
+----------------------------
+
+Netdev has a convention for ordering local variables in functions.
+Order the variable declaration lines longest to shortest, e.g.::
+
+  struct scatterlist *sg;
+  struct sk_buff *skb;
+  int err, i;
+
+If there are dependencies between the variables preventing the ordering
+move the initialization out of line.
+
 I am working in existing code which uses non-standard formatting. Which formatting should I use?
 ------------------------------------------------------------------------------------------------
 Make your code follow the most recent guidelines, so that eventually all code
index fe5daf1..f679152 100644 (file)
@@ -426,7 +426,6 @@ F:  drivers/acpi/*thermal*
 ACPI VIOT DRIVER
 M:     Jean-Philippe Brucker <jean-philippe@linaro.org>
 L:     linux-acpi@vger.kernel.org
-L:     iommu@lists.linux-foundation.org
 L:     iommu@lists.linux.dev
 S:     Maintained
 F:     drivers/acpi/viot.c
@@ -960,7 +959,6 @@ F:  drivers/video/fbdev/geode/
 AMD IOMMU (AMD-VI)
 M:     Joerg Roedel <joro@8bytes.org>
 R:     Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
-L:     iommu@lists.linux-foundation.org
 L:     iommu@lists.linux.dev
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
@@ -2540,6 +2538,7 @@ W:        http://www.armlinux.org.uk/
 ARM/QUALCOMM SUPPORT
 M:     Andy Gross <agross@kernel.org>
 M:     Bjorn Andersson <bjorn.andersson@linaro.org>
+R:     Konrad Dybcio <konrad.dybcio@somainline.org>
 L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
@@ -3617,16 +3616,18 @@ S:      Maintained
 F:     Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml
 F:     drivers/iio/accel/bma400*
 
-BPF (Safe dynamic programs and tools)
+BPF [GENERAL] (Safe Dynamic Programs and Tools)
 M:     Alexei Starovoitov <ast@kernel.org>
 M:     Daniel Borkmann <daniel@iogearbox.net>
 M:     Andrii Nakryiko <andrii@kernel.org>
-R:     Martin KaFai Lau <kafai@fb.com>
-R:     Song Liu <songliubraving@fb.com>
+R:     Martin KaFai Lau <martin.lau@linux.dev>
+R:     Song Liu <song@kernel.org>
 R:     Yonghong Song <yhs@fb.com>
 R:     John Fastabend <john.fastabend@gmail.com>
 R:     KP Singh <kpsingh@kernel.org>
-L:     netdev@vger.kernel.org
+R:     Stanislav Fomichev <sdf@google.com>
+R:     Hao Luo <haoluo@google.com>
+R:     Jiri Olsa <jolsa@kernel.org>
 L:     bpf@vger.kernel.org
 S:     Supported
 W:     https://bpf.io/
@@ -3658,12 +3659,9 @@ F:       scripts/pahole-version.sh
 F:     tools/bpf/
 F:     tools/lib/bpf/
 F:     tools/testing/selftests/bpf/
-N:     bpf
-K:     bpf
 
 BPF JIT for ARM
 M:     Shubham Bansal <illusionist.neo@gmail.com>
-L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Odd Fixes
 F:     arch/arm/net/
@@ -3672,7 +3670,6 @@ BPF JIT for ARM64
 M:     Daniel Borkmann <daniel@iogearbox.net>
 M:     Alexei Starovoitov <ast@kernel.org>
 M:     Zi Shen Lim <zlim.lnx@gmail.com>
-L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Supported
 F:     arch/arm64/net/
@@ -3680,14 +3677,12 @@ F:      arch/arm64/net/
 BPF JIT for MIPS (32-BIT AND 64-BIT)
 M:     Johan Almbladh <johan.almbladh@anyfinetworks.com>
 M:     Paul Burton <paulburton@kernel.org>
-L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/mips/net/
 
 BPF JIT for NFP NICs
 M:     Jakub Kicinski <kuba@kernel.org>
-L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Odd Fixes
 F:     drivers/net/ethernet/netronome/nfp/bpf/
@@ -3695,7 +3690,6 @@ F:        drivers/net/ethernet/netronome/nfp/bpf/
 BPF JIT for POWERPC (32-BIT AND 64-BIT)
 M:     Naveen N. Rao <naveen.n.rao@linux.ibm.com>
 M:     Michael Ellerman <mpe@ellerman.id.au>
-L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Supported
 F:     arch/powerpc/net/
@@ -3703,7 +3697,6 @@ F:        arch/powerpc/net/
 BPF JIT for RISC-V (32-bit)
 M:     Luke Nelson <luke.r.nels@gmail.com>
 M:     Xi Wang <xi.wang@gmail.com>
-L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/riscv/net/
@@ -3711,7 +3704,6 @@ X:        arch/riscv/net/bpf_jit_comp64.c
 
 BPF JIT for RISC-V (64-bit)
 M:     Björn Töpel <bjorn@kernel.org>
-L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/riscv/net/
@@ -3721,7 +3713,6 @@ BPF JIT for S390
 M:     Ilya Leoshkevich <iii@linux.ibm.com>
 M:     Heiko Carstens <hca@linux.ibm.com>
 M:     Vasily Gorbik <gor@linux.ibm.com>
-L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Supported
 F:     arch/s390/net/
@@ -3729,14 +3720,12 @@ X:      arch/s390/net/pnet.c
 
 BPF JIT for SPARC (32-BIT AND 64-BIT)
 M:     David S. Miller <davem@davemloft.net>
-L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Odd Fixes
 F:     arch/sparc/net/
 
 BPF JIT for X86 32-BIT
 M:     Wang YanQing <udknight@gmail.com>
-L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Odd Fixes
 F:     arch/x86/net/bpf_jit_comp32.c
@@ -3744,13 +3733,60 @@ F:      arch/x86/net/bpf_jit_comp32.c
 BPF JIT for X86 64-BIT
 M:     Alexei Starovoitov <ast@kernel.org>
 M:     Daniel Borkmann <daniel@iogearbox.net>
-L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Supported
 F:     arch/x86/net/
 X:     arch/x86/net/bpf_jit_comp32.c
 
-BPF LSM (Security Audit and Enforcement using BPF)
+BPF [CORE]
+M:     Alexei Starovoitov <ast@kernel.org>
+M:     Daniel Borkmann <daniel@iogearbox.net>
+R:     John Fastabend <john.fastabend@gmail.com>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     kernel/bpf/verifier.c
+F:     kernel/bpf/tnum.c
+F:     kernel/bpf/core.c
+F:     kernel/bpf/syscall.c
+F:     kernel/bpf/dispatcher.c
+F:     kernel/bpf/trampoline.c
+F:     include/linux/bpf*
+F:     include/linux/filter.h
+
+BPF [BTF]
+M:     Martin KaFai Lau <martin.lau@linux.dev>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     kernel/bpf/btf.c
+F:     include/linux/btf*
+
+BPF [TRACING]
+M:     Song Liu <song@kernel.org>
+R:     Jiri Olsa <jolsa@kernel.org>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     kernel/trace/bpf_trace.c
+F:     kernel/bpf/stackmap.c
+
+BPF [NETWORKING] (tc BPF, sock_addr)
+M:     Martin KaFai Lau <martin.lau@linux.dev>
+M:     Daniel Borkmann <daniel@iogearbox.net>
+R:     John Fastabend <john.fastabend@gmail.com>
+L:     bpf@vger.kernel.org
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     net/core/filter.c
+F:     net/sched/act_bpf.c
+F:     net/sched/cls_bpf.c
+
+BPF [NETWORKING] (struct_ops, reuseport)
+M:     Martin KaFai Lau <martin.lau@linux.dev>
+L:     bpf@vger.kernel.org
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     kernel/bpf/bpf_struct*
+
+BPF [SECURITY & LSM] (Security Audit and Enforcement using BPF)
 M:     KP Singh <kpsingh@kernel.org>
 R:     Florent Revest <revest@chromium.org>
 R:     Brendan Jackman <jackmanb@chromium.org>
@@ -3761,7 +3797,27 @@ F:       include/linux/bpf_lsm.h
 F:     kernel/bpf/bpf_lsm.c
 F:     security/bpf/
 
-BPF L7 FRAMEWORK
+BPF [STORAGE & CGROUPS]
+M:     Martin KaFai Lau <martin.lau@linux.dev>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     kernel/bpf/cgroup.c
+F:     kernel/bpf/*storage.c
+F:     kernel/bpf/bpf_lru*
+
+BPF [RINGBUF]
+M:     Andrii Nakryiko <andrii@kernel.org>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     kernel/bpf/ringbuf.c
+
+BPF [ITERATOR]
+M:     Yonghong Song <yhs@fb.com>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     kernel/bpf/*iter.c
+
+BPF [L7 FRAMEWORK] (sockmap)
 M:     John Fastabend <john.fastabend@gmail.com>
 M:     Jakub Sitnicki <jakub@cloudflare.com>
 L:     netdev@vger.kernel.org
@@ -3774,13 +3830,31 @@ F:      net/ipv4/tcp_bpf.c
 F:     net/ipv4/udp_bpf.c
 F:     net/unix/unix_bpf.c
 
-BPFTOOL
+BPF [LIBRARY] (libbpf)
+M:     Andrii Nakryiko <andrii@kernel.org>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     tools/lib/bpf/
+
+BPF [TOOLING] (bpftool)
 M:     Quentin Monnet <quentin@isovalent.com>
 L:     bpf@vger.kernel.org
 S:     Maintained
 F:     kernel/bpf/disasm.*
 F:     tools/bpf/bpftool/
 
+BPF [SELFTESTS] (Test Runners & Infrastructure)
+M:     Andrii Nakryiko <andrii@kernel.org>
+R:     Mykola Lysenko <mykolal@fb.com>
+L:     bpf@vger.kernel.org
+S:     Maintained
+F:     tools/testing/selftests/bpf/
+
+BPF [MISC]
+L:     bpf@vger.kernel.org
+S:     Odd Fixes
+K:     (?:\b|_)bpf(?:\b|_)
+
 BROADCOM B44 10/100 ETHERNET DRIVER
 M:     Michael Chan <michael.chan@broadcom.com>
 L:     netdev@vger.kernel.org
@@ -4976,6 +5050,7 @@ Q:        http://patchwork.kernel.org/project/linux-clk/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
 F:     Documentation/devicetree/bindings/clock/
 F:     drivers/clk/
+F:     include/dt-bindings/clock/
 F:     include/linux/clk-pr*
 F:     include/linux/clk/
 F:     include/linux/of_clk.h
@@ -5026,7 +5101,7 @@ COMPUTE EXPRESS LINK (CXL)
 M:     Alison Schofield <alison.schofield@intel.com>
 M:     Vishal Verma <vishal.l.verma@intel.com>
 M:     Ira Weiny <ira.weiny@intel.com>
-M:     Ben Widawsky <ben.widawsky@intel.com>
+M:     Ben Widawsky <bwidawsk@kernel.org>
 M:     Dan Williams <dan.j.williams@intel.com>
 L:     linux-cxl@vger.kernel.org
 S:     Maintained
@@ -5978,7 +6053,6 @@ DMA MAPPING HELPERS
 M:     Christoph Hellwig <hch@lst.de>
 M:     Marek Szyprowski <m.szyprowski@samsung.com>
 R:     Robin Murphy <robin.murphy@arm.com>
-L:     iommu@lists.linux-foundation.org
 L:     iommu@lists.linux.dev
 S:     Supported
 W:     http://git.infradead.org/users/hch/dma-mapping.git
@@ -5991,7 +6065,6 @@ F:        kernel/dma/
 
 DMA MAPPING BENCHMARK
 M:     Xiang Chen <chenxiang66@hisilicon.com>
-L:     iommu@lists.linux-foundation.org
 L:     iommu@lists.linux.dev
 F:     kernel/dma/map_benchmark.c
 F:     tools/testing/selftests/dma/
@@ -7576,7 +7649,6 @@ F:        drivers/gpu/drm/exynos/exynos_dp*
 
 EXYNOS SYSMMU (IOMMU) driver
 M:     Marek Szyprowski <m.szyprowski@samsung.com>
-L:     iommu@lists.linux-foundation.org
 L:     iommu@lists.linux.dev
 S:     Maintained
 F:     drivers/iommu/exynos-iommu.c
@@ -9835,7 +9907,10 @@ INTEL ASoC DRIVERS
 M:     Cezary Rojewski <cezary.rojewski@intel.com>
 M:     Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
 M:     Liam Girdwood <liam.r.girdwood@linux.intel.com>
-M:     Jie Yang <yang.jie@linux.intel.com>
+M:     Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
+M:     Bard Liao <yung-chuan.liao@linux.intel.com>
+M:     Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+M:     Kai Vehmanen <kai.vehmanen@linux.intel.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
 F:     sound/soc/intel/
@@ -9998,7 +10073,6 @@ F:       drivers/hid/intel-ish-hid/
 INTEL IOMMU (VT-d)
 M:     David Woodhouse <dwmw2@infradead.org>
 M:     Lu Baolu <baolu.lu@linux.intel.com>
-L:     iommu@lists.linux-foundation.org
 L:     iommu@lists.linux.dev
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
@@ -10378,7 +10452,6 @@ F:      include/linux/iomap.h
 IOMMU DRIVERS
 M:     Joerg Roedel <joro@8bytes.org>
 M:     Will Deacon <will@kernel.org>
-L:     iommu@lists.linux-foundation.org
 L:     iommu@lists.linux.dev
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
@@ -12538,7 +12611,6 @@ F:      drivers/i2c/busses/i2c-mt65xx.c
 
 MEDIATEK IOMMU DRIVER
 M:     Yong Wu <yong.wu@mediatek.com>
-L:     iommu@lists.linux-foundation.org
 L:     iommu@lists.linux.dev
 L:     linux-mediatek@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
@@ -14397,9 +14469,8 @@ F:      Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
 F:     sound/soc/codecs/tfa989x.c
 
 NXP-NCI NFC DRIVER
-R:     Charles Gorand <charles.gorand@effinnov.com>
 L:     linux-nfc@lists.01.org (subscribers-only)
-S:     Supported
+S:     Orphan
 F:     Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml
 F:     drivers/nfc/nxp-nci
 
@@ -15788,7 +15859,7 @@ F:      drivers/pinctrl/freescale/
 PIN CONTROLLER - INTEL
 M:     Mika Westerberg <mika.westerberg@linux.intel.com>
 M:     Andy Shevchenko <andy@kernel.org>
-S:     Maintained
+S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/intel.git
 F:     drivers/pinctrl/intel/
 
@@ -16310,7 +16381,7 @@ F:      drivers/crypto/qat/
 
 QCOM AUDIO (ASoC) DRIVERS
 M:     Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-M:     Banajit Goswami <bgoswami@codeaurora.org>
+M:     Banajit Goswami <bgoswami@quicinc.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
 F:     sound/soc/codecs/lpass-va-macro.c
@@ -16591,7 +16662,6 @@ F:      drivers/i2c/busses/i2c-qcom-cci.c
 
 QUALCOMM IOMMU
 M:     Rob Clark <robdclark@gmail.com>
-L:     iommu@lists.linux-foundation.org
 L:     iommu@lists.linux.dev
 L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
@@ -18105,6 +18175,7 @@ F:      drivers/misc/sgi-xp/
 
 SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS
 M:     Karsten Graul <kgraul@linux.ibm.com>
+M:     Wenjia Zhang <wenjia@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
 S:     Supported
 W:     http://www.ibm.com/developerworks/linux/linux390/
@@ -18737,8 +18808,10 @@ F:     sound/soc/
 SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS
 M:     Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
 M:     Liam Girdwood <lgirdwood@gmail.com>
+M:     Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
+M:     Bard Liao <yung-chuan.liao@linux.intel.com>
 M:     Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
-M:     Kai Vehmanen <kai.vehmanen@linux.intel.com>
+R:     Kai Vehmanen <kai.vehmanen@linux.intel.com>
 M:     Daniel Baluta <daniel.baluta@nxp.com>
 L:     sound-open-firmware@alsa-project.org (moderated for non-subscribers)
 S:     Supported
@@ -19217,7 +19290,6 @@ F:      arch/x86/boot/video*
 
 SWIOTLB SUBSYSTEM
 M:     Christoph Hellwig <hch@infradead.org>
-L:     iommu@lists.linux-foundation.org
 L:     iommu@lists.linux.dev
 S:     Supported
 W:     http://git.infradead.org/users/hch/dma-mapping.git
@@ -21893,7 +21965,6 @@ XEN SWIOTLB SUBSYSTEM
 M:     Juergen Gross <jgross@suse.com>
 M:     Stefano Stabellini <sstabellini@kernel.org>
 L:     xen-devel@lists.xenproject.org (moderated for non-subscribers)
-L:     iommu@lists.linux-foundation.org
 L:     iommu@lists.linux.dev
 S:     Supported
 F:     arch/x86/xen/*swiotlb*
index 8973b28..faa4880 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 19
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc6
 NAME = Superb Owl
 
 # *DOCUMENTATION*
index 7719ea3..81ccb06 100644 (file)
                status = "okay";
 
                eeprom@53 {
-                       compatible = "atmel,24c32";
+                       compatible = "atmel,24c02";
                        reg = <0x53>;
                        pagesize = <16>;
-                       size = <128>;
                        status = "okay";
                };
        };
index 806eb1d..164201a 100644 (file)
        status = "okay";
 
        eeprom@50 {
-               compatible = "atmel,24c32";
+               compatible = "atmel,24c02";
                reg = <0x50>;
                pagesize = <16>;
                status = "okay";
        };
 
        eeprom@52 {
-               compatible = "atmel,24c32";
+               compatible = "atmel,24c02";
                reg = <0x52>;
                pagesize = <16>;
                status = "disabled";
        };
 
        eeprom@53 {
-               compatible = "atmel,24c32";
+               compatible = "atmel,24c02";
                reg = <0x53>;
                pagesize = <16>;
                status = "disabled";
index c6b3206..21b509c 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usdhc2>;
        bus-width = <4>;
+       no-1-8-v;
        non-removable;
-       cap-sd-highspeed;
-       sd-uhs-ddr50;
-       mmc-ddr-1_8v;
        vmmc-supply = <&reg_wifi>;
        enable-sdio-wakeup;
        status = "okay";
index e90cf3a..543f24c 100644 (file)
                                reg = <0x16>;
                                #reset-cells = <1>;
                        };
+
+                       scmi_voltd: protocol@17 {
+                               reg = <0x17>;
+
+                               scmi_reguls: regulators {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       scmi_reg11: reg11@0 {
+                                               reg = <0>;
+                                               regulator-name = "reg11";
+                                               regulator-min-microvolt = <1100000>;
+                                               regulator-max-microvolt = <1100000>;
+                                       };
+
+                                       scmi_reg18: reg18@1 {
+                                               voltd-name = "reg18";
+                                               reg = <1>;
+                                               regulator-name = "reg18";
+                                               regulator-min-microvolt = <1800000>;
+                                               regulator-max-microvolt = <1800000>;
+                                       };
+
+                                       scmi_usb33: usb33@2 {
+                                               reg = <2>;
+                                               regulator-name = "usb33";
+                                               regulator-min-microvolt = <3300000>;
+                                               regulator-max-microvolt = <3300000>;
+                                       };
+                               };
+                       };
                };
        };
 
                };
        };
 };
+
+&reg11 {
+       status = "disabled";
+};
+
+&reg18 {
+       status = "disabled";
+};
+
+&usb33 {
+       status = "disabled";
+};
+
+&usbotg_hs {
+       usb33d-supply = <&scmi_usb33>;
+};
+
+&usbphyc {
+       vdda1v1-supply = <&scmi_reg11>;
+       vdda1v8-supply = <&scmi_reg18>;
+};
+
+/delete-node/ &clk_hse;
+/delete-node/ &clk_hsi;
+/delete-node/ &clk_lse;
+/delete-node/ &clk_lsi;
+/delete-node/ &clk_csi;
index 7fdc324..e04dda5 100644 (file)
                        compatible = "st,stm32-cec";
                        reg = <0x40016000 0x400>;
                        interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&rcc CEC_K>, <&clk_lse>;
+                       clocks = <&rcc CEC_K>, <&rcc CEC>;
                        clock-names = "cec", "hdmi-cec";
                        status = "disabled";
                };
                usbh_ohci: usb@5800c000 {
                        compatible = "generic-ohci";
                        reg = <0x5800c000 0x1000>;
-                       clocks = <&rcc USBH>, <&usbphyc>;
+                       clocks = <&usbphyc>, <&rcc USBH>;
                        resets = <&rcc USBH_R>;
                        interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
                        status = "disabled";
                usbh_ehci: usb@5800d000 {
                        compatible = "generic-ehci";
                        reg = <0x5800d000 0x1000>;
-                       clocks = <&rcc USBH>;
+                       clocks = <&usbphyc>, <&rcc USBH>;
                        resets = <&rcc USBH_R>;
                        interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
                        companion = <&usbh_ohci>;
index 36371d6..e539cc8 100644 (file)
        clocks = <&scmi_clk CK_SCMI_MPU>;
 };
 
+&dsi {
+       clocks = <&rcc DSI_K>, <&scmi_clk CK_SCMI_HSE>, <&rcc DSI_PX>;
+};
+
 &gpioz {
        clocks = <&scmi_clk CK_SCMI_GPIOZ>;
 };
index 03226a5..97e4f94 100644 (file)
@@ -35,6 +35,7 @@
 };
 
 &dsi {
+       phy-dsi-supply = <&scmi_reg18>;
        clocks = <&rcc DSI_K>, <&scmi_clk CK_SCMI_HSE>, <&rcc DSI_PX>;
 };
 
index c1a7927..9cf0a44 100644 (file)
        resets = <&scmi_reset RST_SCMI_CRYP1>;
 };
 
+&dsi {
+       clocks = <&rcc DSI_K>, <&scmi_clk CK_SCMI_HSE>, <&rcc DSI_PX>;
+};
+
 &gpioz {
        clocks = <&scmi_clk CK_SCMI_GPIOZ>;
 };
index 7842384..3b9dd6f 100644 (file)
@@ -36,6 +36,7 @@
 };
 
 &dsi {
+       phy-dsi-supply = <&scmi_reg18>;
        clocks = <&rcc DSI_K>, <&scmi_clk CK_SCMI_HSE>, <&rcc DSI_PX>;
 };
 
index ca32446..f53086d 100644 (file)
@@ -93,6 +93,7 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_DRM=y
 CONFIG_DRM_PANEL_SEIKO_43WVF1G=y
 CONFIG_DRM_MXSFB=y
+CONFIG_FB=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
index b1a43d7..df6d673 100644 (file)
@@ -202,7 +202,7 @@ static const struct wakeup_source_info ws_info[] = {
 
 static const struct of_device_id sama5d2_ws_ids[] = {
        { .compatible = "atmel,sama5d2-gem",            .data = &ws_info[0] },
-       { .compatible = "atmel,at91rm9200-rtc",         .data = &ws_info[1] },
+       { .compatible = "atmel,sama5d2-rtc",            .data = &ws_info[1] },
        { .compatible = "atmel,sama5d3-udc",            .data = &ws_info[2] },
        { .compatible = "atmel,at91rm9200-ohci",        .data = &ws_info[2] },
        { .compatible = "usb-ohci",                     .data = &ws_info[2] },
@@ -213,24 +213,24 @@ static const struct of_device_id sama5d2_ws_ids[] = {
 };
 
 static const struct of_device_id sam9x60_ws_ids[] = {
-       { .compatible = "atmel,at91sam9x5-rtc",         .data = &ws_info[1] },
+       { .compatible = "microchip,sam9x60-rtc",        .data = &ws_info[1] },
        { .compatible = "atmel,at91rm9200-ohci",        .data = &ws_info[2] },
        { .compatible = "usb-ohci",                     .data = &ws_info[2] },
        { .compatible = "atmel,at91sam9g45-ehci",       .data = &ws_info[2] },
        { .compatible = "usb-ehci",                     .data = &ws_info[2] },
-       { .compatible = "atmel,at91sam9260-rtt",        .data = &ws_info[4] },
+       { .compatible = "microchip,sam9x60-rtt",        .data = &ws_info[4] },
        { .compatible = "cdns,sam9x60-macb",            .data = &ws_info[5] },
        { /* sentinel */ }
 };
 
 static const struct of_device_id sama7g5_ws_ids[] = {
-       { .compatible = "atmel,at91sam9x5-rtc",         .data = &ws_info[1] },
+       { .compatible = "microchip,sama7g5-rtc",        .data = &ws_info[1] },
        { .compatible = "microchip,sama7g5-ohci",       .data = &ws_info[2] },
        { .compatible = "usb-ohci",                     .data = &ws_info[2] },
        { .compatible = "atmel,at91sam9g45-ehci",       .data = &ws_info[2] },
        { .compatible = "usb-ehci",                     .data = &ws_info[2] },
        { .compatible = "microchip,sama7g5-sdhci",      .data = &ws_info[3] },
-       { .compatible = "atmel,at91sam9260-rtt",        .data = &ws_info[4] },
+       { .compatible = "microchip,sama7g5-rtt",        .data = &ws_info[4] },
        { /* sentinel */ }
 };
 
@@ -1079,7 +1079,7 @@ securam_fail:
        return ret;
 }
 
-static void at91_pm_secure_init(void)
+static void __init at91_pm_secure_init(void)
 {
        int suspend_mode;
        struct arm_smccc_res res;
index 4b8ad72..32ac60b 100644 (file)
@@ -71,6 +71,7 @@ static void __init meson_smp_prepare_cpus(const char *scu_compatible,
        }
 
        sram_base = of_iomap(node, 0);
+       of_node_put(node);
        if (!sram_base) {
                pr_err("Couldn't map SRAM registers\n");
                return;
@@ -91,6 +92,7 @@ static void __init meson_smp_prepare_cpus(const char *scu_compatible,
        }
 
        scu_base = of_iomap(node, 0);
+       of_node_put(node);
        if (!scu_base) {
                pr_err("Couldn't map SCU registers\n");
                return;
index 84a1cea..309648c 100644 (file)
@@ -63,11 +63,12 @@ out:
 
 unsigned long __pfn_to_mfn(unsigned long pfn)
 {
-       struct rb_node *n = phys_to_mach.rb_node;
+       struct rb_node *n;
        struct xen_p2m_entry *entry;
        unsigned long irqflags;
 
        read_lock_irqsave(&p2m_lock, irqflags);
+       n = phys_to_mach.rb_node;
        while (n) {
                entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
                if (entry->pfn <= pfn &&
@@ -152,10 +153,11 @@ bool __set_phys_to_machine_multi(unsigned long pfn,
        int rc;
        unsigned long irqflags;
        struct xen_p2m_entry *p2m_entry;
-       struct rb_node *n = phys_to_mach.rb_node;
+       struct rb_node *n;
 
        if (mfn == INVALID_P2M_ENTRY) {
                write_lock_irqsave(&p2m_lock, irqflags);
+               n = phys_to_mach.rb_node;
                while (n) {
                        p2m_entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
                        if (p2m_entry->pfn <= pfn &&
index 4c3ac42..9a4de73 100644 (file)
 &iomuxc {
        pinctrl_eqos: eqosgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC                             0x3
-                       MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO                           0x3
-                       MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0                       0x91
-                       MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1                       0x91
-                       MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2                       0x91
-                       MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3                       0x91
-                       MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK       0x91
-                       MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL                 0x91
-                       MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0                       0x1f
-                       MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1                       0x1f
-                       MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2                       0x1f
-                       MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3                       0x1f
-                       MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL                 0x1f
-                       MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK       0x1f
-                       MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22                               0x19
+                       MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC                             0x2
+                       MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO                           0x2
+                       MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0                       0x90
+                       MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1                       0x90
+                       MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2                       0x90
+                       MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3                       0x90
+                       MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK       0x90
+                       MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL                 0x90
+                       MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0                       0x16
+                       MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1                       0x16
+                       MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2                       0x16
+                       MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3                       0x16
+                       MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL                 0x16
+                       MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK       0x16
+                       MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22                               0x10
                >;
        };
 
        pinctrl_fec: fecgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_SAI1_RXD2__ENET1_MDC               0x3
-                       MX8MP_IOMUXC_SAI1_RXD3__ENET1_MDIO              0x3
-                       MX8MP_IOMUXC_SAI1_RXD4__ENET1_RGMII_RD0         0x91
-                       MX8MP_IOMUXC_SAI1_RXD5__ENET1_RGMII_RD1         0x91
-                       MX8MP_IOMUXC_SAI1_RXD6__ENET1_RGMII_RD2         0x91
-                       MX8MP_IOMUXC_SAI1_RXD7__ENET1_RGMII_RD3         0x91
-                       MX8MP_IOMUXC_SAI1_TXC__ENET1_RGMII_RXC          0x91
-                       MX8MP_IOMUXC_SAI1_TXFS__ENET1_RGMII_RX_CTL      0x91
-                       MX8MP_IOMUXC_SAI1_TXD0__ENET1_RGMII_TD0         0x1f
-                       MX8MP_IOMUXC_SAI1_TXD1__ENET1_RGMII_TD1         0x1f
-                       MX8MP_IOMUXC_SAI1_TXD2__ENET1_RGMII_TD2         0x1f
-                       MX8MP_IOMUXC_SAI1_TXD3__ENET1_RGMII_TD3         0x1f
-                       MX8MP_IOMUXC_SAI1_TXD4__ENET1_RGMII_TX_CTL      0x1f
-                       MX8MP_IOMUXC_SAI1_TXD5__ENET1_RGMII_TXC         0x1f
-                       MX8MP_IOMUXC_SAI1_RXD0__GPIO4_IO02              0x19
+                       MX8MP_IOMUXC_SAI1_RXD2__ENET1_MDC               0x2
+                       MX8MP_IOMUXC_SAI1_RXD3__ENET1_MDIO              0x2
+                       MX8MP_IOMUXC_SAI1_RXD4__ENET1_RGMII_RD0         0x90
+                       MX8MP_IOMUXC_SAI1_RXD5__ENET1_RGMII_RD1         0x90
+                       MX8MP_IOMUXC_SAI1_RXD6__ENET1_RGMII_RD2         0x90
+                       MX8MP_IOMUXC_SAI1_RXD7__ENET1_RGMII_RD3         0x90
+                       MX8MP_IOMUXC_SAI1_TXC__ENET1_RGMII_RXC          0x90
+                       MX8MP_IOMUXC_SAI1_TXFS__ENET1_RGMII_RX_CTL      0x90
+                       MX8MP_IOMUXC_SAI1_TXD0__ENET1_RGMII_TD0         0x16
+                       MX8MP_IOMUXC_SAI1_TXD1__ENET1_RGMII_TD1         0x16
+                       MX8MP_IOMUXC_SAI1_TXD2__ENET1_RGMII_TD2         0x16
+                       MX8MP_IOMUXC_SAI1_TXD3__ENET1_RGMII_TD3         0x16
+                       MX8MP_IOMUXC_SAI1_TXD4__ENET1_RGMII_TX_CTL      0x16
+                       MX8MP_IOMUXC_SAI1_TXD5__ENET1_RGMII_TXC         0x16
+                       MX8MP_IOMUXC_SAI1_RXD0__GPIO4_IO02              0x10
                >;
        };
 
 
        pinctrl_gpio_led: gpioledgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16   0x19
+                       MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16   0x140
                >;
        };
 
        pinctrl_i2c1: i2c1grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL         0x400001c3
-                       MX8MP_IOMUXC_I2C1_SDA__I2C1_SDA         0x400001c3
+                       MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL         0x400001c2
+                       MX8MP_IOMUXC_I2C1_SDA__I2C1_SDA         0x400001c2
                >;
        };
 
        pinctrl_i2c3: i2c3grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL         0x400001c3
-                       MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA         0x400001c3
+                       MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL         0x400001c2
+                       MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA         0x400001c2
                >;
        };
 
        pinctrl_i2c5: i2c5grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_SPDIF_RX__I2C5_SDA         0x400001c3
-                       MX8MP_IOMUXC_SPDIF_TX__I2C5_SCL         0x400001c3
+                       MX8MP_IOMUXC_SPDIF_RX__I2C5_SDA         0x400001c2
+                       MX8MP_IOMUXC_SPDIF_TX__I2C5_SCL         0x400001c2
                >;
        };
 
 
        pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19    0x41
+                       MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19    0x40
                >;
        };
 
        pinctrl_uart2: uart2grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX    0x49
-                       MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX    0x49
+                       MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX    0x140
+                       MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX    0x140
                >;
        };
 
        pinctrl_usb1_vbus: usb1grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_GPIO1_IO14__USB2_OTG_PWR   0x19
+                       MX8MP_IOMUXC_GPIO1_IO14__USB2_OTG_PWR   0x10
                >;
        };
 
                        MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1    0x1d0
                        MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2    0x1d0
                        MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3    0x1d0
-                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1
+                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0
                >;
        };
 
                        MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1    0x1d4
                        MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2    0x1d4
                        MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3    0x1d4
-                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1
+                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0
                >;
        };
 
                        MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1    0x1d6
                        MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2    0x1d6
                        MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3    0x1d6
-                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1
+                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0
                >;
        };
 
index 70a701a..dd703b6 100644 (file)
 &iomuxc {
        pinctrl_eqos: eqosgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC                             0x3
-                       MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO                           0x3
-                       MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0                       0x91
-                       MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1                       0x91
-                       MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2                       0x91
-                       MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3                       0x91
-                       MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK       0x91
-                       MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL                 0x91
-                       MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0                       0x1f
-                       MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1                       0x1f
-                       MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2                       0x1f
-                       MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3                       0x1f
-                       MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL                 0x1f
-                       MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK       0x1f
-                       MX8MP_IOMUXC_NAND_DATA01__GPIO3_IO07                            0x19
+                       MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC                             0x2
+                       MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO                           0x2
+                       MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0                       0x90
+                       MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1                       0x90
+                       MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2                       0x90
+                       MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3                       0x90
+                       MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK       0x90
+                       MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL                 0x90
+                       MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0                       0x16
+                       MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1                       0x16
+                       MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2                       0x16
+                       MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3                       0x16
+                       MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL                 0x16
+                       MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK       0x16
+                       MX8MP_IOMUXC_NAND_DATA01__GPIO3_IO07                            0x10
                >;
        };
 
        pinctrl_uart2: uart2grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX    0x49
-                       MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX    0x49
+                       MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX    0x40
+                       MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX    0x40
                >;
        };
 
                        MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1    0x1d0
                        MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2    0x1d0
                        MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3    0x1d0
-                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1
+                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0
                >;
        };
 
 
        pinctrl_reg_usb1: regusb1grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_GPIO1_IO14__GPIO1_IO14     0x19
+                       MX8MP_IOMUXC_GPIO1_IO14__GPIO1_IO14     0x10
                >;
        };
 
        pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19    0x41
+                       MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19    0x40
                >;
        };
 };
index 984a6b9..6aa720b 100644 (file)
 &iomuxc {
        pinctrl_eqos: eqosgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC                     0x3
-                       MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO                   0x3
-                       MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0               0x91
-                       MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1               0x91
-                       MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2               0x91
-                       MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3               0x91
-                       MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK       0x91
-                       MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL         0x91
-                       MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0               0x1f
-                       MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1               0x1f
-                       MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2               0x1f
-                       MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3               0x1f
-                       MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL         0x1f
-                       MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK       0x1f
+                       MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC                     0x2
+                       MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO                   0x2
+                       MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0               0x90
+                       MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1               0x90
+                       MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2               0x90
+                       MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3               0x90
+                       MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK       0x90
+                       MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL         0x90
+                       MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0               0x16
+                       MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1               0x16
+                       MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2               0x16
+                       MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3               0x16
+                       MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL         0x16
+                       MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK       0x16
                        MX8MP_IOMUXC_SAI1_MCLK__GPIO4_IO20                      0x10
                >;
        };
 
        pinctrl_i2c2: i2c2grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL         0x400001c3
-                       MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA         0x400001c3
+                       MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL         0x400001c2
+                       MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA         0x400001c2
                >;
        };
 
        pinctrl_i2c2_gpio: i2c2gpiogrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_I2C2_SCL__GPIO5_IO16       0x1e3
-                       MX8MP_IOMUXC_I2C2_SDA__GPIO5_IO17       0x1e3
+                       MX8MP_IOMUXC_I2C2_SCL__GPIO5_IO16       0x1e2
+                       MX8MP_IOMUXC_I2C2_SDA__GPIO5_IO17       0x1e2
                >;
        };
 
        pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19    0x41
+                       MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19    0x40
                >;
        };
 
        pinctrl_uart1: uart1grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX    0x49
-                       MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX    0x49
+                       MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX    0x40
+                       MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX    0x40
                >;
        };
 
                        MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1    0x1d0
                        MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2    0x1d0
                        MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3    0x1d0
-                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1
+                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0
                >;
        };
 
                        MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1    0x1d4
                        MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2    0x1d4
                        MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3    0x1d4
-                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1
+                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0
                >;
        };
 
                        MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1    0x1d6
                        MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2    0x1d6
                        MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3    0x1d6
-                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc1
+                       MX8MP_IOMUXC_GPIO1_IO04__USDHC2_VSELECT 0xc0
                >;
        };
 };
index 101d311..5212155 100644 (file)
 
        pinctrl_hog: hoggrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_GPIO1_IO09__GPIO1_IO09     0x40000041 /* DIO0 */
-                       MX8MP_IOMUXC_GPIO1_IO11__GPIO1_IO11     0x40000041 /* DIO1 */
-                       MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14       0x40000041 /* M2SKT_OFF# */
-                       MX8MP_IOMUXC_SD2_DATA2__GPIO2_IO17      0x40000159 /* PCIE1_WDIS# */
-                       MX8MP_IOMUXC_SD2_DATA3__GPIO2_IO18      0x40000159 /* PCIE2_WDIS# */
-                       MX8MP_IOMUXC_SD2_CMD__GPIO2_IO14        0x40000159 /* PCIE3_WDIS# */
-                       MX8MP_IOMUXC_NAND_DATA00__GPIO3_IO06    0x40000041 /* M2SKT_RST# */
-                       MX8MP_IOMUXC_SAI1_TXD6__GPIO4_IO18      0x40000159 /* M2SKT_WDIS# */
-                       MX8MP_IOMUXC_NAND_ALE__GPIO3_IO00       0x40000159 /* M2SKT_GDIS# */
+                       MX8MP_IOMUXC_GPIO1_IO09__GPIO1_IO09     0x40000040 /* DIO0 */
+                       MX8MP_IOMUXC_GPIO1_IO11__GPIO1_IO11     0x40000040 /* DIO1 */
+                       MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14       0x40000040 /* M2SKT_OFF# */
+                       MX8MP_IOMUXC_SD2_DATA2__GPIO2_IO17      0x40000150 /* PCIE1_WDIS# */
+                       MX8MP_IOMUXC_SD2_DATA3__GPIO2_IO18      0x40000150 /* PCIE2_WDIS# */
+                       MX8MP_IOMUXC_SD2_CMD__GPIO2_IO14        0x40000150 /* PCIE3_WDIS# */
+                       MX8MP_IOMUXC_NAND_DATA00__GPIO3_IO06    0x40000040 /* M2SKT_RST# */
+                       MX8MP_IOMUXC_SAI1_TXD6__GPIO4_IO18      0x40000150 /* M2SKT_WDIS# */
+                       MX8MP_IOMUXC_NAND_ALE__GPIO3_IO00       0x40000150 /* M2SKT_GDIS# */
                        MX8MP_IOMUXC_SAI3_TXD__GPIO5_IO01       0x40000104 /* UART_TERM */
                        MX8MP_IOMUXC_SAI3_TXFS__GPIO4_IO31      0x40000104 /* UART_RS485 */
                        MX8MP_IOMUXC_SAI3_TXC__GPIO5_IO00       0x40000104 /* UART_HALF */
 
        pinctrl_accel: accelgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_GPIO1_IO07__GPIO1_IO07     0x159
+                       MX8MP_IOMUXC_GPIO1_IO07__GPIO1_IO07     0x150
                >;
        };
 
        pinctrl_eqos: eqosgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC                             0x3
-                       MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO                           0x3
-                       MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0               0x91
-                       MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1               0x91
-                       MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2               0x91
-                       MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3               0x91
-                       MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK       0x91
-                       MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL         0x91
-                       MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0               0x1f
-                       MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1               0x1f
-                       MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2               0x1f
-                       MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3               0x1f
-                       MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL         0x1f
-                       MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK       0x1f
-                       MX8MP_IOMUXC_SAI3_RXD__GPIO4_IO30               0x141 /* RST# */
-                       MX8MP_IOMUXC_SAI3_RXFS__GPIO4_IO28              0x159 /* IRQ# */
+                       MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC                             0x2
+                       MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO                           0x2
+                       MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0               0x90
+                       MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1               0x90
+                       MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2               0x90
+                       MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3               0x90
+                       MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK       0x90
+                       MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL         0x90
+                       MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0               0x16
+                       MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1               0x16
+                       MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2               0x16
+                       MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3               0x16
+                       MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL         0x16
+                       MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK       0x16
+                       MX8MP_IOMUXC_SAI3_RXD__GPIO4_IO30               0x140 /* RST# */
+                       MX8MP_IOMUXC_SAI3_RXFS__GPIO4_IO28              0x150 /* IRQ# */
                >;
        };
 
        pinctrl_fec: fecgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_SAI1_RXD4__ENET1_RGMII_RD0         0x91
-                       MX8MP_IOMUXC_SAI1_RXD5__ENET1_RGMII_RD1         0x91
-                       MX8MP_IOMUXC_SAI1_RXD6__ENET1_RGMII_RD2         0x91
-                       MX8MP_IOMUXC_SAI1_RXD7__ENET1_RGMII_RD3         0x91
-                       MX8MP_IOMUXC_SAI1_TXC__ENET1_RGMII_RXC          0x91
-                       MX8MP_IOMUXC_SAI1_TXFS__ENET1_RGMII_RX_CTL      0x91
-                       MX8MP_IOMUXC_SAI1_TXD0__ENET1_RGMII_TD0         0x1f
-                       MX8MP_IOMUXC_SAI1_TXD1__ENET1_RGMII_TD1         0x1f
-                       MX8MP_IOMUXC_SAI1_TXD2__ENET1_RGMII_TD2         0x1f
-                       MX8MP_IOMUXC_SAI1_TXD3__ENET1_RGMII_TD3         0x1f
-                       MX8MP_IOMUXC_SAI1_TXD4__ENET1_RGMII_TX_CTL      0x1f
-                       MX8MP_IOMUXC_SAI1_TXD5__ENET1_RGMII_TXC         0x1f
-                       MX8MP_IOMUXC_SAI1_RXFS__ENET1_1588_EVENT0_IN    0x141
-                       MX8MP_IOMUXC_SAI1_RXC__ENET1_1588_EVENT0_OUT    0x141
+                       MX8MP_IOMUXC_SAI1_RXD4__ENET1_RGMII_RD0         0x90
+                       MX8MP_IOMUXC_SAI1_RXD5__ENET1_RGMII_RD1         0x90
+                       MX8MP_IOMUXC_SAI1_RXD6__ENET1_RGMII_RD2         0x90
+                       MX8MP_IOMUXC_SAI1_RXD7__ENET1_RGMII_RD3         0x90
+                       MX8MP_IOMUXC_SAI1_TXC__ENET1_RGMII_RXC          0x90
+                       MX8MP_IOMUXC_SAI1_TXFS__ENET1_RGMII_RX_CTL      0x90
+                       MX8MP_IOMUXC_SAI1_TXD0__ENET1_RGMII_TD0         0x16
+                       MX8MP_IOMUXC_SAI1_TXD1__ENET1_RGMII_TD1         0x16
+                       MX8MP_IOMUXC_SAI1_TXD2__ENET1_RGMII_TD2         0x16
+                       MX8MP_IOMUXC_SAI1_TXD3__ENET1_RGMII_TD3         0x16
+                       MX8MP_IOMUXC_SAI1_TXD4__ENET1_RGMII_TX_CTL      0x16
+                       MX8MP_IOMUXC_SAI1_TXD5__ENET1_RGMII_TXC         0x16
+                       MX8MP_IOMUXC_SAI1_RXFS__ENET1_1588_EVENT0_IN    0x140
+                       MX8MP_IOMUXC_SAI1_RXC__ENET1_1588_EVENT0_OUT    0x140
                >;
        };
 
 
        pinctrl_gsc: gscgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_SAI1_MCLK__GPIO4_IO20      0x159
+                       MX8MP_IOMUXC_SAI1_MCLK__GPIO4_IO20      0x150
                >;
        };
 
        pinctrl_i2c1: i2c1grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL         0x400001c3
-                       MX8MP_IOMUXC_I2C1_SDA__I2C1_SDA         0x400001c3
+                       MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL         0x400001c2
+                       MX8MP_IOMUXC_I2C1_SDA__I2C1_SDA         0x400001c2
                >;
        };
 
        pinctrl_i2c2: i2c2grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL         0x400001c3
-                       MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA         0x400001c3
+                       MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL         0x400001c2
+                       MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA         0x400001c2
                >;
        };
 
        pinctrl_i2c3: i2c3grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL         0x400001c3
-                       MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA         0x400001c3
+                       MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL         0x400001c2
+                       MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA         0x400001c2
                >;
        };
 
        pinctrl_i2c4: i2c4grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_I2C4_SCL__I2C4_SCL         0x400001c3
-                       MX8MP_IOMUXC_I2C4_SDA__I2C4_SDA         0x400001c3
+                       MX8MP_IOMUXC_I2C4_SCL__I2C4_SCL         0x400001c2
+                       MX8MP_IOMUXC_I2C4_SDA__I2C4_SDA         0x400001c2
                >;
        };
 
        pinctrl_ksz: kszgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29       0x159 /* IRQ# */
-                       MX8MP_IOMUXC_SAI3_MCLK__GPIO5_IO02      0x141 /* RST# */
+                       MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29       0x150 /* IRQ# */
+                       MX8MP_IOMUXC_SAI3_MCLK__GPIO5_IO02      0x140 /* RST# */
                >;
        };
 
        pinctrl_gpio_leds: ledgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_SD2_DATA0__GPIO2_IO15      0x19
-                       MX8MP_IOMUXC_SD2_DATA1__GPIO2_IO16      0x19
+                       MX8MP_IOMUXC_SD2_DATA0__GPIO2_IO15      0x10
+                       MX8MP_IOMUXC_SD2_DATA1__GPIO2_IO16      0x10
                >;
        };
 
        pinctrl_pmic: pmicgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_NAND_DATA01__GPIO3_IO07    0x141
+                       MX8MP_IOMUXC_NAND_DATA01__GPIO3_IO07    0x140
                >;
        };
 
        pinctrl_pps: ppsgrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12     0x141
+                       MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12     0x140
                >;
        };
 
 
        pinctrl_reg_usb2: regusb2grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_GPIO1_IO06__GPIO1_IO06     0x141
+                       MX8MP_IOMUXC_GPIO1_IO06__GPIO1_IO06     0x140
                >;
        };
 
        pinctrl_reg_wifi: regwifigrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_NAND_DATA03__GPIO3_IO09    0x119
+                       MX8MP_IOMUXC_NAND_DATA03__GPIO3_IO09    0x110
                >;
        };
 
 
        pinctrl_uart3_gpio: uart3gpiogrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_NAND_DATA02__GPIO3_IO08    0x119
+                       MX8MP_IOMUXC_NAND_DATA02__GPIO3_IO08    0x110
                >;
        };
 
index d9542df..410d0d5 100644 (file)
                                        pgc_ispdwp: power-domain@18 {
                                                #power-domain-cells = <0>;
                                                reg = <IMX8MP_POWER_DOMAIN_MEDIAMIX_ISPDWP>;
-                                               clocks = <&clk IMX8MP_CLK_MEDIA_ISP_DIV>;
+                                               clocks = <&clk IMX8MP_CLK_MEDIA_ISP_ROOT>;
                                        };
                                };
                        };
index 3b0cc85..71e373b 100644 (file)
@@ -74,7 +74,7 @@
                vdd_l17_29-supply = <&vph_pwr>;
                vdd_l20_21-supply = <&vph_pwr>;
                vdd_l25-supply = <&pm8994_s5>;
-               vdd_lvs1_2 = <&pm8994_s4>;
+               vdd_lvs1_2-supply = <&pm8994_s4>;
 
                /* S1, S2, S6 and S12 are managed by RPMPD */
 
index 7748b74..afa91ca 100644 (file)
                vdd_l17_29-supply = <&vph_pwr>;
                vdd_l20_21-supply = <&vph_pwr>;
                vdd_l25-supply = <&pm8994_s5>;
-               vdd_lvs1_2 = <&pm8994_s4>;
+               vdd_lvs1_2-supply = <&pm8994_s4>;
 
                /* S1, S2, S6 and S12 are managed by RPMPD */
 
index 0318d42..1ac2913 100644 (file)
                CPU6: cpu@102 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a57";
-                       reg = <0x0 0x101>;
+                       reg = <0x0 0x102>;
                        enable-method = "psci";
                        next-level-cache = <&L2_1>;
                };
                CPU7: cpu@103 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a57";
-                       reg = <0x0 0x101>;
+                       reg = <0x0 0x103>;
                        enable-method = "psci";
                        next-level-cache = <&L2_1>;
                };
index 9b3e3d1..d1e2df5 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2021 Google LLC.
  */
 
-#include "sc7180-trogdor.dtsi"
+/* This file must be included after sc7180-trogdor.dtsi */
 
 / {
        /* BOARD-SPECIFIC TOP LEVEL NODES */
index fe2369c..88f6a7d 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2020 Google LLC.
  */
 
-#include "sc7180-trogdor.dtsi"
+/* This file must be included after sc7180-trogdor.dtsi */
 
 &ap_sar_sensor {
        semtech,cs0-ground;
index 0692ae0..038538c 100644 (file)
 
                        power-domains = <&dispcc MDSS_GDSC>;
 
-                       clocks = <&gcc GCC_DISP_AHB_CLK>,
+                       clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
                                 <&dispcc DISP_CC_MDSS_MDP_CLK>;
                        clock-names = "iface", "core";
 
index 7d08fad..b87756b 100644 (file)
                        reg = <0x0 0x17100000 0x0 0x10000>,     /* GICD */
                              <0x0 0x17180000 0x0 0x200000>;    /* GICR * 8 */
                        interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       gic_its: msi-controller@17140000 {
+                               compatible = "arm,gic-v3-its";
+                               reg = <0x0 0x17140000 0x0 0x20000>;
+                               msi-controller;
+                               #msi-cells = <1>;
+                       };
                };
 
                timer@17420000 {
 
                        iommus = <&apps_smmu 0xe0 0x0>;
 
-                       interconnects = <&aggre1_noc MASTER_UFS_MEM &mc_virt SLAVE_EBI1>,
-                                       <&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_UFS_MEM_CFG>;
+                       interconnects = <&aggre1_noc MASTER_UFS_MEM 0 &mc_virt SLAVE_EBI1 0>,
+                                       <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_UFS_MEM_CFG 0>;
                        interconnect-names = "ufs-ddr", "cpu-ufs";
                        clock-names =
                                "core_clk",
index e2a5ec9..3618ef3 100644 (file)
@@ -214,6 +214,19 @@ static pte_t get_clear_contig(struct mm_struct *mm,
        return orig_pte;
 }
 
+static pte_t get_clear_contig_flush(struct mm_struct *mm,
+                                   unsigned long addr,
+                                   pte_t *ptep,
+                                   unsigned long pgsize,
+                                   unsigned long ncontig)
+{
+       pte_t orig_pte = get_clear_contig(mm, addr, ptep, pgsize, ncontig);
+       struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0);
+
+       flush_tlb_range(&vma, addr, addr + (pgsize * ncontig));
+       return orig_pte;
+}
+
 /*
  * Changing some bits of contiguous entries requires us to follow a
  * Break-Before-Make approach, breaking the whole contiguous set
@@ -447,19 +460,20 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
        int ncontig, i;
        size_t pgsize = 0;
        unsigned long pfn = pte_pfn(pte), dpfn;
+       struct mm_struct *mm = vma->vm_mm;
        pgprot_t hugeprot;
        pte_t orig_pte;
 
        if (!pte_cont(pte))
                return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
 
-       ncontig = find_num_contig(vma->vm_mm, addr, ptep, &pgsize);
+       ncontig = find_num_contig(mm, addr, ptep, &pgsize);
        dpfn = pgsize >> PAGE_SHIFT;
 
        if (!__cont_access_flags_changed(ptep, pte, ncontig))
                return 0;
 
-       orig_pte = get_clear_contig(vma->vm_mm, addr, ptep, pgsize, ncontig);
+       orig_pte = get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
 
        /* Make sure we don't lose the dirty or young state */
        if (pte_dirty(orig_pte))
@@ -470,7 +484,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 
        hugeprot = pte_pgprot(pte);
        for (i = 0; i < ncontig; i++, ptep++, addr += pgsize, pfn += dpfn)
-               set_pte_at(vma->vm_mm, addr, ptep, pfn_pte(pfn, hugeprot));
+               set_pte_at(mm, addr, ptep, pfn_pte(pfn, hugeprot));
 
        return 1;
 }
@@ -492,7 +506,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
        ncontig = find_num_contig(mm, addr, ptep, &pgsize);
        dpfn = pgsize >> PAGE_SHIFT;
 
-       pte = get_clear_contig(mm, addr, ptep, pgsize, ncontig);
+       pte = get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
        pte = pte_wrprotect(pte);
 
        hugeprot = pte_pgprot(pte);
@@ -505,17 +519,15 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
                            unsigned long addr, pte_t *ptep)
 {
+       struct mm_struct *mm = vma->vm_mm;
        size_t pgsize;
        int ncontig;
-       pte_t orig_pte;
 
        if (!pte_cont(READ_ONCE(*ptep)))
                return ptep_clear_flush(vma, addr, ptep);
 
-       ncontig = find_num_contig(vma->vm_mm, addr, ptep, &pgsize);
-       orig_pte = get_clear_contig(vma->vm_mm, addr, ptep, pgsize, ncontig);
-       flush_tlb_range(vma, addr, addr + pgsize * ncontig);
-       return orig_pte;
+       ncontig = find_num_contig(mm, addr, ptep, &pgsize);
+       return get_clear_contig_flush(mm, addr, ptep, pgsize, ncontig);
 }
 
 static int __init hugetlbpage_init(void)
index 1920d52..53a912b 100644 (file)
@@ -54,7 +54,6 @@ config LOONGARCH
        select GENERIC_CMOS_UPDATE
        select GENERIC_CPU_AUTOPROBE
        select GENERIC_ENTRY
-       select GENERIC_FIND_FIRST_BIT
        select GENERIC_GETTIMEOFDAY
        select GENERIC_IRQ_MULTI_HANDLER
        select GENERIC_IRQ_PROBE
@@ -77,7 +76,6 @@ config LOONGARCH
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE
        select HAVE_ASM_MODVERSIONS
        select HAVE_CONTEXT_TRACKING
-       select HAVE_COPY_THREAD_TLS
        select HAVE_DEBUG_STACKOVERFLOW
        select HAVE_DMA_CONTIGUOUS
        select HAVE_EXIT_THREAD
@@ -86,8 +84,6 @@ config LOONGARCH
        select HAVE_IOREMAP_PROT
        select HAVE_IRQ_EXIT_ON_IRQ_STACK
        select HAVE_IRQ_TIME_ACCOUNTING
-       select HAVE_MEMBLOCK
-       select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_MOD_ARCH_SPECIFIC
        select HAVE_NMI
        select HAVE_PERF_EVENTS
index adb16e4..b6be527 100644 (file)
@@ -48,6 +48,5 @@
 #define fcsr1  $r1
 #define fcsr2  $r2
 #define fcsr3  $r3
-#define vcsr16 $r16
 
 #endif /* _ASM_FPREGDEF_H */
index 3dba498..dc47fc7 100644 (file)
@@ -6,6 +6,7 @@
 #define _ASM_PAGE_H
 
 #include <linux/const.h>
+#include <asm/addrspace.h>
 
 /*
  * PAGE_SHIFT determines the page size
index 1d63c93..57ec45a 100644 (file)
@@ -80,7 +80,6 @@ BUILD_FPR_ACCESS(64)
 
 struct loongarch_fpu {
        unsigned int    fcsr;
-       unsigned int    vcsr;
        uint64_t        fcc;    /* 8x8 */
        union fpureg    fpr[NUM_FPU_REGS];
 };
@@ -161,7 +160,6 @@ struct thread_struct {
         */                                                     \
        .fpu                    = {                             \
                .fcsr           = 0,                            \
-               .vcsr           = 0,                            \
                .fcc            = 0,                            \
                .fpr            = {{{0,},},},                   \
        },                                                      \
index bfb65eb..20cd9e1 100644 (file)
@@ -166,7 +166,6 @@ void output_thread_fpu_defines(void)
 
        OFFSET(THREAD_FCSR, loongarch_fpu, fcsr);
        OFFSET(THREAD_FCC,  loongarch_fpu, fcc);
-       OFFSET(THREAD_VCSR, loongarch_fpu, vcsr);
        BLANK();
 }
 
index 75c6ce0..a631a71 100644 (file)
        movgr2fcsr      fcsr0, \tmp0
        .endm
 
-       .macro sc_save_vcsr base, tmp0
-       movfcsr2gr      \tmp0, vcsr16
-       EX      st.w \tmp0, \base, 0
-       .endm
-
-       .macro sc_restore_vcsr base, tmp0
-       EX      ld.w \tmp0, \base, 0
-       movgr2fcsr      vcsr16, \tmp0
-       .endm
-
 /*
  * Save a thread's fp context.
  */
index a76f547..a13f925 100644 (file)
@@ -429,7 +429,6 @@ int __init init_numa_memory(void)
        return 0;
 }
 
-EXPORT_SYMBOL(init_numa_memory);
 #endif
 
 void __init paging_init(void)
index 6b6e167..92e4040 100644 (file)
@@ -21,6 +21,7 @@ ccflags-vdso += $(filter --target=%,$(KBUILD_CFLAGS))
 endif
 
 cflags-vdso := $(ccflags-vdso) \
+       -isystem $(shell $(CC) -print-file-name=include) \
        $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
        -O2 -g -fno-strict-aliasing -fno-common -fno-builtin -G0 \
        -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \
index 8ae15c2..c6ad6f8 100644 (file)
@@ -25,7 +25,7 @@ struct or1k_frameinfo {
 /*
  * Verify a frameinfo structure.  The return address should be a valid text
  * address.  The frame pointer may be null if its the last frame, otherwise
- * the frame pointer should point to a location in the stack after the the
+ * the frame pointer should point to a location in the stack after the
  * top of the next frame up.
  */
 static inline int or1k_frameinfo_valid(struct or1k_frameinfo *frameinfo)
index 2673d57..94652e1 100644 (file)
@@ -224,8 +224,13 @@ int main(void)
        BLANK();
        DEFINE(ASM_SIGFRAME_SIZE, PARISC_RT_SIGFRAME_SIZE);
        DEFINE(SIGFRAME_CONTEXT_REGS, offsetof(struct rt_sigframe, uc.uc_mcontext) - PARISC_RT_SIGFRAME_SIZE);
+#ifdef CONFIG_64BIT
        DEFINE(ASM_SIGFRAME_SIZE32, PARISC_RT_SIGFRAME_SIZE32);
        DEFINE(SIGFRAME_CONTEXT_REGS32, offsetof(struct compat_rt_sigframe, uc.uc_mcontext) - PARISC_RT_SIGFRAME_SIZE32);
+#else
+       DEFINE(ASM_SIGFRAME_SIZE32, PARISC_RT_SIGFRAME_SIZE);
+       DEFINE(SIGFRAME_CONTEXT_REGS32, offsetof(struct rt_sigframe, uc.uc_mcontext) - PARISC_RT_SIGFRAME_SIZE);
+#endif
        BLANK();
        DEFINE(ICACHE_BASE, offsetof(struct pdc_cache_info, ic_base));
        DEFINE(ICACHE_STRIDE, offsetof(struct pdc_cache_info, ic_stride));
index ed1e88a..bac581b 100644 (file)
@@ -146,7 +146,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
 "      depw    %%r0,31,2,%4\n"
 "1:    ldw     0(%%sr1,%4),%0\n"
 "2:    ldw     4(%%sr1,%4),%3\n"
-"      subi    32,%4,%2\n"
+"      subi    32,%2,%2\n"
 "      mtctl   %2,11\n"
 "      vshd    %0,%3,%0\n"
 "3:    \n"
index c2ce2e6..7aa12e8 100644 (file)
@@ -358,6 +358,10 @@ config ARCH_SUSPEND_NONZERO_CPU
        def_bool y
        depends on PPC_POWERNV || PPC_PSERIES
 
+config ARCH_HAS_ADD_PAGES
+       def_bool y
+       depends on ARCH_ENABLE_MEMORY_HOTPLUG
+
 config PPC_DCR_NATIVE
        bool
 
diff --git a/arch/powerpc/include/asm/bpf_perf_event.h b/arch/powerpc/include/asm/bpf_perf_event.h
new file mode 100644 (file)
index 0000000..e8a7b4f
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_BPF_PERF_EVENT_H
+#define _ASM_POWERPC_BPF_PERF_EVENT_H
+
+#include <asm/ptrace.h>
+
+typedef struct user_pt_regs bpf_user_pt_regs_t;
+
+#endif /* _ASM_POWERPC_BPF_PERF_EVENT_H */
diff --git a/arch/powerpc/include/uapi/asm/bpf_perf_event.h b/arch/powerpc/include/uapi/asm/bpf_perf_event.h
deleted file mode 100644 (file)
index 5e1e648..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
-#define _UAPI__ASM_BPF_PERF_EVENT_H__
-
-#include <asm/ptrace.h>
-
-typedef struct user_pt_regs bpf_user_pt_regs_t;
-
-#endif /* _UAPI__ASM_BPF_PERF_EVENT_H__ */
index b183ab9..dfa5f72 100644 (file)
@@ -13,7 +13,7 @@
 # If you really need to reference something from prom_init.o add
 # it to the list below:
 
-grep "^CONFIG_KASAN=y$" .config >/dev/null
+grep "^CONFIG_KASAN=y$" ${KCONFIG_CONFIG} >/dev/null
 if [ $? -eq 0 ]
 then
        MEM_FUNCS="__memcpy __memset"
index 52b7768..a97128a 100644 (file)
@@ -105,6 +105,37 @@ void __ref arch_remove_linear_mapping(u64 start, u64 size)
        vm_unmap_aliases();
 }
 
+/*
+ * After memory hotplug the variables max_pfn, max_low_pfn and high_memory need
+ * updating.
+ */
+static void update_end_of_memory_vars(u64 start, u64 size)
+{
+       unsigned long end_pfn = PFN_UP(start + size);
+
+       if (end_pfn > max_pfn) {
+               max_pfn = end_pfn;
+               max_low_pfn = end_pfn;
+               high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
+       }
+}
+
+int __ref add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
+                   struct mhp_params *params)
+{
+       int ret;
+
+       ret = __add_pages(nid, start_pfn, nr_pages, params);
+       if (ret)
+               return ret;
+
+       /* update max_pfn, max_low_pfn and high_memory */
+       update_end_of_memory_vars(start_pfn << PAGE_SHIFT,
+                                 nr_pages << PAGE_SHIFT);
+
+       return ret;
+}
+
 int __ref arch_add_memory(int nid, u64 start, u64 size,
                          struct mhp_params *params)
 {
@@ -115,7 +146,7 @@ int __ref arch_add_memory(int nid, u64 start, u64 size,
        rc = arch_create_linear_mapping(nid, start, size, params);
        if (rc)
                return rc;
-       rc = __add_pages(nid, start_pfn, nr_pages, params);
+       rc = add_pages(nid, start_pfn, nr_pages, params);
        if (rc)
                arch_remove_linear_mapping(start, size);
        return rc;
index 7d4368d..b80fc4a 100644 (file)
@@ -96,8 +96,8 @@ int __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
                pgdp = pgd_offset_k(ea);
                p4dp = p4d_offset(pgdp, ea);
                if (p4d_none(*p4dp)) {
-                       pmdp = early_alloc_pgtable(PMD_TABLE_SIZE);
-                       p4d_populate(&init_mm, p4dp, pmdp);
+                       pudp = early_alloc_pgtable(PUD_TABLE_SIZE);
+                       p4d_populate(&init_mm, p4dp, pudp);
                }
                pudp = pud_offset(p4dp, ea);
                if (pud_none(*pudp)) {
@@ -106,7 +106,7 @@ int __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
                }
                pmdp = pmd_offset(pudp, ea);
                if (!pmd_present(*pmdp)) {
-                       ptep = early_alloc_pgtable(PAGE_SIZE);
+                       ptep = early_alloc_pgtable(PTE_TABLE_SIZE);
                        pmd_populate_kernel(&init_mm, pmdp, ptep);
                }
                ptep = pte_offset_kernel(pmdp, ea);
index 463c78c..3805ad1 100644 (file)
@@ -176,12 +176,8 @@ static int __init pnv_get_random_long_early(unsigned long *v)
                    NULL) != pnv_get_random_long_early)
                return 0;
 
-       for_each_compatible_node(dn, NULL, "ibm,power-rng") {
-               if (rng_create(dn))
-                       continue;
-               /* Create devices for hwrng driver */
-               of_platform_device_create(dn, NULL, NULL);
-       }
+       for_each_compatible_node(dn, NULL, "ibm,power-rng")
+               rng_create(dn);
 
        if (!ppc_md.get_random_seed)
                return 0;
@@ -205,10 +201,18 @@ void __init pnv_rng_init(void)
 
 static int __init pnv_rng_late_init(void)
 {
+       struct device_node *dn;
        unsigned long v;
+
        /* In case it wasn't called during init for some other reason. */
        if (ppc_md.get_random_seed == pnv_get_random_long_early)
                pnv_get_random_long_early(&v);
+
+       if (ppc_md.get_random_seed == powernv_get_random_long) {
+               for_each_compatible_node(dn, NULL, "ibm,power-rng")
+                       of_platform_device_create(dn, NULL, NULL);
+       }
+
        return 0;
 }
 machine_subsys_initcall(powernv, pnv_rng_late_init);
index 7d51286..d02911e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_fdt.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/bitmap.h>
 #include <linux/cpumask.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
@@ -57,7 +58,7 @@ static int __init xive_irq_bitmap_add(int base, int count)
        spin_lock_init(&xibm->lock);
        xibm->base = base;
        xibm->count = count;
-       xibm->bitmap = kzalloc(xibm->count, GFP_KERNEL);
+       xibm->bitmap = bitmap_zalloc(xibm->count, GFP_KERNEL);
        if (!xibm->bitmap) {
                kfree(xibm);
                return -ENOMEM;
@@ -75,7 +76,7 @@ static void xive_irq_bitmap_remove_all(void)
 
        list_for_each_entry_safe(xibm, tmp, &xive_irq_bitmaps, list) {
                list_del(&xibm->list);
-               kfree(xibm->bitmap);
+               bitmap_free(xibm->bitmap);
                kfree(xibm);
        }
 }
index 91c0b80..8cd9e56 100644 (file)
@@ -484,7 +484,6 @@ config KEXEC
 config KEXEC_FILE
        bool "kexec file based system call"
        select KEXEC_CORE
-       select BUILD_BIN2C
        depends on CRYPTO
        depends on CRYPTO_SHA256
        depends on CRYPTO_SHA256_S390
index 56007c7..1f2d409 100644 (file)
  *
  * Copyright IBM Corp. 2017, 2020
  * Author(s): Harald Freudenberger
- *
- * The s390_arch_random_generate() function may be called from random.c
- * in interrupt context. So this implementation does the best to be very
- * fast. There is a buffer of random data which is asynchronously checked
- * and filled by a workqueue thread.
- * If there are enough bytes in the buffer the s390_arch_random_generate()
- * just delivers these bytes. Otherwise false is returned until the
- * worker thread refills the buffer.
- * The worker fills the rng buffer by pulling fresh entropy from the
- * high quality (but slow) true hardware random generator. This entropy
- * is then spread over the buffer with an pseudo random generator PRNG.
- * As the arch_get_random_seed_long() fetches 8 bytes and the calling
- * function add_interrupt_randomness() counts this as 1 bit entropy the
- * distribution needs to make sure there is in fact 1 bit entropy contained
- * in 8 bytes of the buffer. The current values pull 32 byte entropy
- * and scatter this into a 2048 byte buffer. So 8 byte in the buffer
- * will contain 1 bit of entropy.
- * The worker thread is rescheduled based on the charge level of the
- * buffer but at least with 500 ms delay to avoid too much CPU consumption.
- * So the max. amount of rng data delivered via arch_get_random_seed is
- * limited to 4k bytes per second.
  */
 
 #include <linux/kernel.h>
 #include <linux/atomic.h>
 #include <linux/random.h>
-#include <linux/slab.h>
 #include <linux/static_key.h>
-#include <linux/workqueue.h>
-#include <linux/moduleparam.h>
 #include <asm/cpacf.h>
 
 DEFINE_STATIC_KEY_FALSE(s390_arch_random_available);
 
 atomic64_t s390_arch_random_counter = ATOMIC64_INIT(0);
 EXPORT_SYMBOL(s390_arch_random_counter);
-
-#define ARCH_REFILL_TICKS (HZ/2)
-#define ARCH_PRNG_SEED_SIZE 32
-#define ARCH_RNG_BUF_SIZE 2048
-
-static DEFINE_SPINLOCK(arch_rng_lock);
-static u8 *arch_rng_buf;
-static unsigned int arch_rng_buf_idx;
-
-static void arch_rng_refill_buffer(struct work_struct *);
-static DECLARE_DELAYED_WORK(arch_rng_work, arch_rng_refill_buffer);
-
-bool s390_arch_random_generate(u8 *buf, unsigned int nbytes)
-{
-       /* max hunk is ARCH_RNG_BUF_SIZE */
-       if (nbytes > ARCH_RNG_BUF_SIZE)
-               return false;
-
-       /* lock rng buffer */
-       if (!spin_trylock(&arch_rng_lock))
-               return false;
-
-       /* try to resolve the requested amount of bytes from the buffer */
-       arch_rng_buf_idx -= nbytes;
-       if (arch_rng_buf_idx < ARCH_RNG_BUF_SIZE) {
-               memcpy(buf, arch_rng_buf + arch_rng_buf_idx, nbytes);
-               atomic64_add(nbytes, &s390_arch_random_counter);
-               spin_unlock(&arch_rng_lock);
-               return true;
-       }
-
-       /* not enough bytes in rng buffer, refill is done asynchronously */
-       spin_unlock(&arch_rng_lock);
-
-       return false;
-}
-EXPORT_SYMBOL(s390_arch_random_generate);
-
-static void arch_rng_refill_buffer(struct work_struct *unused)
-{
-       unsigned int delay = ARCH_REFILL_TICKS;
-
-       spin_lock(&arch_rng_lock);
-       if (arch_rng_buf_idx > ARCH_RNG_BUF_SIZE) {
-               /* buffer is exhausted and needs refill */
-               u8 seed[ARCH_PRNG_SEED_SIZE];
-               u8 prng_wa[240];
-               /* fetch ARCH_PRNG_SEED_SIZE bytes of entropy */
-               cpacf_trng(NULL, 0, seed, sizeof(seed));
-               /* blow this entropy up to ARCH_RNG_BUF_SIZE with PRNG */
-               memset(prng_wa, 0, sizeof(prng_wa));
-               cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
-                          &prng_wa, NULL, 0, seed, sizeof(seed));
-               cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
-                          &prng_wa, arch_rng_buf, ARCH_RNG_BUF_SIZE, NULL, 0);
-               arch_rng_buf_idx = ARCH_RNG_BUF_SIZE;
-       }
-       delay += (ARCH_REFILL_TICKS * arch_rng_buf_idx) / ARCH_RNG_BUF_SIZE;
-       spin_unlock(&arch_rng_lock);
-
-       /* kick next check */
-       queue_delayed_work(system_long_wq, &arch_rng_work, delay);
-}
-
-/*
- * Here follows the implementation of s390_arch_get_random_long().
- *
- * The random longs to be pulled by arch_get_random_long() are
- * prepared in an 4K buffer which is filled from the NIST 800-90
- * compliant s390 drbg. By default the random long buffer is refilled
- * 256 times before the drbg itself needs a reseed. The reseed of the
- * drbg is done with 32 bytes fetched from the high quality (but slow)
- * trng which is assumed to deliver 100% entropy. So the 32 * 8 = 256
- * bits of entropy are spread over 256 * 4KB = 1MB serving 131072
- * arch_get_random_long() invocations before reseeded.
- *
- * How often the 4K random long buffer is refilled with the drbg
- * before the drbg is reseeded can be adjusted. There is a module
- * parameter 's390_arch_rnd_long_drbg_reseed' accessible via
- *   /sys/module/arch_random/parameters/rndlong_drbg_reseed
- * or as kernel command line parameter
- *   arch_random.rndlong_drbg_reseed=<value>
- * This parameter tells how often the drbg fills the 4K buffer before
- * it is re-seeded by fresh entropy from the trng.
- * A value of 16 results in reseeding the drbg at every 16 * 4 KB = 64
- * KB with 32 bytes of fresh entropy pulled from the trng. So a value
- * of 16 would result in 256 bits entropy per 64 KB.
- * A value of 256 results in 1MB of drbg output before a reseed of the
- * drbg is done. So this would spread the 256 bits of entropy among 1MB.
- * Setting this parameter to 0 forces the reseed to take place every
- * time the 4K buffer is depleted, so the entropy rises to 256 bits
- * entropy per 4K or 0.5 bit entropy per arch_get_random_long().  With
- * setting this parameter to negative values all this effort is
- * disabled, arch_get_random long() returns false and thus indicating
- * that the arch_get_random_long() feature is disabled at all.
- */
-
-static unsigned long rndlong_buf[512];
-static DEFINE_SPINLOCK(rndlong_lock);
-static int rndlong_buf_index;
-
-static int rndlong_drbg_reseed = 256;
-module_param_named(rndlong_drbg_reseed, rndlong_drbg_reseed, int, 0600);
-MODULE_PARM_DESC(rndlong_drbg_reseed, "s390 arch_get_random_long() drbg reseed");
-
-static inline void refill_rndlong_buf(void)
-{
-       static u8 prng_ws[240];
-       static int drbg_counter;
-
-       if (--drbg_counter < 0) {
-               /* need to re-seed the drbg */
-               u8 seed[32];
-
-               /* fetch seed from trng */
-               cpacf_trng(NULL, 0, seed, sizeof(seed));
-               /* seed drbg */
-               memset(prng_ws, 0, sizeof(prng_ws));
-               cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
-                          &prng_ws, NULL, 0, seed, sizeof(seed));
-               /* re-init counter for drbg */
-               drbg_counter = rndlong_drbg_reseed;
-       }
-
-       /* fill the arch_get_random_long buffer from drbg */
-       cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, &prng_ws,
-                  (u8 *) rndlong_buf, sizeof(rndlong_buf),
-                  NULL, 0);
-}
-
-bool s390_arch_get_random_long(unsigned long *v)
-{
-       bool rc = false;
-       unsigned long flags;
-
-       /* arch_get_random_long() disabled ? */
-       if (rndlong_drbg_reseed < 0)
-               return false;
-
-       /* try to lock the random long lock */
-       if (!spin_trylock_irqsave(&rndlong_lock, flags))
-               return false;
-
-       if (--rndlong_buf_index >= 0) {
-               /* deliver next long value from the buffer */
-               *v = rndlong_buf[rndlong_buf_index];
-               rc = true;
-               goto out;
-       }
-
-       /* buffer is depleted and needs refill */
-       if (in_interrupt()) {
-               /* delay refill in interrupt context to next caller */
-               rndlong_buf_index = 0;
-               goto out;
-       }
-
-       /* refill random long buffer */
-       refill_rndlong_buf();
-       rndlong_buf_index = ARRAY_SIZE(rndlong_buf);
-
-       /* and provide one random long */
-       *v = rndlong_buf[--rndlong_buf_index];
-       rc = true;
-
-out:
-       spin_unlock_irqrestore(&rndlong_lock, flags);
-       return rc;
-}
-EXPORT_SYMBOL(s390_arch_get_random_long);
-
-static int __init s390_arch_random_init(void)
-{
-       /* all the needed PRNO subfunctions available ? */
-       if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG) &&
-           cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN)) {
-
-               /* alloc arch random working buffer */
-               arch_rng_buf = kmalloc(ARCH_RNG_BUF_SIZE, GFP_KERNEL);
-               if (!arch_rng_buf)
-                       return -ENOMEM;
-
-               /* kick worker queue job to fill the random buffer */
-               queue_delayed_work(system_long_wq,
-                                  &arch_rng_work, ARCH_REFILL_TICKS);
-
-               /* enable arch random to the outside world */
-               static_branch_enable(&s390_arch_random_available);
-       }
-
-       return 0;
-}
-arch_initcall(s390_arch_random_init);
index 5dc712f..2c6e1c6 100644 (file)
 
 #include <linux/static_key.h>
 #include <linux/atomic.h>
+#include <asm/cpacf.h>
 
 DECLARE_STATIC_KEY_FALSE(s390_arch_random_available);
 extern atomic64_t s390_arch_random_counter;
 
-bool s390_arch_get_random_long(unsigned long *v);
-bool s390_arch_random_generate(u8 *buf, unsigned int nbytes);
-
 static inline bool __must_check arch_get_random_long(unsigned long *v)
 {
-       if (static_branch_likely(&s390_arch_random_available))
-               return s390_arch_get_random_long(v);
        return false;
 }
 
@@ -37,7 +33,9 @@ static inline bool __must_check arch_get_random_int(unsigned int *v)
 static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
 {
        if (static_branch_likely(&s390_arch_random_available)) {
-               return s390_arch_random_generate((u8 *)v, sizeof(*v));
+               cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
+               atomic64_add(sizeof(*v), &s390_arch_random_counter);
+               return true;
        }
        return false;
 }
@@ -45,7 +43,9 @@ static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
 static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
 {
        if (static_branch_likely(&s390_arch_random_available)) {
-               return s390_arch_random_generate((u8 *)v, sizeof(*v));
+               cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
+               atomic64_add(sizeof(*v), &s390_arch_random_counter);
+               return true;
        }
        return false;
 }
index 54ae2dc..2f983e0 100644 (file)
@@ -133,9 +133,9 @@ struct slibe {
  * @sb_count: number of storage blocks
  * @sba: storage block element addresses
  * @dcount: size of storage block elements
- * @user0: user defineable value
- * @res4: reserved paramater
- * @user1: user defineable value
+ * @user0: user definable value
+ * @res4: reserved parameter
+ * @user1: user definable value
  */
 struct qaob {
        u64 res0[6];
index 8d91ecc..0a37f5d 100644 (file)
@@ -875,6 +875,11 @@ static void __init setup_randomness(void)
        if (stsi(vmms, 3, 2, 2) == 0 && vmms->count)
                add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count);
        memblock_free(vmms, PAGE_SIZE);
+
+#ifdef CONFIG_ARCH_RANDOM
+       if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
+               static_branch_enable(&s390_arch_random_available);
+#endif
 }
 
 /*
index 360ada8..d237bc6 100644 (file)
@@ -48,7 +48,6 @@ OBJCOPYFLAGS_purgatory.ro += --remove-section='.note.*'
 $(obj)/purgatory.ro: $(obj)/purgatory $(obj)/purgatory.chk FORCE
                $(call if_changed,objcopy)
 
-$(obj)/kexec-purgatory.o: $(obj)/kexec-purgatory.S $(obj)/purgatory.ro FORCE
-       $(call if_changed_rule,as_o_S)
+$(obj)/kexec-purgatory.o: $(obj)/purgatory.ro
 
-obj-$(CONFIG_ARCH_HAS_KEXEC_PURGATORY) += kexec-purgatory.o
+obj-y += kexec-purgatory.o
index 44c350d..d4a314c 100644 (file)
@@ -110,6 +110,7 @@ void kernel_add_identity_map(unsigned long start, unsigned long end)
 void initialize_identity_maps(void *rmode)
 {
        unsigned long cmdline;
+       struct setup_data *sd;
 
        /* Exclude the encryption mask from __PHYSICAL_MASK */
        physical_mask &= ~sme_me_mask;
@@ -163,6 +164,18 @@ void initialize_identity_maps(void *rmode)
        cmdline = get_cmd_line_ptr();
        kernel_add_identity_map(cmdline, cmdline + COMMAND_LINE_SIZE);
 
+       /*
+        * Also map the setup_data entries passed via boot_params in case they
+        * need to be accessed by uncompressed kernel via the identity mapping.
+        */
+       sd = (struct setup_data *)boot_params->hdr.setup_data;
+       while (sd) {
+               unsigned long sd_addr = (unsigned long)sd;
+
+               kernel_add_identity_map(sd_addr, sd_addr + sizeof(*sd) + sd->len);
+               sd = (struct setup_data *)sd->next;
+       }
+
        sev_prep_identity_maps(top_level_pgt);
 
        /* Load the new page-table. */
index f8b9ee9..f37cbff 100644 (file)
@@ -120,6 +120,9 @@ void *extend_brk(size_t size, size_t align);
        static char __brk_##name[size]
 
 extern void probe_roms(void);
+
+void clear_bss(void);
+
 #ifdef __i386__
 
 asmlinkage void __init i386_start_kernel(void);
index bea5cdc..e02a8a8 100644 (file)
@@ -15,7 +15,7 @@
 #define SETUP_INDIRECT                 (1<<31)
 
 /* SETUP_INDIRECT | max(SETUP_*) */
-#define SETUP_TYPE_MAX                 (SETUP_INDIRECT | SETUP_JAILHOUSE)
+#define SETUP_TYPE_MAX                 (SETUP_INDIRECT | SETUP_CC_BLOB)
 
 /* ram_size flags */
 #define RAMDISK_IMAGE_START_MASK       0x07FF
index 8b8cbf2..734b964 100644 (file)
 
 /* Refer to drivers/acpi/cppc_acpi.c for the description of functions */
 
+bool cpc_supported_by_cpu(void)
+{
+       switch (boot_cpu_data.x86_vendor) {
+       case X86_VENDOR_AMD:
+       case X86_VENDOR_HYGON:
+               return boot_cpu_has(X86_FEATURE_CPPC);
+       }
+       return false;
+}
+
 bool cpc_ffh_supported(void)
 {
        return true;
index bd4a341..6a3cfaf 100644 (file)
@@ -426,10 +426,12 @@ void __init do_early_exception(struct pt_regs *regs, int trapnr)
 
 /* Don't add a printk in there. printk relies on the PDA which is not initialized 
    yet. */
-static void __init clear_bss(void)
+void __init clear_bss(void)
 {
        memset(__bss_start, 0,
               (unsigned long) __bss_stop - (unsigned long) __bss_start);
+       memset(__brk_base, 0,
+              (unsigned long) __brk_limit - (unsigned long) __brk_base);
 }
 
 static unsigned long get_cmd_line_ptr(void)
index 81aba71..9487ce8 100644 (file)
@@ -385,7 +385,7 @@ SECTIONS
        __end_of_kernel_reserve = .;
 
        . = ALIGN(PAGE_SIZE);
-       .brk (NOLOAD) : AT(ADDR(.brk) - LOAD_OFFSET) {
+       .brk : AT(ADDR(.brk) - LOAD_OFFSET) {
                __brk_base = .;
                . += 64 * 1024;         /* 64k alignment slop space */
                *(.bss..brk)            /* areas brk users have reserved */
index e3297b1..70fb2ea 100644 (file)
@@ -1183,15 +1183,19 @@ static void __init xen_domu_set_legacy_features(void)
 extern void early_xen_iret_patch(void);
 
 /* First C function to be called on Xen boot */
-asmlinkage __visible void __init xen_start_kernel(void)
+asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
 {
        struct physdev_set_iopl set_iopl;
        unsigned long initrd_start = 0;
        int rc;
 
-       if (!xen_start_info)
+       if (!si)
                return;
 
+       clear_bss();
+
+       xen_start_info = si;
+
        __text_gen_insn(&early_xen_iret_patch,
                        JMP32_INSN_OPCODE, &early_xen_iret_patch, &xen_iret,
                        JMP32_INSN_SIZE);
index 3a2cd93..13af6fe 100644 (file)
@@ -48,15 +48,6 @@ SYM_CODE_START(startup_xen)
        ANNOTATE_NOENDBR
        cld
 
-       /* Clear .bss */
-       xor %eax,%eax
-       mov $__bss_start, %rdi
-       mov $__bss_stop, %rcx
-       sub %rdi, %rcx
-       shr $3, %rcx
-       rep stosq
-
-       mov %rsi, xen_start_info
        mov initial_stack(%rip), %rsp
 
        /* Set up %gs.
@@ -71,6 +62,7 @@ SYM_CODE_START(startup_xen)
        cdq
        wrmsr
 
+       mov     %rsi, %rdi
        call xen_start_kernel
 SYM_CODE_END(startup_xen)
        __FINIT
index 1d44893..7b81685 100644 (file)
@@ -666,6 +666,18 @@ config CRYPTO_CRC32_MIPS
          CRC32c and CRC32 CRC algorithms implemented using mips crypto
          instructions, when available.
 
+config CRYPTO_CRC32_S390
+       tristate "CRC-32 algorithms"
+       depends on S390
+       select CRYPTO_HASH
+       select CRC32
+       help
+         Select this option if you want to use hardware accelerated
+         implementations of CRC algorithms.  With this option, you
+         can optimize the computation of CRC-32 (IEEE 802.3 Ethernet)
+         and CRC-32C (Castagnoli).
+
+         It is available with IBM z13 or later.
 
 config CRYPTO_XXHASH
        tristate "xxHash hash algorithm"
@@ -898,6 +910,16 @@ config CRYPTO_SHA512_SSSE3
          Extensions version 1 (AVX1), or Advanced Vector Extensions
          version 2 (AVX2) instructions, when available.
 
+config CRYPTO_SHA512_S390
+       tristate "SHA384 and SHA512 digest algorithm"
+       depends on S390
+       select CRYPTO_HASH
+       help
+         This is the s390 hardware accelerated implementation of the
+         SHA512 secure hash standard.
+
+         It is available as of z10.
+
 config CRYPTO_SHA1_OCTEON
        tristate "SHA1 digest algorithm (OCTEON)"
        depends on CPU_CAVIUM_OCTEON
@@ -930,6 +952,16 @@ config CRYPTO_SHA1_PPC_SPE
          SHA-1 secure hash standard (DFIPS 180-4) implemented
          using powerpc SPE SIMD instruction set.
 
+config CRYPTO_SHA1_S390
+       tristate "SHA1 digest algorithm"
+       depends on S390
+       select CRYPTO_HASH
+       help
+         This is the s390 hardware accelerated implementation of the
+         SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
+
+         It is available as of z990.
+
 config CRYPTO_SHA256
        tristate "SHA224 and SHA256 digest algorithm"
        select CRYPTO_HASH
@@ -970,6 +1002,16 @@ config CRYPTO_SHA256_SPARC64
          SHA-256 secure hash standard (DFIPS 180-2) implemented
          using sparc64 crypto instructions, when available.
 
+config CRYPTO_SHA256_S390
+       tristate "SHA256 digest algorithm"
+       depends on S390
+       select CRYPTO_HASH
+       help
+         This is the s390 hardware accelerated implementation of the
+         SHA256 secure hash standard (DFIPS 180-2).
+
+         It is available as of z9.
+
 config CRYPTO_SHA512
        tristate "SHA384 and SHA512 digest algorithms"
        select CRYPTO_HASH
@@ -1010,6 +1052,26 @@ config CRYPTO_SHA3
          References:
          http://keccak.noekeon.org/
 
+config CRYPTO_SHA3_256_S390
+       tristate "SHA3_224 and SHA3_256 digest algorithm"
+       depends on S390
+       select CRYPTO_HASH
+       help
+         This is the s390 hardware accelerated implementation of the
+         SHA3_256 secure hash standard.
+
+         It is available as of z14.
+
+config CRYPTO_SHA3_512_S390
+       tristate "SHA3_384 and SHA3_512 digest algorithm"
+       depends on S390
+       select CRYPTO_HASH
+       help
+         This is the s390 hardware accelerated implementation of the
+         SHA3_512 secure hash standard.
+
+         It is available as of z14.
+
 config CRYPTO_SM3
        tristate
 
@@ -1070,6 +1132,16 @@ config CRYPTO_GHASH_CLMUL_NI_INTEL
          This is the x86_64 CLMUL-NI accelerated implementation of
          GHASH, the hash function used in GCM (Galois/Counter mode).
 
+config CRYPTO_GHASH_S390
+       tristate "GHASH hash function"
+       depends on S390
+       select CRYPTO_HASH
+       help
+         This is the s390 hardware accelerated implementation of GHASH,
+         the hash function used in GCM (Galois/Counter mode).
+
+         It is available as of z196.
+
 comment "Ciphers"
 
 config CRYPTO_AES
@@ -1185,6 +1257,23 @@ config CRYPTO_AES_PPC_SPE
          architecture specific assembler implementations that work on 1KB
          tables or 256 bytes S-boxes.
 
+config CRYPTO_AES_S390
+       tristate "AES cipher algorithms"
+       depends on S390
+       select CRYPTO_ALGAPI
+       select CRYPTO_SKCIPHER
+       help
+         This is the s390 hardware accelerated implementation of the
+         AES cipher algorithms (FIPS-197).
+
+         As of z9 the ECB and CBC modes are hardware accelerated
+         for 128 bit keys.
+         As of z10 the ECB and CBC modes are hardware accelerated
+         for all AES key sizes.
+         As of z196 the CTR mode is hardware accelerated for all AES
+         key sizes and XTS mode is hardware accelerated for 256 and
+         512 bit keys.
+
 config CRYPTO_ANUBIS
        tristate "Anubis cipher algorithm"
        depends on CRYPTO_USER_API_ENABLE_OBSOLETE
@@ -1415,6 +1504,19 @@ config CRYPTO_DES3_EDE_X86_64
          algorithm are provided; regular processing one input block and
          one that processes three blocks parallel.
 
+config CRYPTO_DES_S390
+       tristate "DES and Triple DES cipher algorithms"
+       depends on S390
+       select CRYPTO_ALGAPI
+       select CRYPTO_SKCIPHER
+       select CRYPTO_LIB_DES
+       help
+         This is the s390 hardware accelerated implementation of the
+         DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
+
+         As of z990 the ECB and CBC mode are hardware accelerated.
+         As of z196 the CTR mode is hardware accelerated.
+
 config CRYPTO_FCRYPT
        tristate "FCrypt cipher algorithm"
        select CRYPTO_ALGAPI
@@ -1474,6 +1576,18 @@ config CRYPTO_CHACHA_MIPS
        select CRYPTO_SKCIPHER
        select CRYPTO_ARCH_HAVE_LIB_CHACHA
 
+config CRYPTO_CHACHA_S390
+       tristate "ChaCha20 stream cipher"
+       depends on S390
+       select CRYPTO_SKCIPHER
+       select CRYPTO_LIB_CHACHA_GENERIC
+       select CRYPTO_ARCH_HAVE_LIB_CHACHA
+       help
+         This is the s390 SIMD implementation of the ChaCha20 stream
+         cipher (RFC 7539).
+
+         It is available as of z13.
+
 config CRYPTO_SEED
        tristate "SEED cipher algorithm"
        depends on CRYPTO_USER_API_ENABLE_OBSOLETE
index e07782b..43177c2 100644 (file)
@@ -73,6 +73,7 @@ module_param(device_id_scheme, bool, 0444);
 static int only_lcd = -1;
 module_param(only_lcd, int, 0444);
 
+static bool has_backlight;
 static int register_count;
 static DEFINE_MUTEX(register_count_mutex);
 static DEFINE_MUTEX(video_list_lock);
@@ -1222,6 +1223,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
        acpi_video_device_bind(video, data);
        acpi_video_device_find_cap(data);
 
+       if (data->cap._BCM && data->cap._BCL)
+               has_backlight = true;
+
        mutex_lock(&video->device_list_lock);
        list_add_tail(&data->entry, &video->video_device_list);
        mutex_unlock(&video->device_list_lock);
@@ -2249,6 +2253,7 @@ void acpi_video_unregister(void)
        if (register_count) {
                acpi_bus_unregister_driver(&acpi_video_bus);
                register_count = 0;
+               has_backlight = false;
        }
        mutex_unlock(&register_count_mutex);
 }
@@ -2270,13 +2275,7 @@ void acpi_video_unregister_backlight(void)
 
 bool acpi_video_handles_brightness_key_presses(void)
 {
-       bool have_video_busses;
-
-       mutex_lock(&video_list_lock);
-       have_video_busses = !list_empty(&video_bus_head);
-       mutex_unlock(&video_list_lock);
-
-       return have_video_busses &&
+       return has_backlight &&
               (report_key_events & REPORT_BRIGHTNESS_KEY_EVENTS);
 }
 EXPORT_SYMBOL(acpi_video_handles_brightness_key_presses);
index 86fa61a..e2db1bd 100644 (file)
@@ -298,7 +298,7 @@ EXPORT_SYMBOL_GPL(osc_cpc_flexible_adr_space_confirmed);
 bool osc_sb_native_usb4_support_confirmed;
 EXPORT_SYMBOL_GPL(osc_sb_native_usb4_support_confirmed);
 
-bool osc_sb_cppc_not_supported;
+bool osc_sb_cppc2_support_acked;
 
 static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
 static void acpi_bus_osc_negotiate_platform_control(void)
@@ -358,11 +358,6 @@ static void acpi_bus_osc_negotiate_platform_control(void)
                return;
        }
 
-#ifdef CONFIG_ACPI_CPPC_LIB
-       osc_sb_cppc_not_supported = !(capbuf_ret[OSC_SUPPORT_DWORD] &
-                       (OSC_SB_CPC_SUPPORT | OSC_SB_CPCV2_SUPPORT));
-#endif
-
        /*
         * Now run _OSC again with query flag clear and with the caps
         * supported by both the OS and the platform.
@@ -376,6 +371,10 @@ static void acpi_bus_osc_negotiate_platform_control(void)
 
        capbuf_ret = context.ret.pointer;
        if (context.ret.length > OSC_SUPPORT_DWORD) {
+#ifdef CONFIG_ACPI_CPPC_LIB
+               osc_sb_cppc2_support_acked = capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_CPCV2_SUPPORT;
+#endif
+
                osc_sb_apei_support_acked =
                        capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
                osc_pc_lpi_support_confirmed =
index 903528f..6ff1901 100644 (file)
@@ -577,6 +577,19 @@ bool __weak cpc_ffh_supported(void)
        return false;
 }
 
+/**
+ * cpc_supported_by_cpu() - check if CPPC is supported by CPU
+ *
+ * Check if the architectural support for CPPC is present even
+ * if the _OSC hasn't prescribed it
+ *
+ * Return: true for supported, false for not supported
+ */
+bool __weak cpc_supported_by_cpu(void)
+{
+       return false;
+}
+
 /**
  * pcc_data_alloc() - Allocate the pcc_data memory for pcc subspace
  *
@@ -684,8 +697,11 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
        acpi_status status;
        int ret = -ENODATA;
 
-       if (osc_sb_cppc_not_supported)
-               return -ENODEV;
+       if (!osc_sb_cppc2_support_acked) {
+               pr_debug("CPPC v2 _OSC not acked\n");
+               if (!cpc_supported_by_cpu())
+                       return -ENODEV;
+       }
 
        /* Parse the ACPI _CPC table for this CPU. */
        status = acpi_evaluate_object_typed(handle, "_CPC", NULL, &output,
index 6725931..c2c3238 100644 (file)
@@ -90,7 +90,7 @@ static void cs5535_set_piomode(struct ata_port *ap, struct ata_device *adev)
        static const u16 pio_cmd_timings[5] = {
                0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131
        };
-       u32 reg, dummy;
+       u32 reg, __maybe_unused dummy;
        struct ata_device *pair = ata_dev_pair(adev);
 
        int mode = adev->pio_mode - XFER_PIO_0;
@@ -129,7 +129,7 @@ static void cs5535_set_dmamode(struct ata_port *ap, struct ata_device *adev)
        static const u32 mwdma_timings[3] = {
                0x7F0FFFF3, 0x7F035352, 0x7F024241
        };
-       u32 reg, dummy;
+       u32 reg, __maybe_unused dummy;
        int mode = adev->dma_mode;
 
        rdmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg, dummy);
index 7cd789c..460d6f1 100644 (file)
@@ -486,7 +486,18 @@ static void device_link_release_fn(struct work_struct *work)
        /* Ensure that all references to the link object have been dropped. */
        device_link_synchronize_removal();
 
-       pm_runtime_release_supplier(link, true);
+       pm_runtime_release_supplier(link);
+       /*
+        * If supplier_preactivated is set, the link has been dropped between
+        * the pm_runtime_get_suppliers() and pm_runtime_put_suppliers() calls
+        * in __driver_probe_device().  In that case, drop the supplier's
+        * PM-runtime usage counter to remove the reference taken by
+        * pm_runtime_get_suppliers().
+        */
+       if (link->supplier_preactivated)
+               pm_runtime_put_noidle(link->supplier);
+
+       pm_request_idle(link->supplier);
 
        put_device(link->consumer);
        put_device(link->supplier);
index 676dc72..949907e 100644 (file)
@@ -308,13 +308,10 @@ static int rpm_get_suppliers(struct device *dev)
 /**
  * pm_runtime_release_supplier - Drop references to device link's supplier.
  * @link: Target device link.
- * @check_idle: Whether or not to check if the supplier device is idle.
  *
- * Drop all runtime PM references associated with @link to its supplier device
- * and if @check_idle is set, check if that device is idle (and so it can be
- * suspended).
+ * Drop all runtime PM references associated with @link to its supplier device.
  */
-void pm_runtime_release_supplier(struct device_link *link, bool check_idle)
+void pm_runtime_release_supplier(struct device_link *link)
 {
        struct device *supplier = link->supplier;
 
@@ -327,9 +324,6 @@ void pm_runtime_release_supplier(struct device_link *link, bool check_idle)
        while (refcount_dec_not_one(&link->rpm_active) &&
               atomic_read(&supplier->power.usage_count) > 0)
                pm_runtime_put_noidle(supplier);
-
-       if (check_idle)
-               pm_request_idle(supplier);
 }
 
 static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend)
@@ -337,8 +331,11 @@ static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend)
        struct device_link *link;
 
        list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
-                               device_links_read_lock_held())
-               pm_runtime_release_supplier(link, try_to_suspend);
+                               device_links_read_lock_held()) {
+               pm_runtime_release_supplier(link);
+               if (try_to_suspend)
+                       pm_request_idle(link->supplier);
+       }
 }
 
 static void rpm_put_suppliers(struct device *dev)
@@ -1771,7 +1768,6 @@ void pm_runtime_get_suppliers(struct device *dev)
                if (link->flags & DL_FLAG_PM_RUNTIME) {
                        link->supplier_preactivated = true;
                        pm_runtime_get_sync(link->supplier);
-                       refcount_inc(&link->rpm_active);
                }
 
        device_links_read_unlock(idx);
@@ -1791,19 +1787,8 @@ void pm_runtime_put_suppliers(struct device *dev)
        list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
                                device_links_read_lock_held())
                if (link->supplier_preactivated) {
-                       bool put;
-
                        link->supplier_preactivated = false;
-
-                       spin_lock_irq(&dev->power.lock);
-
-                       put = pm_runtime_status_suspended(dev) &&
-                             refcount_dec_not_one(&link->rpm_active);
-
-                       spin_unlock_irq(&dev->power.lock);
-
-                       if (put)
-                               pm_runtime_put(link->supplier);
+                       pm_runtime_put(link->supplier);
                }
 
        device_links_read_unlock(idx);
@@ -1838,7 +1823,8 @@ void pm_runtime_drop_link(struct device_link *link)
                return;
 
        pm_runtime_drop_link_count(link->consumer);
-       pm_runtime_release_supplier(link, true);
+       pm_runtime_release_supplier(link);
+       pm_request_idle(link->supplier);
 }
 
 static bool pm_runtime_need_not_resume(struct device *dev)
index 33f04ef..3646c0c 100644 (file)
@@ -152,6 +152,10 @@ static unsigned int xen_blkif_max_ring_order;
 module_param_named(max_ring_page_order, xen_blkif_max_ring_order, int, 0444);
 MODULE_PARM_DESC(max_ring_page_order, "Maximum order of pages to be used for the shared ring");
 
+static bool __read_mostly xen_blkif_trusted = true;
+module_param_named(trusted, xen_blkif_trusted, bool, 0644);
+MODULE_PARM_DESC(trusted, "Is the backend trusted");
+
 #define BLK_RING_SIZE(info)    \
        __CONST_RING_SIZE(blkif, XEN_PAGE_SIZE * (info)->nr_ring_pages)
 
@@ -210,6 +214,7 @@ struct blkfront_info
        unsigned int feature_discard:1;
        unsigned int feature_secdiscard:1;
        unsigned int feature_persistent:1;
+       unsigned int bounce:1;
        unsigned int discard_granularity;
        unsigned int discard_alignment;
        /* Number of 4KB segments handled */
@@ -310,8 +315,8 @@ static int fill_grant_buffer(struct blkfront_ring_info *rinfo, int num)
                if (!gnt_list_entry)
                        goto out_of_memory;
 
-               if (info->feature_persistent) {
-                       granted_page = alloc_page(GFP_NOIO);
+               if (info->bounce) {
+                       granted_page = alloc_page(GFP_NOIO | __GFP_ZERO);
                        if (!granted_page) {
                                kfree(gnt_list_entry);
                                goto out_of_memory;
@@ -330,7 +335,7 @@ out_of_memory:
        list_for_each_entry_safe(gnt_list_entry, n,
                                 &rinfo->grants, node) {
                list_del(&gnt_list_entry->node);
-               if (info->feature_persistent)
+               if (info->bounce)
                        __free_page(gnt_list_entry->page);
                kfree(gnt_list_entry);
                i--;
@@ -376,7 +381,7 @@ static struct grant *get_grant(grant_ref_t *gref_head,
        /* Assign a gref to this page */
        gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
        BUG_ON(gnt_list_entry->gref == -ENOSPC);
-       if (info->feature_persistent)
+       if (info->bounce)
                grant_foreign_access(gnt_list_entry, info);
        else {
                /* Grant access to the GFN passed by the caller */
@@ -400,7 +405,7 @@ static struct grant *get_indirect_grant(grant_ref_t *gref_head,
        /* Assign a gref to this page */
        gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
        BUG_ON(gnt_list_entry->gref == -ENOSPC);
-       if (!info->feature_persistent) {
+       if (!info->bounce) {
                struct page *indirect_page;
 
                /* Fetch a pre-allocated page to use for indirect grefs */
@@ -703,7 +708,7 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
                .grant_idx = 0,
                .segments = NULL,
                .rinfo = rinfo,
-               .need_copy = rq_data_dir(req) && info->feature_persistent,
+               .need_copy = rq_data_dir(req) && info->bounce,
        };
 
        /*
@@ -981,11 +986,12 @@ static void xlvbd_flush(struct blkfront_info *info)
 {
        blk_queue_write_cache(info->rq, info->feature_flush ? true : false,
                              info->feature_fua ? true : false);
-       pr_info("blkfront: %s: %s %s %s %s %s\n",
+       pr_info("blkfront: %s: %s %s %s %s %s %s %s\n",
                info->gd->disk_name, flush_info(info),
                "persistent grants:", info->feature_persistent ?
                "enabled;" : "disabled;", "indirect descriptors:",
-               info->max_indirect_segments ? "enabled;" : "disabled;");
+               info->max_indirect_segments ? "enabled;" : "disabled;",
+               "bounce buffer:", info->bounce ? "enabled" : "disabled;");
 }
 
 static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset)
@@ -1207,7 +1213,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
        if (!list_empty(&rinfo->indirect_pages)) {
                struct page *indirect_page, *n;
 
-               BUG_ON(info->feature_persistent);
+               BUG_ON(info->bounce);
                list_for_each_entry_safe(indirect_page, n, &rinfo->indirect_pages, lru) {
                        list_del(&indirect_page->lru);
                        __free_page(indirect_page);
@@ -1224,7 +1230,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
                                                          NULL);
                                rinfo->persistent_gnts_c--;
                        }
-                       if (info->feature_persistent)
+                       if (info->bounce)
                                __free_page(persistent_gnt->page);
                        kfree(persistent_gnt);
                }
@@ -1245,7 +1251,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
                for (j = 0; j < segs; j++) {
                        persistent_gnt = rinfo->shadow[i].grants_used[j];
                        gnttab_end_foreign_access(persistent_gnt->gref, NULL);
-                       if (info->feature_persistent)
+                       if (info->bounce)
                                __free_page(persistent_gnt->page);
                        kfree(persistent_gnt);
                }
@@ -1428,7 +1434,7 @@ static int blkif_completion(unsigned long *id,
        data.s = s;
        num_sg = s->num_sg;
 
-       if (bret->operation == BLKIF_OP_READ && info->feature_persistent) {
+       if (bret->operation == BLKIF_OP_READ && info->bounce) {
                for_each_sg(s->sg, sg, num_sg, i) {
                        BUG_ON(sg->offset + sg->length > PAGE_SIZE);
 
@@ -1487,7 +1493,7 @@ static int blkif_completion(unsigned long *id,
                                 * Add the used indirect page back to the list of
                                 * available pages for indirect grefs.
                                 */
-                               if (!info->feature_persistent) {
+                               if (!info->bounce) {
                                        indirect_page = s->indirect_grants[i]->page;
                                        list_add(&indirect_page->lru, &rinfo->indirect_pages);
                                }
@@ -1764,6 +1770,10 @@ static int talk_to_blkback(struct xenbus_device *dev,
        if (!info)
                return -ENODEV;
 
+       /* Check if backend is trusted. */
+       info->bounce = !xen_blkif_trusted ||
+                      !xenbus_read_unsigned(dev->nodename, "trusted", 1);
+
        max_page_order = xenbus_read_unsigned(info->xbdev->otherend,
                                              "max-ring-page-order", 0);
        ring_page_order = min(xen_blkif_max_ring_order, max_page_order);
@@ -2173,17 +2183,18 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
        if (err)
                goto out_of_memory;
 
-       if (!info->feature_persistent && info->max_indirect_segments) {
+       if (!info->bounce && info->max_indirect_segments) {
                /*
-                * We are using indirect descriptors but not persistent
-                * grants, we need to allocate a set of pages that can be
+                * We are using indirect descriptors but don't have a bounce
+                * buffer, we need to allocate a set of pages that can be
                 * used for mapping indirect grefs
                 */
                int num = INDIRECT_GREFS(grants) * BLK_RING_SIZE(info);
 
                BUG_ON(!list_empty(&rinfo->indirect_pages));
                for (i = 0; i < num; i++) {
-                       struct page *indirect_page = alloc_page(GFP_KERNEL);
+                       struct page *indirect_page = alloc_page(GFP_KERNEL |
+                                                               __GFP_ZERO);
                        if (!indirect_page)
                                goto out_of_memory;
                        list_add(&indirect_page->lru, &rinfo->indirect_pages);
@@ -2276,6 +2287,8 @@ static void blkfront_gather_backend_features(struct blkfront_info *info)
                info->feature_persistent =
                        !!xenbus_read_unsigned(info->xbdev->otherend,
                                               "feature-persistent", 0);
+       if (info->feature_persistent)
+               info->bounce = true;
 
        indirect_segments = xenbus_read_unsigned(info->xbdev->otherend,
                                        "feature-max-indirect-segments", 0);
@@ -2547,6 +2560,13 @@ static void blkfront_delay_work(struct work_struct *work)
        struct blkfront_info *info;
        bool need_schedule_work = false;
 
+       /*
+        * Note that when using bounce buffers but not persistent grants
+        * there's no need to run blkfront_delay_work because grants are
+        * revoked in blkif_completion or else an error is reported and the
+        * connection is closed.
+        */
+
        mutex_lock(&blkfront_mutex);
 
        list_for_each_entry(info, &info_list, info_list) {
index 0408701..e893815 100644 (file)
@@ -111,6 +111,7 @@ int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match,
        if (!reset_data)
                return -ENOMEM;
 
+       spin_lock_init(&reset_data->lock);
        reset_data->membase = base;
        reset_data->rcdev.owner = THIS_MODULE;
        reset_data->rcdev.ops = &stm32_reset_ops;
index 7be38bc..9ac75c1 100644 (file)
@@ -566,6 +566,28 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
+static int amd_pstate_cpu_resume(struct cpufreq_policy *policy)
+{
+       int ret;
+
+       ret = amd_pstate_enable(true);
+       if (ret)
+               pr_err("failed to enable amd-pstate during resume, return %d\n", ret);
+
+       return ret;
+}
+
+static int amd_pstate_cpu_suspend(struct cpufreq_policy *policy)
+{
+       int ret;
+
+       ret = amd_pstate_enable(false);
+       if (ret)
+               pr_err("failed to disable amd-pstate during suspend, return %d\n", ret);
+
+       return ret;
+}
+
 /* Sysfs attributes */
 
 /*
@@ -636,6 +658,8 @@ static struct cpufreq_driver amd_pstate_driver = {
        .target         = amd_pstate_target,
        .init           = amd_pstate_cpu_init,
        .exit           = amd_pstate_cpu_exit,
+       .suspend        = amd_pstate_cpu_suspend,
+       .resume         = amd_pstate_cpu_resume,
        .set_boost      = amd_pstate_set_boost,
        .name           = "amd-pstate",
        .attr           = amd_pstate_attr,
index 96de153..2c96de3 100644 (file)
@@ -127,6 +127,7 @@ static const struct of_device_id blocklist[] __initconst = {
        { .compatible = "mediatek,mt8173", },
        { .compatible = "mediatek,mt8176", },
        { .compatible = "mediatek,mt8183", },
+       { .compatible = "mediatek,mt8186", },
        { .compatible = "mediatek,mt8365", },
        { .compatible = "mediatek,mt8516", },
 
index 20f64a8..4b8ee20 100644 (file)
@@ -470,6 +470,10 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
        if (slew_done_gpio_np)
                slew_done_gpio = read_gpio(slew_done_gpio_np);
 
+       of_node_put(volt_gpio_np);
+       of_node_put(freq_gpio_np);
+       of_node_put(slew_done_gpio_np);
+
        /* If we use the frequency GPIOs, calculate the min/max speeds based
         * on the bus frequencies
         */
index 0253731..36c7958 100644 (file)
@@ -442,6 +442,9 @@ static int qcom_cpufreq_hw_cpu_online(struct cpufreq_policy *policy)
        struct platform_device *pdev = cpufreq_get_driver_data();
        int ret;
 
+       if (data->throttle_irq <= 0)
+               return 0;
+
        ret = irq_set_affinity_hint(data->throttle_irq, policy->cpus);
        if (ret)
                dev_err(&pdev->dev, "Failed to set CPU affinity of %s[%d]\n",
@@ -469,6 +472,9 @@ static int qcom_cpufreq_hw_cpu_offline(struct cpufreq_policy *policy)
 
 static void qcom_cpufreq_hw_lmh_exit(struct qcom_cpufreq_data *data)
 {
+       if (data->throttle_irq <= 0)
+               return;
+
        free_irq(data->throttle_irq, data);
 }
 
index 6b6b20d..573b417 100644 (file)
@@ -275,6 +275,7 @@ static int qoriq_cpufreq_probe(struct platform_device *pdev)
 
        np = of_find_matching_node(NULL, qoriq_cpufreq_blacklist);
        if (np) {
+               of_node_put(np);
                dev_info(&pdev->dev, "Disabling due to erratum A-008083");
                return -ENODEV;
        }
index ee99c02..3e6aa31 100644 (file)
@@ -133,98 +133,6 @@ config CRYPTO_PAES_S390
          Select this option if you want to use the paes cipher
          for example to use protected key encrypted devices.
 
-config CRYPTO_SHA1_S390
-       tristate "SHA1 digest algorithm"
-       depends on S390
-       select CRYPTO_HASH
-       help
-         This is the s390 hardware accelerated implementation of the
-         SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
-
-         It is available as of z990.
-
-config CRYPTO_SHA256_S390
-       tristate "SHA256 digest algorithm"
-       depends on S390
-       select CRYPTO_HASH
-       help
-         This is the s390 hardware accelerated implementation of the
-         SHA256 secure hash standard (DFIPS 180-2).
-
-         It is available as of z9.
-
-config CRYPTO_SHA512_S390
-       tristate "SHA384 and SHA512 digest algorithm"
-       depends on S390
-       select CRYPTO_HASH
-       help
-         This is the s390 hardware accelerated implementation of the
-         SHA512 secure hash standard.
-
-         It is available as of z10.
-
-config CRYPTO_SHA3_256_S390
-       tristate "SHA3_224 and SHA3_256 digest algorithm"
-       depends on S390
-       select CRYPTO_HASH
-       help
-         This is the s390 hardware accelerated implementation of the
-         SHA3_256 secure hash standard.
-
-         It is available as of z14.
-
-config CRYPTO_SHA3_512_S390
-       tristate "SHA3_384 and SHA3_512 digest algorithm"
-       depends on S390
-       select CRYPTO_HASH
-       help
-         This is the s390 hardware accelerated implementation of the
-         SHA3_512 secure hash standard.
-
-         It is available as of z14.
-
-config CRYPTO_DES_S390
-       tristate "DES and Triple DES cipher algorithms"
-       depends on S390
-       select CRYPTO_ALGAPI
-       select CRYPTO_SKCIPHER
-       select CRYPTO_LIB_DES
-       help
-         This is the s390 hardware accelerated implementation of the
-         DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
-
-         As of z990 the ECB and CBC mode are hardware accelerated.
-         As of z196 the CTR mode is hardware accelerated.
-
-config CRYPTO_AES_S390
-       tristate "AES cipher algorithms"
-       depends on S390
-       select CRYPTO_ALGAPI
-       select CRYPTO_SKCIPHER
-       help
-         This is the s390 hardware accelerated implementation of the
-         AES cipher algorithms (FIPS-197).
-
-         As of z9 the ECB and CBC modes are hardware accelerated
-         for 128 bit keys.
-         As of z10 the ECB and CBC modes are hardware accelerated
-         for all AES key sizes.
-         As of z196 the CTR mode is hardware accelerated for all AES
-         key sizes and XTS mode is hardware accelerated for 256 and
-         512 bit keys.
-
-config CRYPTO_CHACHA_S390
-       tristate "ChaCha20 stream cipher"
-       depends on S390
-       select CRYPTO_SKCIPHER
-       select CRYPTO_LIB_CHACHA_GENERIC
-       select CRYPTO_ARCH_HAVE_LIB_CHACHA
-       help
-         This is the s390 SIMD implementation of the ChaCha20 stream
-         cipher (RFC 7539).
-
-         It is available as of z13.
-
 config S390_PRNG
        tristate "Pseudo random number generator device driver"
        depends on S390
@@ -238,29 +146,6 @@ config S390_PRNG
 
          It is available as of z9.
 
-config CRYPTO_GHASH_S390
-       tristate "GHASH hash function"
-       depends on S390
-       select CRYPTO_HASH
-       help
-         This is the s390 hardware accelerated implementation of GHASH,
-         the hash function used in GCM (Galois/Counter mode).
-
-         It is available as of z196.
-
-config CRYPTO_CRC32_S390
-       tristate "CRC-32 algorithms"
-       depends on S390
-       select CRYPTO_HASH
-       select CRC32
-       help
-         Select this option if you want to use hardware accelerated
-         implementations of CRC algorithms.  With this option, you
-         can optimize the computation of CRC-32 (IEEE 802.3 Ethernet)
-         and CRC-32C (Castagnoli).
-
-         It is available with IBM z13 or later.
-
 config CRYPTO_DEV_NIAGARA2
        tristate "Niagara2 Stream Processing Unit driver"
        select CRYPTO_LIB_DES
index 9dba52f..7d79a87 100644 (file)
@@ -85,17 +85,9 @@ static int sp_get_irqs(struct sp_device *sp)
        struct sp_platform *sp_platform = sp->dev_specific;
        struct device *dev = sp->dev;
        struct platform_device *pdev = to_platform_device(dev);
-       unsigned int i, count;
        int ret;
 
-       for (i = 0, count = 0; i < pdev->num_resources; i++) {
-               struct resource *res = &pdev->resource[i];
-
-               if (resource_type(res) == IORESOURCE_IRQ)
-                       count++;
-       }
-
-       sp_platform->irq_count = count;
+       sp_platform->irq_count = platform_irq_count(pdev);
 
        ret = platform_get_irq(pdev, 0);
        if (ret < 0) {
@@ -104,7 +96,7 @@ static int sp_get_irqs(struct sp_device *sp)
        }
 
        sp->psp_irq = ret;
-       if (count == 1) {
+       if (sp_platform->irq_count == 1) {
                sp->ccp_irq = ret;
        } else {
                ret = platform_get_irq(pdev, 1);
index 0e89a7a..bfc8ee8 100644 (file)
@@ -197,7 +197,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
        else
                cxld->target_type = CXL_DECODER_ACCELERATOR;
 
-       if (is_cxl_endpoint(to_cxl_port(cxld->dev.parent)))
+       if (is_endpoint_decoder(&cxld->dev))
                return 0;
 
        target_list.value =
index 54f4347..cbf23be 100644 (file)
@@ -355,11 +355,13 @@ static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd,
                return -EBUSY;
 
        /* Check the input buffer is the expected size */
-       if (info->size_in != send_cmd->in.size)
+       if ((info->size_in != CXL_VARIABLE_PAYLOAD) &&
+           (info->size_in != send_cmd->in.size))
                return -ENOMEM;
 
        /* Check the output buffer is at least large enough */
-       if (send_cmd->out.size < info->size_out)
+       if ((info->size_out != CXL_VARIABLE_PAYLOAD) &&
+           (send_cmd->out.size < info->size_out))
                return -ENOMEM;
 
        *mem_cmd = (struct cxl_mem_command) {
index ea60abd..dbce99b 100644 (file)
@@ -272,7 +272,7 @@ static const struct device_type cxl_decoder_root_type = {
        .groups = cxl_decoder_root_attribute_groups,
 };
 
-static bool is_endpoint_decoder(struct device *dev)
+bool is_endpoint_decoder(struct device *dev)
 {
        return dev->type == &cxl_decoder_endpoint_type;
 }
index 140dc32..6799b27 100644 (file)
@@ -340,6 +340,7 @@ struct cxl_dport *cxl_find_dport_by_dev(struct cxl_port *port,
 
 struct cxl_decoder *to_cxl_decoder(struct device *dev);
 bool is_root_decoder(struct device *dev);
+bool is_endpoint_decoder(struct device *dev);
 bool is_cxl_decoder(struct device *dev);
 struct cxl_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
                                           unsigned int nr_targets);
index 60d10ee..7df0b05 100644 (file)
@@ -300,13 +300,13 @@ struct cxl_mbox_identify {
 } __packed;
 
 struct cxl_mbox_get_lsa {
-       u32 offset;
-       u32 length;
+       __le32 offset;
+       __le32 length;
 } __packed;
 
 struct cxl_mbox_set_lsa {
-       u32 offset;
-       u32 reserved;
+       __le32 offset;
+       __le32 reserved;
        u8 data[];
 } __packed;
 
index c310f1f..a979d0b 100644 (file)
@@ -29,6 +29,7 @@ static int create_endpoint(struct cxl_memdev *cxlmd,
 {
        struct cxl_dev_state *cxlds = cxlmd->cxlds;
        struct cxl_port *endpoint;
+       int rc;
 
        endpoint = devm_cxl_add_port(&parent_port->dev, &cxlmd->dev,
                                     cxlds->component_reg_phys, parent_port);
@@ -37,13 +38,17 @@ static int create_endpoint(struct cxl_memdev *cxlmd,
 
        dev_dbg(&cxlmd->dev, "add: %s\n", dev_name(&endpoint->dev));
 
+       rc = cxl_endpoint_autoremove(cxlmd, endpoint);
+       if (rc)
+               return rc;
+
        if (!endpoint->dev.driver) {
                dev_err(&cxlmd->dev, "%s failed probe\n",
                        dev_name(&endpoint->dev));
                return -ENXIO;
        }
 
-       return cxl_endpoint_autoremove(cxlmd, endpoint);
+       return 0;
 }
 
 static void enable_suspend(void *data)
index bbeef91..0aaa70b 100644 (file)
@@ -108,8 +108,8 @@ static int cxl_pmem_get_config_data(struct cxl_dev_state *cxlds,
                return -EINVAL;
 
        get_lsa = (struct cxl_mbox_get_lsa) {
-               .offset = cmd->in_offset,
-               .length = cmd->in_length,
+               .offset = cpu_to_le32(cmd->in_offset),
+               .length = cpu_to_le32(cmd->in_length),
        };
 
        rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_GET_LSA, &get_lsa,
@@ -139,7 +139,7 @@ static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds,
                return -ENOMEM;
 
        *set_lsa = (struct cxl_mbox_set_lsa) {
-               .offset = cmd->in_offset,
+               .offset = cpu_to_le32(cmd->in_offset),
        };
        memcpy(set_lsa->data, cmd->in_buf, cmd->in_length);
 
index 01474da..9602141 100644 (file)
@@ -123,7 +123,7 @@ void devfreq_get_freq_range(struct devfreq *devfreq,
                            unsigned long *min_freq,
                            unsigned long *max_freq)
 {
-       unsigned long *freq_table = devfreq->profile->freq_table;
+       unsigned long *freq_table = devfreq->freq_table;
        s32 qos_min_freq, qos_max_freq;
 
        lockdep_assert_held(&devfreq->lock);
@@ -133,11 +133,11 @@ void devfreq_get_freq_range(struct devfreq *devfreq,
         * The devfreq drivers can initialize this in either ascending or
         * descending order and devfreq core supports both.
         */
-       if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) {
+       if (freq_table[0] < freq_table[devfreq->max_state - 1]) {
                *min_freq = freq_table[0];
-               *max_freq = freq_table[devfreq->profile->max_state - 1];
+               *max_freq = freq_table[devfreq->max_state - 1];
        } else {
-               *min_freq = freq_table[devfreq->profile->max_state - 1];
+               *min_freq = freq_table[devfreq->max_state - 1];
                *max_freq = freq_table[0];
        }
 
@@ -169,8 +169,8 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
 {
        int lev;
 
-       for (lev = 0; lev < devfreq->profile->max_state; lev++)
-               if (freq == devfreq->profile->freq_table[lev])
+       for (lev = 0; lev < devfreq->max_state; lev++)
+               if (freq == devfreq->freq_table[lev])
                        return lev;
 
        return -EINVAL;
@@ -178,7 +178,6 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
 
 static int set_freq_table(struct devfreq *devfreq)
 {
-       struct devfreq_dev_profile *profile = devfreq->profile;
        struct dev_pm_opp *opp;
        unsigned long freq;
        int i, count;
@@ -188,25 +187,22 @@ static int set_freq_table(struct devfreq *devfreq)
        if (count <= 0)
                return -EINVAL;
 
-       profile->max_state = count;
-       profile->freq_table = devm_kcalloc(devfreq->dev.parent,
-                                       profile->max_state,
-                                       sizeof(*profile->freq_table),
-                                       GFP_KERNEL);
-       if (!profile->freq_table) {
-               profile->max_state = 0;
+       devfreq->max_state = count;
+       devfreq->freq_table = devm_kcalloc(devfreq->dev.parent,
+                                          devfreq->max_state,
+                                          sizeof(*devfreq->freq_table),
+                                          GFP_KERNEL);
+       if (!devfreq->freq_table)
                return -ENOMEM;
-       }
 
-       for (i = 0, freq = 0; i < profile->max_state; i++, freq++) {
+       for (i = 0, freq = 0; i < devfreq->max_state; i++, freq++) {
                opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
                if (IS_ERR(opp)) {
-                       devm_kfree(devfreq->dev.parent, profile->freq_table);
-                       profile->max_state = 0;
+                       devm_kfree(devfreq->dev.parent, devfreq->freq_table);
                        return PTR_ERR(opp);
                }
                dev_pm_opp_put(opp);
-               profile->freq_table[i] = freq;
+               devfreq->freq_table[i] = freq;
        }
 
        return 0;
@@ -246,7 +242,7 @@ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
 
        if (lev != prev_lev) {
                devfreq->stats.trans_table[
-                       (prev_lev * devfreq->profile->max_state) + lev]++;
+                       (prev_lev * devfreq->max_state) + lev]++;
                devfreq->stats.total_trans++;
        }
 
@@ -835,6 +831,9 @@ struct devfreq *devfreq_add_device(struct device *dev,
                if (err < 0)
                        goto err_dev;
                mutex_lock(&devfreq->lock);
+       } else {
+               devfreq->freq_table = devfreq->profile->freq_table;
+               devfreq->max_state = devfreq->profile->max_state;
        }
 
        devfreq->scaling_min_freq = find_available_min_freq(devfreq);
@@ -870,8 +869,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
 
        devfreq->stats.trans_table = devm_kzalloc(&devfreq->dev,
                        array3_size(sizeof(unsigned int),
-                                   devfreq->profile->max_state,
-                                   devfreq->profile->max_state),
+                                   devfreq->max_state,
+                                   devfreq->max_state),
                        GFP_KERNEL);
        if (!devfreq->stats.trans_table) {
                mutex_unlock(&devfreq->lock);
@@ -880,7 +879,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
        }
 
        devfreq->stats.time_in_state = devm_kcalloc(&devfreq->dev,
-                       devfreq->profile->max_state,
+                       devfreq->max_state,
                        sizeof(*devfreq->stats.time_in_state),
                        GFP_KERNEL);
        if (!devfreq->stats.time_in_state) {
@@ -932,8 +931,9 @@ struct devfreq *devfreq_add_device(struct device *dev,
        err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
                                                NULL);
        if (err) {
-               dev_err(dev, "%s: Unable to start governor for the device\n",
-                       __func__);
+               dev_err_probe(dev, err,
+                       "%s: Unable to start governor for the device\n",
+                        __func__);
                goto err_init;
        }
        create_sysfs_files(devfreq, devfreq->governor);
@@ -1665,9 +1665,9 @@ static ssize_t available_frequencies_show(struct device *d,
 
        mutex_lock(&df->lock);
 
-       for (i = 0; i < df->profile->max_state; i++)
+       for (i = 0; i < df->max_state; i++)
                count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
-                               "%lu ", df->profile->freq_table[i]);
+                               "%lu ", df->freq_table[i]);
 
        mutex_unlock(&df->lock);
        /* Truncate the trailing space */
@@ -1690,7 +1690,7 @@ static ssize_t trans_stat_show(struct device *dev,
 
        if (!df->profile)
                return -EINVAL;
-       max_state = df->profile->max_state;
+       max_state = df->max_state;
 
        if (max_state == 0)
                return sprintf(buf, "Not Supported.\n");
@@ -1707,19 +1707,17 @@ static ssize_t trans_stat_show(struct device *dev,
        len += sprintf(buf + len, "           :");
        for (i = 0; i < max_state; i++)
                len += sprintf(buf + len, "%10lu",
-                               df->profile->freq_table[i]);
+                               df->freq_table[i]);
 
        len += sprintf(buf + len, "   time(ms)\n");
 
        for (i = 0; i < max_state; i++) {
-               if (df->profile->freq_table[i]
-                                       == df->previous_freq) {
+               if (df->freq_table[i] == df->previous_freq)
                        len += sprintf(buf + len, "*");
-               } else {
+               else
                        len += sprintf(buf + len, " ");
-               }
-               len += sprintf(buf + len, "%10lu:",
-                               df->profile->freq_table[i]);
+
+               len += sprintf(buf + len, "%10lu:", df->freq_table[i]);
                for (j = 0; j < max_state; j++)
                        len += sprintf(buf + len, "%10u",
                                df->stats.trans_table[(i * max_state) + j]);
@@ -1743,7 +1741,7 @@ static ssize_t trans_stat_store(struct device *dev,
        if (!df->profile)
                return -EINVAL;
 
-       if (df->profile->max_state == 0)
+       if (df->max_state == 0)
                return count;
 
        err = kstrtoint(buf, 10, &value);
@@ -1751,11 +1749,11 @@ static ssize_t trans_stat_store(struct device *dev,
                return -EINVAL;
 
        mutex_lock(&df->lock);
-       memset(df->stats.time_in_state, 0, (df->profile->max_state *
+       memset(df->stats.time_in_state, 0, (df->max_state *
                                        sizeof(*df->stats.time_in_state)));
        memset(df->stats.trans_table, 0, array3_size(sizeof(unsigned int),
-                                       df->profile->max_state,
-                                       df->profile->max_state));
+                                       df->max_state,
+                                       df->max_state));
        df->stats.total_trans = 0;
        df->stats.last_update = get_jiffies_64();
        mutex_unlock(&df->lock);
index 9b849d7..a443e7c 100644 (file)
@@ -519,15 +519,19 @@ static int of_get_devfreq_events(struct device_node *np,
 
        count = of_get_child_count(events_np);
        desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL);
-       if (!desc)
+       if (!desc) {
+               of_node_put(events_np);
                return -ENOMEM;
+       }
        info->num_events = count;
 
        of_id = of_match_device(exynos_ppmu_id_match, dev);
        if (of_id)
                info->ppmu_type = (enum exynos_ppmu_type)of_id->data;
-       else
+       else {
+               of_node_put(events_np);
                return -EINVAL;
+       }
 
        j = 0;
        for_each_child_of_node(events_np, node) {
index e689101..f7dcc44 100644 (file)
@@ -447,9 +447,9 @@ static int exynos_bus_probe(struct platform_device *pdev)
                }
        }
 
-       max_state = bus->devfreq->profile->max_state;
-       min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
-       max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
+       max_state = bus->devfreq->max_state;
+       min_freq = (bus->devfreq->freq_table[0] / 1000);
+       max_freq = (bus->devfreq->freq_table[max_state - 1] / 1000);
        pr_info("exynos-bus: new bus device registered: %s (%6ld KHz ~ %6ld KHz)\n",
                        dev_name(dev), min_freq, max_freq);
 
index 72c6797..953cf9a 100644 (file)
@@ -1,4 +1,4 @@
-       // SPDX-License-Identifier: GPL-2.0-only
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * linux/drivers/devfreq/governor_passive.c
  *
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/devfreq.h>
+#include <linux/units.h>
 #include "governor.h"
 
-#define HZ_PER_KHZ     1000
-
 static struct devfreq_cpu_data *
 get_parent_cpu_data(struct devfreq_passive_data *p_data,
                    struct cpufreq_policy *policy)
@@ -34,6 +33,20 @@ get_parent_cpu_data(struct devfreq_passive_data *p_data,
        return NULL;
 }
 
+static void delete_parent_cpu_data(struct devfreq_passive_data *p_data)
+{
+       struct devfreq_cpu_data *parent_cpu_data, *tmp;
+
+       list_for_each_entry_safe(parent_cpu_data, tmp, &p_data->cpu_data_list, node) {
+               list_del(&parent_cpu_data->node);
+
+               if (parent_cpu_data->opp_table)
+                       dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
+
+               kfree(parent_cpu_data);
+       }
+}
+
 static unsigned long get_target_freq_by_required_opp(struct device *p_dev,
                                                struct opp_table *p_opp_table,
                                                struct opp_table *opp_table,
@@ -131,18 +144,18 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq,
                goto out;
 
        /* Use interpolation if required opps is not available */
-       for (i = 0; i < parent_devfreq->profile->max_state; i++)
-               if (parent_devfreq->profile->freq_table[i] == *freq)
+       for (i = 0; i < parent_devfreq->max_state; i++)
+               if (parent_devfreq->freq_table[i] == *freq)
                        break;
 
-       if (i == parent_devfreq->profile->max_state)
+       if (i == parent_devfreq->max_state)
                return -EINVAL;
 
-       if (i < devfreq->profile->max_state) {
-               child_freq = devfreq->profile->freq_table[i];
+       if (i < devfreq->max_state) {
+               child_freq = devfreq->freq_table[i];
        } else {
-               count = devfreq->profile->max_state;
-               child_freq = devfreq->profile->freq_table[count - 1];
+               count = devfreq->max_state;
+               child_freq = devfreq->freq_table[count - 1];
        }
 
 out:
@@ -222,8 +235,7 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
 {
        struct devfreq_passive_data *p_data
                        = (struct devfreq_passive_data *)devfreq->data;
-       struct devfreq_cpu_data *parent_cpu_data;
-       int cpu, ret = 0;
+       int ret;
 
        if (p_data->nb.notifier_call) {
                ret = cpufreq_unregister_notifier(&p_data->nb,
@@ -232,27 +244,9 @@ static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
                        return ret;
        }
 
-       for_each_possible_cpu(cpu) {
-               struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-               if (!policy) {
-                       ret = -EINVAL;
-                       continue;
-               }
-
-               parent_cpu_data = get_parent_cpu_data(p_data, policy);
-               if (!parent_cpu_data) {
-                       cpufreq_cpu_put(policy);
-                       continue;
-               }
+       delete_parent_cpu_data(p_data);
 
-               list_del(&parent_cpu_data->node);
-               if (parent_cpu_data->opp_table)
-                       dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
-               kfree(parent_cpu_data);
-               cpufreq_cpu_put(policy);
-       }
-
-       return ret;
+       return 0;
 }
 
 static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
@@ -336,7 +330,6 @@ err_free_cpu_data:
 err_put_policy:
        cpufreq_cpu_put(policy);
 err:
-       WARN_ON(cpufreq_passive_unregister_notifier(devfreq));
 
        return ret;
 }
@@ -407,8 +400,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq,
        if (!p_data)
                return -EINVAL;
 
-       if (!p_data->this)
-               p_data->this = devfreq;
+       p_data->this = devfreq;
 
        switch (event) {
        case DEVFREQ_GOV_START:
index 3e9d726..7b3e603 100644 (file)
@@ -1900,6 +1900,11 @@ static int at_xdmac_alloc_chan_resources(struct dma_chan *chan)
        for (i = 0; i < init_nr_desc_per_channel; i++) {
                desc = at_xdmac_alloc_desc(chan, GFP_KERNEL);
                if (!desc) {
+                       if (i == 0) {
+                               dev_warn(chan2dev(chan),
+                                        "can't allocate any descriptors\n");
+                               return -EIO;
+                       }
                        dev_warn(chan2dev(chan),
                                "only %d descriptors have been allocated\n", i);
                        break;
index 0a2168a..f696246 100644 (file)
@@ -675,16 +675,10 @@ static int dmatest_func(void *data)
        /*
         * src and dst buffers are freed by ourselves below
         */
-       if (params->polled) {
+       if (params->polled)
                flags = DMA_CTRL_ACK;
-       } else {
-               if (dma_has_cap(DMA_INTERRUPT, dev->cap_mask)) {
-                       flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
-               } else {
-                       pr_err("Channel does not support interrupt!\n");
-                       goto err_pq_array;
-               }
-       }
+       else
+               flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
 
        ktime = ktime_get();
        while (!(kthread_should_stop() ||
@@ -912,7 +906,6 @@ error_unmap_continue:
        runtime = ktime_to_us(ktime);
 
        ret = 0;
-err_pq_array:
        kfree(dma_pq);
 err_srcs_array:
        kfree(srcs);
index e9c9bcb..c741da0 100644 (file)
@@ -1164,8 +1164,9 @@ static int dma_chan_pause(struct dma_chan *dchan)
                        BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
                axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
        } else {
-               val = BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
-                     BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
+               val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
+               val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
+                       BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
                axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
        }
 
@@ -1190,12 +1191,13 @@ static inline void axi_chan_resume(struct axi_dma_chan *chan)
 {
        u32 val;
 
-       val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
        if (chan->chip->dw->hdata->reg_map_8_channels) {
+               val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
                val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
                val |=  (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
                axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
        } else {
+               val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
                val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
                val |=  (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
                axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
index ff0ea60..5a8cc52 100644 (file)
@@ -716,10 +716,7 @@ static void idxd_device_wqs_clear_state(struct idxd_device *idxd)
                struct idxd_wq *wq = idxd->wqs[i];
 
                mutex_lock(&wq->wq_lock);
-               if (wq->state == IDXD_WQ_ENABLED) {
-                       idxd_wq_disable_cleanup(wq);
-                       wq->state = IDXD_WQ_DISABLED;
-               }
+               idxd_wq_disable_cleanup(wq);
                idxd_wq_device_reset_cleanup(wq);
                mutex_unlock(&wq->wq_lock);
        }
index 355fb3e..aa34782 100644 (file)
@@ -512,15 +512,16 @@ static int idxd_probe(struct idxd_device *idxd)
        dev_dbg(dev, "IDXD reset complete\n");
 
        if (IS_ENABLED(CONFIG_INTEL_IDXD_SVM) && sva) {
-               if (iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA))
+               if (iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA)) {
                        dev_warn(dev, "Unable to turn on user SVA feature.\n");
-               else
+               } else {
                        set_bit(IDXD_FLAG_USER_PASID_ENABLED, &idxd->flags);
 
-               if (idxd_enable_system_pasid(idxd))
-                       dev_warn(dev, "No in-kernel DMA with PASID.\n");
-               else
-                       set_bit(IDXD_FLAG_PASID_ENABLED, &idxd->flags);
+                       if (idxd_enable_system_pasid(idxd))
+                               dev_warn(dev, "No in-kernel DMA with PASID.\n");
+                       else
+                               set_bit(IDXD_FLAG_PASID_ENABLED, &idxd->flags);
+               }
        } else if (!sva) {
                dev_warn(dev, "User forced SVA off via module param.\n");
        }
index 8535018..f37a276 100644 (file)
@@ -891,7 +891,7 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
         * SDMA stops cyclic channel when DMA request triggers a channel and no SDMA
         * owned buffer is available (i.e. BD_DONE was set too late).
         */
-       if (!is_sdma_channel_enabled(sdmac->sdma, sdmac->channel)) {
+       if (sdmac->desc && !is_sdma_channel_enabled(sdmac->sdma, sdmac->channel)) {
                dev_warn(sdmac->sdma->dev, "restart cyclic channel %d\n", sdmac->channel);
                sdma_enable_channel(sdmac->sdma, sdmac->channel);
        }
@@ -2346,7 +2346,7 @@ MODULE_DESCRIPTION("i.MX SDMA driver");
 #if IS_ENABLED(CONFIG_SOC_IMX6Q)
 MODULE_FIRMWARE("imx/sdma/sdma-imx6q.bin");
 #endif
-#if IS_ENABLED(CONFIG_SOC_IMX7D)
+#if IS_ENABLED(CONFIG_SOC_IMX7D) || IS_ENABLED(CONFIG_SOC_IMX8M)
 MODULE_FIRMWARE("imx/sdma/sdma-imx7d.bin");
 #endif
 MODULE_LICENSE("GPL");
index efe8bd3..9b9184f 100644 (file)
@@ -1593,11 +1593,12 @@ static int intel_ldma_probe(struct platform_device *pdev)
        d->core_clk = devm_clk_get_optional(dev, NULL);
        if (IS_ERR(d->core_clk))
                return PTR_ERR(d->core_clk);
-       clk_prepare_enable(d->core_clk);
 
        d->rst = devm_reset_control_get_optional(dev, NULL);
        if (IS_ERR(d->rst))
                return PTR_ERR(d->rst);
+
+       clk_prepare_enable(d->core_clk);
        reset_control_deassert(d->rst);
 
        ret = devm_add_action_or_reset(dev, ldma_clk_disable, d);
index 858400e..09915a5 100644 (file)
@@ -2589,7 +2589,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
 
        /* If the DMAC pool is empty, alloc new */
        if (!desc) {
-               DEFINE_SPINLOCK(lock);
+               static DEFINE_SPINLOCK(lock);
                LIST_HEAD(pool);
 
                if (!add_desc(&pool, &lock, GFP_ATOMIC, 1))
index 87f6ca1..2ff787d 100644 (file)
@@ -558,14 +558,6 @@ static int bam_alloc_chan(struct dma_chan *chan)
        return 0;
 }
 
-static int bam_pm_runtime_get_sync(struct device *dev)
-{
-       if (pm_runtime_enabled(dev))
-               return pm_runtime_get_sync(dev);
-
-       return 0;
-}
-
 /**
  * bam_free_chan - Frees dma resources associated with specific channel
  * @chan: specified channel
@@ -581,7 +573,7 @@ static void bam_free_chan(struct dma_chan *chan)
        unsigned long flags;
        int ret;
 
-       ret = bam_pm_runtime_get_sync(bdev->dev);
+       ret = pm_runtime_get_sync(bdev->dev);
        if (ret < 0)
                return;
 
@@ -784,7 +776,7 @@ static int bam_pause(struct dma_chan *chan)
        unsigned long flag;
        int ret;
 
-       ret = bam_pm_runtime_get_sync(bdev->dev);
+       ret = pm_runtime_get_sync(bdev->dev);
        if (ret < 0)
                return ret;
 
@@ -810,7 +802,7 @@ static int bam_resume(struct dma_chan *chan)
        unsigned long flag;
        int ret;
 
-       ret = bam_pm_runtime_get_sync(bdev->dev);
+       ret = pm_runtime_get_sync(bdev->dev);
        if (ret < 0)
                return ret;
 
@@ -919,7 +911,7 @@ static irqreturn_t bam_dma_irq(int irq, void *data)
        if (srcs & P_IRQ)
                tasklet_schedule(&bdev->task);
 
-       ret = bam_pm_runtime_get_sync(bdev->dev);
+       ret = pm_runtime_get_sync(bdev->dev);
        if (ret < 0)
                return IRQ_NONE;
 
@@ -1037,7 +1029,7 @@ static void bam_start_dma(struct bam_chan *bchan)
        if (!vd)
                return;
 
-       ret = bam_pm_runtime_get_sync(bdev->dev);
+       ret = pm_runtime_get_sync(bdev->dev);
        if (ret < 0)
                return;
 
@@ -1374,11 +1366,6 @@ static int bam_dma_probe(struct platform_device *pdev)
        if (ret)
                goto err_unregister_dma;
 
-       if (!bdev->bamclk) {
-               pm_runtime_disable(&pdev->dev);
-               return 0;
-       }
-
        pm_runtime_irq_safe(&pdev->dev);
        pm_runtime_set_autosuspend_delay(&pdev->dev, BAM_DMA_AUTOSUSPEND_DELAY);
        pm_runtime_use_autosuspend(&pdev->dev);
@@ -1462,10 +1449,8 @@ static int __maybe_unused bam_dma_suspend(struct device *dev)
 {
        struct bam_device *bdev = dev_get_drvdata(dev);
 
-       if (bdev->bamclk) {
-               pm_runtime_force_suspend(dev);
-               clk_unprepare(bdev->bamclk);
-       }
+       pm_runtime_force_suspend(dev);
+       clk_unprepare(bdev->bamclk);
 
        return 0;
 }
@@ -1475,13 +1460,11 @@ static int __maybe_unused bam_dma_resume(struct device *dev)
        struct bam_device *bdev = dev_get_drvdata(dev);
        int ret;
 
-       if (bdev->bamclk) {
-               ret = clk_prepare(bdev->bamclk);
-               if (ret)
-                       return ret;
+       ret = clk_prepare(bdev->bamclk);
+       if (ret)
+               return ret;
 
-               pm_runtime_force_resume(dev);
-       }
+       pm_runtime_force_resume(dev);
 
        return 0;
 }
index 71d24fc..f744ddb 100644 (file)
@@ -245,6 +245,7 @@ static void *ti_dra7_xbar_route_allocate(struct of_phandle_args *dma_spec,
        if (dma_spec->args[0] >= xbar->xbar_requests) {
                dev_err(&pdev->dev, "Invalid XBAR request number: %d\n",
                        dma_spec->args[0]);
+               put_device(&pdev->dev);
                return ERR_PTR(-EINVAL);
        }
 
@@ -252,12 +253,14 @@ static void *ti_dra7_xbar_route_allocate(struct of_phandle_args *dma_spec,
        dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
        if (!dma_spec->np) {
                dev_err(&pdev->dev, "Can't get DMA master\n");
+               put_device(&pdev->dev);
                return ERR_PTR(-EINVAL);
        }
 
        map = kzalloc(sizeof(*map), GFP_KERNEL);
        if (!map) {
                of_node_put(dma_spec->np);
+               put_device(&pdev->dev);
                return ERR_PTR(-ENOMEM);
        }
 
@@ -268,6 +271,8 @@ static void *ti_dra7_xbar_route_allocate(struct of_phandle_args *dma_spec,
                mutex_unlock(&xbar->mutex);
                dev_err(&pdev->dev, "Run out of free DMA requests\n");
                kfree(map);
+               of_node_put(dma_spec->np);
+               put_device(&pdev->dev);
                return ERR_PTR(-ENOMEM);
        }
        set_bit(map->xbar_out, xbar->dma_inuse);
index f6fe723..d4e2310 100644 (file)
@@ -181,7 +181,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol,
                return NULL;
        }
 
-       id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
+       id = ida_alloc_min(&scmi_bus_id, 1, GFP_KERNEL);
        if (id < 0) {
                kfree_const(scmi_dev->name);
                kfree(scmi_dev);
@@ -204,7 +204,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol,
 put_dev:
        kfree_const(scmi_dev->name);
        put_device(&scmi_dev->dev);
-       ida_simple_remove(&scmi_bus_id, id);
+       ida_free(&scmi_bus_id, id);
        return NULL;
 }
 
@@ -212,7 +212,7 @@ void scmi_device_destroy(struct scmi_device *scmi_dev)
 {
        kfree_const(scmi_dev->name);
        scmi_handle_put(scmi_dev->handle);
-       ida_simple_remove(&scmi_bus_id, scmi_dev->id);
+       ida_free(&scmi_bus_id, scmi_dev->id);
        device_unregister(&scmi_dev->dev);
 }
 
index c7a83f6..3ed7ae0 100644 (file)
@@ -194,6 +194,7 @@ static int rate_cmp_func(const void *_r1, const void *_r2)
 }
 
 struct scmi_clk_ipriv {
+       struct device *dev;
        u32 clk_id;
        struct scmi_clock_info *clk;
 };
@@ -223,6 +224,29 @@ iter_clk_describe_update_state(struct scmi_iterator_state *st,
        st->num_returned = NUM_RETURNED(flags);
        p->clk->rate_discrete = RATE_DISCRETE(flags);
 
+       /* Warn about out of spec replies ... */
+       if (!p->clk->rate_discrete &&
+           (st->num_returned != 3 || st->num_remaining != 0)) {
+               dev_warn(p->dev,
+                        "Out-of-spec CLOCK_DESCRIBE_RATES reply for %s - returned:%d remaining:%d rx_len:%zd\n",
+                        p->clk->name, st->num_returned, st->num_remaining,
+                        st->rx_len);
+
+               /*
+                * A known quirk: a triplet is returned but num_returned != 3
+                * Check for a safe payload size and fix.
+                */
+               if (st->num_returned != 3 && st->num_remaining == 0 &&
+                   st->rx_len == sizeof(*r) + sizeof(__le32) * 2 * 3) {
+                       st->num_returned = 3;
+                       st->num_remaining = 0;
+               } else {
+                       dev_err(p->dev,
+                               "Cannot fix out-of-spec reply !\n");
+                       return -EPROTO;
+               }
+       }
+
        return 0;
 }
 
@@ -255,7 +279,6 @@ iter_clk_describe_process_response(const struct scmi_protocol_handle *ph,
 
                *rate = RATE_TO_U64(r->rate[st->loop_idx]);
                p->clk->list.num_rates++;
-               //XXX dev_dbg(ph->dev, "Rate %llu Hz\n", *rate);
        }
 
        return ret;
@@ -275,6 +298,7 @@ scmi_clock_describe_rates_get(const struct scmi_protocol_handle *ph, u32 clk_id,
        struct scmi_clk_ipriv cpriv = {
                .clk_id = clk_id,
                .clk = clk,
+               .dev = ph->dev,
        };
 
        iter = ph->hops->iter_response_init(ph, &ops, SCMI_MAX_NUM_RATES,
index c1922bd..8b7ac66 100644 (file)
@@ -1223,6 +1223,7 @@ static int scmi_iterator_run(void *iter)
                if (ret)
                        break;
 
+               st->rx_len = i->t->rx.len;
                ret = iops->update_state(st, i->resp, i->priv);
                if (ret)
                        break;
index b503c22..8abace5 100644 (file)
@@ -117,6 +117,7 @@ struct scmi_optee_channel {
        u32 channel_id;
        u32 tee_session;
        u32 caps;
+       u32 rx_len;
        struct mutex mu;
        struct scmi_chan_info *cinfo;
        union {
@@ -302,6 +303,9 @@ static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t
                return -EIO;
        }
 
+       /* Save response size */
+       channel->rx_len = param[2].u.memref.size;
+
        return 0;
 }
 
@@ -353,6 +357,7 @@ static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *ch
        shbuf = tee_shm_get_va(channel->tee_shm, 0);
        memset(shbuf, 0, msg_size);
        channel->req.msg = shbuf;
+       channel->rx_len = msg_size;
 
        return 0;
 }
@@ -508,7 +513,7 @@ static void scmi_optee_fetch_response(struct scmi_chan_info *cinfo,
        struct scmi_optee_channel *channel = cinfo->transport_info;
 
        if (channel->tee_shm)
-               msg_fetch_response(channel->req.msg, SCMI_OPTEE_MAX_MSG_SIZE, xfer);
+               msg_fetch_response(channel->req.msg, channel->rx_len, xfer);
        else
                shmem_fetch_response(channel->req.shmem, xfer);
 }
index c679f3f..51c3137 100644 (file)
@@ -179,6 +179,8 @@ struct scmi_protocol_handle {
  * @max_resources: Maximum acceptable number of items, configured by the caller
  *                depending on the underlying resources that it is querying.
  * @loop_idx: The iterator loop index in the current multi-part reply.
+ * @rx_len: Size in bytes of the currenly processed message; it can be used by
+ *         the user of the iterator to verify a reply size.
  * @priv: Optional pointer to some additional state-related private data setup
  *       by the caller during the iterations.
  */
@@ -188,6 +190,7 @@ struct scmi_iterator_state {
        unsigned int num_remaining;
        unsigned int max_resources;
        unsigned int loop_idx;
+       size_t rx_len;
        void *priv;
 };
 
index 23cddb2..9db42f6 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
 
 #define VF610_GPIO_PER_PORT            32
 
index f5aa5f9..0c9a63b 100644 (file)
@@ -1460,11 +1460,12 @@ static ssize_t linereq_read(struct file *file,
 static void linereq_free(struct linereq *lr)
 {
        unsigned int i;
-       bool hte;
+       bool hte = false;
 
        for (i = 0; i < lr->num_lines; i++) {
-               hte = !!test_bit(FLAG_EVENT_CLOCK_HTE,
-                                &lr->lines[i].desc->flags);
+               if (lr->lines[i].desc)
+                       hte = !!test_bit(FLAG_EVENT_CLOCK_HTE,
+                                        &lr->lines[i].desc->flags);
                edge_detector_stop(&lr->lines[i], hte);
                if (lr->lines[i].desc)
                        gpiod_free(lr->lines[i].desc);
index 74bd4a7..059fd71 100644 (file)
@@ -329,7 +329,20 @@ int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
                                                     const struct drm_driver *req_driver)
 {
        resource_size_t base, size;
-       int bar, ret = 0;
+       int bar, ret;
+
+       /*
+        * WARNING: Apparently we must kick fbdev drivers before vgacon,
+        * otherwise the vga fbdev driver falls over.
+        */
+#if IS_REACHABLE(CONFIG_FB)
+       ret = remove_conflicting_pci_framebuffers(pdev, req_driver->name);
+       if (ret)
+               return ret;
+#endif
+       ret = vga_remove_vgacon(pdev);
+       if (ret)
+               return ret;
 
        for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) {
                if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
@@ -339,15 +352,6 @@ int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
                drm_aperture_detach_drivers(base, size);
        }
 
-       /*
-        * WARNING: Apparently we must kick fbdev drivers before vgacon,
-        * otherwise the vga fbdev driver falls over.
-        */
-#if IS_REACHABLE(CONFIG_FB)
-       ret = remove_conflicting_pci_framebuffers(pdev, req_driver->name);
-#endif
-       if (ret == 0)
-               ret = vga_remove_vgacon(pdev);
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(drm_aperture_remove_conflicting_pci_framebuffers);
index 5c4cf74..157e232 100644 (file)
@@ -550,7 +550,7 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
 
        res = platform_device_add(data->pdev);
        if (res)
-               goto ipmi_err;
+               goto dev_add_err;
 
        platform_set_drvdata(data->pdev, data);
 
@@ -598,7 +598,9 @@ hwmon_reg_err:
        ipmi_destroy_user(data->ipmi.user);
 ipmi_err:
        platform_set_drvdata(data->pdev, NULL);
-       platform_device_unregister(data->pdev);
+       platform_device_del(data->pdev);
+dev_add_err:
+       platform_device_put(data->pdev);
 dev_err:
        ida_free(&aem_ida, data->id);
 id_err:
@@ -690,7 +692,7 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
 
        res = platform_device_add(data->pdev);
        if (res)
-               goto ipmi_err;
+               goto dev_add_err;
 
        platform_set_drvdata(data->pdev, data);
 
@@ -738,7 +740,9 @@ hwmon_reg_err:
        ipmi_destroy_user(data->ipmi.user);
 ipmi_err:
        platform_set_drvdata(data->pdev, NULL);
-       platform_device_unregister(data->pdev);
+       platform_device_del(data->pdev);
+dev_add_err:
+       platform_device_put(data->pdev);
 dev_err:
        ida_free(&aem_ida, data->id);
 id_err:
index ea070b9..157b73a 100644 (file)
@@ -145,7 +145,7 @@ static int occ_poll(struct occ *occ)
        cmd[6] = 0;                     /* checksum lsb */
 
        /* mutex should already be locked if necessary */
-       rc = occ->send_cmd(occ, cmd, sizeof(cmd));
+       rc = occ->send_cmd(occ, cmd, sizeof(cmd), &occ->resp, sizeof(occ->resp));
        if (rc) {
                occ->last_error = rc;
                if (occ->error_count++ > OCC_ERROR_COUNT_THRESHOLD)
@@ -182,6 +182,7 @@ static int occ_set_user_power_cap(struct occ *occ, u16 user_power_cap)
 {
        int rc;
        u8 cmd[8];
+       u8 resp[8];
        __be16 user_power_cap_be = cpu_to_be16(user_power_cap);
 
        cmd[0] = 0;     /* sequence number */
@@ -198,7 +199,7 @@ static int occ_set_user_power_cap(struct occ *occ, u16 user_power_cap)
        if (rc)
                return rc;
 
-       rc = occ->send_cmd(occ, cmd, sizeof(cmd));
+       rc = occ->send_cmd(occ, cmd, sizeof(cmd), resp, sizeof(resp));
 
        mutex_unlock(&occ->lock);
 
index 64d5ec7..7ac4b2f 100644 (file)
@@ -96,7 +96,8 @@ struct occ {
 
        int powr_sample_time_us;        /* average power sample time */
        u8 poll_cmd_data;               /* to perform OCC poll command */
-       int (*send_cmd)(struct occ *occ, u8 *cmd, size_t len);
+       int (*send_cmd)(struct occ *occ, u8 *cmd, size_t len, void *resp,
+                       size_t resp_len);
 
        unsigned long next_update;
        struct mutex lock;              /* lock OCC access */
index da39ea2..b221be1 100644 (file)
@@ -111,7 +111,8 @@ static int p8_i2c_occ_putscom_be(struct i2c_client *client, u32 address,
                                      be32_to_cpu(data1));
 }
 
-static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
+static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len,
+                              void *resp, size_t resp_len)
 {
        int i, rc;
        unsigned long start;
@@ -120,7 +121,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
        const long wait_time = msecs_to_jiffies(OCC_CMD_IN_PRG_WAIT_MS);
        struct p8_i2c_occ *ctx = to_p8_i2c_occ(occ);
        struct i2c_client *client = ctx->client;
-       struct occ_response *resp = &occ->resp;
+       struct occ_response *or = (struct occ_response *)resp;
 
        start = jiffies;
 
@@ -151,7 +152,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
                        return rc;
 
                /* wait for OCC */
-               if (resp->return_status == OCC_RESP_CMD_IN_PRG) {
+               if (or->return_status == OCC_RESP_CMD_IN_PRG) {
                        rc = -EALREADY;
 
                        if (time_after(jiffies, start + timeout))
@@ -163,7 +164,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
        } while (rc);
 
        /* check the OCC response */
-       switch (resp->return_status) {
+       switch (or->return_status) {
        case OCC_RESP_CMD_IN_PRG:
                rc = -ETIMEDOUT;
                break;
@@ -192,8 +193,8 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
        if (rc < 0)
                return rc;
 
-       data_length = get_unaligned_be16(&resp->data_length);
-       if (data_length > OCC_RESP_DATA_BYTES)
+       data_length = get_unaligned_be16(&or->data_length);
+       if ((data_length + 7) > resp_len)
                return -EMSGSIZE;
 
        /* fetch the rest of the response data */
index 42fc7b9..a91937e 100644 (file)
@@ -78,11 +78,10 @@ done:
        return notify;
 }
 
-static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
+static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len,
+                              void *resp, size_t resp_len)
 {
-       struct occ_response *resp = &occ->resp;
        struct p9_sbe_occ *ctx = to_p9_sbe_occ(occ);
-       size_t resp_len = sizeof(*resp);
        int rc;
 
        rc = fsi_occ_submit(ctx->sbe, cmd, len, resp, &resp_len);
@@ -96,7 +95,7 @@ static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
                return rc;
        }
 
-       switch (resp->return_status) {
+       switch (((struct occ_response *)resp)->return_status) {
        case OCC_RESP_CMD_IN_PRG:
                rc = -ETIMEDOUT;
                break;
index 6bc3273..3ad375a 100644 (file)
@@ -148,7 +148,7 @@ static int ucd9200_probe(struct i2c_client *client)
         * This only affects the READ_IOUT and READ_TEMPERATURE2 registers.
         * READ_IOUT will return the sum of currents of all phases of a rail,
         * and READ_TEMPERATURE2 will return the maximum temperature detected
-        * for the the phases of the rail.
+        * for the phases of the rail.
         */
        for (i = 0; i < info->pages; i++) {
                /*
index b4c1ad1..3d6f8ee 100644 (file)
@@ -1338,6 +1338,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)
        return 0;
 
 err_clk_dis:
+       clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
        clk_disable_unprepare(id->clk);
        pm_runtime_disable(&pdev->dev);
        pm_runtime_set_suspended(&pdev->dev);
index ac8e7d6..39cb1b7 100644 (file)
@@ -161,7 +161,6 @@ static const char *piix4_aux_port_name_sb800 = " port 1";
 
 struct sb800_mmio_cfg {
        void __iomem *addr;
-       struct resource *res;
        bool use_mmio;
 };
 
@@ -179,13 +178,11 @@ static int piix4_sb800_region_request(struct device *dev,
                                      struct sb800_mmio_cfg *mmio_cfg)
 {
        if (mmio_cfg->use_mmio) {
-               struct resource *res;
                void __iomem *addr;
 
-               res = request_mem_region_muxed(SB800_PIIX4_FCH_PM_ADDR,
-                                              SB800_PIIX4_FCH_PM_SIZE,
-                                              "sb800_piix4_smb");
-               if (!res) {
+               if (!request_mem_region_muxed(SB800_PIIX4_FCH_PM_ADDR,
+                                             SB800_PIIX4_FCH_PM_SIZE,
+                                             "sb800_piix4_smb")) {
                        dev_err(dev,
                                "SMBus base address memory region 0x%x already in use.\n",
                                SB800_PIIX4_FCH_PM_ADDR);
@@ -195,12 +192,12 @@ static int piix4_sb800_region_request(struct device *dev,
                addr = ioremap(SB800_PIIX4_FCH_PM_ADDR,
                               SB800_PIIX4_FCH_PM_SIZE);
                if (!addr) {
-                       release_resource(res);
+                       release_mem_region(SB800_PIIX4_FCH_PM_ADDR,
+                                          SB800_PIIX4_FCH_PM_SIZE);
                        dev_err(dev, "SMBus base address mapping failed.\n");
                        return -ENOMEM;
                }
 
-               mmio_cfg->res = res;
                mmio_cfg->addr = addr;
 
                return 0;
@@ -222,7 +219,8 @@ static void piix4_sb800_region_release(struct device *dev,
 {
        if (mmio_cfg->use_mmio) {
                iounmap(mmio_cfg->addr);
-               release_resource(mmio_cfg->res);
+               release_mem_region(SB800_PIIX4_FCH_PM_ADDR,
+                                  SB800_PIIX4_FCH_PM_SIZE);
                return;
        }
 
index 1c107d6..b985e0d 100644 (file)
@@ -1252,8 +1252,10 @@ struct ib_cm_id *ib_cm_insert_listen(struct ib_device *device,
                return ERR_CAST(cm_id_priv);
 
        err = cm_init_listen(cm_id_priv, service_id, 0);
-       if (err)
+       if (err) {
+               ib_destroy_cm_id(&cm_id_priv->id);
                return ERR_PTR(err);
+       }
 
        spin_lock_irq(&cm_id_priv->lock);
        listen_id_priv = cm_insert_listen(cm_id_priv, cm_handler);
index 8def88c..db9ef3e 100644 (file)
@@ -418,6 +418,7 @@ struct qedr_qp {
        u32 sq_psn;
        u32 qkey;
        u32 dest_qp_num;
+       u8 timeout;
 
        /* Relevant to qps created from kernel space only (ULPs) */
        u8 prev_wqe_size;
index f0f43b6..03ed7c0 100644 (file)
@@ -2613,6 +2613,8 @@ int qedr_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                        1 << max_t(int, attr->timeout - 8, 0);
                else
                        qp_params.ack_timeout = 0;
+
+               qp->timeout = attr->timeout;
        }
 
        if (attr_mask & IB_QP_RETRY_CNT) {
@@ -2772,7 +2774,7 @@ int qedr_query_qp(struct ib_qp *ibqp,
        rdma_ah_set_dgid_raw(&qp_attr->ah_attr, &params.dgid.bytes[0]);
        rdma_ah_set_port_num(&qp_attr->ah_attr, 1);
        rdma_ah_set_sl(&qp_attr->ah_attr, 0);
-       qp_attr->timeout = params.timeout;
+       qp_attr->timeout = qp->timeout;
        qp_attr->rnr_retry = params.rnr_retry;
        qp_attr->retry_cnt = params.retry_cnt;
        qp_attr->min_rnr_timer = params.min_rnr_nak_timer;
index 592c1e1..9699ca1 100644 (file)
@@ -382,7 +382,7 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb,
 
 static struct notifier_block dmar_pci_bus_nb = {
        .notifier_call = dmar_pci_bus_notifier,
-       .priority = INT_MIN,
+       .priority = 1,
 };
 
 static struct dmar_drhd_unit *
index 4401659..5c0dce7 100644 (file)
@@ -320,30 +320,6 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
 DEFINE_SPINLOCK(device_domain_lock);
 static LIST_HEAD(device_domain_list);
 
-/*
- * Iterate over elements in device_domain_list and call the specified
- * callback @fn against each element.
- */
-int for_each_device_domain(int (*fn)(struct device_domain_info *info,
-                                    void *data), void *data)
-{
-       int ret = 0;
-       unsigned long flags;
-       struct device_domain_info *info;
-
-       spin_lock_irqsave(&device_domain_lock, flags);
-       list_for_each_entry(info, &device_domain_list, global) {
-               ret = fn(info, data);
-               if (ret) {
-                       spin_unlock_irqrestore(&device_domain_lock, flags);
-                       return ret;
-               }
-       }
-       spin_unlock_irqrestore(&device_domain_lock, flags);
-
-       return 0;
-}
-
 const struct iommu_ops intel_iommu_ops;
 
 static bool translation_pre_enabled(struct intel_iommu *iommu)
index cb4c1d0..17cad7c 100644 (file)
@@ -86,54 +86,6 @@ void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid)
 /*
  * Per device pasid table management:
  */
-static inline void
-device_attach_pasid_table(struct device_domain_info *info,
-                         struct pasid_table *pasid_table)
-{
-       info->pasid_table = pasid_table;
-       list_add(&info->table, &pasid_table->dev);
-}
-
-static inline void
-device_detach_pasid_table(struct device_domain_info *info,
-                         struct pasid_table *pasid_table)
-{
-       info->pasid_table = NULL;
-       list_del(&info->table);
-}
-
-struct pasid_table_opaque {
-       struct pasid_table      **pasid_table;
-       int                     segment;
-       int                     bus;
-       int                     devfn;
-};
-
-static int search_pasid_table(struct device_domain_info *info, void *opaque)
-{
-       struct pasid_table_opaque *data = opaque;
-
-       if (info->iommu->segment == data->segment &&
-           info->bus == data->bus &&
-           info->devfn == data->devfn &&
-           info->pasid_table) {
-               *data->pasid_table = info->pasid_table;
-               return 1;
-       }
-
-       return 0;
-}
-
-static int get_alias_pasid_table(struct pci_dev *pdev, u16 alias, void *opaque)
-{
-       struct pasid_table_opaque *data = opaque;
-
-       data->segment = pci_domain_nr(pdev->bus);
-       data->bus = PCI_BUS_NUM(alias);
-       data->devfn = alias & 0xff;
-
-       return for_each_device_domain(&search_pasid_table, data);
-}
 
 /*
  * Allocate a pasid table for @dev. It should be called in a
@@ -143,28 +95,18 @@ int intel_pasid_alloc_table(struct device *dev)
 {
        struct device_domain_info *info;
        struct pasid_table *pasid_table;
-       struct pasid_table_opaque data;
        struct page *pages;
        u32 max_pasid = 0;
-       int ret, order;
-       int size;
+       int order, size;
 
        might_sleep();
        info = dev_iommu_priv_get(dev);
        if (WARN_ON(!info || !dev_is_pci(dev) || info->pasid_table))
                return -EINVAL;
 
-       /* DMA alias device already has a pasid table, use it: */
-       data.pasid_table = &pasid_table;
-       ret = pci_for_each_dma_alias(to_pci_dev(dev),
-                                    &get_alias_pasid_table, &data);
-       if (ret)
-               goto attach_out;
-
        pasid_table = kzalloc(sizeof(*pasid_table), GFP_KERNEL);
        if (!pasid_table)
                return -ENOMEM;
-       INIT_LIST_HEAD(&pasid_table->dev);
 
        if (info->pasid_supported)
                max_pasid = min_t(u32, pci_max_pasids(to_pci_dev(dev)),
@@ -182,9 +124,7 @@ int intel_pasid_alloc_table(struct device *dev)
        pasid_table->table = page_address(pages);
        pasid_table->order = order;
        pasid_table->max_pasid = 1 << (order + PAGE_SHIFT + 3);
-
-attach_out:
-       device_attach_pasid_table(info, pasid_table);
+       info->pasid_table = pasid_table;
 
        return 0;
 }
@@ -202,10 +142,7 @@ void intel_pasid_free_table(struct device *dev)
                return;
 
        pasid_table = info->pasid_table;
-       device_detach_pasid_table(info, pasid_table);
-
-       if (!list_empty(&pasid_table->dev))
-               return;
+       info->pasid_table = NULL;
 
        /* Free scalable mode PASID directory tables: */
        dir = pasid_table->table;
index 583ea67..bf5b937 100644 (file)
@@ -74,7 +74,6 @@ struct pasid_table {
        void                    *table;         /* pasid table pointer */
        int                     order;          /* page order of pasid table */
        u32                     max_pasid;      /* max pasid */
-       struct list_head        dev;            /* device list */
 };
 
 /* Get PRESENT bit of a PASID directory entry. */
index 1f23a6b..bbb11cb 100644 (file)
@@ -298,7 +298,7 @@ config XTENSA_MX
 
 config XILINX_INTC
        bool "Xilinx Interrupt Controller IP"
-       depends on OF
+       depends on OF_ADDRESS
        select IRQ_DOMAIN
        help
          Support for the Xilinx Interrupt Controller IP core.
index 5ac8318..1c2813a 100644 (file)
 #define AIC_TMR_EL02_PHYS      AIC_TMR_GUEST_PHYS
 #define AIC_TMR_EL02_VIRT      AIC_TMR_GUEST_VIRT
 
-DEFINE_STATIC_KEY_TRUE(use_fast_ipi);
+static DEFINE_STATIC_KEY_TRUE(use_fast_ipi);
 
 struct aic_info {
        int version;
index 5c1cf90..2d25bca 100644 (file)
@@ -2042,15 +2042,40 @@ static void __init gic_of_setup_kvm_info(struct device_node *node)
        vgic_set_kvm_info(&gic_v3_kvm_info);
 }
 
+static void gic_request_region(resource_size_t base, resource_size_t size,
+                              const char *name)
+{
+       if (!request_mem_region(base, size, name))
+               pr_warn_once(FW_BUG "%s region %pa has overlapping address\n",
+                            name, &base);
+}
+
+static void __iomem *gic_of_iomap(struct device_node *node, int idx,
+                                 const char *name, struct resource *res)
+{
+       void __iomem *base;
+       int ret;
+
+       ret = of_address_to_resource(node, idx, res);
+       if (ret)
+               return IOMEM_ERR_PTR(ret);
+
+       gic_request_region(res->start, resource_size(res), name);
+       base = of_iomap(node, idx);
+
+       return base ?: IOMEM_ERR_PTR(-ENOMEM);
+}
+
 static int __init gic_of_init(struct device_node *node, struct device_node *parent)
 {
        void __iomem *dist_base;
        struct redist_region *rdist_regs;
+       struct resource res;
        u64 redist_stride;
        u32 nr_redist_regions;
        int err, i;
 
-       dist_base = of_io_request_and_map(node, 0, "GICD");
+       dist_base = gic_of_iomap(node, 0, "GICD", &res);
        if (IS_ERR(dist_base)) {
                pr_err("%pOF: unable to map gic dist registers\n", node);
                return PTR_ERR(dist_base);
@@ -2073,12 +2098,8 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
        }
 
        for (i = 0; i < nr_redist_regions; i++) {
-               struct resource res;
-               int ret;
-
-               ret = of_address_to_resource(node, 1 + i, &res);
-               rdist_regs[i].redist_base = of_io_request_and_map(node, 1 + i, "GICR");
-               if (ret || IS_ERR(rdist_regs[i].redist_base)) {
+               rdist_regs[i].redist_base = gic_of_iomap(node, 1 + i, "GICR", &res);
+               if (IS_ERR(rdist_regs[i].redist_base)) {
                        pr_err("%pOF: couldn't map region %d\n", node, i);
                        err = -ENODEV;
                        goto out_unmap_rdist;
@@ -2151,7 +2172,7 @@ gic_acpi_parse_madt_redist(union acpi_subtable_headers *header,
                pr_err("Couldn't map GICR region @%llx\n", redist->base_address);
                return -ENOMEM;
        }
-       request_mem_region(redist->base_address, redist->length, "GICR");
+       gic_request_region(redist->base_address, redist->length, "GICR");
 
        gic_acpi_register_redist(redist->base_address, redist_base);
        return 0;
@@ -2174,7 +2195,7 @@ gic_acpi_parse_madt_gicc(union acpi_subtable_headers *header,
        redist_base = ioremap(gicc->gicr_base_address, size);
        if (!redist_base)
                return -ENOMEM;
-       request_mem_region(gicc->gicr_base_address, size, "GICR");
+       gic_request_region(gicc->gicr_base_address, size, "GICR");
 
        gic_acpi_register_redist(gicc->gicr_base_address, redist_base);
        return 0;
@@ -2376,7 +2397,7 @@ gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end)
                pr_err("Unable to map GICD registers\n");
                return -ENOMEM;
        }
-       request_mem_region(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE, "GICD");
+       gic_request_region(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE, "GICD");
 
        err = gic_validate_dist_version(acpi_data.dist_base);
        if (err) {
index 49b47e7..f289ccd 100644 (file)
@@ -66,7 +66,6 @@ static struct or1k_pic_dev or1k_pic_level = {
                .name = "or1k-PIC-level",
                .irq_unmask = or1k_pic_unmask,
                .irq_mask = or1k_pic_mask,
-               .irq_mask_ack = or1k_pic_mask_ack,
        },
        .handle = handle_level_irq,
        .flags = IRQ_LEVEL | IRQ_NOPROBE,
index 9526ccb..80c9f71 100644 (file)
@@ -1001,12 +1001,13 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
 static int validate_raid_redundancy(struct raid_set *rs)
 {
        unsigned int i, rebuild_cnt = 0;
-       unsigned int rebuilds_per_group = 0, copies;
+       unsigned int rebuilds_per_group = 0, copies, raid_disks;
        unsigned int group_size, last_group_start;
 
-       for (i = 0; i < rs->md.raid_disks; i++)
-               if (!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
-                   !rs->dev[i].rdev.sb_page)
+       for (i = 0; i < rs->raid_disks; i++)
+               if (!test_bit(FirstUse, &rs->dev[i].rdev.flags) &&
+                   ((!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
+                     !rs->dev[i].rdev.sb_page)))
                        rebuild_cnt++;
 
        switch (rs->md.level) {
@@ -1046,8 +1047,9 @@ static int validate_raid_redundancy(struct raid_set *rs)
                 *          A    A    B    B    C
                 *          C    D    D    E    E
                 */
+               raid_disks = min(rs->raid_disks, rs->md.raid_disks);
                if (__is_raid10_near(rs->md.new_layout)) {
-                       for (i = 0; i < rs->md.raid_disks; i++) {
+                       for (i = 0; i < raid_disks; i++) {
                                if (!(i % copies))
                                        rebuilds_per_group = 0;
                                if ((!rs->dev[i].rdev.sb_page ||
@@ -1070,10 +1072,10 @@ static int validate_raid_redundancy(struct raid_set *rs)
                 * results in the need to treat the last (potentially larger)
                 * set differently.
                 */
-               group_size = (rs->md.raid_disks / copies);
-               last_group_start = (rs->md.raid_disks / group_size) - 1;
+               group_size = (raid_disks / copies);
+               last_group_start = (raid_disks / group_size) - 1;
                last_group_start *= group_size;
-               for (i = 0; i < rs->md.raid_disks; i++) {
+               for (i = 0; i < raid_disks; i++) {
                        if (!(i % copies) && !(i > last_group_start))
                                rebuilds_per_group = 0;
                        if ((!rs->dev[i].rdev.sb_page ||
@@ -1588,7 +1590,7 @@ static sector_t __rdev_sectors(struct raid_set *rs)
 {
        int i;
 
-       for (i = 0; i < rs->md.raid_disks; i++) {
+       for (i = 0; i < rs->raid_disks; i++) {
                struct md_rdev *rdev = &rs->dev[i].rdev;
 
                if (!test_bit(Journal, &rdev->flags) &&
@@ -3766,13 +3768,13 @@ static int raid_iterate_devices(struct dm_target *ti,
        unsigned int i;
        int r = 0;
 
-       for (i = 0; !r && i < rs->md.raid_disks; i++)
-               if (rs->dev[i].data_dev)
-                       r = fn(ti,
-                                rs->dev[i].data_dev,
-                                0, /* No offset on data devs */
-                                rs->md.dev_sectors,
-                                data);
+       for (i = 0; !r && i < rs->raid_disks; i++) {
+               if (rs->dev[i].data_dev) {
+                       r = fn(ti, rs->dev[i].data_dev,
+                              0, /* No offset on data devs */
+                              rs->md.dev_sectors, data);
+               }
+       }
 
        return r;
 }
index 5d09256..20e53b1 100644 (file)
@@ -7933,7 +7933,7 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
        int err = 0;
        int number = rdev->raid_disk;
        struct md_rdev __rcu **rdevp;
-       struct disk_info *p = conf->disks + number;
+       struct disk_info *p;
        struct md_rdev *tmp;
 
        print_raid5_conf(conf);
@@ -7952,6 +7952,9 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
                log_exit(conf);
                return 0;
        }
+       if (unlikely(number >= conf->pool_size))
+               return 0;
+       p = conf->disks + number;
        if (rdev == rcu_access_pointer(p->rdev))
                rdevp = &p->rdev;
        else if (rdev == rcu_access_pointer(p->replacement))
@@ -8062,6 +8065,7 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
         */
        if (rdev->saved_raid_disk >= 0 &&
            rdev->saved_raid_disk >= first &&
+           rdev->saved_raid_disk <= last &&
            conf->disks[rdev->saved_raid_disk].rdev == NULL)
                first = rdev->saved_raid_disk;
 
index 1ef9b61..f150d87 100644 (file)
@@ -631,16 +631,20 @@ static int rtsx_usb_probe(struct usb_interface *intf,
 
        ucr->pusb_dev = usb_dev;
 
-       ucr->iobuf = usb_alloc_coherent(ucr->pusb_dev, IOBUF_SIZE,
-                       GFP_KERNEL, &ucr->iobuf_dma);
-       if (!ucr->iobuf)
+       ucr->cmd_buf = kmalloc(IOBUF_SIZE, GFP_KERNEL);
+       if (!ucr->cmd_buf)
                return -ENOMEM;
 
+       ucr->rsp_buf = kmalloc(IOBUF_SIZE, GFP_KERNEL);
+       if (!ucr->rsp_buf) {
+               ret = -ENOMEM;
+               goto out_free_cmd_buf;
+       }
+
        usb_set_intfdata(intf, ucr);
 
        ucr->vendor_id = id->idVendor;
        ucr->product_id = id->idProduct;
-       ucr->cmd_buf = ucr->rsp_buf = ucr->iobuf;
 
        mutex_init(&ucr->dev_mutex);
 
@@ -668,8 +672,11 @@ static int rtsx_usb_probe(struct usb_interface *intf,
 
 out_init_fail:
        usb_set_intfdata(ucr->pusb_intf, NULL);
-       usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
-                       ucr->iobuf_dma);
+       kfree(ucr->rsp_buf);
+       ucr->rsp_buf = NULL;
+out_free_cmd_buf:
+       kfree(ucr->cmd_buf);
+       ucr->cmd_buf = NULL;
        return ret;
 }
 
@@ -682,8 +689,12 @@ static void rtsx_usb_disconnect(struct usb_interface *intf)
        mfd_remove_devices(&intf->dev);
 
        usb_set_intfdata(ucr->pusb_intf, NULL);
-       usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
-                       ucr->iobuf_dma);
+
+       kfree(ucr->cmd_buf);
+       ucr->cmd_buf = NULL;
+
+       kfree(ucr->rsp_buf);
+       ucr->rsp_buf = NULL;
 }
 
 #ifdef CONFIG_PM
index c9c56fd..bdffc65 100644 (file)
@@ -80,10 +80,9 @@ static int at25_ee_read(void *priv, unsigned int offset,
        struct at25_data *at25 = priv;
        char *buf = val;
        size_t max_chunk = spi_max_transfer_size(at25->spi);
-       size_t num_msgs = DIV_ROUND_UP(count, max_chunk);
-       size_t nr_bytes = 0;
-       unsigned int msg_offset;
-       size_t msg_count;
+       unsigned int msg_offset = offset;
+       size_t bytes_left = count;
+       size_t segment;
        u8                      *cp;
        ssize_t                 status;
        struct spi_transfer     t[2];
@@ -97,9 +96,8 @@ static int at25_ee_read(void *priv, unsigned int offset,
        if (unlikely(!count))
                return -EINVAL;
 
-       msg_offset = (unsigned int)offset;
-       msg_count = min(count, max_chunk);
-       while (num_msgs) {
+       do {
+               segment = min(bytes_left, max_chunk);
                cp = at25->command;
 
                instr = AT25_READ;
@@ -131,8 +129,8 @@ static int at25_ee_read(void *priv, unsigned int offset,
                t[0].len = at25->addrlen + 1;
                spi_message_add_tail(&t[0], &m);
 
-               t[1].rx_buf = buf + nr_bytes;
-               t[1].len = msg_count;
+               t[1].rx_buf = buf;
+               t[1].len = segment;
                spi_message_add_tail(&t[1], &m);
 
                status = spi_sync(at25->spi, &m);
@@ -142,10 +140,10 @@ static int at25_ee_read(void *priv, unsigned int offset,
                if (status)
                        return status;
 
-               --num_msgs;
-               msg_offset += msg_count;
-               nr_bytes += msg_count;
-       }
+               msg_offset += segment;
+               buf += segment;
+               bytes_left -= segment;
+       } while (bytes_left > 0);
 
        dev_dbg(&at25->spi->dev, "read %zu bytes at %d\n",
                count, offset);
@@ -229,7 +227,7 @@ static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count)
        do {
                unsigned long   timeout, retries;
                unsigned        segment;
-               unsigned        offset = (unsigned) off;
+               unsigned        offset = off;
                u8              *cp = bounce;
                int             sr;
                u8              instr;
index b2a4f99..8c1eeb5 100644 (file)
@@ -94,6 +94,7 @@ config WIREGUARD
        select CRYPTO_CURVE25519_NEON if ARM && KERNEL_MODE_NEON
        select CRYPTO_CHACHA_MIPS if CPU_MIPS32_R2
        select CRYPTO_POLY1305_MIPS if MIPS
+       select CRYPTO_CHACHA_S390 if S390
        help
          WireGuard is a secure, fast, and easy to use replacement for IPSec
          that uses modern cryptography and clever networking tricks. It's
index a86b1f7..d7fb33c 100644 (file)
@@ -2228,7 +2228,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
                                temp_aggregator->num_of_ports--;
                                if (__agg_active_ports(temp_aggregator) == 0) {
                                        select_new_active_agg = temp_aggregator->is_active;
-                                       ad_clear_agg(temp_aggregator);
+                                       if (temp_aggregator->num_of_ports == 0)
+                                               ad_clear_agg(temp_aggregator);
                                        if (select_new_active_agg) {
                                                slave_info(bond->dev, slave->dev, "Removing an active aggregator\n");
                                                /* select new active aggregator */
index 303c8d3..007d43e 100644 (file)
@@ -1302,12 +1302,12 @@ int bond_alb_initialize(struct bonding *bond, int rlb_enabled)
                return res;
 
        if (rlb_enabled) {
-               bond->alb_info.rlb_enabled = 1;
                res = rlb_initialize(bond);
                if (res) {
                        tlb_deinitialize(bond);
                        return res;
                }
+               bond->alb_info.rlb_enabled = 1;
        } else {
                bond->alb_info.rlb_enabled = 0;
        }
index 5458f57..0b0f234 100644 (file)
@@ -722,13 +722,21 @@ static int cfv_probe(struct virtio_device *vdev)
        /* Carrier is off until netdevice is opened */
        netif_carrier_off(netdev);
 
+       /* serialize netdev register + virtio_device_ready() with ndo_open() */
+       rtnl_lock();
+
        /* register Netdev */
-       err = register_netdev(netdev);
+       err = register_netdevice(netdev);
        if (err) {
+               rtnl_unlock();
                dev_err(&vdev->dev, "Unable to register netdev (%d)\n", err);
                goto err;
        }
 
+       virtio_device_ready(vdev);
+
+       rtnl_unlock();
+
        debugfs_init(cfv);
 
        return 0;
index 76df480..4c47c10 100644 (file)
@@ -1646,7 +1646,6 @@ static int grcan_probe(struct platform_device *ofdev)
         */
        sysid_parent = of_find_node_by_path("/ambapp0");
        if (sysid_parent) {
-               of_node_get(sysid_parent);
                err = of_property_read_u32(sysid_parent, "systemid", &sysid);
                if (!err && ((sysid & GRLIB_VERSION_MASK) >=
                             GRCAN_TXBUG_SAFE_GRLIB_VERSION))
index 5d0c82d..7931f9c 100644 (file)
@@ -529,7 +529,7 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs)
        /* acknowledge rx fifo 0 */
        m_can_write(cdev, M_CAN_RXF0A, fgi);
 
-       timestamp = FIELD_GET(RX_BUF_RXTS_MASK, fifo_header.dlc);
+       timestamp = FIELD_GET(RX_BUF_RXTS_MASK, fifo_header.dlc) << 16;
 
        m_can_receive_skb(cdev, skb, timestamp);
 
@@ -1030,7 +1030,7 @@ static int m_can_echo_tx_event(struct net_device *dev)
                }
 
                msg_mark = FIELD_GET(TX_EVENT_MM_MASK, txe);
-               timestamp = FIELD_GET(TX_EVENT_TXTS_MASK, txe);
+               timestamp = FIELD_GET(TX_EVENT_TXTS_MASK, txe) << 16;
 
                /* ack txe element */
                m_can_write(cdev, M_CAN_TXEFA, FIELD_PREP(TXEFA_EFAI_MASK,
@@ -1351,7 +1351,9 @@ static void m_can_chip_config(struct net_device *dev)
        /* enable internal timestamp generation, with a prescalar of 16. The
         * prescalar is applied to the nominal bit timing
         */
-       m_can_write(cdev, M_CAN_TSCC, FIELD_PREP(TSCC_TCP_MASK, 0xf));
+       m_can_write(cdev, M_CAN_TSCC,
+                   FIELD_PREP(TSCC_TCP_MASK, 0xf) |
+                   FIELD_PREP(TSCC_TSS_MASK, TSCC_TSS_INTERNAL));
 
        m_can_config_endisable(cdev, false);
 
index 40a1144..ba42cef 100644 (file)
@@ -1332,7 +1332,10 @@ static void rcar_canfd_set_bittiming(struct net_device *dev)
                cfg = (RCANFD_DCFG_DTSEG1(gpriv, tseg1) | RCANFD_DCFG_DBRP(brp) |
                       RCANFD_DCFG_DSJW(sjw) | RCANFD_DCFG_DTSEG2(gpriv, tseg2));
 
-               rcar_canfd_write(priv->base, RCANFD_F_DCFG(ch), cfg);
+               if (is_v3u(gpriv))
+                       rcar_canfd_write(priv->base, RCANFD_V3U_DCFG(ch), cfg);
+               else
+                       rcar_canfd_write(priv->base, RCANFD_F_DCFG(ch), cfg);
                netdev_dbg(priv->ndev, "drate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n",
                           brp, sjw, tseg1, tseg2);
        } else {
index b212523..9b47b07 100644 (file)
@@ -12,6 +12,7 @@
 // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
 //
 
+#include <asm/unaligned.h>
 #include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/device.h>
@@ -1650,6 +1651,7 @@ static int mcp251xfd_stop(struct net_device *ndev)
        netif_stop_queue(ndev);
        set_bit(MCP251XFD_FLAGS_DOWN, priv->flags);
        hrtimer_cancel(&priv->rx_irq_timer);
+       hrtimer_cancel(&priv->tx_irq_timer);
        mcp251xfd_chip_interrupts_disable(priv);
        free_irq(ndev->irq, priv);
        can_rx_offload_disable(&priv->offload);
@@ -1777,7 +1779,7 @@ mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, u32 *dev_id,
        xfer[0].len = sizeof(buf_tx->cmd);
        xfer[0].speed_hz = priv->spi_max_speed_hz_slow;
        xfer[1].rx_buf = buf_rx->data;
-       xfer[1].len = sizeof(dev_id);
+       xfer[1].len = sizeof(*dev_id);
        xfer[1].speed_hz = priv->spi_max_speed_hz_fast;
 
        mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, MCP251XFD_REG_DEVID);
@@ -1786,7 +1788,7 @@ mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, u32 *dev_id,
        if (err)
                goto out_kfree_buf_tx;
 
-       *dev_id = be32_to_cpup((__be32 *)buf_rx->data);
+       *dev_id = get_unaligned_le32(buf_rx->data);
        *effective_speed_hz_slow = xfer[0].effective_speed_hz;
        *effective_speed_hz_fast = xfer[1].effective_speed_hz;
 
index 217510c..92b7bc7 100644 (file)
@@ -334,19 +334,21 @@ mcp251xfd_regmap_crc_read(void *context,
                 * register. It increments once per SYS clock tick,
                 * which is 20 or 40 MHz.
                 *
-                * Observation shows that if the lowest byte (which is
-                * transferred first on the SPI bus) of that register
-                * is 0x00 or 0x80 the calculated CRC doesn't always
-                * match the transferred one.
+                * Observation on the mcp2518fd shows that if the
+                * lowest byte (which is transferred first on the SPI
+                * bus) of that register is 0x00 or 0x80 the
+                * calculated CRC doesn't always match the transferred
+                * one. On the mcp2517fd this problem is not limited
+                * to the first byte being 0x00 or 0x80.
                 *
                 * If the highest bit in the lowest byte is flipped
                 * the transferred CRC matches the calculated one. We
-                * assume for now the CRC calculation in the chip
-                * works on wrong data and the transferred data is
-                * correct.
+                * assume for now the CRC operates on the correct
+                * data.
                 */
                if (reg == MCP251XFD_REG_TBC &&
-                   (buf_rx->data[0] == 0x0 || buf_rx->data[0] == 0x80)) {
+                   ((buf_rx->data[0] & 0xf8) == 0x0 ||
+                    (buf_rx->data[0] & 0xf8) == 0x80)) {
                        /* Flip highest bit in lowest byte of le32 */
                        buf_rx->data[0] ^= 0x80;
 
@@ -356,10 +358,8 @@ mcp251xfd_regmap_crc_read(void *context,
                                                                  val_len);
                        if (!err) {
                                /* If CRC is now correct, assume
-                                * transferred data was OK, flip bit
-                                * back to original value.
+                                * flipped data is OK.
                                 */
-                               buf_rx->data[0] ^= 0x80;
                                goto out;
                        }
                }
index b29ba91..d3a658b 100644 (file)
@@ -268,6 +268,8 @@ struct gs_can {
 
        struct usb_anchor tx_submitted;
        atomic_t active_tx_urbs;
+       void *rxbuf[GS_MAX_RX_URBS];
+       dma_addr_t rxbuf_dma[GS_MAX_RX_URBS];
 };
 
 /* usb interface struct */
@@ -742,6 +744,7 @@ static int gs_can_open(struct net_device *netdev)
                for (i = 0; i < GS_MAX_RX_URBS; i++) {
                        struct urb *urb;
                        u8 *buf;
+                       dma_addr_t buf_dma;
 
                        /* alloc rx urb */
                        urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -752,7 +755,7 @@ static int gs_can_open(struct net_device *netdev)
                        buf = usb_alloc_coherent(dev->udev,
                                                 dev->parent->hf_size_rx,
                                                 GFP_KERNEL,
-                                                &urb->transfer_dma);
+                                                &buf_dma);
                        if (!buf) {
                                netdev_err(netdev,
                                           "No memory left for USB buffer\n");
@@ -760,6 +763,8 @@ static int gs_can_open(struct net_device *netdev)
                                return -ENOMEM;
                        }
 
+                       urb->transfer_dma = buf_dma;
+
                        /* fill, anchor, and submit rx urb */
                        usb_fill_bulk_urb(urb,
                                          dev->udev,
@@ -781,10 +786,17 @@ static int gs_can_open(struct net_device *netdev)
                                           "usb_submit failed (err=%d)\n", rc);
 
                                usb_unanchor_urb(urb);
+                               usb_free_coherent(dev->udev,
+                                                 sizeof(struct gs_host_frame),
+                                                 buf,
+                                                 buf_dma);
                                usb_free_urb(urb);
                                break;
                        }
 
+                       dev->rxbuf[i] = buf;
+                       dev->rxbuf_dma[i] = buf_dma;
+
                        /* Drop reference,
                         * USB core will take care of freeing it
                         */
@@ -842,13 +854,20 @@ static int gs_can_close(struct net_device *netdev)
        int rc;
        struct gs_can *dev = netdev_priv(netdev);
        struct gs_usb *parent = dev->parent;
+       unsigned int i;
 
        netif_stop_queue(netdev);
 
        /* Stop polling */
        parent->active_channels--;
-       if (!parent->active_channels)
+       if (!parent->active_channels) {
                usb_kill_anchored_urbs(&parent->rx_submitted);
+               for (i = 0; i < GS_MAX_RX_URBS; i++)
+                       usb_free_coherent(dev->udev,
+                                         sizeof(struct gs_host_frame),
+                                         dev->rxbuf[i],
+                                         dev->rxbuf_dma[i]);
+       }
 
        /* Stop sending URBs */
        usb_kill_anchored_urbs(&dev->tx_submitted);
index 3a49257..eefcbe3 100644 (file)
 #define KVASER_USB_RX_BUFFER_SIZE              3072
 #define KVASER_USB_MAX_NET_DEVICES             5
 
-/* USB devices features */
-#define KVASER_USB_HAS_SILENT_MODE             BIT(0)
-#define KVASER_USB_HAS_TXRX_ERRORS             BIT(1)
+/* Kvaser USB device quirks */
+#define KVASER_USB_QUIRK_HAS_SILENT_MODE       BIT(0)
+#define KVASER_USB_QUIRK_HAS_TXRX_ERRORS       BIT(1)
+#define KVASER_USB_QUIRK_IGNORE_CLK_FREQ       BIT(2)
 
 /* Device capabilities */
 #define KVASER_USB_CAP_BERR_CAP                        0x01
@@ -65,12 +66,7 @@ struct kvaser_usb_dev_card_data_hydra {
 struct kvaser_usb_dev_card_data {
        u32 ctrlmode_supported;
        u32 capabilities;
-       union {
-               struct {
-                       enum kvaser_usb_leaf_family family;
-               } leaf;
-               struct kvaser_usb_dev_card_data_hydra hydra;
-       };
+       struct kvaser_usb_dev_card_data_hydra hydra;
 };
 
 /* Context for an outstanding, not yet ACKed, transmission */
@@ -83,7 +79,7 @@ struct kvaser_usb {
        struct usb_device *udev;
        struct usb_interface *intf;
        struct kvaser_usb_net_priv *nets[KVASER_USB_MAX_NET_DEVICES];
-       const struct kvaser_usb_dev_ops *ops;
+       const struct kvaser_usb_driver_info *driver_info;
        const struct kvaser_usb_dev_cfg *cfg;
 
        struct usb_endpoint_descriptor *bulk_in, *bulk_out;
@@ -165,6 +161,12 @@ struct kvaser_usb_dev_ops {
                                  u16 transid);
 };
 
+struct kvaser_usb_driver_info {
+       u32 quirks;
+       enum kvaser_usb_leaf_family family;
+       const struct kvaser_usb_dev_ops *ops;
+};
+
 struct kvaser_usb_dev_cfg {
        const struct can_clock clock;
        const unsigned int timestamp_freq;
@@ -184,4 +186,7 @@ int kvaser_usb_send_cmd_async(struct kvaser_usb_net_priv *priv, void *cmd,
                              int len);
 
 int kvaser_usb_can_rx_over_error(struct net_device *netdev);
+
+extern const struct can_bittiming_const kvaser_usb_flexc_bittiming_const;
+
 #endif /* KVASER_USB_H */
index e67658b..f211bfc 100644 (file)
@@ -61,8 +61,6 @@
 #define USB_USBCAN_R_V2_PRODUCT_ID             294
 #define USB_LEAF_LIGHT_R_V2_PRODUCT_ID         295
 #define USB_LEAF_LIGHT_HS_V2_OEM2_PRODUCT_ID   296
-#define USB_LEAF_PRODUCT_ID_END \
-       USB_LEAF_LIGHT_HS_V2_OEM2_PRODUCT_ID
 
 /* Kvaser USBCan-II devices product ids */
 #define USB_USBCAN_REVB_PRODUCT_ID             2
 #define USB_USBCAN_PRO_4HS_PRODUCT_ID          276
 #define USB_HYBRID_CANLIN_PRODUCT_ID           277
 #define USB_HYBRID_PRO_CANLIN_PRODUCT_ID       278
-#define USB_HYDRA_PRODUCT_ID_END \
-       USB_HYBRID_PRO_CANLIN_PRODUCT_ID
 
-static inline bool kvaser_is_leaf(const struct usb_device_id *id)
-{
-       return (id->idProduct >= USB_LEAF_DEVEL_PRODUCT_ID &&
-               id->idProduct <= USB_CAN_R_PRODUCT_ID) ||
-               (id->idProduct >= USB_LEAF_LITE_V2_PRODUCT_ID &&
-                id->idProduct <= USB_LEAF_PRODUCT_ID_END);
-}
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_hydra = {
+       .quirks = 0,
+       .ops = &kvaser_usb_hydra_dev_ops,
+};
 
-static inline bool kvaser_is_usbcan(const struct usb_device_id *id)
-{
-       return id->idProduct >= USB_USBCAN_REVB_PRODUCT_ID &&
-              id->idProduct <= USB_MEMORATOR_PRODUCT_ID;
-}
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_usbcan = {
+       .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
+                 KVASER_USB_QUIRK_HAS_SILENT_MODE,
+       .family = KVASER_USBCAN,
+       .ops = &kvaser_usb_leaf_dev_ops,
+};
 
-static inline bool kvaser_is_hydra(const struct usb_device_id *id)
-{
-       return id->idProduct >= USB_BLACKBIRD_V2_PRODUCT_ID &&
-              id->idProduct <= USB_HYDRA_PRODUCT_ID_END;
-}
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf = {
+       .quirks = KVASER_USB_QUIRK_IGNORE_CLK_FREQ,
+       .family = KVASER_LEAF,
+       .ops = &kvaser_usb_leaf_dev_ops,
+};
+
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf_err = {
+       .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
+                 KVASER_USB_QUIRK_IGNORE_CLK_FREQ,
+       .family = KVASER_LEAF,
+       .ops = &kvaser_usb_leaf_dev_ops,
+};
+
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf_err_listen = {
+       .quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
+                 KVASER_USB_QUIRK_HAS_SILENT_MODE |
+                 KVASER_USB_QUIRK_IGNORE_CLK_FREQ,
+       .family = KVASER_LEAF,
+       .ops = &kvaser_usb_leaf_dev_ops,
+};
+
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leafimx = {
+       .quirks = 0,
+       .ops = &kvaser_usb_leaf_dev_ops,
+};
 
 static const struct usb_device_id kvaser_usb_table[] = {
-       /* Leaf USB product IDs */
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID) },
+       /* Leaf M32C USB product IDs */
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-                              KVASER_USB_HAS_SILENT_MODE },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-                              KVASER_USB_HAS_SILENT_MODE },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-                              KVASER_USB_HAS_SILENT_MODE },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-                              KVASER_USB_HAS_SILENT_MODE },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-                              KVASER_USB_HAS_SILENT_MODE },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-                              KVASER_USB_HAS_SILENT_MODE },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-                              KVASER_USB_HAS_SILENT_MODE },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-                              KVASER_USB_HAS_SILENT_MODE },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-                              KVASER_USB_HAS_SILENT_MODE },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID) },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_OBDII_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-                              KVASER_USB_HAS_SILENT_MODE },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSLS_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_CH_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_SPRO_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_MERCURY_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_LEAF_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_2HS_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_2HS_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_R_V2_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_R_V2_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM2_PRODUCT_ID) },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
+
+       /* Leaf i.MX28 USB product IDs */
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_2HS_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_2HS_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_R_V2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_R_V2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
 
        /* USBCANII USB product IDs */
        { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN2_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_REVB_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMORATOR_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
        { USB_DEVICE(KVASER_VENDOR_ID, USB_VCI2_PRODUCT_ID),
-               .driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
 
        /* Minihydra USB product IDs */
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_V2_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_5HS_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_5HS_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_4HS_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_HS_V2_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_2HS_V2_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_2HS_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_2HS_V2_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_2CANLIN_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_USBCAN_PRO_2HS_V2_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_MEMO_PRO_2HS_V2_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_2CANLIN_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_U100_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_U100P_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_U100S_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_4HS_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_CANLIN_PRODUCT_ID) },
-       { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_CANLIN_PRODUCT_ID) },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_V2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_5HS_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_5HS_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_4HS_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_HS_V2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_2HS_V2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_2HS_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_2HS_V2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_2CANLIN_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_USBCAN_PRO_2HS_V2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_MEMO_PRO_2HS_V2_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_2CANLIN_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_U100_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_U100P_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_U100S_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_4HS_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_CANLIN_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_CANLIN_PRODUCT_ID),
+               .driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
        { }
 };
 MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
@@ -285,6 +320,7 @@ int kvaser_usb_can_rx_over_error(struct net_device *netdev)
 static void kvaser_usb_read_bulk_callback(struct urb *urb)
 {
        struct kvaser_usb *dev = urb->context;
+       const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
        int err;
        unsigned int i;
 
@@ -301,8 +337,8 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb)
                goto resubmit_urb;
        }
 
-       dev->ops->dev_read_bulk_callback(dev, urb->transfer_buffer,
-                                        urb->actual_length);
+       ops->dev_read_bulk_callback(dev, urb->transfer_buffer,
+                                   urb->actual_length);
 
 resubmit_urb:
        usb_fill_bulk_urb(urb, dev->udev,
@@ -396,6 +432,7 @@ static int kvaser_usb_open(struct net_device *netdev)
 {
        struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
        struct kvaser_usb *dev = priv->dev;
+       const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
        int err;
 
        err = open_candev(netdev);
@@ -406,11 +443,11 @@ static int kvaser_usb_open(struct net_device *netdev)
        if (err)
                goto error;
 
-       err = dev->ops->dev_set_opt_mode(priv);
+       err = ops->dev_set_opt_mode(priv);
        if (err)
                goto error;
 
-       err = dev->ops->dev_start_chip(priv);
+       err = ops->dev_start_chip(priv);
        if (err) {
                netdev_warn(netdev, "Cannot start device, error %d\n", err);
                goto error;
@@ -467,22 +504,23 @@ static int kvaser_usb_close(struct net_device *netdev)
 {
        struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
        struct kvaser_usb *dev = priv->dev;
+       const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
        int err;
 
        netif_stop_queue(netdev);
 
-       err = dev->ops->dev_flush_queue(priv);
+       err = ops->dev_flush_queue(priv);
        if (err)
                netdev_warn(netdev, "Cannot flush queue, error %d\n", err);
 
-       if (dev->ops->dev_reset_chip) {
-               err = dev->ops->dev_reset_chip(dev, priv->channel);
+       if (ops->dev_reset_chip) {
+               err = ops->dev_reset_chip(dev, priv->channel);
                if (err)
                        netdev_warn(netdev, "Cannot reset card, error %d\n",
                                    err);
        }
 
-       err = dev->ops->dev_stop_chip(priv);
+       err = ops->dev_stop_chip(priv);
        if (err)
                netdev_warn(netdev, "Cannot stop device, error %d\n", err);
 
@@ -521,6 +559,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
 {
        struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
        struct kvaser_usb *dev = priv->dev;
+       const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
        struct net_device_stats *stats = &netdev->stats;
        struct kvaser_usb_tx_urb_context *context = NULL;
        struct urb *urb;
@@ -563,8 +602,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
                goto freeurb;
        }
 
-       buf = dev->ops->dev_frame_to_cmd(priv, skb, &cmd_len,
-                                        context->echo_index);
+       buf = ops->dev_frame_to_cmd(priv, skb, &cmd_len, context->echo_index);
        if (!buf) {
                stats->tx_dropped++;
                dev_kfree_skb(skb);
@@ -648,15 +686,16 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev)
        }
 }
 
-static int kvaser_usb_init_one(struct kvaser_usb *dev,
-                              const struct usb_device_id *id, int channel)
+static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
 {
        struct net_device *netdev;
        struct kvaser_usb_net_priv *priv;
+       const struct kvaser_usb_driver_info *driver_info = dev->driver_info;
+       const struct kvaser_usb_dev_ops *ops = driver_info->ops;
        int err;
 
-       if (dev->ops->dev_reset_chip) {
-               err = dev->ops->dev_reset_chip(dev, channel);
+       if (ops->dev_reset_chip) {
+               err = ops->dev_reset_chip(dev, channel);
                if (err)
                        return err;
        }
@@ -685,20 +724,19 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev,
        priv->can.state = CAN_STATE_STOPPED;
        priv->can.clock.freq = dev->cfg->clock.freq;
        priv->can.bittiming_const = dev->cfg->bittiming_const;
-       priv->can.do_set_bittiming = dev->ops->dev_set_bittiming;
-       priv->can.do_set_mode = dev->ops->dev_set_mode;
-       if ((id->driver_info & KVASER_USB_HAS_TXRX_ERRORS) ||
+       priv->can.do_set_bittiming = ops->dev_set_bittiming;
+       priv->can.do_set_mode = ops->dev_set_mode;
+       if ((driver_info->quirks & KVASER_USB_QUIRK_HAS_TXRX_ERRORS) ||
            (priv->dev->card_data.capabilities & KVASER_USB_CAP_BERR_CAP))
-               priv->can.do_get_berr_counter = dev->ops->dev_get_berr_counter;
-       if (id->driver_info & KVASER_USB_HAS_SILENT_MODE)
+               priv->can.do_get_berr_counter = ops->dev_get_berr_counter;
+       if (driver_info->quirks & KVASER_USB_QUIRK_HAS_SILENT_MODE)
                priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
 
        priv->can.ctrlmode_supported |= dev->card_data.ctrlmode_supported;
 
        if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
                priv->can.data_bittiming_const = dev->cfg->data_bittiming_const;
-               priv->can.do_set_data_bittiming =
-                                       dev->ops->dev_set_data_bittiming;
+               priv->can.do_set_data_bittiming = ops->dev_set_data_bittiming;
        }
 
        netdev->flags |= IFF_ECHO;
@@ -729,29 +767,22 @@ static int kvaser_usb_probe(struct usb_interface *intf,
        struct kvaser_usb *dev;
        int err;
        int i;
+       const struct kvaser_usb_driver_info *driver_info;
+       const struct kvaser_usb_dev_ops *ops;
+
+       driver_info = (const struct kvaser_usb_driver_info *)id->driver_info;
+       if (!driver_info)
+               return -ENODEV;
 
        dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return -ENOMEM;
 
-       if (kvaser_is_leaf(id)) {
-               dev->card_data.leaf.family = KVASER_LEAF;
-               dev->ops = &kvaser_usb_leaf_dev_ops;
-       } else if (kvaser_is_usbcan(id)) {
-               dev->card_data.leaf.family = KVASER_USBCAN;
-               dev->ops = &kvaser_usb_leaf_dev_ops;
-       } else if (kvaser_is_hydra(id)) {
-               dev->ops = &kvaser_usb_hydra_dev_ops;
-       } else {
-               dev_err(&intf->dev,
-                       "Product ID (%d) is not a supported Kvaser USB device\n",
-                       id->idProduct);
-               return -ENODEV;
-       }
-
        dev->intf = intf;
+       dev->driver_info = driver_info;
+       ops = driver_info->ops;
 
-       err = dev->ops->dev_setup_endpoints(dev);
+       err = ops->dev_setup_endpoints(dev);
        if (err) {
                dev_err(&intf->dev, "Cannot get usb endpoint(s)");
                return err;
@@ -765,22 +796,22 @@ static int kvaser_usb_probe(struct usb_interface *intf,
 
        dev->card_data.ctrlmode_supported = 0;
        dev->card_data.capabilities = 0;
-       err = dev->ops->dev_init_card(dev);
+       err = ops->dev_init_card(dev);
        if (err) {
                dev_err(&intf->dev,
                        "Failed to initialize card, error %d\n", err);
                return err;
        }
 
-       err = dev->ops->dev_get_software_info(dev);
+       err = ops->dev_get_software_info(dev);
        if (err) {
                dev_err(&intf->dev,
                        "Cannot get software info, error %d\n", err);
                return err;
        }
 
-       if (dev->ops->dev_get_software_details) {
-               err = dev->ops->dev_get_software_details(dev);
+       if (ops->dev_get_software_details) {
+               err = ops->dev_get_software_details(dev);
                if (err) {
                        dev_err(&intf->dev,
                                "Cannot get software details, error %d\n", err);
@@ -798,14 +829,14 @@ static int kvaser_usb_probe(struct usb_interface *intf,
 
        dev_dbg(&intf->dev, "Max outstanding tx = %d URBs\n", dev->max_tx_urbs);
 
-       err = dev->ops->dev_get_card_info(dev);
+       err = ops->dev_get_card_info(dev);
        if (err) {
                dev_err(&intf->dev, "Cannot get card info, error %d\n", err);
                return err;
        }
 
-       if (dev->ops->dev_get_capabilities) {
-               err = dev->ops->dev_get_capabilities(dev);
+       if (ops->dev_get_capabilities) {
+               err = ops->dev_get_capabilities(dev);
                if (err) {
                        dev_err(&intf->dev,
                                "Cannot get capabilities, error %d\n", err);
@@ -815,7 +846,7 @@ static int kvaser_usb_probe(struct usb_interface *intf,
        }
 
        for (i = 0; i < dev->nchannels; i++) {
-               err = kvaser_usb_init_one(dev, id, i);
+               err = kvaser_usb_init_one(dev, i);
                if (err) {
                        kvaser_usb_remove_interfaces(dev);
                        return err;
index a26823c..5d70844 100644 (file)
@@ -375,7 +375,7 @@ static const struct can_bittiming_const kvaser_usb_hydra_kcan_bittiming_c = {
        .brp_inc = 1,
 };
 
-static const struct can_bittiming_const kvaser_usb_hydra_flexc_bittiming_c = {
+const struct can_bittiming_const kvaser_usb_flexc_bittiming_const = {
        .name = "kvaser_usb_flex",
        .tseg1_min = 4,
        .tseg1_max = 16,
@@ -2052,7 +2052,7 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_flexc = {
                .freq = 24 * MEGA /* Hz */,
        },
        .timestamp_freq = 1,
-       .bittiming_const = &kvaser_usb_hydra_flexc_bittiming_c,
+       .bittiming_const = &kvaser_usb_flexc_bittiming_const,
 };
 
 static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_rt = {
index c805b99..cc809ec 100644 (file)
 #define USBCAN_ERROR_STATE_RX_ERROR    BIT(1)
 #define USBCAN_ERROR_STATE_BUSERROR    BIT(2)
 
-/* bittiming parameters */
-#define KVASER_USB_TSEG1_MIN           1
-#define KVASER_USB_TSEG1_MAX           16
-#define KVASER_USB_TSEG2_MIN           1
-#define KVASER_USB_TSEG2_MAX           8
-#define KVASER_USB_SJW_MAX             4
-#define KVASER_USB_BRP_MIN             1
-#define KVASER_USB_BRP_MAX             64
-#define KVASER_USB_BRP_INC             1
-
 /* ctrl modes */
 #define KVASER_CTRL_MODE_NORMAL                1
 #define KVASER_CTRL_MODE_SILENT                2
@@ -343,48 +333,68 @@ struct kvaser_usb_err_summary {
        };
 };
 
-static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = {
-       .name = "kvaser_usb",
-       .tseg1_min = KVASER_USB_TSEG1_MIN,
-       .tseg1_max = KVASER_USB_TSEG1_MAX,
-       .tseg2_min = KVASER_USB_TSEG2_MIN,
-       .tseg2_max = KVASER_USB_TSEG2_MAX,
-       .sjw_max = KVASER_USB_SJW_MAX,
-       .brp_min = KVASER_USB_BRP_MIN,
-       .brp_max = KVASER_USB_BRP_MAX,
-       .brp_inc = KVASER_USB_BRP_INC,
+static const struct can_bittiming_const kvaser_usb_leaf_m16c_bittiming_const = {
+       .name = "kvaser_usb_ucii",
+       .tseg1_min = 4,
+       .tseg1_max = 16,
+       .tseg2_min = 2,
+       .tseg2_max = 8,
+       .sjw_max = 4,
+       .brp_min = 1,
+       .brp_max = 16,
+       .brp_inc = 1,
+};
+
+static const struct can_bittiming_const kvaser_usb_leaf_m32c_bittiming_const = {
+       .name = "kvaser_usb_leaf",
+       .tseg1_min = 3,
+       .tseg1_max = 16,
+       .tseg2_min = 2,
+       .tseg2_max = 8,
+       .sjw_max = 4,
+       .brp_min = 2,
+       .brp_max = 128,
+       .brp_inc = 2,
 };
 
-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_8mhz = {
+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_usbcan_dev_cfg = {
        .clock = {
                .freq = 8 * MEGA /* Hz */,
        },
        .timestamp_freq = 1,
-       .bittiming_const = &kvaser_usb_leaf_bittiming_const,
+       .bittiming_const = &kvaser_usb_leaf_m16c_bittiming_const,
+};
+
+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_m32c_dev_cfg = {
+       .clock = {
+               .freq = 16 * MEGA /* Hz */,
+       },
+       .timestamp_freq = 1,
+       .bittiming_const = &kvaser_usb_leaf_m32c_bittiming_const,
 };
 
-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_16mhz = {
+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_16mhz = {
        .clock = {
                .freq = 16 * MEGA /* Hz */,
        },
        .timestamp_freq = 1,
-       .bittiming_const = &kvaser_usb_leaf_bittiming_const,
+       .bittiming_const = &kvaser_usb_flexc_bittiming_const,
 };
 
-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_24mhz = {
+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_24mhz = {
        .clock = {
                .freq = 24 * MEGA /* Hz */,
        },
        .timestamp_freq = 1,
-       .bittiming_const = &kvaser_usb_leaf_bittiming_const,
+       .bittiming_const = &kvaser_usb_flexc_bittiming_const,
 };
 
-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_32mhz = {
+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_32mhz = {
        .clock = {
                .freq = 32 * MEGA /* Hz */,
        },
        .timestamp_freq = 1,
-       .bittiming_const = &kvaser_usb_leaf_bittiming_const,
+       .bittiming_const = &kvaser_usb_flexc_bittiming_const,
 };
 
 static void *
@@ -404,7 +414,7 @@ kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv,
                                      sizeof(struct kvaser_cmd_tx_can);
                cmd->u.tx_can.channel = priv->channel;
 
-               switch (dev->card_data.leaf.family) {
+               switch (dev->driver_info->family) {
                case KVASER_LEAF:
                        cmd_tx_can_flags = &cmd->u.tx_can.leaf.flags;
                        break;
@@ -524,16 +534,23 @@ static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev,
        dev->fw_version = le32_to_cpu(softinfo->fw_version);
        dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx);
 
-       switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) {
-       case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK:
-               dev->cfg = &kvaser_usb_leaf_dev_cfg_16mhz;
-               break;
-       case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK:
-               dev->cfg = &kvaser_usb_leaf_dev_cfg_24mhz;
-               break;
-       case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK:
-               dev->cfg = &kvaser_usb_leaf_dev_cfg_32mhz;
-               break;
+       if (dev->driver_info->quirks & KVASER_USB_QUIRK_IGNORE_CLK_FREQ) {
+               /* Firmware expects bittiming parameters calculated for 16MHz
+                * clock, regardless of the actual clock
+                */
+               dev->cfg = &kvaser_usb_leaf_m32c_dev_cfg;
+       } else {
+               switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) {
+               case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK:
+                       dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_16mhz;
+                       break;
+               case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK:
+                       dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_24mhz;
+                       break;
+               case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK:
+                       dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_32mhz;
+                       break;
+               }
        }
 }
 
@@ -550,7 +567,7 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev)
        if (err)
                return err;
 
-       switch (dev->card_data.leaf.family) {
+       switch (dev->driver_info->family) {
        case KVASER_LEAF:
                kvaser_usb_leaf_get_software_info_leaf(dev, &cmd.u.leaf.softinfo);
                break;
@@ -558,7 +575,7 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev)
                dev->fw_version = le32_to_cpu(cmd.u.usbcan.softinfo.fw_version);
                dev->max_tx_urbs =
                        le16_to_cpu(cmd.u.usbcan.softinfo.max_outstanding_tx);
-               dev->cfg = &kvaser_usb_leaf_dev_cfg_8mhz;
+               dev->cfg = &kvaser_usb_leaf_usbcan_dev_cfg;
                break;
        }
 
@@ -597,7 +614,7 @@ static int kvaser_usb_leaf_get_card_info(struct kvaser_usb *dev)
 
        dev->nchannels = cmd.u.cardinfo.nchannels;
        if (dev->nchannels > KVASER_USB_MAX_NET_DEVICES ||
-           (dev->card_data.leaf.family == KVASER_USBCAN &&
+           (dev->driver_info->family == KVASER_USBCAN &&
             dev->nchannels > MAX_USBCAN_NET_DEVICES))
                return -EINVAL;
 
@@ -730,7 +747,7 @@ kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv,
            new_state < CAN_STATE_BUS_OFF)
                priv->can.can_stats.restarts++;
 
-       switch (dev->card_data.leaf.family) {
+       switch (dev->driver_info->family) {
        case KVASER_LEAF:
                if (es->leaf.error_factor) {
                        priv->can.can_stats.bus_error++;
@@ -809,7 +826,7 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev,
                }
        }
 
-       switch (dev->card_data.leaf.family) {
+       switch (dev->driver_info->family) {
        case KVASER_LEAF:
                if (es->leaf.error_factor) {
                        cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
@@ -999,7 +1016,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
        stats = &priv->netdev->stats;
 
        if ((cmd->u.rx_can_header.flag & MSG_FLAG_ERROR_FRAME) &&
-           (dev->card_data.leaf.family == KVASER_LEAF &&
+           (dev->driver_info->family == KVASER_LEAF &&
             cmd->id == CMD_LEAF_LOG_MESSAGE)) {
                kvaser_usb_leaf_leaf_rx_error(dev, cmd);
                return;
@@ -1015,7 +1032,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
                return;
        }
 
-       switch (dev->card_data.leaf.family) {
+       switch (dev->driver_info->family) {
        case KVASER_LEAF:
                rx_data = cmd->u.leaf.rx_can.data;
                break;
@@ -1030,7 +1047,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
                return;
        }
 
-       if (dev->card_data.leaf.family == KVASER_LEAF && cmd->id ==
+       if (dev->driver_info->family == KVASER_LEAF && cmd->id ==
            CMD_LEAF_LOG_MESSAGE) {
                cf->can_id = le32_to_cpu(cmd->u.leaf.log_message.id);
                if (cf->can_id & KVASER_EXTENDED_FRAME)
@@ -1128,14 +1145,14 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
                break;
 
        case CMD_LEAF_LOG_MESSAGE:
-               if (dev->card_data.leaf.family != KVASER_LEAF)
+               if (dev->driver_info->family != KVASER_LEAF)
                        goto warn;
                kvaser_usb_leaf_rx_can_msg(dev, cmd);
                break;
 
        case CMD_CHIP_STATE_EVENT:
        case CMD_CAN_ERROR_EVENT:
-               if (dev->card_data.leaf.family == KVASER_LEAF)
+               if (dev->driver_info->family == KVASER_LEAF)
                        kvaser_usb_leaf_leaf_rx_error(dev, cmd);
                else
                        kvaser_usb_leaf_usbcan_rx_error(dev, cmd);
@@ -1147,12 +1164,12 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
 
        /* Ignored commands */
        case CMD_USBCAN_CLOCK_OVERFLOW_EVENT:
-               if (dev->card_data.leaf.family != KVASER_USBCAN)
+               if (dev->driver_info->family != KVASER_USBCAN)
                        goto warn;
                break;
 
        case CMD_FLUSH_QUEUE_REPLY:
-               if (dev->card_data.leaf.family != KVASER_LEAF)
+               if (dev->driver_info->family != KVASER_LEAF)
                        goto warn;
                break;
 
index 8a3b7b1..e179d31 100644 (file)
@@ -258,7 +258,7 @@ static const struct can_bittiming_const xcan_bittiming_const_canfd2 = {
        .tseg2_min = 1,
        .tseg2_max = 128,
        .sjw_max = 128,
-       .brp_min = 2,
+       .brp_min = 1,
        .brp_max = 256,
        .brp_inc = 1,
 };
@@ -271,7 +271,7 @@ static const struct can_bittiming_const xcan_data_bittiming_const_canfd2 = {
        .tseg2_min = 1,
        .tseg2_max = 16,
        .sjw_max = 16,
-       .brp_min = 2,
+       .brp_min = 1,
        .brp_max = 256,
        .brp_inc = 1,
 };
index 87e81c6..be0edfa 100644 (file)
@@ -878,6 +878,11 @@ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port,
                if (duplex == DUPLEX_FULL)
                        reg |= DUPLX_MODE;
 
+               if (tx_pause)
+                       reg |= TXFLOW_CNTL;
+               if (rx_pause)
+                       reg |= RXFLOW_CNTL;
+
                core_writel(priv, reg, offset);
        }
 
index 2572c60..b28baab 100644 (file)
@@ -300,6 +300,7 @@ static int hellcreek_led_setup(struct hellcreek *hellcreek)
        const char *label, *state;
        int ret = -EINVAL;
 
+       of_node_get(hellcreek->dev->of_node);
        leds = of_find_node_by_name(hellcreek->dev->of_node, "leds");
        if (!leds) {
                dev_err(hellcreek->dev, "No LEDs specified in device tree!\n");
index 570d020..9c27b9b 100644 (file)
@@ -1886,6 +1886,8 @@ static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot,
 static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index,
                                      struct felix_stream_filter_counters *counters)
 {
+       mutex_lock(&ocelot->stats_lock);
+
        ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index),
                   SYS_STAT_CFG_STAT_VIEW_M,
                   SYS_STAT_CFG);
@@ -1900,6 +1902,8 @@ static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index,
                     SYS_STAT_CFG_STAT_VIEW(index) |
                     SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10),
                     SYS_STAT_CFG);
+
+       mutex_unlock(&ocelot->stats_lock);
 }
 
 static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port,
index 7e7fe5b..5ab7c0f 100644 (file)
@@ -5981,6 +5981,15 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)
                        release_sub_crqs(adapter, 0);
                        rc = init_sub_crqs(adapter);
                } else {
+                       /* no need to reinitialize completely, but we do
+                        * need to clean up transmits that were in flight
+                        * when we processed the reset.  Failure to do so
+                        * will confound the upper layer, usually TCP, by
+                        * creating the illusion of transmits that are
+                        * awaiting completion.
+                        */
+                       clean_tx_pools(adapter);
+
                        rc = reset_sub_crq_queues(adapter);
                }
        } else {
index 18558a0..407fe8f 100644 (file)
@@ -37,6 +37,7 @@
 #include <net/tc_act/tc_mirred.h>
 #include <net/udp_tunnel.h>
 #include <net/xdp_sock.h>
+#include <linux/bitfield.h>
 #include "i40e_type.h"
 #include "i40e_prototype.h"
 #include <linux/net/intel/i40e_client.h>
@@ -1092,6 +1093,21 @@ static inline void i40e_write_fd_input_set(struct i40e_pf *pf,
                          (u32)(val & 0xFFFFFFFFULL));
 }
 
+/**
+ * i40e_get_pf_count - get PCI PF count.
+ * @hw: pointer to a hw.
+ *
+ * Reports the function number of the highest PCI physical
+ * function plus 1 as it is loaded from the NVM.
+ *
+ * Return: PCI PF count.
+ **/
+static inline u32 i40e_get_pf_count(struct i40e_hw *hw)
+{
+       return FIELD_GET(I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK,
+                        rd32(hw, I40E_GLGEN_PCIFCNCNT));
+}
+
 /* needed by i40e_ethtool.c */
 int i40e_up(struct i40e_vsi *vsi);
 void i40e_down(struct i40e_vsi *vsi);
index 72576bb..aa786fd 100644 (file)
@@ -550,6 +550,47 @@ void i40e_pf_reset_stats(struct i40e_pf *pf)
        pf->hw_csum_rx_error = 0;
 }
 
+/**
+ * i40e_compute_pci_to_hw_id - compute index form PCI function.
+ * @vsi: ptr to the VSI to read from.
+ * @hw: ptr to the hardware info.
+ **/
+static u32 i40e_compute_pci_to_hw_id(struct i40e_vsi *vsi, struct i40e_hw *hw)
+{
+       int pf_count = i40e_get_pf_count(hw);
+
+       if (vsi->type == I40E_VSI_SRIOV)
+               return (hw->port * BIT(7)) / pf_count + vsi->vf_id;
+
+       return hw->port + BIT(7);
+}
+
+/**
+ * i40e_stat_update64 - read and update a 64 bit stat from the chip.
+ * @hw: ptr to the hardware info.
+ * @hireg: the high 32 bit reg to read.
+ * @loreg: the low 32 bit reg to read.
+ * @offset_loaded: has the initial offset been loaded yet.
+ * @offset: ptr to current offset value.
+ * @stat: ptr to the stat.
+ *
+ * Since the device stats are not reset at PFReset, they will not
+ * be zeroed when the driver starts.  We'll save the first values read
+ * and use them as offsets to be subtracted from the raw values in order
+ * to report stats that count from zero.
+ **/
+static void i40e_stat_update64(struct i40e_hw *hw, u32 hireg, u32 loreg,
+                              bool offset_loaded, u64 *offset, u64 *stat)
+{
+       u64 new_data;
+
+       new_data = rd64(hw, loreg);
+
+       if (!offset_loaded || new_data < *offset)
+               *offset = new_data;
+       *stat = new_data - *offset;
+}
+
 /**
  * i40e_stat_update48 - read and update a 48 bit stat from the chip
  * @hw: ptr to the hardware info
@@ -621,6 +662,34 @@ static void i40e_stat_update_and_clear32(struct i40e_hw *hw, u32 reg, u64 *stat)
        *stat += new_data;
 }
 
+/**
+ * i40e_stats_update_rx_discards - update rx_discards.
+ * @vsi: ptr to the VSI to be updated.
+ * @hw: ptr to the hardware info.
+ * @stat_idx: VSI's stat_counter_idx.
+ * @offset_loaded: ptr to the VSI's stat_offsets_loaded.
+ * @stat_offset: ptr to stat_offset to store first read of specific register.
+ * @stat: ptr to VSI's stat to be updated.
+ **/
+static void
+i40e_stats_update_rx_discards(struct i40e_vsi *vsi, struct i40e_hw *hw,
+                             int stat_idx, bool offset_loaded,
+                             struct i40e_eth_stats *stat_offset,
+                             struct i40e_eth_stats *stat)
+{
+       u64 rx_rdpc, rx_rxerr;
+
+       i40e_stat_update32(hw, I40E_GLV_RDPC(stat_idx), offset_loaded,
+                          &stat_offset->rx_discards, &rx_rdpc);
+       i40e_stat_update64(hw,
+                          I40E_GL_RXERR1H(i40e_compute_pci_to_hw_id(vsi, hw)),
+                          I40E_GL_RXERR1L(i40e_compute_pci_to_hw_id(vsi, hw)),
+                          offset_loaded, &stat_offset->rx_discards_other,
+                          &rx_rxerr);
+
+       stat->rx_discards = rx_rdpc + rx_rxerr;
+}
+
 /**
  * i40e_update_eth_stats - Update VSI-specific ethernet statistics counters.
  * @vsi: the VSI to be updated
@@ -680,6 +749,10 @@ void i40e_update_eth_stats(struct i40e_vsi *vsi)
                           I40E_GLV_BPTCL(stat_idx),
                           vsi->stat_offsets_loaded,
                           &oes->tx_broadcast, &es->tx_broadcast);
+
+       i40e_stats_update_rx_discards(vsi, hw, stat_idx,
+                                     vsi->stat_offsets_loaded, oes, es);
+
        vsi->stat_offsets_loaded = true;
 }
 
index 1908eed..7339003 100644 (file)
 #define I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT 0
 #define I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT 16
 #define I40E_GLGEN_MSRWD_MDIRDDATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT                0x001C0AB4 /* Reset: PCIR */
+#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT 0
+#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK  I40E_MASK(0x1F, I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT 16
+#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_MASK  I40E_MASK(0xFF, I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT)
 #define I40E_GLGEN_RSTAT 0x000B8188 /* Reset: POR */
 #define I40E_GLGEN_RSTAT_DEVSTATE_SHIFT 0
 #define I40E_GLGEN_RSTAT_DEVSTATE_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_DEVSTATE_SHIFT)
 #define I40E_VFQF_HKEY1_MAX_INDEX 12
 #define I40E_VFQF_HLUT1(_i, _VF) (0x00220000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */ /* Reset: CORER */
 #define I40E_VFQF_HLUT1_MAX_INDEX 15
+#define I40E_GL_RXERR1H(_i)             (0x00318004 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR1H_MAX_INDEX       143
+#define I40E_GL_RXERR1H_RXERR1H_SHIFT   0
+#define I40E_GL_RXERR1H_RXERR1H_MASK    I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR1H_RXERR1H_SHIFT)
+#define I40E_GL_RXERR1L(_i)             (0x00318000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR1L_MAX_INDEX       143
+#define I40E_GL_RXERR1L_RXERR1L_SHIFT   0
+#define I40E_GL_RXERR1L_RXERR1L_MASK    I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR1L_RXERR1L_SHIFT)
 #define I40E_GLPRT_BPRCH(_i) (0x003005E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_BPRCL(_i) (0x003005E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
 #define I40E_GLPRT_BPTCH(_i) (0x00300A04 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
index 36a4ca1..7b3f30b 100644 (file)
@@ -1172,6 +1172,7 @@ struct i40e_eth_stats {
        u64 tx_broadcast;               /* bptc */
        u64 tx_discards;                /* tdpc */
        u64 tx_errors;                  /* tepc */
+       u64 rx_discards_other;          /* rxerr1 */
 };
 
 /* Statistics collected per VEB per TC */
index 033ea71..86b0f21 100644 (file)
@@ -2147,6 +2147,10 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
                /* VFs only use TC 0 */
                vfres->vsi_res[0].qset_handle
                                          = le16_to_cpu(vsi->info.qs_handle[0]);
+               if (!(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_USO) && !vf->pf_set_mac) {
+                       i40e_del_mac_filter(vsi, vf->default_lan_addr.addr);
+                       eth_zero_addr(vf->default_lan_addr.addr);
+               }
                ether_addr_copy(vfres->vsi_res[0].default_mac_addr,
                                vf->default_lan_addr.addr);
        }
index cc51149..3d5d39a 100644 (file)
@@ -52,7 +52,7 @@
 
 #define    CN93_SDP_EPF_RINFO_SRN(val)           ((val) & 0xFF)
 #define    CN93_SDP_EPF_RINFO_RPVF(val)          (((val) >> 32) & 0xF)
-#define    CN93_SDP_EPF_RINFO_NVFS(val)          (((val) >> 48) && 0xFF)
+#define    CN93_SDP_EPF_RINFO_NVFS(val)          (((val) >> 48) & 0xFF)
 
 /* SDP Function select */
 #define    CN93_SDP_FUNC_SEL_EPF_BIT_POS         8
index 34bf11c..3a39a50 100644 (file)
@@ -4529,13 +4529,6 @@ static int mlx5e_policer_validate(const struct flow_action *action,
                return -EOPNOTSUPP;
        }
 
-       if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
-           act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
-               NL_SET_ERR_MSG_MOD(extack,
-                                  "Offload not supported when conform action is not pipe or ok");
-               return -EOPNOTSUPP;
-       }
-
        if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
            !flow_action_is_last_entry(action, act)) {
                NL_SET_ERR_MSG_MOD(extack,
@@ -4586,6 +4579,12 @@ static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv,
        flow_action_for_each(i, act, flow_action) {
                switch (act->id) {
                case FLOW_ACTION_POLICE:
+                       if (act->police.notexceed.act_id != FLOW_ACTION_CONTINUE) {
+                               NL_SET_ERR_MSG_MOD(extack,
+                                                  "Offload not supported when conform action is not continue");
+                               return -EOPNOTSUPP;
+                       }
+
                        err = mlx5e_policer_validate(flow_action, act, extack);
                        if (err)
                                return err;
index 9dbb573..0d8a006 100644 (file)
@@ -4415,6 +4415,8 @@ static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
        return 0;
 
 err_nexthop_neigh_init:
+       list_del(&nh->router_list_node);
+       mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
        mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
        return err;
 }
@@ -6740,6 +6742,7 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
                                  const struct fib6_info *rt)
 {
        struct net_device *dev = rt->fib6_nh->fib_nh_dev;
+       int err;
 
        nh->nhgi = nh_grp->nhgi;
        nh->nh_weight = rt->fib6_nh->fib_nh_weight;
@@ -6755,7 +6758,16 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
                return 0;
        nh->ifindex = dev->ifindex;
 
-       return mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
+       err = mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
+       if (err)
+               goto err_nexthop_type_init;
+
+       return 0;
+
+err_nexthop_type_init:
+       list_del(&nh->router_list_node);
+       mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
+       return err;
 }
 
 static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
index 5784c41..1d6e3b6 100644 (file)
@@ -994,7 +994,7 @@ static int lan966x_probe(struct platform_device *pdev)
        struct fwnode_handle *ports, *portnp;
        struct lan966x *lan966x;
        u8 mac_addr[ETH_ALEN];
-       int err, i;
+       int err;
 
        lan966x = devm_kzalloc(&pdev->dev, sizeof(*lan966x), GFP_KERNEL);
        if (!lan966x)
@@ -1025,11 +1025,7 @@ static int lan966x_probe(struct platform_device *pdev)
        if (err)
                return dev_err_probe(&pdev->dev, err, "Reset failed");
 
-       i = 0;
-       fwnode_for_each_available_child_node(ports, portnp)
-               ++i;
-
-       lan966x->num_phys_ports = i;
+       lan966x->num_phys_ports = NUM_PHYS_PORTS;
        lan966x->ports = devm_kcalloc(&pdev->dev, lan966x->num_phys_ports,
                                      sizeof(struct lan966x_port *),
                                      GFP_KERNEL);
index 3b86ddd..2787055 100644 (file)
@@ -34,6 +34,7 @@
 /* Reserved amount for (SRC, PRIO) at index 8*SRC + PRIO */
 #define QSYS_Q_RSRV                    95
 
+#define NUM_PHYS_PORTS                 8
 #define CPU_PORT                       8
 
 /* Reserved PGIDs */
index 3429660..5edc8b7 100644 (file)
@@ -396,6 +396,9 @@ static int sparx5_handle_port_mdb_add(struct net_device *dev,
        u32 mact_entry;
        int res, err;
 
+       if (!sparx5_netdevice_check(dev))
+               return -EOPNOTSUPP;
+
        if (netif_is_bridge_master(v->obj.orig_dev)) {
                sparx5_mact_learn(spx5, PGID_CPU, v->addr, v->vid);
                return 0;
@@ -466,6 +469,9 @@ static int sparx5_handle_port_mdb_del(struct net_device *dev,
        u32 mact_entry, res, pgid_entry[3];
        int err;
 
+       if (!sparx5_netdevice_check(dev))
+               return -EOPNOTSUPP;
+
        if (netif_is_bridge_master(v->obj.orig_dev)) {
                sparx5_mact_forget(spx5, v->addr, v->vid);
                return 0;
index 3098d66..1b7fdb4 100644 (file)
@@ -4190,7 +4190,6 @@ static void rtl8169_tso_csum_v1(struct sk_buff *skb, u32 *opts)
 static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
                                struct sk_buff *skb, u32 *opts)
 {
-       u32 transport_offset = (u32)skb_transport_offset(skb);
        struct skb_shared_info *shinfo = skb_shinfo(skb);
        u32 mss = shinfo->gso_size;
 
@@ -4207,7 +4206,7 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
                        WARN_ON_ONCE(1);
                }
 
-               opts[0] |= transport_offset << GTTCPHO_SHIFT;
+               opts[0] |= skb_transport_offset(skb) << GTTCPHO_SHIFT;
                opts[1] |= mss << TD1_MSS_SHIFT;
        } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                u8 ip_protocol;
@@ -4235,7 +4234,7 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
                else
                        WARN_ON_ONCE(1);
 
-               opts[1] |= transport_offset << TCPHO_SHIFT;
+               opts[1] |= skb_transport_offset(skb) << TCPHO_SHIFT;
        } else {
                unsigned int padto = rtl_quirk_packet_padto(tp, skb);
 
@@ -4402,14 +4401,13 @@ static netdev_features_t rtl8169_features_check(struct sk_buff *skb,
                                                struct net_device *dev,
                                                netdev_features_t features)
 {
-       int transport_offset = skb_transport_offset(skb);
        struct rtl8169_private *tp = netdev_priv(dev);
 
        if (skb_is_gso(skb)) {
                if (tp->mac_version == RTL_GIGA_MAC_VER_34)
                        features = rtl8168evl_fix_tso(skb, features);
 
-               if (transport_offset > GTTCPHO_MAX &&
+               if (skb_transport_offset(skb) > GTTCPHO_MAX &&
                    rtl_chip_supports_csum_v2(tp))
                        features &= ~NETIF_F_ALL_TSO;
        } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -4420,7 +4418,7 @@ static netdev_features_t rtl8169_features_check(struct sk_buff *skb,
                if (rtl_quirk_packet_padto(tp, skb))
                        features &= ~NETIF_F_CSUM_MASK;
 
-               if (transport_offset > TCPHO_MAX &&
+               if (skb_transport_offset(skb) > TCPHO_MAX &&
                    rtl_chip_supports_csum_v2(tp))
                        features &= ~NETIF_F_CSUM_MASK;
        }
index a0654e8..0329caf 100644 (file)
@@ -1515,14 +1515,14 @@ static void epic_remove_one(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct epic_private *ep = netdev_priv(dev);
 
+       unregister_netdev(dev);
        dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, ep->tx_ring,
                          ep->tx_ring_dma);
        dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE, ep->rx_ring,
                          ep->rx_ring_dma);
-       unregister_netdev(dev);
        pci_iounmap(pdev, ep->ioaddr);
-       pci_release_regions(pdev);
        free_netdev(dev);
+       pci_release_regions(pdev);
        pci_disable_device(pdev);
        /* pci_power_off(pdev, -1); */
 }
index 4578963..0f1e617 100644 (file)
@@ -88,8 +88,10 @@ static void asix_ax88772a_link_change_notify(struct phy_device *phydev)
        /* Reset PHY, otherwise MII_LPA will provide outdated information.
         * This issue is reproducible only with some link partner PHYs
         */
-       if (phydev->state == PHY_NOLINK && phydev->drv->soft_reset)
-               phydev->drv->soft_reset(phydev);
+       if (phydev->state == PHY_NOLINK) {
+               phy_init_hw(phydev);
+               phy_start_aneg(phydev);
+       }
 }
 
 static struct phy_driver asix_driver[] = {
index e6ad3a4..8549e0e 100644 (file)
@@ -229,9 +229,7 @@ static int dp83822_config_intr(struct phy_device *phydev)
                if (misr_status < 0)
                        return misr_status;
 
-               misr_status |= (DP83822_RX_ERR_HF_INT_EN |
-                               DP83822_FALSE_CARRIER_HF_INT_EN |
-                               DP83822_LINK_STAT_INT_EN |
+               misr_status |= (DP83822_LINK_STAT_INT_EN |
                                DP83822_ENERGY_DET_INT_EN |
                                DP83822_LINK_QUAL_INT_EN);
 
index ef62f35..8d3ee3a 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <linux/atomic.h>
+#include <linux/suspend.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
 #include <net/sock.h>
@@ -976,6 +977,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
        struct phy_driver *drv = phydev->drv;
        irqreturn_t ret;
 
+       /* Wakeup interrupts may occur during a system sleep transition.
+        * Postpone handling until the PHY has resumed.
+        */
+       if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+               struct net_device *netdev = phydev->attached_dev;
+
+               if (netdev) {
+                       struct device *parent = netdev->dev.parent;
+
+                       if (netdev->wol_enabled)
+                               pm_system_wakeup();
+                       else if (device_may_wakeup(&netdev->dev))
+                               pm_wakeup_dev_event(&netdev->dev, 0, true);
+                       else if (parent && device_may_wakeup(parent))
+                               pm_wakeup_dev_event(parent, 0, true);
+               }
+
+               phydev->irq_rerun = 1;
+               disable_irq_nosync(irq);
+               return IRQ_HANDLED;
+       }
+
        mutex_lock(&phydev->lock);
        ret = drv->handle_interrupt(phydev);
        mutex_unlock(&phydev->lock);
index 431a871..46acddd 100644 (file)
@@ -278,6 +278,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
        if (phydev->mac_managed_pm)
                return 0;
 
+       /* Wakeup interrupts may occur during the system sleep transition when
+        * the PHY is inaccessible. Set flag to postpone handling until the PHY
+        * has resumed. Wait for concurrent interrupt handler to complete.
+        */
+       if (phy_interrupt_is_valid(phydev)) {
+               phydev->irq_suspended = 1;
+               synchronize_irq(phydev->irq);
+       }
+
        /* We must stop the state machine manually, otherwise it stops out of
         * control, possibly with the phydev->lock held. Upon resume, netdev
         * may call phy routines that try to grab the same lock, and that may
@@ -315,6 +324,20 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
        if (ret < 0)
                return ret;
 no_resume:
+       if (phy_interrupt_is_valid(phydev)) {
+               phydev->irq_suspended = 0;
+               synchronize_irq(phydev->irq);
+
+               /* Rerun interrupts which were postponed by phy_interrupt()
+                * because they occurred during the system sleep transition.
+                */
+               if (phydev->irq_rerun) {
+                       phydev->irq_rerun = 0;
+                       enable_irq(phydev->irq);
+                       irq_wake_thread(phydev->irq, phydev);
+               }
+       }
+
        if (phydev->attached_dev && phydev->adjust_link)
                phy_start_machine(phydev);
 
index 9a5d5a1..e7b0e12 100644 (file)
@@ -2516,7 +2516,7 @@ static int sfp_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, sfp);
 
-       err = devm_add_action(sfp->dev, sfp_cleanup, sfp);
+       err = devm_add_action_or_reset(sfp->dev, sfp_cleanup, sfp);
        if (err < 0)
                return err;
 
index 87a635a..259b2b8 100644 (file)
@@ -273,6 +273,12 @@ static void tun_napi_init(struct tun_struct *tun, struct tun_file *tfile,
        }
 }
 
+static void tun_napi_enable(struct tun_file *tfile)
+{
+       if (tfile->napi_enabled)
+               napi_enable(&tfile->napi);
+}
+
 static void tun_napi_disable(struct tun_file *tfile)
 {
        if (tfile->napi_enabled)
@@ -634,7 +640,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
        tun = rtnl_dereference(tfile->tun);
 
        if (tun && clean) {
-               tun_napi_disable(tfile);
+               if (!tfile->detached)
+                       tun_napi_disable(tfile);
                tun_napi_del(tfile);
        }
 
@@ -653,8 +660,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
                if (clean) {
                        RCU_INIT_POINTER(tfile->tun, NULL);
                        sock_put(&tfile->sk);
-               } else
+               } else {
                        tun_disable_queue(tun, tfile);
+                       tun_napi_disable(tfile);
+               }
 
                synchronize_net();
                tun_flow_delete_by_queue(tun, tun->numqueues + 1);
@@ -727,6 +736,7 @@ static void tun_detach_all(struct net_device *dev)
                sock_put(&tfile->sk);
        }
        list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) {
+               tun_napi_del(tfile);
                tun_enable_queue(tfile);
                tun_queue_purge(tfile);
                xdp_rxq_info_unreg(&tfile->xdp_rxq);
@@ -807,6 +817,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
 
        if (tfile->detached) {
                tun_enable_queue(tfile);
+               tun_napi_enable(tfile);
        } else {
                sock_hold(&tfile->sk);
                tun_napi_init(tun, tfile, napi, napi_frags);
index 2c81236..45d3cc5 100644 (file)
         AX_MEDIUM_RE)
 
 #define AX88772_MEDIUM_DEFAULT \
-       (AX_MEDIUM_FD | AX_MEDIUM_RFC | \
-        AX_MEDIUM_TFC | AX_MEDIUM_PS | \
+       (AX_MEDIUM_FD | AX_MEDIUM_PS | \
         AX_MEDIUM_AC | AX_MEDIUM_RE)
 
 /* AX88772 & AX88178 RX_CTL values */
index 632fa6c..b4a1b7a 100644 (file)
@@ -431,6 +431,7 @@ void asix_adjust_link(struct net_device *netdev)
 
        asix_write_medium_mode(dev, mode, 0);
        phy_print_status(phydev);
+       usbnet_link_change(dev, phydev->link, 0);
 }
 
 int asix_write_gpio(struct usbnet *dev, u16 value, int sleep, int in_pm)
index 4704ed6..ac2d400 100644 (file)
@@ -1472,6 +1472,42 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
         * are bundled into this buffer and where we can find an array of
         * per-packet metadata (which contains elements encoded into u16).
         */
+
+       /* SKB contents for current firmware:
+        *   <packet 1> <padding>
+        *   ...
+        *   <packet N> <padding>
+        *   <per-packet metadata entry 1> <dummy header>
+        *   ...
+        *   <per-packet metadata entry N> <dummy header>
+        *   <padding2> <rx_hdr>
+        *
+        * where:
+        *   <packet N> contains pkt_len bytes:
+        *              2 bytes of IP alignment pseudo header
+        *              packet received
+        *   <per-packet metadata entry N> contains 4 bytes:
+        *              pkt_len and fields AX_RXHDR_*
+        *   <padding>  0-7 bytes to terminate at
+        *              8 bytes boundary (64-bit).
+        *   <padding2> 4 bytes to make rx_hdr terminate at
+        *              8 bytes boundary (64-bit)
+        *   <dummy-header> contains 4 bytes:
+        *              pkt_len=0 and AX_RXHDR_DROP_ERR
+        *   <rx-hdr>   contains 4 bytes:
+        *              pkt_cnt and hdr_off (offset of
+        *                <per-packet metadata entry 1>)
+        *
+        * pkt_cnt is number of entrys in the per-packet metadata.
+        * In current firmware there is 2 entrys per packet.
+        * The first points to the packet and the
+        *  second is a dummy header.
+        * This was done probably to align fields in 64-bit and
+        *  maintain compatibility with old firmware.
+        * This code assumes that <dummy header> and <padding2> are
+        *  optional.
+        */
+
        if (skb->len < 4)
                return 0;
        skb_trim(skb, skb->len - 4);
@@ -1485,51 +1521,66 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        /* Make sure that the bounds of the metadata array are inside the SKB
         * (and in front of the counter at the end).
         */
-       if (pkt_cnt * 2 + hdr_off > skb->len)
+       if (pkt_cnt * 4 + hdr_off > skb->len)
                return 0;
        pkt_hdr = (u32 *)(skb->data + hdr_off);
 
        /* Packets must not overlap the metadata array */
        skb_trim(skb, hdr_off);
 
-       for (; ; pkt_cnt--, pkt_hdr++) {
+       for (; pkt_cnt > 0; pkt_cnt--, pkt_hdr++) {
+               u16 pkt_len_plus_padd;
                u16 pkt_len;
 
                le32_to_cpus(pkt_hdr);
                pkt_len = (*pkt_hdr >> 16) & 0x1fff;
+               pkt_len_plus_padd = (pkt_len + 7) & 0xfff8;
 
-               if (pkt_len > skb->len)
+               /* Skip dummy header used for alignment
+                */
+               if (pkt_len == 0)
+                       continue;
+
+               if (pkt_len_plus_padd > skb->len)
                        return 0;
 
                /* Check CRC or runt packet */
-               if (((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) == 0) &&
-                   pkt_len >= 2 + ETH_HLEN) {
-                       bool last = (pkt_cnt == 0);
-
-                       if (last) {
-                               ax_skb = skb;
-                       } else {
-                               ax_skb = skb_clone(skb, GFP_ATOMIC);
-                               if (!ax_skb)
-                                       return 0;
-                       }
-                       ax_skb->len = pkt_len;
-                       /* Skip IP alignment pseudo header */
-                       skb_pull(ax_skb, 2);
-                       skb_set_tail_pointer(ax_skb, ax_skb->len);
-                       ax_skb->truesize = pkt_len + sizeof(struct sk_buff);
-                       ax88179_rx_checksum(ax_skb, pkt_hdr);
+               if ((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) ||
+                   pkt_len < 2 + ETH_HLEN) {
+                       dev->net->stats.rx_errors++;
+                       skb_pull(skb, pkt_len_plus_padd);
+                       continue;
+               }
 
-                       if (last)
-                               return 1;
+               /* last packet */
+               if (pkt_len_plus_padd == skb->len) {
+                       skb_trim(skb, pkt_len);
 
-                       usbnet_skb_return(dev, ax_skb);
+                       /* Skip IP alignment pseudo header */
+                       skb_pull(skb, 2);
+
+                       skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd);
+                       ax88179_rx_checksum(skb, pkt_hdr);
+                       return 1;
                }
 
-               /* Trim this packet away from the SKB */
-               if (!skb_pull(skb, (pkt_len + 7) & 0xFFF8))
+               ax_skb = skb_clone(skb, GFP_ATOMIC);
+               if (!ax_skb)
                        return 0;
+               skb_trim(ax_skb, pkt_len);
+
+               /* Skip IP alignment pseudo header */
+               skb_pull(ax_skb, 2);
+
+               skb->truesize = pkt_len_plus_padd +
+                               SKB_DATA_ALIGN(sizeof(struct sk_buff));
+               ax88179_rx_checksum(ax_skb, pkt_hdr);
+               usbnet_skb_return(dev, ax_skb);
+
+               skb_pull(skb, pkt_len_plus_padd);
        }
+
+       return 0;
 }
 
 static struct sk_buff *
index e7fe9c0..1a376ed 100644 (file)
@@ -781,7 +781,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
                        intf->altsetting->desc.bInterfaceNumber, 1)) {
                dev_err(dev, "Can't set altsetting 1.\n");
                ret = -EIO;
-               goto fail_mem;;
+               goto fail_mem;
        }
 
        netdev = alloc_etherdev(sizeof(struct catc));
index 1cb6dab..78a9275 100644 (file)
@@ -2004,7 +2004,7 @@ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
                   cmd, reqtype, value, index, size);
 
        if (size) {
-               buf = kmalloc(size, GFP_KERNEL);
+               buf = kmalloc(size, GFP_NOIO);
                if (!buf)
                        goto out;
        }
@@ -2036,7 +2036,7 @@ static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
                   cmd, reqtype, value, index, size);
 
        if (data) {
-               buf = kmemdup(data, size, GFP_KERNEL);
+               buf = kmemdup(data, size, GFP_NOIO);
                if (!buf)
                        goto out;
        } else {
@@ -2137,7 +2137,7 @@ static void usbnet_async_cmd_cb(struct urb *urb)
 int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
                           u16 value, u16 index, const void *data, u16 size)
 {
-       struct usb_ctrlrequest *req = NULL;
+       struct usb_ctrlrequest *req;
        struct urb *urb;
        int err = -ENOMEM;
        void *buf = NULL;
@@ -2155,7 +2155,7 @@ int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
                if (!buf) {
                        netdev_err(dev->net, "Error allocating buffer"
                                   " in %s!\n", __func__);
-                       goto fail_free;
+                       goto fail_free_urb;
                }
        }
 
@@ -2179,14 +2179,21 @@ int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
        if (err < 0) {
                netdev_err(dev->net, "Error submitting the control"
                           " message: status=%d\n", err);
-               goto fail_free;
+               goto fail_free_all;
        }
        return 0;
 
+fail_free_all:
+       kfree(req);
 fail_free_buf:
        kfree(buf);
-fail_free:
-       kfree(req);
+       /*
+        * avoid a double free
+        * needed because the flag can be set only
+        * after filling the URB
+        */
+       urb->transfer_flags = 0;
+fail_free_urb:
        usb_free_urb(urb);
 fail:
        return err;
index 969a679..356cf8d 100644 (file)
@@ -3642,14 +3642,20 @@ static int virtnet_probe(struct virtio_device *vdev)
        if (vi->has_rss || vi->has_rss_hash_report)
                virtnet_init_default_rss(vi);
 
-       err = register_netdev(dev);
+       /* serialize netdev register + virtio_device_ready() with ndo_open() */
+       rtnl_lock();
+
+       err = register_netdevice(dev);
        if (err) {
                pr_debug("virtio_net: registering device failed\n");
+               rtnl_unlock();
                goto free_failover;
        }
 
        virtio_device_ready(vdev);
 
+       rtnl_unlock();
+
        err = virtnet_cpu_notif_add(vi);
        if (err) {
                pr_debug("virtio_net: registering cpu notifier failed\n");
index 8c0b954..2409007 100644 (file)
@@ -66,6 +66,10 @@ module_param_named(max_queues, xennet_max_queues, uint, 0644);
 MODULE_PARM_DESC(max_queues,
                 "Maximum number of queues per virtual interface");
 
+static bool __read_mostly xennet_trusted = true;
+module_param_named(trusted, xennet_trusted, bool, 0644);
+MODULE_PARM_DESC(trusted, "Is the backend trusted");
+
 #define XENNET_TIMEOUT  (5 * HZ)
 
 static const struct ethtool_ops xennet_ethtool_ops;
@@ -173,6 +177,9 @@ struct netfront_info {
        /* Is device behaving sane? */
        bool broken;
 
+       /* Should skbs be bounced into a zeroed buffer? */
+       bool bounce;
+
        atomic_t rx_gso_checksum_fixup;
 };
 
@@ -271,7 +278,8 @@ static struct sk_buff *xennet_alloc_one_rx_buffer(struct netfront_queue *queue)
        if (unlikely(!skb))
                return NULL;
 
-       page = page_pool_dev_alloc_pages(queue->page_pool);
+       page = page_pool_alloc_pages(queue->page_pool,
+                                    GFP_ATOMIC | __GFP_NOWARN | __GFP_ZERO);
        if (unlikely(!page)) {
                kfree_skb(skb);
                return NULL;
@@ -665,6 +673,33 @@ static int xennet_xdp_xmit(struct net_device *dev, int n,
        return nxmit;
 }
 
+struct sk_buff *bounce_skb(const struct sk_buff *skb)
+{
+       unsigned int headerlen = skb_headroom(skb);
+       /* Align size to allocate full pages and avoid contiguous data leaks */
+       unsigned int size = ALIGN(skb_end_offset(skb) + skb->data_len,
+                                 XEN_PAGE_SIZE);
+       struct sk_buff *n = alloc_skb(size, GFP_ATOMIC | __GFP_ZERO);
+
+       if (!n)
+               return NULL;
+
+       if (!IS_ALIGNED((uintptr_t)n->head, XEN_PAGE_SIZE)) {
+               WARN_ONCE(1, "misaligned skb allocated\n");
+               kfree_skb(n);
+               return NULL;
+       }
+
+       /* Set the data pointer */
+       skb_reserve(n, headerlen);
+       /* Set the tail pointer and length */
+       skb_put(n, skb->len);
+
+       BUG_ON(skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len));
+
+       skb_copy_header(n, skb);
+       return n;
+}
 
 #define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1)
 
@@ -718,9 +753,13 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
 
        /* The first req should be at least ETH_HLEN size or the packet will be
         * dropped by netback.
+        *
+        * If the backend is not trusted bounce all data to zeroed pages to
+        * avoid exposing contiguous data on the granted page not belonging to
+        * the skb.
         */
-       if (unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
-               nskb = skb_copy(skb, GFP_ATOMIC);
+       if (np->bounce || unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
+               nskb = bounce_skb(skb);
                if (!nskb)
                        goto drop;
                dev_consume_skb_any(skb);
@@ -1053,8 +1092,10 @@ static int xennet_get_responses(struct netfront_queue *queue,
                        }
                }
                rcu_read_unlock();
-next:
+
                __skb_queue_tail(list, skb);
+
+next:
                if (!(rx->flags & XEN_NETRXF_more_data))
                        break;
 
@@ -2214,6 +2255,10 @@ static int talk_to_netback(struct xenbus_device *dev,
 
        info->netdev->irq = 0;
 
+       /* Check if backend is trusted. */
+       info->bounce = !xennet_trusted ||
+                      !xenbus_read_unsigned(dev->nodename, "trusted", 1);
+
        /* Check if backend supports multiple queues */
        max_queues = xenbus_read_unsigned(info->xbdev->otherend,
                                          "multi-queue-max-queues", 1);
@@ -2381,6 +2426,9 @@ static int xennet_connect(struct net_device *dev)
                return err;
        if (np->netback_has_xdp_headroom)
                pr_info("backend supports XDP headroom\n");
+       if (np->bounce)
+               dev_info(&np->xbdev->dev,
+                        "bouncing transmitted data to zeroed pages\n");
 
        /* talk_to_netback() sets the correct number of queues */
        num_queues = dev->real_num_tx_queues;
index ceef81d..01329b9 100644 (file)
@@ -167,9 +167,9 @@ static int nfcmrvl_i2c_parse_dt(struct device_node *node,
                pdata->irq_polarity = IRQF_TRIGGER_RISING;
 
        ret = irq_of_parse_and_map(node, 0);
-       if (ret < 0) {
-               pr_err("Unable to get irq, error: %d\n", ret);
-               return ret;
+       if (!ret) {
+               pr_err("Unable to get irq\n");
+               return -EINVAL;
        }
        pdata->irq = ret;
 
index a38e2fc..ad3359a 100644 (file)
@@ -115,9 +115,9 @@ static int nfcmrvl_spi_parse_dt(struct device_node *node,
        }
 
        ret = irq_of_parse_and_map(node, 0);
-       if (ret < 0) {
-               pr_err("Unable to get irq, error: %d\n", ret);
-               return ret;
+       if (!ret) {
+               pr_err("Unable to get irq\n");
+               return -EINVAL;
        }
        pdata->irq = ret;
 
index 7e451c1..ae2ba08 100644 (file)
@@ -122,7 +122,9 @@ static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy,
        skb_put_data(*skb, &header, NXP_NCI_FW_HDR_LEN);
 
        r = i2c_master_recv(client, skb_put(*skb, frame_len), frame_len);
-       if (r != frame_len) {
+       if (r < 0) {
+               goto fw_read_exit_free_skb;
+       } else if (r != frame_len) {
                nfc_err(&client->dev,
                        "Invalid frame length: %u (expected %zu)\n",
                        r, frame_len);
@@ -162,8 +164,13 @@ static int nxp_nci_i2c_nci_read(struct nxp_nci_i2c_phy *phy,
 
        skb_put_data(*skb, (void *)&header, NCI_CTRL_HDR_SIZE);
 
+       if (!header.plen)
+               return 0;
+
        r = i2c_master_recv(client, skb_put(*skb, header.plen), header.plen);
-       if (r != header.plen) {
+       if (r < 0) {
+               goto nci_read_exit_free_skb;
+       } else if (r != header.plen) {
                nfc_err(&client->dev,
                        "Invalid frame payload length: %u (expected %u)\n",
                        r, header.plen);
index a4fc17d..b38d035 100644 (file)
@@ -176,8 +176,8 @@ static int nvdimm_clear_badblocks_region(struct device *dev, void *data)
        ndr_end = nd_region->ndr_start + nd_region->ndr_size - 1;
 
        /* make sure we are in the region */
-       if (ctx->phys < nd_region->ndr_start
-                       || (ctx->phys + ctx->cleared) > ndr_end)
+       if (ctx->phys < nd_region->ndr_start ||
+           (ctx->phys + ctx->cleared - 1) > ndr_end)
                return 0;
 
        sector = (ctx->phys - nd_region->ndr_start) / 512;
index b3d9c29..ec6ac29 100644 (file)
@@ -4595,6 +4595,8 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl)
        nvme_stop_failfast_work(ctrl);
        flush_work(&ctrl->async_event_work);
        cancel_work_sync(&ctrl->fw_act_work);
+       if (ctrl->ops->stop_ctrl)
+               ctrl->ops->stop_ctrl(ctrl);
 }
 EXPORT_SYMBOL_GPL(nvme_stop_ctrl);
 
index 0da94b2..5558f88 100644 (file)
@@ -502,6 +502,7 @@ struct nvme_ctrl_ops {
        void (*free_ctrl)(struct nvme_ctrl *ctrl);
        void (*submit_async_event)(struct nvme_ctrl *ctrl);
        void (*delete_ctrl)(struct nvme_ctrl *ctrl);
+       void (*stop_ctrl)(struct nvme_ctrl *ctrl);
        int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
        void (*print_device_info)(struct nvme_ctrl *ctrl);
 };
index d7b24ee..193b447 100644 (file)
@@ -3465,12 +3465,16 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_DEVICE(0x1987, 0x5012),   /* Phison E12 */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1987, 0x5016),   /* Phison E16 */
-               .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+               .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN |
+                               NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1b4b, 0x1092),   /* Lexar 256 GB SSD */
                .driver_data = NVME_QUIRK_NO_NS_DESC_LIST |
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+       { PCI_DEVICE(0x1cc1, 0x33f8),   /* ADATA IM2P33F8ABR1 1 TB */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x10ec, 0x5762),   /* ADATA SX6000LNP */
-               .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+               .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN |
+                               NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1cc1, 0x8201),   /* ADATA SX8200PNP 512GB */
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
index f2a5e1e..46c2dcf 100644 (file)
@@ -1048,6 +1048,14 @@ static void nvme_rdma_teardown_io_queues(struct nvme_rdma_ctrl *ctrl,
        }
 }
 
+static void nvme_rdma_stop_ctrl(struct nvme_ctrl *nctrl)
+{
+       struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
+
+       cancel_work_sync(&ctrl->err_work);
+       cancel_delayed_work_sync(&ctrl->reconnect_work);
+}
+
 static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)
 {
        struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
@@ -2252,9 +2260,6 @@ static const struct blk_mq_ops nvme_rdma_admin_mq_ops = {
 
 static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
 {
-       cancel_work_sync(&ctrl->err_work);
-       cancel_delayed_work_sync(&ctrl->reconnect_work);
-
        nvme_rdma_teardown_io_queues(ctrl, shutdown);
        nvme_stop_admin_queue(&ctrl->ctrl);
        if (shutdown)
@@ -2304,6 +2309,7 @@ static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
        .submit_async_event     = nvme_rdma_submit_async_event,
        .delete_ctrl            = nvme_rdma_delete_ctrl,
        .get_address            = nvmf_get_address,
+       .stop_ctrl              = nvme_rdma_stop_ctrl,
 };
 
 /*
index bb67538..7a9e6ff 100644 (file)
@@ -1180,8 +1180,7 @@ done:
        } else if (ret < 0) {
                dev_err(queue->ctrl->ctrl.device,
                        "failed to send request %d\n", ret);
-               if (ret != -EPIPE && ret != -ECONNRESET)
-                       nvme_tcp_fail_request(queue->request);
+               nvme_tcp_fail_request(queue->request);
                nvme_tcp_done_send_req(queue);
        }
        return ret;
@@ -2194,9 +2193,6 @@ static void nvme_tcp_error_recovery_work(struct work_struct *work)
 
 static void nvme_tcp_teardown_ctrl(struct nvme_ctrl *ctrl, bool shutdown)
 {
-       cancel_work_sync(&to_tcp_ctrl(ctrl)->err_work);
-       cancel_delayed_work_sync(&to_tcp_ctrl(ctrl)->connect_work);
-
        nvme_tcp_teardown_io_queues(ctrl, shutdown);
        nvme_stop_admin_queue(ctrl);
        if (shutdown)
@@ -2236,6 +2232,12 @@ out_fail:
        nvme_tcp_reconnect_or_remove(ctrl);
 }
 
+static void nvme_tcp_stop_ctrl(struct nvme_ctrl *ctrl)
+{
+       cancel_work_sync(&to_tcp_ctrl(ctrl)->err_work);
+       cancel_delayed_work_sync(&to_tcp_ctrl(ctrl)->connect_work);
+}
+
 static void nvme_tcp_free_ctrl(struct nvme_ctrl *nctrl)
 {
        struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
@@ -2557,6 +2559,7 @@ static const struct nvme_ctrl_ops nvme_tcp_ctrl_ops = {
        .submit_async_event     = nvme_tcp_submit_async_event,
        .delete_ctrl            = nvme_tcp_delete_ctrl,
        .get_address            = nvmf_get_address,
+       .stop_ctrl              = nvme_tcp_stop_ctrl,
 };
 
 static bool
index b5f8525..37c7f4c 100644 (file)
@@ -69,7 +69,7 @@ TRACE_EVENT(nvme_setup_cmd,
                __entry->metadata = !!blk_integrity_rq(req);
                __entry->fctype = cmd->fabrics.fctype;
                __assign_disk_name(__entry->disk, req->q->disk);
-               memcpy(__entry->cdw10, &cmd->common.cdw10,
+               memcpy(__entry->cdw10, &cmd->common.cdws,
                        sizeof(__entry->cdw10));
            ),
            TP_printk("nvme%d: %sqid=%d, cmdid=%u, nsid=%u, flags=0x%x, meta=0x%x, cmd=(%s %s)",
index e44b298..ff77c3d 100644 (file)
@@ -773,11 +773,31 @@ static ssize_t nvmet_passthru_io_timeout_store(struct config_item *item,
 }
 CONFIGFS_ATTR(nvmet_passthru_, io_timeout);
 
+static ssize_t nvmet_passthru_clear_ids_show(struct config_item *item,
+               char *page)
+{
+       return sprintf(page, "%u\n", to_subsys(item->ci_parent)->clear_ids);
+}
+
+static ssize_t nvmet_passthru_clear_ids_store(struct config_item *item,
+               const char *page, size_t count)
+{
+       struct nvmet_subsys *subsys = to_subsys(item->ci_parent);
+       unsigned int clear_ids;
+
+       if (kstrtouint(page, 0, &clear_ids))
+               return -EINVAL;
+       subsys->clear_ids = clear_ids;
+       return count;
+}
+CONFIGFS_ATTR(nvmet_passthru_, clear_ids);
+
 static struct configfs_attribute *nvmet_passthru_attrs[] = {
        &nvmet_passthru_attr_device_path,
        &nvmet_passthru_attr_enable,
        &nvmet_passthru_attr_admin_timeout,
        &nvmet_passthru_attr_io_timeout,
+       &nvmet_passthru_attr_clear_ids,
        NULL,
 };
 
index 90e7532..c27660a 100644 (file)
@@ -1374,6 +1374,12 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
        ctrl->port = req->port;
        ctrl->ops = req->ops;
 
+#ifdef CONFIG_NVME_TARGET_PASSTHRU
+       /* By default, set loop targets to clear IDS by default */
+       if (ctrl->port->disc_addr.trtype == NVMF_TRTYPE_LOOP)
+               subsys->clear_ids = 1;
+#endif
+
        INIT_WORK(&ctrl->async_event_work, nvmet_async_event_work);
        INIT_LIST_HEAD(&ctrl->async_events);
        INIT_RADIX_TREE(&ctrl->p2p_ns_map, GFP_KERNEL);
index 6981875..2b3e571 100644 (file)
@@ -249,6 +249,7 @@ struct nvmet_subsys {
        struct config_group     passthru_group;
        unsigned int            admin_timeout;
        unsigned int            io_timeout;
+       unsigned int            clear_ids;
 #endif /* CONFIG_NVME_TARGET_PASSTHRU */
 
 #ifdef CONFIG_BLK_DEV_ZONED
index b1f7efa..6f39a29 100644 (file)
@@ -30,6 +30,53 @@ void nvmet_passthrough_override_cap(struct nvmet_ctrl *ctrl)
                ctrl->cap &= ~(1ULL << 43);
 }
 
+static u16 nvmet_passthru_override_id_descs(struct nvmet_req *req)
+{
+       struct nvmet_ctrl *ctrl = req->sq->ctrl;
+       u16 status = NVME_SC_SUCCESS;
+       int pos, len;
+       bool csi_seen = false;
+       void *data;
+       u8 csi;
+
+       if (!ctrl->subsys->clear_ids)
+               return status;
+
+       data = kzalloc(NVME_IDENTIFY_DATA_SIZE, GFP_KERNEL);
+       if (!data)
+               return NVME_SC_INTERNAL;
+
+       status = nvmet_copy_from_sgl(req, 0, data, NVME_IDENTIFY_DATA_SIZE);
+       if (status)
+               goto out_free;
+
+       for (pos = 0; pos < NVME_IDENTIFY_DATA_SIZE; pos += len) {
+               struct nvme_ns_id_desc *cur = data + pos;
+
+               if (cur->nidl == 0)
+                       break;
+               if (cur->nidt == NVME_NIDT_CSI) {
+                       memcpy(&csi, cur + 1, NVME_NIDT_CSI_LEN);
+                       csi_seen = true;
+                       break;
+               }
+               len = sizeof(struct nvme_ns_id_desc) + cur->nidl;
+       }
+
+       memset(data, 0, NVME_IDENTIFY_DATA_SIZE);
+       if (csi_seen) {
+               struct nvme_ns_id_desc *cur = data;
+
+               cur->nidt = NVME_NIDT_CSI;
+               cur->nidl = NVME_NIDT_CSI_LEN;
+               memcpy(cur + 1, &csi, NVME_NIDT_CSI_LEN);
+       }
+       status = nvmet_copy_to_sgl(req, 0, data, NVME_IDENTIFY_DATA_SIZE);
+out_free:
+       kfree(data);
+       return status;
+}
+
 static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req)
 {
        struct nvmet_ctrl *ctrl = req->sq->ctrl;
@@ -152,6 +199,11 @@ static u16 nvmet_passthru_override_id_ns(struct nvmet_req *req)
         */
        id->mc = 0;
 
+       if (req->sq->ctrl->subsys->clear_ids) {
+               memset(id->nguid, 0, NVME_NIDT_NGUID_LEN);
+               memset(id->eui64, 0, NVME_NIDT_EUI64_LEN);
+       }
+
        status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
 
 out_free:
@@ -176,6 +228,9 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
                case NVME_ID_CNS_NS:
                        nvmet_passthru_override_id_ns(req);
                        break;
+               case NVME_ID_CNS_NS_DESC_LIST:
+                       nvmet_passthru_override_id_descs(req);
+                       break;
                }
        } else if (status < 0)
                status = NVME_SC_INTERNAL;
index 2793554..0a95425 100644 (file)
@@ -405,7 +405,7 @@ err:
        return NVME_SC_INTERNAL;
 }
 
-static void nvmet_tcp_send_ddgst(struct ahash_request *hash,
+static void nvmet_tcp_calc_ddgst(struct ahash_request *hash,
                struct nvmet_tcp_cmd *cmd)
 {
        ahash_request_set_crypt(hash, cmd->req.sg,
@@ -413,23 +413,6 @@ static void nvmet_tcp_send_ddgst(struct ahash_request *hash,
        crypto_ahash_digest(hash);
 }
 
-static void nvmet_tcp_recv_ddgst(struct ahash_request *hash,
-               struct nvmet_tcp_cmd *cmd)
-{
-       struct scatterlist sg;
-       struct kvec *iov;
-       int i;
-
-       crypto_ahash_init(hash);
-       for (i = 0, iov = cmd->iov; i < cmd->nr_mapped; i++, iov++) {
-               sg_init_one(&sg, iov->iov_base, iov->iov_len);
-               ahash_request_set_crypt(hash, &sg, NULL, iov->iov_len);
-               crypto_ahash_update(hash);
-       }
-       ahash_request_set_crypt(hash, NULL, (void *)&cmd->exp_ddgst, 0);
-       crypto_ahash_final(hash);
-}
-
 static void nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd *cmd)
 {
        struct nvme_tcp_data_pdu *pdu = cmd->data_pdu;
@@ -454,7 +437,7 @@ static void nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd *cmd)
 
        if (queue->data_digest) {
                pdu->hdr.flags |= NVME_TCP_F_DDGST;
-               nvmet_tcp_send_ddgst(queue->snd_hash, cmd);
+               nvmet_tcp_calc_ddgst(queue->snd_hash, cmd);
        }
 
        if (cmd->queue->hdr_digest) {
@@ -1137,7 +1120,7 @@ static void nvmet_tcp_prep_recv_ddgst(struct nvmet_tcp_cmd *cmd)
 {
        struct nvmet_tcp_queue *queue = cmd->queue;
 
-       nvmet_tcp_recv_ddgst(queue->rcv_hash, cmd);
+       nvmet_tcp_calc_ddgst(queue->rcv_hash, cmd);
        queue->offset = 0;
        queue->left = NVME_TCP_DIGEST_LENGTH;
        queue->rcv_state = NVMET_TCP_RECV_DDGST;
index c94e24a..83d47ff 100644 (file)
@@ -236,11 +236,11 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
                const struct aspeed_sig_expr **funcs;
                const struct aspeed_sig_expr ***prios;
 
-               pr_debug("Muxing pin %s for %s\n", pdesc->name, pfunc->name);
-
                if (!pdesc)
                        return -EINVAL;
 
+               pr_debug("Muxing pin %s for %s\n", pdesc->name, pfunc->name);
+
                prios = pdesc->prios;
 
                if (!prios)
index c0630f6..417e41b 100644 (file)
@@ -239,6 +239,7 @@ static const struct pinctrl_pin_desc imx93_pinctrl_pads[] = {
 static const struct imx_pinctrl_soc_info imx93_pinctrl_info = {
        .pins = imx93_pinctrl_pads,
        .npins = ARRAY_SIZE(imx93_pinctrl_pads),
+       .flags = ZERO_OFFSET_VALID,
        .gpr_compatible = "fsl,imx93-iomuxc-gpr",
 };
 
index 57a33fb..14bcca7 100644 (file)
@@ -1338,16 +1338,18 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode
        bank->secure_control = pctl->match_data->secure_control;
        spin_lock_init(&bank->lock);
 
-       /* create irq hierarchical domain */
-       bank->fwnode = fwnode;
+       if (pctl->domain) {
+               /* create irq hierarchical domain */
+               bank->fwnode = fwnode;
 
-       bank->domain = irq_domain_create_hierarchy(pctl->domain, 0,
-                                       STM32_GPIO_IRQ_LINE, bank->fwnode,
-                                       &stm32_gpio_domain_ops, bank);
+               bank->domain = irq_domain_create_hierarchy(pctl->domain, 0, STM32_GPIO_IRQ_LINE,
+                                                          bank->fwnode, &stm32_gpio_domain_ops,
+                                                          bank);
 
-       if (!bank->domain) {
-               err = -ENODEV;
-               goto err_clk;
+               if (!bank->domain) {
+                       err = -ENODEV;
+                       goto err_clk;
+               }
        }
 
        err = gpiochip_add_data(&bank->gpio_chip, bank);
@@ -1510,6 +1512,8 @@ int stm32_pctl_probe(struct platform_device *pdev)
        pctl->domain = stm32_pctrl_get_irq_domain(pdev);
        if (IS_ERR(pctl->domain))
                return PTR_ERR(pctl->domain);
+       if (!pctl->domain)
+               dev_warn(dev, "pinctrl without interrupt support\n");
 
        /* hwspinlock is optional */
        hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
index 4ada803..b5c1a8f 100644 (file)
@@ -158,26 +158,26 @@ static const struct sunxi_desc_pin sun8i_a83t_pins[] = {
        SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
-                 SUNXI_FUNCTION(0x2, "nand"),          /* DQ6 */
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* DQ6 */
                  SUNXI_FUNCTION(0x3, "mmc2")),         /* D6 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
-                 SUNXI_FUNCTION(0x2, "nand"),          /* DQ7 */
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* DQ7 */
                  SUNXI_FUNCTION(0x3, "mmc2")),         /* D7 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
-                 SUNXI_FUNCTION(0x2, "nand"),          /* DQS */
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* DQS */
                  SUNXI_FUNCTION(0x3, "mmc2")),         /* RST */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 17),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
-                 SUNXI_FUNCTION(0x2, "nand")),         /* CE2 */
+                 SUNXI_FUNCTION(0x2, "nand0")),        /* CE2 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 18),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
-                 SUNXI_FUNCTION(0x2, "nand")),         /* CE3 */
+                 SUNXI_FUNCTION(0x2, "nand0")),        /* CE3 */
        /* Hole */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
index d9327d7..dd92840 100644 (file)
@@ -544,6 +544,8 @@ static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin,
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        int i;
 
+       pin -= pctl->desc->pin_base;
+
        for (i = 0; i < num_configs; i++) {
                enum pin_config_param param;
                unsigned long flags;
index 2923daf..7b9c107 100644 (file)
@@ -890,6 +890,7 @@ nvsw_sn2201_create_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
                                  int size)
 {
        struct mlxreg_hotplug_device *dev = devs;
+       int ret;
        int i;
 
        /* Create I2C static devices. */
@@ -901,6 +902,7 @@ nvsw_sn2201_create_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
                                dev->nr, dev->brdinfo->addr);
 
                        dev->adapter = NULL;
+                       ret = PTR_ERR(dev->client);
                        goto fail_create_static_devices;
                }
        }
@@ -914,7 +916,7 @@ fail_create_static_devices:
                dev->client = NULL;
                dev->adapter = NULL;
        }
-       return IS_ERR(dev->client);
+       return ret;
 }
 
 static void nvsw_sn2201_destroy_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
index f08ad85..bc4013e 100644 (file)
@@ -945,6 +945,8 @@ config PANASONIC_LAPTOP
        tristate "Panasonic Laptop Extras"
        depends on INPUT && ACPI
        depends on BACKLIGHT_CLASS_DEVICE
+       depends on ACPI_VIDEO=n || ACPI_VIDEO
+       depends on SERIO_I8042 || SERIO_I8042 = n
        select INPUT_SPARSEKMAP
        help
          This driver adds support for access to backlight control and hotkeys
index 0d8cb22..bc7020e 100644 (file)
@@ -89,6 +89,7 @@ enum hp_wmi_event_ids {
        HPWMI_BACKLIT_KB_BRIGHTNESS     = 0x0D,
        HPWMI_PEAKSHIFT_PERIOD          = 0x0F,
        HPWMI_BATTERY_CHARGE_PERIOD     = 0x10,
+       HPWMI_SANITIZATION_MODE         = 0x17,
 };
 
 /*
@@ -853,6 +854,8 @@ static void hp_wmi_notify(u32 value, void *context)
                break;
        case HPWMI_BATTERY_CHARGE_PERIOD:
                break;
+       case HPWMI_SANITIZATION_MODE:
+               break;
        default:
                pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
                break;
index 3ccb7b7..abd0c81 100644 (file)
@@ -152,6 +152,10 @@ static bool no_bt_rfkill;
 module_param(no_bt_rfkill, bool, 0444);
 MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
 
+static bool allow_v4_dytc;
+module_param(allow_v4_dytc, bool, 0444);
+MODULE_PARM_DESC(allow_v4_dytc, "Enable DYTC version 4 platform-profile support.");
+
 /*
  * ACPI Helpers
  */
@@ -871,12 +875,18 @@ static void dytc_profile_refresh(struct ideapad_private *priv)
 static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = {
        {
                /* Ideapad 5 Pro 16ACH6 */
-               .ident = "LENOVO 82L5",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "82L5")
                }
        },
+       {
+               /* Ideapad 5 15ITL05 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad 5 15ITL05")
+               }
+       },
        {}
 };
 
@@ -901,13 +911,16 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
 
        dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
 
-       if (dytc_version < 5) {
-               if (dytc_version < 4 || !dmi_check_system(ideapad_dytc_v4_allow_table)) {
-                       dev_info(&priv->platform_device->dev,
-                                "DYTC_VERSION is less than 4 or is not allowed: %d\n",
-                                dytc_version);
-                       return -ENODEV;
-               }
+       if (dytc_version < 4) {
+               dev_info(&priv->platform_device->dev, "DYTC_VERSION < 4 is not supported\n");
+               return -ENODEV;
+       }
+
+       if (dytc_version < 5 &&
+           !(allow_v4_dytc || dmi_check_system(ideapad_dytc_v4_allow_table))) {
+               dev_info(&priv->platform_device->dev,
+                        "DYTC_VERSION 4 support may not work. Pass ideapad_laptop.allow_v4_dytc=Y on the kernel commandline to enable\n");
+               return -ENODEV;
        }
 
        priv->dytc = kzalloc(sizeof(*priv->dytc), GFP_KERNEL);
index 40183bd..a1fe1e0 100644 (file)
@@ -1911,6 +1911,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {
        X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L,      &icl_reg_map),
        X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE,          &tgl_reg_map),
        X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L,         &tgl_reg_map),
+       X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N,         &tgl_reg_map),
        X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE,           &adl_reg_map),
        X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P,        &tgl_reg_map),
        {}
index 37850d0..615e39c 100644 (file)
  *             - v0.1  start from toshiba_acpi driver written by John Belmonte
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
+#include <linux/acpi.h>
 #include <linux/backlight.h>
 #include <linux/ctype.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/acpi.h>
+#include <linux/i8042.h>
+#include <linux/init.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
-
+#include <linux/seq_file.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <acpi/video.h>
 
 MODULE_AUTHOR("Hiroshi Miura <miura@da-cha.org>");
 MODULE_AUTHOR("David Bronaugh <dbronaugh@linuxboxen.org>");
@@ -241,6 +243,42 @@ struct pcc_acpi {
        struct platform_device  *platform;
 };
 
+/*
+ * On some Panasonic models the volume up / down / mute keys send duplicate
+ * keypress events over the PS/2 kbd interface, filter these out.
+ */
+static bool panasonic_i8042_filter(unsigned char data, unsigned char str,
+                                  struct serio *port)
+{
+       static bool extended;
+
+       if (str & I8042_STR_AUXDATA)
+               return false;
+
+       if (data == 0xe0) {
+               extended = true;
+               return true;
+       } else if (extended) {
+               extended = false;
+
+               switch (data & 0x7f) {
+               case 0x20: /* e0 20 / e0 a0, Volume Mute press / release */
+               case 0x2e: /* e0 2e / e0 ae, Volume Down press / release */
+               case 0x30: /* e0 30 / e0 b0, Volume Up press / release */
+                       return true;
+               default:
+                       /*
+                        * Report the previously filtered e0 before continuing
+                        * with the next non-filtered byte.
+                        */
+                       serio_interrupt(port, 0xe0, 0);
+                       return false;
+               }
+       }
+
+       return false;
+}
+
 /* method access functions */
 static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
 {
@@ -762,6 +800,8 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
        struct input_dev *hotk_input_dev = pcc->input_dev;
        int rc;
        unsigned long long result;
+       unsigned int key;
+       unsigned int updown;
 
        rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
                                   NULL, &result);
@@ -770,20 +810,27 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
                return;
        }
 
+       key = result & 0xf;
+       updown = result & 0x80; /* 0x80 == key down; 0x00 = key up */
+
        /* hack: some firmware sends no key down for sleep / hibernate */
-       if ((result & 0xf) == 0x7 || (result & 0xf) == 0xa) {
-               if (result & 0x80)
+       if (key == 7 || key == 10) {
+               if (updown)
                        sleep_keydown_seen = 1;
                if (!sleep_keydown_seen)
                        sparse_keymap_report_event(hotk_input_dev,
-                                       result & 0xf, 0x80, false);
+                                       key, 0x80, false);
        }
 
-       if ((result & 0xf) == 0x7 || (result & 0xf) == 0x9 || (result & 0xf) == 0xa) {
-               if (!sparse_keymap_report_event(hotk_input_dev,
-                                               result & 0xf, result & 0x80, false))
-                       pr_err("Unknown hotkey event: 0x%04llx\n", result);
-       }
+       /*
+        * Don't report brightness key-presses if they are also reported
+        * by the ACPI video bus.
+        */
+       if ((key == 1 || key == 2) && acpi_video_handles_brightness_key_presses())
+               return;
+
+       if (!sparse_keymap_report_event(hotk_input_dev, key, updown, false))
+               pr_err("Unknown hotkey event: 0x%04llx\n", result);
 }
 
 static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
@@ -997,6 +1044,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
                pcc->platform = NULL;
        }
 
+       i8042_install_filter(panasonic_i8042_filter);
        return 0;
 
 out_platform:
@@ -1020,6 +1068,8 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device)
        if (!device || !pcc)
                return -EINVAL;
 
+       i8042_remove_filter(panasonic_i8042_filter);
+
        if (pcc->platform) {
                device_remove_file(&pcc->platform->dev, &dev_attr_cdpower);
                platform_device_unregister(pcc->platform);
index e6cb4a1..a8b3830 100644 (file)
@@ -4529,6 +4529,7 @@ static void thinkpad_acpi_amd_s2idle_restore(void)
        iounmap(addr);
 cleanup_resource:
        release_resource(res);
+       kfree(res);
 }
 
 static struct acpi_s2idle_dev_ops thinkpad_acpi_s2idle_dev_ops = {
@@ -10299,21 +10300,15 @@ static struct ibm_struct proxsensor_driver_data = {
 #define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_MMC_BALANCE, 0)
 #define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_MMC_BALANCE, 1)
 
-enum dytc_profile_funcmode {
-       DYTC_FUNCMODE_NONE = 0,
-       DYTC_FUNCMODE_MMC,
-       DYTC_FUNCMODE_PSC,
-};
-
-static enum dytc_profile_funcmode dytc_profile_available;
 static enum platform_profile_option dytc_current_profile;
 static atomic_t dytc_ignore_event = ATOMIC_INIT(0);
 static DEFINE_MUTEX(dytc_mutex);
+static int dytc_capabilities;
 static bool dytc_mmc_get_available;
 
 static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile)
 {
-       if (dytc_profile_available == DYTC_FUNCMODE_MMC) {
+       if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
                switch (dytcmode) {
                case DYTC_MODE_MMC_LOWPOWER:
                        *profile = PLATFORM_PROFILE_LOW_POWER;
@@ -10330,7 +10325,7 @@ static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *p
                }
                return 0;
        }
-       if (dytc_profile_available == DYTC_FUNCMODE_PSC) {
+       if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
                switch (dytcmode) {
                case DYTC_MODE_PSC_LOWPOWER:
                        *profile = PLATFORM_PROFILE_LOW_POWER;
@@ -10352,21 +10347,21 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe
 {
        switch (profile) {
        case PLATFORM_PROFILE_LOW_POWER:
-               if (dytc_profile_available == DYTC_FUNCMODE_MMC)
+               if (dytc_capabilities & BIT(DYTC_FC_MMC))
                        *perfmode = DYTC_MODE_MMC_LOWPOWER;
-               else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
+               else if (dytc_capabilities & BIT(DYTC_FC_PSC))
                        *perfmode = DYTC_MODE_PSC_LOWPOWER;
                break;
        case PLATFORM_PROFILE_BALANCED:
-               if (dytc_profile_available == DYTC_FUNCMODE_MMC)
+               if (dytc_capabilities & BIT(DYTC_FC_MMC))
                        *perfmode = DYTC_MODE_MMC_BALANCE;
-               else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
+               else if (dytc_capabilities & BIT(DYTC_FC_PSC))
                        *perfmode = DYTC_MODE_PSC_BALANCE;
                break;
        case PLATFORM_PROFILE_PERFORMANCE:
-               if (dytc_profile_available == DYTC_FUNCMODE_MMC)
+               if (dytc_capabilities & BIT(DYTC_FC_MMC))
                        *perfmode = DYTC_MODE_MMC_PERFORM;
-               else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
+               else if (dytc_capabilities & BIT(DYTC_FC_PSC))
                        *perfmode = DYTC_MODE_PSC_PERFORM;
                break;
        default: /* Unknown profile */
@@ -10445,7 +10440,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
        if (err)
                goto unlock;
 
-       if (dytc_profile_available == DYTC_FUNCMODE_MMC) {
+       if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
                if (profile == PLATFORM_PROFILE_BALANCED) {
                        /*
                         * To get back to balanced mode we need to issue a reset command.
@@ -10464,7 +10459,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
                                goto unlock;
                }
        }
-       if (dytc_profile_available == DYTC_FUNCMODE_PSC) {
+       if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
                err = dytc_command(DYTC_SET_COMMAND(DYTC_FUNCTION_PSC, perfmode, 1), &output);
                if (err)
                        goto unlock;
@@ -10483,12 +10478,12 @@ static void dytc_profile_refresh(void)
        int perfmode;
 
        mutex_lock(&dytc_mutex);
-       if (dytc_profile_available == DYTC_FUNCMODE_MMC) {
+       if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
                if (dytc_mmc_get_available)
                        err = dytc_command(DYTC_CMD_MMC_GET, &output);
                else
                        err = dytc_cql_command(DYTC_CMD_GET, &output);
-       } else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
+       } else if (dytc_capabilities & BIT(DYTC_FC_PSC))
                err = dytc_command(DYTC_CMD_GET, &output);
 
        mutex_unlock(&dytc_mutex);
@@ -10517,7 +10512,6 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
        set_bit(PLATFORM_PROFILE_BALANCED, dytc_profile.choices);
        set_bit(PLATFORM_PROFILE_PERFORMANCE, dytc_profile.choices);
 
-       dytc_profile_available = DYTC_FUNCMODE_NONE;
        err = dytc_command(DYTC_CMD_QUERY, &output);
        if (err)
                return err;
@@ -10530,13 +10524,12 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
                return -ENODEV;
 
        /* Check what capabilities are supported */
-       err = dytc_command(DYTC_CMD_FUNC_CAP, &output);
+       err = dytc_command(DYTC_CMD_FUNC_CAP, &dytc_capabilities);
        if (err)
                return err;
 
-       if (output & BIT(DYTC_FC_MMC)) { /* MMC MODE */
-               dytc_profile_available = DYTC_FUNCMODE_MMC;
-
+       if (dytc_capabilities & BIT(DYTC_FC_MMC)) { /* MMC MODE */
+               pr_debug("MMC is supported\n");
                /*
                 * Check if MMC_GET functionality available
                 * Version > 6 and return success from MMC_GET command
@@ -10547,8 +10540,13 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
                        if (!err && ((output & DYTC_ERR_MASK) == DYTC_ERR_SUCCESS))
                                dytc_mmc_get_available = true;
                }
-       } else if (output & BIT(DYTC_FC_PSC)) { /* PSC MODE */
-               dytc_profile_available = DYTC_FUNCMODE_PSC;
+       } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { /* PSC MODE */
+               /* Support for this only works on AMD platforms */
+               if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
+                       dbg_printk(TPACPI_DBG_INIT, "PSC not support on Intel platforms\n");
+                       return -ENODEV;
+               }
+               pr_debug("PSC is supported\n");
        } else {
                dbg_printk(TPACPI_DBG_INIT, "No DYTC support available\n");
                return -ENODEV;
@@ -10574,7 +10572,6 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
 
 static void dytc_profile_exit(void)
 {
-       dytc_profile_available = DYTC_FUNCMODE_NONE;
        platform_profile_remove();
 }
 
index cb24917..ae1d6ee 100644 (file)
@@ -60,7 +60,7 @@ static LIST_HEAD(sclp_reg_list);
 /* List of queued requests. */
 static LIST_HEAD(sclp_req_queue);
 
-/* Data for read and and init requests. */
+/* Data for read and init requests. */
 static struct sclp_req sclp_read_req;
 static struct sclp_req sclp_init_req;
 static void *sclp_read_sccb;
index 97e51c3..161d3b1 100644 (file)
@@ -1136,8 +1136,13 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
                        vcdev->err = -EIO;
        }
        virtio_ccw_check_activity(vcdev, activity);
-       /* Interrupts are disabled here */
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
+       /*
+        * Paired with virtio_ccw_synchronize_cbs() and interrupts are
+        * disabled here.
+        */
        read_lock(&vcdev->irq_lock);
+#endif
        for_each_set_bit(i, indicators(vcdev),
                         sizeof(*indicators(vcdev)) * BITS_PER_BYTE) {
                /* The bit clear must happen before the vring kick. */
@@ -1146,7 +1151,9 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
                vq = virtio_ccw_vq_by_ind(vcdev, i);
                vring_interrupt(0, vq);
        }
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
        read_unlock(&vcdev->irq_lock);
+#endif
        if (test_bit(0, indicators2(vcdev))) {
                virtio_config_changed(&vcdev->vdev);
                clear_bit(0, indicators2(vcdev));
index 7d819fc..eb86afb 100644 (file)
@@ -2782,6 +2782,7 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
        struct hisi_hba *hisi_hba = shost_priv(shost);
        struct device *dev = hisi_hba->dev;
        int ret = sas_slave_configure(sdev);
+       unsigned int max_sectors;
 
        if (ret)
                return ret;
@@ -2799,6 +2800,12 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
                }
        }
 
+       /* Set according to IOMMU IOVA caching limit */
+       max_sectors = min_t(size_t, queue_max_hw_sectors(sdev->request_queue),
+                           (PAGE_SIZE * 32) >> SECTOR_SHIFT);
+
+       blk_queue_max_hw_sectors(sdev->request_queue, max_sectors);
+
        return 0;
 }
 
index b2d365a..dae8a2e 100644 (file)
@@ -91,14 +91,14 @@ static const struct at91_soc socs[] __initconst = {
        AT91_SOC(SAM9X60_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
                 AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH,
                 "sam9x60", "sam9x60"),
-       AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D5M_EXID_MATCH,
-                AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH,
+       AT91_SOC(SAM9X60_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
+                AT91_CIDR_VERSION_MASK, SAM9X60_D5M_EXID_MATCH,
                 "sam9x60 64MiB DDR2 SiP", "sam9x60"),
-       AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D1G_EXID_MATCH,
-                AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH,
+       AT91_SOC(SAM9X60_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
+                AT91_CIDR_VERSION_MASK, SAM9X60_D1G_EXID_MATCH,
                 "sam9x60 128MiB DDR2 SiP", "sam9x60"),
-       AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_D6K_EXID_MATCH,
-                AT91_CIDR_VERSION_MASK, SAM9X60_EXID_MATCH,
+       AT91_SOC(SAM9X60_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
+                AT91_CIDR_VERSION_MASK, SAM9X60_D6K_EXID_MATCH,
                 "sam9x60 8MiB SDRAM SiP", "sam9x60"),
 #endif
 #ifdef CONFIG_SOC_SAMA5
index 613935c..58240e3 100644 (file)
@@ -758,7 +758,7 @@ static const struct of_device_id ixp4xx_npe_of_match[] = {
 static struct platform_driver ixp4xx_npe_driver = {
        .driver = {
                .name           = "ixp4xx-npe",
-               .of_match_table = of_match_ptr(ixp4xx_npe_of_match),
+               .of_match_table = ixp4xx_npe_of_match,
        },
        .probe = ixp4xx_npe_probe,
        .remove = ixp4xx_npe_remove,
index 3e95835..4f163d6 100644 (file)
@@ -926,7 +926,7 @@ qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host)
        struct smem_partition_header *header;
        struct smem_ptable_entry *entry;
        struct smem_ptable *ptable;
-       unsigned int remote_host;
+       u16 remote_host;
        u16 host0, host1;
        int i;
 
@@ -951,12 +951,12 @@ qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host)
                        continue;
 
                if (remote_host >= SMEM_HOST_COUNT) {
-                       dev_err(smem->dev, "bad host %hu\n", remote_host);
+                       dev_err(smem->dev, "bad host %u\n", remote_host);
                        return -EINVAL;
                }
 
                if (smem->partitions[remote_host].virt_base) {
-                       dev_err(smem->dev, "duplicate host %hu\n", remote_host);
+                       dev_err(smem->dev, "duplicate host %u\n", remote_host);
                        return -EINVAL;
                }
 
index 3384452..02fdef7 100644 (file)
@@ -2632,7 +2632,7 @@ static void hfa384x_usbctlx_reaper_task(struct work_struct *work)
  */
 static void hfa384x_usbctlx_completion_task(struct work_struct *work)
 {
-       struct hfa384x *hw = container_of(work, struct hfa384x, reaper_bh);
+       struct hfa384x *hw = container_of(work, struct hfa384x, completion_bh);
        struct hfa384x_usbctlx *ctlx, *temp;
        unsigned long flags;
 
index cd80c7d..a9596e7 100644 (file)
@@ -81,6 +81,7 @@ static const struct x86_cpu_id tcc_ids[] __initconst = {
        X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, NULL),
        X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL),
        X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL),
+       X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL),
        {}
 };
 
index 1b6d46b..e85c1d7 100644 (file)
@@ -1962,6 +1962,8 @@ static void mlx5_vdpa_set_vq_cb(struct vdpa_device *vdev, u16 idx, struct vdpa_c
        struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
 
        ndev->event_cbs[idx] = *cb;
+       if (is_ctrl_vq_idx(mvdev, idx))
+               mvdev->cvq.event_cb = *cb;
 }
 
 static void mlx5_cvq_notify(struct vringh *vring)
@@ -2174,7 +2176,6 @@ static int verify_driver_features(struct mlx5_vdpa_dev *mvdev, u64 features)
 static int setup_virtqueues(struct mlx5_vdpa_dev *mvdev)
 {
        struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
-       struct mlx5_control_vq *cvq = &mvdev->cvq;
        int err;
        int i;
 
@@ -2184,16 +2185,6 @@ static int setup_virtqueues(struct mlx5_vdpa_dev *mvdev)
                        goto err_vq;
        }
 
-       if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) {
-               err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features,
-                                       MLX5_CVQ_MAX_ENT, false,
-                                       (struct vring_desc *)(uintptr_t)cvq->desc_addr,
-                                       (struct vring_avail *)(uintptr_t)cvq->driver_addr,
-                                       (struct vring_used *)(uintptr_t)cvq->device_addr);
-               if (err)
-                       goto err_vq;
-       }
-
        return 0;
 
 err_vq:
@@ -2466,6 +2457,21 @@ static void clear_vqs_ready(struct mlx5_vdpa_net *ndev)
        ndev->mvdev.cvq.ready = false;
 }
 
+static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev)
+{
+       struct mlx5_control_vq *cvq = &mvdev->cvq;
+       int err = 0;
+
+       if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ))
+               err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features,
+                                       MLX5_CVQ_MAX_ENT, false,
+                                       (struct vring_desc *)(uintptr_t)cvq->desc_addr,
+                                       (struct vring_avail *)(uintptr_t)cvq->driver_addr,
+                                       (struct vring_used *)(uintptr_t)cvq->device_addr);
+
+       return err;
+}
+
 static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status)
 {
        struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
@@ -2478,6 +2484,11 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status)
 
        if ((status ^ ndev->mvdev.status) & VIRTIO_CONFIG_S_DRIVER_OK) {
                if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
+                       err = setup_cvq_vring(mvdev);
+                       if (err) {
+                               mlx5_vdpa_warn(mvdev, "failed to setup control VQ vring\n");
+                               goto err_setup;
+                       }
                        err = setup_driver(mvdev);
                        if (err) {
                                mlx5_vdpa_warn(mvdev, "failed to setup driver\n");
index 776ad74..3bc27de 100644 (file)
@@ -1476,16 +1476,12 @@ static char *vduse_devnode(struct device *dev, umode_t *mode)
        return kasprintf(GFP_KERNEL, "vduse/%s", dev_name(dev));
 }
 
-static void vduse_mgmtdev_release(struct device *dev)
-{
-}
-
-static struct device vduse_mgmtdev = {
-       .init_name = "vduse",
-       .release = vduse_mgmtdev_release,
+struct vduse_mgmt_dev {
+       struct vdpa_mgmt_dev mgmt_dev;
+       struct device dev;
 };
 
-static struct vdpa_mgmt_dev mgmt_dev;
+static struct vduse_mgmt_dev *vduse_mgmt;
 
 static int vduse_dev_init_vdpa(struct vduse_dev *dev, const char *name)
 {
@@ -1510,7 +1506,7 @@ static int vduse_dev_init_vdpa(struct vduse_dev *dev, const char *name)
        }
        set_dma_ops(&vdev->vdpa.dev, &vduse_dev_dma_ops);
        vdev->vdpa.dma_dev = &vdev->vdpa.dev;
-       vdev->vdpa.mdev = &mgmt_dev;
+       vdev->vdpa.mdev = &vduse_mgmt->mgmt_dev;
 
        return 0;
 }
@@ -1556,34 +1552,52 @@ static struct virtio_device_id id_table[] = {
        { 0 },
 };
 
-static struct vdpa_mgmt_dev mgmt_dev = {
-       .device = &vduse_mgmtdev,
-       .id_table = id_table,
-       .ops = &vdpa_dev_mgmtdev_ops,
-};
+static void vduse_mgmtdev_release(struct device *dev)
+{
+       struct vduse_mgmt_dev *mgmt_dev;
+
+       mgmt_dev = container_of(dev, struct vduse_mgmt_dev, dev);
+       kfree(mgmt_dev);
+}
 
 static int vduse_mgmtdev_init(void)
 {
        int ret;
 
-       ret = device_register(&vduse_mgmtdev);
-       if (ret)
+       vduse_mgmt = kzalloc(sizeof(*vduse_mgmt), GFP_KERNEL);
+       if (!vduse_mgmt)
+               return -ENOMEM;
+
+       ret = dev_set_name(&vduse_mgmt->dev, "vduse");
+       if (ret) {
+               kfree(vduse_mgmt);
                return ret;
+       }
 
-       ret = vdpa_mgmtdev_register(&mgmt_dev);
+       vduse_mgmt->dev.release = vduse_mgmtdev_release;
+
+       ret = device_register(&vduse_mgmt->dev);
        if (ret)
-               goto err;
+               goto dev_reg_err;
 
-       return 0;
-err:
-       device_unregister(&vduse_mgmtdev);
+       vduse_mgmt->mgmt_dev.id_table = id_table;
+       vduse_mgmt->mgmt_dev.ops = &vdpa_dev_mgmtdev_ops;
+       vduse_mgmt->mgmt_dev.device = &vduse_mgmt->dev;
+       ret = vdpa_mgmtdev_register(&vduse_mgmt->mgmt_dev);
+       if (ret)
+               device_unregister(&vduse_mgmt->dev);
+
+       return ret;
+
+dev_reg_err:
+       put_device(&vduse_mgmt->dev);
        return ret;
 }
 
 static void vduse_mgmtdev_exit(void)
 {
-       vdpa_mgmtdev_unregister(&mgmt_dev);
-       device_unregister(&vduse_mgmtdev);
+       vdpa_mgmtdev_unregister(&vduse_mgmt->mgmt_dev);
+       device_unregister(&vduse_mgmt->dev);
 }
 
 static int vduse_init(void)
index 5ad2596..23dcbfd 100644 (file)
@@ -1209,7 +1209,7 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep)
        vhost_dev_stop(&v->vdev);
        vhost_vdpa_free_domain(v);
        vhost_vdpa_config_put(v);
-       vhost_dev_cleanup(&v->vdev);
+       vhost_vdpa_cleanup(v);
        mutex_unlock(&d->mutex);
 
        atomic_dec(&v->opened);
index c4e9171..1a9aa12 100644 (file)
@@ -2469,6 +2469,11 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
        if (charcount != 256 && charcount != 512)
                return -EINVAL;
 
+       /* font bigger than screen resolution ? */
+       if (w > FBCON_SWAP(info->var.rotate, info->var.xres, info->var.yres) ||
+           h > FBCON_SWAP(info->var.rotate, info->var.yres, info->var.xres))
+               return -EINVAL;
+
        /* Make sure drawing engine can handle the font */
        if (!(info->pixmap.blit_x & (1 << (font->width - 1))) ||
            !(info->pixmap.blit_y & (1 << (font->height - 1))))
@@ -2731,6 +2736,34 @@ void fbcon_update_vcs(struct fb_info *info, bool all)
 }
 EXPORT_SYMBOL(fbcon_update_vcs);
 
+/* let fbcon check if it supports a new screen resolution */
+int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+       struct fbcon_ops *ops = info->fbcon_par;
+       struct vc_data *vc;
+       unsigned int i;
+
+       WARN_CONSOLE_UNLOCKED();
+
+       if (!ops)
+               return 0;
+
+       /* prevent setting a screen size which is smaller than font size */
+       for (i = first_fb_vc; i <= last_fb_vc; i++) {
+               vc = vc_cons[i].d;
+               if (!vc || vc->vc_mode != KD_TEXT ||
+                          fbcon_info_from_console(i) != info)
+                       continue;
+
+               if (vc->vc_font.width  > FBCON_SWAP(var->rotate, var->xres, var->yres) ||
+                   vc->vc_font.height > FBCON_SWAP(var->rotate, var->yres, var->xres))
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(fbcon_modechange_possible);
+
 int fbcon_mode_deleted(struct fb_info *info,
                       struct fb_videomode *mode)
 {
index 8afc453..7ee6eb2 100644 (file)
@@ -511,7 +511,7 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
 
                while (n && (n * (logo->width + 8) - 8 > xres))
                        --n;
-               image.dx = (xres - n * (logo->width + 8) - 8) / 2;
+               image.dx = (xres - (n * (logo->width + 8) - 8)) / 2;
                image.dy = y ?: (yres - logo->height) / 2;
        } else {
                image.dx = 0;
@@ -1017,6 +1017,16 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
        if (ret)
                return ret;
 
+       /* verify that virtual resolution >= physical resolution */
+       if (var->xres_virtual < var->xres ||
+           var->yres_virtual < var->yres) {
+               pr_warn("WARNING: fbcon: Driver '%s' missed to adjust virtual screen size (%ux%u vs. %ux%u)\n",
+                       info->fix.id,
+                       var->xres_virtual, var->yres_virtual,
+                       var->xres, var->yres);
+               return -EINVAL;
+       }
+
        if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
                return 0;
 
@@ -1107,7 +1117,9 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
                        return -EFAULT;
                console_lock();
                lock_fb_info(info);
-               ret = fb_set_var(info, &var);
+               ret = fbcon_modechange_possible(info, &var);
+               if (!ret)
+                       ret = fb_set_var(info, &var);
                if (!ret)
                        fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
                unlock_fb_info(info);
index a6dc8b5..e1556d2 100644 (file)
@@ -29,6 +29,19 @@ menuconfig VIRTIO_MENU
 
 if VIRTIO_MENU
 
+config VIRTIO_HARDEN_NOTIFICATION
+        bool "Harden virtio notification"
+        help
+          Enable this to harden the device notifications and suppress
+          those that happen at a time where notifications are illegal.
+
+          Experimental: Note that several drivers still have bugs that
+          may cause crashes or hangs when correct handling of
+          notifications is enforced; depending on the subset of
+          drivers and devices you use, this may or may not work.
+
+          If unsure, say N.
+
 config VIRTIO_PCI
        tristate "PCI driver for virtio devices"
        depends on PCI
index 6bace84..7deeed3 100644 (file)
@@ -219,6 +219,7 @@ static int virtio_features_ok(struct virtio_device *dev)
  * */
 void virtio_reset_device(struct virtio_device *dev)
 {
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
        /*
         * The below virtio_synchronize_cbs() guarantees that any
         * interrupt for this line arriving after
@@ -227,6 +228,7 @@ void virtio_reset_device(struct virtio_device *dev)
         */
        virtio_break_device(dev);
        virtio_synchronize_cbs(dev);
+#endif
 
        dev->config->reset(dev);
 }
index c9bec38..083ff1e 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/virtio.h>
@@ -556,6 +557,28 @@ static const struct virtio_config_ops virtio_mmio_config_ops = {
        .synchronize_cbs = vm_synchronize_cbs,
 };
 
+#ifdef CONFIG_PM_SLEEP
+static int virtio_mmio_freeze(struct device *dev)
+{
+       struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
+
+       return virtio_device_freeze(&vm_dev->vdev);
+}
+
+static int virtio_mmio_restore(struct device *dev)
+{
+       struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
+
+       if (vm_dev->version == 1)
+               writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
+
+       return virtio_device_restore(&vm_dev->vdev);
+}
+
+static const struct dev_pm_ops virtio_mmio_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(virtio_mmio_freeze, virtio_mmio_restore)
+};
+#endif
 
 static void virtio_mmio_release_dev(struct device *_d)
 {
@@ -799,6 +822,9 @@ static struct platform_driver virtio_mmio_driver = {
                .name   = "virtio-mmio",
                .of_match_table = virtio_mmio_match,
                .acpi_match_table = ACPI_PTR(virtio_mmio_acpi_match),
+#ifdef CONFIG_PM_SLEEP
+               .pm     = &virtio_mmio_pm_ops,
+#endif
        },
 };
 
index b790f30..fa2a944 100644 (file)
@@ -220,8 +220,6 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev)
 
        check_offsets();
 
-       mdev->pci_dev = pci_dev;
-
        /* We only own devices >= 0x1000 and <= 0x107f: leave the rest. */
        if (pci_dev->device < 0x1000 || pci_dev->device > 0x107f)
                return -ENODEV;
index 13a7348..643ca77 100644 (file)
@@ -111,7 +111,12 @@ struct vring_virtqueue {
        /* Number we've added since last sync. */
        unsigned int num_added;
 
-       /* Last used index we've seen. */
+       /* Last used index  we've seen.
+        * for split ring, it just contains last used index
+        * for packed ring:
+        * bits up to VRING_PACKED_EVENT_F_WRAP_CTR include the last used index.
+        * bits from VRING_PACKED_EVENT_F_WRAP_CTR include the used wrap counter.
+        */
        u16 last_used_idx;
 
        /* Hint for event idx: already triggered no need to disable. */
@@ -154,9 +159,6 @@ struct vring_virtqueue {
                        /* Driver ring wrap counter. */
                        bool avail_wrap_counter;
 
-                       /* Device ring wrap counter. */
-                       bool used_wrap_counter;
-
                        /* Avail used flags. */
                        u16 avail_used_flags;
 
@@ -933,7 +935,7 @@ static struct virtqueue *vring_create_virtqueue_split(
        for (; num && vring_size(num, vring_align) > PAGE_SIZE; num /= 2) {
                queue = vring_alloc_queue(vdev, vring_size(num, vring_align),
                                          &dma_addr,
-                                         GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
+                                         GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
                if (queue)
                        break;
                if (!may_reduce_num)
@@ -973,6 +975,15 @@ static struct virtqueue *vring_create_virtqueue_split(
 /*
  * Packed ring specific functions - *_packed().
  */
+static inline bool packed_used_wrap_counter(u16 last_used_idx)
+{
+       return !!(last_used_idx & (1 << VRING_PACKED_EVENT_F_WRAP_CTR));
+}
+
+static inline u16 packed_last_used(u16 last_used_idx)
+{
+       return last_used_idx & ~(-(1 << VRING_PACKED_EVENT_F_WRAP_CTR));
+}
 
 static void vring_unmap_extra_packed(const struct vring_virtqueue *vq,
                                     struct vring_desc_extra *extra)
@@ -1406,8 +1417,14 @@ static inline bool is_used_desc_packed(const struct vring_virtqueue *vq,
 
 static inline bool more_used_packed(const struct vring_virtqueue *vq)
 {
-       return is_used_desc_packed(vq, vq->last_used_idx,
-                       vq->packed.used_wrap_counter);
+       u16 last_used;
+       u16 last_used_idx;
+       bool used_wrap_counter;
+
+       last_used_idx = READ_ONCE(vq->last_used_idx);
+       last_used = packed_last_used(last_used_idx);
+       used_wrap_counter = packed_used_wrap_counter(last_used_idx);
+       return is_used_desc_packed(vq, last_used, used_wrap_counter);
 }
 
 static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq,
@@ -1415,7 +1432,8 @@ static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq,
                                          void **ctx)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
-       u16 last_used, id;
+       u16 last_used, id, last_used_idx;
+       bool used_wrap_counter;
        void *ret;
 
        START_USE(vq);
@@ -1434,7 +1452,9 @@ static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq,
        /* Only get used elements after they have been exposed by host. */
        virtio_rmb(vq->weak_barriers);
 
-       last_used = vq->last_used_idx;
+       last_used_idx = READ_ONCE(vq->last_used_idx);
+       used_wrap_counter = packed_used_wrap_counter(last_used_idx);
+       last_used = packed_last_used(last_used_idx);
        id = le16_to_cpu(vq->packed.vring.desc[last_used].id);
        *len = le32_to_cpu(vq->packed.vring.desc[last_used].len);
 
@@ -1451,12 +1471,15 @@ static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq,
        ret = vq->packed.desc_state[id].data;
        detach_buf_packed(vq, id, ctx);
 
-       vq->last_used_idx += vq->packed.desc_state[id].num;
-       if (unlikely(vq->last_used_idx >= vq->packed.vring.num)) {
-               vq->last_used_idx -= vq->packed.vring.num;
-               vq->packed.used_wrap_counter ^= 1;
+       last_used += vq->packed.desc_state[id].num;
+       if (unlikely(last_used >= vq->packed.vring.num)) {
+               last_used -= vq->packed.vring.num;
+               used_wrap_counter ^= 1;
        }
 
+       last_used = (last_used | (used_wrap_counter << VRING_PACKED_EVENT_F_WRAP_CTR));
+       WRITE_ONCE(vq->last_used_idx, last_used);
+
        /*
         * If we expect an interrupt for the next entry, tell host
         * by writing event index and flush out the write before
@@ -1465,9 +1488,7 @@ static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq,
        if (vq->packed.event_flags_shadow == VRING_PACKED_EVENT_FLAG_DESC)
                virtio_store_mb(vq->weak_barriers,
                                &vq->packed.vring.driver->off_wrap,
-                               cpu_to_le16(vq->last_used_idx |
-                                       (vq->packed.used_wrap_counter <<
-                                        VRING_PACKED_EVENT_F_WRAP_CTR)));
+                               cpu_to_le16(vq->last_used_idx));
 
        LAST_ADD_TIME_INVALID(vq);
 
@@ -1499,9 +1520,7 @@ static unsigned int virtqueue_enable_cb_prepare_packed(struct virtqueue *_vq)
 
        if (vq->event) {
                vq->packed.vring.driver->off_wrap =
-                       cpu_to_le16(vq->last_used_idx |
-                               (vq->packed.used_wrap_counter <<
-                                VRING_PACKED_EVENT_F_WRAP_CTR));
+                       cpu_to_le16(vq->last_used_idx);
                /*
                 * We need to update event offset and event wrap
                 * counter first before updating event flags.
@@ -1518,8 +1537,7 @@ static unsigned int virtqueue_enable_cb_prepare_packed(struct virtqueue *_vq)
        }
 
        END_USE(vq);
-       return vq->last_used_idx | ((u16)vq->packed.used_wrap_counter <<
-                       VRING_PACKED_EVENT_F_WRAP_CTR);
+       return vq->last_used_idx;
 }
 
 static bool virtqueue_poll_packed(struct virtqueue *_vq, u16 off_wrap)
@@ -1537,7 +1555,7 @@ static bool virtqueue_poll_packed(struct virtqueue *_vq, u16 off_wrap)
 static bool virtqueue_enable_cb_delayed_packed(struct virtqueue *_vq)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
-       u16 used_idx, wrap_counter;
+       u16 used_idx, wrap_counter, last_used_idx;
        u16 bufs;
 
        START_USE(vq);
@@ -1550,9 +1568,10 @@ static bool virtqueue_enable_cb_delayed_packed(struct virtqueue *_vq)
        if (vq->event) {
                /* TODO: tune this threshold */
                bufs = (vq->packed.vring.num - vq->vq.num_free) * 3 / 4;
-               wrap_counter = vq->packed.used_wrap_counter;
+               last_used_idx = READ_ONCE(vq->last_used_idx);
+               wrap_counter = packed_used_wrap_counter(last_used_idx);
 
-               used_idx = vq->last_used_idx + bufs;
+               used_idx = packed_last_used(last_used_idx) + bufs;
                if (used_idx >= vq->packed.vring.num) {
                        used_idx -= vq->packed.vring.num;
                        wrap_counter ^= 1;
@@ -1582,9 +1601,10 @@ static bool virtqueue_enable_cb_delayed_packed(struct virtqueue *_vq)
         */
        virtio_mb(vq->weak_barriers);
 
-       if (is_used_desc_packed(vq,
-                               vq->last_used_idx,
-                               vq->packed.used_wrap_counter)) {
+       last_used_idx = READ_ONCE(vq->last_used_idx);
+       wrap_counter = packed_used_wrap_counter(last_used_idx);
+       used_idx = packed_last_used(last_used_idx);
+       if (is_used_desc_packed(vq, used_idx, wrap_counter)) {
                END_USE(vq);
                return false;
        }
@@ -1688,8 +1708,12 @@ static struct virtqueue *vring_create_virtqueue_packed(
        vq->we_own_ring = true;
        vq->notify = notify;
        vq->weak_barriers = weak_barriers;
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
        vq->broken = true;
-       vq->last_used_idx = 0;
+#else
+       vq->broken = false;
+#endif
+       vq->last_used_idx = 0 | (1 << VRING_PACKED_EVENT_F_WRAP_CTR);
        vq->event_triggered = false;
        vq->num_added = 0;
        vq->packed_ring = true;
@@ -1720,7 +1744,6 @@ static struct virtqueue *vring_create_virtqueue_packed(
 
        vq->packed.next_avail_idx = 0;
        vq->packed.avail_wrap_counter = 1;
-       vq->packed.used_wrap_counter = 1;
        vq->packed.event_flags_shadow = 0;
        vq->packed.avail_used_flags = 1 << VRING_PACKED_DESC_F_AVAIL;
 
@@ -2135,9 +2158,13 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
        }
 
        if (unlikely(vq->broken)) {
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
                dev_warn_once(&vq->vq.vdev->dev,
                              "virtio vring IRQ raised before DRIVER_OK");
                return IRQ_NONE;
+#else
+               return IRQ_HANDLED;
+#endif
        }
 
        /* Just a hint for performance: so it's ok that this can be racy! */
@@ -2180,7 +2207,11 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
        vq->we_own_ring = false;
        vq->notify = notify;
        vq->weak_barriers = weak_barriers;
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
        vq->broken = true;
+#else
+       vq->broken = false;
+#endif
        vq->last_used_idx = 0;
        vq->event_triggered = false;
        vq->num_added = 0;
index a41ae6e..1fee702 100644 (file)
@@ -21,7 +21,8 @@ static int cachefiles_ondemand_fd_release(struct inode *inode,
         * anon_fd.
         */
        xas_for_each(&xas, req, ULONG_MAX) {
-               if (req->msg.opcode == CACHEFILES_OP_READ) {
+               if (req->msg.object_id == object_id &&
+                   req->msg.opcode == CACHEFILES_OP_READ) {
                        req->error = -EIO;
                        complete(&req->done);
                        xas_store(&xas, NULL);
index 38c9303..ac8fd5e 100644 (file)
@@ -4377,6 +4377,7 @@ static void flush_dirty_session_caps(struct ceph_mds_session *s)
                ihold(inode);
                dout("flush_dirty_caps %llx.%llx\n", ceph_vinop(inode));
                spin_unlock(&mdsc->cap_dirty_lock);
+               ceph_wait_on_async_create(inode);
                ceph_check_caps(ci, CHECK_CAPS_FLUSH, NULL);
                iput(inode);
                spin_lock(&mdsc->cap_dirty_lock);
index 9d3cf01..7492082 100644 (file)
@@ -372,17 +372,22 @@ nomem:
        return NULL;
 }
 
+static inline bool fscache_cookie_is_dropped(struct fscache_cookie *cookie)
+{
+       return READ_ONCE(cookie->state) == FSCACHE_COOKIE_STATE_DROPPED;
+}
+
 static void fscache_wait_on_collision(struct fscache_cookie *candidate,
                                      struct fscache_cookie *wait_for)
 {
        enum fscache_cookie_state *statep = &wait_for->state;
 
-       wait_var_event_timeout(statep, READ_ONCE(*statep) == FSCACHE_COOKIE_STATE_DROPPED,
+       wait_var_event_timeout(statep, fscache_cookie_is_dropped(wait_for),
                               20 * HZ);
-       if (READ_ONCE(*statep) != FSCACHE_COOKIE_STATE_DROPPED) {
+       if (!fscache_cookie_is_dropped(wait_for)) {
                pr_notice("Potential collision c=%08x old: c=%08x",
                          candidate->debug_id, wait_for->debug_id);
-               wait_var_event(statep, READ_ONCE(*statep) == FSCACHE_COOKIE_STATE_DROPPED);
+               wait_var_event(statep, fscache_cookie_is_dropped(wait_for));
        }
 }
 
@@ -517,7 +522,14 @@ static void fscache_perform_lookup(struct fscache_cookie *cookie)
        }
 
        fscache_see_cookie(cookie, fscache_cookie_see_active);
-       fscache_set_cookie_state(cookie, FSCACHE_COOKIE_STATE_ACTIVE);
+       spin_lock(&cookie->lock);
+       if (test_and_clear_bit(FSCACHE_COOKIE_DO_INVALIDATE, &cookie->flags))
+               __fscache_set_cookie_state(cookie,
+                                          FSCACHE_COOKIE_STATE_INVALIDATING);
+       else
+               __fscache_set_cookie_state(cookie, FSCACHE_COOKIE_STATE_ACTIVE);
+       spin_unlock(&cookie->lock);
+       wake_up_cookie_state(cookie);
        trace = fscache_access_lookup_cookie_end;
 
 out:
@@ -752,6 +764,9 @@ again_locked:
                        spin_lock(&cookie->lock);
                }
 
+               if (test_and_clear_bit(FSCACHE_COOKIE_DO_INVALIDATE, &cookie->flags))
+                       fscache_end_cookie_access(cookie, fscache_access_invalidate_cookie_end);
+
                switch (state) {
                case FSCACHE_COOKIE_STATE_RELINQUISHING:
                        fscache_see_cookie(cookie, fscache_cookie_see_relinquish);
@@ -1048,6 +1063,9 @@ void __fscache_invalidate(struct fscache_cookie *cookie,
                return;
 
        case FSCACHE_COOKIE_STATE_LOOKING_UP:
+               __fscache_begin_cookie_access(cookie, fscache_access_invalidate_cookie);
+               set_bit(FSCACHE_COOKIE_DO_INVALIDATE, &cookie->flags);
+               fallthrough;
        case FSCACHE_COOKIE_STATE_CREATING:
                spin_unlock(&cookie->lock);
                _leave(" [look %x]", cookie->inval_counter);
index f2aa7db..a058e01 100644 (file)
@@ -143,7 +143,7 @@ static void fscache_wait_on_volume_collision(struct fscache_volume *candidate,
 {
        wait_var_event_timeout(&candidate->flags,
                               !fscache_is_acquire_pending(candidate), 20 * HZ);
-       if (!fscache_is_acquire_pending(candidate)) {
+       if (fscache_is_acquire_pending(candidate)) {
                pr_notice("Potential volume collision new=%08x old=%08x",
                          candidate->debug_id, collidee_debug_id);
                fscache_stat(&fscache_n_volumes_collision);
@@ -182,7 +182,7 @@ static bool fscache_hash_volume(struct fscache_volume *candidate)
        hlist_bl_add_head(&candidate->hash_link, h);
        hlist_bl_unlock(h);
 
-       if (test_bit(FSCACHE_VOLUME_ACQUIRE_PENDING, &candidate->flags))
+       if (fscache_is_acquire_pending(candidate))
                fscache_wait_on_volume_collision(candidate, collidee_debug_id);
        return true;
 
index 5ff2cdb..a01ea49 100644 (file)
@@ -1183,6 +1183,7 @@ static const struct io_op_def io_op_defs[] = {
                .unbound_nonreg_file    = 1,
                .pollout                = 1,
                .needs_async_setup      = 1,
+               .ioprio                 = 1,
                .async_size             = sizeof(struct io_async_msghdr),
        },
        [IORING_OP_RECVMSG] = {
@@ -1191,6 +1192,7 @@ static const struct io_op_def io_op_defs[] = {
                .pollin                 = 1,
                .buffer_select          = 1,
                .needs_async_setup      = 1,
+               .ioprio                 = 1,
                .async_size             = sizeof(struct io_async_msghdr),
        },
        [IORING_OP_TIMEOUT] = {
@@ -1266,6 +1268,7 @@ static const struct io_op_def io_op_defs[] = {
                .unbound_nonreg_file    = 1,
                .pollout                = 1,
                .audit_skip             = 1,
+               .ioprio                 = 1,
        },
        [IORING_OP_RECV] = {
                .needs_file             = 1,
@@ -1273,6 +1276,7 @@ static const struct io_op_def io_op_defs[] = {
                .pollin                 = 1,
                .buffer_select          = 1,
                .audit_skip             = 1,
+               .ioprio                 = 1,
        },
        [IORING_OP_OPENAT2] = {
        },
@@ -4314,18 +4318,19 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags)
                if (unlikely(ret < 0))
                        return ret;
        } else {
+               rw = req->async_data;
+               s = &rw->s;
+
                /*
                 * Safe and required to re-import if we're using provided
                 * buffers, as we dropped the selected one before retry.
                 */
-               if (req->flags & REQ_F_BUFFER_SELECT) {
+               if (io_do_buffer_select(req)) {
                        ret = io_import_iovec(READ, req, &iovec, s, issue_flags);
                        if (unlikely(ret < 0))
                                return ret;
                }
 
-               rw = req->async_data;
-               s = &rw->s;
                /*
                 * We come here from an earlier attempt, restore our state to
                 * match in case it doesn't. It's cheap enough that we don't
@@ -5061,7 +5066,7 @@ static int io_uring_cmd_prep(struct io_kiocb *req,
 {
        struct io_uring_cmd *ioucmd = &req->uring_cmd;
 
-       if (sqe->rw_flags)
+       if (sqe->rw_flags || sqe->__pad1)
                return -EINVAL;
        ioucmd->cmd = sqe->cmd;
        ioucmd->cmd_op = READ_ONCE(sqe->cmd_op);
@@ -6075,12 +6080,12 @@ static int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_sr_msg *sr = &req->sr_msg;
 
-       if (unlikely(sqe->file_index))
+       if (unlikely(sqe->file_index || sqe->addr2))
                return -EINVAL;
 
        sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
        sr->len = READ_ONCE(sqe->len);
-       sr->flags = READ_ONCE(sqe->addr2);
+       sr->flags = READ_ONCE(sqe->ioprio);
        if (sr->flags & ~IORING_RECVSEND_POLL_FIRST)
                return -EINVAL;
        sr->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL;
@@ -6311,12 +6316,12 @@ static int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_sr_msg *sr = &req->sr_msg;
 
-       if (unlikely(sqe->file_index))
+       if (unlikely(sqe->file_index || sqe->addr2))
                return -EINVAL;
 
        sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
        sr->len = READ_ONCE(sqe->len);
-       sr->flags = READ_ONCE(sqe->addr2);
+       sr->flags = READ_ONCE(sqe->ioprio);
        if (sr->flags & ~IORING_RECVSEND_POLL_FIRST)
                return -EINVAL;
        sr->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL;
@@ -7968,6 +7973,9 @@ static int io_files_update_with_index_alloc(struct io_kiocb *req,
        struct file *file;
        int ret, fd;
 
+       if (!req->ctx->file_data)
+               return -ENXIO;
+
        for (done = 0; done < req->rsrc_update.nr_args; done++) {
                if (copy_from_user(&fd, &fds[done], sizeof(fd))) {
                        ret = -EFAULT;
index e6f4ccc..353f047 100644 (file)
@@ -6490,6 +6490,7 @@ int smb2_write(struct ksmbd_work *work)
                goto out;
        }
 
+       ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
        if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
                writethrough = true;
 
@@ -6505,10 +6506,6 @@ int smb2_write(struct ksmbd_work *work)
                data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
                                    le16_to_cpu(req->DataOffset));
 
-               ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
-               if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
-                       writethrough = true;
-
                ksmbd_debug(SMB, "filename %pd, offset %lld, len %zu\n",
                            fp->filp->f_path.dentry, offset, length);
                err = ksmbd_vfs_write(work, fp, data_buf, length, &offset,
@@ -7703,7 +7700,7 @@ int smb2_ioctl(struct ksmbd_work *work)
        {
                struct file_zero_data_information *zero_data;
                struct ksmbd_file *fp;
-               loff_t off, len;
+               loff_t off, len, bfz;
 
                if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
                        ksmbd_debug(SMB,
@@ -7720,19 +7717,26 @@ int smb2_ioctl(struct ksmbd_work *work)
                zero_data =
                        (struct file_zero_data_information *)&req->Buffer[0];
 
-               fp = ksmbd_lookup_fd_fast(work, id);
-               if (!fp) {
-                       ret = -ENOENT;
+               off = le64_to_cpu(zero_data->FileOffset);
+               bfz = le64_to_cpu(zero_data->BeyondFinalZero);
+               if (off > bfz) {
+                       ret = -EINVAL;
                        goto out;
                }
 
-               off = le64_to_cpu(zero_data->FileOffset);
-               len = le64_to_cpu(zero_data->BeyondFinalZero) - off;
+               len = bfz - off;
+               if (len) {
+                       fp = ksmbd_lookup_fd_fast(work, id);
+                       if (!fp) {
+                               ret = -ENOENT;
+                               goto out;
+                       }
 
-               ret = ksmbd_vfs_zero_data(work, fp, off, len);
-               ksmbd_fd_put(work, fp);
-               if (ret < 0)
-                       goto out;
+                       ret = ksmbd_vfs_zero_data(work, fp, off, len);
+                       ksmbd_fd_put(work, fp);
+                       if (ret < 0)
+                               goto out;
+               }
                break;
        }
        case FSCTL_QUERY_ALLOCATED_RANGES:
@@ -7806,14 +7810,24 @@ int smb2_ioctl(struct ksmbd_work *work)
                src_off = le64_to_cpu(dup_ext->SourceFileOffset);
                dst_off = le64_to_cpu(dup_ext->TargetFileOffset);
                length = le64_to_cpu(dup_ext->ByteCount);
-               cloned = vfs_clone_file_range(fp_in->filp, src_off, fp_out->filp,
-                                             dst_off, length, 0);
+               /*
+                * XXX: It is not clear if FSCTL_DUPLICATE_EXTENTS_TO_FILE
+                * should fall back to vfs_copy_file_range().  This could be
+                * beneficial when re-exporting nfs/smb mount, but note that
+                * this can result in partial copy that returns an error status.
+                * If/when FSCTL_DUPLICATE_EXTENTS_TO_FILE_EX is implemented,
+                * fall back to vfs_copy_file_range(), should be avoided when
+                * the flag DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC is set.
+                */
+               cloned = vfs_clone_file_range(fp_in->filp, src_off,
+                                             fp_out->filp, dst_off, length, 0);
                if (cloned == -EXDEV || cloned == -EOPNOTSUPP) {
                        ret = -EOPNOTSUPP;
                        goto dup_ext_out;
                } else if (cloned != length) {
                        cloned = vfs_copy_file_range(fp_in->filp, src_off,
-                                                    fp_out->filp, dst_off, length, 0);
+                                                    fp_out->filp, dst_off,
+                                                    length, 0);
                        if (cloned != length) {
                                if (cloned < 0)
                                        ret = cloned;
index d035e06..35b55ee 100644 (file)
@@ -5,16 +5,6 @@
  *
  *   Author(s): Long Li <longli@microsoft.com>,
  *             Hyunchul Lee <hyc.lee@gmail.com>
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
  */
 
 #define SUBMOD_NAME    "smb_direct"
index 8fef9de..143bba4 100644 (file)
@@ -230,7 +230,7 @@ static int ksmbd_kthread_fn(void *p)
                        break;
                }
                ret = kernel_accept(iface->ksmbd_socket, &client_sk,
-                                   O_NONBLOCK);
+                                   SOCK_NONBLOCK);
                mutex_unlock(&iface->sock_release_lock);
                if (ret) {
                        if (ret == -EAGAIN)
index dcdd07c..05efcdf 100644 (file)
@@ -1015,7 +1015,9 @@ int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
                                     FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
                                     off, len);
 
-       return vfs_fallocate(fp->filp, FALLOC_FL_ZERO_RANGE, off, len);
+       return vfs_fallocate(fp->filp,
+                            FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
+                            off, len);
 }
 
 int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
@@ -1046,7 +1048,7 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
        *out_count = 0;
        end = start + length;
        while (start < end && *out_count < in_count) {
-               extent_start = f->f_op->llseek(f, start, SEEK_DATA);
+               extent_start = vfs_llseek(f, start, SEEK_DATA);
                if (extent_start < 0) {
                        if (extent_start != -ENXIO)
                                ret = (int)extent_start;
@@ -1056,7 +1058,7 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
                if (extent_start >= end)
                        break;
 
-               extent_end = f->f_op->llseek(f, extent_start, SEEK_HOLE);
+               extent_end = vfs_llseek(f, extent_start, SEEK_HOLE);
                if (extent_end < 0) {
                        if (extent_end != -ENXIO)
                                ret = (int)extent_end;
@@ -1777,6 +1779,10 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
 
                ret = vfs_copy_file_range(src_fp->filp, src_off,
                                          dst_fp->filp, dst_off, len, 0);
+               if (ret == -EOPNOTSUPP || ret == -EXDEV)
+                       ret = generic_copy_file_range(src_fp->filp, src_off,
+                                                     dst_fp->filp, dst_off,
+                                                     len, 0);
                if (ret < 0)
                        return ret;
 
index c0fdcf8..bb0e84a 100644 (file)
@@ -4012,22 +4012,29 @@ static int _nfs4_discover_trunking(struct nfs_server *server,
        }
 
        page = alloc_page(GFP_KERNEL);
+       if (!page)
+               return -ENOMEM;
        locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
-       if (page == NULL || locations == NULL)
-               goto out;
+       if (!locations)
+               goto out_free;
+       locations->fattr = nfs_alloc_fattr();
+       if (!locations->fattr)
+               goto out_free_2;
 
        status = nfs4_proc_get_locations(server, fhandle, locations, page,
                                         cred);
        if (status)
-               goto out;
+               goto out_free_3;
 
        for (i = 0; i < locations->nlocations; i++)
                test_fs_location_for_trunking(&locations->locations[i], clp,
                                              server);
-out:
-       if (page)
-               __free_page(page);
+out_free_3:
+       kfree(locations->fattr);
+out_free_2:
        kfree(locations);
+out_free:
+       __free_page(page);
        return status;
 }
 
index 2540b35..9bab3e9 100644 (file)
@@ -2753,5 +2753,6 @@ again:
                goto again;
 
        nfs_put_client(clp);
+       module_put_and_kthread_exit(0);
        return 0;
 }
index 840e3af..d79db56 100644 (file)
@@ -577,6 +577,7 @@ out_err:
 ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
                             u64 dst_pos, u64 count)
 {
+       ssize_t ret;
 
        /*
         * Limit copy to 4MB to prevent indefinitely blocking an nfsd
@@ -587,7 +588,12 @@ ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
         * limit like this and pipeline multiple COPY requests.
         */
        count = min_t(u64, count, 1 << 22);
-       return vfs_copy_file_range(src, src_pos, dst, dst_pos, count, 0);
+       ret = vfs_copy_file_range(src, src_pos, dst, dst_pos, count, 0);
+
+       if (ret == -EOPNOTSUPP || ret == -EXDEV)
+               ret = generic_copy_file_range(src, src_pos, dst, dst_pos,
+                                             count, 0);
+       return ret;
 }
 
 __be32 nfsd4_vfs_fallocate(struct svc_rqst *rqstp, struct svc_fh *fhp,
@@ -1173,6 +1179,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset,
                        nfsd_copy_write_verifier(verf, nn);
                        err2 = filemap_check_wb_err(nf->nf_file->f_mapping,
                                                    since);
+                       err = nfserrno(err2);
                        break;
                case -EINVAL:
                        err = nfserr_notsupp;
@@ -1180,8 +1187,8 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset,
                default:
                        nfsd_reset_write_verifier(nn);
                        trace_nfsd_writeverf_reset(nn, rqstp, err2);
+                       err = nfserrno(err2);
                }
-               err = nfserrno(err2);
        } else
                nfsd_copy_write_verifier(verf, nn);
 
index c2255b4..b08ce0d 100644 (file)
@@ -1513,8 +1513,15 @@ static int fanotify_test_fid(struct dentry *dentry)
        return 0;
 }
 
-static int fanotify_events_supported(struct path *path, __u64 mask)
+static int fanotify_events_supported(struct fsnotify_group *group,
+                                    struct path *path, __u64 mask,
+                                    unsigned int flags)
 {
+       unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
+       /* Strict validation of events in non-dir inode mask with v5.17+ APIs */
+       bool strict_dir_events = FAN_GROUP_FLAG(group, FAN_REPORT_TARGET_FID) ||
+                                (mask & FAN_RENAME);
+
        /*
         * Some filesystems such as 'proc' acquire unusual locks when opening
         * files. For them fanotify permission events have high chances of
@@ -1526,6 +1533,16 @@ static int fanotify_events_supported(struct path *path, __u64 mask)
        if (mask & FANOTIFY_PERM_EVENTS &&
            path->mnt->mnt_sb->s_type->fs_flags & FS_DISALLOW_NOTIFY_PERM)
                return -EINVAL;
+
+       /*
+        * We shouldn't have allowed setting dirent events and the directory
+        * flags FAN_ONDIR and FAN_EVENT_ON_CHILD in mask of non-dir inode,
+        * but because we always allowed it, error only when using new APIs.
+        */
+       if (strict_dir_events && mark_type == FAN_MARK_INODE &&
+           !d_is_dir(path->dentry) && (mask & FANOTIFY_DIRONLY_EVENT_BITS))
+               return -ENOTDIR;
+
        return 0;
 }
 
@@ -1672,7 +1689,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
                goto fput_and_out;
 
        if (flags & FAN_MARK_ADD) {
-               ret = fanotify_events_supported(&path, mask);
+               ret = fanotify_events_supported(group, &path, mask, flags);
                if (ret)
                        goto path_put_and_out;
        }
@@ -1695,19 +1712,6 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
        else
                mnt = path.mnt;
 
-       /*
-        * FAN_RENAME is not allowed on non-dir (for now).
-        * We shouldn't have allowed setting any dirent events in mask of
-        * non-dir, but because we always allowed it, error only if group
-        * was initialized with the new flag FAN_REPORT_TARGET_FID.
-        */
-       ret = -ENOTDIR;
-       if (inode && !S_ISDIR(inode->i_mode) &&
-           ((mask & FAN_RENAME) ||
-            ((mask & FANOTIFY_DIRENT_EVENTS) &&
-             FAN_GROUP_FLAG(group, FAN_REPORT_TARGET_FID))))
-               goto path_put_and_out;
-
        /* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */
        if (mnt || !S_ISDIR(inode->i_mode)) {
                mask &= ~FAN_EVENT_ON_CHILD;
index b1b1cdf..e0777ee 100644 (file)
@@ -1397,28 +1397,6 @@ ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in,
 }
 EXPORT_SYMBOL(generic_copy_file_range);
 
-static ssize_t do_copy_file_range(struct file *file_in, loff_t pos_in,
-                                 struct file *file_out, loff_t pos_out,
-                                 size_t len, unsigned int flags)
-{
-       /*
-        * Although we now allow filesystems to handle cross sb copy, passing
-        * a file of the wrong filesystem type to filesystem driver can result
-        * in an attempt to dereference the wrong type of ->private_data, so
-        * avoid doing that until we really have a good reason.  NFS defines
-        * several different file_system_type structures, but they all end up
-        * using the same ->copy_file_range() function pointer.
-        */
-       if (file_out->f_op->copy_file_range &&
-           file_out->f_op->copy_file_range == file_in->f_op->copy_file_range)
-               return file_out->f_op->copy_file_range(file_in, pos_in,
-                                                      file_out, pos_out,
-                                                      len, flags);
-
-       return generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
-                                      flags);
-}
-
 /*
  * Performs necessary checks before doing a file copy
  *
@@ -1440,6 +1418,24 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,
        if (ret)
                return ret;
 
+       /*
+        * We allow some filesystems to handle cross sb copy, but passing
+        * a file of the wrong filesystem type to filesystem driver can result
+        * in an attempt to dereference the wrong type of ->private_data, so
+        * avoid doing that until we really have a good reason.
+        *
+        * nfs and cifs define several different file_system_type structures
+        * and several different sets of file_operations, but they all end up
+        * using the same ->copy_file_range() function pointer.
+        */
+       if (file_out->f_op->copy_file_range) {
+               if (file_in->f_op->copy_file_range !=
+                   file_out->f_op->copy_file_range)
+                       return -EXDEV;
+       } else if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) {
+               return -EXDEV;
+       }
+
        /* Don't touch certain kinds of inodes */
        if (IS_IMMUTABLE(inode_out))
                return -EPERM;
@@ -1505,26 +1501,41 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
        file_start_write(file_out);
 
        /*
-        * Try cloning first, this is supported by more file systems, and
-        * more efficient if both clone and copy are supported (e.g. NFS).
+        * Cloning is supported by more file systems, so we implement copy on
+        * same sb using clone, but for filesystems where both clone and copy
+        * are supported (e.g. nfs,cifs), we only call the copy method.
         */
+       if (file_out->f_op->copy_file_range) {
+               ret = file_out->f_op->copy_file_range(file_in, pos_in,
+                                                     file_out, pos_out,
+                                                     len, flags);
+               goto done;
+       }
+
        if (file_in->f_op->remap_file_range &&
            file_inode(file_in)->i_sb == file_inode(file_out)->i_sb) {
-               loff_t cloned;
-
-               cloned = file_in->f_op->remap_file_range(file_in, pos_in,
+               ret = file_in->f_op->remap_file_range(file_in, pos_in,
                                file_out, pos_out,
                                min_t(loff_t, MAX_RW_COUNT, len),
                                REMAP_FILE_CAN_SHORTEN);
-               if (cloned > 0) {
-                       ret = cloned;
+               if (ret > 0)
                        goto done;
-               }
        }
 
-       ret = do_copy_file_range(file_in, pos_in, file_out, pos_out, len,
-                               flags);
-       WARN_ON_ONCE(ret == -EOPNOTSUPP);
+       /*
+        * We can get here for same sb copy of filesystems that do not implement
+        * ->copy_file_range() in case filesystem does not support clone or in
+        * case filesystem supports clone but rejected the clone request (e.g.
+        * because it was not block aligned).
+        *
+        * In both cases, fall back to kernel copy so we are able to maintain a
+        * consistent story about which filesystems support copy_file_range()
+        * and which filesystems do not, that will allow userspace tools to
+        * make consistent desicions w.r.t using copy_file_range().
+        */
+       ret = generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
+                                     flags);
+
 done:
        if (ret > 0) {
                fsnotify_access(file_in);
index 1824f61..224649a 100644 (file)
@@ -50,7 +50,7 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_hasname(struct xfs_da_args *args, struct xfs_buf **bp);
-STATIC int xfs_attr_leaf_try_add(struct xfs_da_args *args, struct xfs_buf *bp);
+STATIC int xfs_attr_leaf_try_add(struct xfs_da_args *args);
 
 /*
  * Internal routines when attribute list is more than one block.
@@ -393,16 +393,10 @@ xfs_attr_sf_addname(
         * It won't fit in the shortform, transform to a leaf block.  GROT:
         * another possible req'mt for a double-split btree op.
         */
-       error = xfs_attr_shortform_to_leaf(args, &attr->xattri_leaf_bp);
+       error = xfs_attr_shortform_to_leaf(args);
        if (error)
                return error;
 
-       /*
-        * Prevent the leaf buffer from being unlocked so that a concurrent AIL
-        * push cannot grab the half-baked leaf buffer and run into problems
-        * with the write verifier.
-        */
-       xfs_trans_bhold(args->trans, attr->xattri_leaf_bp);
        attr->xattri_dela_state = XFS_DAS_LEAF_ADD;
 out:
        trace_xfs_attr_sf_addname_return(attr->xattri_dela_state, args->dp);
@@ -447,11 +441,9 @@ xfs_attr_leaf_addname(
 
        /*
         * Use the leaf buffer we may already hold locked as a result of
-        * a sf-to-leaf conversion. The held buffer is no longer valid
-        * after this call, regardless of the result.
+        * a sf-to-leaf conversion.
         */
-       error = xfs_attr_leaf_try_add(args, attr->xattri_leaf_bp);
-       attr->xattri_leaf_bp = NULL;
+       error = xfs_attr_leaf_try_add(args);
 
        if (error == -ENOSPC) {
                error = xfs_attr3_leaf_to_node(args);
@@ -497,8 +489,6 @@ xfs_attr_node_addname(
        struct xfs_da_args      *args = attr->xattri_da_args;
        int                     error;
 
-       ASSERT(!attr->xattri_leaf_bp);
-
        error = xfs_attr_node_addname_find_attr(attr);
        if (error)
                return error;
@@ -1215,24 +1205,14 @@ xfs_attr_restore_rmt_blk(
  */
 STATIC int
 xfs_attr_leaf_try_add(
-       struct xfs_da_args      *args,
-       struct xfs_buf          *bp)
+       struct xfs_da_args      *args)
 {
+       struct xfs_buf          *bp;
        int                     error;
 
-       /*
-        * If the caller provided a buffer to us, it is locked and held in
-        * the transaction because it just did a shortform to leaf conversion.
-        * Hence we don't need to read it again. Otherwise read in the leaf
-        * buffer.
-        */
-       if (bp) {
-               xfs_trans_bhold_release(args->trans, bp);
-       } else {
-               error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
-               if (error)
-                       return error;
-       }
+       error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
+       if (error)
+               return error;
 
        /*
         * Look up the xattr name to set the insertion point for the new xattr.
index b4a2fc7..dfb47fa 100644 (file)
@@ -515,11 +515,6 @@ struct xfs_attr_intent {
         */
        struct xfs_attri_log_nameval    *xattri_nameval;
 
-       /*
-        * Used by xfs_attr_set to hold a leaf buffer across a transaction roll
-        */
-       struct xfs_buf                  *xattri_leaf_bp;
-
        /* Used to keep track of current state of delayed operation */
        enum xfs_delattr_state          xattri_dela_state;
 
index 37e7c33..8f47396 100644 (file)
@@ -289,6 +289,23 @@ xfs_attr3_leaf_verify_entry(
        return NULL;
 }
 
+/*
+ * Validate an attribute leaf block.
+ *
+ * Empty leaf blocks can occur under the following circumstances:
+ *
+ * 1. setxattr adds a new extended attribute to a file;
+ * 2. The file has zero existing attributes;
+ * 3. The attribute is too large to fit in the attribute fork;
+ * 4. The attribute is small enough to fit in a leaf block;
+ * 5. A log flush occurs after committing the transaction that creates
+ *    the (empty) leaf block; and
+ * 6. The filesystem goes down after the log flush but before the new
+ *    attribute can be committed to the leaf block.
+ *
+ * Hence we need to ensure that we don't fail the validation purely
+ * because the leaf is empty.
+ */
 static xfs_failaddr_t
 xfs_attr3_leaf_verify(
        struct xfs_buf                  *bp)
@@ -310,15 +327,6 @@ xfs_attr3_leaf_verify(
        if (fa)
                return fa;
 
-       /*
-        * Empty leaf blocks should never occur;  they imply the existence of a
-        * software bug that needs fixing. xfs_repair also flags them as a
-        * corruption that needs fixing, so we should never let these go to
-        * disk.
-        */
-       if (ichdr.count == 0)
-               return __this_address;
-
        /*
         * firstused is the block offset of the first name info structure.
         * Make sure it doesn't go off the block or crash into the header.
@@ -922,14 +930,10 @@ xfs_attr_shortform_getvalue(
        return -ENOATTR;
 }
 
-/*
- * Convert from using the shortform to the leaf.  On success, return the
- * buffer so that we can keep it locked until we're totally done with it.
- */
+/* Convert from using the shortform to the leaf format. */
 int
 xfs_attr_shortform_to_leaf(
-       struct xfs_da_args              *args,
-       struct xfs_buf                  **leaf_bp)
+       struct xfs_da_args              *args)
 {
        struct xfs_inode                *dp;
        struct xfs_attr_shortform       *sf;
@@ -991,7 +995,6 @@ xfs_attr_shortform_to_leaf(
                sfe = xfs_attr_sf_nextentry(sfe);
        }
        error = 0;
-       *leaf_bp = bp;
 out:
        kmem_free(tmpbuffer);
        return error;
index efa757f..368f4d9 100644 (file)
@@ -49,8 +49,7 @@ void  xfs_attr_shortform_create(struct xfs_da_args *args);
 void   xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff);
 int    xfs_attr_shortform_lookup(struct xfs_da_args *args);
 int    xfs_attr_shortform_getvalue(struct xfs_da_args *args);
-int    xfs_attr_shortform_to_leaf(struct xfs_da_args *args,
-                       struct xfs_buf **leaf_bp);
+int    xfs_attr_shortform_to_leaf(struct xfs_da_args *args);
 int    xfs_attr_sf_removename(struct xfs_da_args *args);
 int    xfs_attr_sf_findname(struct xfs_da_args *args,
                             struct xfs_attr_sf_entry **sfep,
index 135d441..5077a7a 100644 (file)
@@ -576,7 +576,7 @@ xfs_attri_item_recover(
        struct xfs_trans_res            tres;
        struct xfs_attri_log_format     *attrp;
        struct xfs_attri_log_nameval    *nv = attrip->attri_nameval;
-       int                             error, ret = 0;
+       int                             error;
        int                             total;
        int                             local;
        struct xfs_attrd_log_item       *done_item = NULL;
@@ -655,29 +655,32 @@ xfs_attri_item_recover(
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        xfs_trans_ijoin(tp, ip, 0);
 
-       ret = xfs_xattri_finish_update(attr, done_item);
-       if (ret == -EAGAIN) {
-               /* There's more work to do, so add it to this transaction */
+       error = xfs_xattri_finish_update(attr, done_item);
+       if (error == -EAGAIN) {
+               /*
+                * There's more work to do, so add the intent item to this
+                * transaction so that we can continue it later.
+                */
                xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_ATTR, &attr->xattri_list);
-       } else
-               error = ret;
+               error = xfs_defer_ops_capture_and_commit(tp, capture_list);
+               if (error)
+                       goto out_unlock;
 
+               xfs_iunlock(ip, XFS_ILOCK_EXCL);
+               xfs_irele(ip);
+               return 0;
+       }
        if (error) {
                xfs_trans_cancel(tp);
                goto out_unlock;
        }
 
        error = xfs_defer_ops_capture_and_commit(tp, capture_list);
-
 out_unlock:
-       if (attr->xattri_leaf_bp)
-               xfs_buf_relse(attr->xattri_leaf_bp);
-
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        xfs_irele(ip);
 out:
-       if (ret != -EAGAIN)
-               xfs_attr_free_item(attr);
+       xfs_attr_free_item(attr);
        return error;
 }
 
index 52be583..85e1a26 100644 (file)
@@ -686,6 +686,8 @@ xfs_can_free_eofblocks(
         * forever.
         */
        end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip));
+       if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1)
+               end_fsb = roundup_64(end_fsb, mp->m_sb.sb_rextsize);
        last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
        if (last_fsb <= end_fsb)
                return false;
index 5269354..2609825 100644 (file)
@@ -440,7 +440,7 @@ xfs_inodegc_queue_all(
        for_each_online_cpu(cpu) {
                gc = per_cpu_ptr(mp->m_inodegc, cpu);
                if (!llist_empty(&gc->list))
-                       queue_work_on(cpu, mp->m_inodegc_wq, &gc->work);
+                       mod_delayed_work_on(cpu, mp->m_inodegc_wq, &gc->work, 0);
        }
 }
 
@@ -1841,8 +1841,8 @@ void
 xfs_inodegc_worker(
        struct work_struct      *work)
 {
-       struct xfs_inodegc      *gc = container_of(work, struct xfs_inodegc,
-                                                       work);
+       struct xfs_inodegc      *gc = container_of(to_delayed_work(work),
+                                               struct xfs_inodegc, work);
        struct llist_node       *node = llist_del_all(&gc->list);
        struct xfs_inode        *ip, *n;
 
@@ -1862,19 +1862,29 @@ xfs_inodegc_worker(
 }
 
 /*
- * Force all currently queued inode inactivation work to run immediately and
- * wait for the work to finish.
+ * Expedite all pending inodegc work to run immediately. This does not wait for
+ * completion of the work.
  */
 void
-xfs_inodegc_flush(
+xfs_inodegc_push(
        struct xfs_mount        *mp)
 {
        if (!xfs_is_inodegc_enabled(mp))
                return;
+       trace_xfs_inodegc_push(mp, __return_address);
+       xfs_inodegc_queue_all(mp);
+}
 
+/*
+ * Force all currently queued inode inactivation work to run immediately and
+ * wait for the work to finish.
+ */
+void
+xfs_inodegc_flush(
+       struct xfs_mount        *mp)
+{
+       xfs_inodegc_push(mp);
        trace_xfs_inodegc_flush(mp, __return_address);
-
-       xfs_inodegc_queue_all(mp);
        flush_workqueue(mp->m_inodegc_wq);
 }
 
@@ -2014,6 +2024,7 @@ xfs_inodegc_queue(
        struct xfs_inodegc      *gc;
        int                     items;
        unsigned int            shrinker_hits;
+       unsigned long           queue_delay = 1;
 
        trace_xfs_inode_set_need_inactive(ip);
        spin_lock(&ip->i_flags_lock);
@@ -2025,19 +2036,26 @@ xfs_inodegc_queue(
        items = READ_ONCE(gc->items);
        WRITE_ONCE(gc->items, items + 1);
        shrinker_hits = READ_ONCE(gc->shrinker_hits);
-       put_cpu_ptr(gc);
 
-       if (!xfs_is_inodegc_enabled(mp))
+       /*
+        * We queue the work while holding the current CPU so that the work
+        * is scheduled to run on this CPU.
+        */
+       if (!xfs_is_inodegc_enabled(mp)) {
+               put_cpu_ptr(gc);
                return;
-
-       if (xfs_inodegc_want_queue_work(ip, items)) {
-               trace_xfs_inodegc_queue(mp, __return_address);
-               queue_work(mp->m_inodegc_wq, &gc->work);
        }
 
+       if (xfs_inodegc_want_queue_work(ip, items))
+               queue_delay = 0;
+
+       trace_xfs_inodegc_queue(mp, __return_address);
+       mod_delayed_work(mp->m_inodegc_wq, &gc->work, queue_delay);
+       put_cpu_ptr(gc);
+
        if (xfs_inodegc_want_flush_work(ip, items, shrinker_hits)) {
                trace_xfs_inodegc_throttle(mp, __return_address);
-               flush_work(&gc->work);
+               flush_delayed_work(&gc->work);
        }
 }
 
@@ -2054,7 +2072,7 @@ xfs_inodegc_cpu_dead(
        unsigned int            count = 0;
 
        dead_gc = per_cpu_ptr(mp->m_inodegc, dead_cpu);
-       cancel_work_sync(&dead_gc->work);
+       cancel_delayed_work_sync(&dead_gc->work);
 
        if (llist_empty(&dead_gc->list))
                return;
@@ -2073,12 +2091,12 @@ xfs_inodegc_cpu_dead(
        llist_add_batch(first, last, &gc->list);
        count += READ_ONCE(gc->items);
        WRITE_ONCE(gc->items, count);
-       put_cpu_ptr(gc);
 
        if (xfs_is_inodegc_enabled(mp)) {
                trace_xfs_inodegc_queue(mp, __return_address);
-               queue_work(mp->m_inodegc_wq, &gc->work);
+               mod_delayed_work(mp->m_inodegc_wq, &gc->work, 0);
        }
+       put_cpu_ptr(gc);
 }
 
 /*
@@ -2173,7 +2191,7 @@ xfs_inodegc_shrinker_scan(
                        unsigned int    h = READ_ONCE(gc->shrinker_hits);
 
                        WRITE_ONCE(gc->shrinker_hits, h + 1);
-                       queue_work_on(cpu, mp->m_inodegc_wq, &gc->work);
+                       mod_delayed_work_on(cpu, mp->m_inodegc_wq, &gc->work, 0);
                        no_items = false;
                }
        }
index 2e4cfdd..6cd1807 100644 (file)
@@ -76,6 +76,7 @@ void xfs_blockgc_stop(struct xfs_mount *mp);
 void xfs_blockgc_start(struct xfs_mount *mp);
 
 void xfs_inodegc_worker(struct work_struct *work);
+void xfs_inodegc_push(struct xfs_mount *mp);
 void xfs_inodegc_flush(struct xfs_mount *mp);
 void xfs_inodegc_stop(struct xfs_mount *mp);
 void xfs_inodegc_start(struct xfs_mount *mp);
index 52d6f2c..3e1c62f 100644 (file)
@@ -131,6 +131,26 @@ xfs_ilock_attr_map_shared(
        return lock_mode;
 }
 
+/*
+ * You can't set both SHARED and EXCL for the same lock,
+ * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_MMAPLOCK_SHARED,
+ * XFS_MMAPLOCK_EXCL, XFS_ILOCK_SHARED, XFS_ILOCK_EXCL are valid values
+ * to set in lock_flags.
+ */
+static inline void
+xfs_lock_flags_assert(
+       uint            lock_flags)
+{
+       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
+               (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
+       ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) !=
+               (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL));
+       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
+               (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
+       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_SUBCLASS_MASK)) == 0);
+       ASSERT(lock_flags != 0);
+}
+
 /*
  * In addition to i_rwsem in the VFS inode, the xfs inode contains 2
  * multi-reader locks: invalidate_lock and the i_lock.  This routine allows
@@ -168,18 +188,7 @@ xfs_ilock(
 {
        trace_xfs_ilock(ip, lock_flags, _RET_IP_);
 
-       /*
-        * You can't set both SHARED and EXCL for the same lock,
-        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-        */
-       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) !=
-              (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_SUBCLASS_MASK)) == 0);
+       xfs_lock_flags_assert(lock_flags);
 
        if (lock_flags & XFS_IOLOCK_EXCL) {
                down_write_nested(&VFS_I(ip)->i_rwsem,
@@ -222,18 +231,7 @@ xfs_ilock_nowait(
 {
        trace_xfs_ilock_nowait(ip, lock_flags, _RET_IP_);
 
-       /*
-        * You can't set both SHARED and EXCL for the same lock,
-        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-        */
-       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) !=
-              (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_SUBCLASS_MASK)) == 0);
+       xfs_lock_flags_assert(lock_flags);
 
        if (lock_flags & XFS_IOLOCK_EXCL) {
                if (!down_write_trylock(&VFS_I(ip)->i_rwsem))
@@ -291,19 +289,7 @@ xfs_iunlock(
        xfs_inode_t             *ip,
        uint                    lock_flags)
 {
-       /*
-        * You can't set both SHARED and EXCL for the same lock,
-        * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
-        * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
-        */
-       ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
-              (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) !=
-              (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL));
-       ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
-              (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_SUBCLASS_MASK)) == 0);
-       ASSERT(lock_flags != 0);
+       xfs_lock_flags_assert(lock_flags);
 
        if (lock_flags & XFS_IOLOCK_EXCL)
                up_write(&VFS_I(ip)->i_rwsem);
@@ -379,8 +365,8 @@ xfs_isilocked(
        }
 
        if (lock_flags & (XFS_MMAPLOCK_EXCL|XFS_MMAPLOCK_SHARED)) {
-               return __xfs_rwsem_islocked(&VFS_I(ip)->i_rwsem,
-                               (lock_flags & XFS_IOLOCK_SHARED));
+               return __xfs_rwsem_islocked(&VFS_I(ip)->i_mapping->invalidate_lock,
+                               (lock_flags & XFS_MMAPLOCK_SHARED));
        }
 
        if (lock_flags & (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED)) {
index 1e972f8..ae904b2 100644 (file)
@@ -2092,8 +2092,6 @@ xlog_dealloc_log(
        xlog_in_core_t  *iclog, *next_iclog;
        int             i;
 
-       xlog_cil_destroy(log);
-
        /*
         * Cycle all the iclogbuf locks to make sure all log IO completion
         * is done before we tear down these buffers.
@@ -2105,6 +2103,13 @@ xlog_dealloc_log(
                iclog = iclog->ic_next;
        }
 
+       /*
+        * Destroy the CIL after waiting for iclog IO completion because an
+        * iclog EIO error will try to shut down the log, which accesses the
+        * CIL to wake up the waiters.
+        */
+       xlog_cil_destroy(log);
+
        iclog = log->l_iclog;
        for (i = 0; i < log->l_iclog_bufs; i++) {
                next_iclog = iclog->ic_next;
index ba5d42a..d2eaebd 100644 (file)
@@ -61,7 +61,7 @@ struct xfs_error_cfg {
  */
 struct xfs_inodegc {
        struct llist_head       list;
-       struct work_struct      work;
+       struct delayed_work     work;
 
        /* approximate count of inodes in the list */
        unsigned int            items;
index 74ac9ca..392cb39 100644 (file)
@@ -454,9 +454,12 @@ xfs_qm_scall_getquota(
        struct xfs_dquot        *dqp;
        int                     error;
 
-       /* Flush inodegc work at the start of a quota reporting scan. */
+       /*
+        * Expedite pending inodegc work at the start of a quota reporting
+        * scan but don't block waiting for it to complete.
+        */
        if (id == 0)
-               xfs_inodegc_flush(mp);
+               xfs_inodegc_push(mp);
 
        /*
         * Try to get the dquot. We don't want it allocated on disk, so don't
@@ -498,7 +501,7 @@ xfs_qm_scall_getquota_next(
 
        /* Flush inodegc work at the start of a quota reporting scan. */
        if (*id == 0)
-               xfs_inodegc_flush(mp);
+               xfs_inodegc_push(mp);
 
        error = xfs_qm_dqget_next(mp, *id, type, &dqp);
        if (error)
index ed18160..aa977c7 100644 (file)
@@ -797,8 +797,11 @@ xfs_fs_statfs(
        xfs_extlen_t            lsize;
        int64_t                 ffree;
 
-       /* Wait for whatever inactivations are in progress. */
-       xfs_inodegc_flush(mp);
+       /*
+        * Expedite background inodegc but don't wait. We do not want to block
+        * here waiting hours for a billion extent file to be truncated.
+        */
+       xfs_inodegc_push(mp);
 
        statp->f_type = XFS_SUPER_MAGIC;
        statp->f_namelen = MAXNAMELEN - 1;
@@ -1074,7 +1077,7 @@ xfs_inodegc_init_percpu(
                gc = per_cpu_ptr(mp->m_inodegc, cpu);
                init_llist_head(&gc->list);
                gc->items = 0;
-               INIT_WORK(&gc->work, xfs_inodegc_worker);
+               INIT_DELAYED_WORK(&gc->work, xfs_inodegc_worker);
        }
        return 0;
 }
index d320265..0fa1b7a 100644 (file)
@@ -240,6 +240,7 @@ DEFINE_EVENT(xfs_fs_class, name,                                    \
        TP_PROTO(struct xfs_mount *mp, void *caller_ip), \
        TP_ARGS(mp, caller_ip))
 DEFINE_FS_EVENT(xfs_inodegc_flush);
+DEFINE_FS_EVENT(xfs_inodegc_push);
 DEFINE_FS_EVENT(xfs_inodegc_start);
 DEFINE_FS_EVENT(xfs_inodegc_stop);
 DEFINE_FS_EVENT(xfs_inodegc_queue);
index c610858..d389bab 100644 (file)
@@ -145,6 +145,7 @@ extern bool cppc_allow_fast_switch(void);
 extern int acpi_get_psd_map(unsigned int cpu, struct cppc_cpudata *cpu_data);
 extern unsigned int cppc_get_transition_latency(int cpu);
 extern bool cpc_ffh_supported(void);
+extern bool cpc_supported_by_cpu(void);
 extern int cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val);
 extern int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val);
 #else /* !CONFIG_ACPI_CPPC_LIB */
index 4f82a5b..44975c1 100644 (file)
@@ -584,7 +584,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
 extern bool osc_sb_apei_support_acked;
 extern bool osc_pc_lpi_support_confirmed;
 extern bool osc_sb_native_usb4_support_confirmed;
-extern bool osc_sb_cppc_not_supported;
+extern bool osc_sb_cppc2_support_acked;
 extern bool osc_cpc_flexible_adr_space_confirmed;
 
 /* USB4 Capabilities */
index d08dfcb..4f2a819 100644 (file)
@@ -24,6 +24,7 @@ static inline void __chk_io_ptr(const volatile void __iomem *ptr) { }
 /* context/locking */
 # define __must_hold(x)        __attribute__((context(x,1,1)))
 # define __acquires(x) __attribute__((context(x,0,1)))
+# define __cond_acquires(x) __attribute__((context(x,0,-1)))
 # define __releases(x) __attribute__((context(x,1,0)))
 # define __acquire(x)  __context__(x,1)
 # define __release(x)  __context__(x,-1)
@@ -50,6 +51,7 @@ static inline void __chk_io_ptr(const volatile void __iomem *ptr) { }
 /* context/locking */
 # define __must_hold(x)
 # define __acquires(x)
+# define __cond_acquires(x)
 # define __releases(x)
 # define __acquire(x)  (void)0
 # define __release(x)  (void)0
index dc10bee..34aab4d 100644 (file)
@@ -148,6 +148,8 @@ struct devfreq_stats {
  *             reevaluate operable frequencies. Devfreq users may use
  *             devfreq.nb to the corresponding register notifier call chain.
  * @work:      delayed work for load monitoring.
+ * @freq_table:                current frequency table used by the devfreq driver.
+ * @max_state:         count of entry present in the frequency table.
  * @previous_freq:     previously configured frequency value.
  * @last_status:       devfreq user device info, performance statistics
  * @data:      Private data of the governor. The devfreq framework does not
@@ -185,6 +187,9 @@ struct devfreq {
        struct notifier_block nb;
        struct delayed_work work;
 
+       unsigned long *freq_table;
+       unsigned int max_state;
+
        unsigned long previous_freq;
        struct devfreq_dev_status last_status;
 
index b698266..6c57339 100644 (file)
@@ -21,7 +21,7 @@
  * We consider 10% difference as significant.
  */
 #define IS_SIGNIFICANT_DIFF(val, ref) \
-       (((100UL * abs((val) - (ref))) / (ref)) > 10)
+       ((ref) && (((100UL * abs((val) - (ref))) / (ref)) > 10))
 
 /*
  * Calculate the gap between two values.
index edc2855..e517dbc 100644 (file)
                                         FANOTIFY_PERM_EVENTS | \
                                         FAN_Q_OVERFLOW | FAN_ONDIR)
 
+/* Events and flags relevant only for directories */
+#define FANOTIFY_DIRONLY_EVENT_BITS    (FANOTIFY_DIRENT_EVENTS | \
+                                        FAN_EVENT_ON_CHILD | FAN_ONDIR)
+
 #define ALL_FANOTIFY_EVENT_BITS                (FANOTIFY_OUTGOING_EVENTS | \
                                         FANOTIFY_EVENT_FLAGS)
 
index ff5596d..2382dec 100644 (file)
@@ -15,6 +15,8 @@ void fbcon_new_modelist(struct fb_info *info);
 void fbcon_get_requirement(struct fb_info *info,
                           struct fb_blit_caps *caps);
 void fbcon_fb_blanked(struct fb_info *info, int blank);
+int  fbcon_modechange_possible(struct fb_info *info,
+                              struct fb_var_screeninfo *var);
 void fbcon_update_vcs(struct fb_info *info, bool all);
 void fbcon_remap_all(struct fb_info *info);
 int fbcon_set_con2fb_map_ioctl(void __user *argp);
@@ -33,6 +35,8 @@ static inline void fbcon_new_modelist(struct fb_info *info) {}
 static inline void fbcon_get_requirement(struct fb_info *info,
                                         struct fb_blit_caps *caps) {}
 static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {}
+static inline int  fbcon_modechange_possible(struct fb_info *info,
+                               struct fb_var_screeninfo *var) { return 0; }
 static inline void fbcon_update_vcs(struct fb_info *info, bool all) {}
 static inline void fbcon_remap_all(struct fb_info *info) {}
 static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; }
index 72585c9..b862656 100644 (file)
@@ -130,6 +130,7 @@ struct fscache_cookie {
 #define FSCACHE_COOKIE_DO_PREP_TO_WRITE        12              /* T if cookie needs write preparation */
 #define FSCACHE_COOKIE_HAVE_DATA       13              /* T if this cookie has data stored */
 #define FSCACHE_COOKIE_IS_HASHED       14              /* T if this cookie is hashed */
+#define FSCACHE_COOKIE_DO_INVALIDATE   15              /* T if cookie needs invalidation */
 
        enum fscache_cookie_state       state;
        u8                              advice;         /* FSCACHE_ADV_* */
index 4f29139..5fcf89f 100644 (file)
@@ -612,7 +612,6 @@ struct intel_iommu {
 struct device_domain_info {
        struct list_head link;  /* link to domain siblings */
        struct list_head global; /* link to global list */
-       struct list_head table; /* link to pasid table */
        u32 segment;            /* PCI segment number */
        u8 bus;                 /* PCI bus number */
        u8 devfn;               /* PCI devfn number */
@@ -729,8 +728,6 @@ extern int dmar_ir_support(void);
 void *alloc_pgtable_page(int node);
 void free_pgtable_page(void *vaddr);
 struct intel_iommu *domain_get_iommu(struct dmar_domain *domain);
-int for_each_device_domain(int (*fn)(struct device_domain_info *info,
-                                    void *data), void *data);
 void iommu_flush_write_buffer(struct intel_iommu *iommu);
 int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev);
 struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn);
index 99f17cc..c3a1f78 100644 (file)
@@ -38,7 +38,6 @@ extern void lockref_get(struct lockref *);
 extern int lockref_put_return(struct lockref *);
 extern int lockref_get_not_zero(struct lockref *);
 extern int lockref_put_not_zero(struct lockref *);
-extern int lockref_get_or_lock(struct lockref *);
 extern int lockref_put_or_lock(struct lockref *);
 
 extern void lockref_mark_dead(struct lockref *);
index e115952..c04c4fd 100644 (file)
@@ -16,7 +16,7 @@ static inline int memregion_alloc(gfp_t gfp)
 {
        return -ENOMEM;
 }
-void memregion_free(int id)
+static inline void memregion_free(int id)
 {
 }
 #endif
index f615a66..2563d30 100644 (file)
@@ -1671,7 +1671,7 @@ enum netdev_priv_flags {
        IFF_FAILOVER_SLAVE              = 1<<28,
        IFF_L3MDEV_RX_HANDLER           = 1<<29,
        IFF_LIVE_RENAME_OK              = 1<<30,
-       IFF_TX_SKB_NO_LINEAR            = 1<<31,
+       IFF_TX_SKB_NO_LINEAR            = BIT_ULL(31),
        IFF_CHANGE_PROTO_DOWN           = BIT_ULL(32),
 };
 
index e393400..07cfc92 100644 (file)
@@ -906,12 +906,14 @@ struct nvme_common_command {
        __le32                  cdw2[2];
        __le64                  metadata;
        union nvme_data_ptr     dptr;
+       struct_group(cdws,
        __le32                  cdw10;
        __le32                  cdw11;
        __le32                  cdw12;
        __le32                  cdw13;
        __le32                  cdw14;
        __le32                  cdw15;
+       );
 };
 
 struct nvme_rw_command {
index 508f114..b09f7d3 100644 (file)
@@ -572,6 +572,10 @@ struct macsec_ops;
  * @mdix_ctrl: User setting of crossover
  * @pma_extable: Cached value of PMA/PMD Extended Abilities Register
  * @interrupts: Flag interrupts have been enabled
+ * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
+ *                 handling shall be postponed until PHY has resumed
+ * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
+ *             requiring a rerun of the interrupt handler after resume
  * @interface: enum phy_interface_t value
  * @skb: Netlink message for cable diagnostics
  * @nest: Netlink nest used for cable diagnostics
@@ -626,6 +630,8 @@ struct phy_device {
 
        /* Interrupts are enabled */
        unsigned interrupts:1;
+       unsigned irq_suspended:1;
+       unsigned irq_rerun:1;
 
        enum phy_state state;
 
index 9e4d056..0a41b2d 100644 (file)
@@ -88,7 +88,7 @@ extern void pm_runtime_get_suppliers(struct device *dev);
 extern void pm_runtime_put_suppliers(struct device *dev);
 extern void pm_runtime_new_link(struct device *dev);
 extern void pm_runtime_drop_link(struct device_link *link);
-extern void pm_runtime_release_supplier(struct device_link *link, bool check_idle);
+extern void pm_runtime_release_supplier(struct device_link *link);
 
 extern int devm_pm_runtime_enable(struct device *dev);
 
@@ -314,8 +314,7 @@ static inline void pm_runtime_get_suppliers(struct device *dev) {}
 static inline void pm_runtime_put_suppliers(struct device *dev) {}
 static inline void pm_runtime_new_link(struct device *dev) {}
 static inline void pm_runtime_drop_link(struct device_link *link) {}
-static inline void pm_runtime_release_supplier(struct device_link *link,
-                                              bool check_idle) {}
+static inline void pm_runtime_release_supplier(struct device_link *link) {}
 
 #endif /* !CONFIG_PM */
 
index b8a6e38..a62fcca 100644 (file)
@@ -361,9 +361,9 @@ static inline void refcount_dec(refcount_t *r)
 
 extern __must_check bool refcount_dec_if_one(refcount_t *r);
 extern __must_check bool refcount_dec_not_one(refcount_t *r);
-extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock);
-extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock);
+extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock) __cond_acquires(lock);
+extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock) __cond_acquires(lock);
 extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r,
                                                       spinlock_t *lock,
-                                                      unsigned long *flags);
+                                                      unsigned long *flags) __cond_acquires(lock);
 #endif /* _LINUX_REFCOUNT_H */
index 159729c..3247ed8 100644 (file)
@@ -54,8 +54,6 @@ struct rtsx_ucr {
        struct usb_device       *pusb_dev;
        struct usb_interface    *pusb_intf;
        struct usb_sg_request   current_sg;
-       unsigned char           *iobuf;
-       dma_addr_t              iobuf_dma;
 
        struct timer_list       sg_timer;
        struct mutex            dev_mutex;
index 49c7c32..b47c2e7 100644 (file)
@@ -257,6 +257,7 @@ void virtio_device_ready(struct virtio_device *dev)
 
        WARN_ON(status & VIRTIO_CONFIG_S_DRIVER_OK);
 
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
        /*
         * The virtio_synchronize_cbs() makes sure vring_interrupt()
         * will see the driver specific setup if it sees vq->broken
@@ -264,6 +265,7 @@ void virtio_device_ready(struct virtio_device *dev)
         */
        virtio_synchronize_cbs(dev);
        __virtio_unbreak_device(dev);
+#endif
        /*
         * The transport should ensure the visibility of vq->broken
         * before setting DRIVER_OK. See the comments for the transport
index 6484095..7ac3138 100644 (file)
@@ -152,6 +152,7 @@ enum flow_action_id {
        FLOW_ACTION_PIPE,
        FLOW_ACTION_VLAN_PUSH_ETH,
        FLOW_ACTION_VLAN_POP_ETH,
+       FLOW_ACTION_CONTINUE,
        NUM_FLOW_ACTIONS,
 };
 
index 279ae0f..5c4e5a9 100644 (file)
@@ -1338,24 +1338,28 @@ void nft_unregister_flowtable_type(struct nf_flowtable_type *type);
 /**
  *     struct nft_traceinfo - nft tracing information and state
  *
+ *     @trace: other struct members are initialised
+ *     @nf_trace: copy of skb->nf_trace before rule evaluation
+ *     @type: event type (enum nft_trace_types)
+ *     @skbid: hash of skb to be used as trace id
+ *     @packet_dumped: packet headers sent in a previous traceinfo message
  *     @pkt: pktinfo currently processed
  *     @basechain: base chain currently processed
  *     @chain: chain currently processed
  *     @rule:  rule that was evaluated
  *     @verdict: verdict given by rule
- *     @type: event type (enum nft_trace_types)
- *     @packet_dumped: packet headers sent in a previous traceinfo message
- *     @trace: other struct members are initialised
  */
 struct nft_traceinfo {
+       bool                            trace;
+       bool                            nf_trace;
+       bool                            packet_dumped;
+       enum nft_trace_types            type:8;
+       u32                             skbid;
        const struct nft_pktinfo        *pkt;
        const struct nft_base_chain     *basechain;
        const struct nft_chain          *chain;
        const struct nft_rule_dp        *rule;
        const struct nft_verdict        *verdict;
-       enum nft_trace_types            type;
-       bool                            packet_dumped;
-       bool                            trace;
 };
 
 void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt,
index f20f5f8..b276dcb 100644 (file)
@@ -408,8 +408,6 @@ struct snd_soc_jack_pin;
 
 struct snd_soc_jack_gpio;
 
-typedef int (*hw_write_t)(void *,const char* ,int);
-
 enum snd_soc_pcm_subclass {
        SND_SOC_PCM_CLASS_PCM   = 0,
        SND_SOC_PCM_CLASS_BE    = 1,
index 53e7dae..0ad3da2 100644 (file)
@@ -22,7 +22,10 @@ struct io_uring_sqe {
        union {
                __u64   off;    /* offset into file */
                __u64   addr2;
-               __u32   cmd_op;
+               struct {
+                       __u32   cmd_op;
+                       __u32   __pad1;
+               };
        };
        union {
                __u64   addr;   /* pointer to buffer or iovecs */
@@ -244,7 +247,7 @@ enum io_uring_op {
 #define IORING_ASYNC_CANCEL_ANY        (1U << 2)
 
 /*
- * send/sendmsg and recv/recvmsg flags (sqe->addr2)
+ * send/sendmsg and recv/recvmsg flags (sqe->ioprio)
  *
  * IORING_RECVSEND_POLL_FIRST  If set, instead of first attempting to send
  *                             or receive and arm poll if that yields an
index 9219635..dfe19bf 100644 (file)
@@ -2,16 +2,17 @@
 #ifndef _UAPI_MPTCP_H
 #define _UAPI_MPTCP_H
 
+#ifndef __KERNEL__
+#include <netinet/in.h>                /* for sockaddr_in and sockaddr_in6     */
+#include <sys/socket.h>                /* for struct sockaddr                  */
+#endif
+
 #include <linux/const.h>
 #include <linux/types.h>
 #include <linux/in.h>          /* for sockaddr_in                      */
 #include <linux/in6.h>         /* for sockaddr_in6                     */
 #include <linux/socket.h>      /* for sockaddr_storage and sa_family   */
 
-#ifndef __KERNEL__
-#include <sys/socket.h>                /* for struct sockaddr                  */
-#endif
-
 #define MPTCP_SUBFLOW_FLAG_MCAP_REM            _BITUL(0)
 #define MPTCP_SUBFLOW_FLAG_MCAP_LOC            _BITUL(1)
 #define MPTCP_SUBFLOW_FLAG_JOIN_REM            _BITUL(2)
index e1126a7..eff166f 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef __LINUX_OF_DISPLAY_TIMING_H
 #define __LINUX_OF_DISPLAY_TIMING_H
 
+#include <linux/errno.h>
+
 struct device_node;
 struct display_timing;
 struct display_timings;
index aedac2a..0efbac0 100644 (file)
@@ -1562,6 +1562,21 @@ static void __reg_bound_offset(struct bpf_reg_state *reg)
        reg->var_off = tnum_or(tnum_clear_subreg(var64_off), var32_off);
 }
 
+static void reg_bounds_sync(struct bpf_reg_state *reg)
+{
+       /* We might have learned new bounds from the var_off. */
+       __update_reg_bounds(reg);
+       /* We might have learned something about the sign bit. */
+       __reg_deduce_bounds(reg);
+       /* We might have learned some bits from the bounds. */
+       __reg_bound_offset(reg);
+       /* Intersecting with the old var_off might have improved our bounds
+        * slightly, e.g. if umax was 0x7f...f and var_off was (0; 0xf...fc),
+        * then new var_off is (0; 0x7f...fc) which improves our umax.
+        */
+       __update_reg_bounds(reg);
+}
+
 static bool __reg32_bound_s64(s32 a)
 {
        return a >= 0 && a <= S32_MAX;
@@ -1603,16 +1618,8 @@ static void __reg_combine_32_into_64(struct bpf_reg_state *reg)
                 * so they do not impact tnum bounds calculation.
                 */
                __mark_reg64_unbounded(reg);
-               __update_reg_bounds(reg);
        }
-
-       /* Intersecting with the old var_off might have improved our bounds
-        * slightly.  e.g. if umax was 0x7f...f and var_off was (0; 0xf...fc),
-        * then new var_off is (0; 0x7f...fc) which improves our umax.
-        */
-       __reg_deduce_bounds(reg);
-       __reg_bound_offset(reg);
-       __update_reg_bounds(reg);
+       reg_bounds_sync(reg);
 }
 
 static bool __reg64_bound_s32(s64 a)
@@ -1628,7 +1635,6 @@ static bool __reg64_bound_u32(u64 a)
 static void __reg_combine_64_into_32(struct bpf_reg_state *reg)
 {
        __mark_reg32_unbounded(reg);
-
        if (__reg64_bound_s32(reg->smin_value) && __reg64_bound_s32(reg->smax_value)) {
                reg->s32_min_value = (s32)reg->smin_value;
                reg->s32_max_value = (s32)reg->smax_value;
@@ -1637,14 +1643,7 @@ static void __reg_combine_64_into_32(struct bpf_reg_state *reg)
                reg->u32_min_value = (u32)reg->umin_value;
                reg->u32_max_value = (u32)reg->umax_value;
        }
-
-       /* Intersecting with the old var_off might have improved our bounds
-        * slightly.  e.g. if umax was 0x7f...f and var_off was (0; 0xf...fc),
-        * then new var_off is (0; 0x7f...fc) which improves our umax.
-        */
-       __reg_deduce_bounds(reg);
-       __reg_bound_offset(reg);
-       __update_reg_bounds(reg);
+       reg_bounds_sync(reg);
 }
 
 /* Mark a register as having a completely unknown (scalar) value. */
@@ -6943,9 +6942,7 @@ static void do_refine_retval_range(struct bpf_reg_state *regs, int ret_type,
        ret_reg->s32_max_value = meta->msize_max_value;
        ret_reg->smin_value = -MAX_ERRNO;
        ret_reg->s32_min_value = -MAX_ERRNO;
-       __reg_deduce_bounds(ret_reg);
-       __reg_bound_offset(ret_reg);
-       __update_reg_bounds(ret_reg);
+       reg_bounds_sync(ret_reg);
 }
 
 static int
@@ -8202,11 +8199,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
 
        if (!check_reg_sane_offset(env, dst_reg, ptr_reg->type))
                return -EINVAL;
-
-       __update_reg_bounds(dst_reg);
-       __reg_deduce_bounds(dst_reg);
-       __reg_bound_offset(dst_reg);
-
+       reg_bounds_sync(dst_reg);
        if (sanitize_check_bounds(env, insn, dst_reg) < 0)
                return -EACCES;
        if (sanitize_needed(opcode)) {
@@ -8944,10 +8937,7 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
        /* ALU32 ops are zero extended into 64bit register */
        if (alu32)
                zext_32_to_64(dst_reg);
-
-       __update_reg_bounds(dst_reg);
-       __reg_deduce_bounds(dst_reg);
-       __reg_bound_offset(dst_reg);
+       reg_bounds_sync(dst_reg);
        return 0;
 }
 
@@ -9136,10 +9126,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
                                                         insn->dst_reg);
                                }
                                zext_32_to_64(dst_reg);
-
-                               __update_reg_bounds(dst_reg);
-                               __reg_deduce_bounds(dst_reg);
-                               __reg_bound_offset(dst_reg);
+                               reg_bounds_sync(dst_reg);
                        }
                } else {
                        /* case: R = imm
@@ -9577,26 +9564,33 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
                return;
 
        switch (opcode) {
+       /* JEQ/JNE comparison doesn't change the register equivalence.
+        *
+        * r1 = r2;
+        * if (r1 == 42) goto label;
+        * ...
+        * label: // here both r1 and r2 are known to be 42.
+        *
+        * Hence when marking register as known preserve it's ID.
+        */
        case BPF_JEQ:
+               if (is_jmp32) {
+                       __mark_reg32_known(true_reg, val32);
+                       true_32off = tnum_subreg(true_reg->var_off);
+               } else {
+                       ___mark_reg_known(true_reg, val);
+                       true_64off = true_reg->var_off;
+               }
+               break;
        case BPF_JNE:
-       {
-               struct bpf_reg_state *reg =
-                       opcode == BPF_JEQ ? true_reg : false_reg;
-
-               /* JEQ/JNE comparison doesn't change the register equivalence.
-                * r1 = r2;
-                * if (r1 == 42) goto label;
-                * ...
-                * label: // here both r1 and r2 are known to be 42.
-                *
-                * Hence when marking register as known preserve it's ID.
-                */
-               if (is_jmp32)
-                       __mark_reg32_known(reg, val32);
-               else
-                       ___mark_reg_known(reg, val);
+               if (is_jmp32) {
+                       __mark_reg32_known(false_reg, val32);
+                       false_32off = tnum_subreg(false_reg->var_off);
+               } else {
+                       ___mark_reg_known(false_reg, val);
+                       false_64off = false_reg->var_off;
+               }
                break;
-       }
        case BPF_JSET:
                if (is_jmp32) {
                        false_32off = tnum_and(false_32off, tnum_const(~val32));
@@ -9735,21 +9729,8 @@ static void __reg_combine_min_max(struct bpf_reg_state *src_reg,
                                                        dst_reg->smax_value);
        src_reg->var_off = dst_reg->var_off = tnum_intersect(src_reg->var_off,
                                                             dst_reg->var_off);
-       /* We might have learned new bounds from the var_off. */
-       __update_reg_bounds(src_reg);
-       __update_reg_bounds(dst_reg);
-       /* We might have learned something about the sign bit. */
-       __reg_deduce_bounds(src_reg);
-       __reg_deduce_bounds(dst_reg);
-       /* We might have learned some bits from the bounds. */
-       __reg_bound_offset(src_reg);
-       __reg_bound_offset(dst_reg);
-       /* Intersecting with the old var_off might have improved our bounds
-        * slightly.  e.g. if umax was 0x7f...f and var_off was (0; 0xf...fc),
-        * then new var_off is (0; 0x7f...fc) which improves our umax.
-        */
-       __update_reg_bounds(src_reg);
-       __update_reg_bounds(dst_reg);
+       reg_bounds_sync(src_reg);
+       reg_bounds_sync(dst_reg);
 }
 
 static void reg_combine_min_max(struct bpf_reg_state *true_src,
index 156a992..1893d90 100644 (file)
@@ -222,7 +222,7 @@ static void ptrace_unfreeze_traced(struct task_struct *task)
        if (lock_task_sighand(task, &flags)) {
                task->jobctl &= ~JOBCTL_PTRACE_FROZEN;
                if (__fatal_signal_pending(task)) {
-                       task->jobctl &= ~TASK_TRACED;
+                       task->jobctl &= ~JOBCTL_TRACED;
                        wake_up_state(task, __TASK_TRACED);
                }
                unlock_task_sighand(task, &flags);
index edb1dc9..6f86fda 100644 (file)
@@ -2029,12 +2029,12 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
        bool autoreap = false;
        u64 utime, stime;
 
-       BUG_ON(sig == -1);
+       WARN_ON_ONCE(sig == -1);
 
-       /* do_notify_parent_cldstop should have been called instead.  */
-       BUG_ON(task_is_stopped_or_traced(tsk));
+       /* do_notify_parent_cldstop should have been called instead.  */
+       WARN_ON_ONCE(task_is_stopped_or_traced(tsk));
 
-       BUG_ON(!tsk->ptrace &&
+       WARN_ON_ONCE(!tsk->ptrace &&
               (tsk->group_leader != tsk || !thread_group_empty(tsk)));
 
        /* Wake up all pidfd waiters */
index 58a11f8..3004958 100644 (file)
@@ -526,7 +526,6 @@ void __init tick_nohz_full_setup(cpumask_var_t cpumask)
        cpumask_copy(tick_nohz_full_mask, cpumask);
        tick_nohz_full_running = true;
 }
-EXPORT_SYMBOL_GPL(tick_nohz_full_setup);
 
 static int tick_nohz_cpu_down(unsigned int cpu)
 {
index f4ab4f4..7ecdfdb 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -491,7 +491,8 @@ void ida_free(struct ida *ida, unsigned int id)
        struct ida_bitmap *bitmap;
        unsigned long flags;
 
-       BUG_ON((int)id < 0);
+       if ((int)id < 0)
+               return;
 
        xas_lock_irqsave(&xas, flags);
        bitmap = xas_load(&xas);
index c6f0b18..45e93ec 100644 (file)
@@ -110,31 +110,6 @@ int lockref_put_not_zero(struct lockref *lockref)
 }
 EXPORT_SYMBOL(lockref_put_not_zero);
 
-/**
- * lockref_get_or_lock - Increments count unless the count is 0 or dead
- * @lockref: pointer to lockref structure
- * Return: 1 if count updated successfully or 0 if count was zero
- * and we got the lock instead.
- */
-int lockref_get_or_lock(struct lockref *lockref)
-{
-       CMPXCHG_LOOP(
-               new.count++;
-               if (old.count <= 0)
-                       break;
-       ,
-               return 1;
-       );
-
-       spin_lock(&lockref->lock);
-       if (lockref->count <= 0)
-               return 0;
-       lockref->count++;
-       spin_unlock(&lockref->lock);
-       return 1;
-}
-EXPORT_SYMBOL(lockref_get_or_lock);
-
 /**
  * lockref_put_return - Decrement reference count if possible
  * @lockref: pointer to lockref structure
index ae4fd4d..29eb048 100644 (file)
@@ -528,7 +528,7 @@ unsigned long __sbitmap_queue_get_batch(struct sbitmap_queue *sbq, int nr_tags,
 
                sbitmap_deferred_clear(map);
                if (map->word == (1UL << (map_depth - 1)) - 1)
-                       continue;
+                       goto next;
 
                nr = find_first_zero_bit(&map->word, map_depth);
                if (nr + nr_tags <= map_depth) {
@@ -539,6 +539,8 @@ unsigned long __sbitmap_queue_get_batch(struct sbitmap_queue *sbq, int nr_tags,
                        get_mask = ((1UL << map_tags) - 1) << nr;
                        do {
                                val = READ_ONCE(map->word);
+                               if ((val & ~get_mask) != val)
+                                       goto next;
                                ret = atomic_long_cmpxchg(ptr, val, get_mask | val);
                        } while (ret != val);
                        get_mask = (get_mask & ~ret) >> nr;
@@ -549,6 +551,7 @@ unsigned long __sbitmap_queue_get_batch(struct sbitmap_queue *sbq, int nr_tags,
                                return get_mask;
                        }
                }
+next:
                /* Jump to next index. */
                if (++index >= sb->map_nr)
                        index = 0;
index 59a5c13..a0f99ba 100644 (file)
@@ -571,6 +571,7 @@ int hci_dev_close(__u16 dev)
                goto done;
        }
 
+       cancel_work_sync(&hdev->power_on);
        if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF))
                cancel_delayed_work(&hdev->power_off);
 
@@ -2675,6 +2676,8 @@ void hci_unregister_dev(struct hci_dev *hdev)
        list_del(&hdev->list);
        write_unlock(&hci_dev_list_lock);
 
+       cancel_work_sync(&hdev->power_on);
+
        hci_cmd_sync_clear(hdev);
 
        if (!test_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks))
index 286d676..1739e8c 100644 (file)
@@ -4088,7 +4088,6 @@ int hci_dev_close_sync(struct hci_dev *hdev)
 
        bt_dev_dbg(hdev, "");
 
-       cancel_work_sync(&hdev->power_on);
        cancel_delayed_work(&hdev->power_off);
        cancel_delayed_work(&hdev->ncmd_timer);
 
index 4fd8826..ff47790 100644 (file)
@@ -1012,9 +1012,24 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net,
                return okfn(net, sk, skb);
 
        ops = nf_hook_entries_get_hook_ops(e);
-       for (i = 0; i < e->num_hook_entries &&
-             ops[i]->priority <= NF_BR_PRI_BRNF; i++)
-               ;
+       for (i = 0; i < e->num_hook_entries; i++) {
+               /* These hooks have already been called */
+               if (ops[i]->priority < NF_BR_PRI_BRNF)
+                       continue;
+
+               /* These hooks have not been called yet, run them. */
+               if (ops[i]->priority > NF_BR_PRI_BRNF)
+                       break;
+
+               /* take a closer look at NF_BR_PRI_BRNF. */
+               if (ops[i]->hook == br_nf_pre_routing) {
+                       /* This hook diverted the skb to this function,
+                        * hooks after this have not been run yet.
+                        */
+                       i++;
+                       break;
+               }
+       }
 
        nf_hook_state_init(&state, hook, NFPROTO_BRIDGE, indev, outdev,
                           sk, net, okfn);
index 65ee1b7..e60161b 100644 (file)
@@ -100,6 +100,7 @@ static inline u64 get_u64(const struct canfd_frame *cp, int offset)
 
 struct bcm_op {
        struct list_head list;
+       struct rcu_head rcu;
        int ifindex;
        canid_t can_id;
        u32 flags;
@@ -718,10 +719,9 @@ static struct bcm_op *bcm_find_op(struct list_head *ops,
        return NULL;
 }
 
-static void bcm_remove_op(struct bcm_op *op)
+static void bcm_free_op_rcu(struct rcu_head *rcu_head)
 {
-       hrtimer_cancel(&op->timer);
-       hrtimer_cancel(&op->thrtimer);
+       struct bcm_op *op = container_of(rcu_head, struct bcm_op, rcu);
 
        if ((op->frames) && (op->frames != &op->sframe))
                kfree(op->frames);
@@ -732,6 +732,14 @@ static void bcm_remove_op(struct bcm_op *op)
        kfree(op);
 }
 
+static void bcm_remove_op(struct bcm_op *op)
+{
+       hrtimer_cancel(&op->timer);
+       hrtimer_cancel(&op->thrtimer);
+
+       call_rcu(&op->rcu, bcm_free_op_rcu);
+}
+
 static void bcm_rx_unreg(struct net_device *dev, struct bcm_op *op)
 {
        if (op->rx_reg_dev == dev) {
@@ -757,6 +765,9 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
                if ((op->can_id == mh->can_id) && (op->ifindex == ifindex) &&
                    (op->flags & CAN_FD_FRAME) == (mh->flags & CAN_FD_FRAME)) {
 
+                       /* disable automatic timer on frame reception */
+                       op->flags |= RX_NO_AUTOTIMER;
+
                        /*
                         * Don't care if we're bound or not (due to netdev
                         * problems) can_rx_unregister() is always a save
@@ -785,7 +796,6 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
                                                  bcm_rx_handler, op);
 
                        list_del(&op->list);
-                       synchronize_rcu();
                        bcm_remove_op(op);
                        return 1; /* done */
                }
index 6b2dc7b..cc1caab 100644 (file)
@@ -410,7 +410,7 @@ int skb_tunnel_check_pmtu(struct sk_buff *skb, struct dst_entry *encap_dst,
        u32 mtu = dst_mtu(encap_dst) - headroom;
 
        if ((skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu)) ||
-           (!skb_is_gso(skb) && (skb->len - skb_mac_header_len(skb)) <= mtu))
+           (!skb_is_gso(skb) && (skb->len - skb_network_offset(skb)) <= mtu))
                return 0;
 
        skb_dst_update_pmtu_no_confirm(skb, mtu);
index fe8f23b..da5a3c4 100644 (file)
@@ -1964,7 +1964,10 @@ process:
                struct sock *nsk;
 
                sk = req->rsk_listener;
-               drop_reason = tcp_inbound_md5_hash(sk, skb,
+               if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
+                       drop_reason = SKB_DROP_REASON_XFRM_POLICY;
+               else
+                       drop_reason = tcp_inbound_md5_hash(sk, skb,
                                                   &iph->saddr, &iph->daddr,
                                                   AF_INET, dif, sdif);
                if (unlikely(drop_reason)) {
@@ -2016,6 +2019,7 @@ process:
                        }
                        goto discard_and_relse;
                }
+               nf_reset_ct(skb);
                if (nsk == sk) {
                        reqsk_put(req);
                        tcp_v4_restore_cb(skb);
index 1b19325..49cc658 100644 (file)
@@ -1109,10 +1109,6 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
                goto out;
        }
 
-       if (net->ipv6.devconf_all->disable_policy ||
-           idev->cnf.disable_policy)
-               f6i->dst_nopolicy = true;
-
        neigh_parms_data_state_setall(idev->nd_parms);
 
        ifa->addr = *cfg->pfx;
@@ -5172,9 +5168,9 @@ next:
                fillargs->event = RTM_GETMULTICAST;
 
                /* multicast address */
-               for (ifmca = rcu_dereference(idev->mc_list);
+               for (ifmca = rtnl_dereference(idev->mc_list);
                     ifmca;
-                    ifmca = rcu_dereference(ifmca->next), ip_idx++) {
+                    ifmca = rtnl_dereference(ifmca->next), ip_idx++) {
                        if (ip_idx < s_ip_idx)
                                continue;
                        err = inet6_fill_ifmcaddr(skb, ifmca, fillargs);
index d25dc83..8283557 100644 (file)
@@ -4569,8 +4569,15 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
        }
 
        f6i = ip6_route_info_create(&cfg, gfp_flags, NULL);
-       if (!IS_ERR(f6i))
+       if (!IS_ERR(f6i)) {
                f6i->dst_nocount = true;
+
+               if (!anycast &&
+                   (net->ipv6.devconf_all->disable_policy ||
+                    idev->cnf.disable_policy))
+                       f6i->dst_nopolicy = true;
+       }
+
        return f6i;
 }
 
index 6de0118..d43c50a 100644 (file)
@@ -406,7 +406,6 @@ int __net_init seg6_hmac_net_init(struct net *net)
 
        return rhashtable_init(&sdata->hmac_infos, &rht_params);
 }
-EXPORT_SYMBOL(seg6_hmac_net_init);
 
 void seg6_hmac_exit(void)
 {
index c0b138c..6bcd5e4 100644 (file)
@@ -323,8 +323,6 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u
                kcalloc(cmax, sizeof(*kp), GFP_KERNEL_ACCOUNT | __GFP_NOWARN) :
                NULL;
 
-       rcu_read_lock();
-
        ca = min(t->prl_count, cmax);
 
        if (!kp) {
@@ -341,7 +339,7 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u
                }
        }
 
-       c = 0;
+       rcu_read_lock();
        for_each_prl_rcu(t->prl) {
                if (c >= cmax)
                        break;
@@ -353,7 +351,7 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u
                if (kprl.addr != htonl(INADDR_ANY))
                        break;
        }
-out:
+
        rcu_read_unlock();
 
        len = sizeof(*kp) * c;
@@ -362,7 +360,7 @@ out:
                ret = -EFAULT;
 
        kfree(kp);
-
+out:
        return ret;
 }
 
index be3b918..bd8f0f4 100644 (file)
@@ -765,6 +765,7 @@ static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_bu
        opts->suboptions |= OPTION_MPTCP_RST;
        opts->reset_transient = subflow->reset_transient;
        opts->reset_reason = subflow->reset_reason;
+       MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPRSTTX);
 
        return true;
 }
@@ -788,6 +789,7 @@ static bool mptcp_established_options_fastclose(struct sock *sk,
        opts->rcvr_key = msk->remote_key;
 
        pr_debug("FASTCLOSE key=%llu", opts->rcvr_key);
+       MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFASTCLOSETX);
        return true;
 }
 
@@ -809,6 +811,7 @@ static bool mptcp_established_options_mp_fail(struct sock *sk,
        opts->fail_seq = subflow->map_seq;
 
        pr_debug("MP_FAIL fail_seq=%llu", opts->fail_seq);
+       MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILTX);
 
        return true;
 }
@@ -833,13 +836,11 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
                    mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) {
                        *size += opt_size;
                        remaining -= opt_size;
-                       MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFASTCLOSETX);
                }
                /* MP_RST can be used with MP_FASTCLOSE and MP_FAIL if there is room */
                if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) {
                        *size += opt_size;
                        remaining -= opt_size;
-                       MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPRSTTX);
                }
                return true;
        }
@@ -966,7 +967,7 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
                        goto reset;
                subflow->mp_capable = 0;
                pr_fallback(msk);
-               __mptcp_do_fallback(msk);
+               mptcp_do_fallback(ssk);
                return false;
        }
 
@@ -1583,6 +1584,9 @@ mp_rst:
                *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO,
                                      TCPOLEN_MPTCP_PRIO,
                                      opts->backup, TCPOPT_NOP);
+
+               MPTCP_INC_STATS(sock_net((const struct sock *)tp),
+                               MPTCP_MIB_MPPRIOTX);
        }
 
 mp_capable_done:
index 59a8522..45e2a48 100644 (file)
@@ -299,23 +299,21 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
 {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
        struct mptcp_sock *msk = mptcp_sk(subflow->conn);
-       struct sock *s = (struct sock *)msk;
 
        pr_debug("fail_seq=%llu", fail_seq);
 
        if (!READ_ONCE(msk->allow_infinite_fallback))
                return;
 
-       if (!READ_ONCE(subflow->mp_fail_response_expect)) {
+       if (!subflow->fail_tout) {
                pr_debug("send MP_FAIL response and infinite map");
 
                subflow->send_mp_fail = 1;
-               MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILTX);
                subflow->send_infinite_map = 1;
-       } else if (!sock_flag(sk, SOCK_DEAD)) {
+               tcp_send_ack(sk);
+       } else {
                pr_debug("MP_FAIL response received");
-
-               sk_stop_timer(s, &s->sk_timer);
+               WRITE_ONCE(subflow->fail_tout, 0);
        }
 }
 
index e099f2a..7c7395b 100644 (file)
@@ -717,9 +717,10 @@ void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk)
        }
 }
 
-static int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
-                                       struct mptcp_addr_info *addr,
-                                       u8 bkup)
+int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
+                                struct mptcp_addr_info *addr,
+                                struct mptcp_addr_info *rem,
+                                u8 bkup)
 {
        struct mptcp_subflow_context *subflow;
 
@@ -727,24 +728,29 @@ static int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
 
        mptcp_for_each_subflow(msk, subflow) {
                struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
-               struct sock *sk = (struct sock *)msk;
-               struct mptcp_addr_info local;
+               struct mptcp_addr_info local, remote;
+               bool slow;
 
                local_address((struct sock_common *)ssk, &local);
                if (!mptcp_addresses_equal(&local, addr, addr->port))
                        continue;
 
+               if (rem && rem->family != AF_UNSPEC) {
+                       remote_address((struct sock_common *)ssk, &remote);
+                       if (!mptcp_addresses_equal(&remote, rem, rem->port))
+                               continue;
+               }
+
+               slow = lock_sock_fast(ssk);
                if (subflow->backup != bkup)
                        msk->last_snd = NULL;
                subflow->backup = bkup;
                subflow->send_mp_prio = 1;
                subflow->request_bkup = bkup;
-               __MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPPRIOTX);
 
-               spin_unlock_bh(&msk->pm.lock);
                pr_debug("send ack for mp_prio");
-               mptcp_subflow_send_ack(ssk);
-               spin_lock_bh(&msk->pm.lock);
+               __mptcp_subflow_send_ack(ssk);
+               unlock_sock_fast(ssk, slow);
 
                return 0;
        }
@@ -801,7 +807,8 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
                        removed = true;
                        __MPTCP_INC_STATS(sock_net(sk), rm_type);
                }
-               __set_bit(rm_list->ids[i], msk->pm.id_avail_bitmap);
+               if (rm_type == MPTCP_MIB_RMSUBFLOW)
+                       __set_bit(rm_list->ids[i], msk->pm.id_avail_bitmap);
                if (!removed)
                        continue;
 
@@ -1816,8 +1823,10 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk,
 
        list.ids[list.nr++] = addr->id;
 
+       spin_lock_bh(&msk->pm.lock);
        mptcp_pm_nl_rm_subflow_received(msk, &list);
        mptcp_pm_create_subflow_or_signal_addr(msk);
+       spin_unlock_bh(&msk->pm.lock);
 }
 
 static int mptcp_nl_set_flags(struct net *net,
@@ -1835,12 +1844,10 @@ static int mptcp_nl_set_flags(struct net *net,
                        goto next;
 
                lock_sock(sk);
-               spin_lock_bh(&msk->pm.lock);
                if (changed & MPTCP_PM_ADDR_FLAG_BACKUP)
-                       ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, bkup);
+                       ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, NULL, bkup);
                if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH)
                        mptcp_pm_nl_fullmesh(msk, addr);
-               spin_unlock_bh(&msk->pm.lock);
                release_sock(sk);
 
 next:
@@ -1854,6 +1861,9 @@ next:
 static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
 {
        struct mptcp_pm_addr_entry addr = { .addr = { .family = AF_UNSPEC }, }, *entry;
+       struct mptcp_pm_addr_entry remote = { .addr = { .family = AF_UNSPEC }, };
+       struct nlattr *attr_rem = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
+       struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
        struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
        struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
        u8 changed, mask = MPTCP_PM_ADDR_FLAG_BACKUP |
@@ -1866,6 +1876,12 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
        if (ret < 0)
                return ret;
 
+       if (attr_rem) {
+               ret = mptcp_pm_parse_entry(attr_rem, info, false, &remote);
+               if (ret < 0)
+                       return ret;
+       }
+
        if (addr.flags & MPTCP_PM_ADDR_FLAG_BACKUP)
                bkup = 1;
        if (addr.addr.family == AF_UNSPEC) {
@@ -1874,6 +1890,10 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
                        return -EOPNOTSUPP;
        }
 
+       if (token)
+               return mptcp_userspace_pm_set_flags(sock_net(skb->sk),
+                                                   token, &addr, &remote, bkup);
+
        spin_lock_bh(&pernet->lock);
        entry = __lookup_addr(pernet, &addr.addr, lookup_by_id);
        if (!entry) {
index f56378e..9e82250 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "protocol.h"
+#include "mib.h"
 
 void mptcp_free_local_addr_list(struct mptcp_sock *msk)
 {
@@ -306,15 +307,11 @@ static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk,
                                      const struct mptcp_addr_info *local,
                                      const struct mptcp_addr_info *remote)
 {
-       struct sock *sk = &msk->sk.icsk_inet.sk;
        struct mptcp_subflow_context *subflow;
-       struct sock *found = NULL;
 
        if (local->family != remote->family)
                return NULL;
 
-       lock_sock(sk);
-
        mptcp_for_each_subflow(msk, subflow) {
                const struct inet_sock *issk;
                struct sock *ssk;
@@ -347,16 +344,11 @@ static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk,
                }
 
                if (issk->inet_sport == local->port &&
-                   issk->inet_dport == remote->port) {
-                       found = ssk;
-                       goto found;
-               }
+                   issk->inet_dport == remote->port)
+                       return ssk;
        }
 
-found:
-       release_sock(sk);
-
-       return found;
+       return NULL;
 }
 
 int mptcp_nl_cmd_sf_destroy(struct sk_buff *skb, struct genl_info *info)
@@ -412,18 +404,51 @@ int mptcp_nl_cmd_sf_destroy(struct sk_buff *skb, struct genl_info *info)
        }
 
        sk = &msk->sk.icsk_inet.sk;
+       lock_sock(sk);
        ssk = mptcp_nl_find_ssk(msk, &addr_l, &addr_r);
        if (ssk) {
                struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
 
                mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
                mptcp_close_ssk(sk, ssk, subflow);
+               MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
                err = 0;
        } else {
                err = -ESRCH;
        }
+       release_sock(sk);
 
- destroy_err:
+destroy_err:
        sock_put((struct sock *)msk);
        return err;
 }
+
+int mptcp_userspace_pm_set_flags(struct net *net, struct nlattr *token,
+                                struct mptcp_pm_addr_entry *loc,
+                                struct mptcp_pm_addr_entry *rem, u8 bkup)
+{
+       struct mptcp_sock *msk;
+       int ret = -EINVAL;
+       u32 token_val;
+
+       token_val = nla_get_u32(token);
+
+       msk = mptcp_token_get_sock(net, token_val);
+       if (!msk)
+               return ret;
+
+       if (!mptcp_pm_is_userspace(msk))
+               goto set_flags_err;
+
+       if (loc->addr.family == AF_UNSPEC ||
+           rem->addr.family == AF_UNSPEC)
+               goto set_flags_err;
+
+       lock_sock((struct sock *)msk);
+       ret = mptcp_pm_nl_mp_prio_send_ack(msk, &loc->addr, &rem->addr, bkup);
+       release_sock((struct sock *)msk);
+
+set_flags_err:
+       sock_put((struct sock *)msk);
+       return ret;
+}
index 17e1339..cc21faf 100644 (file)
@@ -500,19 +500,24 @@ static void mptcp_set_timeout(struct sock *sk)
        __mptcp_set_timeout(sk, tout);
 }
 
-static bool tcp_can_send_ack(const struct sock *ssk)
+static inline bool tcp_can_send_ack(const struct sock *ssk)
 {
        return !((1 << inet_sk_state_load(ssk)) &
               (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_TIME_WAIT | TCPF_CLOSE | TCPF_LISTEN));
 }
 
+void __mptcp_subflow_send_ack(struct sock *ssk)
+{
+       if (tcp_can_send_ack(ssk))
+               tcp_send_ack(ssk);
+}
+
 void mptcp_subflow_send_ack(struct sock *ssk)
 {
        bool slow;
 
        slow = lock_sock_fast(ssk);
-       if (tcp_can_send_ack(ssk))
-               tcp_send_ack(ssk);
+       __mptcp_subflow_send_ack(ssk);
        unlock_sock_fast(ssk, slow);
 }
 
@@ -1245,7 +1250,7 @@ static void mptcp_update_infinite_map(struct mptcp_sock *msk,
        MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPTX);
        mptcp_subflow_ctx(ssk)->send_infinite_map = 0;
        pr_fallback(msk);
-       __mptcp_do_fallback(msk);
+       mptcp_do_fallback(ssk);
 }
 
 static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
@@ -2175,21 +2180,6 @@ static void mptcp_retransmit_timer(struct timer_list *t)
        sock_put(sk);
 }
 
-static struct mptcp_subflow_context *
-mp_fail_response_expect_subflow(struct mptcp_sock *msk)
-{
-       struct mptcp_subflow_context *subflow, *ret = NULL;
-
-       mptcp_for_each_subflow(msk, subflow) {
-               if (READ_ONCE(subflow->mp_fail_response_expect)) {
-                       ret = subflow;
-                       break;
-               }
-       }
-
-       return ret;
-}
-
 static void mptcp_timeout_timer(struct timer_list *t)
 {
        struct sock *sk = from_timer(sk, t, sk_timer);
@@ -2346,6 +2336,11 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
                kfree_rcu(subflow, rcu);
        } else {
                /* otherwise tcp will dispose of the ssk and subflow ctx */
+               if (ssk->sk_state == TCP_LISTEN) {
+                       tcp_set_state(ssk, TCP_CLOSE);
+                       mptcp_subflow_queue_clean(ssk);
+                       inet_csk_listen_stop(ssk);
+               }
                __tcp_close(ssk, 0);
 
                /* close acquired an extra ref */
@@ -2518,27 +2513,50 @@ reset_timer:
                mptcp_reset_timer(sk);
 }
 
+/* schedule the timeout timer for the relevant event: either close timeout
+ * or mp_fail timeout. The close timeout takes precedence on the mp_fail one
+ */
+void mptcp_reset_timeout(struct mptcp_sock *msk, unsigned long fail_tout)
+{
+       struct sock *sk = (struct sock *)msk;
+       unsigned long timeout, close_timeout;
+
+       if (!fail_tout && !sock_flag(sk, SOCK_DEAD))
+               return;
+
+       close_timeout = inet_csk(sk)->icsk_mtup.probe_timestamp - tcp_jiffies32 + jiffies + TCP_TIMEWAIT_LEN;
+
+       /* the close timeout takes precedence on the fail one, and here at least one of
+        * them is active
+        */
+       timeout = sock_flag(sk, SOCK_DEAD) ? close_timeout : fail_tout;
+
+       sk_reset_timer(sk, &sk->sk_timer, timeout);
+}
+
 static void mptcp_mp_fail_no_response(struct mptcp_sock *msk)
 {
-       struct mptcp_subflow_context *subflow;
-       struct sock *ssk;
+       struct sock *ssk = msk->first;
        bool slow;
 
-       subflow = mp_fail_response_expect_subflow(msk);
-       if (subflow) {
-               pr_debug("MP_FAIL doesn't respond, reset the subflow");
+       if (!ssk)
+               return;
 
-               ssk = mptcp_subflow_tcp_sock(subflow);
-               slow = lock_sock_fast(ssk);
-               mptcp_subflow_reset(ssk);
-               unlock_sock_fast(ssk, slow);
-       }
+       pr_debug("MP_FAIL doesn't respond, reset the subflow");
+
+       slow = lock_sock_fast(ssk);
+       mptcp_subflow_reset(ssk);
+       WRITE_ONCE(mptcp_subflow_ctx(ssk)->fail_tout, 0);
+       unlock_sock_fast(ssk, slow);
+
+       mptcp_reset_timeout(msk, 0);
 }
 
 static void mptcp_worker(struct work_struct *work)
 {
        struct mptcp_sock *msk = container_of(work, struct mptcp_sock, work);
        struct sock *sk = &msk->sk.icsk_inet.sk;
+       unsigned long fail_tout;
        int state;
 
        lock_sock(sk);
@@ -2575,7 +2593,9 @@ static void mptcp_worker(struct work_struct *work)
        if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags))
                __mptcp_retrans(sk);
 
-       mptcp_mp_fail_no_response(msk);
+       fail_tout = msk->first ? READ_ONCE(mptcp_subflow_ctx(msk->first)->fail_tout) : 0;
+       if (fail_tout && time_after(jiffies, fail_tout))
+               mptcp_mp_fail_no_response(msk);
 
 unlock:
        release_sock(sk);
@@ -2822,6 +2842,7 @@ static void __mptcp_destroy_sock(struct sock *sk)
 static void mptcp_close(struct sock *sk, long timeout)
 {
        struct mptcp_subflow_context *subflow;
+       struct mptcp_sock *msk = mptcp_sk(sk);
        bool do_cancel_work = false;
 
        lock_sock(sk);
@@ -2840,10 +2861,16 @@ static void mptcp_close(struct sock *sk, long timeout)
 cleanup:
        /* orphan all the subflows */
        inet_csk(sk)->icsk_mtup.probe_timestamp = tcp_jiffies32;
-       mptcp_for_each_subflow(mptcp_sk(sk), subflow) {
+       mptcp_for_each_subflow(msk, subflow) {
                struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
                bool slow = lock_sock_fast_nested(ssk);
 
+               /* since the close timeout takes precedence on the fail one,
+                * cancel the latter
+                */
+               if (ssk == msk->first)
+                       subflow->fail_tout = 0;
+
                sock_orphan(ssk);
                unlock_sock_fast(ssk, slow);
        }
@@ -2852,13 +2879,13 @@ cleanup:
        sock_hold(sk);
        pr_debug("msk=%p state=%d", sk, sk->sk_state);
        if (mptcp_sk(sk)->token)
-               mptcp_event(MPTCP_EVENT_CLOSED, mptcp_sk(sk), NULL, GFP_KERNEL);
+               mptcp_event(MPTCP_EVENT_CLOSED, msk, NULL, GFP_KERNEL);
 
        if (sk->sk_state == TCP_CLOSE) {
                __mptcp_destroy_sock(sk);
                do_cancel_work = true;
        } else {
-               sk_reset_timer(sk, &sk->sk_timer, jiffies + TCP_TIMEWAIT_LEN);
+               mptcp_reset_timeout(msk, 0);
        }
        release_sock(sk);
        if (do_cancel_work)
index 200f89f..480c532 100644 (file)
@@ -306,6 +306,7 @@ struct mptcp_sock {
 
        u32 setsockopt_seq;
        char            ca_name[TCP_CA_NAME_MAX];
+       struct mptcp_sock       *dl_next;
 };
 
 #define mptcp_data_lock(sk) spin_lock_bh(&(sk)->sk_lock.slock)
@@ -468,7 +469,6 @@ struct mptcp_subflow_context {
                local_id_valid : 1, /* local_id is correctly initialized */
                valid_csum_seen : 1;        /* at least one csum validated */
        enum mptcp_data_avail data_avail;
-       bool    mp_fail_response_expect;
        u32     remote_nonce;
        u64     thmac;
        u32     local_nonce;
@@ -482,6 +482,7 @@ struct mptcp_subflow_context {
        u8      stale_count;
 
        long    delegated_status;
+       unsigned long   fail_tout;
 
        );
 
@@ -606,8 +607,10 @@ void __init mptcp_subflow_init(void);
 void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how);
 void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
                     struct mptcp_subflow_context *subflow);
+void __mptcp_subflow_send_ack(struct sock *ssk);
 void mptcp_subflow_send_ack(struct sock *ssk);
 void mptcp_subflow_reset(struct sock *ssk);
+void mptcp_subflow_queue_clean(struct sock *ssk);
 void mptcp_sock_graft(struct sock *sk, struct socket *parent);
 struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk);
 
@@ -662,6 +665,7 @@ void mptcp_get_options(const struct sk_buff *skb,
 
 void mptcp_finish_connect(struct sock *sk);
 void __mptcp_set_connected(struct sock *sk);
+void mptcp_reset_timeout(struct mptcp_sock *msk, unsigned long fail_tout);
 static inline bool mptcp_is_fully_established(struct sock *sk)
 {
        return inet_sk_state_load(sk) == TCP_ESTABLISHED &&
@@ -768,6 +772,10 @@ void mptcp_pm_rm_addr_received(struct mptcp_sock *msk,
                               const struct mptcp_rm_list *rm_list);
 void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup);
 void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq);
+int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
+                                struct mptcp_addr_info *addr,
+                                struct mptcp_addr_info *rem,
+                                u8 bkup);
 bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
                              const struct mptcp_pm_addr_entry *entry);
 void mptcp_pm_free_anno_list(struct mptcp_sock *msk);
@@ -784,7 +792,9 @@ int mptcp_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
 int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
                                                   unsigned int id,
                                                   u8 *flags, int *ifindex);
-
+int mptcp_userspace_pm_set_flags(struct net *net, struct nlattr *token,
+                                struct mptcp_pm_addr_entry *loc,
+                                struct mptcp_pm_addr_entry *rem, u8 bkup);
 int mptcp_pm_announce_addr(struct mptcp_sock *msk,
                           const struct mptcp_addr_info *addr,
                           bool echo);
@@ -926,12 +936,25 @@ static inline void __mptcp_do_fallback(struct mptcp_sock *msk)
        set_bit(MPTCP_FALLBACK_DONE, &msk->flags);
 }
 
-static inline void mptcp_do_fallback(struct sock *sk)
+static inline void mptcp_do_fallback(struct sock *ssk)
 {
-       struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
-       struct mptcp_sock *msk = mptcp_sk(subflow->conn);
+       struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
+       struct sock *sk = subflow->conn;
+       struct mptcp_sock *msk;
 
+       msk = mptcp_sk(sk);
        __mptcp_do_fallback(msk);
+       if (READ_ONCE(msk->snd_data_fin_enable) && !(ssk->sk_shutdown & SEND_SHUTDOWN)) {
+               gfp_t saved_allocation = ssk->sk_allocation;
+
+               /* we are in a atomic (BH) scope, override ssk default for data
+                * fin allocation
+                */
+               ssk->sk_allocation = GFP_ATOMIC;
+               ssk->sk_shutdown |= SEND_SHUTDOWN;
+               tcp_shutdown(ssk, SEND_SHUTDOWN);
+               ssk->sk_allocation = saved_allocation;
+       }
 }
 
 #define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)", __func__, a)
index 8841e8c..63e8892 100644 (file)
@@ -843,7 +843,8 @@ enum mapping_status {
        MAPPING_INVALID,
        MAPPING_EMPTY,
        MAPPING_DATA_FIN,
-       MAPPING_DUMMY
+       MAPPING_DUMMY,
+       MAPPING_BAD_CSUM
 };
 
 static void dbg_bad_map(struct mptcp_subflow_context *subflow, u32 ssn)
@@ -958,11 +959,7 @@ static enum mapping_status validate_data_csum(struct sock *ssk, struct sk_buff *
                                 subflow->map_data_csum);
        if (unlikely(csum)) {
                MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DATACSUMERR);
-               if (subflow->mp_join || subflow->valid_csum_seen) {
-                       subflow->send_mp_fail = 1;
-                       MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPFAILTX);
-               }
-               return subflow->mp_join ? MAPPING_INVALID : MAPPING_DUMMY;
+               return MAPPING_BAD_CSUM;
        }
 
        subflow->valid_csum_seen = 1;
@@ -974,7 +971,6 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
 {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
        bool csum_reqd = READ_ONCE(msk->csum_enabled);
-       struct sock *sk = (struct sock *)msk;
        struct mptcp_ext *mpext;
        struct sk_buff *skb;
        u16 data_len;
@@ -1016,9 +1012,6 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
                pr_debug("infinite mapping received");
                MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPRX);
                subflow->map_data_len = 0;
-               if (!sock_flag(ssk, SOCK_DEAD))
-                       sk_stop_timer(sk, &sk->sk_timer);
-
                return MAPPING_INVALID;
        }
 
@@ -1165,6 +1158,33 @@ static bool subflow_can_fallback(struct mptcp_subflow_context *subflow)
                return !subflow->fully_established;
 }
 
+static void mptcp_subflow_fail(struct mptcp_sock *msk, struct sock *ssk)
+{
+       struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
+       unsigned long fail_tout;
+
+       /* greceful failure can happen only on the MPC subflow */
+       if (WARN_ON_ONCE(ssk != READ_ONCE(msk->first)))
+               return;
+
+       /* since the close timeout take precedence on the fail one,
+        * no need to start the latter when the first is already set
+        */
+       if (sock_flag((struct sock *)msk, SOCK_DEAD))
+               return;
+
+       /* we don't need extreme accuracy here, use a zero fail_tout as special
+        * value meaning no fail timeout at all;
+        */
+       fail_tout = jiffies + TCP_RTO_MAX;
+       if (!fail_tout)
+               fail_tout = 1;
+       WRITE_ONCE(subflow->fail_tout, fail_tout);
+       tcp_send_ack(ssk);
+
+       mptcp_reset_timeout(msk, subflow->fail_tout);
+}
+
 static bool subflow_check_data_avail(struct sock *ssk)
 {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
@@ -1184,10 +1204,8 @@ static bool subflow_check_data_avail(struct sock *ssk)
 
                status = get_mapping_status(ssk, msk);
                trace_subflow_check_data_avail(status, skb_peek(&ssk->sk_receive_queue));
-               if (unlikely(status == MAPPING_INVALID))
-                       goto fallback;
-
-               if (unlikely(status == MAPPING_DUMMY))
+               if (unlikely(status == MAPPING_INVALID || status == MAPPING_DUMMY ||
+                            status == MAPPING_BAD_CSUM))
                        goto fallback;
 
                if (status != MAPPING_OK)
@@ -1229,22 +1247,17 @@ no_data:
 fallback:
        if (!__mptcp_check_fallback(msk)) {
                /* RFC 8684 section 3.7. */
-               if (subflow->send_mp_fail) {
+               if (status == MAPPING_BAD_CSUM &&
+                   (subflow->mp_join || subflow->valid_csum_seen)) {
+                       subflow->send_mp_fail = 1;
+
                        if (!READ_ONCE(msk->allow_infinite_fallback)) {
-                               ssk->sk_err = EBADMSG;
-                               tcp_set_state(ssk, TCP_CLOSE);
                                subflow->reset_transient = 0;
                                subflow->reset_reason = MPTCP_RST_EMIDDLEBOX;
-                               tcp_send_active_reset(ssk, GFP_ATOMIC);
-                               while ((skb = skb_peek(&ssk->sk_receive_queue)))
-                                       sk_eat_skb(ssk, skb);
-                       } else if (!sock_flag(ssk, SOCK_DEAD)) {
-                               WRITE_ONCE(subflow->mp_fail_response_expect, true);
-                               sk_reset_timer((struct sock *)msk,
-                                              &((struct sock *)msk)->sk_timer,
-                                              jiffies + TCP_RTO_MAX);
+                               goto reset;
                        }
-                       WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
+                       mptcp_subflow_fail(msk, ssk);
+                       WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_DATA_AVAIL);
                        return true;
                }
 
@@ -1252,16 +1265,20 @@ fallback:
                        /* fatal protocol error, close the socket.
                         * subflow_error_report() will introduce the appropriate barriers
                         */
-                       ssk->sk_err = EBADMSG;
-                       tcp_set_state(ssk, TCP_CLOSE);
                        subflow->reset_transient = 0;
                        subflow->reset_reason = MPTCP_RST_EMPTCP;
+
+reset:
+                       ssk->sk_err = EBADMSG;
+                       tcp_set_state(ssk, TCP_CLOSE);
+                       while ((skb = skb_peek(&ssk->sk_receive_queue)))
+                               sk_eat_skb(ssk, skb);
                        tcp_send_active_reset(ssk, GFP_ATOMIC);
                        WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
                        return false;
                }
 
-               __mptcp_do_fallback(msk);
+               mptcp_do_fallback(ssk);
        }
 
        skb = skb_peek(&ssk->sk_receive_queue);
@@ -1706,6 +1723,58 @@ static void subflow_state_change(struct sock *sk)
        }
 }
 
+void mptcp_subflow_queue_clean(struct sock *listener_ssk)
+{
+       struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue;
+       struct mptcp_sock *msk, *next, *head = NULL;
+       struct request_sock *req;
+
+       /* build a list of all unaccepted mptcp sockets */
+       spin_lock_bh(&queue->rskq_lock);
+       for (req = queue->rskq_accept_head; req; req = req->dl_next) {
+               struct mptcp_subflow_context *subflow;
+               struct sock *ssk = req->sk;
+               struct mptcp_sock *msk;
+
+               if (!sk_is_mptcp(ssk))
+                       continue;
+
+               subflow = mptcp_subflow_ctx(ssk);
+               if (!subflow || !subflow->conn)
+                       continue;
+
+               /* skip if already in list */
+               msk = mptcp_sk(subflow->conn);
+               if (msk->dl_next || msk == head)
+                       continue;
+
+               msk->dl_next = head;
+               head = msk;
+       }
+       spin_unlock_bh(&queue->rskq_lock);
+       if (!head)
+               return;
+
+       /* can't acquire the msk socket lock under the subflow one,
+        * or will cause ABBA deadlock
+        */
+       release_sock(listener_ssk);
+
+       for (msk = head; msk; msk = next) {
+               struct sock *sk = (struct sock *)msk;
+               bool slow;
+
+               slow = lock_sock_fast_nested(sk);
+               next = msk->dl_next;
+               msk->first = NULL;
+               msk->dl_next = NULL;
+               unlock_sock_fast(sk, slow);
+       }
+
+       /* we are still under the listener msk socket lock */
+       lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING);
+}
+
 static int subflow_ulp_init(struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
index 7881441..80713fe 100644 (file)
@@ -1803,7 +1803,8 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
        pdev = to_platform_device(dev->dev.parent);
        if (pdev) {
                np = pdev->dev.of_node;
-               if (np && of_get_property(np, "mlx,multi-host", NULL))
+               if (np && (of_get_property(np, "mellanox,multi-host", NULL) ||
+                          of_get_property(np, "mlx,multi-host", NULL)))
                        ndp->mlx_multi_host = true;
        }
 
index 51144fc..d6b59be 100644 (file)
@@ -5213,13 +5213,20 @@ static int nft_setelem_parse_data(struct nft_ctx *ctx, struct nft_set *set,
                                  struct nft_data *data,
                                  struct nlattr *attr)
 {
+       u32 dtype;
        int err;
 
        err = nft_data_init(ctx, data, NFT_DATA_VALUE_MAXLEN, desc, attr);
        if (err < 0)
                return err;
 
-       if (desc->type != NFT_DATA_VERDICT && desc->len != set->dlen) {
+       if (set->dtype == NFT_DATA_VERDICT)
+               dtype = NFT_DATA_VERDICT;
+       else
+               dtype = NFT_DATA_VALUE;
+
+       if (dtype != desc->type ||
+           set->dlen != desc->len) {
                nft_data_release(data, desc->type);
                return -EINVAL;
        }
index 53f40e4..3ddce24 100644 (file)
@@ -25,9 +25,7 @@ static noinline void __nft_trace_packet(struct nft_traceinfo *info,
                                        const struct nft_chain *chain,
                                        enum nft_trace_types type)
 {
-       const struct nft_pktinfo *pkt = info->pkt;
-
-       if (!info->trace || !pkt->skb->nf_trace)
+       if (!info->trace || !info->nf_trace)
                return;
 
        info->chain = chain;
@@ -42,11 +40,24 @@ static inline void nft_trace_packet(struct nft_traceinfo *info,
                                    enum nft_trace_types type)
 {
        if (static_branch_unlikely(&nft_trace_enabled)) {
+               const struct nft_pktinfo *pkt = info->pkt;
+
+               info->nf_trace = pkt->skb->nf_trace;
                info->rule = rule;
                __nft_trace_packet(info, chain, type);
        }
 }
 
+static inline void nft_trace_copy_nftrace(struct nft_traceinfo *info)
+{
+       if (static_branch_unlikely(&nft_trace_enabled)) {
+               const struct nft_pktinfo *pkt = info->pkt;
+
+               if (info->trace)
+                       info->nf_trace = pkt->skb->nf_trace;
+       }
+}
+
 static void nft_bitwise_fast_eval(const struct nft_expr *expr,
                                  struct nft_regs *regs)
 {
@@ -85,6 +96,7 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info,
                                         const struct nft_chain *chain,
                                         const struct nft_regs *regs)
 {
+       const struct nft_pktinfo *pkt = info->pkt;
        enum nft_trace_types type;
 
        switch (regs->verdict.code) {
@@ -92,8 +104,13 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info,
        case NFT_RETURN:
                type = NFT_TRACETYPE_RETURN;
                break;
+       case NF_STOLEN:
+               type = NFT_TRACETYPE_RULE;
+               /* can't access skb->nf_trace; use copy */
+               break;
        default:
                type = NFT_TRACETYPE_RULE;
+               info->nf_trace = pkt->skb->nf_trace;
                break;
        }
 
@@ -254,6 +271,7 @@ next_rule:
                switch (regs.verdict.code) {
                case NFT_BREAK:
                        regs.verdict.code = NFT_CONTINUE;
+                       nft_trace_copy_nftrace(&info);
                        continue;
                case NFT_CONTINUE:
                        nft_trace_packet(&info, chain, rule,
index 5041725..1163ba9 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/module.h>
 #include <linux/static_key.h>
 #include <linux/hash.h>
-#include <linux/jhash.h>
+#include <linux/siphash.h>
 #include <linux/if_vlan.h>
 #include <linux/init.h>
 #include <linux/skbuff.h>
 DEFINE_STATIC_KEY_FALSE(nft_trace_enabled);
 EXPORT_SYMBOL_GPL(nft_trace_enabled);
 
-static int trace_fill_id(struct sk_buff *nlskb, struct sk_buff *skb)
-{
-       __be32 id;
-
-       /* using skb address as ID results in a limited number of
-        * values (and quick reuse).
-        *
-        * So we attempt to use as many skb members that will not
-        * change while skb is with netfilter.
-        */
-       id = (__be32)jhash_2words(hash32_ptr(skb), skb_get_hash(skb),
-                                 skb->skb_iif);
-
-       return nla_put_be32(nlskb, NFTA_TRACE_ID, id);
-}
-
 static int trace_fill_header(struct sk_buff *nlskb, u16 type,
                             const struct sk_buff *skb,
                             int off, unsigned int len)
@@ -186,6 +170,7 @@ void nft_trace_notify(struct nft_traceinfo *info)
        struct nlmsghdr *nlh;
        struct sk_buff *skb;
        unsigned int size;
+       u32 mark = 0;
        u16 event;
 
        if (!nfnetlink_has_listeners(nft_net(pkt), NFNLGRP_NFTRACE))
@@ -229,7 +214,7 @@ void nft_trace_notify(struct nft_traceinfo *info)
        if (nla_put_be32(skb, NFTA_TRACE_TYPE, htonl(info->type)))
                goto nla_put_failure;
 
-       if (trace_fill_id(skb, pkt->skb))
+       if (nla_put_u32(skb, NFTA_TRACE_ID, info->skbid))
                goto nla_put_failure;
 
        if (nla_put_string(skb, NFTA_TRACE_CHAIN, info->chain->name))
@@ -249,16 +234,24 @@ void nft_trace_notify(struct nft_traceinfo *info)
        case NFT_TRACETYPE_RULE:
                if (nft_verdict_dump(skb, NFTA_TRACE_VERDICT, info->verdict))
                        goto nla_put_failure;
+
+               /* pkt->skb undefined iff NF_STOLEN, disable dump */
+               if (info->verdict->code == NF_STOLEN)
+                       info->packet_dumped = true;
+               else
+                       mark = pkt->skb->mark;
+
                break;
        case NFT_TRACETYPE_POLICY:
+               mark = pkt->skb->mark;
+
                if (nla_put_be32(skb, NFTA_TRACE_POLICY,
                                 htonl(info->basechain->policy)))
                        goto nla_put_failure;
                break;
        }
 
-       if (pkt->skb->mark &&
-           nla_put_be32(skb, NFTA_TRACE_MARK, htonl(pkt->skb->mark)))
+       if (mark && nla_put_be32(skb, NFTA_TRACE_MARK, htonl(mark)))
                goto nla_put_failure;
 
        if (!info->packet_dumped) {
@@ -283,9 +276,20 @@ void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt,
                    const struct nft_verdict *verdict,
                    const struct nft_chain *chain)
 {
+       static siphash_key_t trace_key __read_mostly;
+       struct sk_buff *skb = pkt->skb;
+
        info->basechain = nft_base_chain(chain);
        info->trace = true;
+       info->nf_trace = pkt->skb->nf_trace;
        info->packet_dumped = false;
        info->pkt = pkt;
        info->verdict = verdict;
+
+       net_get_random_once(&trace_key, sizeof(trace_key));
+
+       info->skbid = (u32)siphash_3u32(hash32_ptr(skb),
+                                       skb_get_hash(skb),
+                                       skb->skb_iif,
+                                       &trace_key);
 }
index df40314..76de6c8 100644 (file)
@@ -143,6 +143,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key,
        /* Another cpu may race to insert the element with the same key */
        if (prev) {
                nft_set_elem_destroy(set, he, true);
+               atomic_dec(&set->nelems);
                he = prev;
        }
 
@@ -152,6 +153,7 @@ out:
 
 err2:
        nft_set_elem_destroy(set, he, true);
+       atomic_dec(&set->nelems);
 err1:
        return false;
 }
index 2c8051d..4f9299b 100644 (file)
@@ -2124,6 +2124,32 @@ out_scratch:
        return err;
 }
 
+/**
+ * nft_set_pipapo_match_destroy() - Destroy elements from key mapping array
+ * @set:       nftables API set representation
+ * @m:         matching data pointing to key mapping array
+ */
+static void nft_set_pipapo_match_destroy(const struct nft_set *set,
+                                        struct nft_pipapo_match *m)
+{
+       struct nft_pipapo_field *f;
+       int i, r;
+
+       for (i = 0, f = m->f; i < m->field_count - 1; i++, f++)
+               ;
+
+       for (r = 0; r < f->rules; r++) {
+               struct nft_pipapo_elem *e;
+
+               if (r < f->rules - 1 && f->mt[r + 1].e == f->mt[r].e)
+                       continue;
+
+               e = f->mt[r].e;
+
+               nft_set_elem_destroy(set, e, true);
+       }
+}
+
 /**
  * nft_pipapo_destroy() - Free private data for set and all committed elements
  * @set:       nftables API set representation
@@ -2132,26 +2158,13 @@ static void nft_pipapo_destroy(const struct nft_set *set)
 {
        struct nft_pipapo *priv = nft_set_priv(set);
        struct nft_pipapo_match *m;
-       struct nft_pipapo_field *f;
-       int i, r, cpu;
+       int cpu;
 
        m = rcu_dereference_protected(priv->match, true);
        if (m) {
                rcu_barrier();
 
-               for (i = 0, f = m->f; i < m->field_count - 1; i++, f++)
-                       ;
-
-               for (r = 0; r < f->rules; r++) {
-                       struct nft_pipapo_elem *e;
-
-                       if (r < f->rules - 1 && f->mt[r + 1].e == f->mt[r].e)
-                               continue;
-
-                       e = f->mt[r].e;
-
-                       nft_set_elem_destroy(set, e, true);
-               }
+               nft_set_pipapo_match_destroy(set, m);
 
 #ifdef NFT_PIPAPO_ALIGN
                free_percpu(m->scratch_aligned);
@@ -2165,6 +2178,11 @@ static void nft_pipapo_destroy(const struct nft_set *set)
        }
 
        if (priv->clone) {
+               m = priv->clone;
+
+               if (priv->dirty)
+                       nft_set_pipapo_match_destroy(set, m);
+
 #ifdef NFT_PIPAPO_ALIGN
                free_percpu(priv->clone->scratch_aligned);
 #endif
index fee6409..eb0b819 100644 (file)
@@ -227,8 +227,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
 {
        struct rose_neigh *s;
 
-       rose_stop_ftimer(rose_neigh);
-       rose_stop_t0timer(rose_neigh);
+       del_timer_sync(&rose_neigh->ftimer);
+       del_timer_sync(&rose_neigh->t0timer);
 
        skb_queue_purge(&rose_neigh->queue);
 
index b3138fc..f06ddbe 100644 (file)
@@ -31,89 +31,89 @@ static void rose_idletimer_expiry(struct timer_list *);
 
 void rose_start_heartbeat(struct sock *sk)
 {
-       del_timer(&sk->sk_timer);
+       sk_stop_timer(sk, &sk->sk_timer);
 
        sk->sk_timer.function = rose_heartbeat_expiry;
        sk->sk_timer.expires  = jiffies + 5 * HZ;
 
-       add_timer(&sk->sk_timer);
+       sk_reset_timer(sk, &sk->sk_timer, sk->sk_timer.expires);
 }
 
 void rose_start_t1timer(struct sock *sk)
 {
        struct rose_sock *rose = rose_sk(sk);
 
-       del_timer(&rose->timer);
+       sk_stop_timer(sk, &rose->timer);
 
        rose->timer.function = rose_timer_expiry;
        rose->timer.expires  = jiffies + rose->t1;
 
-       add_timer(&rose->timer);
+       sk_reset_timer(sk, &rose->timer, rose->timer.expires);
 }
 
 void rose_start_t2timer(struct sock *sk)
 {
        struct rose_sock *rose = rose_sk(sk);
 
-       del_timer(&rose->timer);
+       sk_stop_timer(sk, &rose->timer);
 
        rose->timer.function = rose_timer_expiry;
        rose->timer.expires  = jiffies + rose->t2;
 
-       add_timer(&rose->timer);
+       sk_reset_timer(sk, &rose->timer, rose->timer.expires);
 }
 
 void rose_start_t3timer(struct sock *sk)
 {
        struct rose_sock *rose = rose_sk(sk);
 
-       del_timer(&rose->timer);
+       sk_stop_timer(sk, &rose->timer);
 
        rose->timer.function = rose_timer_expiry;
        rose->timer.expires  = jiffies + rose->t3;
 
-       add_timer(&rose->timer);
+       sk_reset_timer(sk, &rose->timer, rose->timer.expires);
 }
 
 void rose_start_hbtimer(struct sock *sk)
 {
        struct rose_sock *rose = rose_sk(sk);
 
-       del_timer(&rose->timer);
+       sk_stop_timer(sk, &rose->timer);
 
        rose->timer.function = rose_timer_expiry;
        rose->timer.expires  = jiffies + rose->hb;
 
-       add_timer(&rose->timer);
+       sk_reset_timer(sk, &rose->timer, rose->timer.expires);
 }
 
 void rose_start_idletimer(struct sock *sk)
 {
        struct rose_sock *rose = rose_sk(sk);
 
-       del_timer(&rose->idletimer);
+       sk_stop_timer(sk, &rose->idletimer);
 
        if (rose->idle > 0) {
                rose->idletimer.function = rose_idletimer_expiry;
                rose->idletimer.expires  = jiffies + rose->idle;
 
-               add_timer(&rose->idletimer);
+               sk_reset_timer(sk, &rose->idletimer, rose->idletimer.expires);
        }
 }
 
 void rose_stop_heartbeat(struct sock *sk)
 {
-       del_timer(&sk->sk_timer);
+       sk_stop_timer(sk, &sk->sk_timer);
 }
 
 void rose_stop_timer(struct sock *sk)
 {
-       del_timer(&rose_sk(sk)->timer);
+       sk_stop_timer(sk, &rose_sk(sk)->timer);
 }
 
 void rose_stop_idletimer(struct sock *sk)
 {
-       del_timer(&rose_sk(sk)->idletimer);
+       sk_stop_timer(sk, &rose_sk(sk)->idletimer);
 }
 
 static void rose_heartbeat_expiry(struct timer_list *t)
@@ -130,6 +130,7 @@ static void rose_heartbeat_expiry(struct timer_list *t)
                    (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
                        bh_unlock_sock(sk);
                        rose_destroy_socket(sk);
+                       sock_put(sk);
                        return;
                }
                break;
@@ -152,6 +153,7 @@ static void rose_heartbeat_expiry(struct timer_list *t)
 
        rose_start_heartbeat(sk);
        bh_unlock_sock(sk);
+       sock_put(sk);
 }
 
 static void rose_timer_expiry(struct timer_list *t)
@@ -181,6 +183,7 @@ static void rose_timer_expiry(struct timer_list *t)
                break;
        }
        bh_unlock_sock(sk);
+       sock_put(sk);
 }
 
 static void rose_idletimer_expiry(struct timer_list *t)
@@ -205,4 +208,5 @@ static void rose_idletimer_expiry(struct timer_list *t)
                sock_set_flag(sk, SOCK_DEAD);
        }
        bh_unlock_sock(sk);
+       sock_put(sk);
 }
index da9733d..817065a 100644 (file)
@@ -588,7 +588,8 @@ static int tcf_idr_release_unsafe(struct tc_action *p)
 }
 
 static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
-                         const struct tc_action_ops *ops)
+                         const struct tc_action_ops *ops,
+                         struct netlink_ext_ack *extack)
 {
        struct nlattr *nest;
        int n_i = 0;
@@ -604,20 +605,25 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
        if (nla_put_string(skb, TCA_KIND, ops->kind))
                goto nla_put_failure;
 
+       ret = 0;
        mutex_lock(&idrinfo->lock);
        idr_for_each_entry_ul(idr, p, tmp, id) {
                if (IS_ERR(p))
                        continue;
                ret = tcf_idr_release_unsafe(p);
-               if (ret == ACT_P_DELETED) {
+               if (ret == ACT_P_DELETED)
                        module_put(ops->owner);
-                       n_i++;
-               } else if (ret < 0) {
-                       mutex_unlock(&idrinfo->lock);
-                       goto nla_put_failure;
-               }
+               else if (ret < 0)
+                       break;
+               n_i++;
        }
        mutex_unlock(&idrinfo->lock);
+       if (ret < 0) {
+               if (n_i)
+                       NL_SET_ERR_MSG(extack, "Unable to flush all TC actions");
+               else
+                       goto nla_put_failure;
+       }
 
        ret = nla_put_u32(skb, TCA_FCNT, n_i);
        if (ret)
@@ -638,7 +644,7 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
        struct tcf_idrinfo *idrinfo = tn->idrinfo;
 
        if (type == RTM_DELACTION) {
-               return tcf_del_walker(idrinfo, skb, ops);
+               return tcf_del_walker(idrinfo, skb, ops, extack);
        } else if (type == RTM_GETACTION) {
                return tcf_dump_walker(idrinfo, skb, cb);
        } else {
index 79c8901..b759628 100644 (file)
@@ -442,7 +442,7 @@ static int tcf_police_act_to_flow_act(int tc_act, u32 *extval,
                act_id = FLOW_ACTION_JUMP;
                *extval = tc_act & TC_ACT_EXT_VAL_MASK;
        } else if (tc_act == TC_ACT_UNSPEC) {
-               NL_SET_ERR_MSG_MOD(extack, "Offload not supported when conform/exceed action is \"continue\"");
+               act_id = FLOW_ACTION_CONTINUE;
        } else {
                NL_SET_ERR_MSG_MOD(extack, "Unsupported conform/exceed action offload");
        }
index 2bc8773..96300cd 100644 (file)
@@ -2149,10 +2149,13 @@ SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
 int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
                   struct sockaddr __user *addr, int __user *addr_len)
 {
+       struct sockaddr_storage address;
+       struct msghdr msg = {
+               /* Save some cycles and don't copy the address if not needed */
+               .msg_name = addr ? (struct sockaddr *)&address : NULL,
+       };
        struct socket *sock;
        struct iovec iov;
-       struct msghdr msg;
-       struct sockaddr_storage address;
        int err, err2;
        int fput_needed;
 
@@ -2163,14 +2166,6 @@ int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
        if (!sock)
                goto out;
 
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       /* Save some cycles and don't copy the address if not needed */
-       msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
-       /* We assume all kernel code knows the size of sockaddr_storage */
-       msg.msg_namelen = 0;
-       msg.msg_iocb = NULL;
-       msg.msg_flags = 0;
        if (sock->file->f_flags & O_NONBLOCK)
                flags |= MSG_DONTWAIT;
        err = sock_recvmsg(sock, &msg, flags);
@@ -2375,6 +2370,7 @@ int __copy_msghdr_from_user(struct msghdr *kmsg,
                return -EFAULT;
 
        kmsg->msg_control_is_user = true;
+       kmsg->msg_get_inq = 0;
        kmsg->msg_control_user = msg.msg_control;
        kmsg->msg_controllen = msg.msg_controllen;
        kmsg->msg_flags = msg.msg_flags;
index f87a2d8..5d2b3e6 100644 (file)
@@ -984,7 +984,7 @@ static noinline __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr,
        p = page_address(*xdr->page_ptr);
        xdr->p = p + frag2bytes;
        space_left = xdr->buf->buflen - xdr->buf->len;
-       if (space_left - nbytes >= PAGE_SIZE)
+       if (space_left - frag1bytes >= PAGE_SIZE)
                xdr->end = p + PAGE_SIZE;
        else
                xdr->end = p + space_left - frag1bytes;
index 6ef95ce..b48d97c 100644 (file)
@@ -472,8 +472,8 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
                                   bool preliminary)
 {
        struct tipc_net *tn = net_generic(net, tipc_net_id);
+       struct tipc_link *l, *snd_l = tipc_bc_sndlink(net);
        struct tipc_node *n, *temp_node;
-       struct tipc_link *l;
        unsigned long intv;
        int bearer_id;
        int i;
@@ -488,6 +488,16 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
                        goto exit;
                /* A preliminary node becomes "real" now, refresh its data */
                tipc_node_write_lock(n);
+               if (!tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX,
+                                        tipc_link_min_win(snd_l), tipc_link_max_win(snd_l),
+                                        n->capabilities, &n->bc_entry.inputq1,
+                                        &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) {
+                       pr_warn("Broadcast rcv link refresh failed, no memory\n");
+                       tipc_node_write_unlock_fast(n);
+                       tipc_node_put(n);
+                       n = NULL;
+                       goto exit;
+               }
                n->preliminary = false;
                n->addr = addr;
                hlist_del_rcu(&n->hash);
@@ -567,7 +577,16 @@ update:
        n->signature = INVALID_NODE_SIG;
        n->active_links[0] = INVALID_BEARER_ID;
        n->active_links[1] = INVALID_BEARER_ID;
-       n->bc_entry.link = NULL;
+       if (!preliminary &&
+           !tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX,
+                                tipc_link_min_win(snd_l), tipc_link_max_win(snd_l),
+                                n->capabilities, &n->bc_entry.inputq1,
+                                &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) {
+               pr_warn("Broadcast rcv link creation failed, no memory\n");
+               kfree(n);
+               n = NULL;
+               goto exit;
+       }
        tipc_node_get(n);
        timer_setup(&n->timer, tipc_node_timeout, 0);
        /* Start a slow timer anyway, crypto needs it */
@@ -1155,7 +1174,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
                          bool *respond, bool *dupl_addr)
 {
        struct tipc_node *n;
-       struct tipc_link *l, *snd_l;
+       struct tipc_link *l;
        struct tipc_link_entry *le;
        bool addr_match = false;
        bool sign_match = false;
@@ -1175,22 +1194,6 @@ void tipc_node_check_dest(struct net *net, u32 addr,
                return;
 
        tipc_node_write_lock(n);
-       if (unlikely(!n->bc_entry.link)) {
-               snd_l = tipc_bc_sndlink(net);
-               if (!tipc_link_bc_create(net, tipc_own_addr(net),
-                                        addr, peer_id, U16_MAX,
-                                        tipc_link_min_win(snd_l),
-                                        tipc_link_max_win(snd_l),
-                                        n->capabilities,
-                                        &n->bc_entry.inputq1,
-                                        &n->bc_entry.namedq, snd_l,
-                                        &n->bc_entry.link)) {
-                       pr_warn("Broadcast rcv link creation failed, no mem\n");
-                       tipc_node_write_unlock_fast(n);
-                       tipc_node_put(n);
-                       return;
-               }
-       }
 
        le = &n->links[b->identity];
 
index 17f8c52..43509c7 100644 (file)
@@ -502,6 +502,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
        sock_init_data(sock, sk);
        tipc_set_sk_state(sk, TIPC_OPEN);
        if (tipc_sk_insert(tsk)) {
+               sk_free(sk);
                pr_warn("Socket create failed; port number exhausted\n");
                return -EINVAL;
        }
index 0513f82..e30649f 100644 (file)
@@ -267,9 +267,6 @@ static int tls_do_decryption(struct sock *sk,
        }
        darg->async = false;
 
-       if (ret == -EBADMSG)
-               TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSDECRYPTERROR);
-
        return ret;
 }
 
@@ -1579,8 +1576,11 @@ static int decrypt_skb_update(struct sock *sk, struct sk_buff *skb,
        }
 
        err = decrypt_internal(sk, skb, dest, NULL, darg);
-       if (err < 0)
+       if (err < 0) {
+               if (err == -EBADMSG)
+                       TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSDECRYPTERROR);
                return err;
+       }
        if (darg->async)
                goto decrypt_next;
 
index 87bdd71..f701121 100644 (file)
@@ -332,6 +332,7 @@ static void __xp_dma_unmap(struct xsk_dma_map *dma_map, unsigned long attrs)
        for (i = 0; i < dma_map->dma_pages_cnt; i++) {
                dma = &dma_map->dma_pages[i];
                if (*dma) {
+                       *dma &= ~XSK_NEXT_PG_CONTIG_MASK;
                        dma_unmap_page_attrs(dma_map->dev, *dma, PAGE_SIZE,
                                             DMA_BIDIRECTIONAL, attrs);
                        *dma = 0;
index 01ee6c8..18b1e5c 100644 (file)
@@ -25,12 +25,19 @@ static unsigned long nhit;
 
 static char symbol[MAX_SYMBOL_LEN] = "kernel_clone";
 module_param_string(symbol, symbol, sizeof(symbol), 0644);
+MODULE_PARM_DESC(symbol, "Probed symbol(s), given by comma separated symbols or a wildcard pattern.");
+
 static char nosymbol[MAX_SYMBOL_LEN] = "";
 module_param_string(nosymbol, nosymbol, sizeof(nosymbol), 0644);
+MODULE_PARM_DESC(nosymbol, "Not-probed symbols, given by a wildcard pattern.");
+
 static bool stackdump = true;
 module_param(stackdump, bool, 0644);
+MODULE_PARM_DESC(stackdump, "Enable stackdump.");
+
 static bool use_trace = false;
 module_param(use_trace, bool, 0644);
+MODULE_PARM_DESC(use_trace, "Use trace_printk instead of printk. This is only for debugging.");
 
 static void show_backtrace(void)
 {
index c2c43a0..16a02e9 100644 (file)
@@ -28,9 +28,6 @@ modules := $(patsubst $(extmod_prefix)%, $(dst)/%$(suffix-y), $(modules))
 __modinst: $(modules)
        @:
 
-quiet_cmd_none =
-      cmd_none = :
-
 #
 # Installation
 #
index 1d1bde1..47da25b 100755 (executable)
@@ -157,10 +157,10 @@ def cmdfiles_for_modorder(modorder):
             if ext != '.ko':
                 sys.exit('{}: module path must end with .ko'.format(ko))
             mod = base + '.mod'
-           # The first line of *.mod lists the objects that compose the module.
+            # Read from *.mod, to get a list of objects that compose the module.
             with open(mod) as m:
-                for obj in m.readline().split():
-                    yield to_cmdfile(obj)
+                for mod_line in m:
+                    yield to_cmdfile(mod_line.rstrip())
 
 
 def process_line(root_directory, command_prefix, file_path):
index bd60308..8634004 100644 (file)
@@ -74,36 +74,36 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci,
        err = snd_cs46xx_create(card, pci,
                                external_amp[dev], thinkpad[dev]);
        if (err < 0)
-               return err;
+               goto error;
        card->private_data = chip;
        chip->accept_valid = mmap_valid[dev];
        err = snd_cs46xx_pcm(chip, 0);
        if (err < 0)
-               return err;
+               goto error;
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        err = snd_cs46xx_pcm_rear(chip, 1);
        if (err < 0)
-               return err;
+               goto error;
        err = snd_cs46xx_pcm_iec958(chip, 2);
        if (err < 0)
-               return err;
+               goto error;
 #endif
        err = snd_cs46xx_mixer(chip, 2);
        if (err < 0)
-               return err;
+               goto error;
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        if (chip->nr_ac97_codecs ==2) {
                err = snd_cs46xx_pcm_center_lfe(chip, 3);
                if (err < 0)
-                       return err;
+                       goto error;
        }
 #endif
        err = snd_cs46xx_midi(chip, 0);
        if (err < 0)
-               return err;
+               goto error;
        err = snd_cs46xx_start_dsp(chip);
        if (err < 0)
-               return err;
+               goto error;
 
        snd_cs46xx_gameport(chip);
 
@@ -117,11 +117,15 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci,
 
        err = snd_card_register(card);
        if (err < 0)
-               return err;
+               goto error;
 
        pci_set_drvdata(pci, card);
        dev++;
        return 0;
+
+ error:
+       snd_card_free(card);
+       return err;
 }
 
 static struct pci_driver cs46xx_driver = {
index cee69fa..007dd8b 100644 (file)
@@ -9212,6 +9212,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x70f4, "Clevo NH77EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70f6, "Clevo NH77DPQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x7716, "Clevo NS50PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x7718, "Clevo L140PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
index 55e773f..93606e5 100644 (file)
@@ -868,10 +868,12 @@ static void ak4613_parse_of(struct ak4613_priv *priv,
 
        /*
         * connected STDI
+        * TDM support is assuming it is probed via Audio-Graph-Card style here.
+        * Default is SDTIx1 if it was probed via Simple-Audio-Card for now.
         */
        sdti_num = of_graph_get_endpoint_count(np);
-       if (WARN_ON((sdti_num > 3) || (sdti_num < 1)))
-               return;
+       if ((sdti_num >= SDTx_MAX) || (sdti_num < 1))
+               sdti_num = 1;
 
        AK4613_CONFIG_SDTI_set(priv, sdti_num);
 }
index 6d3070e..198cfe5 100644 (file)
@@ -37,8 +37,8 @@ static const struct reg_default cs35l41_reg[] = {
        { CS35L41_DAC_PCM1_SRC,                 0x00000008 },
        { CS35L41_ASP_TX1_SRC,                  0x00000018 },
        { CS35L41_ASP_TX2_SRC,                  0x00000019 },
-       { CS35L41_ASP_TX3_SRC,                  0x00000020 },
-       { CS35L41_ASP_TX4_SRC,                  0x00000021 },
+       { CS35L41_ASP_TX3_SRC,                  0x00000000 },
+       { CS35L41_ASP_TX4_SRC,                  0x00000000 },
        { CS35L41_DSP1_RX1_SRC,                 0x00000008 },
        { CS35L41_DSP1_RX2_SRC,                 0x00000009 },
        { CS35L41_DSP1_RX3_SRC,                 0x00000018 },
@@ -644,6 +644,8 @@ static const struct reg_sequence cs35l41_reva0_errata_patch[] = {
        { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
        { CS35L41_PWR_CTRL2,             0x00000000 },
        { CS35L41_AMP_GAIN_CTRL,         0x00000000 },
+       { CS35L41_ASP_TX3_SRC,           0x00000000 },
+       { CS35L41_ASP_TX4_SRC,           0x00000000 },
 };
 
 static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
@@ -655,6 +657,8 @@ static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
        { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
        { CS35L41_PWR_CTRL2,             0x00000000 },
        { CS35L41_AMP_GAIN_CTRL,         0x00000000 },
+       { CS35L41_ASP_TX3_SRC,           0x00000000 },
+       { CS35L41_ASP_TX4_SRC,           0x00000000 },
 };
 
 static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
@@ -666,6 +670,8 @@ static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
        { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
        { CS35L41_PWR_CTRL2,             0x00000000 },
        { CS35L41_AMP_GAIN_CTRL,         0x00000000 },
+       { CS35L41_ASP_TX3_SRC,           0x00000000 },
+       { CS35L41_ASP_TX4_SRC,           0x00000000 },
 };
 
 static const struct reg_sequence cs35l41_fs_errata_patch[] = {
index 3e68a07..71ab2a5 100644 (file)
@@ -333,7 +333,7 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = {
        SOC_SINGLE("HW Noise Gate Enable", CS35L41_NG_CFG, 8, 63, 0),
        SOC_SINGLE("HW Noise Gate Delay", CS35L41_NG_CFG, 4, 7, 0),
        SOC_SINGLE("HW Noise Gate Threshold", CS35L41_NG_CFG, 0, 7, 0),
-       SOC_SINGLE("Aux Noise Gate CH1 Enable",
+       SOC_SINGLE("Aux Noise Gate CH1 Switch",
                   CS35L41_MIXER_NGATE_CH1_CFG, 16, 1, 0),
        SOC_SINGLE("Aux Noise Gate CH1 Entry Delay",
                   CS35L41_MIXER_NGATE_CH1_CFG, 8, 15, 0),
@@ -341,15 +341,15 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = {
                   CS35L41_MIXER_NGATE_CH1_CFG, 0, 7, 0),
        SOC_SINGLE("Aux Noise Gate CH2 Entry Delay",
                   CS35L41_MIXER_NGATE_CH2_CFG, 8, 15, 0),
-       SOC_SINGLE("Aux Noise Gate CH2 Enable",
+       SOC_SINGLE("Aux Noise Gate CH2 Switch",
                   CS35L41_MIXER_NGATE_CH2_CFG, 16, 1, 0),
        SOC_SINGLE("Aux Noise Gate CH2 Threshold",
                   CS35L41_MIXER_NGATE_CH2_CFG, 0, 7, 0),
-       SOC_SINGLE("SCLK Force", CS35L41_SP_FORMAT, CS35L41_SCLK_FRC_SHIFT, 1, 0),
-       SOC_SINGLE("LRCLK Force", CS35L41_SP_FORMAT, CS35L41_LRCLK_FRC_SHIFT, 1, 0),
-       SOC_SINGLE("Invert Class D", CS35L41_AMP_DIG_VOL_CTRL,
+       SOC_SINGLE("SCLK Force Switch", CS35L41_SP_FORMAT, CS35L41_SCLK_FRC_SHIFT, 1, 0),
+       SOC_SINGLE("LRCLK Force Switch", CS35L41_SP_FORMAT, CS35L41_LRCLK_FRC_SHIFT, 1, 0),
+       SOC_SINGLE("Invert Class D Switch", CS35L41_AMP_DIG_VOL_CTRL,
                   CS35L41_AMP_INV_PCM_SHIFT, 1, 0),
-       SOC_SINGLE("Amp Gain ZC", CS35L41_AMP_GAIN_CTRL,
+       SOC_SINGLE("Amp Gain ZC Switch", CS35L41_AMP_GAIN_CTRL,
                   CS35L41_AMP_GAIN_ZC_SHIFT, 1, 0),
        WM_ADSP2_PRELOAD_SWITCH("DSP1", 1),
        WM_ADSP_FW_CONTROL("DSP1", 0),
index 391fd7d..1c7d52b 100644 (file)
@@ -122,6 +122,9 @@ static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol,
                snd_soc_kcontrol_component(kcontrol);
        struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component);
 
+       if (!!ucontrol->value.integer.value[0] == cs47l15->in1_lp_mode)
+               return 0;
+
        switch (ucontrol->value.integer.value[0]) {
        case 0:
                /* Set IN1 to normal mode */
@@ -150,7 +153,7 @@ static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol,
                break;
        }
 
-       return 0;
+       return 1;
 }
 
 static const struct snd_kcontrol_new cs47l15_snd_controls[] = {
index 272041c..b9f19fb 100644 (file)
@@ -618,7 +618,13 @@ int madera_out1_demux_put(struct snd_kcontrol *kcontrol,
 end:
        snd_soc_dapm_mutex_unlock(dapm);
 
-       return snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
+       ret = snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
+       if (ret < 0) {
+               dev_err(madera->dev, "Failed to update demux power state: %d\n", ret);
+               return ret;
+       }
+
+       return change;
 }
 EXPORT_SYMBOL_GPL(madera_out1_demux_put);
 
@@ -893,7 +899,7 @@ static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol,
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
        const int adsp_num = e->shift_l;
        const unsigned int item = ucontrol->value.enumerated.item[0];
-       int ret;
+       int ret = 0;
 
        if (item >= e->items)
                return -EINVAL;
@@ -910,10 +916,10 @@ static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol,
                         "Cannot change '%s' while in use by active audio paths\n",
                         kcontrol->id.name);
                ret = -EBUSY;
-       } else {
+       } else if (priv->adsp_rate_cache[adsp_num] != e->values[item]) {
                /* Volatile register so defer until the codec is powered up */
                priv->adsp_rate_cache[adsp_num] = e->values[item];
-               ret = 0;
+               ret = 1;
        }
 
        mutex_unlock(&priv->rate_lock);
index f47e956..97b6447 100644 (file)
@@ -862,6 +862,16 @@ static int max98373_sdw_probe(struct sdw_slave *slave,
        return max98373_init(slave, regmap);
 }
 
+static int max98373_sdw_remove(struct sdw_slave *slave)
+{
+       struct max98373_priv *max98373 = dev_get_drvdata(&slave->dev);
+
+       if (max98373->first_hw_init)
+               pm_runtime_disable(&slave->dev);
+
+       return 0;
+}
+
 #if defined(CONFIG_OF)
 static const struct of_device_id max98373_of_match[] = {
        { .compatible = "maxim,max98373", },
@@ -893,7 +903,7 @@ static struct sdw_driver max98373_sdw_driver = {
                .pm = &max98373_pm,
        },
        .probe = max98373_sdw_probe,
-       .remove = NULL,
+       .remove = max98373_sdw_remove,
        .ops = &max98373_slave_ops,
        .id_table = max98373_id,
 };
index 1c11b42..72f673f 100644 (file)
@@ -691,6 +691,16 @@ static int rt1308_sdw_probe(struct sdw_slave *slave,
        return 0;
 }
 
+static int rt1308_sdw_remove(struct sdw_slave *slave)
+{
+       struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(&slave->dev);
+
+       if (rt1308->first_hw_init)
+               pm_runtime_disable(&slave->dev);
+
+       return 0;
+}
+
 static const struct sdw_device_id rt1308_id[] = {
        SDW_SLAVE_ENTRY_EXT(0x025d, 0x1308, 0x2, 0, 0),
        {},
@@ -750,6 +760,7 @@ static struct sdw_driver rt1308_sdw_driver = {
                .pm = &rt1308_pm,
        },
        .probe = rt1308_sdw_probe,
+       .remove = rt1308_sdw_remove,
        .ops = &rt1308_slave_ops,
        .id_table = rt1308_id,
 };
index 60baa9f..2d6b5f9 100644 (file)
@@ -676,6 +676,16 @@ static int rt1316_sdw_probe(struct sdw_slave *slave,
        return rt1316_sdw_init(&slave->dev, regmap, slave);
 }
 
+static int rt1316_sdw_remove(struct sdw_slave *slave)
+{
+       struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(&slave->dev);
+
+       if (rt1316->first_hw_init)
+               pm_runtime_disable(&slave->dev);
+
+       return 0;
+}
+
 static const struct sdw_device_id rt1316_id[] = {
        SDW_SLAVE_ENTRY_EXT(0x025d, 0x1316, 0x3, 0x1, 0),
        {},
@@ -735,6 +745,7 @@ static struct sdw_driver rt1316_sdw_driver = {
                .pm = &rt1316_pm,
        },
        .probe = rt1316_sdw_probe,
+       .remove = rt1316_sdw_remove,
        .ops = &rt1316_slave_ops,
        .id_table = rt1316_id,
 };
index 248257a..f04e18c 100644 (file)
@@ -719,9 +719,12 @@ static int rt5682_sdw_remove(struct sdw_slave *slave)
 {
        struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
 
-       if (rt5682 && rt5682->hw_init)
+       if (rt5682->hw_init)
                cancel_delayed_work_sync(&rt5682->jack_detect_work);
 
+       if (rt5682->first_hw_init)
+               pm_runtime_disable(&slave->dev);
+
        return 0;
 }
 
index bda5948..f7439e4 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/soundwire/sdw_type.h>
 #include <linux/soundwire/sdw_registers.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <sound/soc.h>
 #include "rt700.h"
@@ -463,11 +464,14 @@ static int rt700_sdw_remove(struct sdw_slave *slave)
 {
        struct rt700_priv *rt700 = dev_get_drvdata(&slave->dev);
 
-       if (rt700 && rt700->hw_init) {
+       if (rt700->hw_init) {
                cancel_delayed_work_sync(&rt700->jack_detect_work);
                cancel_delayed_work_sync(&rt700->jack_btn_check_work);
        }
 
+       if (rt700->first_hw_init)
+               pm_runtime_disable(&slave->dev);
+
        return 0;
 }
 
index af32295..9bceeeb 100644 (file)
@@ -162,7 +162,7 @@ static void rt700_jack_detect_handler(struct work_struct *work)
        if (!rt700->hs_jack)
                return;
 
-       if (!rt700->component->card->instantiated)
+       if (!rt700->component->card || !rt700->component->card->instantiated)
                return;
 
        reg = RT700_VERB_GET_PIN_SENSE | RT700_HP_OUT;
@@ -315,17 +315,27 @@ static int rt700_set_jack_detect(struct snd_soc_component *component,
        struct snd_soc_jack *hs_jack, void *data)
 {
        struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
+       int ret;
 
        rt700->hs_jack = hs_jack;
 
-       if (!rt700->hw_init) {
-               dev_dbg(&rt700->slave->dev,
-                       "%s hw_init not ready yet\n", __func__);
+       ret = pm_runtime_resume_and_get(component->dev);
+       if (ret < 0) {
+               if (ret != -EACCES) {
+                       dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret);
+                       return ret;
+               }
+
+               /* pm_runtime not enabled yet */
+               dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__);
                return 0;
        }
 
        rt700_jack_init(rt700);
 
+       pm_runtime_mark_last_busy(component->dev);
+       pm_runtime_put_autosuspend(component->dev);
+
        return 0;
 }
 
@@ -1115,6 +1125,11 @@ int rt700_init(struct device *dev, struct regmap *sdw_regmap,
 
        mutex_init(&rt700->disable_irq_lock);
 
+       INIT_DELAYED_WORK(&rt700->jack_detect_work,
+                         rt700_jack_detect_handler);
+       INIT_DELAYED_WORK(&rt700->jack_btn_check_work,
+                         rt700_btn_check_handler);
+
        /*
         * Mark hw_init to false
         * HW init will be performed when device reports present
@@ -1209,13 +1224,6 @@ int rt700_io_init(struct device *dev, struct sdw_slave *slave)
        /* Finish Initial Settings, set power to D3 */
        regmap_write(rt700->regmap, RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
 
-       if (!rt700->first_hw_init) {
-               INIT_DELAYED_WORK(&rt700->jack_detect_work,
-                       rt700_jack_detect_handler);
-               INIT_DELAYED_WORK(&rt700->jack_btn_check_work,
-                       rt700_btn_check_handler);
-       }
-
        /*
         * if set_jack callback occurred early than io_init,
         * we set up the jack detection function now
index aaf5af1..a085b2f 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/soundwire/sdw_registers.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 
 #include "rt711-sdca.h"
 #include "rt711-sdca-sdw.h"
@@ -364,11 +365,17 @@ static int rt711_sdca_sdw_remove(struct sdw_slave *slave)
 {
        struct rt711_sdca_priv *rt711 = dev_get_drvdata(&slave->dev);
 
-       if (rt711 && rt711->hw_init) {
+       if (rt711->hw_init) {
                cancel_delayed_work_sync(&rt711->jack_detect_work);
                cancel_delayed_work_sync(&rt711->jack_btn_check_work);
        }
 
+       if (rt711->first_hw_init)
+               pm_runtime_disable(&slave->dev);
+
+       mutex_destroy(&rt711->calibrate_mutex);
+       mutex_destroy(&rt711->disable_irq_lock);
+
        return 0;
 }
 
index 57629c1..5ad53bb 100644 (file)
@@ -34,7 +34,7 @@ static int rt711_sdca_index_write(struct rt711_sdca_priv *rt711,
 
        ret = regmap_write(regmap, addr, value);
        if (ret < 0)
-               dev_err(rt711->component->dev,
+               dev_err(&rt711->slave->dev,
                        "Failed to set private value: %06x <= %04x ret=%d\n",
                        addr, value, ret);
 
@@ -50,7 +50,7 @@ static int rt711_sdca_index_read(struct rt711_sdca_priv *rt711,
 
        ret = regmap_read(regmap, addr, value);
        if (ret < 0)
-               dev_err(rt711->component->dev,
+               dev_err(&rt711->slave->dev,
                        "Failed to get private value: %06x => %04x ret=%d\n",
                        addr, *value, ret);
 
@@ -294,7 +294,7 @@ static void rt711_sdca_jack_detect_handler(struct work_struct *work)
        if (!rt711->hs_jack)
                return;
 
-       if (!rt711->component->card->instantiated)
+       if (!rt711->component->card || !rt711->component->card->instantiated)
                return;
 
        /* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */
@@ -487,16 +487,27 @@ static int rt711_sdca_set_jack_detect(struct snd_soc_component *component,
        struct snd_soc_jack *hs_jack, void *data)
 {
        struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component);
+       int ret;
 
        rt711->hs_jack = hs_jack;
 
-       if (!rt711->hw_init) {
-               dev_dbg(&rt711->slave->dev,
-                       "%s hw_init not ready yet\n", __func__);
+       ret = pm_runtime_resume_and_get(component->dev);
+       if (ret < 0) {
+               if (ret != -EACCES) {
+                       dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret);
+                       return ret;
+               }
+
+               /* pm_runtime not enabled yet */
+               dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__);
                return 0;
        }
 
        rt711_sdca_jack_init(rt711);
+
+       pm_runtime_mark_last_busy(component->dev);
+       pm_runtime_put_autosuspend(component->dev);
+
        return 0;
 }
 
@@ -1190,14 +1201,6 @@ static int rt711_sdca_probe(struct snd_soc_component *component)
        return 0;
 }
 
-static void rt711_sdca_remove(struct snd_soc_component *component)
-{
-       struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component);
-
-       regcache_cache_only(rt711->regmap, true);
-       regcache_cache_only(rt711->mbq_regmap, true);
-}
-
 static const struct snd_soc_component_driver soc_sdca_dev_rt711 = {
        .probe = rt711_sdca_probe,
        .controls = rt711_sdca_snd_controls,
@@ -1207,7 +1210,6 @@ static const struct snd_soc_component_driver soc_sdca_dev_rt711 = {
        .dapm_routes = rt711_sdca_audio_map,
        .num_dapm_routes = ARRAY_SIZE(rt711_sdca_audio_map),
        .set_jack = rt711_sdca_set_jack_detect,
-       .remove = rt711_sdca_remove,
        .endianness = 1,
 };
 
@@ -1412,8 +1414,12 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap,
        rt711->regmap = regmap;
        rt711->mbq_regmap = mbq_regmap;
 
+       mutex_init(&rt711->calibrate_mutex);
        mutex_init(&rt711->disable_irq_lock);
 
+       INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_sdca_jack_detect_handler);
+       INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_sdca_btn_check_handler);
+
        /*
         * Mark hw_init to false
         * HW init will be performed when device reports present
@@ -1545,14 +1551,6 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave)
        rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL,
                RT711_PUSH_BTN_INT_CTL0, 0x20, 0x00);
 
-       if (!rt711->first_hw_init) {
-               INIT_DELAYED_WORK(&rt711->jack_detect_work,
-                       rt711_sdca_jack_detect_handler);
-               INIT_DELAYED_WORK(&rt711->jack_btn_check_work,
-                       rt711_sdca_btn_check_handler);
-               mutex_init(&rt711->calibrate_mutex);
-       }
-
        /* calibration */
        ret = rt711_sdca_calibration(rt711);
        if (ret < 0)
index bda2cc9..4fe68bc 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/soundwire/sdw_type.h>
 #include <linux/soundwire/sdw_registers.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <sound/soc.h>
 #include "rt711.h"
@@ -464,12 +465,18 @@ static int rt711_sdw_remove(struct sdw_slave *slave)
 {
        struct rt711_priv *rt711 = dev_get_drvdata(&slave->dev);
 
-       if (rt711 && rt711->hw_init) {
+       if (rt711->hw_init) {
                cancel_delayed_work_sync(&rt711->jack_detect_work);
                cancel_delayed_work_sync(&rt711->jack_btn_check_work);
                cancel_work_sync(&rt711->calibration_work);
        }
 
+       if (rt711->first_hw_init)
+               pm_runtime_disable(&slave->dev);
+
+       mutex_destroy(&rt711->calibrate_mutex);
+       mutex_destroy(&rt711->disable_irq_lock);
+
        return 0;
 }
 
index 9838fb4..9df800a 100644 (file)
@@ -242,7 +242,7 @@ static void rt711_jack_detect_handler(struct work_struct *work)
        if (!rt711->hs_jack)
                return;
 
-       if (!rt711->component->card->instantiated)
+       if (!rt711->component->card || !rt711->component->card->instantiated)
                return;
 
        if (pm_runtime_status_suspended(rt711->slave->dev.parent)) {
@@ -457,17 +457,27 @@ static int rt711_set_jack_detect(struct snd_soc_component *component,
        struct snd_soc_jack *hs_jack, void *data)
 {
        struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
+       int ret;
 
        rt711->hs_jack = hs_jack;
 
-       if (!rt711->hw_init) {
-               dev_dbg(&rt711->slave->dev,
-                       "%s hw_init not ready yet\n", __func__);
+       ret = pm_runtime_resume_and_get(component->dev);
+       if (ret < 0) {
+               if (ret != -EACCES) {
+                       dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret);
+                       return ret;
+               }
+
+               /* pm_runtime not enabled yet */
+               dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__);
                return 0;
        }
 
        rt711_jack_init(rt711);
 
+       pm_runtime_mark_last_busy(component->dev);
+       pm_runtime_put_autosuspend(component->dev);
+
        return 0;
 }
 
@@ -932,13 +942,6 @@ static int rt711_probe(struct snd_soc_component *component)
        return 0;
 }
 
-static void rt711_remove(struct snd_soc_component *component)
-{
-       struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
-
-       regcache_cache_only(rt711->regmap, true);
-}
-
 static const struct snd_soc_component_driver soc_codec_dev_rt711 = {
        .probe = rt711_probe,
        .set_bias_level = rt711_set_bias_level,
@@ -949,7 +952,6 @@ static const struct snd_soc_component_driver soc_codec_dev_rt711 = {
        .dapm_routes = rt711_audio_map,
        .num_dapm_routes = ARRAY_SIZE(rt711_audio_map),
        .set_jack = rt711_set_jack_detect,
-       .remove = rt711_remove,
        .endianness = 1,
 };
 
@@ -1204,8 +1206,13 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap,
        rt711->sdw_regmap = sdw_regmap;
        rt711->regmap = regmap;
 
+       mutex_init(&rt711->calibrate_mutex);
        mutex_init(&rt711->disable_irq_lock);
 
+       INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_jack_detect_handler);
+       INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_btn_check_handler);
+       INIT_WORK(&rt711->calibration_work, rt711_calibration_work);
+
        /*
         * Mark hw_init to false
         * HW init will be performed when device reports present
@@ -1313,15 +1320,8 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave)
 
        if (rt711->first_hw_init)
                rt711_calibration(rt711);
-       else {
-               INIT_DELAYED_WORK(&rt711->jack_detect_work,
-                       rt711_jack_detect_handler);
-               INIT_DELAYED_WORK(&rt711->jack_btn_check_work,
-                       rt711_btn_check_handler);
-               mutex_init(&rt711->calibrate_mutex);
-               INIT_WORK(&rt711->calibration_work, rt711_calibration_work);
+       else
                schedule_work(&rt711->calibration_work);
-       }
 
        /*
         * if set_jack callback occurred early than io_init,
index 0ecd294..13e731d 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/soundwire/sdw_type.h>
 #include <linux/soundwire/sdw_registers.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <sound/soc.h>
 #include "rt715-sdca.h"
@@ -193,6 +194,16 @@ static int rt715_sdca_sdw_probe(struct sdw_slave *slave,
        return rt715_sdca_init(&slave->dev, mbq_regmap, regmap, slave);
 }
 
+static int rt715_sdca_sdw_remove(struct sdw_slave *slave)
+{
+       struct rt715_sdca_priv *rt715 = dev_get_drvdata(&slave->dev);
+
+       if (rt715->first_hw_init)
+               pm_runtime_disable(&slave->dev);
+
+       return 0;
+}
+
 static const struct sdw_device_id rt715_sdca_id[] = {
        SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x3, 0x1, 0),
        SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x3, 0x1, 0),
@@ -267,6 +278,7 @@ static struct sdw_driver rt715_sdw_driver = {
                .pm = &rt715_pm,
        },
        .probe = rt715_sdca_sdw_probe,
+       .remove = rt715_sdca_sdw_remove,
        .ops = &rt715_sdca_slave_ops,
        .id_table = rt715_sdca_id,
 };
index a7b21b0..b047bf8 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/soundwire/sdw_type.h>
 #include <linux/soundwire/sdw_registers.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/regmap.h>
 #include <sound/soc.h>
@@ -514,6 +515,16 @@ static int rt715_sdw_probe(struct sdw_slave *slave,
        return 0;
 }
 
+static int rt715_sdw_remove(struct sdw_slave *slave)
+{
+       struct rt715_priv *rt715 = dev_get_drvdata(&slave->dev);
+
+       if (rt715->first_hw_init)
+               pm_runtime_disable(&slave->dev);
+
+       return 0;
+}
+
 static const struct sdw_device_id rt715_id[] = {
        SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x2, 0, 0),
        SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x2, 0, 0),
@@ -575,6 +586,7 @@ static struct sdw_driver rt715_sdw_driver = {
                   .pm = &rt715_pm,
                   },
        .probe = rt715_sdw_probe,
+       .remove = rt715_sdw_remove,
        .ops = &rt715_slave_ops,
        .id_table = rt715_id,
 };
index 617a36a..d9f1352 100644 (file)
@@ -1287,11 +1287,17 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc,
        struct snd_soc_dapm_update *update = NULL;
        u32 port_id = w->shift;
 
+       if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0])
+               return 0;
+
        wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0];
 
+       /* Remove channel from any list it's in before adding it to a new one */
+       list_del_init(&wcd->rx_chs[port_id].list);
+
        switch (wcd->rx_port_value[port_id]) {
        case 0:
-               list_del_init(&wcd->rx_chs[port_id].list);
+               /* Channel already removed from lists. Nothing to do here */
                break;
        case 1:
                list_add_tail(&wcd->rx_chs[port_id].list,
index c1b61b9..781ae56 100644 (file)
@@ -2519,6 +2519,9 @@ static int wcd938x_tx_mode_put(struct snd_kcontrol *kcontrol,
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
        int path = e->shift_l;
 
+       if (wcd938x->tx_mode[path] == ucontrol->value.enumerated.item[0])
+               return 0;
+
        wcd938x->tx_mode[path] = ucontrol->value.enumerated.item[0];
 
        return 1;
@@ -2541,6 +2544,9 @@ static int wcd938x_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
        struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
 
+       if (wcd938x->hph_mode == ucontrol->value.enumerated.item[0])
+               return 0;
+
        wcd938x->hph_mode = ucontrol->value.enumerated.item[0];
 
        return 1;
@@ -2632,6 +2638,9 @@ static int wcd938x_ldoh_put(struct snd_kcontrol *kcontrol,
        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
        struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
 
+       if (wcd938x->ldoh == ucontrol->value.integer.value[0])
+               return 0;
+
        wcd938x->ldoh = ucontrol->value.integer.value[0];
 
        return 1;
@@ -2654,6 +2663,9 @@ static int wcd938x_bcs_put(struct snd_kcontrol *kcontrol,
        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
        struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
 
+       if (wcd938x->bcs_dis == ucontrol->value.integer.value[0])
+               return 0;
+
        wcd938x->bcs_dis = ucontrol->value.integer.value[0];
 
        return 1;
index 4973ba1..4ab7a67 100644 (file)
@@ -413,6 +413,7 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol,
        unsigned int rnew = (!!ucontrol->value.integer.value[1]) << mc->rshift;
        unsigned int lold, rold;
        unsigned int lena, rena;
+       bool change = false;
        int ret;
 
        snd_soc_dapm_mutex_lock(dapm);
@@ -440,8 +441,8 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol,
                goto err;
        }
 
-       ret = regmap_update_bits(arizona->regmap, ARIZONA_DRE_ENABLE,
-                                mask, lnew | rnew);
+       ret = regmap_update_bits_check(arizona->regmap, ARIZONA_DRE_ENABLE,
+                                      mask, lnew | rnew, &change);
        if (ret) {
                dev_err(arizona->dev, "Failed to set DRE: %d\n", ret);
                goto err;
@@ -454,6 +455,9 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol,
        if (!rnew && rold)
                wm5110_clear_pga_volume(arizona, mc->rshift);
 
+       if (change)
+               ret = 1;
+
 err:
        snd_soc_dapm_mutex_unlock(dapm);
 
index 6d7fd88..a7784ac 100644 (file)
@@ -997,7 +997,7 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
                snd_soc_dapm_sync(dapm);
        }
 
-       return 0;
+       return 1;
 }
 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put);
 
index 0d11cc8..6a06fe3 100644 (file)
@@ -128,10 +128,10 @@ struct avs_tplg_token_parser {
 static int
 avs_parse_uuid_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
 {
-       struct snd_soc_tplg_vendor_value_elem *tuple = elem;
+       struct snd_soc_tplg_vendor_uuid_elem *tuple = elem;
        guid_t *val = (guid_t *)((u8 *)object + offset);
 
-       guid_copy((guid_t *)val, (const guid_t *)&tuple->value);
+       guid_copy((guid_t *)val, (const guid_t *)&tuple->uuid);
 
        return 0;
 }
index 00384c6..330c0ac 100644 (file)
@@ -421,8 +421,17 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
        priv->spkvdd_en_gpio = gpiod_get(codec_dev, "wlf,spkvdd-ena", GPIOD_OUT_LOW);
        put_device(codec_dev);
 
-       if (IS_ERR(priv->spkvdd_en_gpio))
-               return dev_err_probe(dev, PTR_ERR(priv->spkvdd_en_gpio), "getting spkvdd-GPIO\n");
+       if (IS_ERR(priv->spkvdd_en_gpio)) {
+               ret = PTR_ERR(priv->spkvdd_en_gpio);
+               /*
+                * The spkvdd gpio-lookup is registered by: drivers/mfd/arizona-spi.c,
+                * so -ENOENT means that arizona-spi hasn't probed yet.
+                */
+               if (ret == -ENOENT)
+                       ret = -EPROBE_DEFER;
+
+               return dev_err_probe(dev, ret, "getting spkvdd-GPIO\n");
+       }
 
        /* override platform name, if required */
        byt_wm5102_card.dev = dev;
index 1f00679..ad826ad 100644 (file)
@@ -1398,6 +1398,33 @@ static struct snd_soc_card card_sof_sdw = {
        .late_probe = sof_sdw_card_late_probe,
 };
 
+static void mc_dailink_exit_loop(struct snd_soc_card *card)
+{
+       struct snd_soc_dai_link *link;
+       int ret;
+       int i, j;
+
+       for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
+               if (!codec_info_list[i].exit)
+                       continue;
+               /*
+                * We don't need to call .exit function if there is no matched
+                * dai link found.
+                */
+               for_each_card_prelinks(card, j, link) {
+                       if (!strcmp(link->codecs[0].dai_name,
+                                   codec_info_list[i].dai_name)) {
+                               ret = codec_info_list[i].exit(card, link);
+                               if (ret)
+                                       dev_warn(card->dev,
+                                                "codec exit failed %d\n",
+                                                ret);
+                               break;
+                       }
+               }
+       }
+}
+
 static int mc_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = &card_sof_sdw;
@@ -1462,6 +1489,7 @@ static int mc_probe(struct platform_device *pdev)
        ret = devm_snd_soc_register_card(&pdev->dev, card);
        if (ret) {
                dev_err(card->dev, "snd_soc_register_card failed %d\n", ret);
+               mc_dailink_exit_loop(card);
                return ret;
        }
 
@@ -1473,29 +1501,8 @@ static int mc_probe(struct platform_device *pdev)
 static int mc_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
-       struct snd_soc_dai_link *link;
-       int ret;
-       int i, j;
 
-       for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
-               if (!codec_info_list[i].exit)
-                       continue;
-               /*
-                * We don't need to call .exit function if there is no matched
-                * dai link found.
-                */
-               for_each_card_prelinks(card, j, link) {
-                       if (!strcmp(link->codecs[0].dai_name,
-                                   codec_info_list[i].dai_name)) {
-                               ret = codec_info_list[i].exit(card, link);
-                               if (ret)
-                                       dev_warn(&pdev->dev,
-                                                "codec exit failed %d\n",
-                                                ret);
-                               break;
-                       }
-               }
-       }
+       mc_dailink_exit_loop(card);
 
        return 0;
 }
index 19c4a90..ee59ef3 100644 (file)
@@ -147,6 +147,12 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
        cfg.num_channels = runtime->channels;
        cfg.bit_width = prtd->bits_per_sample;
 
+       if (prtd->state) {
+               /* clear the previous setup if any  */
+               q6apm_graph_stop(prtd->graph);
+               q6apm_unmap_memory_regions(prtd->graph, substream->stream);
+       }
+
        prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
        prtd->pos = 0;
        /* rate and channels are sent to audio driver */
index 4ce5d25..99a128a 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/of_gpio.h>
 #include <linux/of_device.h>
 #include <linux/clk.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/spinlock.h>
@@ -54,8 +55,40 @@ struct rk_i2s_dev {
        const struct rk_i2s_pins *pins;
        unsigned int bclk_ratio;
        spinlock_t lock; /* tx/rx lock */
+       struct pinctrl *pinctrl;
+       struct pinctrl_state *bclk_on;
+       struct pinctrl_state *bclk_off;
 };
 
+static int i2s_pinctrl_select_bclk_on(struct rk_i2s_dev *i2s)
+{
+       int ret = 0;
+
+       if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_on))
+               ret = pinctrl_select_state(i2s->pinctrl,
+                                    i2s->bclk_on);
+
+       if (ret)
+               dev_err(i2s->dev, "bclk enable failed %d\n", ret);
+
+       return ret;
+}
+
+static int i2s_pinctrl_select_bclk_off(struct rk_i2s_dev *i2s)
+{
+
+       int ret = 0;
+
+       if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_off))
+               ret = pinctrl_select_state(i2s->pinctrl,
+                                    i2s->bclk_off);
+
+       if (ret)
+               dev_err(i2s->dev, "bclk disable failed %d\n", ret);
+
+       return ret;
+}
+
 static int i2s_runtime_suspend(struct device *dev)
 {
        struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
@@ -92,38 +125,49 @@ static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
        return snd_soc_dai_get_drvdata(dai);
 }
 
-static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
+static int rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
 {
        unsigned int val = 0;
        int retry = 10;
+       int ret = 0;
 
        spin_lock(&i2s->lock);
        if (on) {
-               regmap_update_bits(i2s->regmap, I2S_DMACR,
-                                  I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
+               ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
+                               I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
+               if (ret < 0)
+                       goto end;
 
-               regmap_update_bits(i2s->regmap, I2S_XFER,
-                                  I2S_XFER_TXS_START | I2S_XFER_RXS_START,
-                                  I2S_XFER_TXS_START | I2S_XFER_RXS_START);
+               ret = regmap_update_bits(i2s->regmap, I2S_XFER,
+                               I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+                               I2S_XFER_TXS_START | I2S_XFER_RXS_START);
+               if (ret < 0)
+                       goto end;
 
                i2s->tx_start = true;
        } else {
                i2s->tx_start = false;
 
-               regmap_update_bits(i2s->regmap, I2S_DMACR,
-                                  I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
+               ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
+                               I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
+               if (ret < 0)
+                       goto end;
 
                if (!i2s->rx_start) {
-                       regmap_update_bits(i2s->regmap, I2S_XFER,
-                                          I2S_XFER_TXS_START |
-                                          I2S_XFER_RXS_START,
-                                          I2S_XFER_TXS_STOP |
-                                          I2S_XFER_RXS_STOP);
+                       ret = regmap_update_bits(i2s->regmap, I2S_XFER,
+                                       I2S_XFER_TXS_START |
+                                       I2S_XFER_RXS_START,
+                                       I2S_XFER_TXS_STOP |
+                                       I2S_XFER_RXS_STOP);
+                       if (ret < 0)
+                               goto end;
 
                        udelay(150);
-                       regmap_update_bits(i2s->regmap, I2S_CLR,
-                                          I2S_CLR_TXC | I2S_CLR_RXC,
-                                          I2S_CLR_TXC | I2S_CLR_RXC);
+                       ret = regmap_update_bits(i2s->regmap, I2S_CLR,
+                                       I2S_CLR_TXC | I2S_CLR_RXC,
+                                       I2S_CLR_TXC | I2S_CLR_RXC);
+                       if (ret < 0)
+                               goto end;
 
                        regmap_read(i2s->regmap, I2S_CLR, &val);
 
@@ -138,44 +182,57 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
                        }
                }
        }
+end:
        spin_unlock(&i2s->lock);
+       if (ret < 0)
+               dev_err(i2s->dev, "lrclk update failed\n");
+
+       return ret;
 }
 
-static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
+static int rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
 {
        unsigned int val = 0;
        int retry = 10;
+       int ret = 0;
 
        spin_lock(&i2s->lock);
        if (on) {
-               regmap_update_bits(i2s->regmap, I2S_DMACR,
+               ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
                                   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
+               if (ret < 0)
+                       goto end;
 
-               regmap_update_bits(i2s->regmap, I2S_XFER,
+               ret = regmap_update_bits(i2s->regmap, I2S_XFER,
                                   I2S_XFER_TXS_START | I2S_XFER_RXS_START,
                                   I2S_XFER_TXS_START | I2S_XFER_RXS_START);
+               if (ret < 0)
+                       goto end;
 
                i2s->rx_start = true;
        } else {
                i2s->rx_start = false;
 
-               regmap_update_bits(i2s->regmap, I2S_DMACR,
+               ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
                                   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
+               if (ret < 0)
+                       goto end;
 
                if (!i2s->tx_start) {
-                       regmap_update_bits(i2s->regmap, I2S_XFER,
+                       ret = regmap_update_bits(i2s->regmap, I2S_XFER,
                                           I2S_XFER_TXS_START |
                                           I2S_XFER_RXS_START,
                                           I2S_XFER_TXS_STOP |
                                           I2S_XFER_RXS_STOP);
-
+                       if (ret < 0)
+                               goto end;
                        udelay(150);
-                       regmap_update_bits(i2s->regmap, I2S_CLR,
+                       ret = regmap_update_bits(i2s->regmap, I2S_CLR,
                                           I2S_CLR_TXC | I2S_CLR_RXC,
                                           I2S_CLR_TXC | I2S_CLR_RXC);
-
+                       if (ret < 0)
+                               goto end;
                        regmap_read(i2s->regmap, I2S_CLR, &val);
-
                        /* Should wait for clear operation to finish */
                        while (val) {
                                regmap_read(i2s->regmap, I2S_CLR, &val);
@@ -187,7 +244,12 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
                        }
                }
        }
+end:
        spin_unlock(&i2s->lock);
+       if (ret < 0)
+               dev_err(i2s->dev, "lrclk update failed\n");
+
+       return ret;
 }
 
 static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
@@ -425,17 +487,26 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-                       rockchip_snd_rxctrl(i2s, 1);
+                       ret = rockchip_snd_rxctrl(i2s, 1);
                else
-                       rockchip_snd_txctrl(i2s, 1);
+                       ret = rockchip_snd_txctrl(i2s, 1);
+               /* Do not turn on bclk if lrclk open fails. */
+               if (ret < 0)
+                       return ret;
+               i2s_pinctrl_select_bclk_on(i2s);
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-                       rockchip_snd_rxctrl(i2s, 0);
-               else
-                       rockchip_snd_txctrl(i2s, 0);
+               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+                       if (!i2s->tx_start)
+                               i2s_pinctrl_select_bclk_off(i2s);
+                       ret = rockchip_snd_rxctrl(i2s, 0);
+               } else {
+                       if (!i2s->rx_start)
+                               i2s_pinctrl_select_bclk_off(i2s);
+                       ret = rockchip_snd_txctrl(i2s, 0);
+               }
                break;
        default:
                ret = -EINVAL;
@@ -736,6 +807,33 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
        }
 
        i2s->bclk_ratio = 64;
+       i2s->pinctrl = devm_pinctrl_get(&pdev->dev);
+       if (IS_ERR(i2s->pinctrl))
+               dev_err(&pdev->dev, "failed to find i2s pinctrl\n");
+
+       i2s->bclk_on = pinctrl_lookup_state(i2s->pinctrl,
+                                  "bclk_on");
+       if (IS_ERR_OR_NULL(i2s->bclk_on))
+               dev_err(&pdev->dev, "failed to find i2s default state\n");
+       else
+               dev_dbg(&pdev->dev, "find i2s bclk state\n");
+
+       i2s->bclk_off = pinctrl_lookup_state(i2s->pinctrl,
+                                 "bclk_off");
+       if (IS_ERR_OR_NULL(i2s->bclk_off))
+               dev_err(&pdev->dev, "failed to find i2s gpio state\n");
+       else
+               dev_dbg(&pdev->dev, "find i2s bclk_off state\n");
+
+       i2s_pinctrl_select_bclk_off(i2s);
+
+       i2s->playback_dma_data.addr = res->start + I2S_TXDR;
+       i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       i2s->playback_dma_data.maxburst = 4;
+
+       i2s->capture_dma_data.addr = res->start + I2S_RXDR;
+       i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       i2s->capture_dma_data.maxburst = 4;
 
        dev_set_drvdata(&pdev->dev, i2s);
 
index 869c765..a8e842e 100644 (file)
@@ -62,6 +62,8 @@ struct snd_soc_dapm_widget *
 snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
                         const struct snd_soc_dapm_widget *widget);
 
+static unsigned int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg);
+
 /* dapm power sequences - make this per codec in the future */
 static int dapm_up_seq[] = {
        [snd_soc_dapm_pre] = 1,
@@ -442,6 +444,9 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
 
                        snd_soc_dapm_add_path(widget->dapm, data->widget,
                                              widget, NULL, NULL);
+               } else if (e->reg != SND_SOC_NOPM) {
+                       data->value = soc_dapm_read(widget->dapm, e->reg) &
+                                     (e->mask << e->shift_l);
                }
                break;
        default:
index e693070..d867f44 100644 (file)
@@ -526,7 +526,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
                return -EINVAL;
        if (mc->platform_max && tmp > mc->platform_max)
                return -EINVAL;
-       if (tmp > mc->max - mc->min + 1)
+       if (tmp > mc->max - mc->min)
                return -EINVAL;
 
        if (invert)
@@ -547,7 +547,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
                        return -EINVAL;
                if (mc->platform_max && tmp > mc->platform_max)
                        return -EINVAL;
-               if (tmp > mc->max - mc->min + 1)
+               if (tmp > mc->max - mc->min)
                        return -EINVAL;
 
                if (invert)
index 000ea90..e24eea7 100644 (file)
@@ -181,12 +181,20 @@ int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask)
  * Power Management.
  */
 
-static int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask)
+int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask)
 {
+       struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
+       const struct sof_intel_dsp_desc *chip = hda->desc;
        unsigned int cpa;
        u32 adspcs;
        int ret;
 
+       /* restrict core_mask to host managed cores mask */
+       core_mask &= chip->host_managed_cores_mask;
+       /* return if core_mask is not valid */
+       if (!core_mask)
+               return 0;
+
        /* update bits */
        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS,
                                HDA_DSP_ADSPCS_SPA_MASK(core_mask),
index 6429012..145d483 100644 (file)
@@ -95,9 +95,9 @@ out_put:
 }
 
 /*
- * first boot sequence has some extra steps. core 0 waits for power
- * status on core 1, so power up core 1 also momentarily, keep it in
- * reset/stall and then turn it off
+ * first boot sequence has some extra steps.
+ * power on all host managed cores and only unstall/run the boot core to boot the
+ * DSP then turn off all non boot cores (if any) is powered on.
  */
 static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
 {
@@ -110,7 +110,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
        int ret;
 
        /* step 1: power up corex */
-       ret = hda_dsp_enable_core(sdev, chip->host_managed_cores_mask);
+       ret = hda_dsp_core_power_up(sdev, chip->host_managed_cores_mask);
        if (ret < 0) {
                if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
                        dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n");
@@ -127,7 +127,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
        snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr);
 
        /* step 3: unset core 0 reset state & unstall/run core 0 */
-       ret = hda_dsp_core_run(sdev, BIT(0));
+       ret = hda_dsp_core_run(sdev, chip->init_core_mask);
        if (ret < 0) {
                if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
                        dev_err(sdev->dev,
@@ -389,7 +389,8 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
        struct snd_dma_buffer dmab;
        int ret, ret1, i;
 
-       if (hda->imrboot_supported && !sdev->first_boot) {
+       if (sdev->system_suspend_target < SOF_SUSPEND_S4 &&
+           hda->imrboot_supported && !sdev->first_boot) {
                dev_dbg(sdev->dev, "IMR restore supported, booting from IMR directly\n");
                hda->boot_iteration = 0;
                ret = hda_dsp_boot_imr(sdev);
index dc1f743..6888e0a 100644 (file)
@@ -192,79 +192,7 @@ snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
                goto found;
        }
 
-       switch (sof_hda_position_quirk) {
-       case SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY:
-               /*
-                * This legacy code, inherited from the Skylake driver,
-                * mixes DPIB registers and DPIB DDR updates and
-                * does not seem to follow any known hardware recommendations.
-                * It's not clear e.g. why there is a different flow
-                * for capture and playback, the only information that matters is
-                * what traffic class is used, and on all SOF-enabled platforms
-                * only VC0 is supported so the work-around was likely not necessary
-                * and quite possibly wrong.
-                */
-
-               /* DPIB/posbuf position mode:
-                * For Playback, Use DPIB register from HDA space which
-                * reflects the actual data transferred.
-                * For Capture, Use the position buffer for pointer, as DPIB
-                * is not accurate enough, its update may be completed
-                * earlier than the data written to DDR.
-                */
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
-                                              AZX_REG_VS_SDXDPIB_XBASE +
-                                              (AZX_REG_VS_SDXDPIB_XINTERVAL *
-                                               hstream->index));
-               } else {
-                       /*
-                        * For capture stream, we need more workaround to fix the
-                        * position incorrect issue:
-                        *
-                        * 1. Wait at least 20us before reading position buffer after
-                        * the interrupt generated(IOC), to make sure position update
-                        * happens on frame boundary i.e. 20.833uSec for 48KHz.
-                        * 2. Perform a dummy Read to DPIB register to flush DMA
-                        * position value.
-                        * 3. Read the DMA Position from posbuf. Now the readback
-                        * value should be >= period boundary.
-                        */
-                       usleep_range(20, 21);
-                       snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
-                                        AZX_REG_VS_SDXDPIB_XBASE +
-                                        (AZX_REG_VS_SDXDPIB_XINTERVAL *
-                                         hstream->index));
-                       pos = snd_hdac_stream_get_pos_posbuf(hstream);
-               }
-               break;
-       case SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS:
-               /*
-                * In case VC1 traffic is disabled this is the recommended option
-                */
-               pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
-                                      AZX_REG_VS_SDXDPIB_XBASE +
-                                      (AZX_REG_VS_SDXDPIB_XINTERVAL *
-                                       hstream->index));
-               break;
-       case SOF_HDA_POSITION_QUIRK_USE_DPIB_DDR_UPDATE:
-               /*
-                * This is the recommended option when VC1 is enabled.
-                * While this isn't needed for SOF platforms it's added for
-                * consistency and debug.
-                */
-               pos = snd_hdac_stream_get_pos_posbuf(hstream);
-               break;
-       default:
-               dev_err_once(sdev->dev, "hda_position_quirk value %d not supported\n",
-                            sof_hda_position_quirk);
-               pos = 0;
-               break;
-       }
-
-       if (pos >= hstream->bufsize)
-               pos = 0;
-
+       pos = hda_dsp_stream_get_position(hstream, substream->stream, true);
 found:
        pos = bytes_to_frames(substream->runtime, pos);
 
index daeb64c..d95ae17 100644 (file)
@@ -707,12 +707,13 @@ bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev)
 }
 
 static void
-hda_dsp_set_bytes_transferred(struct hdac_stream *hstream, u64 buffer_size)
+hda_dsp_compr_bytes_transferred(struct hdac_stream *hstream, int direction)
 {
+       u64 buffer_size = hstream->bufsize;
        u64 prev_pos, pos, num_bytes;
 
        div64_u64_rem(hstream->curr_pos, buffer_size, &prev_pos);
-       pos = snd_hdac_stream_get_pos_posbuf(hstream);
+       pos = hda_dsp_stream_get_position(hstream, direction, false);
 
        if (pos < prev_pos)
                num_bytes = (buffer_size - prev_pos) +  pos;
@@ -748,8 +749,7 @@ static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status)
                        if (s->substream && sof_hda->no_ipc_position) {
                                snd_sof_pcm_period_elapsed(s->substream);
                        } else if (s->cstream) {
-                               hda_dsp_set_bytes_transferred(s,
-                                       s->cstream->runtime->buffer_size);
+                               hda_dsp_compr_bytes_transferred(s, s->cstream->direction);
                                snd_compr_fragment_elapsed(s->cstream);
                        }
                }
@@ -1009,3 +1009,89 @@ void hda_dsp_stream_free(struct snd_sof_dev *sdev)
                devm_kfree(sdev->dev, hda_stream);
        }
 }
+
+snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
+                                             int direction, bool can_sleep)
+{
+       struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
+       struct sof_intel_hda_stream *hda_stream = hstream_to_sof_hda_stream(hext_stream);
+       struct snd_sof_dev *sdev = hda_stream->sdev;
+       snd_pcm_uframes_t pos;
+
+       switch (sof_hda_position_quirk) {
+       case SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY:
+               /*
+                * This legacy code, inherited from the Skylake driver,
+                * mixes DPIB registers and DPIB DDR updates and
+                * does not seem to follow any known hardware recommendations.
+                * It's not clear e.g. why there is a different flow
+                * for capture and playback, the only information that matters is
+                * what traffic class is used, and on all SOF-enabled platforms
+                * only VC0 is supported so the work-around was likely not necessary
+                * and quite possibly wrong.
+                */
+
+               /* DPIB/posbuf position mode:
+                * For Playback, Use DPIB register from HDA space which
+                * reflects the actual data transferred.
+                * For Capture, Use the position buffer for pointer, as DPIB
+                * is not accurate enough, its update may be completed
+                * earlier than the data written to DDR.
+                */
+               if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+                       pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
+                                              AZX_REG_VS_SDXDPIB_XBASE +
+                                              (AZX_REG_VS_SDXDPIB_XINTERVAL *
+                                               hstream->index));
+               } else {
+                       /*
+                        * For capture stream, we need more workaround to fix the
+                        * position incorrect issue:
+                        *
+                        * 1. Wait at least 20us before reading position buffer after
+                        * the interrupt generated(IOC), to make sure position update
+                        * happens on frame boundary i.e. 20.833uSec for 48KHz.
+                        * 2. Perform a dummy Read to DPIB register to flush DMA
+                        * position value.
+                        * 3. Read the DMA Position from posbuf. Now the readback
+                        * value should be >= period boundary.
+                        */
+                       if (can_sleep)
+                               usleep_range(20, 21);
+
+                       snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
+                                        AZX_REG_VS_SDXDPIB_XBASE +
+                                        (AZX_REG_VS_SDXDPIB_XINTERVAL *
+                                         hstream->index));
+                       pos = snd_hdac_stream_get_pos_posbuf(hstream);
+               }
+               break;
+       case SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS:
+               /*
+                * In case VC1 traffic is disabled this is the recommended option
+                */
+               pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
+                                      AZX_REG_VS_SDXDPIB_XBASE +
+                                      (AZX_REG_VS_SDXDPIB_XINTERVAL *
+                                       hstream->index));
+               break;
+       case SOF_HDA_POSITION_QUIRK_USE_DPIB_DDR_UPDATE:
+               /*
+                * This is the recommended option when VC1 is enabled.
+                * While this isn't needed for SOF platforms it's added for
+                * consistency and debug.
+                */
+               pos = snd_hdac_stream_get_pos_posbuf(hstream);
+               break;
+       default:
+               dev_err_once(sdev->dev, "hda_position_quirk value %d not supported\n",
+                            sof_hda_position_quirk);
+               pos = 0;
+               break;
+       }
+
+       if (pos >= hstream->bufsize)
+               pos = 0;
+
+       return pos;
+}
index 3e0f7b0..06476ff 100644 (file)
@@ -497,6 +497,7 @@ struct sof_intel_hda_stream {
  */
 int hda_dsp_probe(struct snd_sof_dev *sdev);
 int hda_dsp_remove(struct snd_sof_dev *sdev);
+int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask);
 int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask);
 int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask);
 int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev,
@@ -564,6 +565,9 @@ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev,
 bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev);
 bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev);
 
+snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
+                                             int direction, bool can_sleep);
+
 struct hdac_ext_stream *
        hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags);
 int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag);
index 043554d..10740c5 100644 (file)
@@ -1577,24 +1577,23 @@ static int sof_ipc3_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_
        struct sof_ipc_ctrl_data *cdata;
        int ret;
 
-       scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL);
-       if (!scontrol->ipc_control_data)
-               return -ENOMEM;
-
-       if (scontrol->max_size < sizeof(*cdata) ||
-           scontrol->max_size < sizeof(struct sof_abi_hdr)) {
-               ret = -EINVAL;
-               goto err;
+       if (scontrol->max_size < (sizeof(*cdata) + sizeof(struct sof_abi_hdr))) {
+               dev_err(sdev->dev, "%s: insufficient size for a bytes control: %zu.\n",
+                       __func__, scontrol->max_size);
+               return -EINVAL;
        }
 
-       /* init the get/put bytes data */
        if (scontrol->priv_size > scontrol->max_size - sizeof(*cdata)) {
-               dev_err(sdev->dev, "err: bytes data size %zu exceeds max %zu.\n",
+               dev_err(sdev->dev,
+                       "%s: bytes data size %zu exceeds max %zu.\n", __func__,
                        scontrol->priv_size, scontrol->max_size - sizeof(*cdata));
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
+       scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL);
+       if (!scontrol->ipc_control_data)
+               return -ENOMEM;
+
        scontrol->size = sizeof(struct sof_ipc_ctrl_data) + scontrol->priv_size;
 
        cdata = scontrol->ipc_control_data;
index 3333a06..e006532 100644 (file)
@@ -392,7 +392,7 @@ static int mt8186_dsp_probe(struct snd_sof_dev *sdev)
                                                      PLATFORM_DEVID_NONE,
                                                      pdev, sizeof(*pdev));
        if (IS_ERR(priv->ipc_dev)) {
-               ret = IS_ERR(priv->ipc_dev);
+               ret = PTR_ERR(priv->ipc_dev);
                dev_err(sdev->dev, "failed to create mtk-adsp-ipc device\n");
                goto err_adsp_off;
        }
index 18eb327..df740be 100644 (file)
@@ -23,6 +23,9 @@ static u32 snd_sof_dsp_power_target(struct snd_sof_dev *sdev)
        u32 target_dsp_state;
 
        switch (sdev->system_suspend_target) {
+       case SOF_SUSPEND_S5:
+       case SOF_SUSPEND_S4:
+               /* DSP should be in D3 if the system is suspending to S3+ */
        case SOF_SUSPEND_S3:
                /* DSP should be in D3 if the system is suspending to S3 */
                target_dsp_state = SOF_DSP_PM_D3;
@@ -335,8 +338,24 @@ int snd_sof_prepare(struct device *dev)
                return 0;
 
 #if defined(CONFIG_ACPI)
-       if (acpi_target_system_state() == ACPI_STATE_S0)
+       switch (acpi_target_system_state()) {
+       case ACPI_STATE_S0:
                sdev->system_suspend_target = SOF_SUSPEND_S0IX;
+               break;
+       case ACPI_STATE_S1:
+       case ACPI_STATE_S2:
+       case ACPI_STATE_S3:
+               sdev->system_suspend_target = SOF_SUSPEND_S3;
+               break;
+       case ACPI_STATE_S4:
+               sdev->system_suspend_target = SOF_SUSPEND_S4;
+               break;
+       case ACPI_STATE_S5:
+               sdev->system_suspend_target = SOF_SUSPEND_S5;
+               break;
+       default:
+               break;
+       }
 #endif
 
        return 0;
index 9d7f53f..f0f3d72 100644 (file)
@@ -85,6 +85,8 @@ enum sof_system_suspend_state {
        SOF_SUSPEND_NONE = 0,
        SOF_SUSPEND_S0IX,
        SOF_SUSPEND_S3,
+       SOF_SUSPEND_S4,
+       SOF_SUSPEND_S5,
 };
 
 enum sof_dfsentry_type {
index 4f56e17..f93201a 100644 (file)
@@ -3802,6 +3802,54 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
+/*
+ * MacroSilicon MS2100/MS2106 based AV capture cards
+ *
+ * These claim 96kHz 1ch in the descriptors, but are actually 48kHz 2ch.
+ * They also need QUIRK_FLAG_ALIGN_TRANSFER, which makes one wonder if
+ * they pretend to be 96kHz mono as a workaround for stereo being broken
+ * by that...
+ *
+ * They also have an issue with initial stream alignment that causes the
+ * channels to be swapped and out of phase, which is dealt with in quirks.c.
+ */
+{
+       USB_AUDIO_DEVICE(0x534d, 0x0021),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "MacroSilicon",
+               .product_name = "MS210x",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = &(const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_MIXER,
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+                                       .channels = 2,
+                                       .iface = 3,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = 0,
+                                       .endpoint = 0x82,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                               USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_CONTINUOUS,
+                                       .rate_min = 48000,
+                                       .rate_max = 48000,
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+
 /*
  * MacroSilicon MS2109 based HDMI capture cards
  *
@@ -4119,6 +4167,206 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       /*
+        * Fiero SC-01 (firmware v1.0.0 @ 48 kHz)
+        */
+       USB_DEVICE(0x2b53, 0x0023),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "Fiero",
+               .product_name = "SC-01",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = &(const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       /* Playback */
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+                                       .iface = 1,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x01,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                                  USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_48000,
+                                       .rate_min = 48000,
+                                       .rate_max = 48000,
+                                       .nr_rates = 1,
+                                       .rate_table = (unsigned int[]) { 48000 },
+                                       .clock = 0x29
+                               }
+                       },
+                       /* Capture */
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+                                       .iface = 2,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x82,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                                  USB_ENDPOINT_SYNC_ASYNC |
+                                                  USB_ENDPOINT_USAGE_IMPLICIT_FB,
+                                       .rates = SNDRV_PCM_RATE_48000,
+                                       .rate_min = 48000,
+                                       .rate_max = 48000,
+                                       .nr_rates = 1,
+                                       .rate_table = (unsigned int[]) { 48000 },
+                                       .clock = 0x29
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+{
+       /*
+        * Fiero SC-01 (firmware v1.0.0 @ 96 kHz)
+        */
+       USB_DEVICE(0x2b53, 0x0024),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "Fiero",
+               .product_name = "SC-01",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = &(const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       /* Playback */
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+                                       .iface = 1,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x01,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                                  USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_96000,
+                                       .rate_min = 96000,
+                                       .rate_max = 96000,
+                                       .nr_rates = 1,
+                                       .rate_table = (unsigned int[]) { 96000 },
+                                       .clock = 0x29
+                               }
+                       },
+                       /* Capture */
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+                                       .iface = 2,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x82,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                                  USB_ENDPOINT_SYNC_ASYNC |
+                                                  USB_ENDPOINT_USAGE_IMPLICIT_FB,
+                                       .rates = SNDRV_PCM_RATE_96000,
+                                       .rate_min = 96000,
+                                       .rate_max = 96000,
+                                       .nr_rates = 1,
+                                       .rate_table = (unsigned int[]) { 96000 },
+                                       .clock = 0x29
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+{
+       /*
+        * Fiero SC-01 (firmware v1.1.0)
+        */
+       USB_DEVICE(0x2b53, 0x0031),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "Fiero",
+               .product_name = "SC-01",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = &(const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       /* Playback */
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+                                       .iface = 1,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x01,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                                  USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_48000 |
+                                                SNDRV_PCM_RATE_96000,
+                                       .rate_min = 48000,
+                                       .rate_max = 96000,
+                                       .nr_rates = 2,
+                                       .rate_table = (unsigned int[]) { 48000, 96000 },
+                                       .clock = 0x29
+                               }
+                       },
+                       /* Capture */
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 2,
+                                       .fmt_bits = 24,
+                                       .iface = 2,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x82,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                                  USB_ENDPOINT_SYNC_ASYNC |
+                                                  USB_ENDPOINT_USAGE_IMPLICIT_FB,
+                                       .rates = SNDRV_PCM_RATE_48000 |
+                                                SNDRV_PCM_RATE_96000,
+                                       .rate_min = 48000,
+                                       .rate_max = 96000,
+                                       .nr_rates = 2,
+                                       .rate_table = (unsigned int[]) { 48000, 96000 },
+                                       .clock = 0x29
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 
 #undef USB_DEVICE_VENDOR_SPEC
 #undef USB_AUDIO_DEVICE
index e8468f9..968d90c 100644 (file)
@@ -1478,6 +1478,7 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
        case USB_ID(0x041e, 0x3f19): /* E-Mu 0204 USB */
                set_format_emu_quirk(subs, fmt);
                break;
+       case USB_ID(0x534d, 0x0021): /* MacroSilicon MS2100/MS2106 */
        case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */
                subs->stream_offset_adj = 2;
                break;
@@ -1842,6 +1843,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
        DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */
                   QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x1397, 0x0508, /* Behringer UMC204HD */
+                  QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+       DEVICE_FLG(0x1397, 0x0509, /* Behringer UMC404HD */
+                  QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
        DEVICE_FLG(0x13e5, 0x0001, /* Serato Phono */
                   QUIRK_FLAG_IGNORE_CTL_ERROR),
        DEVICE_FLG(0x154e, 0x1002, /* Denon DCD-1500RE */
@@ -1904,10 +1909,18 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_IGNORE_CTL_ERROR),
        DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
                   QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x534d, 0x0021, /* MacroSilicon MS2100/MS2106 */
+                  QUIRK_FLAG_ALIGN_TRANSFER),
        DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */
                   QUIRK_FLAG_ALIGN_TRANSFER),
        DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
                   QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */
+                  QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+       DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */
+                  QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+       DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */
+                  QUIRK_FLAG_GENERIC_IMPLICIT_FB),
 
        /* Vendor matches */
        VENDOR_FLG(0x045e, /* MS Lifecam */
index c1b6ddc..3bb1343 100644 (file)
@@ -139,8 +139,10 @@ struct kvm_guest_debug_arch {
        __u64 dbg_wvr[KVM_ARM_MAX_DBG_REGS];
 };
 
+#define KVM_DEBUG_ARCH_HSR_HIGH_VALID  (1 << 0)
 struct kvm_debug_exit_arch {
        __u32 hsr;
+       __u32 hsr_high; /* ESR_EL2[61:32] */
        __u64 far;      /* used for watchpoints */
 };
 
@@ -332,6 +334,40 @@ struct kvm_arm_copy_mte_tags {
 #define KVM_ARM64_SVE_VLS_WORDS        \
        ((KVM_ARM64_SVE_VQ_MAX - KVM_ARM64_SVE_VQ_MIN) / 64 + 1)
 
+/* Bitmap feature firmware registers */
+#define KVM_REG_ARM_FW_FEAT_BMAP               (0x0016 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_FW_FEAT_BMAP_REG(r)                (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
+                                               KVM_REG_ARM_FW_FEAT_BMAP |      \
+                                               ((r) & 0xffff))
+
+#define KVM_REG_ARM_STD_BMAP                   KVM_REG_ARM_FW_FEAT_BMAP_REG(0)
+
+enum {
+       KVM_REG_ARM_STD_BIT_TRNG_V1_0   = 0,
+#ifdef __KERNEL__
+       KVM_REG_ARM_STD_BMAP_BIT_COUNT,
+#endif
+};
+
+#define KVM_REG_ARM_STD_HYP_BMAP               KVM_REG_ARM_FW_FEAT_BMAP_REG(1)
+
+enum {
+       KVM_REG_ARM_STD_HYP_BIT_PV_TIME = 0,
+#ifdef __KERNEL__
+       KVM_REG_ARM_STD_HYP_BMAP_BIT_COUNT,
+#endif
+};
+
+#define KVM_REG_ARM_VENDOR_HYP_BMAP            KVM_REG_ARM_FW_FEAT_BMAP_REG(2)
+
+enum {
+       KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT    = 0,
+       KVM_REG_ARM_VENDOR_HYP_BIT_PTP          = 1,
+#ifdef __KERNEL__
+       KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_COUNT,
+#endif
+};
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR      0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
index 6a184d2..5088bd9 100644 (file)
@@ -444,6 +444,9 @@ struct kvm_run {
 #define KVM_SYSTEM_EVENT_SHUTDOWN       1
 #define KVM_SYSTEM_EVENT_RESET          2
 #define KVM_SYSTEM_EVENT_CRASH          3
+#define KVM_SYSTEM_EVENT_WAKEUP         4
+#define KVM_SYSTEM_EVENT_SUSPEND        5
+#define KVM_SYSTEM_EVENT_SEV_TERM       6
                        __u32 type;
                        __u32 ndata;
                        union {
@@ -646,6 +649,7 @@ struct kvm_vapic_addr {
 #define KVM_MP_STATE_OPERATING         7
 #define KVM_MP_STATE_LOAD              8
 #define KVM_MP_STATE_AP_RESET_HOLD     9
+#define KVM_MP_STATE_SUSPENDED         10
 
 struct kvm_mp_state {
        __u32 mp_state;
@@ -1150,8 +1154,9 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_S390_MEM_OP_EXTENSION 211
 #define KVM_CAP_PMU_CAPABILITY 212
 #define KVM_CAP_DISABLE_QUIRKS2 213
-/* #define KVM_CAP_VM_TSC_CONTROL 214 */
+#define KVM_CAP_VM_TSC_CONTROL 214
 #define KVM_CAP_SYSTEM_EVENT_DATA 215
+#define KVM_CAP_ARM_SYSTEM_SUSPEND 216
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1240,6 +1245,7 @@ struct kvm_x86_mce {
 #define KVM_XEN_HVM_CONFIG_SHARED_INFO         (1 << 2)
 #define KVM_XEN_HVM_CONFIG_RUNSTATE            (1 << 3)
 #define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL       (1 << 4)
+#define KVM_XEN_HVM_CONFIG_EVTCHN_SEND         (1 << 5)
 
 struct kvm_xen_hvm_config {
        __u32 flags;
@@ -1478,7 +1484,8 @@ struct kvm_s390_ucas_mapping {
 #define KVM_SET_PIT2              _IOW(KVMIO,  0xa0, struct kvm_pit_state2)
 /* Available with KVM_CAP_PPC_GET_PVINFO */
 #define KVM_PPC_GET_PVINFO       _IOW(KVMIO,  0xa1, struct kvm_ppc_pvinfo)
-/* Available with KVM_CAP_TSC_CONTROL */
+/* Available with KVM_CAP_TSC_CONTROL for a vCPU, or with
+*  KVM_CAP_VM_TSC_CONTROL to set defaults for a VM */
 #define KVM_SET_TSC_KHZ           _IO(KVMIO,  0xa2)
 #define KVM_GET_TSC_KHZ           _IO(KVMIO,  0xa3)
 /* Available with KVM_CAP_PCI_2_3 */
@@ -1694,6 +1701,32 @@ struct kvm_xen_hvm_attr {
                struct {
                        __u64 gfn;
                } shared_info;
+               struct {
+                       __u32 send_port;
+                       __u32 type; /* EVTCHNSTAT_ipi / EVTCHNSTAT_interdomain */
+                       __u32 flags;
+#define KVM_XEN_EVTCHN_DEASSIGN                (1 << 0)
+#define KVM_XEN_EVTCHN_UPDATE          (1 << 1)
+#define KVM_XEN_EVTCHN_RESET           (1 << 2)
+                       /*
+                        * Events sent by the guest are either looped back to
+                        * the guest itself (potentially on a different port#)
+                        * or signalled via an eventfd.
+                        */
+                       union {
+                               struct {
+                                       __u32 port;
+                                       __u32 vcpu;
+                                       __u32 priority;
+                               } port;
+                               struct {
+                                       __u32 port; /* Zero for eventfd */
+                                       __s32 fd;
+                               } eventfd;
+                               __u32 padding[4];
+                       } deliver;
+               } evtchn;
+               __u32 xen_version;
                __u64 pad[8];
        } u;
 };
@@ -1702,11 +1735,17 @@ struct kvm_xen_hvm_attr {
 #define KVM_XEN_ATTR_TYPE_LONG_MODE            0x0
 #define KVM_XEN_ATTR_TYPE_SHARED_INFO          0x1
 #define KVM_XEN_ATTR_TYPE_UPCALL_VECTOR                0x2
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */
+#define KVM_XEN_ATTR_TYPE_EVTCHN               0x3
+#define KVM_XEN_ATTR_TYPE_XEN_VERSION          0x4
 
 /* Per-vCPU Xen attributes */
 #define KVM_XEN_VCPU_GET_ATTR  _IOWR(KVMIO, 0xca, struct kvm_xen_vcpu_attr)
 #define KVM_XEN_VCPU_SET_ATTR  _IOW(KVMIO,  0xcb, struct kvm_xen_vcpu_attr)
 
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */
+#define KVM_XEN_HVM_EVTCHN_SEND        _IOW(KVMIO,  0xd0, struct kvm_irq_routing_xen_evtchn)
+
 #define KVM_GET_SREGS2             _IOR(KVMIO,  0xcc, struct kvm_sregs2)
 #define KVM_SET_SREGS2             _IOW(KVMIO,  0xcd, struct kvm_sregs2)
 
@@ -1724,6 +1763,13 @@ struct kvm_xen_vcpu_attr {
                        __u64 time_blocked;
                        __u64 time_offline;
                } runstate;
+               __u32 vcpu_id;
+               struct {
+                       __u32 port;
+                       __u32 priority;
+                       __u64 expires_ns;
+               } timer;
+               __u8 vector;
        } u;
 };
 
@@ -1734,6 +1780,10 @@ struct kvm_xen_vcpu_attr {
 #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT        0x3
 #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA   0x4
 #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */
+#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID         0x6
+#define KVM_XEN_VCPU_ATTR_TYPE_TIMER           0x7
+#define KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR   0x8
 
 /* Secure Encrypted Virtualization command */
 enum sev_cmd_id {
index 864bb9d..57153e0 100644 (file)
@@ -3826,8 +3826,7 @@ static int validate_ibt(struct objtool_file *file)
                    !strcmp(sec->name, "__bug_table")                   ||
                    !strcmp(sec->name, "__ex_table")                    ||
                    !strcmp(sec->name, "__jump_table")                  ||
-                   !strcmp(sec->name, "__mcount_loc")                  ||
-                   !strcmp(sec->name, "__tracepoints"))
+                   !strcmp(sec->name, "__mcount_loc"))
                        continue;
 
                list_for_each_entry(reloc, &sec->reloc->reloc_list, list)
index e271e05..80b1d2b 100644 (file)
@@ -149,11 +149,10 @@ get_bpf_prog_info_linear(int fd, __u64 arrays)
                count = bpf_prog_info_read_offset_u32(&info, desc->count_offset);
                size  = bpf_prog_info_read_offset_u32(&info, desc->size_offset);
 
-               data_len += count * size;
+               data_len += roundup(count * size, sizeof(__u64));
        }
 
        /* step 3: allocate continuous memory */
-       data_len = roundup(data_len, sizeof(__u64));
        info_linear = malloc(sizeof(struct perf_bpil) + data_len);
        if (!info_linear)
                return ERR_PTR(-ENOMEM);
@@ -180,7 +179,7 @@ get_bpf_prog_info_linear(int fd, __u64 arrays)
                bpf_prog_info_set_offset_u64(&info_linear->info,
                                             desc->array_offset,
                                             ptr_to_u64(ptr));
-               ptr += count * size;
+               ptr += roundup(count * size, sizeof(__u64));
        }
 
        /* step 5: call syscall again to get required arrays */
index b73e84a..f289b77 100644 (file)
@@ -265,6 +265,12 @@ int off_cpu_write(struct perf_session *session)
 
        sample_type = evsel->core.attr.sample_type;
 
+       if (sample_type & ~OFFCPU_SAMPLE_TYPES) {
+               pr_err("not supported sample type: %llx\n",
+                      (unsigned long long)sample_type);
+               return -1;
+       }
+
        if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER)) {
                if (evsel->core.id)
                        sid = evsel->core.id[0];
@@ -319,7 +325,6 @@ int off_cpu_write(struct perf_session *session)
                }
                if (sample_type & PERF_SAMPLE_CGROUP)
                        data.array[n++] = key.cgroup_id;
-               /* TODO: handle more sample types */
 
                size = n * sizeof(u64);
                data.hdr.size = size;
index 792ae28..cc6d7fd 100644 (file)
@@ -71,6 +71,11 @@ struct {
        __uint(max_entries, 1);
 } cgroup_filter SEC(".maps");
 
+/* new kernel task_struct definition */
+struct task_struct___new {
+       long __state;
+} __attribute__((preserve_access_index));
+
 /* old kernel task_struct definition */
 struct task_struct___old {
        long state;
@@ -93,14 +98,17 @@ const volatile bool uses_cgroup_v1 = false;
  */
 static inline int get_task_state(struct task_struct *t)
 {
-       if (bpf_core_field_exists(t->__state))
-               return BPF_CORE_READ(t, __state);
+       /* recast pointer to capture new type for compiler */
+       struct task_struct___new *t_new = (void *)t;
 
-       /* recast pointer to capture task_struct___old type for compiler */
-       struct task_struct___old *t_old = (void *)t;
+       if (bpf_core_field_exists(t_new->__state)) {
+               return BPF_CORE_READ(t_new, __state);
+       } else {
+               /* recast pointer to capture old type for compiler */
+               struct task_struct___old *t_old = (void *)t;
 
-       /* now use old "state" name of the field */
-       return BPF_CORE_READ(t_old, state);
+               return BPF_CORE_READ(t_old, state);
+       }
 }
 
 static inline __u64 get_cgroup_id(struct task_struct *t)
index ce499c5..094b0a9 100644 (file)
@@ -48,6 +48,7 @@
 #include "util.h"
 #include "hashmap.h"
 #include "pmu-hybrid.h"
+#include "off_cpu.h"
 #include "../perf-sys.h"
 #include "util/parse-branch-options.h"
 #include <internal/xyarray.h>
@@ -1102,6 +1103,11 @@ static void evsel__set_default_freq_period(struct record_opts *opts,
        }
 }
 
+static bool evsel__is_offcpu_event(struct evsel *evsel)
+{
+       return evsel__is_bpf_output(evsel) && !strcmp(evsel->name, OFFCPU_EVENT);
+}
+
 /*
  * The enable_on_exec/disabled value strategy:
  *
@@ -1366,6 +1372,9 @@ void evsel__config(struct evsel *evsel, struct record_opts *opts,
         */
        if (evsel__is_dummy_event(evsel))
                evsel__reset_sample_bit(evsel, BRANCH_STACK);
+
+       if (evsel__is_offcpu_event(evsel))
+               evsel->core.attr.sample_type &= OFFCPU_SAMPLE_TYPES;
 }
 
 int evsel__set_filter(struct evsel *evsel, const char *filter)
index 548008f..2dd67c6 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef PERF_UTIL_OFF_CPU_H
 #define PERF_UTIL_OFF_CPU_H
 
+#include <linux/perf_event.h>
+
 struct evlist;
 struct target;
 struct perf_session;
@@ -8,6 +10,13 @@ struct record_opts;
 
 #define OFFCPU_EVENT  "offcpu-time"
 
+#define OFFCPU_SAMPLE_TYPES  (PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_IP | \
+                             PERF_SAMPLE_TID | PERF_SAMPLE_TIME | \
+                             PERF_SAMPLE_ID | PERF_SAMPLE_CPU | \
+                             PERF_SAMPLE_PERIOD | PERF_SAMPLE_CALLCHAIN | \
+                             PERF_SAMPLE_CGROUP)
+
+
 #ifdef HAVE_BPF_SKEL
 int off_cpu_prepare(struct evlist *evlist, struct target *target,
                    struct record_opts *opts);
index 27acdc5..84d17bd 100644 (file)
@@ -754,7 +754,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
        snprintf(filename, sizeof(filename), "%s/proc/%d/task",
                 machine->root_dir, pid);
 
-       n = scandir(filename, &dirent, filter_task, alphasort);
+       n = scandir(filename, &dirent, filter_task, NULL);
        if (n < 0)
                return n;
 
@@ -767,11 +767,12 @@ static int __event__synthesize_thread(union perf_event *comm_event,
                if (*end)
                        continue;
 
-               rc = -1;
+               /* some threads may exit just after scan, ignore it */
                if (perf_event__prepare_comm(comm_event, pid, _pid, machine,
                                             &tgid, &ppid, &kernel_thread) != 0)
-                       break;
+                       continue;
 
+               rc = -1;
                if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
                                                ppid, process, machine) < 0)
                        break;
@@ -987,7 +988,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
                return 0;
 
        snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
-       n = scandir(proc_path, &dirent, filter_task, alphasort);
+       n = scandir(proc_path, &dirent, filter_task, NULL);
        if (n < 0)
                return err;
 
index 6e5b8cc..81b6bd6 100644 (file)
@@ -197,7 +197,7 @@ out_err:
 #ifndef NO_LIBUNWIND_DEBUG_FRAME
 static u64 elf_section_offset(int fd, const char *name)
 {
-       u64 address, offset;
+       u64 address, offset = 0;
 
        if (elf_section_address_and_offset(fd, name, &address, &offset))
                return 0;
index af293ea..e172d89 100644 (file)
@@ -4,6 +4,7 @@
  * Tests for sockmap/sockhash holding kTLS sockets.
  */
 
+#include <netinet/tcp.h>
 #include "test_progs.h"
 
 #define MAX_TEST_NAME 80
@@ -92,9 +93,78 @@ close_srv:
        close(srv);
 }
 
+static void test_sockmap_ktls_update_fails_when_sock_has_ulp(int family, int map)
+{
+       struct sockaddr_storage addr = {};
+       socklen_t len = sizeof(addr);
+       struct sockaddr_in6 *v6;
+       struct sockaddr_in *v4;
+       int err, s, zero = 0;
+
+       switch (family) {
+       case AF_INET:
+               v4 = (struct sockaddr_in *)&addr;
+               v4->sin_family = AF_INET;
+               break;
+       case AF_INET6:
+               v6 = (struct sockaddr_in6 *)&addr;
+               v6->sin6_family = AF_INET6;
+               break;
+       default:
+               PRINT_FAIL("unsupported socket family %d", family);
+               return;
+       }
+
+       s = socket(family, SOCK_STREAM, 0);
+       if (!ASSERT_GE(s, 0, "socket"))
+               return;
+
+       err = bind(s, (struct sockaddr *)&addr, len);
+       if (!ASSERT_OK(err, "bind"))
+               goto close;
+
+       err = getsockname(s, (struct sockaddr *)&addr, &len);
+       if (!ASSERT_OK(err, "getsockname"))
+               goto close;
+
+       err = connect(s, (struct sockaddr *)&addr, len);
+       if (!ASSERT_OK(err, "connect"))
+               goto close;
+
+       /* save sk->sk_prot and set it to tls_prots */
+       err = setsockopt(s, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls"));
+       if (!ASSERT_OK(err, "setsockopt(TCP_ULP)"))
+               goto close;
+
+       /* sockmap update should not affect saved sk_prot */
+       err = bpf_map_update_elem(map, &zero, &s, BPF_ANY);
+       if (!ASSERT_ERR(err, "sockmap update elem"))
+               goto close;
+
+       /* call sk->sk_prot->setsockopt to dispatch to saved sk_prot */
+       err = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &zero, sizeof(zero));
+       ASSERT_OK(err, "setsockopt(TCP_NODELAY)");
+
+close:
+       close(s);
+}
+
+static const char *fmt_test_name(const char *subtest_name, int family,
+                                enum bpf_map_type map_type)
+{
+       const char *map_type_str = BPF_MAP_TYPE_SOCKMAP ? "SOCKMAP" : "SOCKHASH";
+       const char *family_str = AF_INET ? "IPv4" : "IPv6";
+       static char test_name[MAX_TEST_NAME];
+
+       snprintf(test_name, MAX_TEST_NAME,
+                "sockmap_ktls %s %s %s",
+                subtest_name, family_str, map_type_str);
+
+       return test_name;
+}
+
 static void run_tests(int family, enum bpf_map_type map_type)
 {
-       char test_name[MAX_TEST_NAME];
        int map;
 
        map = bpf_map_create(map_type, NULL, sizeof(int), sizeof(int), 1, NULL);
@@ -103,14 +173,10 @@ static void run_tests(int family, enum bpf_map_type map_type)
                return;
        }
 
-       snprintf(test_name, MAX_TEST_NAME,
-                "sockmap_ktls disconnect_after_delete %s %s",
-                family == AF_INET ? "IPv4" : "IPv6",
-                map_type == BPF_MAP_TYPE_SOCKMAP ? "SOCKMAP" : "SOCKHASH");
-       if (!test__start_subtest(test_name))
-               return;
-
-       test_sockmap_ktls_disconnect_after_delete(family, map);
+       if (test__start_subtest(fmt_test_name("disconnect_after_delete", family, map_type)))
+               test_sockmap_ktls_disconnect_after_delete(family, map);
+       if (test__start_subtest(fmt_test_name("update_fails_when_sock_has_ulp", family, map_type)))
+               test_sockmap_ktls_update_fails_when_sock_has_ulp(family, map);
 
        close(map);
 }
index 6ddc418..1a27a62 100644 (file)
        .result = ACCEPT,
        .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
 },
+{
+       "jeq32/jne32: bounds checking",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_6, 563),
+       BPF_MOV64_IMM(BPF_REG_2, 0),
+       BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
+       BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
+       BPF_ALU32_REG(BPF_OR, BPF_REG_2, BPF_REG_6),
+       BPF_JMP32_IMM(BPF_JNE, BPF_REG_2, 8, 5),
+       BPF_JMP_IMM(BPF_JSGE, BPF_REG_2, 500, 2),
+       BPF_MOV64_IMM(BPF_REG_0, 2),
+       BPF_EXIT_INSN(),
+       BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
+       BPF_EXIT_INSN(),
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_EXIT_INSN(),
+       },
+       .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       .result = ACCEPT,
+       .retval = 1,
+},
index 6f951d1..497fe17 100644 (file)
        .result = ACCEPT,
        .retval = 3,
 },
+{
+       "jump & dead code elimination",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_MOV64_IMM(BPF_REG_3, 0),
+       BPF_ALU64_IMM(BPF_NEG, BPF_REG_3, 0),
+       BPF_ALU64_IMM(BPF_NEG, BPF_REG_3, 0),
+       BPF_ALU64_IMM(BPF_OR, BPF_REG_3, 32767),
+       BPF_JMP_IMM(BPF_JSGE, BPF_REG_3, 0, 1),
+       BPF_EXIT_INSN(),
+       BPF_JMP_IMM(BPF_JSLE, BPF_REG_3, 0x8000, 1),
+       BPF_EXIT_INSN(),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, -32767),
+       BPF_MOV64_IMM(BPF_REG_0, 2),
+       BPF_JMP_IMM(BPF_JLE, BPF_REG_3, 0, 1),
+       BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
+       BPF_EXIT_INSN(),
+       },
+       .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       .result = ACCEPT,
+       .retval = 2,
+},
index 7ea54af..ddad703 100644 (file)
@@ -54,7 +54,7 @@ TEST_GEN_FILES += ipsec
 TEST_GEN_FILES += ioam6_parser
 TEST_GEN_FILES += gro
 TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
-TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls
+TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls tun
 TEST_GEN_FILES += toeplitz
 TEST_GEN_FILES += cmsg_sender
 TEST_GEN_FILES += stress_reuseport_listen
index 8a69c91..8ccaf87 100644 (file)
@@ -2,7 +2,7 @@
 
 CLANG ?= clang
 CCINCLUDE += -I../../bpf
-CCINCLUDE += -I../../../lib
+CCINCLUDE += -I../../../../lib
 CCINCLUDE += -I../../../../../usr/include/
 
 TEST_CUSTOM_PROGS = $(OUTPUT)/bpf/nat6to4.o
index 37ae49d..3ffb9d6 100755 (executable)
@@ -1240,6 +1240,7 @@ learning_test()
        # FDB entry was installed.
        bridge link set dev $br_port1 flood off
 
+       ip link set $host1_if promisc on
        tc qdisc add dev $host1_if ingress
        tc filter add dev $host1_if ingress protocol ip pref 1 handle 101 \
                flower dst_mac $mac action drop
@@ -1250,7 +1251,7 @@ learning_test()
        tc -j -s filter show dev $host1_if ingress \
                | jq -e ".[] | select(.options.handle == 101) \
                | select(.options.actions[0].stats.packets == 1)" &> /dev/null
-       check_fail $? "Packet reached second host when should not"
+       check_fail $? "Packet reached first host when should not"
 
        $MZ $host1_if -c 1 -p 64 -a $mac -t ip -q
        sleep 1
@@ -1289,6 +1290,7 @@ learning_test()
 
        tc filter del dev $host1_if ingress protocol ip pref 1 handle 101 flower
        tc qdisc del dev $host1_if ingress
+       ip link set $host1_if promisc off
 
        bridge link set dev $br_port1 flood on
 
@@ -1306,6 +1308,7 @@ flood_test_do()
 
        # Add an ACL on `host2_if` which will tell us whether the packet
        # was flooded to it or not.
+       ip link set $host2_if promisc on
        tc qdisc add dev $host2_if ingress
        tc filter add dev $host2_if ingress protocol ip pref 1 handle 101 \
                flower dst_mac $mac action drop
@@ -1323,6 +1326,7 @@ flood_test_do()
 
        tc filter del dev $host2_if ingress protocol ip pref 1 handle 101 flower
        tc qdisc del dev $host2_if ingress
+       ip link set $host2_if promisc off
 
        return $err
 }
index 9dd43d7..515859a 100755 (executable)
@@ -61,6 +61,39 @@ chk_msk_nr()
        __chk_nr "grep -c token:" $*
 }
 
+wait_msk_nr()
+{
+       local condition="grep -c token:"
+       local expected=$1
+       local timeout=20
+       local msg nr
+       local max=0
+       local i=0
+
+       shift 1
+       msg=$*
+
+       while [ $i -lt $timeout ]; do
+               nr=$(ss -inmHMN $ns | $condition)
+               [ $nr == $expected ] && break;
+               [ $nr -gt $max ] && max=$nr
+               i=$((i + 1))
+               sleep 1
+       done
+
+       printf "%-50s" "$msg"
+       if [ $i -ge $timeout ]; then
+               echo "[ fail ] timeout while expecting $expected max $max last $nr"
+               ret=$test_cnt
+       elif [ $nr != $expected ]; then
+               echo "[ fail ] expected $expected found $nr"
+               ret=$test_cnt
+       else
+               echo "[  ok  ]"
+       fi
+       test_cnt=$((test_cnt+1))
+}
+
 chk_msk_fallback_nr()
 {
                __chk_nr "grep -c fallback" $*
@@ -146,7 +179,7 @@ ip -n $ns link set dev lo up
 echo "a" | \
        timeout ${timeout_test} \
                ip netns exec $ns \
-                       ./mptcp_connect -p 10000 -l -t ${timeout_poll} \
+                       ./mptcp_connect -p 10000 -l -t ${timeout_poll} -w 20 \
                                0.0.0.0 >/dev/null &
 wait_local_port_listen $ns 10000
 chk_msk_nr 0 "no msk on netns creation"
@@ -155,7 +188,7 @@ chk_msk_listen 10000
 echo "b" | \
        timeout ${timeout_test} \
                ip netns exec $ns \
-                       ./mptcp_connect -p 10000 -r 0 -t ${timeout_poll} \
+                       ./mptcp_connect -p 10000 -r 0 -t ${timeout_poll} -w 20 \
                                127.0.0.1 >/dev/null &
 wait_connected $ns 10000
 chk_msk_nr 2 "after MPC handshake "
@@ -167,13 +200,13 @@ flush_pids
 echo "a" | \
        timeout ${timeout_test} \
                ip netns exec $ns \
-                       ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} \
+                       ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} -w 20 \
                                0.0.0.0 >/dev/null &
 wait_local_port_listen $ns 10001
 echo "b" | \
        timeout ${timeout_test} \
                ip netns exec $ns \
-                       ./mptcp_connect -p 10001 -r 0 -t ${timeout_poll} \
+                       ./mptcp_connect -p 10001 -r 0 -t ${timeout_poll} -w 20 \
                                127.0.0.1 >/dev/null &
 wait_connected $ns 10001
 chk_msk_fallback_nr 1 "check fallback"
@@ -184,7 +217,7 @@ for I in `seq 1 $NR_CLIENTS`; do
        echo "a" | \
                timeout ${timeout_test} \
                        ip netns exec $ns \
-                               ./mptcp_connect -p $((I+10001)) -l -w 10 \
+                               ./mptcp_connect -p $((I+10001)) -l -w 20 \
                                        -t ${timeout_poll} 0.0.0.0 >/dev/null &
 done
 wait_local_port_listen $ns $((NR_CLIENTS + 10001))
@@ -193,12 +226,11 @@ for I in `seq 1 $NR_CLIENTS`; do
        echo "b" | \
                timeout ${timeout_test} \
                        ip netns exec $ns \
-                               ./mptcp_connect -p $((I+10001)) -w 10 \
+                               ./mptcp_connect -p $((I+10001)) -w 20 \
                                        -t ${timeout_poll} 127.0.0.1 >/dev/null &
 done
-sleep 1.5
 
-chk_msk_nr $((NR_CLIENTS*2)) "many msk socket present"
+wait_msk_nr $((NR_CLIENTS*2)) "many msk socket present"
 flush_pids
 
 exit $ret
index 8628aa6..e2ea6c1 100644 (file)
@@ -265,7 +265,7 @@ static void sock_test_tcpulp(int sock, int proto, unsigned int line)
 static int sock_listen_mptcp(const char * const listenaddr,
                             const char * const port)
 {
-       int sock;
+       int sock = -1;
        struct addrinfo hints = {
                .ai_protocol = IPPROTO_TCP,
                .ai_socktype = SOCK_STREAM,
index 29f75e2..8672d89 100644 (file)
@@ -88,7 +88,7 @@ static void xgetaddrinfo(const char *node, const char *service,
 static int sock_listen_mptcp(const char * const listenaddr,
                             const char * const port)
 {
-       int sock;
+       int sock = -1;
        struct addrinfo hints = {
                .ai_protocol = IPPROTO_TCP,
                .ai_socktype = SOCK_STREAM,
index ac9a4d9..ae61f39 100644 (file)
@@ -136,7 +136,7 @@ static void xgetaddrinfo(const char *node, const char *service,
 static int sock_listen_mptcp(const char * const listenaddr,
                             const char * const port)
 {
-       int sock;
+       int sock = -1;
        struct addrinfo hints = {
                .ai_protocol = IPPROTO_TCP,
                .ai_socktype = SOCK_STREAM,
index 6a2f4b9..cb79f07 100644 (file)
@@ -39,7 +39,7 @@ static void syntax(char *argv[])
        fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n");
        fprintf(stderr, "\tdel <id> [<ip>]\n");
        fprintf(stderr, "\tget <id>\n");
-       fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>]\n");
+       fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>] [token <token>] [rip <ip>] [rport <port>]\n");
        fprintf(stderr, "\tflush\n");
        fprintf(stderr, "\tdump\n");
        fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
@@ -1279,7 +1279,10 @@ int set_flags(int fd, int pm_family, int argc, char *argv[])
        struct rtattr *rta, *nest;
        struct nlmsghdr *nh;
        u_int32_t flags = 0;
+       u_int32_t token = 0;
+       u_int16_t rport = 0;
        u_int16_t family;
+       void *rip = NULL;
        int nest_start;
        int use_id = 0;
        u_int8_t id;
@@ -1339,7 +1342,13 @@ int set_flags(int fd, int pm_family, int argc, char *argv[])
                error(1, 0, " missing flags keyword");
 
        for (; arg < argc; arg++) {
-               if (!strcmp(argv[arg], "flags")) {
+               if (!strcmp(argv[arg], "token")) {
+                       if (++arg >= argc)
+                               error(1, 0, " missing token value");
+
+                       /* token */
+                       token = atoi(argv[arg]);
+               } else if (!strcmp(argv[arg], "flags")) {
                        char *tok, *str;
 
                        /* flags */
@@ -1378,12 +1387,72 @@ int set_flags(int fd, int pm_family, int argc, char *argv[])
                        rta->rta_len = RTA_LENGTH(2);
                        memcpy(RTA_DATA(rta), &port, 2);
                        off += NLMSG_ALIGN(rta->rta_len);
+               } else if (!strcmp(argv[arg], "rport")) {
+                       if (++arg >= argc)
+                               error(1, 0, " missing remote port");
+
+                       rport = atoi(argv[arg]);
+               } else if (!strcmp(argv[arg], "rip")) {
+                       if (++arg >= argc)
+                               error(1, 0, " missing remote ip");
+
+                       rip = argv[arg];
                } else {
                        error(1, 0, "unknown keyword %s", argv[arg]);
                }
        }
        nest->rta_len = off - nest_start;
 
+       /* token */
+       if (token) {
+               rta = (void *)(data + off);
+               rta->rta_type = MPTCP_PM_ATTR_TOKEN;
+               rta->rta_len = RTA_LENGTH(4);
+               memcpy(RTA_DATA(rta), &token, 4);
+               off += NLMSG_ALIGN(rta->rta_len);
+       }
+
+       /* remote addr/port */
+       if (rip) {
+               nest_start = off;
+               nest = (void *)(data + off);
+               nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR_REMOTE;
+               nest->rta_len = RTA_LENGTH(0);
+               off += NLMSG_ALIGN(nest->rta_len);
+
+               /* addr data */
+               rta = (void *)(data + off);
+               if (inet_pton(AF_INET, rip, RTA_DATA(rta))) {
+                       family = AF_INET;
+                       rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
+                       rta->rta_len = RTA_LENGTH(4);
+               } else if (inet_pton(AF_INET6, rip, RTA_DATA(rta))) {
+                       family = AF_INET6;
+                       rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
+                       rta->rta_len = RTA_LENGTH(16);
+               } else {
+                       error(1, errno, "can't parse ip %s", (char *)rip);
+               }
+               off += NLMSG_ALIGN(rta->rta_len);
+
+               /* family */
+               rta = (void *)(data + off);
+               rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
+               rta->rta_len = RTA_LENGTH(2);
+               memcpy(RTA_DATA(rta), &family, 2);
+               off += NLMSG_ALIGN(rta->rta_len);
+
+               if (rport) {
+                       rta = (void *)(data + off);
+                       rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
+                       rta->rta_len = RTA_LENGTH(2);
+                       memcpy(RTA_DATA(rta), &rport, 2);
+                       off += NLMSG_ALIGN(rta->rta_len);
+               }
+
+               nest->rta_len = off - nest_start;
+       }
+
        do_nl_req(fd, nh, off, 0);
        return 0;
 }
index 78d0bb6..abe3d4e 100755 (executable)
@@ -770,10 +770,42 @@ test_subflows()
        rm -f "$evts"
 }
 
+test_prio()
+{
+       local count
+
+       # Send MP_PRIO signal from client to server machine
+       ip netns exec "$ns2" ./pm_nl_ctl set 10.0.1.2 port "$client4_port" flags backup token "$client4_token" rip 10.0.1.1 rport "$server4_port"
+       sleep 0.5
+
+       # Check TX
+       stdbuf -o0 -e0 printf "MP_PRIO TX                                                 \t"
+       count=$(ip netns exec "$ns2" nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}')
+       [ -z "$count" ] && count=0
+       if [ $count != 1 ]; then
+               stdbuf -o0 -e0 printf "[FAIL]\n"
+               exit 1
+       else
+               stdbuf -o0 -e0 printf "[OK]\n"
+       fi
+
+       # Check RX
+       stdbuf -o0 -e0 printf "MP_PRIO RX                                                 \t"
+       count=$(ip netns exec "$ns1" nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}')
+       [ -z "$count" ] && count=0
+       if [ $count != 1 ]; then
+               stdbuf -o0 -e0 printf "[FAIL]\n"
+               exit 1
+       else
+               stdbuf -o0 -e0 printf "[OK]\n"
+       fi
+}
+
 make_connection
 make_connection "v6"
 test_announce
 test_remove
 test_subflows
+test_prio
 
 exit 0
diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/net/tun.c
new file mode 100644 (file)
index 0000000..fa83918
--- /dev/null
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include "../kselftest_harness.h"
+
+static int tun_attach(int fd, char *dev)
+{
+       struct ifreq ifr;
+
+       memset(&ifr, 0, sizeof(ifr));
+       strcpy(ifr.ifr_name, dev);
+       ifr.ifr_flags = IFF_ATTACH_QUEUE;
+
+       return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
+}
+
+static int tun_detach(int fd, char *dev)
+{
+       struct ifreq ifr;
+
+       memset(&ifr, 0, sizeof(ifr));
+       strcpy(ifr.ifr_name, dev);
+       ifr.ifr_flags = IFF_DETACH_QUEUE;
+
+       return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
+}
+
+static int tun_alloc(char *dev)
+{
+       struct ifreq ifr;
+       int fd, err;
+
+       fd = open("/dev/net/tun", O_RDWR);
+       if (fd < 0) {
+               fprintf(stderr, "can't open tun: %s\n", strerror(errno));
+               return fd;
+       }
+
+       memset(&ifr, 0, sizeof(ifr));
+       strcpy(ifr.ifr_name, dev);
+       ifr.ifr_flags = IFF_TAP | IFF_NAPI | IFF_MULTI_QUEUE;
+
+       err = ioctl(fd, TUNSETIFF, (void *) &ifr);
+       if (err < 0) {
+               fprintf(stderr, "can't TUNSETIFF: %s\n", strerror(errno));
+               close(fd);
+               return err;
+       }
+       strcpy(dev, ifr.ifr_name);
+       return fd;
+}
+
+static int tun_delete(char *dev)
+{
+       struct {
+               struct nlmsghdr  nh;
+               struct ifinfomsg ifm;
+               unsigned char    data[64];
+       } req;
+       struct rtattr *rta;
+       int ret, rtnl;
+
+       rtnl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+       if (rtnl < 0) {
+               fprintf(stderr, "can't open rtnl: %s\n", strerror(errno));
+               return 1;
+       }
+
+       memset(&req, 0, sizeof(req));
+       req.nh.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.ifm)));
+       req.nh.nlmsg_flags = NLM_F_REQUEST;
+       req.nh.nlmsg_type = RTM_DELLINK;
+
+       req.ifm.ifi_family = AF_UNSPEC;
+
+       rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nh.nlmsg_len));
+       rta->rta_type = IFLA_IFNAME;
+       rta->rta_len = RTA_LENGTH(IFNAMSIZ);
+       req.nh.nlmsg_len += rta->rta_len;
+       memcpy(RTA_DATA(rta), dev, IFNAMSIZ);
+
+       ret = send(rtnl, &req, req.nh.nlmsg_len, 0);
+       if (ret < 0)
+               fprintf(stderr, "can't send: %s\n", strerror(errno));
+       ret = (unsigned int)ret != req.nh.nlmsg_len;
+
+       close(rtnl);
+       return ret;
+}
+
+FIXTURE(tun)
+{
+       char ifname[IFNAMSIZ];
+       int fd, fd2;
+};
+
+FIXTURE_SETUP(tun)
+{
+       memset(self->ifname, 0, sizeof(self->ifname));
+
+       self->fd = tun_alloc(self->ifname);
+       ASSERT_GE(self->fd, 0);
+
+       self->fd2 = tun_alloc(self->ifname);
+       ASSERT_GE(self->fd2, 0);
+}
+
+FIXTURE_TEARDOWN(tun)
+{
+       if (self->fd >= 0)
+               close(self->fd);
+       if (self->fd2 >= 0)
+               close(self->fd2);
+}
+
+TEST_F(tun, delete_detach_close) {
+       EXPECT_EQ(tun_delete(self->ifname), 0);
+       EXPECT_EQ(tun_detach(self->fd, self->ifname), -1);
+       EXPECT_EQ(errno, 22);
+}
+
+TEST_F(tun, detach_delete_close) {
+       EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
+       EXPECT_EQ(tun_delete(self->ifname), 0);
+}
+
+TEST_F(tun, detach_close_delete) {
+       EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
+       close(self->fd);
+       self->fd = -1;
+       EXPECT_EQ(tun_delete(self->ifname), 0);
+}
+
+TEST_F(tun, reattach_delete_close) {
+       EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
+       EXPECT_EQ(tun_attach(self->fd, self->ifname), 0);
+       EXPECT_EQ(tun_delete(self->ifname), 0);
+}
+
+TEST_F(tun, reattach_close_delete) {
+       EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
+       EXPECT_EQ(tun_attach(self->fd, self->ifname), 0);
+       close(self->fd);
+       self->fd = -1;
+       EXPECT_EQ(tun_delete(self->ifname), 0);
+}
+
+TEST_HARNESS_MAIN
index f8a19f5..ebbd0b2 100755 (executable)
@@ -34,7 +34,7 @@ cfg_veth() {
        ip -netns "${PEER_NS}" addr add dev veth1 192.168.1.1/24
        ip -netns "${PEER_NS}" addr add dev veth1 2001:db8::1/64 nodad
        ip -netns "${PEER_NS}" link set dev veth1 up
-       ip -n "${PEER_NS}" link set veth1 xdp object ../bpf/xdp_dummy.o section xdp_dummy
+       ip -n "${PEER_NS}" link set veth1 xdp object ../bpf/xdp_dummy.o section xdp
 }
 
 run_one() {
index 820bc50..fad2d1a 100755 (executable)
@@ -34,7 +34,7 @@ run_one() {
        ip -netns "${PEER_NS}" addr add dev veth1 2001:db8::1/64 nodad
        ip -netns "${PEER_NS}" link set dev veth1 up
 
-       ip -n "${PEER_NS}" link set veth1 xdp object ../bpf/xdp_dummy.o section xdp_dummy
+       ip -n "${PEER_NS}" link set veth1 xdp object ../bpf/xdp_dummy.o section xdp
        ip netns exec "${PEER_NS}" ./udpgso_bench_rx ${rx_args} -r &
        ip netns exec "${PEER_NS}" ./udpgso_bench_rx -t ${rx_args} -r &
 
index 807b74c..832c738 100755 (executable)
@@ -36,7 +36,7 @@ run_one() {
        ip netns exec "${PEER_NS}" ethtool -K veth1 rx-gro-list on
 
 
-       ip -n "${PEER_NS}" link set veth1 xdp object ../bpf/xdp_dummy.o section xdp_dummy
+       ip -n "${PEER_NS}" link set veth1 xdp object ../bpf/xdp_dummy.o section xdp
        tc -n "${PEER_NS}" qdisc add dev veth1 clsact
        tc -n "${PEER_NS}" filter add dev veth1 ingress prio 4 protocol ipv6 bpf object-file ../bpf/nat6to4.o section schedcls/ingress6/nat_6  direct-action
        tc -n "${PEER_NS}" filter add dev veth1 egress prio 4 protocol ip bpf object-file ../bpf/nat6to4.o section schedcls/egress4/snat4 direct-action
index 6f05e06..1bcd82e 100755 (executable)
@@ -46,7 +46,7 @@ create_ns() {
                ip -n $BASE$ns addr add dev veth$ns $BM_NET_V4$ns/24
                ip -n $BASE$ns addr add dev veth$ns $BM_NET_V6$ns/64 nodad
        done
-       ip -n $NS_DST link set veth$DST xdp object ../bpf/xdp_dummy.o section xdp_dummy 2>/dev/null
+       ip -n $NS_DST link set veth$DST xdp object ../bpf/xdp_dummy.o section xdp 2>/dev/null
 }
 
 create_vxlan_endpoint() {
index 80b5d35..dc932fd 100755 (executable)
@@ -120,7 +120,7 @@ run_all() {
        run_udp "${ipv4_args}"
 
        echo "ipv6"
-       run_tcp "${ipv4_args}"
+       run_tcp "${ipv6_args}"
        run_udp "${ipv6_args}"
 }
 
index 19eac3e..430895d 100755 (executable)
@@ -289,14 +289,14 @@ if [ $CPUS -gt 1 ]; then
        ip netns exec $NS_SRC ethtool -L veth$SRC rx 1 tx 2 2>/dev/null
        printf "%-60s" "bad setting: XDP with RX nr less than TX"
        ip -n $NS_DST link set dev veth$DST xdp object ../bpf/xdp_dummy.o \
-               section xdp_dummy 2>/dev/null &&\
+               section xdp 2>/dev/null &&\
                echo "fail - set operation successful ?!?" || echo " ok "
 
        # the following tests will run with multiple channels active
        ip netns exec $NS_SRC ethtool -L veth$SRC rx 2
        ip netns exec $NS_DST ethtool -L veth$DST rx 2
        ip -n $NS_DST link set dev veth$DST xdp object ../bpf/xdp_dummy.o \
-               section xdp_dummy 2>/dev/null
+               section xdp 2>/dev/null
        printf "%-60s" "bad setting: reducing RX nr below peer TX with XDP set"
        ip netns exec $NS_DST ethtool -L veth$DST rx 1 2>/dev/null &&\
                echo "fail - set operation successful ?!?" || echo " ok "
@@ -311,7 +311,7 @@ if [ $CPUS -gt 2 ]; then
        chk_channels "setting invalid channels nr" $DST 2 2
 fi
 
-ip -n $NS_DST link set dev veth$DST xdp object ../bpf/xdp_dummy.o section xdp_dummy 2>/dev/null
+ip -n $NS_DST link set dev veth$DST xdp object ../bpf/xdp_dummy.o section xdp 2>/dev/null
 chk_gro_flag "with xdp attached - gro flag" $DST on
 chk_gro_flag "        - peer gro flag" $SRC off
 chk_tso_flag "        - tso flag" $SRC off
index b24494c..c652e8c 100644 (file)
         "teardown": [
             "$TC actions flush action gact"
         ]
+    },
+    {
+        "id": "7f52",
+        "name": "Try to flush action which is referenced by filter",
+        "category": [
+            "actions",
+            "gact"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            [
+                "$TC actions flush action gact",
+                0,
+                1,
+                255
+            ],
+            "$TC qdisc add dev $DEV1 ingress",
+            "$TC actions add action pass index 1",
+            "$TC filter add dev $DEV1 protocol all ingress prio 1 handle 0x1234 matchall action gact index 1"
+        ],
+        "cmdUnderTest": "$TC actions flush action gact",
+        "expExitCode": "1",
+        "verifyCmd": "$TC actions ls action gact",
+        "matchPattern": "total acts 1.*action order [0-9]*: gact action pass.*index 1 ref 2 bind 1",
+        "matchCount": "1",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 ingress",
+            [
+                "sleep 1; $TC actions flush action gact",
+                0,
+                1
+            ]
+        ]
+    },
+    {
+        "id": "ae1e",
+        "name": "Try to flush actions when last one is referenced by filter",
+        "category": [
+            "actions",
+            "gact"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            [
+                "$TC actions flush action gact",
+                0,
+                1,
+                255
+            ],
+            "$TC qdisc add dev $DEV1 ingress",
+           [
+                "$TC actions add action pass index 1",
+               0,
+               1,
+               255
+           ],
+            "$TC actions add action reclassify index 2",
+            "$TC actions add action drop index 3",
+            "$TC filter add dev $DEV1 protocol all ingress prio 1 handle 0x1234 matchall action gact index 3"
+        ],
+        "cmdUnderTest": "$TC actions flush action gact",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions ls action gact",
+        "matchPattern": "total acts 1.*action order [0-9]*: gact action drop.*index 3 ref 2 bind 1",
+        "matchCount": "1",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 ingress",
+            [
+                "sleep 1; $TC actions flush action gact",
+                0,
+                1
+            ]
+        ]
     }
 ]
index 7d1b809..9700358 100644 (file)
@@ -19,8 +19,6 @@ endif
 MIRROR := https://download.wireguard.com/qemu-test/distfiles/
 
 KERNEL_BUILD_PATH := $(BUILD_PATH)/kernel$(if $(findstring yes,$(DEBUG_KERNEL)),-debug)
-rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
-WIREGUARD_SOURCES := $(call rwildcard,$(KERNEL_PATH)/drivers/net/wireguard/,*)
 
 default: qemu
 
@@ -109,20 +107,22 @@ CHOST := x86_64-linux-musl
 QEMU_ARCH := x86_64
 KERNEL_ARCH := x86_64
 KERNEL_BZIMAGE := $(KERNEL_BUILD_PATH)/arch/x86/boot/bzImage
+QEMU_VPORT_RESULT := virtio-serial-device
 ifeq ($(HOST_ARCH),$(ARCH))
-QEMU_MACHINE := -cpu host -machine q35,accel=kvm
+QEMU_MACHINE := -cpu host -machine microvm,accel=kvm,pit=off,pic=off,rtc=off -no-acpi
 else
-QEMU_MACHINE := -cpu max -machine q35
+QEMU_MACHINE := -cpu max -machine microvm -no-acpi
 endif
 else ifeq ($(ARCH),i686)
 CHOST := i686-linux-musl
 QEMU_ARCH := i386
 KERNEL_ARCH := x86
 KERNEL_BZIMAGE := $(KERNEL_BUILD_PATH)/arch/x86/boot/bzImage
+QEMU_VPORT_RESULT := virtio-serial-device
 ifeq ($(subst x86_64,i686,$(HOST_ARCH)),$(ARCH))
-QEMU_MACHINE := -cpu host -machine q35,accel=kvm
+QEMU_MACHINE := -cpu host -machine microvm,accel=kvm,pit=off,pic=off,rtc=off -no-acpi
 else
-QEMU_MACHINE := -cpu max -machine q35
+QEMU_MACHINE := -cpu coreduo -machine microvm -no-acpi
 endif
 else ifeq ($(ARCH),mips64)
 CHOST := mips64-linux-musl
@@ -208,10 +208,11 @@ QEMU_ARCH := m68k
 KERNEL_ARCH := m68k
 KERNEL_BZIMAGE := $(KERNEL_BUILD_PATH)/vmlinux
 KERNEL_CMDLINE := $(shell sed -n 's/CONFIG_CMDLINE=\(.*\)/\1/p' arch/m68k.config)
+QEMU_VPORT_RESULT := virtio-serial-device
 ifeq ($(HOST_ARCH),$(ARCH))
-QEMU_MACHINE := -cpu host,accel=kvm -machine q800 -append $(KERNEL_CMDLINE)
+QEMU_MACHINE := -cpu host,accel=kvm -machine virt -append $(KERNEL_CMDLINE)
 else
-QEMU_MACHINE := -machine q800 -smp 1 -append $(KERNEL_CMDLINE)
+QEMU_MACHINE := -machine virt -smp 1 -append $(KERNEL_CMDLINE)
 endif
 else ifeq ($(ARCH),riscv64)
 CHOST := riscv64-linux-musl
@@ -322,8 +323,9 @@ $(KERNEL_BUILD_PATH)/.config: $(TOOLCHAIN_PATH)/.installed kernel.config arch/$(
        cd $(KERNEL_BUILD_PATH) && ARCH=$(KERNEL_ARCH) $(KERNEL_PATH)/scripts/kconfig/merge_config.sh -n $(KERNEL_BUILD_PATH)/.config $(KERNEL_BUILD_PATH)/minimal.config
        $(if $(findstring yes,$(DEBUG_KERNEL)),cp debug.config $(KERNEL_BUILD_PATH) && cd $(KERNEL_BUILD_PATH) && ARCH=$(KERNEL_ARCH) $(KERNEL_PATH)/scripts/kconfig/merge_config.sh -n $(KERNEL_BUILD_PATH)/.config debug.config,)
 
-$(KERNEL_BZIMAGE): $(TOOLCHAIN_PATH)/.installed $(KERNEL_BUILD_PATH)/.config $(BUILD_PATH)/init-cpio-spec.txt $(IPERF_PATH)/src/iperf3 $(IPUTILS_PATH)/ping $(BASH_PATH)/bash $(IPROUTE2_PATH)/misc/ss $(IPROUTE2_PATH)/ip/ip $(IPTABLES_PATH)/iptables/xtables-legacy-multi $(NMAP_PATH)/ncat/ncat $(WIREGUARD_TOOLS_PATH)/src/wg $(BUILD_PATH)/init ../netns.sh $(WIREGUARD_SOURCES)
+$(KERNEL_BZIMAGE): $(TOOLCHAIN_PATH)/.installed $(KERNEL_BUILD_PATH)/.config $(BUILD_PATH)/init-cpio-spec.txt $(IPERF_PATH)/src/iperf3 $(IPUTILS_PATH)/ping $(BASH_PATH)/bash $(IPROUTE2_PATH)/misc/ss $(IPROUTE2_PATH)/ip/ip $(IPTABLES_PATH)/iptables/xtables-legacy-multi $(NMAP_PATH)/ncat/ncat $(WIREGUARD_TOOLS_PATH)/src/wg $(BUILD_PATH)/init
        $(MAKE) -C $(KERNEL_PATH) O=$(KERNEL_BUILD_PATH) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(CROSS_COMPILE)
+.PHONY: $(KERNEL_BZIMAGE)
 
 $(TOOLCHAIN_PATH)/$(CHOST)/include/linux/.installed: | $(KERNEL_BUILD_PATH)/.config $(TOOLCHAIN_PATH)/.installed
        rm -rf $(TOOLCHAIN_PATH)/$(CHOST)/include/linux
index fc7959b..0579c66 100644 (file)
@@ -7,6 +7,7 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_VIRTIO_MENU=y
 CONFIG_VIRTIO_MMIO=y
 CONFIG_VIRTIO_CONSOLE=y
+CONFIG_COMPAT_32BIT_TIME=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyAMA0 wg.success=vport0p1 panic_on_warn=1"
 CONFIG_FRAME_WARN=1024
index f3066be..2a3307b 100644 (file)
@@ -7,6 +7,7 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_VIRTIO_MENU=y
 CONFIG_VIRTIO_MMIO=y
 CONFIG_VIRTIO_CONSOLE=y
+CONFIG_COMPAT_32BIT_TIME=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyAMA0 wg.success=vport0p1 panic_on_warn=1"
 CONFIG_CPU_BIG_ENDIAN=y
index 6d90892..35b0650 100644 (file)
@@ -1,6 +1,10 @@
-CONFIG_ACPI=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_VIRTIO_MENU=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
+CONFIG_COMPAT_32BIT_TIME=y
 CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1 panic_on_warn=1"
+CONFIG_CMDLINE="console=ttyS0 wg.success=vport0p1 panic_on_warn=1 reboot=t"
 CONFIG_FRAME_WARN=1024
index 82c925e..39c48cb 100644 (file)
@@ -1,9 +1,7 @@
 CONFIG_MMU=y
+CONFIG_VIRT=y
 CONFIG_M68KCLASSIC=y
-CONFIG_M68040=y
-CONFIG_MAC=y
-CONFIG_SERIAL_PMACZILOG=y
-CONFIG_SERIAL_PMACZILOG_TTYS=y
-CONFIG_SERIAL_PMACZILOG_CONSOLE=y
-CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1 panic_on_warn=1"
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_CMDLINE="console=ttyGF0 wg.success=vport0p1 panic_on_warn=1"
 CONFIG_FRAME_WARN=1024
index d7ec63c..2a84402 100644 (file)
@@ -6,6 +6,7 @@ CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_SYSCON=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_COMPAT_32BIT_TIME=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1 panic_on_warn=1"
 CONFIG_FRAME_WARN=1024
index 18a4982..56146a1 100644 (file)
@@ -7,6 +7,7 @@ CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_SYSCON=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_COMPAT_32BIT_TIME=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1 panic_on_warn=1"
 CONFIG_FRAME_WARN=1024
index 5e04882..174a9ff 100644 (file)
@@ -4,6 +4,7 @@ CONFIG_PPC_85xx=y
 CONFIG_PHYS_64BIT=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_COMPAT_32BIT_TIME=y
 CONFIG_MATH_EMULATION=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1 panic_on_warn=1"
index efa0069..cf2d137 100644 (file)
@@ -1,6 +1,9 @@
-CONFIG_ACPI=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_VIRTIO_MENU=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
 CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttyS0 wg.success=ttyS1 panic_on_warn=1"
+CONFIG_CMDLINE="console=ttyS0 wg.success=vport0p1 panic_on_warn=1 reboot=t"
 CONFIG_FRAME_WARN=1280
index c9e1284..3e49924 100644 (file)
@@ -11,6 +11,7 @@
 #include <stdlib.h>
 #include <stdbool.h>
 #include <fcntl.h>
+#include <time.h>
 #include <sys/wait.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
@@ -70,6 +71,15 @@ static void seed_rng(void)
        close(fd);
 }
 
+static void set_time(void)
+{
+       if (time(NULL))
+               return;
+       pretty_message("[+] Setting fake time...");
+       if (stime(&(time_t){1433512680}) < 0)
+               panic("settimeofday()");
+}
+
 static void mount_filesystems(void)
 {
        pretty_message("[+] Mounting filesystems...");
@@ -259,6 +269,7 @@ int main(int argc, char *argv[])
        print_banner();
        mount_filesystems();
        seed_rng();
+       set_time();
        kmod_selftests();
        enable_logging();
        clear_leaks();