Merge tag 'for-linus-2021-01-24' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 24 Jan 2021 17:35:28 +0000 (09:35 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 24 Jan 2021 17:35:28 +0000 (09:35 -0800)
Pull misc fixes from Christian Brauner:

 - Jann reported sparse complaints because of a missing __user
   annotation in a helper we added way back when we added
   pidfd_send_signal() to avoid compat syscall handling. Fix it.

 - Yanfei replaces a reference in a comment to the _do_fork() helper I
   removed a while ago with a reference to the new kernel_clone()
   replacement

 - Alexander Guril added a simple coding style fix

* tag 'for-linus-2021-01-24' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux:
  kthread: remove comments about old _do_fork() helper
  Kernel: fork.c: Fix coding style: Do not use {} around single-line statements
  signal: Add missing __user annotation to copy_siginfo_from_user_any

523 files changed:
.mailmap
CREDITS
Documentation/ABI/testing/sysfs-driver-ufs
Documentation/admin-guide/device-mapper/dm-integrity.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/dev-tools/kunit/usage.rst
Documentation/devicetree/bindings/net/renesas,etheravb.yaml
Documentation/devicetree/bindings/net/snps,dwmac.yaml
Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml
Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml
Documentation/firmware-guide/acpi/apei/einj.rst
Documentation/networking/netdevices.rst
Documentation/networking/tls-offload.rst
Documentation/sound/alsa-configuration.rst
MAINTAINERS
Makefile
arch/arm/xen/enlighten.c
arch/arm64/Kconfig
arch/arm64/include/asm/atomic.h
arch/arm64/include/asm/processor.h
arch/arm64/kernel/asm-offsets.c
arch/arm64/kernel/entry-ftrace.S
arch/arm64/kernel/entry.S
arch/arm64/kernel/perf_event.c
arch/arm64/kernel/probes/kprobes.c
arch/arm64/kernel/probes/kprobes_trampoline.S
arch/arm64/kernel/signal.c
arch/arm64/kernel/syscall.c
arch/arm64/mm/fault.c
arch/arm64/mm/init.c
arch/ia64/include/asm/sparsemem.h
arch/mips/boot/compressed/decompress.c
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/kernel/binfmt_elfn32.c
arch/mips/kernel/binfmt_elfo32.c
arch/mips/kernel/relocate.c
arch/openrisc/include/asm/io.h
arch/openrisc/mm/ioremap.c
arch/powerpc/include/asm/vdso/gettimeofday.h
arch/powerpc/kernel/vmlinux.lds.S
arch/riscv/Kconfig
arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
arch/riscv/configs/defconfig
arch/riscv/include/asm/pgtable.h
arch/riscv/include/asm/vdso.h
arch/riscv/kernel/cacheinfo.c
arch/riscv/kernel/entry.S
arch/riscv/kernel/setup.c
arch/riscv/kernel/stacktrace.c
arch/riscv/kernel/time.c
arch/riscv/kernel/vdso.c
arch/riscv/mm/init.c
arch/riscv/mm/kasan_init.c
arch/x86/hyperv/hv_init.c
arch/x86/hyperv/mmu.c
arch/x86/include/asm/mshyperv.h
arch/x86/kernel/cpu/mshyperv.c
arch/x86/xen/enlighten_hvm.c
arch/x86/xen/smp_hvm.c
crypto/asymmetric_keys/public_key.c
crypto/xor.c
drivers/acpi/internal.h
drivers/acpi/scan.c
drivers/clk/tegra/clk-tegra30.c
drivers/crypto/Kconfig
drivers/dma-buf/heaps/cma_heap.c
drivers/gpio/Kconfig
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpiolib-cdev.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_gem_vram_helper.c
drivers/gpu/drm/drm_plane.c
drivers/gpu/drm/drm_syncobj.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/display/icl_dsi.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_dp.h
drivers/gpu/drm/i915/display/intel_hdcp.c
drivers/gpu/drm/i915/display/intel_panel.c
drivers/gpu/drm/i915/display/vlv_dsi.c
drivers/gpu/drm/i915/gt/gen7_renderclear.c
drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_ring_submission.c
drivers/gpu/drm/i915/gt/intel_timeline.c
drivers/gpu/drm/i915/gvt/display.c
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_mitigations.c [new file with mode: 0644]
drivers/gpu/drm/i915/i915_mitigations.h [new file with mode: 0644]
drivers/gpu/drm/i915/i915_pmu.c
drivers/gpu/drm/i915/i915_request.h
drivers/gpu/drm/nouveau/dispnv50/Kbuild
drivers/gpu/drm/nouveau/dispnv50/core.c
drivers/gpu/drm/nouveau/dispnv50/curs.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/dispnv50/disp.h
drivers/gpu/drm/nouveau/dispnv50/wimm.c
drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c
drivers/gpu/drm/nouveau/dispnv50/wndw.c
drivers/gpu/drm/nouveau/dispnv50/wndw.h
drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c
drivers/gpu/drm/nouveau/dispnv50/wndwc67e.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/include/nvif/cl0080.h
drivers/gpu/drm/nouveau/include/nvif/class.h
drivers/gpu/drm/nouveau/include/nvkm/core/device.h
drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
drivers/gpu/drm/nouveau/nouveau_backlight.c
drivers/gpu/drm/nouveau/nvif/disp.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/rootga102.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/ga100.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu102.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramga102.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/gpio/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/gpio/ga102.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gk110.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm200.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/pad.h
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c
drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c
drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
drivers/gpu/drm/ttm/ttm_pool.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/hid/Kconfig
drivers/hid/amd-sfh-hid/amd_sfh_client.c
drivers/hid/amd-sfh-hid/amd_sfh_hid.h
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-uclogic-params.c
drivers/hid/hid-wiimote-core.c
drivers/hid/wacom_sys.c
drivers/hv/vmbus_drv.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-octeon-core.c
drivers/i2c/busses/i2c-tegra-bpmp.c
drivers/i2c/busses/i2c-tegra.c
drivers/infiniband/core/cma_configfs.c
drivers/infiniband/core/restrack.c
drivers/infiniband/core/ucma.c
drivers/infiniband/core/umem.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/hw/usnic/usnic_ib_verbs.c
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
drivers/iommu/intel/iommu.c
drivers/iommu/intel/svm.c
drivers/md/Kconfig
drivers/md/dm-bufio.c
drivers/md/dm-crypt.c
drivers/md/dm-integrity.c
drivers/md/dm-raid.c
drivers/md/dm-snap.c
drivers/md/dm-table.c
drivers/md/dm.c
drivers/mmc/core/queue.c
drivers/mmc/host/sdhci-brcmstb.c
drivers/mmc/host/sdhci-of-dwcmshc.c
drivers/mmc/host/sdhci-xenon.c
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/raw/intel-nand-controller.c
drivers/mtd/nand/raw/nandsim.c
drivers/mtd/nand/raw/omap2.c
drivers/mtd/nand/spi/core.c
drivers/net/can/dev.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
drivers/net/can/usb/peak_usb/pcan_usb_fd.c
drivers/net/can/vxcan.c
drivers/net/dsa/b53/b53_common.c
drivers/net/dsa/mv88e6xxx/global1_vtu.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
drivers/net/ethernet/chelsio/cxgb4/t4_tcb.h
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_hw.c
drivers/net/ethernet/intel/i40e/i40e_xsk.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot_net.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/stmicro/stmmac/dwmac5.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
drivers/net/ipa/ipa_modem.c
drivers/net/mdio/mdio-bitbang.c
drivers/net/phy/smsc.c
drivers/net/ppp/ppp_generic.c
drivers/net/usb/Kconfig
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/r8152.c
drivers/net/usb/r8153_ecm.c
drivers/net/usb/rndis_host.c
drivers/nvme/host/core.c
drivers/nvme/host/tcp.c
drivers/nvme/target/rdma.c
drivers/perf/arm_pmu.c
drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
drivers/pinctrl/nomadik/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-ingenic.c
drivers/pinctrl/qcom/pinctrl-msm.c
drivers/pinctrl/qcom/pinctrl-msm.h
drivers/platform/surface/Kconfig
drivers/platform/surface/surface_gpe.c
drivers/platform/x86/amd-pmc.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/i2c-multi-instantiate.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel-vbtn.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/touchscreen_dmi.c
drivers/scsi/fnic/vnic_dev.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/libfc/fc_exch.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/mpt3sas/Kconfig
drivers/scsi/qedi/qedi_main.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_transport_srp.c
drivers/scsi/sd.c
drivers/scsi/ufs/Kconfig
drivers/scsi/ufs/ufshcd.c
drivers/soc/litex/litex_soc_ctrl.c
drivers/spi/spi-cadence.c
drivers/spi/spi-fsl-spi.c
drivers/target/target_core_user.c
drivers/target/target_core_xcopy.c
drivers/target/target_core_xcopy.h
drivers/tty/serial/sifive.c
drivers/xen/events/events_base.c
drivers/xen/platform-pci.c
drivers/xen/privcmd.c
drivers/xen/xenbus/xenbus.h
drivers/xen/xenbus/xenbus_comms.c
drivers/xen/xenbus/xenbus_probe.c
fs/btrfs/backref.c
fs/btrfs/block-group.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/btrfs/print-tree.c
fs/btrfs/print-tree.h
fs/btrfs/relocation.c
fs/btrfs/send.c
fs/btrfs/space-info.c
fs/btrfs/transaction.c
fs/btrfs/tree-checker.c
fs/btrfs/volumes.c
fs/cachefiles/rdwr.c
fs/ceph/mds_client.c
fs/cifs/connect.c
fs/cifs/dfs_cache.c
fs/cifs/fs_context.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/transport.c
fs/ext4/ext4_jbd2.c
fs/ext4/ext4_jbd2.h
fs/ext4/fast_commit.c
fs/ext4/file.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/fs-writeback.c
fs/io_uring.c
fs/namespace.c
fs/nfs/delegation.c
fs/nfs/internal.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4super.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/pnfs_nfs.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfssvc.c
fs/nfsd/xdr4.h
fs/proc/task_mmu.c
fs/udf/super.c
include/asm-generic/bitops/atomic.h
include/linux/compiler-gcc.h
include/linux/dm-bufio.h
include/linux/kasan.h
include/linux/mdio-bitbang.h
include/linux/memcontrol.h
include/linux/perf/arm_pmu.h
include/linux/skbuff.h
include/linux/usb/usbnet.h
include/net/cfg80211.h
include/net/inet_connection_sock.h
include/net/mac80211.h
include/net/sock.h
include/trace/events/sunrpc.h
include/xen/xenbus.h
kernel/bpf/bpf_inode_storage.c
kernel/bpf/bpf_task_storage.c
kernel/bpf/btf.c
kernel/bpf/cgroup.c
kernel/bpf/helpers.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/printk/printk.c
kernel/printk/printk_ringbuffer.c
kernel/signal.c
kernel/trace/Kconfig
kernel/trace/trace_kprobe.c
lib/iov_iter.c
mm/hugetlb.c
mm/kasan/init.c
mm/memblock.c
mm/memory-failure.c
mm/mempolicy.c
mm/page_alloc.c
mm/process_vm_access.c
mm/slub.c
mm/vmalloc.c
mm/vmscan.c
net/8021q/vlan.c
net/bpf/test_run.c
net/can/isotp.c
net/ceph/auth_x.c
net/ceph/crypto.c
net/ceph/messenger_v1.c
net/ceph/messenger_v2.c
net/ceph/mon_client.c
net/ceph/osd_client.c
net/core/dev.c
net/core/devlink.c
net/core/gen_estimator.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sock_reuseport.c
net/dcb/dcbnl.c
net/dsa/dsa2.c
net/dsa/master.c
net/ipv4/esp4.c
net/ipv4/inet_connection_sock.c
net/ipv4/netfilter/ipt_rpfilter.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/esp6.c
net/ipv6/ip6_output.c
net/ipv6/sit.c
net/mac80211/debugfs.c
net/mac80211/rx.c
net/mac80211/tx.c
net/mptcp/protocol.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_nat_core.c
net/nfc/nci/core.c
net/rxrpc/input.c
net/rxrpc/key.c
net/sched/cls_flower.c
net/sched/cls_tcindex.c
net/sched/sch_api.c
net/smc/smc_core.c
net/smc/smc_ib.c
net/smc/smc_ism.c
net/sunrpc/addr.c
net/sunrpc/svc_xprt.c
net/sunrpc/svcsock.c
net/tipc/link.c
net/tipc/node.c
net/wireless/reg.c
net/xdp/xsk.c
security/lsm_audit.c
sound/core/seq/oss/seq_oss_synth.c
sound/firewire/fireface/ff-transaction.c
sound/firewire/tascam/tascam-transaction.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_tegra.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/soc/amd/raven/pci-acp3x.c
sound/soc/amd/renoir/rn-pci-acp3x.c
sound/soc/atmel/Kconfig
sound/soc/codecs/Kconfig
sound/soc/codecs/hdmi-codec.c
sound/soc/codecs/max98373-i2c.c
sound/soc/codecs/max98373-sdw.c
sound/soc/codecs/max98373.c
sound/soc/codecs/max98373.h
sound/soc/codecs/rt711.c
sound/soc/fsl/imx-hdmi.c
sound/soc/intel/boards/haswell.c
sound/soc/intel/skylake/cnl-sst.c
sound/soc/meson/axg-tdm-interface.c
sound/soc/meson/axg-tdmin.c
sound/soc/qcom/lpass-cpu.c
sound/soc/qcom/lpass-platform.c
sound/soc/sh/rcar/adg.c
sound/soc/soc-dapm.c
sound/soc/sof/Kconfig
sound/soc/sof/intel/hda-codec.c
sound/soc/sof/intel/hda-dsp.c
sound/soc/sof/intel/hda.h
sound/usb/card.c
sound/usb/card.h
sound/usb/clock.c
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/implicit.c
sound/usb/pcm.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/usbaudio.h
tools/bootconfig/scripts/bconf2ftrace.sh
tools/bootconfig/scripts/ftrace2bconf.sh
tools/gpio/gpio-event-mon.c
tools/gpio/gpio-watch.c
tools/include/linux/build_bug.h
tools/include/uapi/linux/kvm.h
tools/lib/bpf/btf.c
tools/lib/perf/evlist.c
tools/lib/perf/tests/test-cpumap.c
tools/lib/perf/tests/test-evlist.c
tools/lib/perf/tests/test-evsel.c
tools/lib/perf/tests/test-threadmap.c
tools/perf/builtin-script.c
tools/perf/examples/bpf/5sec.c
tools/perf/tests/shell/stat+shadow_stat.sh
tools/perf/util/header.c
tools/perf/util/machine.c
tools/perf/util/metricgroup.c
tools/perf/util/session.c
tools/perf/util/stat-shadow.c
tools/power/x86/intel-speed-select/isst-config.c
tools/testing/kunit/kunit.py
tools/testing/kunit/kunit_config.py
tools/testing/kunit/kunit_json.py
tools/testing/kunit/kunit_kernel.py
tools/testing/kunit/kunit_parser.py
tools/testing/selftests/Makefile
tools/testing/selftests/arm64/fp/fpsimd-test.S
tools/testing/selftests/arm64/fp/sve-test.S
tools/testing/selftests/bpf/prog_tests/test_local_storage.c
tools/testing/selftests/bpf/progs/local_storage.c
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/bpf/verifier/spill_fill.c
tools/testing/selftests/net/fib_tests.sh
tools/testing/selftests/net/tls.c
tools/testing/selftests/netfilter/nft_conntrack_helper.sh

index 632700cee55cdaeaea8d6765037150f493271c8f..b1ab0129c7d6b034b1e41355892afdebf60ebdb8 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -55,6 +55,8 @@ Bart Van Assche <bvanassche@acm.org> <bart.vanassche@wdc.com>
 Ben Gardner <bgardner@wabtec.com>
 Ben M Cahill <ben.m.cahill@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>
 Boris Brezillon <bbrezillon@kernel.org> <b.brezillon.dev@gmail.com>
 Boris Brezillon <bbrezillon@kernel.org> <b.brezillon@overkiz.com>
 Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@bootlin.com>
diff --git a/CREDITS b/CREDITS
index 090ed4b004a5b216c821ec820f1440c35c253402..9add7e6a4fa022ef1b06818bed57392ef3def9b5 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -710,6 +710,10 @@ S: Las Cuevas 2385 - Bo Guemes
 S: Las Heras, Mendoza CP 5539
 S: Argentina
 
+N: Jay Cliburn
+E: jcliburn@gmail.com
+D: ATLX Ethernet drivers
+
 N: Steven P. Cole
 E: scole@lanl.gov
 E: elenstev@mesatop.com
@@ -1284,6 +1288,10 @@ D: Major kbuild rework during the 2.5 cycle
 D: ISDN Maintainer
 S: USA
 
+N: Gerrit Renker
+E: gerrit@erg.abdn.ac.uk
+D: DCCP protocol support.
+
 N: Philip Gladstone
 E: philip@gladstonefamily.net
 D: Kernel / timekeeping stuff
@@ -2138,6 +2146,10 @@ E: seasons@falcon.sch.bme.hu
 E: seasons@makosteszta.sote.hu
 D: Original author of software suspend
 
+N: Alexey Kuznetsov
+E: kuznet@ms2.inr.ac.ru
+D: Author and maintainer of large parts of the networking stack
+
 N: Jaroslav Kysela
 E: perex@perex.cz
 W: https://www.perex.cz
@@ -2696,6 +2708,10 @@ N: Wolfgang Muees
 E: wolfgang@iksw-muees.de
 D: Auerswald USB driver
 
+N: Shrijeet Mukherjee
+E: shrijeet@gmail.com
+D: Network routing domains (VRF).
+
 N: Paul Mundt
 E: paul.mundt@gmail.com
 D: SuperH maintainer
@@ -4110,6 +4126,10 @@ S: B-1206 Jingmao Guojigongyu
 S: 16 Baliqiao Nanjie, Beijing 101100
 S: People's Repulic of China
 
+N: Aviad Yehezkel
+E: aviadye@nvidia.com
+D: Kernel TLS implementation and offload support.
+
 N: Victor Yodaiken
 E: yodaiken@fsmlabs.com
 D: RTLinux (RealTime Linux)
@@ -4167,6 +4187,10 @@ S: 1507 145th Place SE #B5
 S: Bellevue, Washington 98007
 S: USA
 
+N: Wensong Zhang
+E: wensong@linux-vs.org
+D: IP virtual server (IPVS).
+
 N: Haojian Zhuang
 E: haojian.zhuang@gmail.com
 D: MMP support
index adc0d0e916078001cd573c896cda7402e7b5e10b..75ccc5c62b3c498a940dafb12014b56cdfe156c2 100644 (file)
@@ -916,21 +916,25 @@ Date:             September 2014
 Contact:       Subhash Jadavani <subhashj@codeaurora.org>
 Description:   This entry could be used to set or show the UFS device
                runtime power management level. The current driver
-               implementation supports 6 levels with next target states:
+               implementation supports 7 levels with next target states:
 
                ==  ====================================================
-               0   an UFS device will stay active, an UIC link will
+               0   UFS device will stay active, UIC link will
                    stay active
-               1   an UFS device will stay active, an UIC link will
+               1   UFS device will stay active, UIC link will
                    hibernate
-               2   an UFS device will moved to sleep, an UIC link will
+               2   UFS device will be moved to sleep, UIC link will
                    stay active
-               3   an UFS device will moved to sleep, an UIC link will
+               3   UFS device will be moved to sleep, UIC link will
                    hibernate
-               4   an UFS device will be powered off, an UIC link will
+               4   UFS device will be powered off, UIC link will
                    hibernate
-               5   an UFS device will be powered off, an UIC link will
+               5   UFS device will be powered off, UIC link will
                    be powered off
+               6   UFS device will be moved to deep sleep, UIC link
+                   will be powered off. Note, deep sleep might not be
+                   supported in which case this value will not be
+                   accepted
                ==  ====================================================
 
 What:          /sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state
@@ -954,21 +958,25 @@ Date:             September 2014
 Contact:       Subhash Jadavani <subhashj@codeaurora.org>
 Description:   This entry could be used to set or show the UFS device
                system power management level. The current driver
-               implementation supports 6 levels with next target states:
+               implementation supports 7 levels with next target states:
 
                ==  ====================================================
-               0   an UFS device will stay active, an UIC link will
+               0   UFS device will stay active, UIC link will
                    stay active
-               1   an UFS device will stay active, an UIC link will
+               1   UFS device will stay active, UIC link will
                    hibernate
-               2   an UFS device will moved to sleep, an UIC link will
+               2   UFS device will be moved to sleep, UIC link will
                    stay active
-               3   an UFS device will moved to sleep, an UIC link will
+               3   UFS device will be moved to sleep, UIC link will
                    hibernate
-               4   an UFS device will be powered off, an UIC link will
+               4   UFS device will be powered off, UIC link will
                    hibernate
-               5   an UFS device will be powered off, an UIC link will
+               5   UFS device will be powered off, UIC link will
                    be powered off
+               6   UFS device will be moved to deep sleep, UIC link
+                   will be powered off. Note, deep sleep might not be
+                   supported in which case this value will not be
+                   accepted
                ==  ====================================================
 
 What:          /sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state
index 4e6f504474ac2d48bab8e3df7260fc441e033ba4..2cc5488acbd97a1efda5152a4c6e80299246d2a2 100644 (file)
@@ -177,14 +177,20 @@ bitmap_flush_interval:number
        The bitmap flush interval in milliseconds. The metadata buffers
        are synchronized when this interval expires.
 
+allow_discards
+       Allow block discard requests (a.k.a. TRIM) for the integrity device.
+       Discards are only allowed to devices using internal hash.
+
 fix_padding
        Use a smaller padding of the tag area that is more
        space-efficient. If this option is not present, large padding is
        used - that is for compatibility with older kernels.
 
-allow_discards
-       Allow block discard requests (a.k.a. TRIM) for the integrity device.
-       Discards are only allowed to devices using internal hash.
+legacy_recalculate
+       Allow recalculating of volumes with HMAC keys. This is disabled by
+       default for security reasons - an attacker could modify the volume,
+       set recalc_sector to zero, and the kernel would not detect the
+       modification.
 
 The journal mode (D/J), buffer_sectors, journal_watermark, commit_time and
 allow_discards can be changed when reloading the target (load an inactive
index 9e3cdb271d06cfc198e80824ecfd83b305ae326c..a10b545c2070a54455c3e7181cc43135dc68f611 100644 (file)
                        This option is obsoleted by the "nopv" option, which
                        has equivalent effect for XEN platform.
 
+       xen_no_vector_callback
+                       [KNL,X86,XEN] Disable the vector callback for Xen
+                       event channel interrupts.
+
        xen_scrub_pages=        [XEN]
                        Boolean option to control scrubbing pages before giving them back
                        to Xen, for use by other domains. Can be also changed at runtime
index d9fdc14f0677b889857a08c92d2db331aae83ef7..650f99590df57d0b3593455c993987cdfcdb400d 100644 (file)
@@ -522,6 +522,63 @@ There's more boilerplate involved, but it can:
   * E.g. if we wanted to also test ``sha256sum``, we could add a ``sha256``
     field and reuse ``cases``.
 
+* be converted to a "parameterized test", see below.
+
+Parameterized Testing
+~~~~~~~~~~~~~~~~~~~~~
+
+The table-driven testing pattern is common enough that KUnit has special
+support for it.
+
+Reusing the same ``cases`` array from above, we can write the test as a
+"parameterized test" with the following.
+
+.. code-block:: c
+
+       // This is copy-pasted from above.
+       struct sha1_test_case {
+               const char *str;
+               const char *sha1;
+       };
+       struct sha1_test_case cases[] = {
+               {
+                       .str = "hello world",
+                       .sha1 = "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed",
+               },
+               {
+                       .str = "hello world!",
+                       .sha1 = "430ce34d020724ed75a196dfc2ad67c77772d169",
+               },
+       };
+
+       // Need a helper function to generate a name for each test case.
+       static void case_to_desc(const struct sha1_test_case *t, char *desc)
+       {
+               strcpy(desc, t->str);
+       }
+       // Creates `sha1_gen_params()` to iterate over `cases`.
+       KUNIT_ARRAY_PARAM(sha1, cases, case_to_desc);
+
+       // Looks no different from a normal test.
+       static void sha1_test(struct kunit *test)
+       {
+               // This function can just contain the body of the for-loop.
+               // The former `cases[i]` is accessible under test->param_value.
+               char out[40];
+               struct sha1_test_case *test_param = (struct sha1_test_case *)(test->param_value);
+
+               sha1sum(test_param->str, out);
+               KUNIT_EXPECT_STREQ_MSG(test, (char *)out, test_param->sha1,
+                                     "sha1sum(%s)", test_param->str);
+       }
+
+       // Instead of KUNIT_CASE, we use KUNIT_CASE_PARAM and pass in the
+       // function declared by KUNIT_ARRAY_PARAM.
+       static struct kunit_case sha1_test_cases[] = {
+               KUNIT_CASE_PARAM(sha1_test, sha1_gen_params),
+               {}
+       };
+
 .. _kunit-on-non-uml:
 
 KUnit on non-UML architectures
index 244befb6402aa8b4cd28641e9dc8236547bf1b62..de9dd574a2f954a3ba3f59406db98952c0acfcb2 100644 (file)
@@ -163,6 +163,7 @@ allOf:
             enum:
               - renesas,etheravb-r8a774a1
               - renesas,etheravb-r8a774b1
+              - renesas,etheravb-r8a774e1
               - renesas,etheravb-r8a7795
               - renesas,etheravb-r8a7796
               - renesas,etheravb-r8a77961
index b2f6083f556af0d6b789d8b340a8699152bac912..dfbf5fe4547ab611a7004ee2baeb4914d93ce61e 100644 (file)
@@ -161,7 +161,8 @@ properties:
             * snps,route-dcbcp, DCB Control Packets
             * snps,route-up, Untagged Packets
             * snps,route-multi-broad, Multicast & Broadcast Packets
-          * snps,priority, RX queue priority (Range 0x0 to 0xF)
+          * snps,priority, bitmask of the tagged frames priorities assigned to
+            the queue
 
   snps,mtl-tx-config:
     $ref: /schemas/types.yaml#/definitions/phandle
@@ -188,7 +189,10 @@ properties:
             * snps,idle_slope, unlock on WoL
             * snps,high_credit, max write outstanding req. limit
             * snps,low_credit, max read outstanding req. limit
-          * snps,priority, TX queue priority (Range 0x0 to 0xF)
+          * snps,priority, bitmask of the priorities assigned to the queue.
+            When a PFC frame is received with priorities matching the bitmask,
+            the queue is blocked from transmitting for the pause time specified
+            in the PFC frame.
 
   snps,reset-gpio:
     deprecated: true
index 805da4d6a88ed53c2592e9c4cf0adf42f8320a15..ec06789b21dfc4ccd1b90cf96ba56374cd8848c0 100644 (file)
@@ -1,4 +1,6 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2020 Texas Instruments Incorporated
+# Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
 %YAML 1.2
 ---
 $id: http://devicetree.org/schemas/sound/ti,j721e-cpb-audio.yaml#
@@ -7,7 +9,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Texas Instruments J721e Common Processor Board Audio Support
 
 maintainers:
-  - Peter Ujfalusi <peter.ujfalusi@ti.com>
+  - Peter Ujfalusi <peter.ujfalusi@gmail.com>
 
 description: |
   The audio support on the board is using pcm3168a codec connected to McASP10
index bb780f621628788c8983d706283ddf1da8a7217a..ee9f960de36b7c9eb083680d589b518272a0522d 100644 (file)
@@ -1,4 +1,6 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2020 Texas Instruments Incorporated
+# Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
 %YAML 1.2
 ---
 $id: http://devicetree.org/schemas/sound/ti,j721e-cpb-ivi-audio.yaml#
@@ -7,7 +9,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Texas Instruments J721e Common Processor Board Audio Support
 
 maintainers:
-  - Peter Ujfalusi <peter.ujfalusi@ti.com>
+  - Peter Ujfalusi <peter.ujfalusi@gmail.com>
 
 description: |
   The Infotainment board plugs into the Common Processor Board, the support of the
index e588bccf5158370fb03dfe4db06b20ee93114108..c042176e17078f5a72eba00b501d665475566c76 100644 (file)
@@ -50,8 +50,8 @@ The following files belong to it:
   0x00000010        Memory Uncorrectable non-fatal
   0x00000020        Memory Uncorrectable fatal
   0x00000040        PCI Express Correctable
-  0x00000080        PCI Express Uncorrectable fatal
-  0x00000100        PCI Express Uncorrectable non-fatal
+  0x00000080        PCI Express Uncorrectable non-fatal
+  0x00000100        PCI Express Uncorrectable fatal
   0x00000200        Platform Correctable
   0x00000400        Platform Uncorrectable non-fatal
   0x00000800        Platform Uncorrectable fatal
index e65665c5ab5016393a2d71a56ddf83703aeaece2..17bdcb746dcf530af859440aa04e78d4fb1226f4 100644 (file)
@@ -10,18 +10,177 @@ Introduction
 The following is a random collection of documentation regarding
 network devices.
 
-struct net_device allocation rules
-==================================
+struct net_device lifetime rules
+================================
 Network device structures need to persist even after module is unloaded and
 must be allocated with alloc_netdev_mqs() and friends.
 If device has registered successfully, it will be freed on last use
-by free_netdev(). This is required to handle the pathologic case cleanly
-(example: rmmod mydriver </sys/class/net/myeth/mtu )
+by free_netdev(). This is required to handle the pathological case cleanly
+(example: ``rmmod mydriver </sys/class/net/myeth/mtu``)
 
-alloc_netdev_mqs()/alloc_netdev() reserve extra space for driver
+alloc_netdev_mqs() / alloc_netdev() reserve extra space for driver
 private data which gets freed when the network device is freed. If
 separately allocated data is attached to the network device
-(netdev_priv(dev)) then it is up to the module exit handler to free that.
+(netdev_priv()) then it is up to the module exit handler to free that.
+
+There are two groups of APIs for registering struct net_device.
+First group can be used in normal contexts where ``rtnl_lock`` is not already
+held: register_netdev(), unregister_netdev().
+Second group can be used when ``rtnl_lock`` is already held:
+register_netdevice(), unregister_netdevice(), free_netdevice().
+
+Simple drivers
+--------------
+
+Most drivers (especially device drivers) handle lifetime of struct net_device
+in context where ``rtnl_lock`` is not held (e.g. driver probe and remove paths).
+
+In that case the struct net_device registration is done using
+the register_netdev(), and unregister_netdev() functions:
+
+.. code-block:: c
+
+  int probe()
+  {
+    struct my_device_priv *priv;
+    int err;
+
+    dev = alloc_netdev_mqs(...);
+    if (!dev)
+      return -ENOMEM;
+    priv = netdev_priv(dev);
+
+    /* ... do all device setup before calling register_netdev() ...
+     */
+
+    err = register_netdev(dev);
+    if (err)
+      goto err_undo;
+
+    /* net_device is visible to the user! */
+
+  err_undo:
+    /* ... undo the device setup ... */
+    free_netdev(dev);
+    return err;
+  }
+
+  void remove()
+  {
+    unregister_netdev(dev);
+    free_netdev(dev);
+  }
+
+Note that after calling register_netdev() the device is visible in the system.
+Users can open it and start sending / receiving traffic immediately,
+or run any other callback, so all initialization must be done prior to
+registration.
+
+unregister_netdev() closes the device and waits for all users to be done
+with it. The memory of struct net_device itself may still be referenced
+by sysfs but all operations on that device will fail.
+
+free_netdev() can be called after unregister_netdev() returns on when
+register_netdev() failed.
+
+Device management under RTNL
+----------------------------
+
+Registering struct net_device while in context which already holds
+the ``rtnl_lock`` requires extra care. In those scenarios most drivers
+will want to make use of struct net_device's ``needs_free_netdev``
+and ``priv_destructor`` members for freeing of state.
+
+Example flow of netdev handling under ``rtnl_lock``:
+
+.. code-block:: c
+
+  static void my_setup(struct net_device *dev)
+  {
+    dev->needs_free_netdev = true;
+  }
+
+  static void my_destructor(struct net_device *dev)
+  {
+    some_obj_destroy(priv->obj);
+    some_uninit(priv);
+  }
+
+  int create_link()
+  {
+    struct my_device_priv *priv;
+    int err;
+
+    ASSERT_RTNL();
+
+    dev = alloc_netdev(sizeof(*priv), "net%d", NET_NAME_UNKNOWN, my_setup);
+    if (!dev)
+      return -ENOMEM;
+    priv = netdev_priv(dev);
+
+    /* Implicit constructor */
+    err = some_init(priv);
+    if (err)
+      goto err_free_dev;
+
+    priv->obj = some_obj_create();
+    if (!priv->obj) {
+      err = -ENOMEM;
+      goto err_some_uninit;
+    }
+    /* End of constructor, set the destructor: */
+    dev->priv_destructor = my_destructor;
+
+    err = register_netdevice(dev);
+    if (err)
+      /* register_netdevice() calls destructor on failure */
+      goto err_free_dev;
+
+    /* If anything fails now unregister_netdevice() (or unregister_netdev())
+     * will take care of calling my_destructor and free_netdev().
+     */
+
+    return 0;
+
+  err_some_uninit:
+    some_uninit(priv);
+  err_free_dev:
+    free_netdev(dev);
+    return err;
+  }
+
+If struct net_device.priv_destructor is set it will be called by the core
+some time after unregister_netdevice(), it will also be called if
+register_netdevice() fails. The callback may be invoked with or without
+``rtnl_lock`` held.
+
+There is no explicit constructor callback, driver "constructs" the private
+netdev state after allocating it and before registration.
+
+Setting struct net_device.needs_free_netdev makes core call free_netdevice()
+automatically after unregister_netdevice() when all references to the device
+are gone. It only takes effect after a successful call to register_netdevice()
+so if register_netdevice() fails driver is responsible for calling
+free_netdev().
+
+free_netdev() is safe to call on error paths right after unregister_netdevice()
+or when register_netdevice() fails. Parts of netdev (de)registration process
+happen after ``rtnl_lock`` is released, therefore in those cases free_netdev()
+will defer some of the processing until ``rtnl_lock`` is released.
+
+Devices spawned from struct rtnl_link_ops should never free the
+struct net_device directly.
+
+.ndo_init and .ndo_uninit
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``.ndo_init`` and ``.ndo_uninit`` callbacks are called during net_device
+registration and de-registration, under ``rtnl_lock``. Drivers can use
+those e.g. when parts of their init process need to run under ``rtnl_lock``.
+
+``.ndo_init`` runs before device is visible in the system, ``.ndo_uninit``
+runs during de-registering after device is closed but other subsystems
+may still have outstanding references to the netdevice.
 
 MTU
 ===
index 0f55c6d540f9794097d96e65c8d319210c02fbd8..5f0dea3d571e359a2655defdcf9b7383b9801ba8 100644 (file)
@@ -530,7 +530,10 @@ TLS device feature flags only control adding of new TLS connection
 offloads, old connections will remain active after flags are cleared.
 
 TLS encryption cannot be offloaded to devices without checksum calculation
-offload. Hence, TLS TX device feature flag requires NETIF_F_HW_CSUM being set.
+offload. Hence, TLS TX device feature flag requires TX csum offload being set.
 Disabling the latter implies clearing the former. Disabling TX checksum offload
 should not affect old connections, and drivers should make sure checksum
 calculation does not break for them.
+Similarly, device-offloaded TLS decryption implies doing RXCSUM. If the user
+does not want to enable RX csum offload, TLS RX device feature is disabled
+as well.
index fe52c314b76391a4f5fc071c65ff98e92f0432cd..b36af65a08edffd6331c0330c780f57f5919798d 100644 (file)
@@ -1501,7 +1501,7 @@ Module for Digigram miXart8 sound cards.
 
 This module supports multiple cards.
 Note: One miXart8 board will be represented as 4 alsa cards.
-See MIXART.txt for details.
+See Documentation/sound/cards/mixart.rst for details.
 
 When the driver is compiled as a module and the hotplug firmware
 is supported, the firmware data is loaded via hotplug automatically.
index cc1e6a5ee6e67357822317c7f71ea9171bdcefcb..f79ec98bbb2913893f62d62b48e831ab10b211f5 100644 (file)
@@ -820,7 +820,6 @@ M:  Netanel Belgazal <netanel@amazon.com>
 M:     Arthur Kiyanovski <akiyano@amazon.com>
 R:     Guy Tzalik <gtzalik@amazon.com>
 R:     Saeed Bishara <saeedb@amazon.com>
-R:     Zorik Machulsky <zorik@amazon.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     Documentation/networking/device_drivers/ethernet/amazon/ena.rst
@@ -907,7 +906,7 @@ AMD KFD
 M:     Felix Kuehling <Felix.Kuehling@amd.com>
 L:     amd-gfx@lists.freedesktop.org
 S:     Supported
-T:     git git://people.freedesktop.org/~agd5f/linux
+T:     git https://gitlab.freedesktop.org/agd5f/linux.git
 F:     drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd*.[ch]
 F:     drivers/gpu/drm/amd/amdkfd/
 F:     drivers/gpu/drm/amd/include/cik_structs.h
@@ -2942,7 +2941,6 @@ S:        Maintained
 F:     drivers/hwmon/asus_atk0110.c
 
 ATLX ETHERNET DRIVERS
-M:     Jay Cliburn <jcliburn@gmail.com>
 M:     Chris Snook <chris.snook@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
@@ -3336,7 +3334,7 @@ F:        arch/riscv/net/
 X:     arch/riscv/net/bpf_jit_comp64.c
 
 BPF JIT for RISC-V (64-bit)
-M:     Björn Töpel <bjorn.topel@gmail.com>
+M:     Björn Töpel <bjorn@kernel.org>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Maintained
@@ -4922,9 +4920,8 @@ F:        Documentation/scsi/dc395x.rst
 F:     drivers/scsi/dc395x.*
 
 DCCP PROTOCOL
-M:     Gerrit Renker <gerrit@erg.abdn.ac.uk>
 L:     dccp@vger.kernel.org
-S:     Maintained
+S:     Orphan
 W:     http://www.linuxfoundation.org/collaborate/workgroups/networking/dccp
 F:     include/linux/dccp.h
 F:     include/linux/tfrc.h
@@ -9326,7 +9323,6 @@ W:        http://www.adaptec.com/
 F:     drivers/scsi/ips*
 
 IPVS
-M:     Wensong Zhang <wensong@linux-vs.org>
 M:     Simon Horman <horms@verge.net.au>
 M:     Julian Anastasov <ja@ssi.bg>
 L:     netdev@vger.kernel.org
@@ -12416,7 +12412,6 @@ F:      tools/testing/selftests/net/ipsec.c
 
 NETWORKING [IPv4/IPv6]
 M:     "David S. Miller" <davem@davemloft.net>
-M:     Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
 M:     Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
@@ -12473,7 +12468,6 @@ F:      net/ipv6/tcp*.c
 
 NETWORKING [TLS]
 M:     Boris Pismenny <borisp@nvidia.com>
-M:     Aviad Yehezkel <aviadye@nvidia.com>
 M:     John Fastabend <john.fastabend@gmail.com>
 M:     Daniel Borkmann <daniel@iogearbox.net>
 M:     Jakub Kicinski <kuba@kernel.org>
@@ -12848,7 +12842,7 @@ F:      include/misc/ocxl*
 F:     include/uapi/misc/ocxl.h
 
 OMAP AUDIO SUPPORT
-M:     Peter Ujfalusi <peter.ujfalusi@ti.com>
+M:     Peter Ujfalusi <peter.ujfalusi@gmail.com>
 M:     Jarkko Nikula <jarkko.nikula@bitmer.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:     linux-omap@vger.kernel.org
@@ -14510,10 +14504,18 @@ S:    Supported
 F:     drivers/crypto/qat/
 
 QCOM AUDIO (ASoC) DRIVERS
-M:     Patrick Lai <plai@codeaurora.org>
+M:     Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
 M:     Banajit Goswami <bgoswami@codeaurora.org>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
+F:     sound/soc/codecs/lpass-va-macro.c
+F:     sound/soc/codecs/lpass-wsa-macro.*
+F:     sound/soc/codecs/msm8916-wcd-analog.c
+F:     sound/soc/codecs/msm8916-wcd-digital.c
+F:     sound/soc/codecs/wcd9335.*
+F:     sound/soc/codecs/wcd934x.c
+F:     sound/soc/codecs/wcd-clsh-v2.*
+F:     sound/soc/codecs/wsa881x.c
 F:     sound/soc/qcom/
 
 QCOM IPA DRIVER
@@ -14818,7 +14820,7 @@ M:      Alex Deucher <alexander.deucher@amd.com>
 M:     Christian König <christian.koenig@amd.com>
 L:     amd-gfx@lists.freedesktop.org
 S:     Supported
-T:     git git://people.freedesktop.org/~agd5f/linux
+T:     git https://gitlab.freedesktop.org/agd5f/linux.git
 F:     drivers/gpu/drm/amd/
 F:     drivers/gpu/drm/radeon/
 F:     include/uapi/drm/amdgpu_drm.h
@@ -16319,6 +16321,7 @@ M:      Pekka Enberg <penberg@kernel.org>
 M:     David Rientjes <rientjes@google.com>
 M:     Joonsoo Kim <iamjoonsoo.kim@lge.com>
 M:     Andrew Morton <akpm@linux-foundation.org>
+M:     Vlastimil Babka <vbabka@suse.cz>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     include/linux/sl?b*.h
@@ -16964,7 +16967,7 @@ M:      Olivier Moysan <olivier.moysan@st.com>
 M:     Arnaud Pouliquen <arnaud.pouliquen@st.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
-F:     Documentation/devicetree/bindings/sound/st,stm32-*.txt
+F:     Documentation/devicetree/bindings/iio/adc/st,stm32-*.yaml
 F:     sound/soc/stm/
 
 STM32 TIMER/LPTIMER DRIVERS
@@ -17541,7 +17544,7 @@ F:      arch/xtensa/
 F:     drivers/irqchip/irq-xtensa-*
 
 TEXAS INSTRUMENTS ASoC DRIVERS
-M:     Peter Ujfalusi <peter.ujfalusi@ti.com>
+M:     Peter Ujfalusi <peter.ujfalusi@gmail.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
 F:     sound/soc/ti/
@@ -17851,7 +17854,7 @@ F:      Documentation/devicetree/bindings/net/nfc/trf7970a.txt
 F:     drivers/nfc/trf7970a.c
 
 TI TWL4030 SERIES SOC CODEC DRIVER
-M:     Peter Ujfalusi <peter.ujfalusi@ti.com>
+M:     Peter Ujfalusi <peter.ujfalusi@gmail.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
 F:     sound/soc/codecs/twl4030*
@@ -19071,7 +19074,6 @@ K:      regulator_get_optional
 
 VRF
 M:     David Ahern <dsahern@kernel.org>
-M:     Shrijeet Mukherjee <shrijeet@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     Documentation/networking/vrf.rst
@@ -19422,7 +19424,7 @@ F:      drivers/net/ethernet/*/*/*xdp*
 K:     (?:\b|_)xdp(?:\b|_)
 
 XDP SOCKETS (AF_XDP)
-M:     Björn Töpel <bjorn.topel@intel.com>
+M:     Björn Töpel <bjorn@kernel.org>
 M:     Magnus Karlsson <magnus.karlsson@intel.com>
 R:     Jonathan Lemon <jonathan.lemon@gmail.com>
 L:     netdev@vger.kernel.org
index 9e73f82e0d86360250203b9f51b2fcdbee564ba0..b0e4767735dca21d441c0ae373c53cf9a09ecf11 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 11
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
index 60e901cd0de6a31af593f4100c21ee2e3edc3def..5a957a9a09843c1031b7a9a3a46d5a454c417867 100644 (file)
@@ -371,7 +371,7 @@ static int __init xen_guest_init(void)
        }
        gnttab_init();
        if (!xen_initial_domain())
-               xenbus_probe(NULL);
+               xenbus_probe();
 
        /*
         * Making sure board specific code will not set up ops for
index 05e17351e4f334d765744af5172050c843bda79e..f39568b28ec1c47a5abbe2db43be5529111291fa 100644 (file)
@@ -174,8 +174,6 @@ config ARM64
        select HAVE_NMI
        select HAVE_PATA_PLATFORM
        select HAVE_PERF_EVENTS
-       select HAVE_PERF_EVENTS_NMI if ARM64_PSEUDO_NMI && HW_PERF_EVENTS
-       select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI
        select HAVE_PERF_REGS
        select HAVE_PERF_USER_STACK_DUMP
        select HAVE_REGS_AND_STACK_ACCESS_API
index 015ddffaf6caa3213813fcdcbb5601b1a3ec95d8..b56a4b2bc24864081198bc104ab6f26d6855201c 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/lse.h>
 
 #define ATOMIC_OP(op)                                                  \
-static inline void arch_##op(int i, atomic_t *v)                       \
+static __always_inline void arch_##op(int i, atomic_t *v)              \
 {                                                                      \
        __lse_ll_sc_body(op, i, v);                                     \
 }
@@ -32,7 +32,7 @@ ATOMIC_OP(atomic_sub)
 #undef ATOMIC_OP
 
 #define ATOMIC_FETCH_OP(name, op)                                      \
-static inline int arch_##op##name(int i, atomic_t *v)                  \
+static __always_inline int arch_##op##name(int i, atomic_t *v)         \
 {                                                                      \
        return __lse_ll_sc_body(op##name, i, v);                        \
 }
@@ -56,7 +56,7 @@ ATOMIC_FETCH_OPS(atomic_sub_return)
 #undef ATOMIC_FETCH_OPS
 
 #define ATOMIC64_OP(op)                                                        \
-static inline void arch_##op(long i, atomic64_t *v)                    \
+static __always_inline void arch_##op(long i, atomic64_t *v)           \
 {                                                                      \
        __lse_ll_sc_body(op, i, v);                                     \
 }
@@ -71,7 +71,7 @@ ATOMIC64_OP(atomic64_sub)
 #undef ATOMIC64_OP
 
 #define ATOMIC64_FETCH_OP(name, op)                                    \
-static inline long arch_##op##name(long i, atomic64_t *v)              \
+static __always_inline long arch_##op##name(long i, atomic64_t *v)     \
 {                                                                      \
        return __lse_ll_sc_body(op##name, i, v);                        \
 }
@@ -94,7 +94,7 @@ ATOMIC64_FETCH_OPS(atomic64_sub_return)
 #undef ATOMIC64_FETCH_OP
 #undef ATOMIC64_FETCH_OPS
 
-static inline long arch_atomic64_dec_if_positive(atomic64_t *v)
+static __always_inline long arch_atomic64_dec_if_positive(atomic64_t *v)
 {
        return __lse_ll_sc_body(atomic64_dec_if_positive, v);
 }
index 69ad25fbeae4af047de3f697b0958559b6e7ecf1..ca2cd75d32863c8301129700e0c6ab6f67183add 100644 (file)
@@ -94,8 +94,7 @@
 #endif /* CONFIG_ARM64_FORCE_52BIT */
 
 extern phys_addr_t arm64_dma_phys_limit;
-extern phys_addr_t arm64_dma32_phys_limit;
-#define ARCH_LOW_ADDRESS_LIMIT ((arm64_dma_phys_limit ? : arm64_dma32_phys_limit) - 1)
+#define ARCH_LOW_ADDRESS_LIMIT (arm64_dma_phys_limit - 1)
 
 struct debug_info {
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
index f42fd9e339815f7b97525cd30b1ebe61692393c0..3017844635874838c968780c48a1c4f22312435b 100644 (file)
@@ -75,7 +75,7 @@ int main(void)
   DEFINE(S_SDEI_TTBR1,         offsetof(struct pt_regs, sdei_ttbr1));
   DEFINE(S_PMR_SAVE,           offsetof(struct pt_regs, pmr_save));
   DEFINE(S_STACKFRAME,         offsetof(struct pt_regs, stackframe));
-  DEFINE(S_FRAME_SIZE,         sizeof(struct pt_regs));
+  DEFINE(PT_REGS_SIZE,         sizeof(struct pt_regs));
   BLANK();
 #ifdef CONFIG_COMPAT
   DEFINE(COMPAT_SIGFRAME_REGS_OFFSET,          offsetof(struct compat_sigframe, uc.uc_mcontext.arm_r0));
index a338f40e64d393b2f78d5b01b4bda24930e0db87..b3e4f9a088b1a76118205f0065fda2cc6859aa2f 100644 (file)
@@ -35,7 +35,7 @@
  */
        .macro  ftrace_regs_entry, allregs=0
        /* Make room for pt_regs, plus a callee frame */
-       sub     sp, sp, #(S_FRAME_SIZE + 16)
+       sub     sp, sp, #(PT_REGS_SIZE + 16)
 
        /* Save function arguments (and x9 for simplicity) */
        stp     x0, x1, [sp, #S_X0]
        .endif
 
        /* Save the callsite's SP and LR */
-       add     x10, sp, #(S_FRAME_SIZE + 16)
+       add     x10, sp, #(PT_REGS_SIZE + 16)
        stp     x9, x10, [sp, #S_LR]
 
        /* Save the PC after the ftrace callsite */
        str     x30, [sp, #S_PC]
 
        /* Create a frame record for the callsite above pt_regs */
-       stp     x29, x9, [sp, #S_FRAME_SIZE]
-       add     x29, sp, #S_FRAME_SIZE
+       stp     x29, x9, [sp, #PT_REGS_SIZE]
+       add     x29, sp, #PT_REGS_SIZE
 
        /* Create our frame record within pt_regs. */
        stp     x29, x30, [sp, #S_STACKFRAME]
@@ -120,7 +120,7 @@ ftrace_common_return:
        ldr     x9, [sp, #S_PC]
 
        /* Restore the callsite's SP */
-       add     sp, sp, #S_FRAME_SIZE + 16
+       add     sp, sp, #PT_REGS_SIZE + 16
 
        ret     x9
 SYM_CODE_END(ftrace_common)
@@ -130,7 +130,7 @@ SYM_CODE_START(ftrace_graph_caller)
        ldr     x0, [sp, #S_PC]
        sub     x0, x0, #AARCH64_INSN_SIZE      // ip (callsite's BL insn)
        add     x1, sp, #S_LR                   // parent_ip (callsite's LR)
-       ldr     x2, [sp, #S_FRAME_SIZE]         // parent fp (callsite's FP)
+       ldr     x2, [sp, #PT_REGS_SIZE]         // parent fp (callsite's FP)
        bl      prepare_ftrace_return
        b       ftrace_common_return
 SYM_CODE_END(ftrace_graph_caller)
index a8c3e7aaca749427ffd0a6aeb45f88dc3d23138a..c9bae73f2621a345d9b590cf896a2e8ecc5d47c4 100644 (file)
@@ -75,7 +75,7 @@ alternative_else_nop_endif
        .endif
 #endif
 
-       sub     sp, sp, #S_FRAME_SIZE
+       sub     sp, sp, #PT_REGS_SIZE
 #ifdef CONFIG_VMAP_STACK
        /*
         * Test whether the SP has overflowed, without corrupting a GPR.
@@ -96,7 +96,7 @@ alternative_else_nop_endif
         * userspace, and can clobber EL0 registers to free up GPRs.
         */
 
-       /* Stash the original SP (minus S_FRAME_SIZE) in tpidr_el0. */
+       /* Stash the original SP (minus PT_REGS_SIZE) in tpidr_el0. */
        msr     tpidr_el0, x0
 
        /* Recover the original x0 value and stash it in tpidrro_el0 */
@@ -253,7 +253,7 @@ alternative_else_nop_endif
 
        scs_load tsk, x20
        .else
-       add     x21, sp, #S_FRAME_SIZE
+       add     x21, sp, #PT_REGS_SIZE
        get_current_task tsk
        .endif /* \el == 0 */
        mrs     x22, elr_el1
@@ -377,7 +377,7 @@ alternative_else_nop_endif
        ldp     x26, x27, [sp, #16 * 13]
        ldp     x28, x29, [sp, #16 * 14]
        ldr     lr, [sp, #S_LR]
-       add     sp, sp, #S_FRAME_SIZE           // restore sp
+       add     sp, sp, #PT_REGS_SIZE           // restore sp
 
        .if     \el == 0
 alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
@@ -580,12 +580,12 @@ __bad_stack:
 
        /*
         * Store the original GPRs to the new stack. The orginal SP (minus
-        * S_FRAME_SIZE) was stashed in tpidr_el0 by kernel_ventry.
+        * PT_REGS_SIZE) was stashed in tpidr_el0 by kernel_ventry.
         */
-       sub     sp, sp, #S_FRAME_SIZE
+       sub     sp, sp, #PT_REGS_SIZE
        kernel_entry 1
        mrs     x0, tpidr_el0
-       add     x0, x0, #S_FRAME_SIZE
+       add     x0, x0, #PT_REGS_SIZE
        str     x0, [sp, #S_SP]
 
        /* Stash the regs for handle_bad_stack */
index 38bb07eff8720d238e1d03759f59fb76e8f5ee05..3605f77ad4df1796c52b01a2bb959569d5ea1a83 100644 (file)
@@ -23,8 +23,6 @@
 #include <linux/platform_device.h>
 #include <linux/sched_clock.h>
 #include <linux/smp.h>
-#include <linux/nmi.h>
-#include <linux/cpufreq.h>
 
 /* ARMv8 Cortex-A53 specific event types. */
 #define ARMV8_A53_PERFCTR_PREF_LINEFILL                                0xC2
@@ -1250,21 +1248,10 @@ static struct platform_driver armv8_pmu_driver = {
 
 static int __init armv8_pmu_driver_init(void)
 {
-       int ret;
-
        if (acpi_disabled)
-               ret = platform_driver_register(&armv8_pmu_driver);
+               return platform_driver_register(&armv8_pmu_driver);
        else
-               ret = arm_pmu_acpi_probe(armv8_pmuv3_init);
-
-       /*
-        * Try to re-initialize lockup detector after PMU init in
-        * case PMU events are triggered via NMIs.
-        */
-       if (ret == 0 && arm_pmu_irq_is_nmi())
-               lockup_detector_init();
-
-       return ret;
+               return arm_pmu_acpi_probe(armv8_pmuv3_init);
 }
 device_initcall(armv8_pmu_driver_init)
 
@@ -1322,27 +1309,3 @@ void arch_perf_update_userpage(struct perf_event *event,
        userpg->cap_user_time_zero = 1;
        userpg->cap_user_time_short = 1;
 }
-
-#ifdef CONFIG_HARDLOCKUP_DETECTOR_PERF
-/*
- * Safe maximum CPU frequency in case a particular platform doesn't implement
- * cpufreq driver. Although, architecture doesn't put any restrictions on
- * maximum frequency but 5 GHz seems to be safe maximum given the available
- * Arm CPUs in the market which are clocked much less than 5 GHz. On the other
- * hand, we can't make it much higher as it would lead to a large hard-lockup
- * detection timeout on parts which are running slower (eg. 1GHz on
- * Developerbox) and doesn't possess a cpufreq driver.
- */
-#define SAFE_MAX_CPU_FREQ      5000000000UL // 5 GHz
-u64 hw_nmi_get_sample_period(int watchdog_thresh)
-{
-       unsigned int cpu = smp_processor_id();
-       unsigned long max_cpu_freq;
-
-       max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
-       if (!max_cpu_freq)
-               max_cpu_freq = SAFE_MAX_CPU_FREQ;
-
-       return (u64)max_cpu_freq * watchdog_thresh;
-}
-#endif
index 89c64ada8732413bc28ae5669651b0adf5efe702..66aac2881ba84ea06b2318b45f42919982c31c98 100644 (file)
@@ -352,8 +352,8 @@ kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned int esr)
        unsigned long addr = instruction_pointer(regs);
        struct kprobe *cur = kprobe_running();
 
-       if (cur && (kcb->kprobe_status == KPROBE_HIT_SS)
-           && ((unsigned long)&cur->ainsn.api.insn[1] == addr)) {
+       if (cur && (kcb->kprobe_status & (KPROBE_HIT_SS | KPROBE_REENTER)) &&
+           ((unsigned long)&cur->ainsn.api.insn[1] == addr)) {
                kprobes_restore_local_irqflag(kcb, regs);
                post_kprobe_handler(cur, kcb, regs);
 
index 890ca72c5a5148a662c52de78f42c81c88abf420..288a84e253ccbecc227a8356e20819a1099266bd 100644 (file)
@@ -25,7 +25,7 @@
        stp x24, x25, [sp, #S_X24]
        stp x26, x27, [sp, #S_X26]
        stp x28, x29, [sp, #S_X28]
-       add x0, sp, #S_FRAME_SIZE
+       add x0, sp, #PT_REGS_SIZE
        stp lr, x0, [sp, #S_LR]
        /*
         * Construct a useful saved PSTATE
@@ -62,7 +62,7 @@
        .endm
 
 SYM_CODE_START(kretprobe_trampoline)
-       sub sp, sp, #S_FRAME_SIZE
+       sub sp, sp, #PT_REGS_SIZE
 
        save_all_base_regs
 
@@ -76,7 +76,7 @@ SYM_CODE_START(kretprobe_trampoline)
 
        restore_all_base_regs
 
-       add sp, sp, #S_FRAME_SIZE
+       add sp, sp, #PT_REGS_SIZE
        ret
 
 SYM_CODE_END(kretprobe_trampoline)
index f71d6ce4673f53e5e935514791a52d6149b3b9e5..6237486ff6bb73db074d6e275c7d739548a1a7d0 100644 (file)
@@ -914,13 +914,6 @@ static void do_signal(struct pt_regs *regs)
 asmlinkage void do_notify_resume(struct pt_regs *regs,
                                 unsigned long thread_flags)
 {
-       /*
-        * The assembly code enters us with IRQs off, but it hasn't
-        * informed the tracing code of that for efficiency reasons.
-        * Update the trace code with the current status.
-        */
-       trace_hardirqs_off();
-
        do {
                if (thread_flags & _TIF_NEED_RESCHED) {
                        /* Unmask Debug and SError for the next task */
index f61e9d8cc55a1efe2cda0bb94f67177bb79acef6..c2877c332f2dc636a403193bff46e2df84001df5 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <asm/daifflags.h>
 #include <asm/debug-monitors.h>
+#include <asm/exception.h>
 #include <asm/fpsimd.h>
 #include <asm/syscall.h>
 #include <asm/thread_info.h>
@@ -165,15 +166,8 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
        if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) {
                local_daif_mask();
                flags = current_thread_info()->flags;
-               if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP)) {
-                       /*
-                        * We're off to userspace, where interrupts are
-                        * always enabled after we restore the flags from
-                        * the SPSR.
-                        */
-                       trace_hardirqs_on();
+               if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP))
                        return;
-               }
                local_daif_restore(DAIF_PROCCTX);
        }
 
index 3c40da479899dbb667f427ce8206c52d35e0c16e..35d75c60e2b8df0ed065e6090082c498d25897f7 100644 (file)
@@ -709,10 +709,11 @@ static int do_tag_check_fault(unsigned long far, unsigned int esr,
                              struct pt_regs *regs)
 {
        /*
-        * The architecture specifies that bits 63:60 of FAR_EL1 are UNKNOWN for tag
-        * check faults. Mask them out now so that userspace doesn't see them.
+        * The architecture specifies that bits 63:60 of FAR_EL1 are UNKNOWN
+        * for tag check faults. Set them to corresponding bits in the untagged
+        * address.
         */
-       far &= (1UL << 60) - 1;
+       far = (__untagged_addr(far) & ~MTE_TAG_MASK) | (far & MTE_TAG_MASK);
        do_bad_area(far, esr, regs);
        return 0;
 }
index 7deddf56f7c3ef3a17d1b87604088c2ed30922ba..709d98fea90cc1f8b08c85864fbaa6fd6a0b7d42 100644 (file)
@@ -53,13 +53,13 @@ s64 memstart_addr __ro_after_init = -1;
 EXPORT_SYMBOL(memstart_addr);
 
 /*
- * We create both ZONE_DMA and ZONE_DMA32. ZONE_DMA covers the first 1G of
- * memory as some devices, namely the Raspberry Pi 4, have peripherals with
- * this limited view of the memory. ZONE_DMA32 will cover the rest of the 32
- * bit addressable memory area.
+ * If the corresponding config options are enabled, we create both ZONE_DMA
+ * and ZONE_DMA32. By default ZONE_DMA covers the 32-bit addressable memory
+ * unless restricted on specific platforms (e.g. 30-bit on Raspberry Pi 4).
+ * In such case, ZONE_DMA32 covers the rest of the 32-bit addressable memory,
+ * otherwise it is empty.
  */
 phys_addr_t arm64_dma_phys_limit __ro_after_init;
-phys_addr_t arm64_dma32_phys_limit __ro_after_init;
 
 #ifdef CONFIG_KEXEC_CORE
 /*
@@ -84,7 +84,7 @@ static void __init reserve_crashkernel(void)
 
        if (crash_base == 0) {
                /* Current arm64 boot protocol requires 2MB alignment */
-               crash_base = memblock_find_in_range(0, arm64_dma32_phys_limit,
+               crash_base = memblock_find_in_range(0, arm64_dma_phys_limit,
                                crash_size, SZ_2M);
                if (crash_base == 0) {
                        pr_warn("cannot allocate crashkernel (size:0x%llx)\n",
@@ -196,6 +196,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
        unsigned long max_zone_pfns[MAX_NR_ZONES]  = {0};
        unsigned int __maybe_unused acpi_zone_dma_bits;
        unsigned int __maybe_unused dt_zone_dma_bits;
+       phys_addr_t __maybe_unused dma32_phys_limit = max_zone_phys(32);
 
 #ifdef CONFIG_ZONE_DMA
        acpi_zone_dma_bits = fls64(acpi_iort_dma_get_max_cpu_address());
@@ -205,8 +206,12 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
        max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit);
 #endif
 #ifdef CONFIG_ZONE_DMA32
-       max_zone_pfns[ZONE_DMA32] = PFN_DOWN(arm64_dma32_phys_limit);
+       max_zone_pfns[ZONE_DMA32] = PFN_DOWN(dma32_phys_limit);
+       if (!arm64_dma_phys_limit)
+               arm64_dma_phys_limit = dma32_phys_limit;
 #endif
+       if (!arm64_dma_phys_limit)
+               arm64_dma_phys_limit = PHYS_MASK + 1;
        max_zone_pfns[ZONE_NORMAL] = max;
 
        free_area_init(max_zone_pfns);
@@ -394,16 +399,9 @@ void __init arm64_memblock_init(void)
 
        early_init_fdt_scan_reserved_mem();
 
-       if (IS_ENABLED(CONFIG_ZONE_DMA32))
-               arm64_dma32_phys_limit = max_zone_phys(32);
-       else
-               arm64_dma32_phys_limit = PHYS_MASK + 1;
-
        reserve_elfcorehdr();
 
        high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
-
-       dma_contiguous_reserve(arm64_dma32_phys_limit);
 }
 
 void __init bootmem_init(void)
@@ -438,6 +436,11 @@ void __init bootmem_init(void)
        sparse_init();
        zone_sizes_init(min, max);
 
+       /*
+        * Reserve the CMA area after arm64_dma_phys_limit was initialised.
+        */
+       dma_contiguous_reserve(arm64_dma_phys_limit);
+
        /*
         * request_standard_resources() depends on crashkernel's memory being
         * reserved, so do it here.
@@ -455,7 +458,7 @@ void __init bootmem_init(void)
 void __init mem_init(void)
 {
        if (swiotlb_force == SWIOTLB_FORCE ||
-           max_pfn > PFN_DOWN(arm64_dma_phys_limit ? : arm64_dma32_phys_limit))
+           max_pfn > PFN_DOWN(arm64_dma_phys_limit))
                swiotlb_init(1);
        else
                swiotlb_force = SWIOTLB_NO_FORCE;
index dd8c166ffd7b5ffbf56e3217a209512745d7e65b..42ed5248fae9876875a71f5b66c40a0a884c8749 100644 (file)
@@ -3,6 +3,7 @@
 #define _ASM_IA64_SPARSEMEM_H
 
 #ifdef CONFIG_SPARSEMEM
+#include <asm/page.h>
 /*
  * SECTION_SIZE_BITS            2^N: how big each section will be
  * MAX_PHYSMEM_BITS             2^N: how much memory we can have in that space
index c61c641674e6b4765495cf4cc9751af7b54d539d..e3946b06e840a6b2e6c5a297e81f16db50a4c914 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/libfdt.h>
 
 #include <asm/addrspace.h>
+#include <asm/unaligned.h>
 
 /*
  * These two variables specify the free mem region
@@ -117,7 +118,7 @@ void decompress_kernel(unsigned long boot_heap_start)
                dtb_size = fdt_totalsize((void *)&__appended_dtb);
 
                /* last four bytes is always image size in little endian */
-               image_size = le32_to_cpup((void *)&__image_end - 4);
+               image_size = get_unaligned_le32((void *)&__image_end - 4);
 
                /* copy dtb to where the booted kernel will expect it */
                memcpy((void *)VMLINUX_LOAD_ADDRESS_ULL + image_size,
index bd47e15d02c73ea599e896a197500896ee7c174a..be5d4afcd30f930e6eb828d55a05099be8402a5d 100644 (file)
@@ -1444,7 +1444,7 @@ static void octeon_irq_setup_secondary_ciu2(void)
 static int __init octeon_irq_init_ciu(
        struct device_node *ciu_node, struct device_node *parent)
 {
-       unsigned int i, r;
+       int i, r;
        struct irq_chip *chip;
        struct irq_chip *chip_edge;
        struct irq_chip *chip_mbox;
index 6ee3f7218c675b6c605d06776ef1164ef6d13441..c4441416e96b6a28c91e884a9594f4b3dbb5efd9 100644 (file)
@@ -103,4 +103,11 @@ jiffies_to_old_timeval32(unsigned long jiffies, struct old_timeval32 *value)
 #undef ns_to_kernel_old_timeval
 #define ns_to_kernel_old_timeval ns_to_old_timeval32
 
+/*
+ * Some data types as stored in coredump.
+ */
+#define user_long_t             compat_long_t
+#define user_siginfo_t          compat_siginfo_t
+#define copy_siginfo_to_external        copy_siginfo_to_external32
+
 #include "../../../fs/binfmt_elf.c"
index 6dd103d3cebba2f299fa60489b65c9377f975ee4..7b2a23f48c1ac227f6bad0eb4eadb068c28017ea 100644 (file)
@@ -106,4 +106,11 @@ jiffies_to_old_timeval32(unsigned long jiffies, struct old_timeval32 *value)
 #undef ns_to_kernel_old_timeval
 #define ns_to_kernel_old_timeval ns_to_old_timeval32
 
+/*
+ * Some data types as stored in coredump.
+ */
+#define user_long_t             compat_long_t
+#define user_siginfo_t          compat_siginfo_t
+#define copy_siginfo_to_external        copy_siginfo_to_external32
+
 #include "../../../fs/binfmt_elf.c"
index 47aeb3350a76029edaf96a03d29d8ce975058232..0e365b7c742d93b0a0c1ce06fdbcb0aa8b180dff 100644 (file)
@@ -187,8 +187,14 @@ static int __init relocate_exception_table(long offset)
 static inline __init unsigned long rotate_xor(unsigned long hash,
                                              const void *area, size_t size)
 {
-       size_t i;
-       unsigned long *ptr = (unsigned long *)area;
+       const typeof(hash) *ptr = PTR_ALIGN(area, sizeof(hash));
+       size_t diff, i;
+
+       diff = (void *)ptr - area;
+       if (unlikely(size < diff + sizeof(hash)))
+               return hash;
+
+       size = ALIGN_DOWN(size - diff, sizeof(hash));
 
        for (i = 0; i < size / sizeof(hash); i++) {
                /* Rotate by odd number of bits and XOR. */
index 7d6b4a77b379d8e2f14aeb862128e481e8b20850..c298061c70a7ee2ed6b1a71db0d5399164e45a11 100644 (file)
@@ -31,7 +31,7 @@
 void __iomem *ioremap(phys_addr_t offset, unsigned long size);
 
 #define iounmap iounmap
-extern void iounmap(void *addr);
+extern void iounmap(void __iomem *addr);
 
 #include <asm-generic/io.h>
 
index 5aed97a18bac934dd7e0abfb1e9b5d44c99dcfec..daae13a76743be694d295c570419dcf31dc2c7fb 100644 (file)
@@ -77,7 +77,7 @@ void __iomem *__ref ioremap(phys_addr_t addr, unsigned long size)
 }
 EXPORT_SYMBOL(ioremap);
 
-void iounmap(void *addr)
+void iounmap(void __iomem *addr)
 {
        /* If the page is from the fixmap pool then we just clear out
         * the fixmap mapping.
index 81671aa365b34d39dde25f31b69f19d211458354..77c635c2c90d43f2979006e280ba8e1071ea5b41 100644 (file)
@@ -103,6 +103,8 @@ int gettimeofday_fallback(struct __kernel_old_timeval *_tv, struct timezone *_tz
        return do_syscall_2(__NR_gettimeofday, (unsigned long)_tv, (unsigned long)_tz);
 }
 
+#ifdef __powerpc64__
+
 static __always_inline
 int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 {
@@ -115,10 +117,22 @@ int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
        return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
 }
 
-#ifdef CONFIG_VDSO32
+#else
 
 #define BUILD_VDSO32           1
 
+static __always_inline
+int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
+{
+       return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned long)_ts);
+}
+
+static __always_inline
+int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
+{
+       return do_syscall_2(__NR_clock_getres_time64, _clkid, (unsigned long)_ts);
+}
+
 static __always_inline
 int clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
 {
index 8e0b1298bf19bb9c7d56447bb02eb31dec6d0dce..4ab426b8b0e02276423241b25d2386eedc24b90e 100644 (file)
@@ -187,6 +187,12 @@ SECTIONS
        .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
                _sinittext = .;
                INIT_TEXT
+
+               /*
+                *.init.text might be RO so we must ensure this section ends on
+                * a page boundary.
+                */
+               . = ALIGN(PAGE_SIZE);
                _einittext = .;
 #ifdef CONFIG_PPC64
                *(.tramp.ftrace.init);
@@ -200,6 +206,8 @@ SECTIONS
                EXIT_TEXT
        }
 
+       . = ALIGN(PAGE_SIZE);
+
        INIT_DATA_SECTION(16)
 
        . = ALIGN(8);
index 81b76d44725d7c50d3cdf2f406705b03ba5d5b56..e9e2c1f0a690594389a2d034a56f59f8a376a89f 100644 (file)
@@ -137,7 +137,7 @@ config PA_BITS
 
 config PAGE_OFFSET
        hex
-       default 0xC0000000 if 32BIT && MAXPHYSMEM_2GB
+       default 0xC0000000 if 32BIT && MAXPHYSMEM_1GB
        default 0x80000000 if 64BIT && !MMU
        default 0xffffffff80000000 if 64BIT && MAXPHYSMEM_2GB
        default 0xffffffe000000000 if 64BIT && MAXPHYSMEM_128GB
@@ -247,10 +247,12 @@ config MODULE_SECTIONS
 
 choice
        prompt "Maximum Physical Memory"
-       default MAXPHYSMEM_2GB if 32BIT
+       default MAXPHYSMEM_1GB if 32BIT
        default MAXPHYSMEM_2GB if 64BIT && CMODEL_MEDLOW
        default MAXPHYSMEM_128GB if 64BIT && CMODEL_MEDANY
 
+       config MAXPHYSMEM_1GB
+               bool "1GiB"
        config MAXPHYSMEM_2GB
                bool "2GiB"
        config MAXPHYSMEM_128GB
index 4a2729f5ca3f0113be3e02e72f9c427fe02207cc..24d75a146e02d441c167b2b5028e3303eb80f1e3 100644 (file)
@@ -88,7 +88,9 @@
        phy-mode = "gmii";
        phy-handle = <&phy0>;
        phy0: ethernet-phy@0 {
+               compatible = "ethernet-phy-id0007.0771";
                reg = <0>;
+               reset-gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
        };
 };
 
index d222d353d86d40823e249bfdfa80e4a8bd3f4045..8c3d1e4517031ac56b07c1c1c393b0d7b64cee79 100644 (file)
@@ -64,6 +64,8 @@ CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_VIRTIO=y
 CONFIG_SPI=y
 CONFIG_SPI_SIFIVE=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SIFIVE=y
 # CONFIG_PTP_1588_CLOCK is not set
 CONFIG_POWER_RESET=y
 CONFIG_DRM=y
index 41a72861987ccc9a0406b4926bd21e8e2c728ebb..251e1db088fa2d8508762bcc5e459f2e7b120684 100644 (file)
@@ -99,7 +99,6 @@
                                | _PAGE_DIRTY)
 
 #define PAGE_KERNEL            __pgprot(_PAGE_KERNEL)
-#define PAGE_KERNEL_EXEC       __pgprot(_PAGE_KERNEL | _PAGE_EXEC)
 #define PAGE_KERNEL_READ       __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
 #define PAGE_KERNEL_EXEC       __pgprot(_PAGE_KERNEL | _PAGE_EXEC)
 #define PAGE_KERNEL_READ_EXEC  __pgprot((_PAGE_KERNEL & ~_PAGE_WRITE) \
index 8454f746bbfd0f3ed6712537847deb332d0e32d0..1453a2f563bcc8180101763585e776c0abe5e426 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <linux/types.h>
 
-#ifndef GENERIC_TIME_VSYSCALL
+#ifndef CONFIG_GENERIC_TIME_VSYSCALL
 struct vdso_data {
 };
 #endif
index de59dd457b41584083dee7866e189bbb396945dd..d8678135704425973c3ba11d058dd56babef2481 100644 (file)
@@ -26,7 +26,16 @@ cache_get_priv_group(struct cacheinfo *this_leaf)
 
 static struct cacheinfo *get_cacheinfo(u32 level, enum cache_type type)
 {
-       struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(smp_processor_id());
+       /*
+        * Using raw_smp_processor_id() elides a preemptability check, but this
+        * is really indicative of a larger problem: the cacheinfo UABI assumes
+        * that cores have a homonogenous view of the cache hierarchy.  That
+        * happens to be the case for the current set of RISC-V systems, but
+        * likely won't be true in general.  Since there's no way to provide
+        * correct information for these systems via the current UABI we're
+        * just eliding the check for now.
+        */
+       struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(raw_smp_processor_id());
        struct cacheinfo *this_leaf;
        int index;
 
index 524d918f3601b2f73b8d4cf88a1936ad507b5f15..744f3209c48d0b30d0e67f7b00f136b75d5e0fd0 100644 (file)
@@ -124,15 +124,15 @@ skip_context_tracking:
        REG_L a1, (a1)
        jr a1
 1:
-#ifdef CONFIG_TRACE_IRQFLAGS
-       call trace_hardirqs_on
-#endif
        /*
         * Exceptions run with interrupts enabled or disabled depending on the
         * state of SR_PIE in m/sstatus.
         */
        andi t0, s1, SR_PIE
        beqz t0, 1f
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call trace_hardirqs_on
+#endif
        csrs CSR_STATUS, SR_IE
 
 1:
@@ -155,6 +155,15 @@ skip_context_tracking:
        tail do_trap_unknown
 
 handle_syscall:
+#ifdef CONFIG_RISCV_M_MODE
+       /*
+        * When running is M-Mode (no MMU config), MPIE does not get set.
+        * As a result, we need to force enable interrupts here because
+        * handle_exception did not do set SR_IE as it always sees SR_PIE
+        * being cleared.
+        */
+       csrs CSR_STATUS, SR_IE
+#endif
 #if defined(CONFIG_TRACE_IRQFLAGS) || defined(CONFIG_CONTEXT_TRACKING)
        /* Recover a0 - a7 for system calls */
        REG_L a0, PT_A0(sp)
@@ -186,14 +195,7 @@ check_syscall_nr:
         * Syscall number held in a7.
         * If syscall number is above allowed value, redirect to ni_syscall.
         */
-       bge a7, t0, 1f
-       /*
-        * Check if syscall is rejected by tracer, i.e., a7 == -1.
-        * If yes, we pretend it was executed.
-        */
-       li t1, -1
-       beq a7, t1, ret_from_syscall_rejected
-       blt a7, t1, 1f
+       bgeu a7, t0, 1f
        /* Call syscall */
        la s0, sys_call_table
        slli t0, a7, RISCV_LGPTR
index 1d85e9bf783cf907ba1e0ef17a0d529c1f9f5cb6..3fa3f26dde85664a6ccd993d9ee3bdcdf118eee3 100644 (file)
@@ -127,7 +127,9 @@ static void __init init_resources(void)
 {
        struct memblock_region *region = NULL;
        struct resource *res = NULL;
-       int ret = 0;
+       struct resource *mem_res = NULL;
+       size_t mem_res_sz = 0;
+       int ret = 0, i = 0;
 
        code_res.start = __pa_symbol(_text);
        code_res.end = __pa_symbol(_etext) - 1;
@@ -145,16 +147,17 @@ static void __init init_resources(void)
        bss_res.end = __pa_symbol(__bss_stop) - 1;
        bss_res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
 
+       mem_res_sz = (memblock.memory.cnt + memblock.reserved.cnt) * sizeof(*mem_res);
+       mem_res = memblock_alloc(mem_res_sz, SMP_CACHE_BYTES);
+       if (!mem_res)
+               panic("%s: Failed to allocate %zu bytes\n", __func__, mem_res_sz);
        /*
         * Start by adding the reserved regions, if they overlap
         * with /memory regions, insert_resource later on will take
         * care of it.
         */
        for_each_reserved_mem_region(region) {
-               res = memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
-               if (!res)
-                       panic("%s: Failed to allocate %zu bytes\n", __func__,
-                             sizeof(struct resource));
+               res = &mem_res[i++];
 
                res->name = "Reserved";
                res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
@@ -171,8 +174,10 @@ static void __init init_resources(void)
                 * Ignore any other reserved regions within
                 * system memory.
                 */
-               if (memblock_is_memory(res->start))
+               if (memblock_is_memory(res->start)) {
+                       memblock_free((phys_addr_t) res, sizeof(struct resource));
                        continue;
+               }
 
                ret = add_resource(&iomem_resource, res);
                if (ret < 0)
@@ -181,10 +186,7 @@ static void __init init_resources(void)
 
        /* Add /memory regions to the resource tree */
        for_each_mem_region(region) {
-               res = memblock_alloc(sizeof(struct resource), SMP_CACHE_BYTES);
-               if (!res)
-                       panic("%s: Failed to allocate %zu bytes\n", __func__,
-                             sizeof(struct resource));
+               res = &mem_res[i++];
 
                if (unlikely(memblock_is_nomap(region))) {
                        res->name = "Reserved";
@@ -205,9 +207,9 @@ static void __init init_resources(void)
        return;
 
  error:
-       memblock_free((phys_addr_t) res, sizeof(struct resource));
        /* Better an empty resource tree than an inconsistent one */
        release_child_resources(&iomem_resource);
+       memblock_free((phys_addr_t) mem_res, mem_res_sz);
 }
 
 
index 48b870a685b3092f863474539ffd7ecfd00a0ffe..df5d2da7c40be3fa9ec41e464911277b98321db3 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <asm/stacktrace.h>
 
-register unsigned long sp_in_global __asm__("sp");
+register const unsigned long sp_in_global __asm__("sp");
 
 #ifdef CONFIG_FRAME_POINTER
 
@@ -28,9 +28,8 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
                sp = user_stack_pointer(regs);
                pc = instruction_pointer(regs);
        } else if (task == NULL || task == current) {
-               const register unsigned long current_sp = sp_in_global;
                fp = (unsigned long)__builtin_frame_address(0);
-               sp = current_sp;
+               sp = sp_in_global;
                pc = (unsigned long)walk_stackframe;
        } else {
                /* task blocked in __switch_to */
index 4d3a1048ad8b1cbc690c75321933e9057a2b69b6..8a5cf99c07762403ebd55ba6f54e03005e28b7e4 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2017 SiFive
  */
 
+#include <linux/of_clk.h>
 #include <linux/clocksource.h>
 #include <linux/delay.h>
 #include <asm/sbi.h>
@@ -24,6 +25,8 @@ void __init time_init(void)
        riscv_timebase = prop;
 
        lpj_fine = riscv_timebase / HZ;
+
+       of_clk_init(NULL);
        timer_probe();
 }
 
index 678204231700cad475be9334ab77cd46cefc6fdb..3f1d35e7c98a62d9b3113999e45938e2b97dfbab 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/binfmts.h>
 #include <linux/err.h>
 #include <asm/page.h>
-#ifdef GENERIC_TIME_VSYSCALL
+#ifdef CONFIG_GENERIC_TIME_VSYSCALL
 #include <vdso/datapage.h>
 #else
 #include <asm/vdso.h>
index bf5379135e39b628619de135632876d5338abe9d..7cd4993f4ff21a932b6ef29512f685ea4e947f9a 100644 (file)
@@ -157,9 +157,10 @@ disable:
 void __init setup_bootmem(void)
 {
        phys_addr_t mem_start = 0;
-       phys_addr_t start, end = 0;
+       phys_addr_t start, dram_end, end = 0;
        phys_addr_t vmlinux_end = __pa_symbol(&_end);
        phys_addr_t vmlinux_start = __pa_symbol(&_start);
+       phys_addr_t max_mapped_addr = __pa(~(ulong)0);
        u64 i;
 
        /* Find the memory region containing the kernel */
@@ -181,7 +182,18 @@ void __init setup_bootmem(void)
        /* Reserve from the start of the kernel to the end of the kernel */
        memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
 
-       max_pfn = PFN_DOWN(memblock_end_of_DRAM());
+       dram_end = memblock_end_of_DRAM();
+
+       /*
+        * memblock allocator is not aware of the fact that last 4K bytes of
+        * the addressable memory can not be mapped because of IS_ERR_VALUE
+        * macro. Make sure that last 4k bytes are not usable by memblock
+        * if end of dram is equal to maximum addressable memory.
+        */
+       if (max_mapped_addr == (dram_end - 1))
+               memblock_set_current_limit(max_mapped_addr - 4096);
+
+       max_pfn = PFN_DOWN(dram_end);
        max_low_pfn = max_pfn;
        dma32_phys_limit = min(4UL * SZ_1G, (unsigned long)PFN_PHYS(max_low_pfn));
        set_max_mapnr(max_low_pfn);
index 12ddd1f6bf70c8e96ac92b02e0b37c8e22c51043..a8a2ffd9114aaa22c60661c7cd2d80023747cb2e 100644 (file)
@@ -93,8 +93,8 @@ void __init kasan_init(void)
                                                                VMALLOC_END));
 
        for_each_mem_range(i, &_start, &_end) {
-               void *start = (void *)_start;
-               void *end = (void *)_end;
+               void *start = (void *)__va(_start);
+               void *end = (void *)__va(_end);
 
                if (start >= end)
                        break;
index e04d90af4c27cd4966351d277e945ff4df47461b..6375967a8244dc4e6777d8ff95de1be33ea77e06 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/hyperv-tlfs.h>
 #include <asm/mshyperv.h>
 #include <asm/idtentry.h>
+#include <linux/kexec.h>
 #include <linux/version.h>
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
@@ -26,6 +27,8 @@
 #include <linux/syscore_ops.h>
 #include <clocksource/hyperv_timer.h>
 
+int hyperv_init_cpuhp;
+
 void *hv_hypercall_pg;
 EXPORT_SYMBOL_GPL(hv_hypercall_pg);
 
@@ -312,6 +315,25 @@ static struct syscore_ops hv_syscore_ops = {
        .resume         = hv_resume,
 };
 
+static void (* __initdata old_setup_percpu_clockev)(void);
+
+static void __init hv_stimer_setup_percpu_clockev(void)
+{
+       /*
+        * Ignore any errors in setting up stimer clockevents
+        * as we can run with the LAPIC timer as a fallback.
+        */
+       (void)hv_stimer_alloc();
+
+       /*
+        * Still register the LAPIC timer, because the direct-mode STIMER is
+        * not supported by old versions of Hyper-V. This also allows users
+        * to switch to LAPIC timer via /sys, if they want to.
+        */
+       if (old_setup_percpu_clockev)
+               old_setup_percpu_clockev();
+}
+
 /*
  * This function is to be invoked early in the boot sequence after the
  * hypervisor has been detected.
@@ -390,10 +412,14 @@ void __init hyperv_init(void)
        wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
 
        /*
-        * Ignore any errors in setting up stimer clockevents
-        * as we can run with the LAPIC timer as a fallback.
+        * hyperv_init() is called before LAPIC is initialized: see
+        * apic_intr_mode_init() -> x86_platform.apic_post_init() and
+        * apic_bsp_setup() -> setup_local_APIC(). The direct-mode STIMER
+        * depends on LAPIC, so hv_stimer_alloc() should be called from
+        * x86_init.timers.setup_percpu_clockev.
         */
-       (void)hv_stimer_alloc();
+       old_setup_percpu_clockev = x86_init.timers.setup_percpu_clockev;
+       x86_init.timers.setup_percpu_clockev = hv_stimer_setup_percpu_clockev;
 
        hv_apic_init();
 
@@ -401,6 +427,7 @@ void __init hyperv_init(void)
 
        register_syscore_ops(&hv_syscore_ops);
 
+       hyperv_init_cpuhp = cpuhp;
        return;
 
 remove_cpuhp_state:
index 5208ba49c89a96144ba52d82cabc21ad39a743e8..2c87350c1fb095149a06709cbc0b11f2427f7acc 100644 (file)
@@ -66,11 +66,17 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus,
        if (!hv_hypercall_pg)
                goto do_native;
 
-       if (cpumask_empty(cpus))
-               return;
-
        local_irq_save(flags);
 
+       /*
+        * Only check the mask _after_ interrupt has been disabled to avoid the
+        * mask changing under our feet.
+        */
+       if (cpumask_empty(cpus)) {
+               local_irq_restore(flags);
+               return;
+       }
+
        flush_pcpu = (struct hv_tlb_flush **)
                     this_cpu_ptr(hyperv_pcpu_input_arg);
 
index ffc289992d1b0f5bd81eeeed98feae67d71dfb22..30f76b96685799c7e95cfff039d265a1dc42dea0 100644 (file)
@@ -74,6 +74,8 @@ static inline void hv_disable_stimer0_percpu_irq(int irq) {}
 
 
 #if IS_ENABLED(CONFIG_HYPERV)
+extern int hyperv_init_cpuhp;
+
 extern void *hv_hypercall_pg;
 extern void  __percpu  **hyperv_pcpu_input_arg;
 
index f628e3dc150f38088dafb158857335f2f83866bf..43b54bef5448fa360c9ff21444b62fc678e80fd7 100644 (file)
@@ -135,14 +135,32 @@ static void hv_machine_shutdown(void)
 {
        if (kexec_in_progress && hv_kexec_handler)
                hv_kexec_handler();
+
+       /*
+        * Call hv_cpu_die() on all the CPUs, otherwise later the hypervisor
+        * corrupts the old VP Assist Pages and can crash the kexec kernel.
+        */
+       if (kexec_in_progress && hyperv_init_cpuhp > 0)
+               cpuhp_remove_state(hyperv_init_cpuhp);
+
+       /* The function calls stop_other_cpus(). */
        native_machine_shutdown();
+
+       /* Disable the hypercall page when there is only 1 active CPU. */
+       if (kexec_in_progress)
+               hyperv_cleanup();
 }
 
 static void hv_machine_crash_shutdown(struct pt_regs *regs)
 {
        if (hv_crash_handler)
                hv_crash_handler(regs);
+
+       /* The function calls crash_smp_send_stop(). */
        native_machine_crash_shutdown(regs);
+
+       /* Disable the hypercall page when there is only 1 active CPU. */
+       hyperv_cleanup();
 }
 #endif /* CONFIG_KEXEC_CORE */
 #endif /* CONFIG_HYPERV */
index 9e87ab010c82bbbe02798d17be75ba6171d199f6..e68ea5f4ad1ce0c3bfadafec4e01dc44fc2664e5 100644 (file)
@@ -164,10 +164,10 @@ static int xen_cpu_up_prepare_hvm(unsigned int cpu)
        else
                per_cpu(xen_vcpu_id, cpu) = cpu;
        rc = xen_vcpu_setup(cpu);
-       if (rc)
+       if (rc || !xen_have_vector_callback)
                return rc;
 
-       if (xen_have_vector_callback && xen_feature(XENFEAT_hvm_safe_pvclock))
+       if (xen_feature(XENFEAT_hvm_safe_pvclock))
                xen_setup_timer(cpu);
 
        rc = xen_smp_intr_init(cpu);
@@ -188,6 +188,8 @@ static int xen_cpu_dead_hvm(unsigned int cpu)
        return 0;
 }
 
+static bool no_vector_callback __initdata;
+
 static void __init xen_hvm_guest_init(void)
 {
        if (xen_pv_domain())
@@ -207,7 +209,7 @@ static void __init xen_hvm_guest_init(void)
 
        xen_panic_handler_init();
 
-       if (xen_feature(XENFEAT_hvm_callback_vector))
+       if (!no_vector_callback && xen_feature(XENFEAT_hvm_callback_vector))
                xen_have_vector_callback = 1;
 
        xen_hvm_smp_init();
@@ -233,6 +235,13 @@ static __init int xen_parse_nopv(char *arg)
 }
 early_param("xen_nopv", xen_parse_nopv);
 
+static __init int xen_parse_no_vector_callback(char *arg)
+{
+       no_vector_callback = true;
+       return 0;
+}
+early_param("xen_no_vector_callback", xen_parse_no_vector_callback);
+
 bool __init xen_hvm_need_lapic(void)
 {
        if (xen_pv_domain())
index f5e7db4f82abb63039ce49271ecbe87f857a1655..6ff3c887e0b99523cd69774b8de8f3009f69d92f 100644 (file)
@@ -33,9 +33,11 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
        int cpu;
 
        native_smp_prepare_cpus(max_cpus);
-       WARN_ON(xen_smp_intr_init(0));
 
-       xen_init_lock_cpu(0);
+       if (xen_have_vector_callback) {
+               WARN_ON(xen_smp_intr_init(0));
+               xen_init_lock_cpu(0);
+       }
 
        for_each_possible_cpu(cpu) {
                if (cpu == 0)
@@ -50,9 +52,11 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
 static void xen_hvm_cpu_die(unsigned int cpu)
 {
        if (common_cpu_die(cpu) == 0) {
-               xen_smp_intr_free(cpu);
-               xen_uninit_lock_cpu(cpu);
-               xen_teardown_timer(cpu);
+               if (xen_have_vector_callback) {
+                       xen_smp_intr_free(cpu);
+                       xen_uninit_lock_cpu(cpu);
+                       xen_teardown_timer(cpu);
+               }
        }
 }
 #else
@@ -64,14 +68,19 @@ static void xen_hvm_cpu_die(unsigned int cpu)
 
 void __init xen_hvm_smp_init(void)
 {
-       if (!xen_have_vector_callback)
+       smp_ops.smp_prepare_boot_cpu = xen_hvm_smp_prepare_boot_cpu;
+       smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
+       smp_ops.smp_cpus_done = xen_smp_cpus_done;
+       smp_ops.cpu_die = xen_hvm_cpu_die;
+
+       if (!xen_have_vector_callback) {
+#ifdef CONFIG_PARAVIRT_SPINLOCKS
+               nopvspin = true;
+#endif
                return;
+       }
 
-       smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
        smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
-       smp_ops.cpu_die = xen_hvm_cpu_die;
        smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi;
        smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi;
-       smp_ops.smp_prepare_boot_cpu = xen_hvm_smp_prepare_boot_cpu;
-       smp_ops.smp_cpus_done = xen_smp_cpus_done;
 }
index 8892908ad58ce40c2b868c48c957cc49c49d1ad9..788a4ba1e2e747de90b600b56a5b610ba4eb935b 100644 (file)
@@ -356,7 +356,8 @@ int public_key_verify_signature(const struct public_key *pkey,
        if (ret)
                goto error_free_key;
 
-       if (strcmp(sig->pkey_algo, "sm2") == 0 && sig->data_size) {
+       if (sig->pkey_algo && strcmp(sig->pkey_algo, "sm2") == 0 &&
+           sig->data_size) {
                ret = cert_sig_digest_update(sig, tfm);
                if (ret)
                        goto error_free_key;
index eacbf4f939900fe4f280f053c5ee1ac45a75a0c2..8f899f898ec9f903734693cd6f4ba8a593bbcc14 100644 (file)
@@ -107,6 +107,8 @@ do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
        preempt_enable();
 
        // bytes/ns == GB/s, multiply by 1000 to get MB/s [not MiB/s]
+       if (!min)
+               min = 1;
        speed = (1000 * REPS * BENCH_SIZE) / (unsigned int)ktime_to_ns(min);
        tmpl->speed = speed;
 
index cb229e24c56375b0a89255667436abc46fa9b0d3..e6a5d997241c43d803d9758b01328db8b6cdb0cc 100644 (file)
@@ -97,7 +97,7 @@ void acpi_scan_table_handler(u32 event, void *table, void *context);
 extern struct list_head acpi_bus_id_list;
 
 struct acpi_device_bus_id {
-       char bus_id[15];
+       const char *bus_id;
        unsigned int instance_no;
        struct list_head node;
 };
index 80b668c80073a58417e6bd6a2ad0d1ddc0f28d31..1db063b02f63eb8d61076b44cfc00fe40b8a5b65 100644 (file)
@@ -486,6 +486,7 @@ static void acpi_device_del(struct acpi_device *device)
                                acpi_device_bus_id->instance_no--;
                        else {
                                list_del(&acpi_device_bus_id->node);
+                               kfree_const(acpi_device_bus_id->bus_id);
                                kfree(acpi_device_bus_id);
                        }
                        break;
@@ -585,6 +586,8 @@ static int acpi_get_device_data(acpi_handle handle, struct acpi_device **device,
        if (!device)
                return -EINVAL;
 
+       *device = NULL;
+
        status = acpi_get_data_full(handle, acpi_scan_drop_device,
                                    (void **)device, callback);
        if (ACPI_FAILURE(status) || !*device) {
@@ -674,7 +677,14 @@ int acpi_device_add(struct acpi_device *device,
        }
        if (!found) {
                acpi_device_bus_id = new_bus_id;
-               strcpy(acpi_device_bus_id->bus_id, acpi_device_hid(device));
+               acpi_device_bus_id->bus_id =
+                       kstrdup_const(acpi_device_hid(device), GFP_KERNEL);
+               if (!acpi_device_bus_id->bus_id) {
+                       pr_err(PREFIX "Memory allocation error for bus id\n");
+                       result = -ENOMEM;
+                       goto err_free_new_bus_id;
+               }
+
                acpi_device_bus_id->instance_no = 0;
                list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list);
        }
@@ -709,6 +719,11 @@ int acpi_device_add(struct acpi_device *device,
        if (device->parent)
                list_del(&device->node);
        list_del(&device->wakeup_list);
+
+ err_free_new_bus_id:
+       if (!found)
+               kfree(new_bus_id);
+
        mutex_unlock(&acpi_device_lock);
 
  err_detach:
index 37244a7e68c229d478e36389efbfceba7cec5306..9cf249c344d9e415877c2f1a8b89ad1fa4d5f958 100644 (file)
@@ -1256,6 +1256,8 @@ static struct tegra_clk_init_table init_table[] __initdata = {
        { TEGRA30_CLK_I2S3_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
        { TEGRA30_CLK_I2S4_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
        { TEGRA30_CLK_VIMCLK_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
+       { TEGRA30_CLK_HDA, TEGRA30_CLK_PLL_P, 102000000, 0 },
+       { TEGRA30_CLK_HDA2CODEC_2X, TEGRA30_CLK_PLL_P, 48000000, 0 },
        /* must be the last entry */
        { TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 },
 };
index bbd51703e738b972a9437476e8cb4b60b31f5c8f..e535f28a80283e36db6ca9d1a9d484078ca40c0d 100644 (file)
@@ -366,6 +366,7 @@ if CRYPTO_DEV_OMAP
 config CRYPTO_DEV_OMAP_SHAM
        tristate "Support for OMAP MD5/SHA1/SHA2 hw accelerator"
        depends on ARCH_OMAP2PLUS
+       select CRYPTO_ENGINE
        select CRYPTO_SHA1
        select CRYPTO_MD5
        select CRYPTO_SHA256
index 3c4e343011721e336869567f5292959ec634b1a1..364fc2f3e499549cd3eb89673b1a3dffd8af7977 100644 (file)
@@ -251,6 +251,9 @@ static void cma_heap_dma_buf_release(struct dma_buf *dmabuf)
                buffer->vaddr = NULL;
        }
 
+       /* free page list */
+       kfree(buffer->pages);
+       /* release memory */
        cma_release(cma_heap->cma, buffer->cma_pages, buffer->pagecount);
        kfree(buffer);
 }
index c70f46e80a3b72ea828ddfdb526f8a7632d38030..dea65d85594fcceb84cb60c721714f5276904734 100644 (file)
@@ -521,7 +521,8 @@ config GPIO_SAMA5D2_PIOBU
 
 config GPIO_SIFIVE
        bool "SiFive GPIO support"
-       depends on OF_GPIO && IRQ_DOMAIN_HIERARCHY
+       depends on OF_GPIO
+       select IRQ_DOMAIN_HIERARCHY
        select GPIO_GENERIC
        select GPIOLIB_IRQCHIP
        select REGMAP_MMIO
@@ -597,6 +598,8 @@ config GPIO_TEGRA
        default ARCH_TEGRA
        depends on ARCH_TEGRA || COMPILE_TEST
        depends on OF_GPIO
+       select GPIOLIB_IRQCHIP
+       select IRQ_DOMAIN_HIERARCHY
        help
          Say yes here to support GPIO pins on NVIDIA Tegra SoCs.
 
index 672681a976f50ee08d593ee5db71d8b5c64f8766..a912a8fed197ac32bb393a87ba17c63421f12184 100644 (file)
@@ -676,20 +676,17 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
        else
                state->duty_cycle = 1;
 
+       val = (unsigned long long) u; /* on duration */
        regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u);
-       val = (unsigned long long) u * NSEC_PER_SEC;
+       val += (unsigned long long) u; /* period = on + off duration */
+       val *= NSEC_PER_SEC;
        do_div(val, mvpwm->clk_rate);
-       if (val < state->duty_cycle) {
+       if (val > UINT_MAX)
+               state->period = UINT_MAX;
+       else if (val)
+               state->period = val;
+       else
                state->period = 1;
-       } else {
-               val -= state->duty_cycle;
-               if (val > UINT_MAX)
-                       state->period = UINT_MAX;
-               else if (val)
-                       state->period = val;
-               else
-                       state->period = 1;
-       }
 
        regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, &u);
        if (u)
index 12b679ca552cccea423e04874e1f2e3c11bef7a6..1a7b51163528b5a29bfb9c201459a3c959a21d9a 100644 (file)
@@ -1979,6 +1979,21 @@ struct gpio_chardev_data {
 #endif
 };
 
+static int chipinfo_get(struct gpio_chardev_data *cdev, void __user *ip)
+{
+       struct gpio_device *gdev = cdev->gdev;
+       struct gpiochip_info chipinfo;
+
+       memset(&chipinfo, 0, sizeof(chipinfo));
+
+       strscpy(chipinfo.name, dev_name(&gdev->dev), sizeof(chipinfo.name));
+       strscpy(chipinfo.label, gdev->label, sizeof(chipinfo.label));
+       chipinfo.lines = gdev->ngpio;
+       if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
+               return -EFAULT;
+       return 0;
+}
+
 #ifdef CONFIG_GPIO_CDEV_V1
 /*
  * returns 0 if the versions match, else the previously selected ABI version
@@ -1993,6 +2008,41 @@ static int lineinfo_ensure_abi_version(struct gpio_chardev_data *cdata,
 
        return abiv;
 }
+
+static int lineinfo_get_v1(struct gpio_chardev_data *cdev, void __user *ip,
+                          bool watch)
+{
+       struct gpio_desc *desc;
+       struct gpioline_info lineinfo;
+       struct gpio_v2_line_info lineinfo_v2;
+
+       if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
+               return -EFAULT;
+
+       /* this doubles as a range check on line_offset */
+       desc = gpiochip_get_desc(cdev->gdev->chip, lineinfo.line_offset);
+       if (IS_ERR(desc))
+               return PTR_ERR(desc);
+
+       if (watch) {
+               if (lineinfo_ensure_abi_version(cdev, 1))
+                       return -EPERM;
+
+               if (test_and_set_bit(lineinfo.line_offset, cdev->watched_lines))
+                       return -EBUSY;
+       }
+
+       gpio_desc_to_lineinfo(desc, &lineinfo_v2);
+       gpio_v2_line_info_to_v1(&lineinfo_v2, &lineinfo);
+
+       if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) {
+               if (watch)
+                       clear_bit(lineinfo.line_offset, cdev->watched_lines);
+               return -EFAULT;
+       }
+
+       return 0;
+}
 #endif
 
 static int lineinfo_get(struct gpio_chardev_data *cdev, void __user *ip,
@@ -2030,6 +2080,22 @@ static int lineinfo_get(struct gpio_chardev_data *cdev, void __user *ip,
        return 0;
 }
 
+static int lineinfo_unwatch(struct gpio_chardev_data *cdev, void __user *ip)
+{
+       __u32 offset;
+
+       if (copy_from_user(&offset, ip, sizeof(offset)))
+               return -EFAULT;
+
+       if (offset >= cdev->gdev->ngpio)
+               return -EINVAL;
+
+       if (!test_and_clear_bit(offset, cdev->watched_lines))
+               return -EBUSY;
+
+       return 0;
+}
+
 /*
  * gpio_ioctl() - ioctl handler for the GPIO chardev
  */
@@ -2037,80 +2103,24 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct gpio_chardev_data *cdev = file->private_data;
        struct gpio_device *gdev = cdev->gdev;
-       struct gpio_chip *gc = gdev->chip;
        void __user *ip = (void __user *)arg;
-       __u32 offset;
 
        /* We fail any subsequent ioctl():s when the chip is gone */
-       if (!gc)
+       if (!gdev->chip)
                return -ENODEV;
 
        /* Fill in the struct and pass to userspace */
        if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
-               struct gpiochip_info chipinfo;
-
-               memset(&chipinfo, 0, sizeof(chipinfo));
-
-               strscpy(chipinfo.name, dev_name(&gdev->dev),
-                       sizeof(chipinfo.name));
-               strscpy(chipinfo.label, gdev->label,
-                       sizeof(chipinfo.label));
-               chipinfo.lines = gdev->ngpio;
-               if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
-                       return -EFAULT;
-               return 0;
+               return chipinfo_get(cdev, ip);
 #ifdef CONFIG_GPIO_CDEV_V1
-       } else if (cmd == GPIO_GET_LINEINFO_IOCTL) {
-               struct gpio_desc *desc;
-               struct gpioline_info lineinfo;
-               struct gpio_v2_line_info lineinfo_v2;
-
-               if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
-                       return -EFAULT;
-
-               /* this doubles as a range check on line_offset */
-               desc = gpiochip_get_desc(gc, lineinfo.line_offset);
-               if (IS_ERR(desc))
-                       return PTR_ERR(desc);
-
-               gpio_desc_to_lineinfo(desc, &lineinfo_v2);
-               gpio_v2_line_info_to_v1(&lineinfo_v2, &lineinfo);
-
-               if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
-                       return -EFAULT;
-               return 0;
        } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
                return linehandle_create(gdev, ip);
        } else if (cmd == GPIO_GET_LINEEVENT_IOCTL) {
                return lineevent_create(gdev, ip);
-       } else if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) {
-               struct gpio_desc *desc;
-               struct gpioline_info lineinfo;
-               struct gpio_v2_line_info lineinfo_v2;
-
-               if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
-                       return -EFAULT;
-
-               /* this doubles as a range check on line_offset */
-               desc = gpiochip_get_desc(gc, lineinfo.line_offset);
-               if (IS_ERR(desc))
-                       return PTR_ERR(desc);
-
-               if (lineinfo_ensure_abi_version(cdev, 1))
-                       return -EPERM;
-
-               if (test_and_set_bit(lineinfo.line_offset, cdev->watched_lines))
-                       return -EBUSY;
-
-               gpio_desc_to_lineinfo(desc, &lineinfo_v2);
-               gpio_v2_line_info_to_v1(&lineinfo_v2, &lineinfo);
-
-               if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) {
-                       clear_bit(lineinfo.line_offset, cdev->watched_lines);
-                       return -EFAULT;
-               }
-
-               return 0;
+       } else if (cmd == GPIO_GET_LINEINFO_IOCTL ||
+                  cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) {
+               return lineinfo_get_v1(cdev, ip,
+                                      cmd == GPIO_GET_LINEINFO_WATCH_IOCTL);
 #endif /* CONFIG_GPIO_CDEV_V1 */
        } else if (cmd == GPIO_V2_GET_LINEINFO_IOCTL ||
                   cmd == GPIO_V2_GET_LINEINFO_WATCH_IOCTL) {
@@ -2119,16 +2129,7 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        } else if (cmd == GPIO_V2_GET_LINE_IOCTL) {
                return linereq_create(gdev, ip);
        } else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) {
-               if (copy_from_user(&offset, ip, sizeof(offset)))
-                       return -EFAULT;
-
-               if (offset >= cdev->gdev->ngpio)
-                       return -EINVAL;
-
-               if (!test_and_clear_bit(offset, cdev->watched_lines))
-                       return -EBUSY;
-
-               return 0;
+               return lineinfo_unwatch(cdev, ip);
        }
        return -EINVAL;
 }
index b02cc2abd3b680263cdc9c5cd11c278969c9b9ee..b78a634cca2401daa86a081403d0304f95c74fff 100644 (file)
@@ -1489,6 +1489,9 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
                type = IRQ_TYPE_NONE;
        }
 
+       if (gc->to_irq)
+               chip_warn(gc, "to_irq is redefined in %s and you shouldn't rely on it\n", __func__);
+
        gc->to_irq = gpiochip_to_irq;
        gc->irq.default_type = type;
        gc->irq.lock_key = lock_key;
index 306077884a6794e5709efcefea25dea0554b3a33..6107ac91db250731468f7e86b56ffbe63daca372 100644 (file)
@@ -112,6 +112,7 @@ int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)
 union igp_info {
        struct atom_integrated_system_info_v1_11 v11;
        struct atom_integrated_system_info_v1_12 v12;
+       struct atom_integrated_system_info_v2_1 v21;
 };
 
 union umc_info {
@@ -209,24 +210,42 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
                if (adev->flags & AMD_IS_APU) {
                        igp_info = (union igp_info *)
                                (mode_info->atom_context->bios + data_offset);
-                       switch (crev) {
-                       case 11:
-                               mem_channel_number = igp_info->v11.umachannelnumber;
-                               /* channel width is 64 */
-                               if (vram_width)
-                                       *vram_width = mem_channel_number * 64;
-                               mem_type = igp_info->v11.memorytype;
-                               if (vram_type)
-                                       *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+                       switch (frev) {
+                       case 1:
+                               switch (crev) {
+                               case 11:
+                               case 12:
+                                       mem_channel_number = igp_info->v11.umachannelnumber;
+                                       if (!mem_channel_number)
+                                               mem_channel_number = 1;
+                                       /* channel width is 64 */
+                                       if (vram_width)
+                                               *vram_width = mem_channel_number * 64;
+                                       mem_type = igp_info->v11.memorytype;
+                                       if (vram_type)
+                                               *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
                                break;
-                       case 12:
-                               mem_channel_number = igp_info->v12.umachannelnumber;
-                               /* channel width is 64 */
-                               if (vram_width)
-                                       *vram_width = mem_channel_number * 64;
-                               mem_type = igp_info->v12.memorytype;
-                               if (vram_type)
-                                       *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+                       case 2:
+                               switch (crev) {
+                               case 1:
+                               case 2:
+                                       mem_channel_number = igp_info->v21.umachannelnumber;
+                                       if (!mem_channel_number)
+                                               mem_channel_number = 1;
+                                       /* channel width is 64 */
+                                       if (vram_width)
+                                               *vram_width = mem_channel_number * 64;
+                                       mem_type = igp_info->v21.memorytype;
+                                       if (vram_type)
+                                               *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
                                break;
                        default:
                                return -EINVAL;
index b69c34074d8d7a02f9fb23ee7fef394561f37978..cab1ebaf6d6299a365c272b90055cd8e847104fb 100644 (file)
@@ -81,7 +81,6 @@ MODULE_FIRMWARE("amdgpu/navi10_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/navi14_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/vangogh_gpu_info.bin");
-MODULE_FIRMWARE("amdgpu/green_sardine_gpu_info.bin");
 
 #define AMDGPU_RESUME_MS               2000
 
@@ -3034,7 +3033,7 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
 #endif
        default:
                if (amdgpu_dc > 0)
-                       DRM_INFO("Display Core has been requested via kernel parameter "
+                       DRM_INFO_ONCE("Display Core has been requested via kernel parameter "
                                         "but isn't supported by ASIC, ignoring\n");
                return false;
        }
index 72efd579ec5ee198ef2c100f38faefa5f60641e0..7169fb5e3d9c47f0c8fd575b11544c31cd83cdb9 100644 (file)
@@ -1085,6 +1085,8 @@ static const struct pci_device_id pciidlist[] = {
 
        /* Renoir */
        {0x1002, 0x1636, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RENOIR|AMD_IS_APU},
+       {0x1002, 0x1638, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RENOIR|AMD_IS_APU},
+       {0x1002, 0x164C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RENOIR|AMD_IS_APU},
 
        /* Navi12 */
        {0x1002, 0x7360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12},
index ba108678452551f0917d01ff67cf6c186822a171..346963e3cf7313cf056e9de612e45dfc74873147 100644 (file)
 #define mmGCR_GENERAL_CNTL_Sienna_Cichlid                      0x1580
 #define mmGCR_GENERAL_CNTL_Sienna_Cichlid_BASE_IDX     0
 
+#define mmGOLDEN_TSC_COUNT_UPPER_Vangogh                0x0025
+#define mmGOLDEN_TSC_COUNT_UPPER_Vangogh_BASE_IDX       1
+#define mmGOLDEN_TSC_COUNT_LOWER_Vangogh                0x0026
+#define mmGOLDEN_TSC_COUNT_LOWER_Vangogh_BASE_IDX       1
 #define mmSPI_CONFIG_CNTL_1_Vangogh             0x2441
 #define mmSPI_CONFIG_CNTL_1_Vangogh_BASE_IDX    1
 #define mmVGT_TF_MEMORY_BASE_HI_Vangogh          0x2261
 #define mmVGT_ESGS_RING_SIZE_Vangogh_BASE_IDX    1
 #define mmSPI_CONFIG_CNTL_Vangogh                0x2440
 #define mmSPI_CONFIG_CNTL_Vangogh_BASE_IDX       1
+#define mmGCR_GENERAL_CNTL_Vangogh               0x1580
+#define mmGCR_GENERAL_CNTL_Vangogh_BASE_IDX      0
 
 #define mmCP_HYP_PFP_UCODE_ADDR                        0x5814
 #define mmCP_HYP_PFP_UCODE_ADDR_BASE_IDX       1
 #define mmGCVM_L2_CGTT_CLK_CTRL_Sienna_Cichlid          0x15db
 #define mmGCVM_L2_CGTT_CLK_CTRL_Sienna_Cichlid_BASE_IDX        0
 
+#define mmGC_THROTTLE_CTRL_Sienna_Cichlid              0x2030
+#define mmGC_THROTTLE_CTRL_Sienna_Cichlid_BASE_IDX     0
+
 MODULE_FIRMWARE("amdgpu/navi10_ce.bin");
 MODULE_FIRMWARE("amdgpu/navi10_pfp.bin");
 MODULE_FIRMWARE("amdgpu/navi10_me.bin");
@@ -3237,7 +3246,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_3_vangogh[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x00800000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_EXCEPTION_CONTROL, 0x7fff0f1f, 0x00b80000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGB_ADDR_CONFIG, 0x0c1807ff, 0x00000142),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL, 0x1ff1ffff, 0x00000500),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL_Vangogh, 0x1ff1ffff, 0x00000500),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL1_PIPE_STEER, 0x000000ff, 0x000000e4),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_0, 0x77777777, 0x32103210),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2_PIPE_STEER_1, 0x77777777, 0x32103210),
@@ -3324,6 +3333,7 @@ static void gfx_v10_0_ring_emit_de_meta(struct amdgpu_ring *ring, bool resume);
 static void gfx_v10_0_ring_emit_frame_cntl(struct amdgpu_ring *ring, bool start, bool secure);
 static u32 gfx_v10_3_get_disabled_sa(struct amdgpu_device *adev);
 static void gfx_v10_3_program_pbb_mode(struct amdgpu_device *adev);
+static void gfx_v10_3_set_power_brake_sequence(struct amdgpu_device *adev);
 
 static void gfx10_kiq_set_resources(struct amdgpu_ring *kiq_ring, uint64_t queue_mask)
 {
@@ -7192,6 +7202,9 @@ static int gfx_v10_0_hw_init(void *handle)
        if (adev->asic_type == CHIP_SIENNA_CICHLID)
                gfx_v10_3_program_pbb_mode(adev);
 
+       if (adev->asic_type >= CHIP_SIENNA_CICHLID)
+               gfx_v10_3_set_power_brake_sequence(adev);
+
        return r;
 }
 
@@ -7377,8 +7390,16 @@ static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev)
 
        amdgpu_gfx_off_ctrl(adev, false);
        mutex_lock(&adev->gfx.gpu_clock_mutex);
-       clock = (uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER) |
-               ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER) << 32ULL);
+       switch (adev->asic_type) {
+       case CHIP_VANGOGH:
+               clock = (uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Vangogh) |
+                       ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh) << 32ULL);
+               break;
+       default:
+               clock = (uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER) |
+                       ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER) << 32ULL);
+               break;
+       }
        mutex_unlock(&adev->gfx.gpu_clock_mutex);
        amdgpu_gfx_off_ctrl(adev, true);
        return clock;
@@ -9169,6 +9190,31 @@ static void gfx_v10_3_program_pbb_mode(struct amdgpu_device *adev)
        }
 }
 
+static void gfx_v10_3_set_power_brake_sequence(struct amdgpu_device *adev)
+{
+       WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX,
+                    (0x1 << GRBM_GFX_INDEX__SA_BROADCAST_WRITES__SHIFT) |
+                    (0x1 << GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES__SHIFT) |
+                    (0x1 << GRBM_GFX_INDEX__SE_BROADCAST_WRITES__SHIFT));
+
+       WREG32_SOC15(GC, 0, mmGC_CAC_IND_INDEX, ixPWRBRK_STALL_PATTERN_CTRL);
+       WREG32_SOC15(GC, 0, mmGC_CAC_IND_DATA,
+                    (0x1 << PWRBRK_STALL_PATTERN_CTRL__PWRBRK_STEP_INTERVAL__SHIFT) |
+                    (0x12 << PWRBRK_STALL_PATTERN_CTRL__PWRBRK_BEGIN_STEP__SHIFT) |
+                    (0x13 << PWRBRK_STALL_PATTERN_CTRL__PWRBRK_END_STEP__SHIFT) |
+                    (0xf << PWRBRK_STALL_PATTERN_CTRL__PWRBRK_THROTTLE_PATTERN_BIT_NUMS__SHIFT));
+
+       WREG32_SOC15(GC, 0, mmGC_THROTTLE_CTRL_Sienna_Cichlid,
+                    (0x1 << GC_THROTTLE_CTRL__PWRBRK_STALL_EN__SHIFT) |
+                    (0x1 << GC_THROTTLE_CTRL__PATTERN_MODE__SHIFT) |
+                    (0x5 << GC_THROTTLE_CTRL__RELEASE_STEP_INTERVAL__SHIFT));
+
+       WREG32_SOC15(GC, 0, mmDIDT_IND_INDEX, ixDIDT_SQ_THROTTLE_CTRL);
+
+       WREG32_SOC15(GC, 0, mmDIDT_IND_DATA,
+                    (0x1 << DIDT_SQ_THROTTLE_CTRL__PWRBRK_STALL_EN__SHIFT));
+}
+
 const struct amdgpu_ip_block_version gfx_v10_0_ip_block =
 {
        .type = AMD_IP_BLOCK_TYPE_GFX,
index 07104a1de3082b776211bd36f7ea1eaa8e4873ae..1961745e89c73df00c0fcc5198b96039d0f481e7 100644 (file)
@@ -491,12 +491,11 @@ mmhub_v2_3_update_medium_grain_clock_gating(struct amdgpu_device *adev,
 {
        uint32_t def, data, def1, data1;
 
-       def  = data  = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG);
+       def  = data  = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_CGTT_CLK_CTRL);
        def1 = data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2);
 
        if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG)) {
-               data |= MM_ATC_L2_MISC_CG__ENABLE_MASK;
-
+               data &= ~MM_ATC_L2_CGTT_CLK_CTRL__SOFT_OVERRIDE_MASK;
                data1 &= ~(DAGB0_CNTL_MISC2__DISABLE_WRREQ_CG_MASK |
                           DAGB0_CNTL_MISC2__DISABLE_WRRET_CG_MASK |
                           DAGB0_CNTL_MISC2__DISABLE_RDREQ_CG_MASK |
@@ -505,8 +504,7 @@ mmhub_v2_3_update_medium_grain_clock_gating(struct amdgpu_device *adev,
                           DAGB0_CNTL_MISC2__DISABLE_TLBRD_CG_MASK);
 
        } else {
-               data &= ~MM_ATC_L2_MISC_CG__ENABLE_MASK;
-
+               data |= MM_ATC_L2_CGTT_CLK_CTRL__SOFT_OVERRIDE_MASK;
                data1 |= (DAGB0_CNTL_MISC2__DISABLE_WRREQ_CG_MASK |
                          DAGB0_CNTL_MISC2__DISABLE_WRRET_CG_MASK |
                          DAGB0_CNTL_MISC2__DISABLE_RDREQ_CG_MASK |
@@ -516,7 +514,7 @@ mmhub_v2_3_update_medium_grain_clock_gating(struct amdgpu_device *adev,
        }
 
        if (def != data)
-               WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG, data);
+               WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_CGTT_CLK_CTRL, data);
        if (def1 != data1)
                WREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2, data1);
 }
@@ -525,17 +523,44 @@ static void
 mmhub_v2_3_update_medium_grain_light_sleep(struct amdgpu_device *adev,
                                           bool enable)
 {
-       uint32_t def, data;
-
-       def  = data  = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG);
-
-       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS))
-               data |= MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK;
-       else
-               data &= ~MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK;
+       uint32_t def, data, def1, data1, def2, data2;
+
+       def  = data  = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_CGTT_CLK_CTRL);
+       def1 = data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_WR_CGTT_CLK_CTRL);
+       def2 = data2 = RREG32_SOC15(MMHUB, 0, mmDAGB0_RD_CGTT_CLK_CTRL);
+
+       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS)) {
+               data &= ~MM_ATC_L2_CGTT_CLK_CTRL__MGLS_OVERRIDE_MASK;
+               data1 &= !(DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_MASK |
+                       DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_WRITE_MASK |
+                       DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_READ_MASK |
+                       DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_RETURN_MASK |
+                       DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_REGISTER_MASK);
+               data2 &= !(DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_MASK |
+                       DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_WRITE_MASK |
+                       DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_READ_MASK |
+                       DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_RETURN_MASK |
+                       DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_REGISTER_MASK);
+       } else {
+               data |= MM_ATC_L2_CGTT_CLK_CTRL__MGLS_OVERRIDE_MASK;
+               data1 |= (DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_MASK |
+                       DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_WRITE_MASK |
+                       DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_READ_MASK |
+                       DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_RETURN_MASK |
+                       DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_REGISTER_MASK);
+               data2 |= (DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_MASK |
+                       DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_WRITE_MASK |
+                       DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_READ_MASK |
+                       DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_RETURN_MASK |
+                       DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_REGISTER_MASK);
+       }
 
        if (def != data)
-               WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG, data);
+               WREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_CGTT_CLK_CTRL, data);
+       if (def1 != data1)
+               WREG32_SOC15(MMHUB, 0, mmDAGB0_WR_CGTT_CLK_CTRL, data1);
+       if (def2 != data2)
+               WREG32_SOC15(MMHUB, 0, mmDAGB0_RD_CGTT_CLK_CTRL, data2);
 }
 
 static int mmhub_v2_3_set_clockgating(struct amdgpu_device *adev,
@@ -554,26 +579,39 @@ static int mmhub_v2_3_set_clockgating(struct amdgpu_device *adev,
 
 static void mmhub_v2_3_get_clockgating(struct amdgpu_device *adev, u32 *flags)
 {
-       int data, data1;
+       int data, data1, data2, data3;
 
        if (amdgpu_sriov_vf(adev))
                *flags = 0;
 
-       data  = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_MISC_CG);
-       data1 = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2);
+       data = RREG32_SOC15(MMHUB, 0, mmDAGB0_CNTL_MISC2);
+       data1  = RREG32_SOC15(MMHUB, 0, mmMM_ATC_L2_CGTT_CLK_CTRL);
+       data2 = RREG32_SOC15(MMHUB, 0, mmDAGB0_WR_CGTT_CLK_CTRL);
+       data3 = RREG32_SOC15(MMHUB, 0, mmDAGB0_RD_CGTT_CLK_CTRL);
 
        /* AMD_CG_SUPPORT_MC_MGCG */
-       if ((data & MM_ATC_L2_MISC_CG__ENABLE_MASK) &&
-           !(data1 & (DAGB0_CNTL_MISC2__DISABLE_WRREQ_CG_MASK |
+       if (!(data & (DAGB0_CNTL_MISC2__DISABLE_WRREQ_CG_MASK |
                       DAGB0_CNTL_MISC2__DISABLE_WRRET_CG_MASK |
                       DAGB0_CNTL_MISC2__DISABLE_RDREQ_CG_MASK |
                       DAGB0_CNTL_MISC2__DISABLE_RDRET_CG_MASK |
                       DAGB0_CNTL_MISC2__DISABLE_TLBWR_CG_MASK |
-                      DAGB0_CNTL_MISC2__DISABLE_TLBRD_CG_MASK)))
-               *flags |= AMD_CG_SUPPORT_MC_MGCG;
+                      DAGB0_CNTL_MISC2__DISABLE_TLBRD_CG_MASK))
+               && !(data1 & MM_ATC_L2_CGTT_CLK_CTRL__SOFT_OVERRIDE_MASK)) {
+                       *flags |= AMD_CG_SUPPORT_MC_MGCG;
+       }
 
        /* AMD_CG_SUPPORT_MC_LS */
-       if (data & MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK)
+       if (!(data1 & MM_ATC_L2_CGTT_CLK_CTRL__MGLS_OVERRIDE_MASK)
+               && !(data2 & (DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_MASK |
+                               DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_WRITE_MASK |
+                               DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_READ_MASK |
+                               DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_RETURN_MASK |
+                               DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_REGISTER_MASK))
+               && !(data3 & (DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_MASK |
+                               DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_WRITE_MASK |
+                               DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_READ_MASK |
+                               DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_RETURN_MASK |
+                               DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_REGISTER_MASK)))
                *flags |= AMD_CG_SUPPORT_MC_LS;
 }
 
index d65a5339d354ac268760c7b88e74fbdb174ea0dc..3ba7bdfde65d81f8f0c91c88b93f1ce15d33cd47 100644 (file)
@@ -47,7 +47,7 @@ enum psp_gfx_crtl_cmd_id
     GFX_CTRL_CMD_ID_DISABLE_INT     = 0x00060000,   /* disable PSP-to-Gfx interrupt */
     GFX_CTRL_CMD_ID_MODE1_RST       = 0x00070000,   /* trigger the Mode 1 reset */
     GFX_CTRL_CMD_ID_GBR_IH_SET      = 0x00080000,   /* set Gbr IH_RB_CNTL registers */
-    GFX_CTRL_CMD_ID_CONSUME_CMD     = 0x000A0000,   /* send interrupt to psp for updating write pointer of vf */
+    GFX_CTRL_CMD_ID_CONSUME_CMD     = 0x00090000,   /* send interrupt to psp for updating write pointer of vf */
     GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING = 0x000C0000, /* destroy GPCOM ring */
 
     GFX_CTRL_CMD_ID_MAX             = 0x000F0000,   /* max command ID */
index 8a23636ecc27ff8577997ce207733d7f240e7ecf..0b3516c4eefb33881c235ba44d8338c0cef2515e 100644 (file)
@@ -1239,7 +1239,8 @@ static int soc15_common_early_init(void *handle)
                break;
        case CHIP_RENOIR:
                adev->asic_funcs = &soc15_asic_funcs;
-               if (adev->pdev->device == 0x1636)
+               if ((adev->pdev->device == 0x1636) ||
+                   (adev->pdev->device == 0x164c))
                        adev->apu_flags |= AMD_APU_IS_RENOIR;
                else
                        adev->apu_flags |= AMD_APU_IS_GREEN_SARDINE;
index 8cac497c2c459aa86421ddbce9eab12d6544ce03..a5640a6138cf2cb019cb00d12a08d4f6faee2ad6 100644 (file)
@@ -1040,11 +1040,14 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
                                (struct crat_subtype_iolink *)sub_type_hdr);
                if (ret < 0)
                        return ret;
-               crat_table->length += (sub_type_hdr->length * entries);
-               crat_table->total_entries += entries;
 
-               sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
-                               sub_type_hdr->length * entries);
+               if (entries) {
+                       crat_table->length += (sub_type_hdr->length * entries);
+                       crat_table->total_entries += entries;
+
+                       sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
+                                       sub_type_hdr->length * entries);
+               }
 #else
                pr_info("IO link not available for non x86 platforms\n");
 #endif
index 146486071d01d88812919e16c1de2843aa1b809a..c6da89df055de87c89ba0ba05ed8739993a1c97b 100644 (file)
@@ -939,41 +939,6 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
 }
 #endif
 
-#ifdef CONFIG_DEBUG_FS
-static int create_crtc_crc_properties(struct amdgpu_display_manager *dm)
-{
-       dm->crc_win_x_start_property =
-               drm_property_create_range(adev_to_drm(dm->adev),
-                                         DRM_MODE_PROP_ATOMIC,
-                                         "AMD_CRC_WIN_X_START", 0, U16_MAX);
-       if (!dm->crc_win_x_start_property)
-               return -ENOMEM;
-
-       dm->crc_win_y_start_property =
-               drm_property_create_range(adev_to_drm(dm->adev),
-                                         DRM_MODE_PROP_ATOMIC,
-                                         "AMD_CRC_WIN_Y_START", 0, U16_MAX);
-       if (!dm->crc_win_y_start_property)
-               return -ENOMEM;
-
-       dm->crc_win_x_end_property =
-               drm_property_create_range(adev_to_drm(dm->adev),
-                                         DRM_MODE_PROP_ATOMIC,
-                                         "AMD_CRC_WIN_X_END", 0, U16_MAX);
-       if (!dm->crc_win_x_end_property)
-               return -ENOMEM;
-
-       dm->crc_win_y_end_property =
-               drm_property_create_range(adev_to_drm(dm->adev),
-                                         DRM_MODE_PROP_ATOMIC,
-                                         "AMD_CRC_WIN_Y_END", 0, U16_MAX);
-       if (!dm->crc_win_y_end_property)
-               return -ENOMEM;
-
-       return 0;
-}
-#endif
-
 static int amdgpu_dm_init(struct amdgpu_device *adev)
 {
        struct dc_init_data init_data;
@@ -1120,10 +1085,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
 
                dc_init_callbacks(adev->dm.dc, &init_params);
        }
-#endif
-#ifdef CONFIG_DEBUG_FS
-       if (create_crtc_crc_properties(&adev->dm))
-               DRM_ERROR("amdgpu: failed to create crc property.\n");
 #endif
        if (amdgpu_dm_initialize_drm_device(adev)) {
                DRM_ERROR(
@@ -5333,64 +5294,12 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)
        state->crc_src = cur->crc_src;
        state->cm_has_degamma = cur->cm_has_degamma;
        state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb;
-#ifdef CONFIG_DEBUG_FS
-       state->crc_window = cur->crc_window;
-#endif
+
        /* TODO Duplicate dc_stream after objects are stream object is flattened */
 
        return &state->base;
 }
 
-#ifdef CONFIG_DEBUG_FS
-static int amdgpu_dm_crtc_atomic_set_property(struct drm_crtc *crtc,
-                                           struct drm_crtc_state *crtc_state,
-                                           struct drm_property *property,
-                                           uint64_t val)
-{
-       struct drm_device *dev = crtc->dev;
-       struct amdgpu_device *adev = drm_to_adev(dev);
-       struct dm_crtc_state *dm_new_state =
-               to_dm_crtc_state(crtc_state);
-
-       if (property == adev->dm.crc_win_x_start_property)
-               dm_new_state->crc_window.x_start = val;
-       else if (property == adev->dm.crc_win_y_start_property)
-               dm_new_state->crc_window.y_start = val;
-       else if (property == adev->dm.crc_win_x_end_property)
-               dm_new_state->crc_window.x_end = val;
-       else if (property == adev->dm.crc_win_y_end_property)
-               dm_new_state->crc_window.y_end = val;
-       else
-               return -EINVAL;
-
-       return 0;
-}
-
-static int amdgpu_dm_crtc_atomic_get_property(struct drm_crtc *crtc,
-                                           const struct drm_crtc_state *state,
-                                           struct drm_property *property,
-                                           uint64_t *val)
-{
-       struct drm_device *dev = crtc->dev;
-       struct amdgpu_device *adev = drm_to_adev(dev);
-       struct dm_crtc_state *dm_state =
-               to_dm_crtc_state(state);
-
-       if (property == adev->dm.crc_win_x_start_property)
-               *val = dm_state->crc_window.x_start;
-       else if (property == adev->dm.crc_win_y_start_property)
-               *val = dm_state->crc_window.y_start;
-       else if (property == adev->dm.crc_win_x_end_property)
-               *val = dm_state->crc_window.x_end;
-       else if (property == adev->dm.crc_win_y_end_property)
-               *val = dm_state->crc_window.y_end;
-       else
-               return -EINVAL;
-
-       return 0;
-}
-#endif
-
 static inline int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
 {
        enum dc_irq_source irq_source;
@@ -5457,10 +5366,6 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
        .enable_vblank = dm_enable_vblank,
        .disable_vblank = dm_disable_vblank,
        .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
-#ifdef CONFIG_DEBUG_FS
-       .atomic_set_property = amdgpu_dm_crtc_atomic_set_property,
-       .atomic_get_property = amdgpu_dm_crtc_atomic_get_property,
-#endif
 };
 
 static enum drm_connector_status
@@ -6662,25 +6567,6 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
        return 0;
 }
 
-#ifdef CONFIG_DEBUG_FS
-static void attach_crtc_crc_properties(struct amdgpu_display_manager *dm,
-                               struct amdgpu_crtc *acrtc)
-{
-       drm_object_attach_property(&acrtc->base.base,
-                                  dm->crc_win_x_start_property,
-                                  0);
-       drm_object_attach_property(&acrtc->base.base,
-                                  dm->crc_win_y_start_property,
-                                  0);
-       drm_object_attach_property(&acrtc->base.base,
-                                  dm->crc_win_x_end_property,
-                                  0);
-       drm_object_attach_property(&acrtc->base.base,
-                                  dm->crc_win_y_end_property,
-                                  0);
-}
-#endif
-
 static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
                               struct drm_plane *plane,
                               uint32_t crtc_index)
@@ -6728,9 +6614,7 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
        drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES,
                                   true, MAX_COLOR_LUT_ENTRIES);
        drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES);
-#ifdef CONFIG_DEBUG_FS
-       attach_crtc_crc_properties(dm, acrtc);
-#endif
+
        return 0;
 
 fail:
@@ -8367,7 +8251,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
         */
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-               bool configure_crc = false;
 
                dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
 
@@ -8377,27 +8260,20 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                        dc_stream_retain(dm_new_crtc_state->stream);
                        acrtc->dm_irq_params.stream = dm_new_crtc_state->stream;
                        manage_dm_interrupts(adev, acrtc, true);
-               }
-               if (IS_ENABLED(CONFIG_DEBUG_FS) && new_crtc_state->active &&
-                       amdgpu_dm_is_valid_crc_source(dm_new_crtc_state->crc_src)) {
+
+#ifdef CONFIG_DEBUG_FS
                        /**
                         * Frontend may have changed so reapply the CRC capture
                         * settings for the stream.
                         */
                        dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
-                       dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
 
-                       if (amdgpu_dm_crc_window_is_default(dm_new_crtc_state)) {
-                               if (!old_crtc_state->active || drm_atomic_crtc_needs_modeset(new_crtc_state))
-                                       configure_crc = true;
-                       } else {
-                               if (amdgpu_dm_crc_window_changed(dm_new_crtc_state, dm_old_crtc_state))
-                                       configure_crc = true;
-                       }
-
-                       if (configure_crc)
+                       if (amdgpu_dm_is_valid_crc_source(dm_new_crtc_state->crc_src)) {
                                amdgpu_dm_crtc_configure_crc_source(
-                                       crtc, dm_new_crtc_state, dm_new_crtc_state->crc_src);
+                                       crtc, dm_new_crtc_state,
+                                       dm_new_crtc_state->crc_src);
+                       }
+#endif
                }
        }
 
index 2ee6edb3df931b5eb100722377eff805f9c19fd7..1182dafcef0228fd8818cfd82e597066a7abc3c0 100644 (file)
@@ -336,32 +336,6 @@ struct amdgpu_display_manager {
         */
        const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;
 
-#ifdef CONFIG_DEBUG_FS
-       /**
-        * @crc_win_x_start_property:
-        *
-        * X start of the crc calculation window
-        */
-       struct drm_property *crc_win_x_start_property;
-       /**
-        * @crc_win_y_start_property:
-        *
-        * Y start of the crc calculation window
-        */
-       struct drm_property *crc_win_y_start_property;
-       /**
-        * @crc_win_x_end_property:
-        *
-        * X end of the crc calculation window
-        */
-       struct drm_property *crc_win_x_end_property;
-       /**
-        * @crc_win_y_end_property:
-        *
-        * Y end of the crc calculation window
-        */
-       struct drm_property *crc_win_y_end_property;
-#endif
        /**
         * @mst_encoders:
         *
@@ -448,15 +422,6 @@ struct dm_plane_state {
        struct dc_plane_state *dc_state;
 };
 
-#ifdef CONFIG_DEBUG_FS
-struct crc_rec {
-       uint16_t x_start;
-       uint16_t y_start;
-       uint16_t x_end;
-       uint16_t y_end;
-       };
-#endif
-
 struct dm_crtc_state {
        struct drm_crtc_state base;
        struct dc_stream_state *stream;
@@ -479,9 +444,6 @@ struct dm_crtc_state {
        struct dc_info_packet vrr_infopacket;
 
        int abm_level;
-#ifdef CONFIG_DEBUG_FS
-       struct crc_rec crc_window;
-#endif
 };
 
 #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
index 7b886a779a8cabe94b9b48272869630c2fd9f42e..66cb8730586b1c0b520024bbb501b6b83e536c99 100644 (file)
@@ -81,41 +81,6 @@ const char *const *amdgpu_dm_crtc_get_crc_sources(struct drm_crtc *crtc,
        return pipe_crc_sources;
 }
 
-static void amdgpu_dm_set_crc_window_default(struct dm_crtc_state *dm_crtc_state)
-{
-       dm_crtc_state->crc_window.x_start = 0;
-       dm_crtc_state->crc_window.y_start = 0;
-       dm_crtc_state->crc_window.x_end = 0;
-       dm_crtc_state->crc_window.y_end = 0;
-}
-
-bool amdgpu_dm_crc_window_is_default(struct dm_crtc_state *dm_crtc_state)
-{
-       bool ret = true;
-
-       if ((dm_crtc_state->crc_window.x_start != 0) ||
-               (dm_crtc_state->crc_window.y_start != 0) ||
-               (dm_crtc_state->crc_window.x_end != 0) ||
-               (dm_crtc_state->crc_window.y_end != 0))
-               ret = false;
-
-       return ret;
-}
-
-bool amdgpu_dm_crc_window_changed(struct dm_crtc_state *dm_new_crtc_state,
-                                       struct dm_crtc_state *dm_old_crtc_state)
-{
-       bool ret = false;
-
-       if ((dm_new_crtc_state->crc_window.x_start != dm_old_crtc_state->crc_window.x_start) ||
-               (dm_new_crtc_state->crc_window.y_start != dm_old_crtc_state->crc_window.y_start) ||
-               (dm_new_crtc_state->crc_window.x_end != dm_old_crtc_state->crc_window.x_end) ||
-               (dm_new_crtc_state->crc_window.y_end != dm_old_crtc_state->crc_window.y_end))
-               ret = true;
-
-       return ret;
-}
-
 int
 amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc, const char *src_name,
                                 size_t *values_cnt)
@@ -140,7 +105,6 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
        struct dc_stream_state *stream_state = dm_crtc_state->stream;
        bool enable = amdgpu_dm_is_valid_crc_source(source);
        int ret = 0;
-       struct crc_params *crc_window = NULL, tmp_window;
 
        /* Configuration will be deferred to stream enable. */
        if (!stream_state)
@@ -150,24 +114,8 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
 
        /* Enable CRTC CRC generation if necessary. */
        if (dm_is_crc_source_crtc(source) || source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE) {
-               if (!enable)
-                       amdgpu_dm_set_crc_window_default(dm_crtc_state);
-
-               if (!amdgpu_dm_crc_window_is_default(dm_crtc_state)) {
-                       crc_window = &tmp_window;
-
-                       tmp_window.windowa_x_start = dm_crtc_state->crc_window.x_start;
-                       tmp_window.windowa_y_start = dm_crtc_state->crc_window.y_start;
-                       tmp_window.windowa_x_end = dm_crtc_state->crc_window.x_end;
-                       tmp_window.windowa_y_end = dm_crtc_state->crc_window.y_end;
-                       tmp_window.windowb_x_start = dm_crtc_state->crc_window.x_start;
-                       tmp_window.windowb_y_start = dm_crtc_state->crc_window.y_start;
-                       tmp_window.windowb_x_end = dm_crtc_state->crc_window.x_end;
-                       tmp_window.windowb_y_end = dm_crtc_state->crc_window.y_end;
-               }
-
                if (!dc_stream_configure_crc(stream_state->ctx->dc,
-                                            stream_state, crc_window, enable, enable)) {
+                                            stream_state, NULL, enable, enable)) {
                        ret = -EINVAL;
                        goto unlock;
                }
index eba2f1d35d07548e0b8f50e71939bd435450eb0b..f7d731797d3fc339389ace86c5b27c56b6152b51 100644 (file)
@@ -46,13 +46,10 @@ static inline bool amdgpu_dm_is_valid_crc_source(enum amdgpu_dm_pipe_crc_source
 }
 
 /* amdgpu_dm_crc.c */
-bool amdgpu_dm_crc_window_is_default(struct dm_crtc_state *dm_crtc_state);
-bool amdgpu_dm_crc_window_changed(struct dm_crtc_state *dm_new_crtc_state,
-                                       struct dm_crtc_state *dm_old_crtc_state);
+#ifdef CONFIG_DEBUG_FS
 int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
                                        struct dm_crtc_state *dm_crtc_state,
                                        enum amdgpu_dm_pipe_crc_source source);
-#ifdef CONFIG_DEBUG_FS
 int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name);
 int amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc,
                                     const char *src_name,
index 5b466f440d671a6f6c2333b54eb7ccea20c6d51c..ab98c259ef69562a4b9b6c096fee5535a6bab022 100644 (file)
@@ -251,6 +251,7 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base,
        struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu;
        bool force_reset = false;
        bool update_uclk = false;
+       bool p_state_change_support;
 
        if (dc->work_arounds.skip_clock_update || !clk_mgr->smu_present)
                return;
@@ -291,8 +292,9 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base,
                clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz;
 
        clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support;
-       if (should_update_pstate_support(safe_to_lower, new_clocks->p_state_change_support, clk_mgr_base->clks.p_state_change_support)) {
-               clk_mgr_base->clks.p_state_change_support = new_clocks->p_state_change_support;
+       p_state_change_support = new_clocks->p_state_change_support || (display_count == 0);
+       if (should_update_pstate_support(safe_to_lower, p_state_change_support, clk_mgr_base->clks.p_state_change_support)) {
+               clk_mgr_base->clks.p_state_change_support = p_state_change_support;
 
                /* to disable P-State switching, set UCLK min = max */
                if (!clk_mgr_base->clks.p_state_change_support)
index 2fc12239b22cb72f4c81fbf83b83969b4e6efed0..f95bade5962429b1c4c352aca4a3f1295d952903 100644 (file)
@@ -2399,6 +2399,9 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_setting
                        initial_link_setting;
        uint32_t link_bw;
 
+       if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
+               return false;
+
        /* search for the minimum link setting that:
         * 1. is supported according to the link training result
         * 2. could support the b/w requested by the timing
@@ -3045,14 +3048,14 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
                for (i = 0; i < MAX_PIPES; i++) {
                        pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
                        if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
-                                       pipe_ctx->stream->link == link)
+                                       pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
                                core_link_disable_stream(pipe_ctx);
                }
 
                for (i = 0; i < MAX_PIPES; i++) {
                        pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
                        if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
-                                       pipe_ctx->stream->link == link)
+                                       pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
                                core_link_enable_stream(link->dc->current_state, pipe_ctx);
                }
 
@@ -3992,7 +3995,7 @@ bool dc_link_dp_set_test_pattern(
        unsigned int cust_pattern_size)
 {
        struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
-       struct pipe_ctx *pipe_ctx = &pipes[0];
+       struct pipe_ctx *pipe_ctx = NULL;
        unsigned int lane;
        unsigned int i;
        unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
@@ -4002,12 +4005,18 @@ bool dc_link_dp_set_test_pattern(
        memset(&training_pattern, 0, sizeof(training_pattern));
 
        for (i = 0; i < MAX_PIPES; i++) {
+               if (pipes[i].stream == NULL)
+                       continue;
+
                if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
                        pipe_ctx = &pipes[i];
                        break;
                }
        }
 
+       if (pipe_ctx == NULL)
+               return false;
+
        /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
        if (link->test_pattern_enabled && test_pattern ==
                        DP_TEST_PATTERN_VIDEO_MODE) {
index cfc130e2d6fd01241e3ef0788f03250bd45a2c61..017b67b830e669a05acd66619484787960f97383 100644 (file)
@@ -647,8 +647,13 @@ static void power_on_plane(
        if (REG(DC_IP_REQUEST_CNTL)) {
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 1);
-               hws->funcs.dpp_pg_control(hws, plane_id, true);
-               hws->funcs.hubp_pg_control(hws, plane_id, true);
+
+               if (hws->funcs.dpp_pg_control)
+                       hws->funcs.dpp_pg_control(hws, plane_id, true);
+
+               if (hws->funcs.hubp_pg_control)
+                       hws->funcs.hubp_pg_control(hws, plane_id, true);
+
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 0);
                DC_LOG_DEBUG(
@@ -1082,8 +1087,13 @@ void dcn10_plane_atomic_power_down(struct dc *dc,
        if (REG(DC_IP_REQUEST_CNTL)) {
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 1);
-               hws->funcs.dpp_pg_control(hws, dpp->inst, false);
-               hws->funcs.hubp_pg_control(hws, hubp->inst, false);
+
+               if (hws->funcs.dpp_pg_control)
+                       hws->funcs.dpp_pg_control(hws, dpp->inst, false);
+
+               if (hws->funcs.hubp_pg_control)
+                       hws->funcs.hubp_pg_control(hws, hubp->inst, false);
+
                dpp->funcs->dpp_reset(dpp);
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 0);
index 100ce0e28fd5ab40c85caccf96e86a4f95bc00bf..b096011acb490fff2016c154c2ccd20f723b0479 100644 (file)
@@ -470,7 +470,7 @@ void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool lock)
 unsigned int mpc1_get_mpc_out_mux(struct mpc *mpc, int opp_id)
 {
        struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
-       uint32_t val = 0;
+       uint32_t val = 0xf;
 
        if (opp_id < MAX_OPP && REG(MUX[opp_id]))
                REG_GET(MUX[opp_id], MPC_OUT_MUX, &val);
index 36745193c391c0d949a8b16eeaf81cf187721fce..90e912fef2b36c069142e570bea412bb151486f4 100644 (file)
@@ -608,8 +608,8 @@ static const struct dc_debug_options debug_defaults_drv = {
                .disable_pplib_clock_request = false,
                .disable_pplib_wm_range = false,
                .pplib_wm_report_mode = WM_REPORT_DEFAULT,
-               .pipe_split_policy = MPC_SPLIT_DYNAMIC,
-               .force_single_disp_pipe_split = true,
+               .pipe_split_policy = MPC_SPLIT_AVOID,
+               .force_single_disp_pipe_split = false,
                .disable_dcc = DCC_ENABLE,
                .voltage_align_fclk = true,
                .disable_stereo_support = true,
index cb822df21b7c5a213f7261a2ccd54760a532deaa..480d928cb1ca6edb6a3c1dd9e19ac9575521c199 100644 (file)
@@ -1062,8 +1062,13 @@ static void dcn20_power_on_plane(
        if (REG(DC_IP_REQUEST_CNTL)) {
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 1);
-               dcn20_dpp_pg_control(hws, pipe_ctx->plane_res.dpp->inst, true);
-               dcn20_hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, true);
+
+               if (hws->funcs.dpp_pg_control)
+                       hws->funcs.dpp_pg_control(hws, pipe_ctx->plane_res.dpp->inst, true);
+
+               if (hws->funcs.hubp_pg_control)
+                       hws->funcs.hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, true);
+
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 0);
                DC_LOG_DEBUG(
index e04ecf0fc0dbc6f4c2afa5846c22fd3b3fc5ef78..5ed18cac57e8da901fc02a489ea11c44d745c036 100644 (file)
@@ -2517,8 +2517,7 @@ struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
                 * if this primary pipe has a bottom pipe in prev. state
                 * and if the bottom pipe is still available (which it should be),
                 * pick that pipe as secondary
-                * Same logic applies for ODM pipes. Since mpo is not allowed with odm
-                * check in else case.
+                * Same logic applies for ODM pipes
                 */
                if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) {
                        preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx;
@@ -2526,7 +2525,9 @@ struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
                                secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
                                secondary_pipe->pipe_idx = preferred_pipe_idx;
                        }
-               } else if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) {
+               }
+               if (secondary_pipe == NULL &&
+                               dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) {
                        preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe->pipe_idx;
                        if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
                                secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
index 1c88d2edd381c567e9b0759010051b62a19b39e4..b000b43a820d470bf6e0ee6ae33fd3c4656876bd 100644 (file)
@@ -296,7 +296,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
        .num_banks = 8,
        .num_chans = 4,
        .vmm_page_size_bytes = 4096,
-       .dram_clock_change_latency_us = 23.84,
+       .dram_clock_change_latency_us = 11.72,
        .return_bus_width_bytes = 64,
        .dispclk_dppclk_vco_speed_mhz = 3600,
        .xfc_bus_transport_time_us = 4,
index 4825c5c1c6ed686217ec3f9850a75fd080091bdc..35f5bf08ae96e2570d22282da46f1f499236d4a4 100644 (file)
@@ -1731,6 +1731,7 @@ static struct resource_funcs dcn301_res_pool_funcs = {
        .populate_dml_pipes = dcn30_populate_dml_pipes_from_context,
        .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
        .add_stream_to_ctx = dcn30_add_stream_to_ctx,
+       .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
        .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
        .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context,
        .set_mcif_arb_params = dcn30_set_mcif_arb_params,
index 860e72a51534cc014d9baccf227aeccc1979a4a9..80170f9721ce949330d72408b81c48575af13101 100644 (file)
@@ -2635,14 +2635,15 @@ static void dml20v2_DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndP
        }
 
        if (mode_lib->vba.DRAMClockChangeSupportsVActive &&
-                       mode_lib->vba.MinActiveDRAMClockChangeMargin > 60 &&
-                       mode_lib->vba.PrefetchMode[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb] == 0) {
+                       mode_lib->vba.MinActiveDRAMClockChangeMargin > 60) {
                mode_lib->vba.DRAMClockChangeWatermark += 25;
 
                for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) {
-                       if (mode_lib->vba.DRAMClockChangeWatermark >
-                       dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark))
-                               mode_lib->vba.MinTTUVBlank[k] += 25;
+                       if (mode_lib->vba.PrefetchMode[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb] == 0) {
+                               if (mode_lib->vba.DRAMClockChangeWatermark >
+                               dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark))
+                                       mode_lib->vba.MinTTUVBlank[k] += 25;
+                       }
                }
 
                mode_lib->vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive;
index f743685a20e8a70bf71d0b7885b4da46ec2dda78..9a9697038016027d84c2cc2696a86922df5a8eda 100644 (file)
@@ -1121,7 +1121,7 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu,
 static int renoir_gfx_state_change_set(struct smu_context *smu, uint32_t state)
 {
 
-       return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GpuChangeState, state, NULL);
+       return 0;
 }
 
 static const struct pptable_funcs renoir_ppt_funcs = {
index ba1507036f265bba483090b72aeb757969762c32..4a8cbec832bc46051a8d500fa1ab3df67d23929d 100644 (file)
@@ -3021,7 +3021,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set,
 
        ret = handle_conflicting_encoders(state, true);
        if (ret)
-               return ret;
+               goto fail;
 
        ret = drm_atomic_commit(state);
 
index 02ca22e90290d4a3ad583b69c4b330a90c3cd594..0b232a73c1b74d3a41a11126df9f9a256add07dc 100644 (file)
@@ -387,9 +387,16 @@ static int drm_gem_vram_kmap_locked(struct drm_gem_vram_object *gbo,
        if (gbo->vmap_use_count > 0)
                goto out;
 
-       ret = ttm_bo_vmap(&gbo->bo, &gbo->map);
-       if (ret)
-               return ret;
+       /*
+        * VRAM helpers unmap the BO only on demand. So the previous
+        * page mapping might still be around. Only vmap if the there's
+        * no mapping present.
+        */
+       if (dma_buf_map_is_null(&gbo->map)) {
+               ret = ttm_bo_vmap(&gbo->bo, &gbo->map);
+               if (ret)
+                       return ret;
+       }
 
 out:
        ++gbo->vmap_use_count;
@@ -577,6 +584,7 @@ static void drm_gem_vram_bo_driver_move_notify(struct drm_gem_vram_object *gbo,
                return;
 
        ttm_bo_vunmap(bo, &gbo->map);
+       dma_buf_map_clear(&gbo->map); /* explicitly clear mapping for next vmap call */
 }
 
 static int drm_gem_vram_bo_driver_move(struct drm_gem_vram_object *gbo,
index e6231947f98723a7720504ec61ad00adf4ec08b0..a0cb746bcb0a9a1344e0cd23fa3dcf7a228a9f3b 100644 (file)
@@ -1163,7 +1163,14 @@ retry:
        if (ret)
                goto out;
 
-       if (old_fb->format != fb->format) {
+       /*
+        * Only check the FOURCC format code, excluding modifiers. This is
+        * enough for all legacy drivers. Atomic drivers have their own
+        * checks in their ->atomic_check implementation, which will
+        * return -EINVAL if any hw or driver constraint is violated due
+        * to modifier changes.
+        */
+       if (old_fb->format->format != fb->format->format) {
                DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
                ret = -EINVAL;
                goto out;
index 6e74e6745ecaeb21a864768d66dc07dfe7a11d82..3491460498491d0d8f5f96058b5adbf6a7ef6c80 100644 (file)
@@ -388,19 +388,18 @@ int drm_syncobj_find_fence(struct drm_file *file_private,
                return -ENOENT;
 
        *fence = drm_syncobj_fence_get(syncobj);
-       drm_syncobj_put(syncobj);
 
        if (*fence) {
                ret = dma_fence_chain_find_seqno(fence, point);
                if (!ret)
-                       return 0;
+                       goto out;
                dma_fence_put(*fence);
        } else {
                ret = -EINVAL;
        }
 
        if (!(flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT))
-               return ret;
+               goto out;
 
        memset(&wait, 0, sizeof(wait));
        wait.task = current;
@@ -432,6 +431,9 @@ int drm_syncobj_find_fence(struct drm_file *file_private,
        if (wait.node.next)
                drm_syncobj_remove_wait(syncobj, &wait);
 
+out:
+       drm_syncobj_put(syncobj);
+
        return ret;
 }
 EXPORT_SYMBOL(drm_syncobj_find_fence);
index e5574e506a5ccf03684f47fc0f59d9a62f4ae1d8..6d9e81ea67f4b742d52afaf420a8ccfc9a4ef329 100644 (file)
@@ -38,6 +38,7 @@ i915-y += i915_drv.o \
          i915_config.o \
          i915_irq.o \
          i915_getparam.o \
+         i915_mitigations.o \
          i915_params.o \
          i915_pci.o \
          i915_scatterlist.o \
index a9439b4156037169b17361c2ea7a446f7d45b573..b3533a32f8ba2e4d015532123111c7ee989381a8 100644 (file)
@@ -1616,10 +1616,6 @@ static void gen11_dsi_get_power_domains(struct intel_encoder *encoder,
 
        get_dsi_io_power_domains(i915,
                                 enc_to_intel_dsi(encoder));
-
-       if (crtc_state->dsc.compression_enable)
-               intel_display_power_get(i915,
-                                       intel_dsc_power_domain(crtc_state));
 }
 
 static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
index 92940a0c5ef8fa77c2d5664fcd2d40b864416d2f..d5ace48b1acee3f0283feaf817ccdcee2fa30f32 100644 (file)
@@ -3725,7 +3725,7 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
        intel_ddi_init_dp_buf_reg(encoder, crtc_state);
        if (!is_mst)
                intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
-       intel_dp_configure_protocol_converter(intel_dp);
+       intel_dp_configure_protocol_converter(intel_dp, crtc_state);
        intel_dp_sink_set_decompression_state(intel_dp, crtc_state,
                                              true);
        intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
index 37f1a10fd02172e79f443c32471e74a9b407cf88..09123e8625c498f8f01fcb27ebd29563813d5461 100644 (file)
@@ -4014,7 +4014,8 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp,
        intel_de_posting_read(dev_priv, intel_dp->output_reg);
 }
 
-void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp)
+void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
+                                          const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
        u8 tmp;
@@ -4033,8 +4034,8 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp)
                drm_dbg_kms(&i915->drm, "Failed to set protocol converter HDMI mode to %s\n",
                            enableddisabled(intel_dp->has_hdmi_sink));
 
-       tmp = intel_dp->dfp.ycbcr_444_to_420 ?
-               DP_CONVERSION_TO_YCBCR420_ENABLE : 0;
+       tmp = crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 &&
+               intel_dp->dfp.ycbcr_444_to_420 ? DP_CONVERSION_TO_YCBCR420_ENABLE : 0;
 
        if (drm_dp_dpcd_writeb(&intel_dp->aux,
                               DP_PROTOCOL_CONVERTER_CONTROL_1, tmp) != 1)
@@ -4088,7 +4089,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
        }
 
        intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
-       intel_dp_configure_protocol_converter(intel_dp);
+       intel_dp_configure_protocol_converter(intel_dp, pipe_config);
        intel_dp_start_link_train(intel_dp, pipe_config);
        intel_dp_stop_link_train(intel_dp, pipe_config);
 
index b871a09b69013a398a4b19853f065afabf37ecc7..05f7ddf7a79527620b9cc2db5e6e1ee570fcb539 100644 (file)
@@ -51,7 +51,8 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
 int intel_dp_retrain_link(struct intel_encoder *encoder,
                          struct drm_modeset_acquire_ctx *ctx);
 void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode);
-void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp);
+void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
+                                          const struct intel_crtc_state *crtc_state);
 void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
                                           const struct intel_crtc_state *crtc_state,
                                           bool enable);
index b2a4bbcfdcd25acd81a97d720d18bb50f2aa3964..b9d8825e2bb12f397ea31cee5b2288d6995a0fd0 100644 (file)
@@ -2210,6 +2210,7 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state,
        if (content_protection_type_changed) {
                mutex_lock(&hdcp->mutex);
                hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+               drm_connector_get(&connector->base);
                schedule_work(&hdcp->prop_work);
                mutex_unlock(&hdcp->mutex);
        }
@@ -2221,6 +2222,14 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state,
                desired_and_not_enabled =
                        hdcp->value != DRM_MODE_CONTENT_PROTECTION_ENABLED;
                mutex_unlock(&hdcp->mutex);
+               /*
+                * If HDCP already ENABLED and CP property is DESIRED, schedule
+                * prop_work to update correct CP property to user space.
+                */
+               if (!desired_and_not_enabled && !content_protection_type_changed) {
+                       drm_connector_get(&connector->base);
+                       schedule_work(&hdcp->prop_work);
+               }
        }
 
        if (desired_and_not_enabled || content_protection_type_changed)
index 9f23bac0d7924d3857e1e0e8fdc202f1341dc5b5..d64fce1a17cbc5668f756853a769244554d9504d 100644 (file)
@@ -1650,16 +1650,13 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus
                val = pch_get_backlight(connector);
        else
                val = lpt_get_backlight(connector);
-       val = intel_panel_compute_brightness(connector, val);
-       panel->backlight.level = clamp(val, panel->backlight.min,
-                                      panel->backlight.max);
 
        if (cpu_mode) {
                drm_dbg_kms(&dev_priv->drm,
                            "CPU backlight register was enabled, switching to PCH override\n");
 
                /* Write converted CPU PWM value to PCH override register */
-               lpt_set_backlight(connector->base.state, panel->backlight.level);
+               lpt_set_backlight(connector->base.state, val);
                intel_de_write(dev_priv, BLC_PWM_PCH_CTL1,
                               pch_ctl1 | BLM_PCH_OVERRIDE_ENABLE);
 
@@ -1667,6 +1664,10 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus
                               cpu_ctl2 & ~BLM_PWM_ENABLE);
        }
 
+       val = intel_panel_compute_brightness(connector, val);
+       panel->backlight.level = clamp(val, panel->backlight.min,
+                                      panel->backlight.max);
+
        return 0;
 }
 
index d52f9c1779081e02afa7d843926938f04fc25912..f94025ec603a6d132b0024b05afad604834fad02 100644 (file)
@@ -812,10 +812,20 @@ static void intel_dsi_pre_enable(struct intel_atomic_state *state,
                intel_dsi_prepare(encoder, pipe_config);
 
        intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_ON);
-       intel_dsi_msleep(intel_dsi, intel_dsi->panel_on_delay);
 
-       /* Deassert reset */
-       intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET);
+       /*
+        * Give the panel time to power-on and then deassert its reset.
+        * Depending on the VBT MIPI sequences version the deassert-seq
+        * may contain the necessary delay, intel_dsi_msleep() will skip
+        * the delay in that case. If there is no deassert-seq, then an
+        * unconditional msleep is used to give the panel time to power-on.
+        */
+       if (dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]) {
+               intel_dsi_msleep(intel_dsi, intel_dsi->panel_on_delay);
+               intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET);
+       } else {
+               msleep(intel_dsi->panel_on_delay);
+       }
 
        if (IS_GEMINILAKE(dev_priv)) {
                glk_cold_boot = glk_dsi_enable_io(encoder);
index d93d85cd30270ba371ac877632b1d2261dcdc8e5..94465374ca2fe5505c67804bf697d5b88f9c102f 100644 (file)
@@ -7,8 +7,6 @@
 #include "i915_drv.h"
 #include "intel_gpu_commands.h"
 
-#define MAX_URB_ENTRIES 64
-#define STATE_SIZE (4 * 1024)
 #define GT3_INLINE_DATA_DELAYS 0x1E00
 #define batch_advance(Y, CS) GEM_BUG_ON((Y)->end != (CS))
 
@@ -34,38 +32,59 @@ struct batch_chunk {
 };
 
 struct batch_vals {
-       u32 max_primitives;
-       u32 max_urb_entries;
-       u32 cmd_size;
-       u32 state_size;
+       u32 max_threads;
        u32 state_start;
-       u32 batch_size;
+       u32 surface_start;
        u32 surface_height;
        u32 surface_width;
-       u32 scratch_size;
-       u32 max_size;
+       u32 size;
 };
 
+static inline int num_primitives(const struct batch_vals *bv)
+{
+       /*
+        * We need to saturate the GPU with work in order to dispatch
+        * a shader on every HW thread, and clear the thread-local registers.
+        * In short, we have to dispatch work faster than the shaders can
+        * run in order to fill the EU and occupy each HW thread.
+        */
+       return bv->max_threads;
+}
+
 static void
 batch_get_defaults(struct drm_i915_private *i915, struct batch_vals *bv)
 {
        if (IS_HASWELL(i915)) {
-               bv->max_primitives = 280;
-               bv->max_urb_entries = MAX_URB_ENTRIES;
+               switch (INTEL_INFO(i915)->gt) {
+               default:
+               case 1:
+                       bv->max_threads = 70;
+                       break;
+               case 2:
+                       bv->max_threads = 140;
+                       break;
+               case 3:
+                       bv->max_threads = 280;
+                       break;
+               }
                bv->surface_height = 16 * 16;
                bv->surface_width = 32 * 2 * 16;
        } else {
-               bv->max_primitives = 128;
-               bv->max_urb_entries = MAX_URB_ENTRIES / 2;
+               switch (INTEL_INFO(i915)->gt) {
+               default:
+               case 1: /* including vlv */
+                       bv->max_threads = 36;
+                       break;
+               case 2:
+                       bv->max_threads = 128;
+                       break;
+               }
                bv->surface_height = 16 * 8;
                bv->surface_width = 32 * 16;
        }
-       bv->cmd_size = bv->max_primitives * 4096;
-       bv->state_size = STATE_SIZE;
-       bv->state_start = bv->cmd_size;
-       bv->batch_size = bv->cmd_size + bv->state_size;
-       bv->scratch_size = bv->surface_height * bv->surface_width;
-       bv->max_size = bv->batch_size + bv->scratch_size;
+       bv->state_start = round_up(SZ_1K + num_primitives(bv) * 64, SZ_4K);
+       bv->surface_start = bv->state_start + SZ_4K;
+       bv->size = bv->surface_start + bv->surface_height * bv->surface_width;
 }
 
 static void batch_init(struct batch_chunk *bc,
@@ -155,7 +174,8 @@ static u32
 gen7_fill_binding_table(struct batch_chunk *state,
                        const struct batch_vals *bv)
 {
-       u32 surface_start = gen7_fill_surface_state(state, bv->batch_size, bv);
+       u32 surface_start =
+               gen7_fill_surface_state(state, bv->surface_start, bv);
        u32 *cs = batch_alloc_items(state, 32, 8);
        u32 offset = batch_offset(state, cs);
 
@@ -214,9 +234,9 @@ static void
 gen7_emit_state_base_address(struct batch_chunk *batch,
                             u32 surface_state_base)
 {
-       u32 *cs = batch_alloc_items(batch, 0, 12);
+       u32 *cs = batch_alloc_items(batch, 0, 10);
 
-       *cs++ = STATE_BASE_ADDRESS | (12 - 2);
+       *cs++ = STATE_BASE_ADDRESS | (10 - 2);
        /* general */
        *cs++ = batch_addr(batch) | BASE_ADDRESS_MODIFY;
        /* surface */
@@ -233,8 +253,6 @@ gen7_emit_state_base_address(struct batch_chunk *batch,
        *cs++ = BASE_ADDRESS_MODIFY;
        *cs++ = 0;
        *cs++ = BASE_ADDRESS_MODIFY;
-       *cs++ = 0;
-       *cs++ = 0;
        batch_advance(batch, cs);
 }
 
@@ -244,8 +262,7 @@ gen7_emit_vfe_state(struct batch_chunk *batch,
                    u32 urb_size, u32 curbe_size,
                    u32 mode)
 {
-       u32 urb_entries = bv->max_urb_entries;
-       u32 threads = bv->max_primitives - 1;
+       u32 threads = bv->max_threads - 1;
        u32 *cs = batch_alloc_items(batch, 32, 8);
 
        *cs++ = MEDIA_VFE_STATE | (8 - 2);
@@ -254,7 +271,7 @@ gen7_emit_vfe_state(struct batch_chunk *batch,
        *cs++ = 0;
 
        /* number of threads & urb entries for GPGPU vs Media Mode */
-       *cs++ = threads << 16 | urb_entries << 8 | mode << 2;
+       *cs++ = threads << 16 | 1 << 8 | mode << 2;
 
        *cs++ = 0;
 
@@ -293,17 +310,12 @@ gen7_emit_media_object(struct batch_chunk *batch,
 {
        unsigned int x_offset = (media_object_index % 16) * 64;
        unsigned int y_offset = (media_object_index / 16) * 16;
-       unsigned int inline_data_size;
-       unsigned int media_batch_size;
-       unsigned int i;
+       unsigned int pkt = 6 + 3;
        u32 *cs;
 
-       inline_data_size = 112 * 8;
-       media_batch_size = inline_data_size + 6;
-
-       cs = batch_alloc_items(batch, 8, media_batch_size);
+       cs = batch_alloc_items(batch, 8, pkt);
 
-       *cs++ = MEDIA_OBJECT | (media_batch_size - 2);
+       *cs++ = MEDIA_OBJECT | (pkt - 2);
 
        /* interface descriptor offset */
        *cs++ = 0;
@@ -317,25 +329,44 @@ gen7_emit_media_object(struct batch_chunk *batch,
        *cs++ = 0;
 
        /* inline */
-       *cs++ = (y_offset << 16) | (x_offset);
+       *cs++ = y_offset << 16 | x_offset;
        *cs++ = 0;
        *cs++ = GT3_INLINE_DATA_DELAYS;
-       for (i = 3; i < inline_data_size; i++)
-               *cs++ = 0;
 
        batch_advance(batch, cs);
 }
 
 static void gen7_emit_pipeline_flush(struct batch_chunk *batch)
 {
-       u32 *cs = batch_alloc_items(batch, 0, 5);
+       u32 *cs = batch_alloc_items(batch, 0, 4);
 
-       *cs++ = GFX_OP_PIPE_CONTROL(5);
-       *cs++ = PIPE_CONTROL_STATE_CACHE_INVALIDATE |
-               PIPE_CONTROL_GLOBAL_GTT_IVB;
+       *cs++ = GFX_OP_PIPE_CONTROL(4);
+       *cs++ = PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
+               PIPE_CONTROL_DEPTH_CACHE_FLUSH |
+               PIPE_CONTROL_DC_FLUSH_ENABLE |
+               PIPE_CONTROL_CS_STALL;
        *cs++ = 0;
        *cs++ = 0;
+
+       batch_advance(batch, cs);
+}
+
+static void gen7_emit_pipeline_invalidate(struct batch_chunk *batch)
+{
+       u32 *cs = batch_alloc_items(batch, 0, 8);
+
+       /* ivb: Stall before STATE_CACHE_INVALIDATE */
+       *cs++ = GFX_OP_PIPE_CONTROL(4);
+       *cs++ = PIPE_CONTROL_STALL_AT_SCOREBOARD |
+               PIPE_CONTROL_CS_STALL;
+       *cs++ = 0;
+       *cs++ = 0;
+
+       *cs++ = GFX_OP_PIPE_CONTROL(4);
+       *cs++ = PIPE_CONTROL_STATE_CACHE_INVALIDATE;
        *cs++ = 0;
+       *cs++ = 0;
+
        batch_advance(batch, cs);
 }
 
@@ -344,34 +375,34 @@ static void emit_batch(struct i915_vma * const vma,
                       const struct batch_vals *bv)
 {
        struct drm_i915_private *i915 = vma->vm->i915;
-       unsigned int desc_count = 64;
-       const u32 urb_size = 112;
+       const unsigned int desc_count = 1;
+       const unsigned int urb_size = 1;
        struct batch_chunk cmds, state;
-       u32 interface_descriptor;
+       u32 descriptors;
        unsigned int i;
 
-       batch_init(&cmds, vma, start, 0, bv->cmd_size);
-       batch_init(&state, vma, start, bv->state_start, bv->state_size);
+       batch_init(&cmds, vma, start, 0, bv->state_start);
+       batch_init(&state, vma, start, bv->state_start, SZ_4K);
 
-       interface_descriptor =
-               gen7_fill_interface_descriptor(&state, bv,
-                                              IS_HASWELL(i915) ?
-                                              &cb_kernel_hsw :
-                                              &cb_kernel_ivb,
-                                              desc_count);
-       gen7_emit_pipeline_flush(&cmds);
+       descriptors = gen7_fill_interface_descriptor(&state, bv,
+                                                    IS_HASWELL(i915) ?
+                                                    &cb_kernel_hsw :
+                                                    &cb_kernel_ivb,
+                                                    desc_count);
+
+       gen7_emit_pipeline_invalidate(&cmds);
        batch_add(&cmds, PIPELINE_SELECT | PIPELINE_SELECT_MEDIA);
        batch_add(&cmds, MI_NOOP);
-       gen7_emit_state_base_address(&cmds, interface_descriptor);
+       gen7_emit_pipeline_invalidate(&cmds);
+
        gen7_emit_pipeline_flush(&cmds);
+       gen7_emit_state_base_address(&cmds, descriptors);
+       gen7_emit_pipeline_invalidate(&cmds);
 
        gen7_emit_vfe_state(&cmds, bv, urb_size - 1, 0, 0);
+       gen7_emit_interface_descriptor_load(&cmds, descriptors, desc_count);
 
-       gen7_emit_interface_descriptor_load(&cmds,
-                                           interface_descriptor,
-                                           desc_count);
-
-       for (i = 0; i < bv->max_primitives; i++)
+       for (i = 0; i < num_primitives(bv); i++)
                gen7_emit_media_object(&cmds, i);
 
        batch_add(&cmds, MI_BATCH_BUFFER_END);
@@ -385,15 +416,15 @@ int gen7_setup_clear_gpr_bb(struct intel_engine_cs * const engine,
 
        batch_get_defaults(engine->i915, &bv);
        if (!vma)
-               return bv.max_size;
+               return bv.size;
 
-       GEM_BUG_ON(vma->obj->base.size < bv.max_size);
+       GEM_BUG_ON(vma->obj->base.size < bv.size);
 
        batch = i915_gem_object_pin_map(vma->obj, I915_MAP_WC);
        if (IS_ERR(batch))
                return PTR_ERR(batch);
 
-       emit_batch(vma, memset(batch, 0, bv.max_size), &bv);
+       emit_batch(vma, memset(batch, 0, bv.size), &bv);
 
        i915_gem_object_flush_map(vma->obj);
        __i915_gem_object_release_map(vma->obj);
index a24cc1ff08a0c4a6b2d4853fdfa5af04973cca91..0625cbb3b431202b33373f7af3367e015c8c42a3 100644 (file)
@@ -134,11 +134,6 @@ static bool remove_signaling_context(struct intel_breadcrumbs *b,
        return true;
 }
 
-static inline bool __request_completed(const struct i915_request *rq)
-{
-       return i915_seqno_passed(__hwsp_seqno(rq), rq->fence.seqno);
-}
-
 __maybe_unused static bool
 check_signal_order(struct intel_context *ce, struct i915_request *rq)
 {
@@ -257,7 +252,7 @@ static void signal_irq_work(struct irq_work *work)
                list_for_each_entry_rcu(rq, &ce->signals, signal_link) {
                        bool release;
 
-                       if (!__request_completed(rq))
+                       if (!__i915_request_is_complete(rq))
                                break;
 
                        if (!test_and_clear_bit(I915_FENCE_FLAG_SIGNAL,
@@ -379,7 +374,7 @@ static void insert_breadcrumb(struct i915_request *rq)
         * straight onto a signaled list, and queue the irq worker for
         * its signal completion.
         */
-       if (__request_completed(rq)) {
+       if (__i915_request_is_complete(rq)) {
                if (__signal_request(rq) &&
                    llist_add(&rq->signal_node, &b->signaled_requests))
                        irq_work_queue(&b->irq_work);
index 7614a3d24fca5e65783dcf6ebf1126c175a8c2fa..26c7d0a50585a0e2808a17e0a7745d5c6b77d787 100644 (file)
@@ -3988,6 +3988,9 @@ err:
 static void lrc_destroy_wa_ctx(struct intel_engine_cs *engine)
 {
        i915_vma_unpin_and_release(&engine->wa_ctx.vma, 0);
+
+       /* Called on error unwind, clear all flags to prevent further use */
+       memset(&engine->wa_ctx, 0, sizeof(engine->wa_ctx));
 }
 
 typedef u32 *(*wa_bb_func_t)(struct intel_engine_cs *engine, u32 *batch);
index a41b43f445b8ae3fee0f545a7d3a29e5ef10a3c9..ecf3a6118a6d7989a36488672faca28edf37fdc6 100644 (file)
@@ -32,6 +32,7 @@
 #include "gen6_ppgtt.h"
 #include "gen7_renderclear.h"
 #include "i915_drv.h"
+#include "i915_mitigations.h"
 #include "intel_breadcrumbs.h"
 #include "intel_context.h"
 #include "intel_gt.h"
@@ -886,7 +887,8 @@ static int switch_context(struct i915_request *rq)
        GEM_BUG_ON(HAS_EXECLISTS(engine->i915));
 
        if (engine->wa_ctx.vma && ce != engine->kernel_context) {
-               if (engine->wa_ctx.vma->private != ce) {
+               if (engine->wa_ctx.vma->private != ce &&
+                   i915_mitigate_clear_residuals()) {
                        ret = clear_residuals(rq);
                        if (ret)
                                return ret;
@@ -1290,7 +1292,7 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine)
 
        GEM_BUG_ON(timeline->hwsp_ggtt != engine->status_page.vma);
 
-       if (IS_HASWELL(engine->i915) && engine->class == RENDER_CLASS) {
+       if (IS_GEN(engine->i915, 7) && engine->class == RENDER_CLASS) {
                err = gen7_ctx_switch_bb_init(engine);
                if (err)
                        goto err_ring_unpin;
index 7ea94d201fe6fbd9c5e8d1e160621bfd2ceaf273..8015964043eb7ad4e0bce14f88373dbd2577f6f3 100644 (file)
@@ -126,6 +126,10 @@ static void __rcu_cacheline_free(struct rcu_head *rcu)
        struct intel_timeline_cacheline *cl =
                container_of(rcu, typeof(*cl), rcu);
 
+       /* Must wait until after all *rq->hwsp are complete before removing */
+       i915_gem_object_unpin_map(cl->hwsp->vma->obj);
+       __idle_hwsp_free(cl->hwsp, ptr_unmask_bits(cl->vaddr, CACHELINE_BITS));
+
        i915_active_fini(&cl->active);
        kfree(cl);
 }
@@ -133,11 +137,6 @@ static void __rcu_cacheline_free(struct rcu_head *rcu)
 static void __idle_cacheline_free(struct intel_timeline_cacheline *cl)
 {
        GEM_BUG_ON(!i915_active_is_idle(&cl->active));
-
-       i915_gem_object_unpin_map(cl->hwsp->vma->obj);
-       i915_vma_put(cl->hwsp->vma);
-       __idle_hwsp_free(cl->hwsp, ptr_unmask_bits(cl->vaddr, CACHELINE_BITS));
-
        call_rcu(&cl->rcu, __rcu_cacheline_free);
 }
 
@@ -179,7 +178,6 @@ cacheline_alloc(struct intel_timeline_hwsp *hwsp, unsigned int cacheline)
                return ERR_CAST(vaddr);
        }
 
-       i915_vma_get(hwsp->vma);
        cl->hwsp = hwsp;
        cl->vaddr = page_pack_bits(vaddr, cacheline);
 
index a15f875396576d0a0e56a79068de2ec75d0758bd..62a5b0dd2003b76ece28cc0a12db1dd178ee8e07 100644 (file)
@@ -217,6 +217,15 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
                                  DDI_BUF_CTL_ENABLE);
                        vgpu_vreg_t(vgpu, DDI_BUF_CTL(port)) |= DDI_BUF_IS_IDLE;
                }
+               vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+                       ~(PORTA_HOTPLUG_ENABLE | PORTA_HOTPLUG_STATUS_MASK);
+               vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+                       ~(PORTB_HOTPLUG_ENABLE | PORTB_HOTPLUG_STATUS_MASK);
+               vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+                       ~(PORTC_HOTPLUG_ENABLE | PORTC_HOTPLUG_STATUS_MASK);
+               /* No hpd_invert set in vgpu vbt, need to clear invert mask */
+               vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &= ~BXT_DDI_HPD_INVERT_MASK;
+               vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &= ~BXT_DE_PORT_HOTPLUG_MASK;
 
                vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) &= ~(BIT(0) | BIT(1));
                vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) &=
@@ -273,6 +282,8 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
                        vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)) |=
                                (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
                                 TRANS_DDI_FUNC_ENABLE);
+                       vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+                               PORTA_HOTPLUG_ENABLE;
                        vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
                                GEN8_DE_PORT_HOTPLUG(HPD_PORT_A);
                }
@@ -301,6 +312,8 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
                                (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
                                 (PORT_B << TRANS_DDI_PORT_SHIFT) |
                                 TRANS_DDI_FUNC_ENABLE);
+                       vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+                               PORTB_HOTPLUG_ENABLE;
                        vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
                                GEN8_DE_PORT_HOTPLUG(HPD_PORT_B);
                }
@@ -329,6 +342,8 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
                                (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
                                 (PORT_B << TRANS_DDI_PORT_SHIFT) |
                                 TRANS_DDI_FUNC_ENABLE);
+                       vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+                               PORTC_HOTPLUG_ENABLE;
                        vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
                                GEN8_DE_PORT_HOTPLUG(HPD_PORT_C);
                }
@@ -661,44 +676,62 @@ void intel_vgpu_emulate_hotplug(struct intel_vgpu *vgpu, bool connected)
                                PORTD_HOTPLUG_STATUS_MASK;
                intel_vgpu_trigger_virtual_event(vgpu, DP_D_HOTPLUG);
        } else if (IS_BROXTON(i915)) {
-               if (connected) {
-                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
+               if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
+                       if (connected) {
                                vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
                                        GEN8_DE_PORT_HOTPLUG(HPD_PORT_A);
+                       } else {
+                               vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
+                                       ~GEN8_DE_PORT_HOTPLUG(HPD_PORT_A);
                        }
-                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
-                               vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
-                                       SFUSE_STRAP_DDIB_DETECTED;
+                       vgpu_vreg_t(vgpu, GEN8_DE_PORT_IIR) |=
+                               GEN8_DE_PORT_HOTPLUG(HPD_PORT_A);
+                       vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+                               ~PORTA_HOTPLUG_STATUS_MASK;
+                       vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+                               PORTA_HOTPLUG_LONG_DETECT;
+                       intel_vgpu_trigger_virtual_event(vgpu, DP_A_HOTPLUG);
+               }
+               if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
+                       if (connected) {
                                vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
                                        GEN8_DE_PORT_HOTPLUG(HPD_PORT_B);
-                       }
-                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
                                vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
-                                       SFUSE_STRAP_DDIC_DETECTED;
-                               vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
-                                       GEN8_DE_PORT_HOTPLUG(HPD_PORT_C);
-                       }
-               } else {
-                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
+                                       SFUSE_STRAP_DDIB_DETECTED;
+                       } else {
                                vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
-                                       ~GEN8_DE_PORT_HOTPLUG(HPD_PORT_A);
-                       }
-                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
+                                       ~GEN8_DE_PORT_HOTPLUG(HPD_PORT_B);
                                vgpu_vreg_t(vgpu, SFUSE_STRAP) &=
                                        ~SFUSE_STRAP_DDIB_DETECTED;
-                               vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
-                                       ~GEN8_DE_PORT_HOTPLUG(HPD_PORT_B);
                        }
-                       if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
-                               vgpu_vreg_t(vgpu, SFUSE_STRAP) &=
-                                       ~SFUSE_STRAP_DDIC_DETECTED;
+                       vgpu_vreg_t(vgpu, GEN8_DE_PORT_IIR) |=
+                               GEN8_DE_PORT_HOTPLUG(HPD_PORT_B);
+                       vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+                               ~PORTB_HOTPLUG_STATUS_MASK;
+                       vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+                               PORTB_HOTPLUG_LONG_DETECT;
+                       intel_vgpu_trigger_virtual_event(vgpu, DP_B_HOTPLUG);
+               }
+               if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
+                       if (connected) {
+                               vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
+                                       GEN8_DE_PORT_HOTPLUG(HPD_PORT_C);
+                               vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
+                                       SFUSE_STRAP_DDIC_DETECTED;
+                       } else {
                                vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
                                        ~GEN8_DE_PORT_HOTPLUG(HPD_PORT_C);
+                               vgpu_vreg_t(vgpu, SFUSE_STRAP) &=
+                                       ~SFUSE_STRAP_DDIC_DETECTED;
                        }
+                       vgpu_vreg_t(vgpu, GEN8_DE_PORT_IIR) |=
+                               GEN8_DE_PORT_HOTPLUG(HPD_PORT_C);
+                       vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+                               ~PORTC_HOTPLUG_STATUS_MASK;
+                       vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+                               PORTC_HOTPLUG_LONG_DETECT;
+                       intel_vgpu_trigger_virtual_event(vgpu, DP_C_HOTPLUG);
                }
-               vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
-                       PORTB_HOTPLUG_STATUS_MASK;
-               intel_vgpu_trigger_virtual_event(vgpu, DP_B_HOTPLUG);
        }
 }
 
index e49944fde3339aafd16962ace9fab7337e0c0f6a..cbe5931906e0a8976aa7ecd4b0d820d05fd6ea42 100644 (file)
@@ -437,10 +437,9 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
        if (ret)
                goto out_clean_sched_policy;
 
-       if (IS_BROADWELL(dev_priv))
+       if (IS_BROADWELL(dev_priv) || IS_BROXTON(dev_priv))
                ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_B);
-       /* FixMe: Re-enable APL/BXT once vfio_edid enabled */
-       else if (!IS_BROXTON(dev_priv))
+       else
                ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_D);
        if (ret)
                goto out_clean_sched_policy;
index 88ad754962af1e3d2e7cc23176755f34b6029355..99eb0d7bbc447fb7b4c58798ce66e6752189bc18 100644 (file)
@@ -1047,6 +1047,8 @@ static void intel_shutdown_encoders(struct drm_i915_private *dev_priv)
 
 void i915_driver_shutdown(struct drm_i915_private *i915)
 {
+       disable_rpm_wakeref_asserts(&i915->runtime_pm);
+
        i915_gem_suspend(i915);
 
        drm_kms_helper_poll_disable(&i915->drm);
@@ -1060,6 +1062,8 @@ void i915_driver_shutdown(struct drm_i915_private *i915)
 
        intel_suspend_encoders(i915);
        intel_shutdown_encoders(i915);
+
+       enable_rpm_wakeref_asserts(&i915->runtime_pm);
 }
 
 static bool suspend_to_idle(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/i915_mitigations.c b/drivers/gpu/drm/i915/i915_mitigations.c
new file mode 100644 (file)
index 0000000..84f1259
--- /dev/null
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright Â© 2021 Intel Corporation
+ */
+
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "i915_drv.h"
+#include "i915_mitigations.h"
+
+static unsigned long mitigations __read_mostly = ~0UL;
+
+enum {
+       CLEAR_RESIDUALS = 0,
+};
+
+static const char * const names[] = {
+       [CLEAR_RESIDUALS] = "residuals",
+};
+
+bool i915_mitigate_clear_residuals(void)
+{
+       return READ_ONCE(mitigations) & BIT(CLEAR_RESIDUALS);
+}
+
+static int mitigations_set(const char *val, const struct kernel_param *kp)
+{
+       unsigned long new = ~0UL;
+       char *str, *sep, *tok;
+       bool first = true;
+       int err = 0;
+
+       BUILD_BUG_ON(ARRAY_SIZE(names) >= BITS_PER_TYPE(mitigations));
+
+       str = kstrdup(val, GFP_KERNEL);
+       if (!str)
+               return -ENOMEM;
+
+       for (sep = str; (tok = strsep(&sep, ","));) {
+               bool enable = true;
+               int i;
+
+               /* Be tolerant of leading/trailing whitespace */
+               tok = strim(tok);
+
+               if (first) {
+                       first = false;
+
+                       if (!strcmp(tok, "auto"))
+                               continue;
+
+                       new = 0;
+                       if (!strcmp(tok, "off"))
+                               continue;
+               }
+
+               if (*tok == '!') {
+                       enable = !enable;
+                       tok++;
+               }
+
+               if (!strncmp(tok, "no", 2)) {
+                       enable = !enable;
+                       tok += 2;
+               }
+
+               if (*tok == '\0')
+                       continue;
+
+               for (i = 0; i < ARRAY_SIZE(names); i++) {
+                       if (!strcmp(tok, names[i])) {
+                               if (enable)
+                                       new |= BIT(i);
+                               else
+                                       new &= ~BIT(i);
+                               break;
+                       }
+               }
+               if (i == ARRAY_SIZE(names)) {
+                       pr_err("Bad \"%s.mitigations=%s\", '%s' is unknown\n",
+                              DRIVER_NAME, val, tok);
+                       err = -EINVAL;
+                       break;
+               }
+       }
+       kfree(str);
+       if (err)
+               return err;
+
+       WRITE_ONCE(mitigations, new);
+       return 0;
+}
+
+static int mitigations_get(char *buffer, const struct kernel_param *kp)
+{
+       unsigned long local = READ_ONCE(mitigations);
+       int count, i;
+       bool enable;
+
+       if (!local)
+               return scnprintf(buffer, PAGE_SIZE, "%s\n", "off");
+
+       if (local & BIT(BITS_PER_LONG - 1)) {
+               count = scnprintf(buffer, PAGE_SIZE, "%s,", "auto");
+               enable = false;
+       } else {
+               enable = true;
+               count = 0;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(names); i++) {
+               if ((local & BIT(i)) != enable)
+                       continue;
+
+               count += scnprintf(buffer + count, PAGE_SIZE - count,
+                                  "%s%s,", enable ? "" : "!", names[i]);
+       }
+
+       buffer[count - 1] = '\n';
+       return count;
+}
+
+static const struct kernel_param_ops ops = {
+       .set = mitigations_set,
+       .get = mitigations_get,
+};
+
+module_param_cb_unsafe(mitigations, &ops, NULL, 0600);
+MODULE_PARM_DESC(mitigations,
+"Selectively enable security mitigations for all Intel® GPUs in the system.\n"
+"\n"
+"  auto -- enables all mitigations required for the platform [default]\n"
+"  off  -- disables all mitigations\n"
+"\n"
+"Individual mitigations can be enabled by passing a comma-separated string,\n"
+"e.g. mitigations=residuals to enable only clearing residuals or\n"
+"mitigations=auto,noresiduals to disable only the clear residual mitigation.\n"
+"Either '!' or 'no' may be used to switch from enabling the mitigation to\n"
+"disabling it.\n"
+"\n"
+"Active mitigations for Ivybridge, Baytrail, Haswell:\n"
+"  residuals -- clear all thread-local registers between contexts"
+);
diff --git a/drivers/gpu/drm/i915/i915_mitigations.h b/drivers/gpu/drm/i915/i915_mitigations.h
new file mode 100644 (file)
index 0000000..1359d81
--- /dev/null
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright Â© 2021 Intel Corporation
+ */
+
+#ifndef __I915_MITIGATIONS_H__
+#define __I915_MITIGATIONS_H__
+
+#include <linux/types.h>
+
+bool i915_mitigate_clear_residuals(void);
+
+#endif /* __I915_MITIGATIONS_H__ */
index d76685ce03998143a090a52e787f799bcfc19a5b..9856479b56d8bf17ea4f2731601b7d0cc7177cb4 100644 (file)
@@ -184,13 +184,24 @@ static u64 get_rc6(struct intel_gt *gt)
        return val;
 }
 
-static void park_rc6(struct drm_i915_private *i915)
+static void init_rc6(struct i915_pmu *pmu)
 {
-       struct i915_pmu *pmu = &i915->pmu;
+       struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
+       intel_wakeref_t wakeref;
 
-       if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY))
+       with_intel_runtime_pm(i915->gt.uncore->rpm, wakeref) {
                pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt);
+               pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur =
+                                       pmu->sample[__I915_SAMPLE_RC6].cur;
+               pmu->sleep_last = ktime_get();
+       }
+}
 
+static void park_rc6(struct drm_i915_private *i915)
+{
+       struct i915_pmu *pmu = &i915->pmu;
+
+       pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt);
        pmu->sleep_last = ktime_get();
 }
 
@@ -201,6 +212,7 @@ static u64 get_rc6(struct intel_gt *gt)
        return __get_rc6(gt);
 }
 
+static void init_rc6(struct i915_pmu *pmu) { }
 static void park_rc6(struct drm_i915_private *i915) {}
 
 #endif
@@ -612,10 +624,8 @@ static void i915_pmu_enable(struct perf_event *event)
                container_of(event->pmu, typeof(*i915), pmu.base);
        unsigned int bit = event_enabled_bit(event);
        struct i915_pmu *pmu = &i915->pmu;
-       intel_wakeref_t wakeref;
        unsigned long flags;
 
-       wakeref = intel_runtime_pm_get(&i915->runtime_pm);
        spin_lock_irqsave(&pmu->lock, flags);
 
        /*
@@ -626,13 +636,6 @@ static void i915_pmu_enable(struct perf_event *event)
        GEM_BUG_ON(bit >= ARRAY_SIZE(pmu->enable_count));
        GEM_BUG_ON(pmu->enable_count[bit] == ~0);
 
-       if (pmu->enable_count[bit] == 0 &&
-           config_enabled_mask(I915_PMU_RC6_RESIDENCY) & BIT_ULL(bit)) {
-               pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur = 0;
-               pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt);
-               pmu->sleep_last = ktime_get();
-       }
-
        pmu->enable |= BIT_ULL(bit);
        pmu->enable_count[bit]++;
 
@@ -673,8 +676,6 @@ static void i915_pmu_enable(struct perf_event *event)
         * an existing non-zero value.
         */
        local64_set(&event->hw.prev_count, __i915_pmu_event_read(event));
-
-       intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 }
 
 static void i915_pmu_disable(struct perf_event *event)
@@ -1130,6 +1131,7 @@ void i915_pmu_register(struct drm_i915_private *i915)
        hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        pmu->timer.function = i915_sample;
        pmu->cpuhp.cpu = -1;
+       init_rc6(pmu);
 
        if (!is_igp(i915)) {
                pmu->name = kasprintf(GFP_KERNEL,
index 620b6fab2c5cfb8cd19dfbf0ae12d9f80ba93b3d..92adfee30c7c022def7ad74e29865a16221a9764 100644 (file)
@@ -434,7 +434,7 @@ static inline u32 hwsp_seqno(const struct i915_request *rq)
 
 static inline bool __i915_request_has_started(const struct i915_request *rq)
 {
-       return i915_seqno_passed(hwsp_seqno(rq), rq->fence.seqno - 1);
+       return i915_seqno_passed(__hwsp_seqno(rq), rq->fence.seqno - 1);
 }
 
 /**
@@ -465,11 +465,19 @@ static inline bool __i915_request_has_started(const struct i915_request *rq)
  */
 static inline bool i915_request_started(const struct i915_request *rq)
 {
+       bool result;
+
        if (i915_request_signaled(rq))
                return true;
 
-       /* Remember: started but may have since been preempted! */
-       return __i915_request_has_started(rq);
+       result = true;
+       rcu_read_lock(); /* the HWSP may be freed at runtime */
+       if (likely(!i915_request_signaled(rq)))
+               /* Remember: started but may have since been preempted! */
+               result = __i915_request_has_started(rq);
+       rcu_read_unlock();
+
+       return result;
 }
 
 /**
@@ -482,10 +490,16 @@ static inline bool i915_request_started(const struct i915_request *rq)
  */
 static inline bool i915_request_is_running(const struct i915_request *rq)
 {
+       bool result;
+
        if (!i915_request_is_active(rq))
                return false;
 
-       return __i915_request_has_started(rq);
+       rcu_read_lock();
+       result = __i915_request_has_started(rq) && i915_request_is_active(rq);
+       rcu_read_unlock();
+
+       return result;
 }
 
 /**
@@ -509,12 +523,25 @@ static inline bool i915_request_is_ready(const struct i915_request *rq)
        return !list_empty(&rq->sched.link);
 }
 
+static inline bool __i915_request_is_complete(const struct i915_request *rq)
+{
+       return i915_seqno_passed(__hwsp_seqno(rq), rq->fence.seqno);
+}
+
 static inline bool i915_request_completed(const struct i915_request *rq)
 {
+       bool result;
+
        if (i915_request_signaled(rq))
                return true;
 
-       return i915_seqno_passed(hwsp_seqno(rq), rq->fence.seqno);
+       result = true;
+       rcu_read_lock(); /* the HWSP may be freed at runtime */
+       if (likely(!i915_request_signaled(rq)))
+               result = __i915_request_is_complete(rq);
+       rcu_read_unlock();
+
+       return result;
 }
 
 static inline void i915_request_mark_complete(struct i915_request *rq)
index 6fdddb266fb1b22333780a3604c5f46825eeb81b..4488e1c061b3d94f3876ca5464d4d096c3698414 100644 (file)
@@ -37,6 +37,7 @@ nouveau-y += dispnv50/wimmc37b.o
 nouveau-y += dispnv50/wndw.o
 nouveau-y += dispnv50/wndwc37e.o
 nouveau-y += dispnv50/wndwc57e.o
+nouveau-y += dispnv50/wndwc67e.o
 
 nouveau-y += dispnv50/base.o
 nouveau-y += dispnv50/base507c.o
index 27ea3f34706d4fbdc218ca04cdf339c28d99850b..abefc2343443bef6895f95a35ac08cde64d273ca 100644 (file)
@@ -42,6 +42,7 @@ nv50_core_new(struct nouveau_drm *drm, struct nv50_core **pcore)
                int version;
                int (*new)(struct nouveau_drm *, s32, struct nv50_core **);
        } cores[] = {
+               { GA102_DISP_CORE_CHANNEL_DMA, 0, corec57d_new },
                { TU102_DISP_CORE_CHANNEL_DMA, 0, corec57d_new },
                { GV100_DISP_CORE_CHANNEL_DMA, 0, corec37d_new },
                { GP102_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
index 121c24a18f111ccee5d5240d0824fde6777139f6..31d8b2e4791dd0fbcaf75009eb3df76b80c24f9b 100644 (file)
@@ -31,6 +31,7 @@ nv50_curs_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw)
                int version;
                int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **);
        } curses[] = {
+               { GA102_DISP_CURSOR, 0, cursc37a_new },
                { TU102_DISP_CURSOR, 0, cursc37a_new },
                { GV100_DISP_CURSOR, 0, cursc37a_new },
                { GK104_DISP_CURSOR, 0, curs907a_new },
index 33fff388dd83c2f259808e689117d532c582aebb..c6367035970eb5e6a14fcf4e4d3c531c28de91b7 100644 (file)
@@ -222,7 +222,7 @@ nv50_dmac_wait(struct nvif_push *push, u32 size)
 
 int
 nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
-                const s32 *oclass, u8 head, void *data, u32 size, u64 syncbuf,
+                const s32 *oclass, u8 head, void *data, u32 size, s64 syncbuf,
                 struct nv50_dmac *dmac)
 {
        struct nouveau_cli *cli = (void *)device->object.client;
@@ -271,7 +271,7 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
        if (ret)
                return ret;
 
-       if (!syncbuf)
+       if (syncbuf < 0)
                return 0;
 
        ret = nvif_object_ctor(&dmac->base.user, "kmsSyncCtxDma", NV50_DISP_HANDLE_SYNCBUF,
index 92bddc0836171b853dec40cb09447da4e15259f9..38dec11e7dda5577fdd11263b8e9b8b8b2a44309 100644 (file)
@@ -95,7 +95,7 @@ struct nv50_outp_atom {
 
 int nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
                     const s32 *oclass, u8 head, void *data, u32 size,
-                    u64 syncbuf, struct nv50_dmac *dmac);
+                    s64 syncbuf, struct nv50_dmac *dmac);
 void nv50_dmac_destroy(struct nv50_dmac *);
 
 /*
index a1ac153d5e9844fc35c76b292888ae8c17a752c9..566fbddfc8d7f47beffdb28ef5748a324fb555b6 100644 (file)
@@ -31,6 +31,7 @@ nv50_wimm_init(struct nouveau_drm *drm, struct nv50_wndw *wndw)
                int version;
                int (*init)(struct nouveau_drm *, s32, struct nv50_wndw *);
        } wimms[] = {
+               { GA102_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init },
                { TU102_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init },
                { GV100_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init },
                {}
index 685b7087132426933adf63d9fdddf55fdc439995..b390029c69ec130872a1dc9c6373eba82dea47d5 100644 (file)
@@ -76,7 +76,7 @@ wimmc37b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm,
        int ret;
 
        ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
-                              &oclass, 0, &args, sizeof(args), 0,
+                              &oclass, 0, &args, sizeof(args), -1,
                               &wndw->wimm);
        if (ret) {
                NV_ERROR(drm, "wimm%04x allocation failed: %d\n", oclass, ret);
index 0356474ad6f6afcd37e5c9540968d406fb5b41bc..ce451242f79eb2fc16403a5cf1d039b70ede0ced 100644 (file)
@@ -784,6 +784,7 @@ nv50_wndw_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
                int (*new)(struct nouveau_drm *, enum drm_plane_type,
                           int, s32, struct nv50_wndw **);
        } wndws[] = {
+               { GA102_DISP_WINDOW_CHANNEL_DMA, 0, wndwc67e_new },
                { TU102_DISP_WINDOW_CHANNEL_DMA, 0, wndwc57e_new },
                { GV100_DISP_WINDOW_CHANNEL_DMA, 0, wndwc37e_new },
                {}
index 3278e28800343c37fe7a88a29df1d7bcee6cab41..f4e0c508003441eea6b190d77f5caf6b3afa258e 100644 (file)
@@ -129,6 +129,14 @@ int wndwc37e_update(struct nv50_wndw *, u32 *);
 
 int wndwc57e_new(struct nouveau_drm *, enum drm_plane_type, int, s32,
                 struct nv50_wndw **);
+bool wndwc57e_ilut(struct nv50_wndw *, struct nv50_wndw_atom *, int);
+int wndwc57e_ilut_set(struct nv50_wndw *, struct nv50_wndw_atom *);
+int wndwc57e_ilut_clr(struct nv50_wndw *);
+int wndwc57e_csc_set(struct nv50_wndw *, struct nv50_wndw_atom *);
+int wndwc57e_csc_clr(struct nv50_wndw *);
+
+int wndwc67e_new(struct nouveau_drm *, enum drm_plane_type, int, s32,
+                struct nv50_wndw **);
 
 int nv50_wndw_new(struct nouveau_drm *, enum drm_plane_type, int index,
                  struct nv50_wndw **);
index 429be0bb022206678f4fd7d76e19cfeca18e916d..abdd3bb658b383e7fe4f28d315655dad31b93a13 100644 (file)
@@ -80,7 +80,7 @@ wndwc57e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
        return 0;
 }
 
-static int
+int
 wndwc57e_csc_clr(struct nv50_wndw *wndw)
 {
        struct nvif_push *push = wndw->wndw.push;
@@ -98,7 +98,7 @@ wndwc57e_csc_clr(struct nv50_wndw *wndw)
        return 0;
 }
 
-static int
+int
 wndwc57e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 {
        struct nvif_push *push = wndw->wndw.push;
@@ -111,7 +111,7 @@ wndwc57e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
        return 0;
 }
 
-static int
+int
 wndwc57e_ilut_clr(struct nv50_wndw *wndw)
 {
        struct nvif_push *push = wndw->wndw.push;
@@ -124,7 +124,7 @@ wndwc57e_ilut_clr(struct nv50_wndw *wndw)
        return 0;
 }
 
-static int
+int
 wndwc57e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 {
        struct nvif_push *push = wndw->wndw.push;
@@ -179,7 +179,7 @@ wndwc57e_ilut_load(struct drm_color_lut *in, int size, void __iomem *mem)
        writew(readw(mem - 4), mem + 4);
 }
 
-static bool
+bool
 wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
 {
        if (size = size ? size : 1024, size != 256 && size != 1024)
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc67e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc67e.c
new file mode 100644 (file)
index 0000000..7a370fa
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "wndw.h"
+#include "atom.h"
+
+#include <nvif/pushc37b.h>
+
+#include <nvhw/class/clc57e.h>
+
+static int
+wndwc67e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+       struct nvif_push *push = wndw->wndw.push;
+       int ret;
+
+       if ((ret = PUSH_WAIT(push, 17)))
+               return ret;
+
+       PUSH_MTHD(push, NVC57E, SET_PRESENT_CONTROL,
+                 NVVAL(NVC57E, SET_PRESENT_CONTROL, MIN_PRESENT_INTERVAL, asyw->image.interval) |
+                 NVVAL(NVC57E, SET_PRESENT_CONTROL, BEGIN_MODE, asyw->image.mode) |
+                 NVDEF(NVC57E, SET_PRESENT_CONTROL, TIMESTAMP_MODE, DISABLE));
+
+       PUSH_MTHD(push, NVC57E, SET_SIZE,
+                 NVVAL(NVC57E, SET_SIZE, WIDTH, asyw->image.w) |
+                 NVVAL(NVC57E, SET_SIZE, HEIGHT, asyw->image.h),
+
+                               SET_STORAGE,
+                 NVVAL(NVC57E, SET_STORAGE, BLOCK_HEIGHT, asyw->image.blockh),
+
+                               SET_PARAMS,
+                 NVVAL(NVC57E, SET_PARAMS, FORMAT, asyw->image.format) |
+                 NVDEF(NVC57E, SET_PARAMS, CLAMP_BEFORE_BLEND, DISABLE) |
+                 NVDEF(NVC57E, SET_PARAMS, SWAP_UV, DISABLE) |
+                 NVDEF(NVC57E, SET_PARAMS, FMT_ROUNDING_MODE, ROUND_TO_NEAREST),
+
+                               SET_PLANAR_STORAGE(0),
+                 NVVAL(NVC57E, SET_PLANAR_STORAGE, PITCH, asyw->image.blocks[0]) |
+                 NVVAL(NVC57E, SET_PLANAR_STORAGE, PITCH, asyw->image.pitch[0] >> 6));
+
+       PUSH_MTHD(push, NVC57E, SET_CONTEXT_DMA_ISO(0), asyw->image.handle, 1);
+       PUSH_MTHD(push, NVC57E, SET_OFFSET(0), asyw->image.offset[0] >> 8);
+
+       PUSH_MTHD(push, NVC57E, SET_POINT_IN(0),
+                 NVVAL(NVC57E, SET_POINT_IN, X, asyw->state.src_x >> 16) |
+                 NVVAL(NVC57E, SET_POINT_IN, Y, asyw->state.src_y >> 16));
+
+       PUSH_MTHD(push, NVC57E, SET_SIZE_IN,
+                 NVVAL(NVC57E, SET_SIZE_IN, WIDTH, asyw->state.src_w >> 16) |
+                 NVVAL(NVC57E, SET_SIZE_IN, HEIGHT, asyw->state.src_h >> 16));
+
+       PUSH_MTHD(push, NVC57E, SET_SIZE_OUT,
+                 NVVAL(NVC57E, SET_SIZE_OUT, WIDTH, asyw->state.crtc_w) |
+                 NVVAL(NVC57E, SET_SIZE_OUT, HEIGHT, asyw->state.crtc_h));
+       return 0;
+}
+
+static const struct nv50_wndw_func
+wndwc67e = {
+       .acquire = wndwc37e_acquire,
+       .release = wndwc37e_release,
+       .sema_set = wndwc37e_sema_set,
+       .sema_clr = wndwc37e_sema_clr,
+       .ntfy_set = wndwc37e_ntfy_set,
+       .ntfy_clr = wndwc37e_ntfy_clr,
+       .ntfy_reset = corec37d_ntfy_init,
+       .ntfy_wait_begun = base507c_ntfy_wait_begun,
+       .ilut = wndwc57e_ilut,
+       .ilut_identity = true,
+       .ilut_size = 1024,
+       .xlut_set = wndwc57e_ilut_set,
+       .xlut_clr = wndwc57e_ilut_clr,
+       .csc = base907c_csc,
+       .csc_set = wndwc57e_csc_set,
+       .csc_clr = wndwc57e_csc_clr,
+       .image_set = wndwc67e_image_set,
+       .image_clr = wndwc37e_image_clr,
+       .blend_set = wndwc37e_blend_set,
+       .update = wndwc37e_update,
+};
+
+int
+wndwc67e_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
+            s32 oclass, struct nv50_wndw **pwndw)
+{
+       return wndwc37e_new_(&wndwc67e, drm, type, index, oclass, BIT(index >> 1), pwndw);
+}
index cd9a2e687bb61ba96cfe347ef3b25cc9e8e78fb5..57d4f457a7d4ad03b4bd998a1ef1777923ebab83 100644 (file)
@@ -33,6 +33,7 @@ struct nv_device_info_v0 {
 #define NV_DEVICE_INFO_V0_PASCAL                                           0x0a
 #define NV_DEVICE_INFO_V0_VOLTA                                            0x0b
 #define NV_DEVICE_INFO_V0_TURING                                           0x0c
+#define NV_DEVICE_INFO_V0_AMPERE                                           0x0d
        __u8  family;
        __u8  pad06[2];
        __u64 ram_size;
index 2c79beb41126fa75ff55c2479afdba27db841320..ba2c28ea43d20f46b6aca9a2e4e2798a50de45d0 100644 (file)
@@ -88,6 +88,7 @@
 #define GP102_DISP                                    /* cl5070.h */ 0x00009870
 #define GV100_DISP                                    /* cl5070.h */ 0x0000c370
 #define TU102_DISP                                    /* cl5070.h */ 0x0000c570
+#define GA102_DISP                                    /* cl5070.h */ 0x0000c670
 
 #define GV100_DISP_CAPS                                              0x0000c373
 
 #define GK104_DISP_CURSOR                             /* cl507a.h */ 0x0000917a
 #define GV100_DISP_CURSOR                             /* cl507a.h */ 0x0000c37a
 #define TU102_DISP_CURSOR                             /* cl507a.h */ 0x0000c57a
+#define GA102_DISP_CURSOR                             /* cl507a.h */ 0x0000c67a
 
 #define NV50_DISP_OVERLAY                             /* cl507b.h */ 0x0000507b
 #define G82_DISP_OVERLAY                              /* cl507b.h */ 0x0000827b
 
 #define GV100_DISP_WINDOW_IMM_CHANNEL_DMA             /* clc37b.h */ 0x0000c37b
 #define TU102_DISP_WINDOW_IMM_CHANNEL_DMA             /* clc37b.h */ 0x0000c57b
+#define GA102_DISP_WINDOW_IMM_CHANNEL_DMA             /* clc37b.h */ 0x0000c67b
 
 #define NV50_DISP_BASE_CHANNEL_DMA                    /* cl507c.h */ 0x0000507c
 #define G82_DISP_BASE_CHANNEL_DMA                     /* cl507c.h */ 0x0000827c
 #define GP102_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000987d
 #define GV100_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000c37d
 #define TU102_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000c57d
+#define GA102_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000c67d
 
 #define NV50_DISP_OVERLAY_CHANNEL_DMA                 /* cl507e.h */ 0x0000507e
 #define G82_DISP_OVERLAY_CHANNEL_DMA                  /* cl507e.h */ 0x0000827e
 
 #define GV100_DISP_WINDOW_CHANNEL_DMA                 /* clc37e.h */ 0x0000c37e
 #define TU102_DISP_WINDOW_CHANNEL_DMA                 /* clc37e.h */ 0x0000c57e
+#define GA102_DISP_WINDOW_CHANNEL_DMA                 /* clc37e.h */ 0x0000c67e
 
 #define NV50_TESLA                                                   0x00005097
 #define G82_TESLA                                                    0x00008297
index 5c007ce62fc34e1a42f5d2be2d0da98106a76416..c920939a1467946c1c2281a1798d92dda5dc8623 100644 (file)
@@ -120,6 +120,7 @@ struct nvkm_device {
                GP100    = 0x130,
                GV100    = 0x140,
                TU100    = 0x160,
+               GA100    = 0x170,
        } card_type;
        u32 chipset;
        u8  chiprev;
index 5a96c942d912f0c68edc9227fd7eab1ef08ab503..0f6fa6631a197aaa7f26479e5bf24192678a0091 100644 (file)
@@ -37,4 +37,5 @@ int gp100_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
 int gp102_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
 int gv100_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
 int tu102_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
+int ga102_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
 #endif
index 1a39e52e09e36e7a92f5c104509c20f9cf17a7b0..50cc7c05eac49c64587bc3c90b24994e82505566 100644 (file)
@@ -32,4 +32,5 @@ int gm107_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
 int gm200_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
 int gv100_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
 int tu102_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int ga100_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
 #endif
index 34b56b10218a8f782ef0a581eabbbed9b3bf14ed..2ecd52aec1d121d050844e1e2e8b425c64c54aee 100644 (file)
@@ -86,6 +86,8 @@ int gp100_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
 int gp102_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
 int gp10b_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
 int gv100_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
+int ga100_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
+int ga102_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
 
 #include <subdev/bios.h>
 #include <subdev/bios/ramcfg.h>
index eaacf8d80527cfc080ab34fccd496f16090bc27e..cdcce5ece6ff5973426f791cb4f02fc27537a904 100644 (file)
@@ -37,4 +37,5 @@ int nv50_gpio_new(struct nvkm_device *, int, struct nvkm_gpio **);
 int g94_gpio_new(struct nvkm_device *, int, struct nvkm_gpio **);
 int gf119_gpio_new(struct nvkm_device *, int, struct nvkm_gpio **);
 int gk104_gpio_new(struct nvkm_device *, int, struct nvkm_gpio **);
+int ga102_gpio_new(struct nvkm_device *, int, struct nvkm_gpio **);
 #endif
index 81b977319640ae9d7331ea07c78c1e89a313edd6..640f649ce497e4a9c93f8fc5ad1940f4ba205125 100644 (file)
@@ -92,6 +92,7 @@ int g94_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
 int gf117_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
 int gf119_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
 int gk104_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
+int gk110_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
 int gm200_i2c_new(struct nvkm_device *, int, struct nvkm_i2c **);
 
 static inline int
index 6641fe4c252c62bf8d2c4c42d97e2e64a984489c..e45ca458396709be315edb7cf88c36604db96dc4 100644 (file)
@@ -32,4 +32,5 @@ int gk20a_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int gp100_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int gp10b_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int tu102_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
+int ga100_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 #endif
index c7a94c94dbf378289b6cbcbd76b51f8b47d18497..72f35a2babcb20eef0450df7f25f4ee71dc2d9f0 100644 (file)
@@ -256,6 +256,7 @@ nouveau_backlight_init(struct drm_connector *connector)
        case NV_DEVICE_INFO_V0_PASCAL:
        case NV_DEVICE_INFO_V0_VOLTA:
        case NV_DEVICE_INFO_V0_TURING:
+       case NV_DEVICE_INFO_V0_AMPERE: //XXX: not confirmed
                ret = nv50_backlight_init(nv_encoder, &props, &ops);
                break;
        default:
index 8d0d30e08f57eff1842fc7fe1d98526ef14a392a..529cb60d5efb020faf0e4a81b45b5cd133fa5a6f 100644 (file)
@@ -35,6 +35,7 @@ nvif_disp_ctor(struct nvif_device *device, const char *name, s32 oclass,
               struct nvif_disp *disp)
 {
        static const struct nvif_mclass disps[] = {
+               { GA102_DISP, -1 },
                { TU102_DISP, -1 },
                { GV100_DISP, -1 },
                { GP102_DISP, -1 },
index 7851bec5f0e5feccd8b2be5f1fbcb2b6180a21bf..cdcc851e06f9b5d8e82341048f8e77e53f07363c 100644 (file)
@@ -1815,7 +1815,7 @@ nvf0_chipset = {
        .fb = gk110_fb_new,
        .fuse = gf100_fuse_new,
        .gpio = gk104_gpio_new,
-       .i2c = gk104_i2c_new,
+       .i2c = gk110_i2c_new,
        .ibus = gk104_ibus_new,
        .iccsense = gf100_iccsense_new,
        .imem = nv50_instmem_new,
@@ -1853,7 +1853,7 @@ nvf1_chipset = {
        .fb = gk110_fb_new,
        .fuse = gf100_fuse_new,
        .gpio = gk104_gpio_new,
-       .i2c = gk104_i2c_new,
+       .i2c = gk110_i2c_new,
        .ibus = gk104_ibus_new,
        .iccsense = gf100_iccsense_new,
        .imem = nv50_instmem_new,
@@ -1891,7 +1891,7 @@ nv106_chipset = {
        .fb = gk110_fb_new,
        .fuse = gf100_fuse_new,
        .gpio = gk104_gpio_new,
-       .i2c = gk104_i2c_new,
+       .i2c = gk110_i2c_new,
        .ibus = gk104_ibus_new,
        .iccsense = gf100_iccsense_new,
        .imem = nv50_instmem_new,
@@ -1929,7 +1929,7 @@ nv108_chipset = {
        .fb = gk110_fb_new,
        .fuse = gf100_fuse_new,
        .gpio = gk104_gpio_new,
-       .i2c = gk104_i2c_new,
+       .i2c = gk110_i2c_new,
        .ibus = gk104_ibus_new,
        .iccsense = gf100_iccsense_new,
        .imem = nv50_instmem_new,
@@ -1967,7 +1967,7 @@ nv117_chipset = {
        .fb = gm107_fb_new,
        .fuse = gm107_fuse_new,
        .gpio = gk104_gpio_new,
-       .i2c = gk104_i2c_new,
+       .i2c = gk110_i2c_new,
        .ibus = gk104_ibus_new,
        .iccsense = gf100_iccsense_new,
        .imem = nv50_instmem_new,
@@ -2003,7 +2003,7 @@ nv118_chipset = {
        .fb = gm107_fb_new,
        .fuse = gm107_fuse_new,
        .gpio = gk104_gpio_new,
-       .i2c = gk104_i2c_new,
+       .i2c = gk110_i2c_new,
        .ibus = gk104_ibus_new,
        .iccsense = gf100_iccsense_new,
        .imem = nv50_instmem_new,
@@ -2652,6 +2652,61 @@ nv168_chipset = {
        .sec2 = tu102_sec2_new,
 };
 
+static const struct nvkm_device_chip
+nv170_chipset = {
+       .name = "GA100",
+       .bar = tu102_bar_new,
+       .bios = nvkm_bios_new,
+       .devinit = ga100_devinit_new,
+       .fb = ga100_fb_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gm200_i2c_new,
+       .ibus = gm200_ibus_new,
+       .imem = nv50_instmem_new,
+       .mc = ga100_mc_new,
+       .mmu = tu102_mmu_new,
+       .pci = gp100_pci_new,
+       .timer = gk20a_timer_new,
+};
+
+static const struct nvkm_device_chip
+nv172_chipset = {
+       .name = "GA102",
+       .bar = tu102_bar_new,
+       .bios = nvkm_bios_new,
+       .devinit = ga100_devinit_new,
+       .fb = ga102_fb_new,
+       .gpio = ga102_gpio_new,
+       .i2c = gm200_i2c_new,
+       .ibus = gm200_ibus_new,
+       .imem = nv50_instmem_new,
+       .mc = ga100_mc_new,
+       .mmu = tu102_mmu_new,
+       .pci = gp100_pci_new,
+       .timer = gk20a_timer_new,
+       .disp = ga102_disp_new,
+       .dma = gv100_dma_new,
+};
+
+static const struct nvkm_device_chip
+nv174_chipset = {
+       .name = "GA104",
+       .bar = tu102_bar_new,
+       .bios = nvkm_bios_new,
+       .devinit = ga100_devinit_new,
+       .fb = ga102_fb_new,
+       .gpio = ga102_gpio_new,
+       .i2c = gm200_i2c_new,
+       .ibus = gm200_ibus_new,
+       .imem = nv50_instmem_new,
+       .mc = ga100_mc_new,
+       .mmu = tu102_mmu_new,
+       .pci = gp100_pci_new,
+       .timer = gk20a_timer_new,
+       .disp = ga102_disp_new,
+       .dma = gv100_dma_new,
+};
+
 static int
 nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size,
                       struct nvkm_notify *notify)
@@ -3063,6 +3118,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                        case 0x130: device->card_type = GP100; break;
                        case 0x140: device->card_type = GV100; break;
                        case 0x160: device->card_type = TU100; break;
+                       case 0x170: device->card_type = GA100; break;
                        default:
                                break;
                        }
@@ -3160,10 +3216,23 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                case 0x166: device->chip = &nv166_chipset; break;
                case 0x167: device->chip = &nv167_chipset; break;
                case 0x168: device->chip = &nv168_chipset; break;
+               case 0x172: device->chip = &nv172_chipset; break;
+               case 0x174: device->chip = &nv174_chipset; break;
                default:
-                       nvdev_error(device, "unknown chipset (%08x)\n", boot0);
-                       ret = -ENODEV;
-                       goto done;
+                       if (nvkm_boolopt(device->cfgopt, "NvEnableUnsupportedChipsets", false)) {
+                               switch (device->chipset) {
+                               case 0x170: device->chip = &nv170_chipset; break;
+                               default:
+                                       break;
+                               }
+                       }
+
+                       if (!device->chip) {
+                               nvdev_error(device, "unknown chipset (%08x)\n", boot0);
+                               ret = -ENODEV;
+                               goto done;
+                       }
+                       break;
                }
 
                nvdev_info(device, "NVIDIA %s (%08x)\n",
index 03c6d9aef075cca0b13770d25d941602bb7ef49f..1478947987860d664a89247afaecd8e7d46c9dc7 100644 (file)
@@ -176,6 +176,7 @@ nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size)
        case GP100: args->v0.family = NV_DEVICE_INFO_V0_PASCAL; break;
        case GV100: args->v0.family = NV_DEVICE_INFO_V0_VOLTA; break;
        case TU100: args->v0.family = NV_DEVICE_INFO_V0_TURING; break;
+       case GA100: args->v0.family = NV_DEVICE_INFO_V0_AMPERE; break;
        default:
                args->v0.family = 0;
                break;
index cf075311cdd27ae189b5c00cedc589f14b93f44e..b03f043efe261542c267a0a7a3ead68858c36f82 100644 (file)
@@ -17,6 +17,7 @@ nvkm-y += nvkm/engine/disp/gp100.o
 nvkm-y += nvkm/engine/disp/gp102.o
 nvkm-y += nvkm/engine/disp/gv100.o
 nvkm-y += nvkm/engine/disp/tu102.o
+nvkm-y += nvkm/engine/disp/ga102.o
 nvkm-y += nvkm/engine/disp/vga.o
 
 nvkm-y += nvkm/engine/disp/head.o
@@ -42,6 +43,7 @@ nvkm-y += nvkm/engine/disp/sorgm200.o
 nvkm-y += nvkm/engine/disp/sorgp100.o
 nvkm-y += nvkm/engine/disp/sorgv100.o
 nvkm-y += nvkm/engine/disp/sortu102.o
+nvkm-y += nvkm/engine/disp/sorga102.o
 
 nvkm-y += nvkm/engine/disp/outp.o
 nvkm-y += nvkm/engine/disp/dp.o
@@ -75,6 +77,7 @@ nvkm-y += nvkm/engine/disp/rootgp100.o
 nvkm-y += nvkm/engine/disp/rootgp102.o
 nvkm-y += nvkm/engine/disp/rootgv100.o
 nvkm-y += nvkm/engine/disp/roottu102.o
+nvkm-y += nvkm/engine/disp/rootga102.o
 
 nvkm-y += nvkm/engine/disp/capsgv100.o
 
index 3800aeb507d0167d4e7bb41210c6fb5fd925cdc2..55fbfe28c6dc1a50da06bc117a95cc91b303b4ac 100644 (file)
 
 #include <nvif/event.h>
 
+/* IED scripts are no longer used by UEFI/RM from Ampere, but have been updated for
+ * the x86 option ROM.  However, the relevant VBIOS table versions weren't modified,
+ * so we're unable to detect this in a nice way.
+ */
+#define AMPERE_IED_HACK(disp) ((disp)->engine.subdev.device->card_type >= GA100)
+
 struct lt_state {
        struct nvkm_dp *dp;
        u8  stat[6];
@@ -238,6 +244,19 @@ nvkm_dp_train_links(struct nvkm_dp *dp)
                dp->dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED;
        lt.pc2 = dp->dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED;
 
+       if (AMPERE_IED_HACK(disp) && (lnkcmp = lt.dp->info.script[0])) {
+               /* Execute BeforeLinkTraining script from DP Info table. */
+               while (ior->dp.bw < nvbios_rd08(bios, lnkcmp))
+                       lnkcmp += 3;
+               lnkcmp = nvbios_rd16(bios, lnkcmp + 1);
+
+               nvbios_init(&dp->outp.disp->engine.subdev, lnkcmp,
+                       init.outp = &dp->outp.info;
+                       init.or   = ior->id;
+                       init.link = ior->asy.link;
+               );
+       }
+
        /* Set desired link configuration on the source. */
        if ((lnkcmp = lt.dp->info.lnkcmp)) {
                if (dp->version < 0x30) {
@@ -316,12 +335,14 @@ nvkm_dp_train_init(struct nvkm_dp *dp)
                );
        }
 
-       /* Execute BeforeLinkTraining script from DP Info table. */
-       nvbios_init(&dp->outp.disp->engine.subdev, dp->info.script[0],
-               init.outp = &dp->outp.info;
-               init.or   = dp->outp.ior->id;
-               init.link = dp->outp.ior->asy.link;
-       );
+       if (!AMPERE_IED_HACK(dp->outp.disp)) {
+               /* Execute BeforeLinkTraining script from DP Info table. */
+               nvbios_init(&dp->outp.disp->engine.subdev, dp->info.script[0],
+                       init.outp = &dp->outp.info;
+                       init.or   = dp->outp.ior->id;
+                       init.link = dp->outp.ior->asy.link;
+               );
+       }
 }
 
 static const struct dp_rates {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c
new file mode 100644 (file)
index 0000000..aa2e564
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "nv50.h"
+#include "head.h"
+#include "ior.h"
+#include "channv50.h"
+#include "rootnv50.h"
+
+static const struct nv50_disp_func
+ga102_disp = {
+       .init = tu102_disp_init,
+       .fini = gv100_disp_fini,
+       .intr = gv100_disp_intr,
+       .uevent = &gv100_disp_chan_uevent,
+       .super = gv100_disp_super,
+       .root = &ga102_disp_root_oclass,
+       .wndw = { .cnt = gv100_disp_wndw_cnt },
+       .head = { .cnt = gv100_head_cnt, .new = gv100_head_new },
+       .sor = { .cnt = gv100_sor_cnt, .new = ga102_sor_new },
+       .ramht_size = 0x2000,
+};
+
+int
+ga102_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
+{
+       return nv50_disp_new_(&ga102_disp, device, index, pdisp);
+}
index 09f3038eff26fba9b411681dd66db46cf5f5273f..9f0bb7c6b0100f07d7d4b1dd36a94b5db91b072e 100644 (file)
@@ -150,6 +150,8 @@ void gv100_sor_dp_audio(struct nvkm_ior *, int, bool);
 void gv100_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32);
 void gv100_sor_dp_watermark(struct nvkm_ior *, int, u8);
 
+void tu102_sor_dp_vcpi(struct nvkm_ior *, int, u8, u8, u16, u16);
+
 void g84_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
 void gt215_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
 void gf119_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
@@ -207,4 +209,6 @@ int gv100_sor_cnt(struct nvkm_disp *, unsigned long *);
 int gv100_sor_new(struct nvkm_disp *, int);
 
 int tu102_sor_new(struct nvkm_disp *, int);
+
+int ga102_sor_new(struct nvkm_disp *, int);
 #endif
index a677161c7f3a6c77096a0dedc155e63b05a87cb1..db31b37752a270b163b9b1ea8366546bef2470fa 100644 (file)
@@ -86,6 +86,8 @@ void gv100_disp_intr(struct nv50_disp *);
 void gv100_disp_super(struct work_struct *);
 int gv100_disp_wndw_cnt(struct nvkm_disp *, unsigned long *);
 
+int tu102_disp_init(struct nv50_disp *);
+
 void nv50_disp_dptmds_war_2(struct nv50_disp *, struct dcb_output *);
 void nv50_disp_dptmds_war_3(struct nv50_disp *, struct dcb_output *);
 void nv50_disp_update_sppll1(struct nv50_disp *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootga102.c
new file mode 100644 (file)
index 0000000..9af07c3
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "rootnv50.h"
+#include "channv50.h"
+
+#include <nvif/class.h>
+
+static const struct nv50_disp_root_func
+ga102_disp_root = {
+       .user = {
+               {{-1,-1,GV100_DISP_CAPS                }, gv100_disp_caps_new },
+               {{0,0,GA102_DISP_CURSOR                }, gv100_disp_curs_new },
+               {{0,0,GA102_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new },
+               {{0,0,GA102_DISP_CORE_CHANNEL_DMA      }, gv100_disp_core_new },
+               {{0,0,GA102_DISP_WINDOW_CHANNEL_DMA    }, gv100_disp_wndw_new },
+               {}
+       },
+};
+
+static int
+ga102_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass,
+                   void *data, u32 size, struct nvkm_object **pobject)
+{
+       return nv50_disp_root_new_(&ga102_disp_root, disp, oclass, data, size, pobject);
+}
+
+const struct nvkm_disp_oclass
+ga102_disp_root_oclass = {
+       .base.oclass = GA102_DISP,
+       .base.minver = -1,
+       .base.maxver = -1,
+       .ctor = ga102_disp_root_new,
+};
index 7070f5408d92bf617746b5e7baa76b45eff8f825..27bb170d02930441d99b1f09b49335b74f44e482 100644 (file)
@@ -41,4 +41,5 @@ extern const struct nvkm_disp_oclass gp100_disp_root_oclass;
 extern const struct nvkm_disp_oclass gp102_disp_root_oclass;
 extern const struct nvkm_disp_oclass gv100_disp_root_oclass;
 extern const struct nvkm_disp_oclass tu102_disp_root_oclass;
+extern const struct nvkm_disp_oclass ga102_disp_root_oclass;
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c
new file mode 100644 (file)
index 0000000..033827d
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "ior.h"
+
+#include <subdev/timer.h>
+
+static int
+ga102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux)
+{
+       struct nvkm_device *device = sor->disp->engine.subdev.device;
+       const u32 soff = nv50_ior_base(sor);
+       const u32 loff = nv50_sor_link(sor);
+       u32 dpctrl = 0x00000000;
+       u32 clksor = 0x00000000;
+
+       switch (sor->dp.bw) {
+       case 0x06: clksor |= 0x00000000; break;
+       case 0x0a: clksor |= 0x00040000; break;
+       case 0x14: clksor |= 0x00080000; break;
+       case 0x1e: clksor |= 0x000c0000; break;
+       default:
+               WARN_ON(1);
+               return -EINVAL;
+       }
+
+       dpctrl |= ((1 << sor->dp.nr) - 1) << 16;
+       if (sor->dp.mst)
+               dpctrl |= 0x40000000;
+       if (sor->dp.ef)
+               dpctrl |= 0x00004000;
+
+       nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor);
+
+       /*XXX*/
+       nvkm_msec(device, 40, NVKM_DELAY);
+       nvkm_mask(device, 0x612300 + soff, 0x00030000, 0x00010000);
+       nvkm_mask(device, 0x61c10c + loff, 0x00000003, 0x00000001);
+
+       nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl);
+       return 0;
+}
+
+static void
+ga102_sor_clock(struct nvkm_ior *sor)
+{
+       struct nvkm_device *device = sor->disp->engine.subdev.device;
+       u32 div2 = 0;
+       if (sor->asy.proto == TMDS) {
+               if (sor->tmds.high_speed)
+                       div2 = 1;
+       }
+       nvkm_wr32(device, 0x00ec08 + (sor->id * 0x10), 0x00000000);
+       nvkm_wr32(device, 0x00ec04 + (sor->id * 0x10), div2);
+}
+
+static const struct nvkm_ior_func
+ga102_sor_hda = {
+       .route = {
+               .get = gm200_sor_route_get,
+               .set = gm200_sor_route_set,
+       },
+       .state = gv100_sor_state,
+       .power = nv50_sor_power,
+       .clock = ga102_sor_clock,
+       .hdmi = {
+               .ctrl = gv100_hdmi_ctrl,
+               .scdc = gm200_hdmi_scdc,
+       },
+       .dp = {
+               .lanes = { 0, 1, 2, 3 },
+               .links = ga102_sor_dp_links,
+               .power = g94_sor_dp_power,
+               .pattern = gm107_sor_dp_pattern,
+               .drive = gm200_sor_dp_drive,
+               .vcpi = tu102_sor_dp_vcpi,
+               .audio = gv100_sor_dp_audio,
+               .audio_sym = gv100_sor_dp_audio_sym,
+               .watermark = gv100_sor_dp_watermark,
+       },
+       .hda = {
+               .hpd = gf119_hda_hpd,
+               .eld = gf119_hda_eld,
+               .device_entry = gv100_hda_device_entry,
+       },
+};
+
+static const struct nvkm_ior_func
+ga102_sor = {
+       .route = {
+               .get = gm200_sor_route_get,
+               .set = gm200_sor_route_set,
+       },
+       .state = gv100_sor_state,
+       .power = nv50_sor_power,
+       .clock = ga102_sor_clock,
+       .hdmi = {
+               .ctrl = gv100_hdmi_ctrl,
+               .scdc = gm200_hdmi_scdc,
+       },
+       .dp = {
+               .lanes = { 0, 1, 2, 3 },
+               .links = ga102_sor_dp_links,
+               .power = g94_sor_dp_power,
+               .pattern = gm107_sor_dp_pattern,
+               .drive = gm200_sor_dp_drive,
+               .vcpi = tu102_sor_dp_vcpi,
+               .audio = gv100_sor_dp_audio,
+               .audio_sym = gv100_sor_dp_audio_sym,
+               .watermark = gv100_sor_dp_watermark,
+       },
+};
+
+int
+ga102_sor_new(struct nvkm_disp *disp, int id)
+{
+       struct nvkm_device *device = disp->engine.subdev.device;
+       u32 hda = nvkm_rd32(device, 0x08a15c);
+       if (hda & BIT(id))
+               return nvkm_ior_new_(&ga102_sor_hda, disp, SOR, id);
+       return nvkm_ior_new_(&ga102_sor, disp, SOR, id);
+}
index 59865a934c4b9d4e3e0c85ab4f47a0bd86b2073b..0cf9e8752d2588c83b146d3534907a7c7b7c10b6 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <subdev/timer.h>
 
-static void
+void
 tu102_sor_dp_vcpi(struct nvkm_ior *sor, int head,
                  u8 slot, u8 slot_nr, u16 pbn, u16 aligned)
 {
index 883ae4151ff8887074e63fec782a211b07a5fa94..4c85d1d4fbd4265cabd179923519412766473114 100644 (file)
@@ -28,7 +28,7 @@
 #include <core/gpuobj.h>
 #include <subdev/timer.h>
 
-static int
+int
 tu102_disp_init(struct nv50_disp *disp)
 {
        struct nvkm_device *device = disp->base.engine.subdev.device;
index 7deb81b6dbac6bc5a440da281eca94b51b632f83..4b571cc6bc70f4cacb934cd731aed683ca8ec0f0 100644 (file)
@@ -75,7 +75,7 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
        nvkm_debug(subdev, "%08x: type %02x, %d bytes\n",
                   image.base, image.type, image.size);
 
-       if (!shadow_fetch(bios, mthd, image.size)) {
+       if (!shadow_fetch(bios, mthd, image.base + image.size)) {
                nvkm_debug(subdev, "%08x: fetch failed\n", image.base);
                return 0;
        }
index 3634cd0630b81ce4d697261ee0100f1ce4ec5b39..023ddc7c5399a40ffbb19da8fb14cf53a4f4871a 100644 (file)
@@ -64,6 +64,9 @@ pramin_init(struct nvkm_bios *bios, const char *name)
                return NULL;
 
        /* we can't get the bios image pointer without PDISP */
+       if (device->card_type >= GA100)
+               addr = device->chipset == 0x170; /*XXX: find the fuse reg for this */
+       else
        if (device->card_type >= GM100)
                addr = nvkm_rd32(device, 0x021c04);
        else
index b3429371ed824b7bd4b3043b0118accbcdf48655..d1abb64841dac7ad969e4ab1ff688c03c5060095 100644 (file)
@@ -15,3 +15,4 @@ nvkm-y += nvkm/subdev/devinit/gm107.o
 nvkm-y += nvkm/subdev/devinit/gm200.o
 nvkm-y += nvkm/subdev/devinit/gv100.o
 nvkm-y += nvkm/subdev/devinit/tu102.o
+nvkm-y += nvkm/subdev/devinit/ga100.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/ga100.c
new file mode 100644 (file)
index 0000000..636a921
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "nv50.h"
+
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+#include <subdev/clk/pll.h>
+
+static int
+ga100_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq)
+{
+       struct nvkm_subdev *subdev = &init->subdev;
+       struct nvkm_device *device = subdev->device;
+       struct nvbios_pll info;
+       int head = type - PLL_VPLL0;
+       int N, fN, M, P;
+       int ret;
+
+       ret = nvbios_pll_parse(device->bios, type, &info);
+       if (ret)
+               return ret;
+
+       ret = gt215_pll_calc(subdev, &info, freq, &N, &fN, &M, &P);
+       if (ret < 0)
+               return ret;
+
+       switch (info.type) {
+       case PLL_VPLL0:
+       case PLL_VPLL1:
+       case PLL_VPLL2:
+       case PLL_VPLL3:
+               nvkm_wr32(device, 0x00ef00 + (head * 0x40), 0x02080004);
+               nvkm_wr32(device, 0x00ef18 + (head * 0x40), (N << 16) | fN);
+               nvkm_wr32(device, 0x00ef04 + (head * 0x40), (P << 16) | M);
+               nvkm_wr32(device, 0x00e9c0 + (head * 0x04), 0x00000001);
+               break;
+       default:
+               nvkm_warn(subdev, "%08x/%dKhz unimplemented\n", type, freq);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static const struct nvkm_devinit_func
+ga100_devinit = {
+       .init = nv50_devinit_init,
+       .post = tu102_devinit_post,
+       .pll_set = ga100_devinit_pll_set,
+};
+
+int
+ga100_devinit_new(struct nvkm_device *device, int index, struct nvkm_devinit **pinit)
+{
+       return nv50_devinit_new_(&ga100_devinit, device, index, pinit);
+}
index 94723352137a7f9730f9a87ead7dfbafb16a9ca9..05961e624264754078e6bc48bc669db3f978c54f 100644 (file)
@@ -19,4 +19,5 @@ void nvkm_devinit_ctor(const struct nvkm_devinit_func *, struct nvkm_device *,
                       int index, struct nvkm_devinit *);
 
 int nv04_devinit_post(struct nvkm_devinit *, bool);
+int tu102_devinit_post(struct nvkm_devinit *, bool);
 #endif
index 397670e72fff936a4e7d1812490198996e318093..9a469bf482f2f5bb13b270c625d9fc37b476df2c 100644 (file)
@@ -65,7 +65,7 @@ tu102_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq)
        return ret;
 }
 
-static int
+int
 tu102_devinit_post(struct nvkm_devinit *base, bool post)
 {
        struct nv50_devinit *init = nv50_devinit(base);
index 43a42159a3d00e5fe432f997ba92565a612ec2f2..5d0bab8ecb433d60dd28306048f4f7ca656ea483 100644 (file)
@@ -32,6 +32,8 @@ nvkm-y += nvkm/subdev/fb/gp100.o
 nvkm-y += nvkm/subdev/fb/gp102.o
 nvkm-y += nvkm/subdev/fb/gp10b.o
 nvkm-y += nvkm/subdev/fb/gv100.o
+nvkm-y += nvkm/subdev/fb/ga100.o
+nvkm-y += nvkm/subdev/fb/ga102.o
 
 nvkm-y += nvkm/subdev/fb/ram.o
 nvkm-y += nvkm/subdev/fb/ramnv04.o
@@ -52,6 +54,7 @@ nvkm-y += nvkm/subdev/fb/ramgk104.o
 nvkm-y += nvkm/subdev/fb/ramgm107.o
 nvkm-y += nvkm/subdev/fb/ramgm200.o
 nvkm-y += nvkm/subdev/fb/ramgp100.o
+nvkm-y += nvkm/subdev/fb/ramga102.o
 nvkm-y += nvkm/subdev/fb/sddr2.o
 nvkm-y += nvkm/subdev/fb/sddr3.o
 nvkm-y += nvkm/subdev/fb/gddr3.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c
new file mode 100644 (file)
index 0000000..bf82686
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "gf100.h"
+#include "ram.h"
+
+static const struct nvkm_fb_func
+ga100_fb = {
+       .dtor = gf100_fb_dtor,
+       .oneinit = gf100_fb_oneinit,
+       .init = gp100_fb_init,
+       .init_page = gv100_fb_init_page,
+       .init_unkn = gp100_fb_init_unkn,
+       .ram_new = gp100_ram_new,
+       .default_bigpage = 16,
+};
+
+int
+ga100_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
+{
+       return gp102_fb_new_(&ga100_fb, device, index, pfb);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c
new file mode 100644 (file)
index 0000000..bcecf84
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "gf100.h"
+#include "ram.h"
+
+static const struct nvkm_fb_func
+ga102_fb = {
+       .dtor = gf100_fb_dtor,
+       .oneinit = gf100_fb_oneinit,
+       .init = gp100_fb_init,
+       .init_page = gv100_fb_init_page,
+       .init_unkn = gp100_fb_init_unkn,
+       .ram_new = ga102_ram_new,
+       .default_bigpage = 16,
+};
+
+int
+ga102_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
+{
+       return gp102_fb_new_(&ga102_fb, device, index, pfb);
+}
index 10ff5d053f7ea4e0f0645028906da0d6acc2a031..feda86a5fba8592000ac2657a815b72203cbaf91 100644 (file)
@@ -22,7 +22,7 @@
 #include "gf100.h"
 #include "ram.h"
 
-static int
+int
 gv100_fb_init_page(struct nvkm_fb *fb)
 {
        return (fb->page == 16) ? 0 : -EINVAL;
index 5be9c563350d7b684e4bdb3a4ca5f90805d09d28..66932ac10d15c68b65e80d982a90e54873e3d393 100644 (file)
@@ -82,4 +82,6 @@ int gp102_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *, int,
                  struct nvkm_fb **);
 bool gp102_fb_vpr_scrub_required(struct nvkm_fb *);
 int gp102_fb_vpr_scrub(struct nvkm_fb *);
+
+int gv100_fb_init_page(struct nvkm_fb *);
 #endif
index d723a9b4e3c47006903c362b60f18da649b775b4..ea7d66f3dd825dba1f4eb6162e9a66e163d1677a 100644 (file)
@@ -70,4 +70,5 @@ int gk104_ram_new(struct nvkm_fb *, struct nvkm_ram **);
 int gm107_ram_new(struct nvkm_fb *, struct nvkm_ram **);
 int gm200_ram_new(struct nvkm_fb *, struct nvkm_ram **);
 int gp100_ram_new(struct nvkm_fb *, struct nvkm_ram **);
+int ga102_ram_new(struct nvkm_fb *, struct nvkm_ram **);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramga102.c
new file mode 100644 (file)
index 0000000..298c136
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "ram.h"
+
+#include <subdev/bios.h>
+#include <subdev/bios/init.h>
+#include <subdev/bios/rammap.h>
+
+static const struct nvkm_ram_func
+ga102_ram = {
+};
+
+int
+ga102_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
+{
+       struct nvkm_device *device = fb->subdev.device;
+       enum nvkm_ram_type type = nvkm_fb_bios_memtype(device->bios);
+       u32 size = nvkm_rd32(device, 0x1183a4);
+
+       return nvkm_ram_new_(&ga102_ram, fb, type, (u64)size << 20, pram);
+}
index b2ad5922a1c2dedb83d140a2ae2f561a08932850..efbbaa080de5172c1ebd02a49182e77337d0a240 100644 (file)
@@ -5,3 +5,4 @@ nvkm-y += nvkm/subdev/gpio/nv50.o
 nvkm-y += nvkm/subdev/gpio/g94.o
 nvkm-y += nvkm/subdev/gpio/gf119.o
 nvkm-y += nvkm/subdev/gpio/gk104.o
+nvkm-y += nvkm/subdev/gpio/ga102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/ga102.c
new file mode 100644 (file)
index 0000000..62c791b
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "priv.h"
+
+static void
+ga102_gpio_reset(struct nvkm_gpio *gpio, u8 match)
+{
+       struct nvkm_device *device = gpio->subdev.device;
+       struct nvkm_bios *bios = device->bios;
+       u8 ver, len;
+       u16 entry;
+       int ent = -1;
+
+       while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) {
+               u32 data = nvbios_rd32(bios, entry);
+               u8  line =   (data & 0x0000003f);
+               u8  defs = !!(data & 0x00000080);
+               u8  func =   (data & 0x0000ff00) >> 8;
+               u8  unk0 =   (data & 0x00ff0000) >> 16;
+               u8  unk1 =   (data & 0x1f000000) >> 24;
+
+               if ( func  == DCB_GPIO_UNUSED ||
+                   (match != DCB_GPIO_UNUSED && match != func))
+                       continue;
+
+               nvkm_gpio_set(gpio, 0, func, line, defs);
+
+               nvkm_mask(device, 0x021200 + (line * 4), 0xff, unk0);
+               if (unk1--)
+                       nvkm_mask(device, 0x00d740 + (unk1 * 4), 0xff, line);
+       }
+}
+
+static int
+ga102_gpio_drive(struct nvkm_gpio *gpio, int line, int dir, int out)
+{
+       struct nvkm_device *device = gpio->subdev.device;
+       u32 data = ((dir ^ 1) << 13) | (out << 12);
+       nvkm_mask(device, 0x021200 + (line * 4), 0x00003000, data);
+       nvkm_mask(device, 0x00d604, 0x00000001, 0x00000001); /* update? */
+       return 0;
+}
+
+static int
+ga102_gpio_sense(struct nvkm_gpio *gpio, int line)
+{
+       struct nvkm_device *device = gpio->subdev.device;
+       return !!(nvkm_rd32(device, 0x021200 + (line * 4)) & 0x00004000);
+}
+
+static void
+ga102_gpio_intr_stat(struct nvkm_gpio *gpio, u32 *hi, u32 *lo)
+{
+       struct nvkm_device *device = gpio->subdev.device;
+       u32 intr0 = nvkm_rd32(device, 0x021640);
+       u32 intr1 = nvkm_rd32(device, 0x02164c);
+       u32 stat0 = nvkm_rd32(device, 0x021648) & intr0;
+       u32 stat1 = nvkm_rd32(device, 0x021654) & intr1;
+       *lo = (stat1 & 0xffff0000) | (stat0 >> 16);
+       *hi = (stat1 << 16) | (stat0 & 0x0000ffff);
+       nvkm_wr32(device, 0x021640, intr0);
+       nvkm_wr32(device, 0x02164c, intr1);
+}
+
+static void
+ga102_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data)
+{
+       struct nvkm_device *device = gpio->subdev.device;
+       u32 inte0 = nvkm_rd32(device, 0x021648);
+       u32 inte1 = nvkm_rd32(device, 0x021654);
+       if (type & NVKM_GPIO_LO)
+               inte0 = (inte0 & ~(mask << 16)) | (data << 16);
+       if (type & NVKM_GPIO_HI)
+               inte0 = (inte0 & ~(mask & 0xffff)) | (data & 0xffff);
+       mask >>= 16;
+       data >>= 16;
+       if (type & NVKM_GPIO_LO)
+               inte1 = (inte1 & ~(mask << 16)) | (data << 16);
+       if (type & NVKM_GPIO_HI)
+               inte1 = (inte1 & ~mask) | data;
+       nvkm_wr32(device, 0x021648, inte0);
+       nvkm_wr32(device, 0x021654, inte1);
+}
+
+static const struct nvkm_gpio_func
+ga102_gpio = {
+       .lines = 32,
+       .intr_stat = ga102_gpio_intr_stat,
+       .intr_mask = ga102_gpio_intr_mask,
+       .drive = ga102_gpio_drive,
+       .sense = ga102_gpio_sense,
+       .reset = ga102_gpio_reset,
+};
+
+int
+ga102_gpio_new(struct nvkm_device *device, int index, struct nvkm_gpio **pgpio)
+{
+       return nvkm_gpio_new_(&ga102_gpio, device, index, pgpio);
+}
index 723d0284caefc7d19757861a16e816c5e7913aff..819703913a00c4db2f0b00c048686acb9393e602 100644 (file)
@@ -7,6 +7,7 @@ nvkm-y += nvkm/subdev/i2c/g94.o
 nvkm-y += nvkm/subdev/i2c/gf117.o
 nvkm-y += nvkm/subdev/i2c/gf119.o
 nvkm-y += nvkm/subdev/i2c/gk104.o
+nvkm-y += nvkm/subdev/i2c/gk110.o
 nvkm-y += nvkm/subdev/i2c/gm200.o
 
 nvkm-y += nvkm/subdev/i2c/pad.o
index 30b48896965ebc981c838087357dbfcc408ef054..f920eabf8628dc5db7219d20cb1829fda2cd5ccb 100644 (file)
@@ -3,6 +3,13 @@
 #define __NVKM_I2C_AUX_H__
 #include "pad.h"
 
+static inline void
+nvkm_i2c_aux_autodpcd(struct nvkm_i2c *i2c, int aux, bool enable)
+{
+       if (i2c->func->aux_autodpcd)
+               i2c->func->aux_autodpcd(i2c, aux, false);
+}
+
 struct nvkm_i2c_aux_func {
        bool address_only;
        int  (*xfer)(struct nvkm_i2c_aux *, bool retry, u8 type,
index db7769cb33ebadfa10078c05f019c35cd4680338..47068f6f9c55d439eb0397d1fa254659776807a0 100644 (file)
@@ -77,7 +77,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
                 u8 type, u32 addr, u8 *data, u8 *size)
 {
        struct g94_i2c_aux *aux = g94_i2c_aux(obj);
-       struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
+       struct nvkm_i2c *i2c = aux->base.pad->i2c;
+       struct nvkm_device *device = i2c->subdev.device;
        const u32 base = aux->ch * 0x50;
        u32 ctrl, stat, timeout, retries = 0;
        u32 xbuf[4] = {};
@@ -96,6 +97,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
                goto out;
        }
 
+       nvkm_i2c_aux_autodpcd(i2c, aux->ch, false);
+
        if (!(type & 1)) {
                memcpy(xbuf, data, *size);
                for (i = 0; i < 16; i += 4) {
@@ -128,7 +131,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
                        if (!timeout--) {
                                AUX_ERR(&aux->base, "timeout %08x", ctrl);
                                ret = -EIO;
-                               goto out;
+                               goto out_err;
                        }
                } while (ctrl & 0x00010000);
                ret = 0;
@@ -154,7 +157,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
                memcpy(data, xbuf, *size);
                *size = stat & 0x0000001f;
        }
-
+out_err:
+       nvkm_i2c_aux_autodpcd(i2c, aux->ch, true);
 out:
        g94_i2c_aux_fini(aux);
        return ret < 0 ? ret : (stat & 0x000f0000) >> 16;
index edb6148cbca042c544939adb2cae2588e90a3e0e..8bd1d442e4654a0f4ff0f75c9c485e64d7562a9d 100644 (file)
@@ -33,7 +33,7 @@ static void
 gm200_i2c_aux_fini(struct gm200_i2c_aux *aux)
 {
        struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
-       nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00310000, 0x00000000);
+       nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00710000, 0x00000000);
 }
 
 static int
@@ -54,10 +54,10 @@ gm200_i2c_aux_init(struct gm200_i2c_aux *aux)
                        AUX_ERR(&aux->base, "begin idle timeout %08x", ctrl);
                        return -EBUSY;
                }
-       } while (ctrl & 0x03010000);
+       } while (ctrl & 0x07010000);
 
        /* set some magic, and wait up to 1ms for it to appear */
-       nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00300000, ureq);
+       nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00700000, ureq);
        timeout = 1000;
        do {
                ctrl = nvkm_rd32(device, 0x00d954 + (aux->ch * 0x50));
@@ -67,7 +67,7 @@ gm200_i2c_aux_init(struct gm200_i2c_aux *aux)
                        gm200_i2c_aux_fini(aux);
                        return -EBUSY;
                }
-       } while ((ctrl & 0x03000000) != urep);
+       } while ((ctrl & 0x07000000) != urep);
 
        return 0;
 }
@@ -77,7 +77,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
                   u8 type, u32 addr, u8 *data, u8 *size)
 {
        struct gm200_i2c_aux *aux = gm200_i2c_aux(obj);
-       struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
+       struct nvkm_i2c *i2c = aux->base.pad->i2c;
+       struct nvkm_device *device = i2c->subdev.device;
        const u32 base = aux->ch * 0x50;
        u32 ctrl, stat, timeout, retries = 0;
        u32 xbuf[4] = {};
@@ -96,6 +97,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
                goto out;
        }
 
+       nvkm_i2c_aux_autodpcd(i2c, aux->ch, false);
+
        if (!(type & 1)) {
                memcpy(xbuf, data, *size);
                for (i = 0; i < 16; i += 4) {
@@ -128,7 +131,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
                        if (!timeout--) {
                                AUX_ERR(&aux->base, "timeout %08x", ctrl);
                                ret = -EIO;
-                               goto out;
+                               goto out_err;
                        }
                } while (ctrl & 0x00010000);
                ret = 0;
@@ -155,6 +158,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
                *size = stat & 0x0000001f;
        }
 
+out_err:
+       nvkm_i2c_aux_autodpcd(i2c, aux->ch, true);
 out:
        gm200_i2c_aux_fini(aux);
        return ret < 0 ? ret : (stat & 0x000f0000) >> 16;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gk110.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gk110.c
new file mode 100644 (file)
index 0000000..8e3bfa1
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "priv.h"
+#include "pad.h"
+
+static void
+gk110_aux_autodpcd(struct nvkm_i2c *i2c, int aux, bool enable)
+{
+       nvkm_mask(i2c->subdev.device, 0x00e4f8 + (aux * 0x50), 0x00010000, enable << 16);
+}
+
+static const struct nvkm_i2c_func
+gk110_i2c = {
+       .pad_x_new = gf119_i2c_pad_x_new,
+       .pad_s_new = gf119_i2c_pad_s_new,
+       .aux = 4,
+       .aux_stat = gk104_aux_stat,
+       .aux_mask = gk104_aux_mask,
+       .aux_autodpcd = gk110_aux_autodpcd,
+};
+
+int
+gk110_i2c_new(struct nvkm_device *device, int index, struct nvkm_i2c **pi2c)
+{
+       return nvkm_i2c_new_(&gk110_i2c, device, index, pi2c);
+}
index a23c5f315221cb68d0230bff8095148a1a4604b0..7b2375bff8a9cc8cc9e43ed0c945db02a8fe75fe 100644 (file)
 #include "priv.h"
 #include "pad.h"
 
+static void
+gm200_aux_autodpcd(struct nvkm_i2c *i2c, int aux, bool enable)
+{
+       nvkm_mask(i2c->subdev.device, 0x00d968 + (aux * 0x50), 0x00010000, enable << 16);
+}
+
 static const struct nvkm_i2c_func
 gm200_i2c = {
        .pad_x_new = gf119_i2c_pad_x_new,
@@ -31,6 +37,7 @@ gm200_i2c = {
        .aux = 8,
        .aux_stat = gk104_aux_stat,
        .aux_mask = gk104_aux_mask,
+       .aux_autodpcd = gm200_aux_autodpcd,
 };
 
 int
index 461016814f4f272205386e4286b2e20befc8b920..44b7bb7d4777650ce3730868007750f6668dbd08 100644 (file)
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: MIT */
 #ifndef __NVKM_I2C_PAD_H__
 #define __NVKM_I2C_PAD_H__
-#include <subdev/i2c.h>
+#include "priv.h"
 
 struct nvkm_i2c_pad {
        const struct nvkm_i2c_pad_func *func;
index bd86bc298ebe54e87bd6cda6fb122f663c244f21..e35f6036fcfcb85edd2d652cec50e858d72a4dfb 100644 (file)
@@ -23,6 +23,10 @@ struct nvkm_i2c_func {
        /* mask on/off interrupt types for a given set of auxch
         */
        void (*aux_mask)(struct nvkm_i2c *, u32, u32, u32);
+
+       /* enable/disable HW-initiated DPCD reads
+        */
+       void (*aux_autodpcd)(struct nvkm_i2c *, int aux, bool enable);
 };
 
 void g94_aux_stat(struct nvkm_i2c *, u32 *, u32 *, u32 *, u32 *);
index 2340040942c937c20dddd4bfd26a686df360596a..1115376bc85f5fd5d28e5cb37185721d73cf5e7d 100644 (file)
@@ -22,6 +22,7 @@
  * Authors: Ben Skeggs
  */
 #include "priv.h"
+#include <subdev/timer.h>
 
 static void
 gf100_ibus_intr_hub(struct nvkm_subdev *ibus, int i)
@@ -31,7 +32,6 @@ gf100_ibus_intr_hub(struct nvkm_subdev *ibus, int i)
        u32 data = nvkm_rd32(device, 0x122124 + (i * 0x0400));
        u32 stat = nvkm_rd32(device, 0x122128 + (i * 0x0400));
        nvkm_debug(ibus, "HUB%d: %06x %08x (%08x)\n", i, addr, data, stat);
-       nvkm_mask(device, 0x122128 + (i * 0x0400), 0x00000200, 0x00000000);
 }
 
 static void
@@ -42,7 +42,6 @@ gf100_ibus_intr_rop(struct nvkm_subdev *ibus, int i)
        u32 data = nvkm_rd32(device, 0x124124 + (i * 0x0400));
        u32 stat = nvkm_rd32(device, 0x124128 + (i * 0x0400));
        nvkm_debug(ibus, "ROP%d: %06x %08x (%08x)\n", i, addr, data, stat);
-       nvkm_mask(device, 0x124128 + (i * 0x0400), 0x00000200, 0x00000000);
 }
 
 static void
@@ -53,7 +52,6 @@ gf100_ibus_intr_gpc(struct nvkm_subdev *ibus, int i)
        u32 data = nvkm_rd32(device, 0x128124 + (i * 0x0400));
        u32 stat = nvkm_rd32(device, 0x128128 + (i * 0x0400));
        nvkm_debug(ibus, "GPC%d: %06x %08x (%08x)\n", i, addr, data, stat);
-       nvkm_mask(device, 0x128128 + (i * 0x0400), 0x00000200, 0x00000000);
 }
 
 void
@@ -90,6 +88,12 @@ gf100_ibus_intr(struct nvkm_subdev *ibus)
                        intr1 &= ~stat;
                }
        }
+
+       nvkm_mask(device, 0x121c4c, 0x0000003f, 0x00000002);
+       nvkm_msec(device, 2000,
+               if (!(nvkm_rd32(device, 0x121c4c) & 0x0000003f))
+                       break;
+       );
 }
 
 static int
index f3915f85838ed400e4dc3d4a5bc5b36f12b5591f..22e487b493ad1346851a58c02599ceb97011a798 100644 (file)
@@ -22,6 +22,7 @@
  * Authors: Ben Skeggs
  */
 #include "priv.h"
+#include <subdev/timer.h>
 
 static void
 gk104_ibus_intr_hub(struct nvkm_subdev *ibus, int i)
@@ -31,7 +32,6 @@ gk104_ibus_intr_hub(struct nvkm_subdev *ibus, int i)
        u32 data = nvkm_rd32(device, 0x122124 + (i * 0x0800));
        u32 stat = nvkm_rd32(device, 0x122128 + (i * 0x0800));
        nvkm_debug(ibus, "HUB%d: %06x %08x (%08x)\n", i, addr, data, stat);
-       nvkm_mask(device, 0x122128 + (i * 0x0800), 0x00000200, 0x00000000);
 }
 
 static void
@@ -42,7 +42,6 @@ gk104_ibus_intr_rop(struct nvkm_subdev *ibus, int i)
        u32 data = nvkm_rd32(device, 0x124124 + (i * 0x0800));
        u32 stat = nvkm_rd32(device, 0x124128 + (i * 0x0800));
        nvkm_debug(ibus, "ROP%d: %06x %08x (%08x)\n", i, addr, data, stat);
-       nvkm_mask(device, 0x124128 + (i * 0x0800), 0x00000200, 0x00000000);
 }
 
 static void
@@ -53,7 +52,6 @@ gk104_ibus_intr_gpc(struct nvkm_subdev *ibus, int i)
        u32 data = nvkm_rd32(device, 0x128124 + (i * 0x0800));
        u32 stat = nvkm_rd32(device, 0x128128 + (i * 0x0800));
        nvkm_debug(ibus, "GPC%d: %06x %08x (%08x)\n", i, addr, data, stat);
-       nvkm_mask(device, 0x128128 + (i * 0x0800), 0x00000200, 0x00000000);
 }
 
 void
@@ -90,6 +88,12 @@ gk104_ibus_intr(struct nvkm_subdev *ibus)
                        intr1 &= ~stat;
                }
        }
+
+       nvkm_mask(device, 0x12004c, 0x0000003f, 0x00000002);
+       nvkm_msec(device, 2000,
+               if (!(nvkm_rd32(device, 0x12004c) & 0x0000003f))
+                       break;
+       );
 }
 
 static int
index 2585ef07532ac094a2f888ffb38d503a846572b3..ac2b34e9ac6add2ca24bff686f8799bcf39ff7ac 100644 (file)
@@ -14,3 +14,4 @@ nvkm-y += nvkm/subdev/mc/gk20a.o
 nvkm-y += nvkm/subdev/mc/gp100.o
 nvkm-y += nvkm/subdev/mc/gp10b.o
 nvkm-y += nvkm/subdev/mc/tu102.o
+nvkm-y += nvkm/subdev/mc/ga100.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c
new file mode 100644 (file)
index 0000000..967eb3a
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "priv.h"
+
+static void
+ga100_mc_intr_unarm(struct nvkm_mc *mc)
+{
+       nvkm_wr32(mc->subdev.device, 0xb81610, 0x00000004);
+}
+
+static void
+ga100_mc_intr_rearm(struct nvkm_mc *mc)
+{
+       nvkm_wr32(mc->subdev.device, 0xb81608, 0x00000004);
+}
+
+static void
+ga100_mc_intr_mask(struct nvkm_mc *mc, u32 mask, u32 intr)
+{
+       nvkm_wr32(mc->subdev.device, 0xb81210,          mask & intr );
+       nvkm_wr32(mc->subdev.device, 0xb81410, mask & ~(mask & intr));
+}
+
+static u32
+ga100_mc_intr_stat(struct nvkm_mc *mc)
+{
+       u32 intr_top = nvkm_rd32(mc->subdev.device, 0xb81600), intr = 0x00000000;
+       if (intr_top & 0x00000004)
+               intr = nvkm_mask(mc->subdev.device, 0xb81010, 0x00000000, 0x00000000);
+       return intr;
+}
+
+static void
+ga100_mc_init(struct nvkm_mc *mc)
+{
+       nv50_mc_init(mc);
+       nvkm_wr32(mc->subdev.device, 0xb81210, 0xffffffff);
+}
+
+static const struct nvkm_mc_func
+ga100_mc = {
+       .init = ga100_mc_init,
+       .intr = gp100_mc_intr,
+       .intr_unarm = ga100_mc_intr_unarm,
+       .intr_rearm = ga100_mc_intr_rearm,
+       .intr_mask = ga100_mc_intr_mask,
+       .intr_stat = ga100_mc_intr_stat,
+       .reset = gk104_mc_reset,
+};
+
+int
+ga100_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
+{
+       return nvkm_mc_new_(&ga100_mc, device, index, pmc);
+}
index de91e9a2617258cbcc93e7ea027a9d4a77a1f99f..6d5212ae2fd57b741715e7d7c9e4c83fe5bdd13e 100644 (file)
@@ -316,9 +316,9 @@ nvkm_mmu_vram(struct nvkm_mmu *mmu)
 {
        struct nvkm_device *device = mmu->subdev.device;
        struct nvkm_mm *mm = &device->fb->ram->vram;
-       const u32 sizeN = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NORMAL);
-       const u32 sizeU = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NOMAP);
-       const u32 sizeM = nvkm_mm_heap_size(mm, NVKM_RAM_MM_MIXED);
+       const u64 sizeN = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NORMAL);
+       const u64 sizeU = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NOMAP);
+       const u64 sizeM = nvkm_mm_heap_size(mm, NVKM_RAM_MM_MIXED);
        u8 type = NVKM_MEM_KIND * !!mmu->func->kind;
        u8 heap = NVKM_MEM_VRAM;
        int heapM, heapN, heapU;
index a00b7ab9c14cfca59adbd7b8545ebb1a14d29d60..11e0313db0ea681d4a100b583597c20fad09eee9 100644 (file)
@@ -66,7 +66,7 @@ static struct ttm_pool_type global_uncached[MAX_ORDER];
 static struct ttm_pool_type global_dma32_write_combined[MAX_ORDER];
 static struct ttm_pool_type global_dma32_uncached[MAX_ORDER];
 
-static spinlock_t shrinker_lock;
+static struct mutex shrinker_lock;
 static struct list_head shrinker_list;
 static struct shrinker mm_shrinker;
 
@@ -79,12 +79,13 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags,
        struct page *p;
        void *vaddr;
 
-       if (order) {
-               gfp_flags |= GFP_TRANSHUGE_LIGHT | __GFP_NORETRY |
+       /* Don't set the __GFP_COMP flag for higher order allocations.
+        * Mapping pages directly into an userspace process and calling
+        * put_page() on a TTM allocated page is illegal.
+        */
+       if (order)
+               gfp_flags |= __GFP_NOMEMALLOC | __GFP_NORETRY |
                        __GFP_KSWAPD_RECLAIM;
-               gfp_flags &= ~__GFP_MOVABLE;
-               gfp_flags &= ~__GFP_COMP;
-       }
 
        if (!pool->use_dma_alloc) {
                p = alloc_pages(gfp_flags, order);
@@ -190,7 +191,7 @@ static int ttm_pool_map(struct ttm_pool *pool, unsigned int order,
                size_t size = (1ULL << order) * PAGE_SIZE;
 
                addr = dma_map_page(pool->dev, p, 0, size, DMA_BIDIRECTIONAL);
-               if (dma_mapping_error(pool->dev, **dma_addr))
+               if (dma_mapping_error(pool->dev, addr))
                        return -EFAULT;
        }
 
@@ -249,9 +250,9 @@ static void ttm_pool_type_init(struct ttm_pool_type *pt, struct ttm_pool *pool,
        spin_lock_init(&pt->lock);
        INIT_LIST_HEAD(&pt->pages);
 
-       spin_lock(&shrinker_lock);
+       mutex_lock(&shrinker_lock);
        list_add_tail(&pt->shrinker_list, &shrinker_list);
-       spin_unlock(&shrinker_lock);
+       mutex_unlock(&shrinker_lock);
 }
 
 /* Remove a pool_type from the global shrinker list and free all pages */
@@ -259,9 +260,9 @@ static void ttm_pool_type_fini(struct ttm_pool_type *pt)
 {
        struct page *p, *tmp;
 
-       spin_lock(&shrinker_lock);
+       mutex_lock(&shrinker_lock);
        list_del(&pt->shrinker_list);
-       spin_unlock(&shrinker_lock);
+       mutex_unlock(&shrinker_lock);
 
        list_for_each_entry_safe(p, tmp, &pt->pages, lru)
                ttm_pool_free_page(pt->pool, pt->caching, pt->order, p);
@@ -302,7 +303,7 @@ static unsigned int ttm_pool_shrink(void)
        unsigned int num_freed;
        struct page *p;
 
-       spin_lock(&shrinker_lock);
+       mutex_lock(&shrinker_lock);
        pt = list_first_entry(&shrinker_list, typeof(*pt), shrinker_list);
 
        p = ttm_pool_type_take(pt);
@@ -314,7 +315,7 @@ static unsigned int ttm_pool_shrink(void)
        }
 
        list_move_tail(&pt->shrinker_list, &shrinker_list);
-       spin_unlock(&shrinker_lock);
+       mutex_unlock(&shrinker_lock);
 
        return num_freed;
 }
@@ -564,7 +565,7 @@ int ttm_pool_debugfs(struct ttm_pool *pool, struct seq_file *m)
 {
        unsigned int i;
 
-       spin_lock(&shrinker_lock);
+       mutex_lock(&shrinker_lock);
 
        seq_puts(m, "\t ");
        for (i = 0; i < MAX_ORDER; ++i)
@@ -600,7 +601,7 @@ int ttm_pool_debugfs(struct ttm_pool *pool, struct seq_file *m)
        seq_printf(m, "\ntotal\t: %8lu of %8lu\n",
                   atomic_long_read(&allocated_pages), page_pool_size);
 
-       spin_unlock(&shrinker_lock);
+       mutex_unlock(&shrinker_lock);
 
        return 0;
 }
@@ -644,7 +645,7 @@ int ttm_pool_mgr_init(unsigned long num_pages)
        if (!page_pool_size)
                page_pool_size = num_pages;
 
-       spin_lock_init(&shrinker_lock);
+       mutex_init(&shrinker_lock);
        INIT_LIST_HEAD(&shrinker_list);
 
        for (i = 0; i < MAX_ORDER; ++i) {
index 55510622057826ee3376fc8552cb492b6ed87136..98cab0bbe92d881086f09e1b916d8d27c5c320e4 100644 (file)
@@ -1267,6 +1267,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
        card->dai_link = dai_link;
        card->num_links = 1;
        card->name = vc4_hdmi->variant->card_name;
+       card->driver_name = "vc4-hdmi";
        card->dev = dev;
        card->owner = THIS_MODULE;
 
index 7bdda1b5b2217420cc1fe9860b7477b8bfac5749..09fa75a2b289e5e31c457d85fa4c6db90c3e86ed 100644 (file)
@@ -899,6 +899,7 @@ config HID_SONY
        depends on NEW_LEDS
        depends on LEDS_CLASS
        select POWER_SUPPLY
+       select CRC32
        help
        Support for
 
index 3d1ccac5d99a34a519dc5148e07780807d4a2b98..2ab38b715347717142c9805a902869c25fc10cf6 100644 (file)
@@ -154,7 +154,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
 
        for (i = 0; i < cl_data->num_hid_devices; i++) {
                cl_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8,
-                                                                 &cl_data->sensor_phys_addr[i],
+                                                                 &cl_data->sensor_dma_addr[i],
                                                                  GFP_KERNEL);
                cl_data->sensor_sts[i] = 0;
                cl_data->sensor_requested_cnt[i] = 0;
@@ -187,7 +187,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
                }
                info.period = msecs_to_jiffies(AMD_SFH_IDLE_LOOP);
                info.sensor_idx = cl_idx;
-               info.phys_address = cl_data->sensor_phys_addr[i];
+               info.dma_address = cl_data->sensor_dma_addr[i];
 
                cl_data->report_descr[i] = kzalloc(cl_data->report_descr_sz[i], GFP_KERNEL);
                if (!cl_data->report_descr[i]) {
@@ -212,7 +212,7 @@ cleanup:
                if (cl_data->sensor_virt_addr[i]) {
                        dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
                                          cl_data->sensor_virt_addr[i],
-                                         cl_data->sensor_phys_addr[i]);
+                                         cl_data->sensor_dma_addr[i]);
                }
                kfree(cl_data->feature_report[i]);
                kfree(cl_data->input_report[i]);
@@ -238,7 +238,7 @@ int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
                if (cl_data->sensor_virt_addr[i]) {
                        dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int),
                                          cl_data->sensor_virt_addr[i],
-                                         cl_data->sensor_phys_addr[i]);
+                                         cl_data->sensor_dma_addr[i]);
                }
        }
        kfree(cl_data);
index 6be0783d885ce5f91e808760dfc9f152c9bcb220..d7eac1728e314add855c917ba5e07edf4e95c443 100644 (file)
@@ -27,7 +27,7 @@ struct amdtp_cl_data {
        int hid_descr_size[MAX_HID_DEVICES];
        phys_addr_t phys_addr_base;
        u32 *sensor_virt_addr[MAX_HID_DEVICES];
-       phys_addr_t sensor_phys_addr[MAX_HID_DEVICES];
+       dma_addr_t sensor_dma_addr[MAX_HID_DEVICES];
        u32 sensor_sts[MAX_HID_DEVICES];
        u32 sensor_requested_cnt[MAX_HID_DEVICES];
        u8 report_type[MAX_HID_DEVICES];
index a51c7b76283bb46b156fe405cf487a986d1cdd3e..dbac1664166277ba2117b2dde68677699200cfd6 100644 (file)
@@ -41,7 +41,7 @@ void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info i
        cmd_param.s.buf_layout = 1;
        cmd_param.s.buf_length = 16;
 
-       writeq(info.phys_address, privdata->mmio + AMD_C2P_MSG2);
+       writeq(info.dma_address, privdata->mmio + AMD_C2P_MSG2);
        writel(cmd_param.ul, privdata->mmio + AMD_C2P_MSG1);
        writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
 }
index e8be94f935b78f862bd7cb0da3e07613b7e6ae49..8f8d19b2cfe5ba611ac62ea0fdf63327abe74a97 100644 (file)
@@ -67,7 +67,7 @@ struct amd_mp2_dev {
 struct amd_mp2_sensor_info {
        u8 sensor_idx;
        u32 period;
-       phys_addr_t phys_address;
+       dma_addr_t dma_address;
 };
 
 void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
index 4c5f23640f9c7434260346a41d3036d32ddd9da7..5ba0aa1d2335351111836d97520cea279ade0175 100644 (file)
 #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W        0x0401
 #define USB_DEVICE_ID_HP_X2            0x074d
 #define USB_DEVICE_ID_HP_X2_10_COVER   0x0755
+#define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN   0x2706
 
 #define USB_VENDOR_ID_ELECOM           0x056e
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
index dc7f6b4a775c982a3f966480526083287d717534..f23027d2795ba0b816aabfb74200b1cfb09f9566 100644 (file)
@@ -322,6 +322,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
                USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD),
          HID_BATTERY_QUIRK_IGNORE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN),
+         HID_BATTERY_QUIRK_IGNORE },
        {}
 };
 
index 1ffcfc9a1e033b9015a2c88ce72b2b5710e4ee49..45e7e0bdd382bd736f51fecba28ecd370f5eba2d 100644 (file)
@@ -1869,6 +1869,10 @@ static const struct hid_device_id logi_dj_receivers[] = {
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
                0xc531),
         .driver_data = recvr_type_gaming_hidpp},
+       { /* Logitech G602 receiver (0xc537) */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+               0xc537),
+        .driver_data = recvr_type_gaming_hidpp},
        { /* Logitech lightspeed receiver (0xc539) */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
                USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1),
index f85781464807d130b41797b2b57274438a7e4ca9..7eb9a6ddb46a67e7d06866b923f0bf0994c7b1b9 100644 (file)
@@ -4053,6 +4053,8 @@ static const struct hid_device_id hidpp_devices[] = {
        { /* MX Master mouse over Bluetooth */
          HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012),
          .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
+       { /* MX Ergo trackball over Bluetooth */
+         HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01d) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01e),
          .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
        { /* MX Master 3 mouse over Bluetooth */
index d670bcd57bdef88870661a81fd9179d72a3077cd..0743ef51d3b246ab2086ca3dda387a842b79e19e 100644 (file)
@@ -2054,6 +2054,10 @@ static const struct hid_device_id mt_devices[] = {
                HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
                        USB_VENDOR_ID_SYNAPTICS, 0xce08) },
 
+       { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
+               HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+                       USB_VENDOR_ID_SYNAPTICS, 0xce09) },
+
        /* TopSeed panels */
        { .driver_data = MT_CLS_TOPSEED,
                MT_USB_DEVICE(USB_VENDOR_ID_TOPSEED2,
index d26d8cd98efcfddc869155a07779828c54eee6bc..56406cee401fffcfc4b63f8cd6dc926b7b93dfbb 100644 (file)
@@ -90,7 +90,7 @@ static int uclogic_params_get_str_desc(__u8 **pbuf, struct hid_device *hdev,
                goto cleanup;
        } else if (rc < 0) {
                hid_err(hdev,
-                       "failed retrieving string descriptor #%hhu: %d\n",
+                       "failed retrieving string descriptor #%u: %d\n",
                        idx, rc);
                goto cleanup;
        }
index 41012681cafd1ec469d9bfb19930cf1d4a5c6d00..4399d6c6afef2c2bdb22eb013e4b2ac1a729284e 100644 (file)
@@ -1482,7 +1482,7 @@ static void handler_return(struct wiimote_data *wdata, const __u8 *payload)
                wdata->state.cmd_err = err;
                wiimote_cmd_complete(wdata);
        } else if (err) {
-               hid_warn(wdata->hdev, "Remote error %hhu on req %hhu\n", err,
+               hid_warn(wdata->hdev, "Remote error %u on req %u\n", err,
                                                                        cmd);
        }
 }
index 045c464228d91f6a9bb8cba52fc5360ec7331013..e8acd235db2a90f156ec516d37990921a759e0db 100644 (file)
@@ -1270,6 +1270,37 @@ static int wacom_devm_sysfs_create_group(struct wacom *wacom,
                                               group);
 }
 
+static void wacom_devm_kfifo_release(struct device *dev, void *res)
+{
+       struct kfifo_rec_ptr_2 *devres = res;
+
+       kfifo_free(devres);
+}
+
+static int wacom_devm_kfifo_alloc(struct wacom *wacom)
+{
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+       struct kfifo_rec_ptr_2 *pen_fifo = &wacom_wac->pen_fifo;
+       int error;
+
+       pen_fifo = devres_alloc(wacom_devm_kfifo_release,
+                             sizeof(struct kfifo_rec_ptr_2),
+                             GFP_KERNEL);
+
+       if (!pen_fifo)
+               return -ENOMEM;
+
+       error = kfifo_alloc(pen_fifo, WACOM_PKGLEN_MAX, GFP_KERNEL);
+       if (error) {
+               devres_free(pen_fifo);
+               return error;
+       }
+
+       devres_add(&wacom->hdev->dev, pen_fifo);
+
+       return 0;
+}
+
 enum led_brightness wacom_leds_brightness_get(struct wacom_led *led)
 {
        struct wacom *wacom = led->wacom;
@@ -2724,7 +2755,7 @@ static int wacom_probe(struct hid_device *hdev,
        if (features->check_for_hid_type && features->hid_type != hdev->type)
                return -ENODEV;
 
-       error = kfifo_alloc(&wacom_wac->pen_fifo, WACOM_PKGLEN_MAX, GFP_KERNEL);
+       error = wacom_devm_kfifo_alloc(wacom);
        if (error)
                return error;
 
@@ -2786,8 +2817,6 @@ static void wacom_remove(struct hid_device *hdev)
 
        if (wacom->wacom_wac.features.type != REMOTE)
                wacom_release_resources(wacom);
-
-       kfifo_free(&wacom_wac->pen_fifo);
 }
 
 #ifdef CONFIG_PM
index 502f8cd95f6d46cb6db5923ba877612f886d4a7a..d491fdcee61f025e37c0a3551c29b555ce5a2b87 100644 (file)
@@ -2550,7 +2550,6 @@ static void hv_kexec_handler(void)
        /* Make sure conn_state is set as hv_synic_cleanup checks for it */
        mb();
        cpuhp_remove_state(hyperv_cpuhp_online);
-       hyperv_cleanup();
 };
 
 static void hv_crash_handler(struct pt_regs *regs)
@@ -2566,7 +2565,6 @@ static void hv_crash_handler(struct pt_regs *regs)
        cpu = smp_processor_id();
        hv_stimer_cleanup(cpu);
        hv_synic_disable_regs(cpu);
-       hyperv_cleanup();
 };
 
 static int hv_synic_suspend(void)
index d4d60ad0eda0b04746ba2664071efae6e1745dc3..ab1f39ac39f4f081fb943c877efa0195770c508f 100644 (file)
@@ -1013,6 +1013,7 @@ config I2C_SIRF
 config I2C_SPRD
        tristate "Spreadtrum I2C interface"
        depends on I2C=y && (ARCH_SPRD || COMPILE_TEST)
+       depends on COMMON_CLK
        help
          If you say yes to this option, support will be included for the
          Spreadtrum I2C interface.
index b444fbf1a26255988ef94407583ebd6d08aef9c7..a8e8af57e33f466ae463d230feeef0ebddf7e59c 100644 (file)
@@ -241,6 +241,19 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
 
 };
 
+static const struct platform_device_id imx_i2c_devtype[] = {
+       {
+               .name = "imx1-i2c",
+               .driver_data = (kernel_ulong_t)&imx1_i2c_hwdata,
+       }, {
+               .name = "imx21-i2c",
+               .driver_data = (kernel_ulong_t)&imx21_i2c_hwdata,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, imx_i2c_devtype);
+
 static const struct of_device_id i2c_imx_dt_ids[] = {
        { .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, },
        { .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, },
@@ -1330,7 +1343,11 @@ static int i2c_imx_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        match = device_get_match_data(&pdev->dev);
-       i2c_imx->hwdata = match;
+       if (match)
+               i2c_imx->hwdata = match;
+       else
+               i2c_imx->hwdata = (struct imx_i2c_hwdata *)
+                               platform_get_device_id(pdev)->driver_data;
 
        /* Setup i2c_imx driver structure */
        strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name));
@@ -1498,6 +1515,7 @@ static struct platform_driver i2c_imx_driver = {
                .of_match_table = i2c_imx_dt_ids,
                .acpi_match_table = i2c_imx_acpi_ids,
        },
+       .id_table = imx_i2c_devtype,
 };
 
 static int __init i2c_adap_imx_init(void)
index d9607905dc2f1dd0db15c6ca457ebc445921d829..845eda70b8cab52a0453c9f4cb545010fba4305d 100644 (file)
@@ -347,7 +347,7 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
                if (result)
                        return result;
                if (recv_len && i == 0) {
-                       if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
+                       if (data[i] > I2C_SMBUS_BLOCK_MAX)
                                return -EPROTO;
                        length += data[i];
                }
index ec7a7e917eddb2ce94b65f97f4c2b813a64ee45f..c0c7d01473f2ba110553c0349e10ca6b03dbb7ca 100644 (file)
@@ -80,7 +80,7 @@ static int tegra_bpmp_xlate_flags(u16 flags, u16 *out)
                flags &= ~I2C_M_RECV_LEN;
        }
 
-       return (flags != 0) ? -EINVAL : 0;
+       return 0;
 }
 
 /**
index 6f08c0c3238d5ade9a25f4c9900ba79d23fe2782..8b113ae32dc713f26d28726a934a30c9f3b55863 100644 (file)
@@ -326,6 +326,8 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg)
        /* read back register to make sure that register writes completed */
        if (reg != I2C_TX_FIFO)
                readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
+       else if (i2c_dev->is_vi)
+               readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, I2C_INT_STATUS));
 }
 
 static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
@@ -339,6 +341,21 @@ static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data,
        writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
 }
 
+static void i2c_writesl_vi(struct tegra_i2c_dev *i2c_dev, void *data,
+                          unsigned int reg, unsigned int len)
+{
+       u32 *data32 = data;
+
+       /*
+        * VI I2C controller has known hardware bug where writes get stuck
+        * when immediate multiple writes happen to TX_FIFO register.
+        * Recommended software work around is to read I2C register after
+        * each write to TX_FIFO register to flush out the data.
+        */
+       while (len--)
+               i2c_writel(i2c_dev, *data32++, reg);
+}
+
 static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data,
                       unsigned int reg, unsigned int len)
 {
@@ -533,7 +550,7 @@ static int tegra_i2c_poll_register(struct tegra_i2c_dev *i2c_dev,
        void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg);
        u32 val;
 
-       if (!i2c_dev->atomic_mode)
+       if (!i2c_dev->atomic_mode && !in_irq())
                return readl_relaxed_poll_timeout(addr, val, !(val & mask),
                                                  delay_us, timeout_us);
 
@@ -811,7 +828,10 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
                i2c_dev->msg_buf_remaining = buf_remaining;
                i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD;
 
-               i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
+               if (i2c_dev->is_vi)
+                       i2c_writesl_vi(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
+               else
+                       i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
 
                buf += words_to_transfer * BYTES_PER_FIFO_WORD;
        }
index 7f70e5a7de10543318f1afe420193e8f42084c59..97a77ea8d3c9c1048b27dd90b68e3b90b3809c33 100644 (file)
@@ -131,8 +131,10 @@ static ssize_t default_roce_mode_store(struct config_item *item,
                return ret;
 
        gid_type = ib_cache_gid_parse_type_str(buf);
-       if (gid_type < 0)
+       if (gid_type < 0) {
+               cma_configfs_params_put(cma_dev);
                return -EINVAL;
+       }
 
        ret = cma_set_default_gid_type(cma_dev, group->port_num, gid_type);
 
index e0a41c8670023a4ef2df594248353fbfef4e28cb..ff1551b3cf619862d66077b8a7b6f12d3175147b 100644 (file)
@@ -254,6 +254,7 @@ void rdma_restrack_add(struct rdma_restrack_entry *res)
        } else {
                ret = xa_alloc_cyclic(&rt->xa, &res->id, res, xa_limit_32b,
                                      &rt->next_id, GFP_KERNEL);
+               ret = (ret < 0) ? ret : 0;
        }
 
 out:
index 7dab9a27a145a8eee04150c3caa11f2988bae584..da2512c30ffd5276c02e651638c3db89d403287f 100644 (file)
@@ -95,8 +95,6 @@ struct ucma_context {
        u64                     uid;
 
        struct list_head        list;
-       /* sync between removal event and id destroy, protected by file mut */
-       int                     destroying;
        struct work_struct      close_work;
 };
 
@@ -122,7 +120,7 @@ static DEFINE_XARRAY_ALLOC(ctx_table);
 static DEFINE_XARRAY_ALLOC(multicast_table);
 
 static const struct file_operations ucma_fops;
-static int __destroy_id(struct ucma_context *ctx);
+static int ucma_destroy_private_ctx(struct ucma_context *ctx);
 
 static inline struct ucma_context *_ucma_find_context(int id,
                                                      struct ucma_file *file)
@@ -179,19 +177,14 @@ static void ucma_close_id(struct work_struct *work)
 
        /* once all inflight tasks are finished, we close all underlying
         * resources. The context is still alive till its explicit destryoing
-        * by its creator.
+        * by its creator. This puts back the xarray's reference.
         */
        ucma_put_ctx(ctx);
        wait_for_completion(&ctx->comp);
        /* No new events will be generated after destroying the id. */
        rdma_destroy_id(ctx->cm_id);
 
-       /*
-        * At this point ctx->ref is zero so the only place the ctx can be is in
-        * a uevent or in __destroy_id(). Since the former doesn't touch
-        * ctx->cm_id and the latter sync cancels this, there is no races with
-        * this store.
-        */
+       /* Reading the cm_id without holding a positive ref is not allowed */
        ctx->cm_id = NULL;
 }
 
@@ -204,7 +197,6 @@ static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file)
                return NULL;
 
        INIT_WORK(&ctx->close_work, ucma_close_id);
-       refcount_set(&ctx->ref, 1);
        init_completion(&ctx->comp);
        /* So list_del() will work if we don't do ucma_finish_ctx() */
        INIT_LIST_HEAD(&ctx->list);
@@ -218,6 +210,13 @@ static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file)
        return ctx;
 }
 
+static void ucma_set_ctx_cm_id(struct ucma_context *ctx,
+                              struct rdma_cm_id *cm_id)
+{
+       refcount_set(&ctx->ref, 1);
+       ctx->cm_id = cm_id;
+}
+
 static void ucma_finish_ctx(struct ucma_context *ctx)
 {
        lockdep_assert_held(&ctx->file->mut);
@@ -303,7 +302,7 @@ static int ucma_connect_event_handler(struct rdma_cm_id *cm_id,
        ctx = ucma_alloc_ctx(listen_ctx->file);
        if (!ctx)
                goto err_backlog;
-       ctx->cm_id = cm_id;
+       ucma_set_ctx_cm_id(ctx, cm_id);
 
        uevent = ucma_create_uevent(listen_ctx, event);
        if (!uevent)
@@ -321,8 +320,7 @@ static int ucma_connect_event_handler(struct rdma_cm_id *cm_id,
        return 0;
 
 err_alloc:
-       xa_erase(&ctx_table, ctx->id);
-       kfree(ctx);
+       ucma_destroy_private_ctx(ctx);
 err_backlog:
        atomic_inc(&listen_ctx->backlog);
        /* Returning error causes the new ID to be destroyed */
@@ -356,8 +354,12 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,
                wake_up_interruptible(&ctx->file->poll_wait);
        }
 
-       if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL && !ctx->destroying)
-               queue_work(system_unbound_wq, &ctx->close_work);
+       if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL) {
+               xa_lock(&ctx_table);
+               if (xa_load(&ctx_table, ctx->id) == ctx)
+                       queue_work(system_unbound_wq, &ctx->close_work);
+               xa_unlock(&ctx_table);
+       }
        return 0;
 }
 
@@ -461,13 +463,12 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
                ret = PTR_ERR(cm_id);
                goto err1;
        }
-       ctx->cm_id = cm_id;
+       ucma_set_ctx_cm_id(ctx, cm_id);
 
        resp.id = ctx->id;
        if (copy_to_user(u64_to_user_ptr(cmd.response),
                         &resp, sizeof(resp))) {
-               xa_erase(&ctx_table, ctx->id);
-               __destroy_id(ctx);
+               ucma_destroy_private_ctx(ctx);
                return -EFAULT;
        }
 
@@ -477,8 +478,7 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
        return 0;
 
 err1:
-       xa_erase(&ctx_table, ctx->id);
-       kfree(ctx);
+       ucma_destroy_private_ctx(ctx);
        return ret;
 }
 
@@ -516,68 +516,73 @@ static void ucma_cleanup_mc_events(struct ucma_multicast *mc)
        rdma_unlock_handler(mc->ctx->cm_id);
 }
 
-/*
- * ucma_free_ctx is called after the underlying rdma CM-ID is destroyed. At
- * this point, no new events will be reported from the hardware. However, we
- * still need to cleanup the UCMA context for this ID. Specifically, there
- * might be events that have not yet been consumed by the user space software.
- * mutex. After that we release them as needed.
- */
-static int ucma_free_ctx(struct ucma_context *ctx)
+static int ucma_cleanup_ctx_events(struct ucma_context *ctx)
 {
        int events_reported;
        struct ucma_event *uevent, *tmp;
        LIST_HEAD(list);
 
-       ucma_cleanup_multicast(ctx);
-
-       /* Cleanup events not yet reported to the user. */
+       /* Cleanup events not yet reported to the user.*/
        mutex_lock(&ctx->file->mut);
        list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list) {
-               if (uevent->ctx == ctx || uevent->conn_req_ctx == ctx)
+               if (uevent->ctx != ctx)
+                       continue;
+
+               if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST &&
+                   xa_cmpxchg(&ctx_table, uevent->conn_req_ctx->id,
+                              uevent->conn_req_ctx, XA_ZERO_ENTRY,
+                              GFP_KERNEL) == uevent->conn_req_ctx) {
                        list_move_tail(&uevent->list, &list);
+                       continue;
+               }
+               list_del(&uevent->list);
+               kfree(uevent);
        }
        list_del(&ctx->list);
        events_reported = ctx->events_reported;
        mutex_unlock(&ctx->file->mut);
 
        /*
-        * If this was a listening ID then any connections spawned from it
-        * that have not been delivered to userspace are cleaned up too.
-        * Must be done outside any locks.
+        * If this was a listening ID then any connections spawned from it that
+        * have not been delivered to userspace are cleaned up too. Must be done
+        * outside any locks.
         */
        list_for_each_entry_safe(uevent, tmp, &list, list) {
-               list_del(&uevent->list);
-               if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST &&
-                   uevent->conn_req_ctx != ctx)
-                       __destroy_id(uevent->conn_req_ctx);
+               ucma_destroy_private_ctx(uevent->conn_req_ctx);
                kfree(uevent);
        }
-
-       mutex_destroy(&ctx->mutex);
-       kfree(ctx);
        return events_reported;
 }
 
-static int __destroy_id(struct ucma_context *ctx)
+/*
+ * When this is called the xarray must have a XA_ZERO_ENTRY in the ctx->id (ie
+ * the ctx is not public to the user). This either because:
+ *  - ucma_finish_ctx() hasn't been called
+ *  - xa_cmpxchg() succeed to remove the entry (only one thread can succeed)
+ */
+static int ucma_destroy_private_ctx(struct ucma_context *ctx)
 {
+       int events_reported;
+
        /*
-        * If the refcount is already 0 then ucma_close_id() has already
-        * destroyed the cm_id, otherwise holding the refcount keeps cm_id
-        * valid. Prevent queue_work() from being called.
+        * Destroy the underlying cm_id. New work queuing is prevented now by
+        * the removal from the xarray. Once the work is cancled ref will either
+        * be 0 because the work ran to completion and consumed the ref from the
+        * xarray, or it will be positive because we still have the ref from the
+        * xarray. This can also be 0 in cases where cm_id was never set
         */
-       if (refcount_inc_not_zero(&ctx->ref)) {
-               rdma_lock_handler(ctx->cm_id);
-               ctx->destroying = 1;
-               rdma_unlock_handler(ctx->cm_id);
-               ucma_put_ctx(ctx);
-       }
-
        cancel_work_sync(&ctx->close_work);
-       /* At this point it's guaranteed that there is no inflight closing task */
-       if (ctx->cm_id)
+       if (refcount_read(&ctx->ref))
                ucma_close_id(&ctx->close_work);
-       return ucma_free_ctx(ctx);
+
+       events_reported = ucma_cleanup_ctx_events(ctx);
+       ucma_cleanup_multicast(ctx);
+
+       WARN_ON(xa_cmpxchg(&ctx_table, ctx->id, XA_ZERO_ENTRY, NULL,
+                          GFP_KERNEL) != NULL);
+       mutex_destroy(&ctx->mutex);
+       kfree(ctx);
+       return events_reported;
 }
 
 static ssize_t ucma_destroy_id(struct ucma_file *file, const char __user *inbuf,
@@ -596,14 +601,17 @@ static ssize_t ucma_destroy_id(struct ucma_file *file, const char __user *inbuf,
 
        xa_lock(&ctx_table);
        ctx = _ucma_find_context(cmd.id, file);
-       if (!IS_ERR(ctx))
-               __xa_erase(&ctx_table, ctx->id);
+       if (!IS_ERR(ctx)) {
+               if (__xa_cmpxchg(&ctx_table, ctx->id, ctx, XA_ZERO_ENTRY,
+                                GFP_KERNEL) != ctx)
+                       ctx = ERR_PTR(-ENOENT);
+       }
        xa_unlock(&ctx_table);
 
        if (IS_ERR(ctx))
                return PTR_ERR(ctx);
 
-       resp.events_reported = __destroy_id(ctx);
+       resp.events_reported = ucma_destroy_private_ctx(ctx);
        if (copy_to_user(u64_to_user_ptr(cmd.response),
                         &resp, sizeof(resp)))
                ret = -EFAULT;
@@ -1777,15 +1785,16 @@ static int ucma_close(struct inode *inode, struct file *filp)
         * prevented by this being a FD release function. The list_add_tail() in
         * ucma_connect_event_handler() can run concurrently, however it only
         * adds to the list *after* a listening ID. By only reading the first of
-        * the list, and relying on __destroy_id() to block
+        * the list, and relying on ucma_destroy_private_ctx() to block
         * ucma_connect_event_handler(), no additional locking is needed.
         */
        while (!list_empty(&file->ctx_list)) {
                struct ucma_context *ctx = list_first_entry(
                        &file->ctx_list, struct ucma_context, list);
 
-               xa_erase(&ctx_table, ctx->id);
-               __destroy_id(ctx);
+               WARN_ON(xa_cmpxchg(&ctx_table, ctx->id, ctx, XA_ZERO_ENTRY,
+                                  GFP_KERNEL) != ctx);
+               ucma_destroy_private_ctx(ctx);
        }
        kfree(file);
        return 0;
index 7ca4112e3e8f7ff001c154225743391be9f9fb8a..917338db7ac13e8d6582c5ba84f00b6b85b369b4 100644 (file)
@@ -135,7 +135,7 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
         */
        if (mask)
                pgsz_bitmap &= GENMASK(count_trailing_zeros(mask), 0);
-       return rounddown_pow_of_two(pgsz_bitmap);
+       return pgsz_bitmap ? rounddown_pow_of_two(pgsz_bitmap) : 0;
 }
 EXPORT_SYMBOL(ib_umem_find_best_pgsz);
 
index 3bae9ba0ead8518eba40570130412955d2c19f92..d26f3f3e0462a03e8cc38058124add5bcb0f86d8 100644 (file)
@@ -3956,7 +3956,7 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
 
        err = set_has_smi_cap(dev);
        if (err)
-               return err;
+               goto err_mp;
 
        if (!mlx5_core_mp_enabled(mdev)) {
                for (i = 1; i <= dev->num_ports; i++) {
@@ -4319,7 +4319,7 @@ static int mlx5_ib_stage_bfrag_init(struct mlx5_ib_dev *dev)
 
        err = mlx5_alloc_bfreg(dev->mdev, &dev->fp_bfreg, false, true);
        if (err)
-               mlx5_free_bfreg(dev->mdev, &dev->fp_bfreg);
+               mlx5_free_bfreg(dev->mdev, &dev->bfreg);
 
        return err;
 }
index bc98bd950d99fadb0a24e2b9979be7fa1369b77e..3acb5c10b1553f03ab96a3336d9c0318e9edd966 100644 (file)
@@ -434,9 +434,9 @@ static void ocrdma_dealloc_ucontext_pd(struct ocrdma_ucontext *uctx)
                pr_err("%s(%d) Freeing in use pdid=0x%x.\n",
                       __func__, dev->id, pd->id);
        }
-       kfree(uctx->cntxt_pd);
        uctx->cntxt_pd = NULL;
        _ocrdma_dealloc_pd(dev, pd);
+       kfree(pd);
 }
 
 static struct ocrdma_pd *ocrdma_get_ucontext_pd(struct ocrdma_ucontext *uctx)
index 38a37770c01627cd3baaf9e9a270a491b2a5655e..3705c6b8b2237105997082ee0173e1130edae9fa 100644 (file)
@@ -214,6 +214,7 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
 
                }
                usnic_uiom_free_dev_list(dev_list);
+               dev_list = NULL;
        }
 
        /* Try to find resources on an unused vf */
@@ -239,6 +240,8 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
 qp_grp_check:
        if (IS_ERR_OR_NULL(qp_grp)) {
                usnic_err("Failed to allocate qp_grp\n");
+               if (usnic_ib_share_vf)
+                       usnic_uiom_free_dev_list(dev_list);
                return ERR_PTR(qp_grp ? PTR_ERR(qp_grp) : -ENOMEM);
        }
        return qp_grp;
index 1b83d140742f397ddcbbf0054914187b0430a566..bcda17012aee8fa433cbc3f31896613e3e6e2606 100644 (file)
@@ -325,7 +325,9 @@ static struct arm_smmu_device *qcom_smmu_create(struct arm_smmu_device *smmu,
 }
 
 static const struct of_device_id __maybe_unused qcom_smmu_impl_of_match[] = {
+       { .compatible = "qcom,msm8998-smmu-v2" },
        { .compatible = "qcom,sc7180-smmu-500" },
+       { .compatible = "qcom,sdm630-smmu-v2" },
        { .compatible = "qcom,sdm845-smmu-500" },
        { .compatible = "qcom,sm8150-smmu-500" },
        { .compatible = "qcom,sm8250-smmu-500" },
index 65cf06d70bf4ed900bb0a07ad36c63c6aeca406e..f665322a09919fbaea5dd3eae59c7ac87a7fe04d 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/dmi.h>
 #include <linux/pci-ats.h>
 #include <linux/memblock.h>
-#include <linux/dma-map-ops.h>
 #include <linux/dma-direct.h>
 #include <linux/crash_dump.h>
 #include <linux/numa.h>
index 790ef3497e7e3557a1fcf9cfad0dd7d67d73a382..18a9f05df4079b1b3ee2d19f8a748536cbec360e 100644 (file)
@@ -118,8 +118,10 @@ void intel_svm_check(struct intel_iommu *iommu)
        iommu->flags |= VTD_FLAG_SVM_CAPABLE;
 }
 
-static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_dev *sdev,
-                               unsigned long address, unsigned long pages, int ih)
+static void __flush_svm_range_dev(struct intel_svm *svm,
+                                 struct intel_svm_dev *sdev,
+                                 unsigned long address,
+                                 unsigned long pages, int ih)
 {
        struct qi_desc desc;
 
@@ -170,6 +172,22 @@ static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_d
        }
 }
 
+static void intel_flush_svm_range_dev(struct intel_svm *svm,
+                                     struct intel_svm_dev *sdev,
+                                     unsigned long address,
+                                     unsigned long pages, int ih)
+{
+       unsigned long shift = ilog2(__roundup_pow_of_two(pages));
+       unsigned long align = (1ULL << (VTD_PAGE_SHIFT + shift));
+       unsigned long start = ALIGN_DOWN(address, align);
+       unsigned long end = ALIGN(address + (pages << VTD_PAGE_SHIFT), align);
+
+       while (start < end) {
+               __flush_svm_range_dev(svm, sdev, start, align >> VTD_PAGE_SHIFT, ih);
+               start += align;
+       }
+}
+
 static void intel_flush_svm_range(struct intel_svm *svm, unsigned long address,
                                unsigned long pages, int ih)
 {
index b7e2d96666142eb948924a8112ed02e2c3f779f1..9e44c09f6410890f43faaad328e7edea0f5da986 100644 (file)
@@ -605,6 +605,7 @@ config DM_INTEGRITY
        select BLK_DEV_INTEGRITY
        select DM_BUFIO
        select CRYPTO
+       select CRYPTO_SKCIPHER
        select ASYNC_XOR
        help
          This device-mapper target emulates a block device that has
@@ -622,6 +623,7 @@ config DM_ZONED
        tristate "Drive-managed zoned block device target support"
        depends on BLK_DEV_DM
        depends on BLK_DEV_ZONED
+       select CRC32
        help
          This device-mapper target takes a host-managed or host-aware zoned
          block device and exposes most of its capacity as a regular block
index 9c1a86bde658e48b67dcc67058d01de0c15d6e12..fce4cbf9529d6c85e5f7df6e99eb71db2c1df053 100644 (file)
@@ -1534,6 +1534,12 @@ sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
 }
 EXPORT_SYMBOL_GPL(dm_bufio_get_device_size);
 
+struct dm_io_client *dm_bufio_get_dm_io_client(struct dm_bufio_client *c)
+{
+       return c->dm_io;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_dm_io_client);
+
 sector_t dm_bufio_get_block_number(struct dm_buffer *b)
 {
        return b->block;
index 53791138d78bf4b5296f3aa400f517b60aabe9f4..5a55617a08e687c0ef2f454d6b8754f8af0bfade 100644 (file)
@@ -1454,13 +1454,16 @@ static int crypt_convert_block_skcipher(struct crypt_config *cc,
 static void kcryptd_async_done(struct crypto_async_request *async_req,
                               int error);
 
-static void crypt_alloc_req_skcipher(struct crypt_config *cc,
+static int crypt_alloc_req_skcipher(struct crypt_config *cc,
                                     struct convert_context *ctx)
 {
        unsigned key_index = ctx->cc_sector & (cc->tfms_count - 1);
 
-       if (!ctx->r.req)
-               ctx->r.req = mempool_alloc(&cc->req_pool, GFP_NOIO);
+       if (!ctx->r.req) {
+               ctx->r.req = mempool_alloc(&cc->req_pool, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
+               if (!ctx->r.req)
+                       return -ENOMEM;
+       }
 
        skcipher_request_set_tfm(ctx->r.req, cc->cipher_tfm.tfms[key_index]);
 
@@ -1471,13 +1474,18 @@ static void crypt_alloc_req_skcipher(struct crypt_config *cc,
        skcipher_request_set_callback(ctx->r.req,
            CRYPTO_TFM_REQ_MAY_BACKLOG,
            kcryptd_async_done, dmreq_of_req(cc, ctx->r.req));
+
+       return 0;
 }
 
-static void crypt_alloc_req_aead(struct crypt_config *cc,
+static int crypt_alloc_req_aead(struct crypt_config *cc,
                                 struct convert_context *ctx)
 {
-       if (!ctx->r.req_aead)
-               ctx->r.req_aead = mempool_alloc(&cc->req_pool, GFP_NOIO);
+       if (!ctx->r.req_aead) {
+               ctx->r.req_aead = mempool_alloc(&cc->req_pool, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
+               if (!ctx->r.req_aead)
+                       return -ENOMEM;
+       }
 
        aead_request_set_tfm(ctx->r.req_aead, cc->cipher_tfm.tfms_aead[0]);
 
@@ -1488,15 +1496,17 @@ static void crypt_alloc_req_aead(struct crypt_config *cc,
        aead_request_set_callback(ctx->r.req_aead,
            CRYPTO_TFM_REQ_MAY_BACKLOG,
            kcryptd_async_done, dmreq_of_req(cc, ctx->r.req_aead));
+
+       return 0;
 }
 
-static void crypt_alloc_req(struct crypt_config *cc,
+static int crypt_alloc_req(struct crypt_config *cc,
                            struct convert_context *ctx)
 {
        if (crypt_integrity_aead(cc))
-               crypt_alloc_req_aead(cc, ctx);
+               return crypt_alloc_req_aead(cc, ctx);
        else
-               crypt_alloc_req_skcipher(cc, ctx);
+               return crypt_alloc_req_skcipher(cc, ctx);
 }
 
 static void crypt_free_req_skcipher(struct crypt_config *cc,
@@ -1529,17 +1539,28 @@ static void crypt_free_req(struct crypt_config *cc, void *req, struct bio *base_
  * Encrypt / decrypt data from one bio to another one (can be the same one)
  */
 static blk_status_t crypt_convert(struct crypt_config *cc,
-                        struct convert_context *ctx, bool atomic)
+                        struct convert_context *ctx, bool atomic, bool reset_pending)
 {
        unsigned int tag_offset = 0;
        unsigned int sector_step = cc->sector_size >> SECTOR_SHIFT;
        int r;
 
-       atomic_set(&ctx->cc_pending, 1);
+       /*
+        * if reset_pending is set we are dealing with the bio for the first time,
+        * else we're continuing to work on the previous bio, so don't mess with
+        * the cc_pending counter
+        */
+       if (reset_pending)
+               atomic_set(&ctx->cc_pending, 1);
 
        while (ctx->iter_in.bi_size && ctx->iter_out.bi_size) {
 
-               crypt_alloc_req(cc, ctx);
+               r = crypt_alloc_req(cc, ctx);
+               if (r) {
+                       complete(&ctx->restart);
+                       return BLK_STS_DEV_RESOURCE;
+               }
+
                atomic_inc(&ctx->cc_pending);
 
                if (crypt_integrity_aead(cc))
@@ -1553,7 +1574,25 @@ static blk_status_t crypt_convert(struct crypt_config *cc,
                 * but the driver request queue is full, let's wait.
                 */
                case -EBUSY:
-                       wait_for_completion(&ctx->restart);
+                       if (in_interrupt()) {
+                               if (try_wait_for_completion(&ctx->restart)) {
+                                       /*
+                                        * we don't have to block to wait for completion,
+                                        * so proceed
+                                        */
+                               } else {
+                                       /*
+                                        * we can't wait for completion without blocking
+                                        * exit and continue processing in a workqueue
+                                        */
+                                       ctx->r.req = NULL;
+                                       ctx->cc_sector += sector_step;
+                                       tag_offset++;
+                                       return BLK_STS_DEV_RESOURCE;
+                               }
+                       } else {
+                               wait_for_completion(&ctx->restart);
+                       }
                        reinit_completion(&ctx->restart);
                        fallthrough;
                /*
@@ -1691,6 +1730,12 @@ static void crypt_inc_pending(struct dm_crypt_io *io)
        atomic_inc(&io->io_pending);
 }
 
+static void kcryptd_io_bio_endio(struct work_struct *work)
+{
+       struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
+       bio_endio(io->base_bio);
+}
+
 /*
  * One of the bios was finished. Check for completion of
  * the whole request and correctly clean up the buffer.
@@ -1713,7 +1758,23 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
                kfree(io->integrity_metadata);
 
        base_bio->bi_status = error;
-       bio_endio(base_bio);
+
+       /*
+        * If we are running this function from our tasklet,
+        * we can't call bio_endio() here, because it will call
+        * clone_endio() from dm.c, which in turn will
+        * free the current struct dm_crypt_io structure with
+        * our tasklet. In this case we need to delay bio_endio()
+        * execution to after the tasklet is done and dequeued.
+        */
+       if (tasklet_trylock(&io->tasklet)) {
+               tasklet_unlock(&io->tasklet);
+               bio_endio(base_bio);
+               return;
+       }
+
+       INIT_WORK(&io->work, kcryptd_io_bio_endio);
+       queue_work(cc->io_queue, &io->work);
 }
 
 /*
@@ -1945,6 +2006,37 @@ static bool kcryptd_crypt_write_inline(struct crypt_config *cc,
        }
 }
 
+static void kcryptd_crypt_write_continue(struct work_struct *work)
+{
+       struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
+       struct crypt_config *cc = io->cc;
+       struct convert_context *ctx = &io->ctx;
+       int crypt_finished;
+       sector_t sector = io->sector;
+       blk_status_t r;
+
+       wait_for_completion(&ctx->restart);
+       reinit_completion(&ctx->restart);
+
+       r = crypt_convert(cc, &io->ctx, true, false);
+       if (r)
+               io->error = r;
+       crypt_finished = atomic_dec_and_test(&ctx->cc_pending);
+       if (!crypt_finished && kcryptd_crypt_write_inline(cc, ctx)) {
+               /* Wait for completion signaled by kcryptd_async_done() */
+               wait_for_completion(&ctx->restart);
+               crypt_finished = 1;
+       }
+
+       /* Encryption was already finished, submit io now */
+       if (crypt_finished) {
+               kcryptd_crypt_write_io_submit(io, 0);
+               io->sector = sector;
+       }
+
+       crypt_dec_pending(io);
+}
+
 static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
 {
        struct crypt_config *cc = io->cc;
@@ -1973,7 +2065,17 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
 
        crypt_inc_pending(io);
        r = crypt_convert(cc, ctx,
-                         test_bit(DM_CRYPT_NO_WRITE_WORKQUEUE, &cc->flags));
+                         test_bit(DM_CRYPT_NO_WRITE_WORKQUEUE, &cc->flags), true);
+       /*
+        * Crypto API backlogged the request, because its queue was full
+        * and we're in softirq context, so continue from a workqueue
+        * (TODO: is it actually possible to be in softirq in the write path?)
+        */
+       if (r == BLK_STS_DEV_RESOURCE) {
+               INIT_WORK(&io->work, kcryptd_crypt_write_continue);
+               queue_work(cc->crypt_queue, &io->work);
+               return;
+       }
        if (r)
                io->error = r;
        crypt_finished = atomic_dec_and_test(&ctx->cc_pending);
@@ -1998,6 +2100,25 @@ static void kcryptd_crypt_read_done(struct dm_crypt_io *io)
        crypt_dec_pending(io);
 }
 
+static void kcryptd_crypt_read_continue(struct work_struct *work)
+{
+       struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
+       struct crypt_config *cc = io->cc;
+       blk_status_t r;
+
+       wait_for_completion(&io->ctx.restart);
+       reinit_completion(&io->ctx.restart);
+
+       r = crypt_convert(cc, &io->ctx, true, false);
+       if (r)
+               io->error = r;
+
+       if (atomic_dec_and_test(&io->ctx.cc_pending))
+               kcryptd_crypt_read_done(io);
+
+       crypt_dec_pending(io);
+}
+
 static void kcryptd_crypt_read_convert(struct dm_crypt_io *io)
 {
        struct crypt_config *cc = io->cc;
@@ -2009,7 +2130,16 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io)
                           io->sector);
 
        r = crypt_convert(cc, &io->ctx,
-                         test_bit(DM_CRYPT_NO_READ_WORKQUEUE, &cc->flags));
+                         test_bit(DM_CRYPT_NO_READ_WORKQUEUE, &cc->flags), true);
+       /*
+        * Crypto API backlogged the request, because its queue was full
+        * and we're in softirq context, so continue from a workqueue
+        */
+       if (r == BLK_STS_DEV_RESOURCE) {
+               INIT_WORK(&io->work, kcryptd_crypt_read_continue);
+               queue_work(cc->crypt_queue, &io->work);
+               return;
+       }
        if (r)
                io->error = r;
 
@@ -2091,8 +2221,12 @@ static void kcryptd_queue_crypt(struct dm_crypt_io *io)
 
        if ((bio_data_dir(io->base_bio) == READ && test_bit(DM_CRYPT_NO_READ_WORKQUEUE, &cc->flags)) ||
            (bio_data_dir(io->base_bio) == WRITE && test_bit(DM_CRYPT_NO_WRITE_WORKQUEUE, &cc->flags))) {
-               if (in_irq()) {
-                       /* Crypto API's "skcipher_walk_first() refuses to work in hard IRQ context */
+               /*
+                * in_irq(): Crypto API's skcipher_walk_first() refuses to work in hard IRQ context.
+                * irqs_disabled(): the kernel may run some IO completion from the idle thread, but
+                * it is being executed with irqs disabled.
+                */
+               if (in_irq() || irqs_disabled()) {
                        tasklet_init(&io->tasklet, kcryptd_crypt_tasklet, (unsigned long)&io->work);
                        tasklet_schedule(&io->tasklet);
                        return;
index 5a7a1b90e671cfa09c64dc268547f31101f18cd9..b64fede032dc5314eda9ccf353738ef7617fb89a 100644 (file)
@@ -257,8 +257,9 @@ struct dm_integrity_c {
        bool journal_uptodate;
        bool just_formatted;
        bool recalculate_flag;
-       bool fix_padding;
        bool discard;
+       bool fix_padding;
+       bool legacy_recalculate;
 
        struct alg_spec internal_hash_alg;
        struct alg_spec journal_crypt_alg;
@@ -386,6 +387,14 @@ static int dm_integrity_failed(struct dm_integrity_c *ic)
        return READ_ONCE(ic->failed);
 }
 
+static bool dm_integrity_disable_recalculate(struct dm_integrity_c *ic)
+{
+       if ((ic->internal_hash_alg.key || ic->journal_mac_alg.key) &&
+           !ic->legacy_recalculate)
+               return true;
+       return false;
+}
+
 static commit_id_t dm_integrity_commit_id(struct dm_integrity_c *ic, unsigned i,
                                          unsigned j, unsigned char seq)
 {
@@ -1379,12 +1388,52 @@ thorough_test:
 #undef MAY_BE_HASH
 }
 
-static void dm_integrity_flush_buffers(struct dm_integrity_c *ic)
+struct flush_request {
+       struct dm_io_request io_req;
+       struct dm_io_region io_reg;
+       struct dm_integrity_c *ic;
+       struct completion comp;
+};
+
+static void flush_notify(unsigned long error, void *fr_)
+{
+       struct flush_request *fr = fr_;
+       if (unlikely(error != 0))
+               dm_integrity_io_error(fr->ic, "flusing disk cache", -EIO);
+       complete(&fr->comp);
+}
+
+static void dm_integrity_flush_buffers(struct dm_integrity_c *ic, bool flush_data)
 {
        int r;
+
+       struct flush_request fr;
+
+       if (!ic->meta_dev)
+               flush_data = false;
+       if (flush_data) {
+               fr.io_req.bi_op = REQ_OP_WRITE,
+               fr.io_req.bi_op_flags = REQ_PREFLUSH | REQ_SYNC,
+               fr.io_req.mem.type = DM_IO_KMEM,
+               fr.io_req.mem.ptr.addr = NULL,
+               fr.io_req.notify.fn = flush_notify,
+               fr.io_req.notify.context = &fr;
+               fr.io_req.client = dm_bufio_get_dm_io_client(ic->bufio),
+               fr.io_reg.bdev = ic->dev->bdev,
+               fr.io_reg.sector = 0,
+               fr.io_reg.count = 0,
+               fr.ic = ic;
+               init_completion(&fr.comp);
+               r = dm_io(&fr.io_req, 1, &fr.io_reg, NULL);
+               BUG_ON(r);
+       }
+
        r = dm_bufio_write_dirty_buffers(ic->bufio);
        if (unlikely(r))
                dm_integrity_io_error(ic, "writing tags", r);
+
+       if (flush_data)
+               wait_for_completion(&fr.comp);
 }
 
 static void sleep_on_endio_wait(struct dm_integrity_c *ic)
@@ -2110,7 +2159,7 @@ offload_to_thread:
 
        if (unlikely(dio->op == REQ_OP_DISCARD) && likely(ic->mode != 'D')) {
                integrity_metadata(&dio->work);
-               dm_integrity_flush_buffers(ic);
+               dm_integrity_flush_buffers(ic, false);
 
                dio->in_flight = (atomic_t)ATOMIC_INIT(1);
                dio->completion = NULL;
@@ -2195,7 +2244,7 @@ static void integrity_commit(struct work_struct *w)
        flushes = bio_list_get(&ic->flush_bio_list);
        if (unlikely(ic->mode != 'J')) {
                spin_unlock_irq(&ic->endio_wait.lock);
-               dm_integrity_flush_buffers(ic);
+               dm_integrity_flush_buffers(ic, true);
                goto release_flush_bios;
        }
 
@@ -2409,7 +2458,7 @@ skip_io:
        complete_journal_op(&comp);
        wait_for_completion_io(&comp.comp);
 
-       dm_integrity_flush_buffers(ic);
+       dm_integrity_flush_buffers(ic, true);
 }
 
 static void integrity_writer(struct work_struct *w)
@@ -2451,7 +2500,7 @@ static void recalc_write_super(struct dm_integrity_c *ic)
 {
        int r;
 
-       dm_integrity_flush_buffers(ic);
+       dm_integrity_flush_buffers(ic, false);
        if (dm_integrity_failed(ic))
                return;
 
@@ -2654,7 +2703,7 @@ static void bitmap_flush_work(struct work_struct *work)
        unsigned long limit;
        struct bio *bio;
 
-       dm_integrity_flush_buffers(ic);
+       dm_integrity_flush_buffers(ic, false);
 
        range.logical_sector = 0;
        range.n_sectors = ic->provided_data_sectors;
@@ -2663,9 +2712,7 @@ static void bitmap_flush_work(struct work_struct *work)
        add_new_range_and_wait(ic, &range);
        spin_unlock_irq(&ic->endio_wait.lock);
 
-       dm_integrity_flush_buffers(ic);
-       if (ic->meta_dev)
-               blkdev_issue_flush(ic->dev->bdev, GFP_NOIO);
+       dm_integrity_flush_buffers(ic, true);
 
        limit = ic->provided_data_sectors;
        if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
@@ -2934,11 +2981,11 @@ static void dm_integrity_postsuspend(struct dm_target *ti)
                if (ic->meta_dev)
                        queue_work(ic->writer_wq, &ic->writer_work);
                drain_workqueue(ic->writer_wq);
-               dm_integrity_flush_buffers(ic);
+               dm_integrity_flush_buffers(ic, true);
        }
 
        if (ic->mode == 'B') {
-               dm_integrity_flush_buffers(ic);
+               dm_integrity_flush_buffers(ic, true);
 #if 1
                /* set to 0 to test bitmap replay code */
                init_journal(ic, 0, ic->journal_sections, 0);
@@ -3102,6 +3149,7 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
                arg_count += !!ic->journal_crypt_alg.alg_string;
                arg_count += !!ic->journal_mac_alg.alg_string;
                arg_count += (ic->sb->flags & cpu_to_le32(SB_FLAG_FIXED_PADDING)) != 0;
+               arg_count += ic->legacy_recalculate;
                DMEMIT("%s %llu %u %c %u", ic->dev->name, ic->start,
                       ic->tag_size, ic->mode, arg_count);
                if (ic->meta_dev)
@@ -3125,6 +3173,8 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
                }
                if ((ic->sb->flags & cpu_to_le32(SB_FLAG_FIXED_PADDING)) != 0)
                        DMEMIT(" fix_padding");
+               if (ic->legacy_recalculate)
+                       DMEMIT(" legacy_recalculate");
 
 #define EMIT_ALG(a, n)                                                 \
                do {                                                    \
@@ -3754,7 +3804,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        unsigned extra_args;
        struct dm_arg_set as;
        static const struct dm_arg _args[] = {
-               {0, 9, "Invalid number of feature args"},
+               {0, 16, "Invalid number of feature args"},
        };
        unsigned journal_sectors, interleave_sectors, buffer_sectors, journal_watermark, sync_msec;
        bool should_write_sb;
@@ -3902,6 +3952,8 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
                        ic->discard = true;
                } else if (!strcmp(opt_string, "fix_padding")) {
                        ic->fix_padding = true;
+               } else if (!strcmp(opt_string, "legacy_recalculate")) {
+                       ic->legacy_recalculate = true;
                } else {
                        r = -EINVAL;
                        ti->error = "Invalid argument";
@@ -4197,6 +4249,20 @@ try_smaller_buffer:
                        r = -ENOMEM;
                        goto bad;
                }
+       } else {
+               if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
+                       ti->error = "Recalculate can only be specified with internal_hash";
+                       r = -EINVAL;
+                       goto bad;
+               }
+       }
+
+       if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING) &&
+           le64_to_cpu(ic->sb->recalc_sector) < ic->provided_data_sectors &&
+           dm_integrity_disable_recalculate(ic)) {
+               ti->error = "Recalculating with HMAC is disabled for security reasons - if you really need it, use the argument \"legacy_recalculate\"";
+               r = -EOPNOTSUPP;
+               goto bad;
        }
 
        ic->bufio = dm_bufio_client_create(ic->meta_dev ? ic->meta_dev->bdev : ic->dev->bdev,
index 23c38777e8f63892880bc608509c147836a5407a..cab12b2251bac21c2717912d7228132e4860b821 100644 (file)
@@ -3729,10 +3729,10 @@ static void raid_io_hints(struct dm_target *ti, struct queue_limits *limits)
        blk_limits_io_opt(limits, chunk_size_bytes * mddev_data_stripes(rs));
 
        /*
-        * RAID1 and RAID10 personalities require bio splitting,
-        * RAID0/4/5/6 don't and process large discard bios properly.
+        * RAID0 and RAID10 personalities require bio splitting,
+        * RAID1/4/5/6 don't and process large discard bios properly.
         */
-       if (rs_is_raid1(rs) || rs_is_raid10(rs)) {
+       if (rs_is_raid0(rs) || rs_is_raid10(rs)) {
                limits->discard_granularity = chunk_size_bytes;
                limits->max_discard_sectors = rs->md.chunk_sectors;
        }
index 4668b2cd98f4e246f217674839f2f6b82a834fef..11890db71f3fe30a6a01958ae1da28ceb5d76d79 100644 (file)
@@ -141,6 +141,11 @@ struct dm_snapshot {
         * for them to be committed.
         */
        struct bio_list bios_queued_during_merge;
+
+       /*
+        * Flush data after merge.
+        */
+       struct bio flush_bio;
 };
 
 /*
@@ -1121,6 +1126,17 @@ shut:
 
 static void error_bios(struct bio *bio);
 
+static int flush_data(struct dm_snapshot *s)
+{
+       struct bio *flush_bio = &s->flush_bio;
+
+       bio_reset(flush_bio);
+       bio_set_dev(flush_bio, s->origin->bdev);
+       flush_bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+
+       return submit_bio_wait(flush_bio);
+}
+
 static void merge_callback(int read_err, unsigned long write_err, void *context)
 {
        struct dm_snapshot *s = context;
@@ -1134,6 +1150,11 @@ static void merge_callback(int read_err, unsigned long write_err, void *context)
                goto shut;
        }
 
+       if (flush_data(s) < 0) {
+               DMERR("Flush after merge failed: shutting down merge");
+               goto shut;
+       }
+
        if (s->store->type->commit_merge(s->store,
                                         s->num_merging_chunks) < 0) {
                DMERR("Write error in exception store: shutting down merge");
@@ -1318,6 +1339,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        s->first_merging_chunk = 0;
        s->num_merging_chunks = 0;
        bio_list_init(&s->bios_queued_during_merge);
+       bio_init(&s->flush_bio, NULL, 0);
 
        /* Allocate hash table for COW data */
        if (init_hash_tables(s)) {
@@ -1504,6 +1526,8 @@ static void snapshot_dtr(struct dm_target *ti)
 
        dm_exception_store_destroy(s->store);
 
+       bio_uninit(&s->flush_bio);
+
        dm_put_device(ti, s->cow);
 
        dm_put_device(ti, s->origin);
index 188f41287f180baf5a8ea7bc8defb02717a1da5f..4acf2342f7adf0896077835eef7b1332965db9bb 100644 (file)
@@ -363,14 +363,23 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
 {
        int r;
        dev_t dev;
+       unsigned int major, minor;
+       char dummy;
        struct dm_dev_internal *dd;
        struct dm_table *t = ti->table;
 
        BUG_ON(!t);
 
-       dev = dm_get_dev_t(path);
-       if (!dev)
-               return -ENODEV;
+       if (sscanf(path, "%u:%u%c", &major, &minor, &dummy) == 2) {
+               /* Extract the major/minor numbers */
+               dev = MKDEV(major, minor);
+               if (MAJOR(dev) != major || MINOR(dev) != minor)
+                       return -EOVERFLOW;
+       } else {
+               dev = dm_get_dev_t(path);
+               if (!dev)
+                       return -ENODEV;
+       }
 
        dd = find_device(&t->devices, dev);
        if (!dd) {
index b3c3c8b4cb428f587dbe9840b276fdc14d8fd630..7bac564f3faa6e1b49899b72e1d5286efcff840b 100644 (file)
@@ -562,7 +562,7 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
                 * subset of the parent bdev; require extra privileges.
                 */
                if (!capable(CAP_SYS_RAWIO)) {
-                       DMWARN_LIMIT(
+                       DMDEBUG_LIMIT(
        "%s: sending ioctl %x to DM device without required privilege.",
                                current->comm, cmd);
                        r = -ENOIOCTLCMD;
index de7cb0369c308f9fdd664552c9f14c985f3f7c1e..002426e3cf76c9d2f0fec4c35f757a7153717710 100644 (file)
@@ -384,8 +384,10 @@ static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card)
                     "merging was advertised but not possible");
        blk_queue_max_segments(mq->queue, mmc_get_max_segments(host));
 
-       if (mmc_card_mmc(card))
+       if (mmc_card_mmc(card) && card->ext_csd.data_sector_size) {
                block_size = card->ext_csd.data_sector_size;
+               WARN_ON(block_size != 512 && block_size != 4096);
+       }
 
        blk_queue_logical_block_size(mq->queue, block_size);
        /*
index bbf3496f44955f333ed2085499d99999403542ab..f9780c65ebe98a76d94fe014b3299ccde99ddd23 100644 (file)
@@ -314,11 +314,7 @@ err_clk:
 
 static void sdhci_brcmstb_shutdown(struct platform_device *pdev)
 {
-       int ret;
-
-       ret = sdhci_pltfm_unregister(pdev);
-       if (ret)
-               dev_err(&pdev->dev, "failed to shutdown\n");
+       sdhci_pltfm_suspend(&pdev->dev);
 }
 
 MODULE_DEVICE_TABLE(of, sdhci_brcm_of_match);
index 4b673792b5a42ef9b2a5a20ee8152393e93087ad..d90020ed362273a47bdbabde4423fb283a4098be 100644 (file)
@@ -16,6 +16,8 @@
 
 #include "sdhci-pltfm.h"
 
+#define SDHCI_DWCMSHC_ARG2_STUFF       GENMASK(31, 16)
+
 /* DWCMSHC specific Mode Select value */
 #define DWCMSHC_CTRL_HS400             0x7
 
@@ -49,6 +51,29 @@ static void dwcmshc_adma_write_desc(struct sdhci_host *host, void **desc,
        sdhci_adma_write_desc(host, desc, addr, len, cmd);
 }
 
+static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc,
+                                    struct mmc_request *mrq)
+{
+       struct sdhci_host *host = mmc_priv(mmc);
+
+       /*
+        * No matter V4 is enabled or not, ARGUMENT2 register is 32-bit
+        * block count register which doesn't support stuff bits of
+        * CMD23 argument on dwcmsch host controller.
+        */
+       if (mrq->sbc && (mrq->sbc->arg & SDHCI_DWCMSHC_ARG2_STUFF))
+               host->flags &= ~SDHCI_AUTO_CMD23;
+       else
+               host->flags |= SDHCI_AUTO_CMD23;
+}
+
+static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+       dwcmshc_check_auto_cmd23(mmc, mrq);
+
+       sdhci_request(mmc, mrq);
+}
+
 static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
                                      unsigned int timing)
 {
@@ -133,6 +158,8 @@ static int dwcmshc_probe(struct platform_device *pdev)
 
        sdhci_get_of_property(pdev);
 
+       host->mmc_host_ops.request = dwcmshc_request;
+
        err = sdhci_add_host(host);
        if (err)
                goto err_clk;
index c67611fdaa8aa13d5cb82b7dc345ce5ce486a3ae..d19eef5f725f88d2df7847e6cf97e3669d52cbfa 100644 (file)
@@ -168,7 +168,12 @@ static void xenon_reset_exit(struct sdhci_host *host,
        /* Disable tuning request and auto-retuning again */
        xenon_retune_setup(host);
 
-       xenon_set_acg(host, true);
+       /*
+        * The ACG should be turned off at the early init time, in order
+        * to solve a possible issues with the 1.8V regulator stabilization.
+        * The feature is enabled in later stage.
+        */
+       xenon_set_acg(host, false);
 
        xenon_set_sdclk_off_idle(host, sdhc_id, false);
 
index 5cdf05bcbf8faacfb24ee71758ff0182a3517836..3fa8c22d3f36af1da132b9f3932f48101af0ccd7 100644 (file)
@@ -1615,7 +1615,7 @@ static int gpmi_ecc_read_page_raw(struct nand_chip *chip, uint8_t *buf,
        /* Extract interleaved payload data and ECC bits */
        for (step = 0; step < nfc_geo->ecc_chunk_count; step++) {
                if (buf)
-                       nand_extract_bits(buf, step * eccsize, tmp_buf,
+                       nand_extract_bits(buf, step * eccsize * 8, tmp_buf,
                                          src_bit_off, eccsize * 8);
                src_bit_off += eccsize * 8;
 
index fdb112e8a90d294e64632782eacad0010184d2cb..a304fda5d1fa5684be2b0a8a48caaa5cd9eaaa95 100644 (file)
@@ -579,7 +579,7 @@ static int ebu_nand_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct ebu_nand_controller *ebu_host;
        struct nand_chip *nand;
-       struct mtd_info *mtd = NULL;
+       struct mtd_info *mtd;
        struct resource *res;
        char *resname;
        int ret;
@@ -647,12 +647,13 @@ static int ebu_nand_probe(struct platform_device *pdev)
               ebu_host->ebu + EBU_ADDR_SEL(cs));
 
        nand_set_flash_node(&ebu_host->chip, dev->of_node);
+
+       mtd = nand_to_mtd(&ebu_host->chip);
        if (!mtd->name) {
                dev_err(ebu_host->dev, "NAND label property is mandatory\n");
                return -EINVAL;
        }
 
-       mtd = nand_to_mtd(&ebu_host->chip);
        mtd->dev.parent = dev;
        ebu_host->dev = dev;
 
index f2b9250c0ea830b4096c2011e4442498fca95944..0750121ac371c73081160bf11a5548dcc38b8f50 100644 (file)
@@ -2210,6 +2210,9 @@ static int ns_attach_chip(struct nand_chip *chip)
 {
        unsigned int eccsteps, eccbytes;
 
+       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+       chip->ecc.algo = bch ? NAND_ECC_ALGO_BCH : NAND_ECC_ALGO_HAMMING;
+
        if (!bch)
                return 0;
 
@@ -2233,8 +2236,6 @@ static int ns_attach_chip(struct nand_chip *chip)
                return -EINVAL;
        }
 
-       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-       chip->ecc.algo = NAND_ECC_ALGO_BCH;
        chip->ecc.size = 512;
        chip->ecc.strength = bch;
        chip->ecc.bytes = eccbytes;
@@ -2273,8 +2274,6 @@ static int __init ns_init_module(void)
        nsmtd       = nand_to_mtd(chip);
        nand_set_controller_data(chip, (void *)ns);
 
-       chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
-       chip->ecc.algo   = NAND_ECC_ALGO_HAMMING;
        /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */
        /* and 'badblocks' parameters to work */
        chip->options   |= NAND_SKIP_BBTSCAN;
index fbb9955f2467118355e5f0217859d9cbd8de1a69..2c3e65cb68f33053e3cb1901c4f8be876bd00163 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand-ecc-sw-bch.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/omap-dma.h>
@@ -1866,18 +1867,19 @@ static const struct mtd_ooblayout_ops omap_ooblayout_ops = {
 static int omap_sw_ooblayout_ecc(struct mtd_info *mtd, int section,
                                 struct mtd_oob_region *oobregion)
 {
-       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct nand_device *nand = mtd_to_nanddev(mtd);
+       const struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv;
        int off = BADBLOCK_MARKER_LENGTH;
 
-       if (section >= chip->ecc.steps)
+       if (section >= engine_conf->nsteps)
                return -ERANGE;
 
        /*
         * When SW correction is employed, one OMAP specific marker byte is
         * reserved after each ECC step.
         */
-       oobregion->offset = off + (section * (chip->ecc.bytes + 1));
-       oobregion->length = chip->ecc.bytes;
+       oobregion->offset = off + (section * (engine_conf->code_size + 1));
+       oobregion->length = engine_conf->code_size;
 
        return 0;
 }
@@ -1885,7 +1887,8 @@ static int omap_sw_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int omap_sw_ooblayout_free(struct mtd_info *mtd, int section,
                                  struct mtd_oob_region *oobregion)
 {
-       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct nand_device *nand = mtd_to_nanddev(mtd);
+       const struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv;
        int off = BADBLOCK_MARKER_LENGTH;
 
        if (section)
@@ -1895,7 +1898,7 @@ static int omap_sw_ooblayout_free(struct mtd_info *mtd, int section,
         * When SW correction is employed, one OMAP specific marker byte is
         * reserved after each ECC step.
         */
-       off += ((chip->ecc.bytes + 1) * chip->ecc.steps);
+       off += ((engine_conf->code_size + 1) * engine_conf->nsteps);
        if (off >= mtd->oobsize)
                return -ERANGE;
 
index 8ea545bb924d2b2ee83edfc8629b397d12f5bdf4..61d932c1b71806166c089a173182c33a7d4fcc1a 100644 (file)
@@ -343,6 +343,7 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand,
                                      const struct nand_page_io_req *req)
 {
        struct nand_device *nand = spinand_to_nand(spinand);
+       struct mtd_info *mtd = spinand_to_mtd(spinand);
        struct spi_mem_dirmap_desc *rdesc;
        unsigned int nbytes = 0;
        void *buf = NULL;
@@ -382,9 +383,16 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand,
                memcpy(req->databuf.in, spinand->databuf + req->dataoffs,
                       req->datalen);
 
-       if (req->ooblen)
-               memcpy(req->oobbuf.in, spinand->oobbuf + req->ooboffs,
-                      req->ooblen);
+       if (req->ooblen) {
+               if (req->mode == MTD_OPS_AUTO_OOB)
+                       mtd_ooblayout_get_databytes(mtd, req->oobbuf.in,
+                                                   spinand->oobbuf,
+                                                   req->ooboffs,
+                                                   req->ooblen);
+               else
+                       memcpy(req->oobbuf.in, spinand->oobbuf + req->ooboffs,
+                              req->ooblen);
+       }
 
        return 0;
 }
index 3486704c8a95736fe3b917ddbe85da6c9639dc9c..8b1ae023cb218f2db5bd3f58a28f6e91ccfa5104 100644 (file)
@@ -592,11 +592,11 @@ static void can_restart(struct net_device *dev)
 
        cf->can_id |= CAN_ERR_RESTARTED;
 
-       netif_rx_ni(skb);
-
        stats->rx_packets++;
        stats->rx_bytes += cf->len;
 
+       netif_rx_ni(skb);
+
 restart:
        netdev_dbg(dev, "restarted\n");
        priv->can_stats.restarts++;
index 36235afb0bc6628db8398d8b87451aba4611d5dd..f07e8b737d31ee04031082ca37c0f047f34d3cf3 100644 (file)
@@ -1491,7 +1491,7 @@ mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv,
        else
                skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cfd);
 
-       if (!cfd) {
+       if (!skb) {
                stats->rx_dropped++;
                return 0;
        }
index 61631f4fd92a1d2dea864873431d60beca8b4318..f347ecc79aef2d5395ecc44167fbdb999eb4edef 100644 (file)
@@ -514,11 +514,11 @@ static int pcan_usb_fd_decode_canmsg(struct pcan_usb_fd_if *usb_if,
        else
                memcpy(cfd->data, rm->d, cfd->len);
 
-       peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(rm->ts_low));
-
        netdev->stats.rx_packets++;
        netdev->stats.rx_bytes += cfd->len;
 
+       peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(rm->ts_low));
+
        return 0;
 }
 
@@ -580,11 +580,11 @@ static int pcan_usb_fd_decode_status(struct pcan_usb_fd_if *usb_if,
        if (!skb)
                return -ENOMEM;
 
-       peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(sm->ts_low));
-
        netdev->stats.rx_packets++;
        netdev->stats.rx_bytes += cf->len;
 
+       peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(sm->ts_low));
+
        return 0;
 }
 
index fa47bab510bb90cb35bcc56fe9d0275dccc57cf4..f9a524c5f6d62710722b920b615154670dfc8992 100644 (file)
@@ -39,6 +39,7 @@ static netdev_tx_t vxcan_xmit(struct sk_buff *skb, struct net_device *dev)
        struct net_device *peer;
        struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
        struct net_device_stats *peerstats, *srcstats = &dev->stats;
+       u8 len;
 
        if (can_dropped_invalid_skb(dev, skb))
                return NETDEV_TX_OK;
@@ -61,12 +62,13 @@ static netdev_tx_t vxcan_xmit(struct sk_buff *skb, struct net_device *dev)
        skb->dev        = peer;
        skb->ip_summed  = CHECKSUM_UNNECESSARY;
 
+       len = cfd->len;
        if (netif_rx_ni(skb) == NET_RX_SUCCESS) {
                srcstats->tx_packets++;
-               srcstats->tx_bytes += cfd->len;
+               srcstats->tx_bytes += len;
                peerstats = &peer->stats;
                peerstats->rx_packets++;
-               peerstats->rx_bytes += cfd->len;
+               peerstats->rx_bytes += len;
        }
 
 out_unlock:
index 288b5a5c3e0dbcae40788d27f9843cd06bf3624e..95c7fa171e35acd7a04886ca9e03408b77f3ce16 100644 (file)
@@ -1404,7 +1404,7 @@ int b53_vlan_prepare(struct dsa_switch *ds, int port,
            !(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED))
                return -EINVAL;
 
-       if (vlan->vid_end > dev->num_vlans)
+       if (vlan->vid_end >= dev->num_vlans)
                return -ERANGE;
 
        b53_enable_vlan(dev, true, ds->vlan_filtering);
index 66ddf67b87371d0a9c12667b700a6996710023f9..7b96396be609e7bb1331d63c6fd11a403922e0b7 100644 (file)
@@ -351,6 +351,10 @@ int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
                if (err)
                        return err;
 
+               err = mv88e6185_g1_stu_data_read(chip, entry);
+               if (err)
+                       return err;
+
                /* VTU DBNum[3:0] are located in VTU Operation 3:0
                 * VTU DBNum[5:4] are located in VTU Operation 9:8
                 */
index b1ae9eb8f24793a56089926fe78fedbbfa3399db..0404aafd5ce56ddc1c1ecac402d24dd2f9c51455 100644 (file)
@@ -2503,8 +2503,10 @@ static int bcm_sysport_probe(struct platform_device *pdev)
        priv = netdev_priv(dev);
 
        priv->clk = devm_clk_get_optional(&pdev->dev, "sw_sysport");
-       if (IS_ERR(priv->clk))
-               return PTR_ERR(priv->clk);
+       if (IS_ERR(priv->clk)) {
+               ret = PTR_ERR(priv->clk);
+               goto err_free_netdev;
+       }
 
        /* Allocate number of TX rings */
        priv->tx_rings = devm_kcalloc(&pdev->dev, txq,
index 9ff79d5d14c4c7559e4a54526c54e33987794b50..2f8b193a772dac6e6839fad460a24a174821e7a4 100644 (file)
@@ -2532,7 +2532,7 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
 
                if (rc && ((struct hwrm_err_output *)&resp)->cmd_err ==
                    NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
-                       install.flags |=
+                       install.flags =
                                cpu_to_le16(NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
 
                        rc = _hwrm_send_message_silent(bp, &install,
@@ -2546,6 +2546,7 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
                                 * UPDATE directory and try the flash again
                                 */
                                defrag_attempted = true;
+                               install.flags = 0;
                                rc = __bnxt_flash_nvram(bp->dev,
                                                        BNX_DIR_TYPE_UPDATE,
                                                        BNX_DIR_ORDINAL_FIRST,
index 8c8368c2f335cb3671dda19e7e58af64d5061ad5..64dbbb04b04346719b46e5e4214ce095d7c9947d 100644 (file)
@@ -222,8 +222,12 @@ int bnxt_get_ulp_msix_base(struct bnxt *bp)
 
 int bnxt_get_ulp_stat_ctxs(struct bnxt *bp)
 {
-       if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP))
-               return BNXT_MIN_ROCE_STAT_CTXS;
+       if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) {
+               struct bnxt_en_dev *edev = bp->edev;
+
+               if (edev->ulp_tbl[BNXT_ROCE_ULP].msix_requested)
+                       return BNXT_MIN_ROCE_STAT_CTXS;
+       }
 
        return 0;
 }
index 92473dda55d9f8238f6c5c3a6ebf168349b3f8b0..22a0220123adeba947911924d553fdf9c446402f 100644 (file)
 #define TCB_L2T_IX_M           0xfffULL
 #define TCB_L2T_IX_V(x)                ((x) << TCB_L2T_IX_S)
 
+#define TCB_T_FLAGS_W           1
+#define TCB_T_FLAGS_S           0
+#define TCB_T_FLAGS_M           0xffffffffffffffffULL
+#define TCB_T_FLAGS_V(x)        ((__u64)(x) << TCB_T_FLAGS_S)
+
+#define TCB_FIELD_COOKIE_TFLAG 1
+
 #define TCB_SMAC_SEL_W         0
 #define TCB_SMAC_SEL_S         24
 #define TCB_SMAC_SEL_M         0xffULL
index 72bb123d53db73e58875431784c2bf3fa351d594..9e237801364210ed337a135f2825b77e054037ab 100644 (file)
@@ -575,7 +575,11 @@ int send_tx_flowc_wr(struct sock *sk, int compl,
 void chtls_tcp_push(struct sock *sk, int flags);
 int chtls_push_frames(struct chtls_sock *csk, int comp);
 int chtls_set_tcb_tflag(struct sock *sk, unsigned int bit_pos, int val);
+void chtls_set_tcb_field_rpl_skb(struct sock *sk, u16 word,
+                                u64 mask, u64 val, u8 cookie,
+                                int through_l2t);
 int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 mode, int cipher_type);
+void chtls_set_quiesce_ctrl(struct sock *sk, int val);
 void skb_entail(struct sock *sk, struct sk_buff *skb, int flags);
 unsigned int keyid_to_addr(int start_addr, int keyid);
 void free_tls_keyid(struct sock *sk);
index 51dd030b3b3661eb2d2fa37f7416fadda447557e..e5cfbe196ba664decb2a32216a47a1803373d947 100644 (file)
@@ -32,6 +32,7 @@
 #include "chtls.h"
 #include "chtls_cm.h"
 #include "clip_tbl.h"
+#include "t4_tcb.h"
 
 /*
  * State transitions and actions for close.  Note that if we are in SYN_SENT
@@ -267,7 +268,9 @@ static void chtls_send_reset(struct sock *sk, int mode, struct sk_buff *skb)
        if (sk->sk_state != TCP_SYN_RECV)
                chtls_send_abort(sk, mode, skb);
        else
-               goto out;
+               chtls_set_tcb_field_rpl_skb(sk, TCB_T_FLAGS_W,
+                                           TCB_T_FLAGS_V(TCB_T_FLAGS_M), 0,
+                                           TCB_FIELD_COOKIE_TFLAG, 1);
 
        return;
 out:
@@ -1949,6 +1952,8 @@ static void chtls_close_con_rpl(struct sock *sk, struct sk_buff *skb)
                else if (tcp_sk(sk)->linger2 < 0 &&
                         !csk_flag_nochk(csk, CSK_ABORT_SHUTDOWN))
                        chtls_abort_conn(sk, skb);
+               else if (csk_flag_nochk(csk, CSK_TX_DATA_SENT))
+                       chtls_set_quiesce_ctrl(sk, 0);
                break;
        default:
                pr_info("close_con_rpl in bad state %d\n", sk->sk_state);
@@ -2292,6 +2297,28 @@ static int chtls_wr_ack(struct chtls_dev *cdev, struct sk_buff *skb)
        return 0;
 }
 
+static int chtls_set_tcb_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
+{
+       struct cpl_set_tcb_rpl *rpl = cplhdr(skb) + RSS_HDR;
+       unsigned int hwtid = GET_TID(rpl);
+       struct sock *sk;
+
+       sk = lookup_tid(cdev->tids, hwtid);
+
+       /* return EINVAL if socket doesn't exist */
+       if (!sk)
+               return -EINVAL;
+
+       /* Reusing the skb as size of cpl_set_tcb_field structure
+        * is greater than cpl_abort_req
+        */
+       if (TCB_COOKIE_G(rpl->cookie) == TCB_FIELD_COOKIE_TFLAG)
+               chtls_send_abort(sk, CPL_ABORT_SEND_RST, NULL);
+
+       kfree_skb(skb);
+       return 0;
+}
+
 chtls_handler_func chtls_handlers[NUM_CPL_CMDS] = {
        [CPL_PASS_OPEN_RPL]     = chtls_pass_open_rpl,
        [CPL_CLOSE_LISTSRV_RPL] = chtls_close_listsrv_rpl,
@@ -2304,5 +2331,6 @@ chtls_handler_func chtls_handlers[NUM_CPL_CMDS] = {
        [CPL_CLOSE_CON_RPL]     = chtls_conn_cpl,
        [CPL_ABORT_REQ_RSS]     = chtls_conn_cpl,
        [CPL_ABORT_RPL_RSS]     = chtls_conn_cpl,
-       [CPL_FW4_ACK]           = chtls_wr_ack,
+       [CPL_FW4_ACK]           = chtls_wr_ack,
+       [CPL_SET_TCB_RPL]       = chtls_set_tcb_rpl,
 };
index a4fb463af22ac335c425532787f4b8a7bb91e11d..1e67140b0f8013633566ca244c4a5d04b4869251 100644 (file)
@@ -88,6 +88,24 @@ static int chtls_set_tcb_field(struct sock *sk, u16 word, u64 mask, u64 val)
        return ret < 0 ? ret : 0;
 }
 
+void chtls_set_tcb_field_rpl_skb(struct sock *sk, u16 word,
+                                u64 mask, u64 val, u8 cookie,
+                                int through_l2t)
+{
+       struct sk_buff *skb;
+       unsigned int wrlen;
+
+       wrlen = sizeof(struct cpl_set_tcb_field) + sizeof(struct ulptx_idata);
+       wrlen = roundup(wrlen, 16);
+
+       skb = alloc_skb(wrlen, GFP_KERNEL | __GFP_NOFAIL);
+       if (!skb)
+               return;
+
+       __set_tcb_field(sk, skb, word, mask, val, cookie, 0);
+       send_or_defer(sk, tcp_sk(sk), skb, through_l2t);
+}
+
 /*
  * Set one of the t_flags bits in the TCB.
  */
@@ -113,6 +131,29 @@ static int chtls_set_tcb_quiesce(struct sock *sk, int val)
                                   TF_RX_QUIESCE_V(val));
 }
 
+void chtls_set_quiesce_ctrl(struct sock *sk, int val)
+{
+       struct chtls_sock *csk;
+       struct sk_buff *skb;
+       unsigned int wrlen;
+       int ret;
+
+       wrlen = sizeof(struct cpl_set_tcb_field) + sizeof(struct ulptx_idata);
+       wrlen = roundup(wrlen, 16);
+
+       skb = alloc_skb(wrlen, GFP_ATOMIC);
+       if (!skb)
+               return;
+
+       csk = rcu_dereference_sk_user_data(sk);
+
+       __set_tcb_field(sk, skb, 1, TF_RX_QUIESCE_V(1), 0, 0, 1);
+       set_wr_txq(skb, CPL_PRIORITY_CONTROL, csk->port_id);
+       ret = cxgb4_ofld_send(csk->egress_dev, skb);
+       if (ret < 0)
+               kfree_skb(skb);
+}
+
 /* TLS Key bitmap processing */
 int chtls_init_kmap(struct chtls_dev *cdev, struct cxgb4_lld_info *lldi)
 {
index 47eb9c584a123ae92af5f6a8a36cf1be66296832..492ce213208d2a1d91d95a5ad7163a16af7ec668 100644 (file)
@@ -348,12 +348,12 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)
                 * SBP is *not* set in PRT_SBPVSI (default not set).
                 */
                skb = i40e_construct_skb_zc(rx_ring, *bi);
-               *bi = NULL;
                if (!skb) {
                        rx_ring->rx_stats.alloc_buff_failed++;
                        break;
                }
 
+               *bi = NULL;
                cleaned_count++;
                i40e_inc_ntc(rx_ring);
 
index 4b1808acef5812a934aeed1b44a804bd4fdb9bb2..358119d98358200130bbe76d6507d1fe52a334a8 100644 (file)
@@ -5882,8 +5882,6 @@ static void mvpp2_phylink_validate(struct phylink_config *config,
 
        phylink_set(mask, Autoneg);
        phylink_set_port_modes(mask);
-       phylink_set(mask, Pause);
-       phylink_set(mask, Asym_Pause);
 
        switch (state->interface) {
        case PHY_INTERFACE_MODE_10GBASER:
index d298b935717784e5ba3bdf3344a0898e624a5759..6c6b411e78fd87c66da58761a2f55cb765189a8b 100644 (file)
@@ -469,6 +469,9 @@ int rvu_mbox_handler_cgx_mac_addr_set(struct rvu *rvu,
        int pf = rvu_get_pf(req->hdr.pcifunc);
        u8 cgx_id, lmac_id;
 
+       if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
+               return -EPERM;
+
        rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
 
        cgx_lmac_addr_set(cgx_id, lmac_id, req->mac_addr);
@@ -485,6 +488,9 @@ int rvu_mbox_handler_cgx_mac_addr_get(struct rvu *rvu,
        int rc = 0, i;
        u64 cfg;
 
+       if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
+               return -EPERM;
+
        rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
 
        rsp->hdr.rc = rc;
index 8fa286ccdd6bb281a834bc135593487878930403..bf85ce9835d7f93728e618f7bddbab1d41c37503 100644 (file)
@@ -19,7 +19,7 @@
 #define MLXSW_THERMAL_ASIC_TEMP_NORM   75000   /* 75C */
 #define MLXSW_THERMAL_ASIC_TEMP_HIGH   85000   /* 85C */
 #define MLXSW_THERMAL_ASIC_TEMP_HOT    105000  /* 105C */
-#define MLXSW_THERMAL_ASIC_TEMP_CRIT   110000  /* 110C */
+#define MLXSW_THERMAL_ASIC_TEMP_CRIT   140000  /* 140C */
 #define MLXSW_THERMAL_HYSTERESIS_TEMP  5000    /* 5C */
 #define MLXSW_THERMAL_MODULE_TEMP_SHIFT        (MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
 #define MLXSW_THERMAL_ZONE_MAX_NAME    16
@@ -176,6 +176,12 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
        if (err)
                return err;
 
+       if (crit_temp > emerg_temp) {
+               dev_warn(dev, "%s : Critical threshold %d is above emergency threshold %d\n",
+                        tz->tzdev->type, crit_temp, emerg_temp);
+               return 0;
+       }
+
        /* According to the system thermal requirements, the thermal zones are
         * defined with four trip points. The critical and emergency
         * temperature thresholds, provided by QSFP module are set as "active"
@@ -190,11 +196,8 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
                tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp;
        tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp;
        tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp;
-       if (emerg_temp > crit_temp)
-               tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp +
+       tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp +
                                        MLXSW_THERMAL_MODULE_TEMP_SHIFT;
-       else
-               tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp;
 
        return 0;
 }
index 0b9992bd66262935f2c00adefdfe52f6cdd7d603..ff87a0bc089cffc6cbe71c34ea88d86132ae1d53 100644 (file)
@@ -60,14 +60,27 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port,
                      const unsigned char mac[ETH_ALEN],
                      unsigned int vid, enum macaccess_entry_type type)
 {
+       u32 cmd = ANA_TABLES_MACACCESS_VALID |
+               ANA_TABLES_MACACCESS_DEST_IDX(port) |
+               ANA_TABLES_MACACCESS_ENTRYTYPE(type) |
+               ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN);
+       unsigned int mc_ports;
+
+       /* Set MAC_CPU_COPY if the CPU port is used by a multicast entry */
+       if (type == ENTRYTYPE_MACv4)
+               mc_ports = (mac[1] << 8) | mac[2];
+       else if (type == ENTRYTYPE_MACv6)
+               mc_ports = (mac[0] << 8) | mac[1];
+       else
+               mc_ports = 0;
+
+       if (mc_ports & BIT(ocelot->num_phys_ports))
+               cmd |= ANA_TABLES_MACACCESS_MAC_CPU_COPY;
+
        ocelot_mact_select(ocelot, mac, vid);
 
        /* Issue a write command */
-       ocelot_write(ocelot, ANA_TABLES_MACACCESS_VALID |
-                            ANA_TABLES_MACACCESS_DEST_IDX(port) |
-                            ANA_TABLES_MACACCESS_ENTRYTYPE(type) |
-                            ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN),
-                            ANA_TABLES_MACACCESS);
+       ocelot_write(ocelot, cmd, ANA_TABLES_MACACCESS);
 
        return ocelot_mact_wait_for_completion(ocelot);
 }
index 2bd2840d88bdc89835f08a56fd7c35581492162c..42230f92ca9c8a142f2212a93b98a3190cbaa6de 100644 (file)
@@ -1042,10 +1042,8 @@ static int ocelot_netdevice_event(struct notifier_block *unused,
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        int ret = 0;
 
-       if (!ocelot_netdevice_dev_check(dev))
-               return 0;
-
        if (event == NETDEV_PRECHANGEUPPER &&
+           ocelot_netdevice_dev_check(dev) &&
            netif_is_lag_master(info->upper_dev)) {
                struct netdev_lag_upper_info *lag_upper_info = info->upper_info;
                struct netlink_ext_ack *extack;
index f21847739ef1fecbd37eacb588717304574ca2eb..d258e0ccf9465309eef1b3062cdf2cce8025a565 100644 (file)
@@ -564,11 +564,6 @@ static const struct net_device_ops netxen_netdev_ops = {
        .ndo_set_features = netxen_set_features,
 };
 
-static inline bool netxen_function_zero(struct pci_dev *pdev)
-{
-       return (PCI_FUNC(pdev->devfn) == 0) ? true : false;
-}
-
 static inline void netxen_set_interrupt_mode(struct netxen_adapter *adapter,
                                             u32 mode)
 {
@@ -664,7 +659,7 @@ static int netxen_setup_intr(struct netxen_adapter *adapter)
        netxen_initialize_interrupt_registers(adapter);
        netxen_set_msix_bit(pdev, 0);
 
-       if (netxen_function_zero(pdev)) {
+       if (adapter->portnum == 0) {
                if (!netxen_setup_msi_interrupts(adapter, num_msix))
                        netxen_set_interrupt_mode(adapter, NETXEN_MSI_MODE);
                else
index c633046329352601ce76ad7d12913fffd420e9ec..590b088bc4c7f3e2f0d6d79443fcff6a6f4da077 100644 (file)
@@ -2606,10 +2606,10 @@ static int sh_eth_close(struct net_device *ndev)
        /* Free all the skbuffs in the Rx queue and the DMA buffer. */
        sh_eth_ring_free(ndev);
 
-       pm_runtime_put_sync(&mdp->pdev->dev);
-
        mdp->is_opened = 0;
 
+       pm_runtime_put(&mdp->pdev->dev);
+
        return 0;
 }
 
@@ -3034,6 +3034,28 @@ static int sh_mdio_release(struct sh_eth_private *mdp)
        return 0;
 }
 
+static int sh_mdiobb_read(struct mii_bus *bus, int phy, int reg)
+{
+       int res;
+
+       pm_runtime_get_sync(bus->parent);
+       res = mdiobb_read(bus, phy, reg);
+       pm_runtime_put(bus->parent);
+
+       return res;
+}
+
+static int sh_mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
+{
+       int res;
+
+       pm_runtime_get_sync(bus->parent);
+       res = mdiobb_write(bus, phy, reg, val);
+       pm_runtime_put(bus->parent);
+
+       return res;
+}
+
 /* MDIO bus init function */
 static int sh_mdio_init(struct sh_eth_private *mdp,
                        struct sh_eth_plat_data *pd)
@@ -3058,6 +3080,10 @@ static int sh_mdio_init(struct sh_eth_private *mdp,
        if (!mdp->mii_bus)
                return -ENOMEM;
 
+       /* Wrap accessors with Runtime PM-aware ops */
+       mdp->mii_bus->read = sh_mdiobb_read;
+       mdp->mii_bus->write = sh_mdiobb_write;
+
        /* Hook up MII support for ethtool */
        mdp->mii_bus->name = "sh_mii";
        mdp->mii_bus->parent = dev;
index 03e79a677c8bd015f00434635f19217624f0ff85..8f7ac24545efe2659c4a7ea6acb4deb2bf74c9fd 100644 (file)
@@ -568,68 +568,24 @@ static int dwmac5_est_write(void __iomem *ioaddr, u32 reg, u32 val, bool gcl)
 int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
                         unsigned int ptp_rate)
 {
-       u32 speed, total_offset, offset, ctrl, ctr_low;
-       u32 extcfg = readl(ioaddr + GMAC_EXT_CONFIG);
-       u32 mac_cfg = readl(ioaddr + GMAC_CONFIG);
        int i, ret = 0x0;
-       u64 total_ctr;
-
-       if (extcfg & GMAC_CONFIG_EIPG_EN) {
-               offset = (extcfg & GMAC_CONFIG_EIPG) >> GMAC_CONFIG_EIPG_SHIFT;
-               offset = 104 + (offset * 8);
-       } else {
-               offset = (mac_cfg & GMAC_CONFIG_IPG) >> GMAC_CONFIG_IPG_SHIFT;
-               offset = 96 - (offset * 8);
-       }
-
-       speed = mac_cfg & (GMAC_CONFIG_PS | GMAC_CONFIG_FES);
-       speed = speed >> GMAC_CONFIG_FES_SHIFT;
-
-       switch (speed) {
-       case 0x0:
-               offset = offset * 1000; /* 1G */
-               break;
-       case 0x1:
-               offset = offset * 400; /* 2.5G */
-               break;
-       case 0x2:
-               offset = offset * 100000; /* 10M */
-               break;
-       case 0x3:
-               offset = offset * 10000; /* 100M */
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       offset = offset / 1000;
+       u32 ctrl;
 
        ret |= dwmac5_est_write(ioaddr, BTR_LOW, cfg->btr[0], false);
        ret |= dwmac5_est_write(ioaddr, BTR_HIGH, cfg->btr[1], false);
        ret |= dwmac5_est_write(ioaddr, TER, cfg->ter, false);
        ret |= dwmac5_est_write(ioaddr, LLR, cfg->gcl_size, false);
+       ret |= dwmac5_est_write(ioaddr, CTR_LOW, cfg->ctr[0], false);
+       ret |= dwmac5_est_write(ioaddr, CTR_HIGH, cfg->ctr[1], false);
        if (ret)
                return ret;
 
-       total_offset = 0;
        for (i = 0; i < cfg->gcl_size; i++) {
-               ret = dwmac5_est_write(ioaddr, i, cfg->gcl[i] + offset, true);
+               ret = dwmac5_est_write(ioaddr, i, cfg->gcl[i], true);
                if (ret)
                        return ret;
-
-               total_offset += offset;
        }
 
-       total_ctr = cfg->ctr[0] + cfg->ctr[1] * 1000000000ULL;
-       total_ctr += total_offset;
-
-       ctr_low = do_div(total_ctr, 1000000000);
-
-       ret |= dwmac5_est_write(ioaddr, CTR_LOW, ctr_low, false);
-       ret |= dwmac5_est_write(ioaddr, CTR_HIGH, total_ctr, false);
-       if (ret)
-               return ret;
-
        ctrl = readl(ioaddr + MTL_EST_CONTROL);
        ctrl &= ~PTOV;
        ctrl |= ((1000000000 / ptp_rate) * 6) << PTOV_SHIFT;
index 5b1c12ff98c05f3f56e62ff754d62712cc4be449..26b971cd4da5abfb8407fe9b8bf3aa63c6f87c52 100644 (file)
@@ -2184,7 +2184,7 @@ static int stmmac_napi_check(struct stmmac_priv *priv, u32 chan)
                        spin_lock_irqsave(&ch->lock, flags);
                        stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 0);
                        spin_unlock_irqrestore(&ch->lock, flags);
-                       __napi_schedule_irqoff(&ch->rx_napi);
+                       __napi_schedule(&ch->rx_napi);
                }
        }
 
@@ -2193,7 +2193,7 @@ static int stmmac_napi_check(struct stmmac_priv *priv, u32 chan)
                        spin_lock_irqsave(&ch->lock, flags);
                        stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 0, 1);
                        spin_unlock_irqrestore(&ch->lock, flags);
-                       __napi_schedule_irqoff(&ch->tx_napi);
+                       __napi_schedule(&ch->tx_napi);
                }
        }
 
@@ -4026,6 +4026,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
        int txfifosz = priv->plat->tx_fifo_size;
+       const int mtu = new_mtu;
 
        if (txfifosz == 0)
                txfifosz = priv->dma_cap.tx_fifo_size;
@@ -4043,7 +4044,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
        if ((txfifosz < new_mtu) || (new_mtu > BUF_SIZE_16KiB))
                return -EINVAL;
 
-       dev->mtu = new_mtu;
+       dev->mtu = mtu;
 
        netdev_update_features(dev);
 
index f5bed4d26e80464bc35f7537ff586439134a37d9..8ed3b2c834a09e44cce6f4810a5484c3cd5d7943 100644 (file)
@@ -599,7 +599,8 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
 {
        u32 size, wid = priv->dma_cap.estwid, dep = priv->dma_cap.estdep;
        struct plat_stmmacenet_data *plat = priv->plat;
-       struct timespec64 time;
+       struct timespec64 time, current_time;
+       ktime_t current_time_ns;
        bool fpe = false;
        int i, ret = 0;
        u64 ctr;
@@ -694,7 +695,22 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
        }
 
        /* Adjust for real system time */
-       time = ktime_to_timespec64(qopt->base_time);
+       priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, &current_time);
+       current_time_ns = timespec64_to_ktime(current_time);
+       if (ktime_after(qopt->base_time, current_time_ns)) {
+               time = ktime_to_timespec64(qopt->base_time);
+       } else {
+               ktime_t base_time;
+               s64 n;
+
+               n = div64_s64(ktime_sub_ns(current_time_ns, qopt->base_time),
+                             qopt->cycle_time);
+               base_time = ktime_add_ns(qopt->base_time,
+                                        (n + 1) * qopt->cycle_time);
+
+               time = ktime_to_timespec64(base_time);
+       }
+
        priv->plat->est->btr[0] = (u32)time.tv_nsec;
        priv->plat->est->btr[1] = (u32)time.tv_sec;
 
index e34fe2d77324eb658aa302d99a1454a22a1f2600..9b08eb8239846300ffe50359dc435bc7d5c87b15 100644 (file)
@@ -216,6 +216,7 @@ int ipa_modem_start(struct ipa *ipa)
        ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]->netdev = netdev;
        ipa->name_map[IPA_ENDPOINT_AP_MODEM_RX]->netdev = netdev;
 
+       SET_NETDEV_DEV(netdev, &ipa->pdev->dev);
        priv = netdev_priv(netdev);
        priv->ipa = ipa;
 
index 5136275c8e7399fbbd74d048abb89f50929e5af3..d3915f83185430e9db7e6cfb3903af50ba244d7a 100644 (file)
@@ -149,7 +149,7 @@ static int mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, u32 addr)
        return dev_addr;
 }
 
-static int mdiobb_read(struct mii_bus *bus, int phy, int reg)
+int mdiobb_read(struct mii_bus *bus, int phy, int reg)
 {
        struct mdiobb_ctrl *ctrl = bus->priv;
        int ret, i;
@@ -180,8 +180,9 @@ static int mdiobb_read(struct mii_bus *bus, int phy, int reg)
        mdiobb_get_bit(ctrl);
        return ret;
 }
+EXPORT_SYMBOL(mdiobb_read);
 
-static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
+int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
 {
        struct mdiobb_ctrl *ctrl = bus->priv;
 
@@ -201,6 +202,7 @@ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
        mdiobb_get_bit(ctrl);
        return 0;
 }
+EXPORT_SYMBOL(mdiobb_write);
 
 struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)
 {
index 33372756a451fb45fa29e50a6e74f8965d461839..ddb78fb4d6dc37480e4ac6b131442316a27bcc84 100644 (file)
@@ -317,7 +317,8 @@ static int smsc_phy_probe(struct phy_device *phydev)
        /* Make clk optional to keep DTB backward compatibility. */
        priv->refclk = clk_get_optional(dev, NULL);
        if (IS_ERR(priv->refclk))
-               dev_err_probe(dev, PTR_ERR(priv->refclk), "Failed to request clock\n");
+               return dev_err_probe(dev, PTR_ERR(priv->refclk),
+                                    "Failed to request clock\n");
 
        ret = clk_prepare_enable(priv->refclk);
        if (ret)
index 09c27f7773f9592a44ba41b24712825d4b828913..d445ecb1d0c75f406d971ab5131db6911ef95aff 100644 (file)
@@ -623,6 +623,7 @@ static int ppp_bridge_channels(struct channel *pch, struct channel *pchb)
                write_unlock_bh(&pch->upl);
                return -EALREADY;
        }
+       refcount_inc(&pchb->file.refcnt);
        rcu_assign_pointer(pch->bridge, pchb);
        write_unlock_bh(&pch->upl);
 
@@ -632,19 +633,24 @@ static int ppp_bridge_channels(struct channel *pch, struct channel *pchb)
                write_unlock_bh(&pchb->upl);
                goto err_unset;
        }
+       refcount_inc(&pch->file.refcnt);
        rcu_assign_pointer(pchb->bridge, pch);
        write_unlock_bh(&pchb->upl);
 
-       refcount_inc(&pch->file.refcnt);
-       refcount_inc(&pchb->file.refcnt);
-
        return 0;
 
 err_unset:
        write_lock_bh(&pch->upl);
+       /* Re-read pch->bridge with upl held in case it was modified concurrently */
+       pchb = rcu_dereference_protected(pch->bridge, lockdep_is_held(&pch->upl));
        RCU_INIT_POINTER(pch->bridge, NULL);
        write_unlock_bh(&pch->upl);
        synchronize_rcu();
+
+       if (pchb)
+               if (refcount_dec_and_test(&pchb->file.refcnt))
+                       ppp_destroy_channel(pchb);
+
        return -EALREADY;
 }
 
index 1e37190287808973b6d56b190a9dfe848754be47..fbbe7864363190136d95c22d4e09aefa10da8aa0 100644 (file)
@@ -631,7 +631,6 @@ config USB_NET_AQC111
 config USB_RTL8153_ECM
        tristate "RTL8153 ECM support"
        depends on USB_NET_CDCETHER && (USB_RTL8152 || USB_RTL8152=n)
-       default y
        help
          This option supports ECM mode for RTL8153 ethernet adapter, when
          CONFIG_USB_RTL8152 is not set, or the RTL8153 device is not
index 8c1d61c2cbacbca84da2051a77d4f3e0bc943cd3..6aaa0675c28a397c30991375f22256e9209bb2a3 100644 (file)
@@ -793,6 +793,13 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+/* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x721e, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */
 {
        USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM,
index 5a78848db93fdaba8a6888fad3cd2b13ac03cbd6..291e76d32abe7c4ee928f8af1e669d9720495667 100644 (file)
@@ -1827,6 +1827,15 @@ cdc_ncm_speed_change(struct usbnet *dev,
        uint32_t rx_speed = le32_to_cpu(data->DLBitRRate);
        uint32_t tx_speed = le32_to_cpu(data->ULBitRate);
 
+       /* if the speed hasn't changed, don't report it.
+        * RTL8156 shipped before 2021 sends notification about every 32ms.
+        */
+       if (dev->rx_speed == rx_speed && dev->tx_speed == tx_speed)
+               return;
+
+       dev->rx_speed = rx_speed;
+       dev->tx_speed = tx_speed;
+
        /*
         * Currently the USB-NET API does not support reporting the actual
         * device speed. Do print it instead.
@@ -1867,7 +1876,8 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
                 * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be
                 * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE.
                 */
-               usbnet_link_change(dev, !!event->wValue, 0);
+               if (netif_carrier_ok(dev->net) != !!event->wValue)
+                       usbnet_link_change(dev, !!event->wValue, 0);
                break;
 
        case USB_CDC_NOTIFY_SPEED_CHANGE:
index c448d608982168826bf25a923b6ffd283c7f5206..67cd6986634fb4552b902559bc628ece68df4cfc 100644 (file)
@@ -6877,6 +6877,7 @@ static const struct usb_device_id rtl8152_table[] = {
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7205)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x720c)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7214)},
+       {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x721e)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0xa387)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)},
        {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA,  0x09ff)},
index 2c3fabd38b1635d01f139796869b18c1b133f2fc..20b2df8d74ae1b33d2eeb9ce49015b6fba62acf9 100644 (file)
@@ -122,12 +122,20 @@ static const struct driver_info r8153_info = {
 };
 
 static const struct usb_device_id products[] = {
+/* Realtek RTL8153 Based USB 3.0 Ethernet Adapters */
 {
        USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID_REALTEK, 0x8153, USB_CLASS_COMM,
                                      USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
        .driver_info = (unsigned long)&r8153_info,
 },
 
+/* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID_LENOVO, 0x721e, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = (unsigned long)&r8153_info,
+},
+
        { },            /* END */
 };
 MODULE_DEVICE_TABLE(usb, products);
index 6609d21ef8942ef044f0b31aaadbd8084924568e..f813ca9dec53167c8a959489b6590c7ab6173474 100644 (file)
@@ -387,7 +387,7 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
        reply_len = sizeof *phym;
        retval = rndis_query(dev, intf, u.buf,
                             RNDIS_OID_GEN_PHYSICAL_MEDIUM,
-                            0, (void **) &phym, &reply_len);
+                            reply_len, (void **)&phym, &reply_len);
        if (retval != 0 || !phym) {
                /* OID is optional so don't fail here. */
                phym_unspec = cpu_to_le32(RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED);
index f320273fc6727fec7b9f944c8c1ea895d12e51e0..200bdd672c281ffc54d7d5bc19be654ca2302d48 100644 (file)
@@ -2856,6 +2856,11 @@ static const struct attribute_group *nvme_subsys_attrs_groups[] = {
        NULL,
 };
 
+static inline bool nvme_discovery_ctrl(struct nvme_ctrl *ctrl)
+{
+       return ctrl->opts && ctrl->opts->discovery_nqn;
+}
+
 static bool nvme_validate_cntlid(struct nvme_subsystem *subsys,
                struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
 {
@@ -2875,7 +2880,7 @@ static bool nvme_validate_cntlid(struct nvme_subsystem *subsys,
                }
 
                if ((id->cmic & NVME_CTRL_CMIC_MULTI_CTRL) ||
-                   (ctrl->opts && ctrl->opts->discovery_nqn))
+                   nvme_discovery_ctrl(ctrl))
                        continue;
 
                dev_err(ctrl->device,
@@ -3144,7 +3149,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
                        goto out_free;
                }
 
-               if (!ctrl->opts->discovery_nqn && !ctrl->kas) {
+               if (!nvme_discovery_ctrl(ctrl) && !ctrl->kas) {
                        dev_err(ctrl->device,
                                "keep-alive support is mandatory for fabrics\n");
                        ret = -EINVAL;
@@ -3184,7 +3189,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
        if (ret < 0)
                return ret;
 
-       if (!ctrl->identified) {
+       if (!ctrl->identified && !nvme_discovery_ctrl(ctrl)) {
                ret = nvme_hwmon_init(ctrl);
                if (ret < 0)
                        return ret;
index 979ee31b8dd1c9c961ab27364d94ea972598e4b6..216619926563ed2c40373ba6981da58d5481c235 100644 (file)
@@ -201,7 +201,7 @@ static inline size_t nvme_tcp_req_cur_offset(struct nvme_tcp_request *req)
 
 static inline size_t nvme_tcp_req_cur_length(struct nvme_tcp_request *req)
 {
-       return min_t(size_t, req->iter.bvec->bv_len - req->iter.iov_offset,
+       return min_t(size_t, iov_iter_single_seg_count(&req->iter),
                        req->pdu_len - req->pdu_sent);
 }
 
@@ -286,7 +286,7 @@ static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
         * directly, otherwise queue io_work. Also, only do that if we
         * are on the same cpu, so we don't introduce contention.
         */
-       if (queue->io_cpu == smp_processor_id() &&
+       if (queue->io_cpu == __smp_processor_id() &&
            sync && empty && mutex_trylock(&queue->send_mutex)) {
                queue->more_requests = !last;
                nvme_tcp_send_all(queue);
index bdfc22eb2a10fa95847411b047a4e0ea9a2f676a..06b6b742bb213e3ba924ef113d81e4081379b2be 100644 (file)
@@ -1220,6 +1220,14 @@ nvmet_rdma_find_get_device(struct rdma_cm_id *cm_id)
        }
        ndev->inline_data_size = nport->inline_data_size;
        ndev->inline_page_count = inline_page_count;
+
+       if (nport->pi_enable && !(cm_id->device->attrs.device_cap_flags &
+                                 IB_DEVICE_INTEGRITY_HANDOVER)) {
+               pr_warn("T10-PI is not supported by device %s. Disabling it\n",
+                       cm_id->device->name);
+               nport->pi_enable = false;
+       }
+
        ndev->device = cm_id->device;
        kref_init(&ndev->ref);
 
@@ -1855,14 +1863,6 @@ static int nvmet_rdma_enable_port(struct nvmet_rdma_port *port)
                goto out_destroy_id;
        }
 
-       if (port->nport->pi_enable &&
-           !(cm_id->device->attrs.device_cap_flags &
-             IB_DEVICE_INTEGRITY_HANDOVER)) {
-               pr_err("T10-PI is not supported for %pISpcs\n", addr);
-               ret = -EINVAL;
-               goto out_destroy_id;
-       }
-
        port->cm_id = cm_id;
        return 0;
 
index 794a37d5085376c54b571274f360f9c427d5c5d9..cb2f55f450e4adf05a7b3d81e8b9a01230665584 100644 (file)
@@ -726,11 +726,6 @@ static int armpmu_get_cpu_irq(struct arm_pmu *pmu, int cpu)
        return per_cpu(hw_events->irq, cpu);
 }
 
-bool arm_pmu_irq_is_nmi(void)
-{
-       return has_nmi;
-}
-
 /*
  * PMU hardware loses all context when a CPU goes offline.
  * When a CPU is hotplugged back in, since some hardware registers are
index 34803a6c76643259def0d596cc6f62fb3db6b4a0..5c1a109842a76054e369873b2386875ab567b2a4 100644 (file)
@@ -347,7 +347,7 @@ FUNC_GROUP_DECL(RMII4, F24, E23, E24, E25, C25, C24, B26, B25, B24);
 
 #define D22 40
 SIG_EXPR_LIST_DECL_SESG(D22, SD1CLK, SD1, SIG_DESC_SET(SCU414, 8));
-SIG_EXPR_LIST_DECL_SEMG(D22, PWM8, PWM8G0, PWM8, SIG_DESC_SET(SCU414, 8));
+SIG_EXPR_LIST_DECL_SEMG(D22, PWM8, PWM8G0, PWM8, SIG_DESC_SET(SCU4B4, 8));
 PIN_DECL_2(D22, GPIOF0, SD1CLK, PWM8);
 GROUP_DECL(PWM8G0, D22);
 
index 7aeb552d16ce9f1496c88e5c41af82f009937764..72f17f26acd80df9880a4b92e0bf1f2c0b42a436 100644 (file)
@@ -920,6 +920,10 @@ int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
                        err = hw->soc->bias_set(hw, desc, pullup);
                        if (err)
                                return err;
+               } else if (hw->soc->bias_set_combo) {
+                       err = hw->soc->bias_set_combo(hw, desc, pullup, arg);
+                       if (err)
+                               return err;
                } else {
                        return -ENOTSUPP;
                }
index d4ea10803fd9077b81bf844713b7291cb1c7ecc6..abfe11c7b49fb039ba050a070d35097705f527f3 100644 (file)
@@ -949,7 +949,6 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
        } else {
                int irq = chip->to_irq(chip, offset);
                const int pullidx = pull ? 1 : 0;
-               bool wake;
                int val;
                static const char * const pulls[] = {
                        "none        ",
index 53a6a24bd05270291b690de275b072cba5cfb722..3ea163498647f558bd2be134b14b26417f68f3ee 100644 (file)
 #define JZ4740_GPIO_TRIG       0x70
 #define JZ4740_GPIO_FLAG       0x80
 
-#define JZ4760_GPIO_INT                0x10
-#define JZ4760_GPIO_PAT1       0x30
-#define JZ4760_GPIO_PAT0       0x40
-#define JZ4760_GPIO_FLAG       0x50
-#define JZ4760_GPIO_PEN                0x70
+#define JZ4770_GPIO_INT                0x10
+#define JZ4770_GPIO_PAT1       0x30
+#define JZ4770_GPIO_PAT0       0x40
+#define JZ4770_GPIO_FLAG       0x50
+#define JZ4770_GPIO_PEN                0x70
 
 #define X1830_GPIO_PEL                 0x110
 #define X1830_GPIO_PEH                 0x120
@@ -1688,8 +1688,8 @@ static inline bool ingenic_gpio_get_value(struct ingenic_gpio_chip *jzgc,
 static void ingenic_gpio_set_value(struct ingenic_gpio_chip *jzgc,
                                   u8 offset, int value)
 {
-       if (jzgc->jzpc->info->version >= ID_JZ4760)
-               ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_PAT0, offset, !!value);
+       if (jzgc->jzpc->info->version >= ID_JZ4770)
+               ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_PAT0, offset, !!value);
        else
                ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_DATA, offset, !!value);
 }
@@ -1718,9 +1718,9 @@ static void irq_set_type(struct ingenic_gpio_chip *jzgc,
                break;
        }
 
-       if (jzgc->jzpc->info->version >= ID_JZ4760) {
-               reg1 = JZ4760_GPIO_PAT1;
-               reg2 = JZ4760_GPIO_PAT0;
+       if (jzgc->jzpc->info->version >= ID_JZ4770) {
+               reg1 = JZ4770_GPIO_PAT1;
+               reg2 = JZ4770_GPIO_PAT0;
        } else {
                reg1 = JZ4740_GPIO_TRIG;
                reg2 = JZ4740_GPIO_DIR;
@@ -1758,8 +1758,8 @@ static void ingenic_gpio_irq_enable(struct irq_data *irqd)
        struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
        int irq = irqd->hwirq;
 
-       if (jzgc->jzpc->info->version >= ID_JZ4760)
-               ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_INT, irq, true);
+       if (jzgc->jzpc->info->version >= ID_JZ4770)
+               ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_INT, irq, true);
        else
                ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, true);
 
@@ -1774,8 +1774,8 @@ static void ingenic_gpio_irq_disable(struct irq_data *irqd)
 
        ingenic_gpio_irq_mask(irqd);
 
-       if (jzgc->jzpc->info->version >= ID_JZ4760)
-               ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_INT, irq, false);
+       if (jzgc->jzpc->info->version >= ID_JZ4770)
+               ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_INT, irq, false);
        else
                ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, false);
 }
@@ -1799,8 +1799,8 @@ static void ingenic_gpio_irq_ack(struct irq_data *irqd)
                        irq_set_type(jzgc, irq, IRQ_TYPE_LEVEL_HIGH);
        }
 
-       if (jzgc->jzpc->info->version >= ID_JZ4760)
-               ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_FLAG, irq, false);
+       if (jzgc->jzpc->info->version >= ID_JZ4770)
+               ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false);
        else
                ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true);
 }
@@ -1856,8 +1856,8 @@ static void ingenic_gpio_irq_handler(struct irq_desc *desc)
 
        chained_irq_enter(irq_chip, desc);
 
-       if (jzgc->jzpc->info->version >= ID_JZ4760)
-               flag = ingenic_gpio_read_reg(jzgc, JZ4760_GPIO_FLAG);
+       if (jzgc->jzpc->info->version >= ID_JZ4770)
+               flag = ingenic_gpio_read_reg(jzgc, JZ4770_GPIO_FLAG);
        else
                flag = ingenic_gpio_read_reg(jzgc, JZ4740_GPIO_FLAG);
 
@@ -1938,9 +1938,9 @@ static int ingenic_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
        struct ingenic_pinctrl *jzpc = jzgc->jzpc;
        unsigned int pin = gc->base + offset;
 
-       if (jzpc->info->version >= ID_JZ4760) {
-               if (ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_INT) ||
-                   ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_PAT1))
+       if (jzpc->info->version >= ID_JZ4770) {
+               if (ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_INT) ||
+                   ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PAT1))
                        return GPIO_LINE_DIRECTION_IN;
                return GPIO_LINE_DIRECTION_OUT;
        }
@@ -1991,20 +1991,20 @@ static int ingenic_pinmux_set_pin_fn(struct ingenic_pinctrl *jzpc,
                        'A' + offt, idx, func);
 
        if (jzpc->info->version >= ID_X1000) {
-               ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
+               ingenic_shadow_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
                ingenic_shadow_config_pin(jzpc, pin, GPIO_MSK, false);
-               ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, func & 0x2);
-               ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_PAT0, func & 0x1);
+               ingenic_shadow_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, func & 0x2);
+               ingenic_shadow_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, func & 0x1);
                ingenic_shadow_config_pin_load(jzpc, pin);
-       } else if (jzpc->info->version >= ID_JZ4760) {
-               ingenic_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
+       } else if (jzpc->info->version >= ID_JZ4770) {
+               ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
                ingenic_config_pin(jzpc, pin, GPIO_MSK, false);
-               ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, func & 0x2);
-               ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT0, func & 0x1);
+               ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, func & 0x2);
+               ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, func & 0x1);
        } else {
                ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, true);
                ingenic_config_pin(jzpc, pin, JZ4740_GPIO_TRIG, func & 0x2);
-               ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, func > 0);
+               ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, func & 0x1);
        }
 
        return 0;
@@ -2057,14 +2057,14 @@ static int ingenic_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
                        'A' + offt, idx, input ? "in" : "out");
 
        if (jzpc->info->version >= ID_X1000) {
-               ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
+               ingenic_shadow_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
                ingenic_shadow_config_pin(jzpc, pin, GPIO_MSK, true);
-               ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, input);
+               ingenic_shadow_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, input);
                ingenic_shadow_config_pin_load(jzpc, pin);
-       } else if (jzpc->info->version >= ID_JZ4760) {
-               ingenic_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
+       } else if (jzpc->info->version >= ID_JZ4770) {
+               ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
                ingenic_config_pin(jzpc, pin, GPIO_MSK, true);
-               ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, input);
+               ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, input);
        } else {
                ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, false);
                ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DIR, !input);
@@ -2091,8 +2091,8 @@ static int ingenic_pinconf_get(struct pinctrl_dev *pctldev,
        unsigned int offt = pin / PINS_PER_GPIO_CHIP;
        bool pull;
 
-       if (jzpc->info->version >= ID_JZ4760)
-               pull = !ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_PEN);
+       if (jzpc->info->version >= ID_JZ4770)
+               pull = !ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PEN);
        else
                pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS);
 
@@ -2141,8 +2141,8 @@ static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
                                        REG_SET(X1830_GPIO_PEH), bias << idxh);
                }
 
-       } else if (jzpc->info->version >= ID_JZ4760) {
-               ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PEN, !bias);
+       } else if (jzpc->info->version >= ID_JZ4770) {
+               ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PEN, !bias);
        } else {
                ingenic_config_pin(jzpc, pin, JZ4740_GPIO_PULL_DIS, !bias);
        }
@@ -2151,8 +2151,8 @@ static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
 static void ingenic_set_output_level(struct ingenic_pinctrl *jzpc,
                                     unsigned int pin, bool high)
 {
-       if (jzpc->info->version >= ID_JZ4760)
-               ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT0, high);
+       if (jzpc->info->version >= ID_JZ4770)
+               ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, high);
        else
                ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DATA, high);
 }
index e051aecf95c4ee5f8fc4feec3be30861dd61db0f..d70caecd21d25af56c54cd71be10221a36d98fd7 100644 (file)
@@ -51,6 +51,7 @@
  * @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge
  *                  detection.
  * @skip_wake_irqs: Skip IRQs that are handled by wakeup interrupt controller
+ * @disabled_for_mux: These IRQs were disabled because we muxed away.
  * @soc:            Reference to soc_data of platform specific data.
  * @regs:           Base addresses for the TLMM tiles.
  * @phys_base:      Physical base address
@@ -72,6 +73,7 @@ struct msm_pinctrl {
        DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
        DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
        DECLARE_BITMAP(skip_wake_irqs, MAX_NR_GPIO);
+       DECLARE_BITMAP(disabled_for_mux, MAX_NR_GPIO);
 
        const struct msm_pinctrl_soc_data *soc;
        void __iomem *regs[MAX_NR_TILES];
@@ -96,6 +98,14 @@ MSM_ACCESSOR(intr_cfg)
 MSM_ACCESSOR(intr_status)
 MSM_ACCESSOR(intr_target)
 
+static void msm_ack_intr_status(struct msm_pinctrl *pctrl,
+                               const struct msm_pingroup *g)
+{
+       u32 val = g->intr_ack_high ? BIT(g->intr_status_bit) : 0;
+
+       msm_writel_intr_status(val, pctrl, g);
+}
+
 static int msm_get_groups_count(struct pinctrl_dev *pctldev)
 {
        struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
@@ -171,6 +181,10 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
                              unsigned group)
 {
        struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+       struct gpio_chip *gc = &pctrl->chip;
+       unsigned int irq = irq_find_mapping(gc->irq.domain, group);
+       struct irq_data *d = irq_get_irq_data(irq);
+       unsigned int gpio_func = pctrl->soc->gpio_func;
        const struct msm_pingroup *g;
        unsigned long flags;
        u32 val, mask;
@@ -187,6 +201,20 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
        if (WARN_ON(i == g->nfuncs))
                return -EINVAL;
 
+       /*
+        * If an GPIO interrupt is setup on this pin then we need special
+        * handling.  Specifically interrupt detection logic will still see
+        * the pin twiddle even when we're muxed away.
+        *
+        * When we see a pin with an interrupt setup on it then we'll disable
+        * (mask) interrupts on it when we mux away until we mux back.  Note
+        * that disable_irq() refcounts and interrupts are disabled as long as
+        * at least one disable_irq() has been called.
+        */
+       if (d && i != gpio_func &&
+           !test_and_set_bit(d->hwirq, pctrl->disabled_for_mux))
+               disable_irq(irq);
+
        raw_spin_lock_irqsave(&pctrl->lock, flags);
 
        val = msm_readl_ctl(pctrl, g);
@@ -196,6 +224,20 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
 
        raw_spin_unlock_irqrestore(&pctrl->lock, flags);
 
+       if (d && i == gpio_func &&
+           test_and_clear_bit(d->hwirq, pctrl->disabled_for_mux)) {
+               /*
+                * Clear interrupts detected while not GPIO since we only
+                * masked things.
+                */
+               if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs))
+                       irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, false);
+               else
+                       msm_ack_intr_status(pctrl, g);
+
+               enable_irq(irq);
+       }
+
        return 0;
 }
 
@@ -210,8 +252,7 @@ static int msm_pinmux_request_gpio(struct pinctrl_dev *pctldev,
        if (!g->nfuncs)
                return 0;
 
-       /* For now assume function 0 is GPIO because it always is */
-       return msm_pinmux_set_mux(pctldev, g->funcs[0], offset);
+       return msm_pinmux_set_mux(pctldev, g->funcs[pctrl->soc->gpio_func], offset);
 }
 
 static const struct pinmux_ops msm_pinmux_ops = {
@@ -774,7 +815,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
        raw_spin_unlock_irqrestore(&pctrl->lock, flags);
 }
 
-static void msm_gpio_irq_clear_unmask(struct irq_data *d, bool status_clear)
+static void msm_gpio_irq_unmask(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
@@ -792,17 +833,6 @@ static void msm_gpio_irq_clear_unmask(struct irq_data *d, bool status_clear)
 
        raw_spin_lock_irqsave(&pctrl->lock, flags);
 
-       if (status_clear) {
-               /*
-                * clear the interrupt status bit before unmask to avoid
-                * any erroneous interrupts that would have got latched
-                * when the interrupt is not in use.
-                */
-               val = msm_readl_intr_status(pctrl, g);
-               val &= ~BIT(g->intr_status_bit);
-               msm_writel_intr_status(val, pctrl, g);
-       }
-
        val = msm_readl_intr_cfg(pctrl, g);
        val |= BIT(g->intr_raw_status_bit);
        val |= BIT(g->intr_enable_bit);
@@ -822,7 +852,7 @@ static void msm_gpio_irq_enable(struct irq_data *d)
                irq_chip_enable_parent(d);
 
        if (!test_bit(d->hwirq, pctrl->skip_wake_irqs))
-               msm_gpio_irq_clear_unmask(d, true);
+               msm_gpio_irq_unmask(d);
 }
 
 static void msm_gpio_irq_disable(struct irq_data *d)
@@ -837,11 +867,6 @@ static void msm_gpio_irq_disable(struct irq_data *d)
                msm_gpio_irq_mask(d);
 }
 
-static void msm_gpio_irq_unmask(struct irq_data *d)
-{
-       msm_gpio_irq_clear_unmask(d, false);
-}
-
 /**
  * msm_gpio_update_dual_edge_parent() - Prime next edge for IRQs handled by parent.
  * @d: The irq dta.
@@ -894,7 +919,6 @@ static void msm_gpio_irq_ack(struct irq_data *d)
        struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
        const struct msm_pingroup *g;
        unsigned long flags;
-       u32 val;
 
        if (test_bit(d->hwirq, pctrl->skip_wake_irqs)) {
                if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
@@ -906,12 +930,7 @@ static void msm_gpio_irq_ack(struct irq_data *d)
 
        raw_spin_lock_irqsave(&pctrl->lock, flags);
 
-       val = msm_readl_intr_status(pctrl, g);
-       if (g->intr_ack_high)
-               val |= BIT(g->intr_status_bit);
-       else
-               val &= ~BIT(g->intr_status_bit);
-       msm_writel_intr_status(val, pctrl, g);
+       msm_ack_intr_status(pctrl, g);
 
        if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
                msm_gpio_update_dual_edge_pos(pctrl, g, d);
@@ -936,6 +955,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
        const struct msm_pingroup *g;
        unsigned long flags;
+       bool was_enabled;
        u32 val;
 
        if (msm_gpio_needs_dual_edge_parent_workaround(d, type)) {
@@ -997,6 +1017,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
         * could cause the INTR_STATUS to be set for EDGE interrupts.
         */
        val = msm_readl_intr_cfg(pctrl, g);
+       was_enabled = val & BIT(g->intr_raw_status_bit);
        val |= BIT(g->intr_raw_status_bit);
        if (g->intr_detection_width == 2) {
                val &= ~(3 << g->intr_detection_bit);
@@ -1046,6 +1067,14 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        }
        msm_writel_intr_cfg(val, pctrl, g);
 
+       /*
+        * The first time we set RAW_STATUS_EN it could trigger an interrupt.
+        * Clear the interrupt.  This is safe because we have
+        * IRQCHIP_SET_TYPE_MASKED.
+        */
+       if (!was_enabled)
+               msm_ack_intr_status(pctrl, g);
+
        if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
                msm_gpio_update_dual_edge_pos(pctrl, g, d);
 
@@ -1099,16 +1128,11 @@ static int msm_gpio_irq_reqres(struct irq_data *d)
        }
 
        /*
-        * Clear the interrupt that may be pending before we enable
-        * the line.
-        * This is especially a problem with the GPIOs routed to the
-        * PDC. These GPIOs are direct-connect interrupts to the GIC.
-        * Disabling the interrupt line at the PDC does not prevent
-        * the interrupt from being latched at the GIC. The state at
-        * GIC needs to be cleared before enabling.
+        * The disable / clear-enable workaround we do in msm_pinmux_set_mux()
+        * only works if disable is not lazy since we only clear any bogus
+        * interrupt in hardware. Explicitly mark the interrupt as UNLAZY.
         */
-       if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs))
-               irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, 0);
+       irq_set_status_flags(d->irq, IRQ_DISABLE_UNLAZY);
 
        return 0;
 out:
index 333f99243c43ac24bad1a83ccd1cb9089d2a1870..e31a5167c91ec9710f0d111b9320de909b1c4dc0 100644 (file)
@@ -118,6 +118,7 @@ struct msm_gpio_wakeirq_map {
  * @wakeirq_dual_edge_errata: If true then GPIOs using the wakeirq_map need
  *                            to be aware that their parent can't handle dual
  *                            edge interrupts.
+ * @gpio_func: Which function number is GPIO (usually 0).
  */
 struct msm_pinctrl_soc_data {
        const struct pinctrl_pin_desc *pins;
@@ -134,6 +135,7 @@ struct msm_pinctrl_soc_data {
        const struct msm_gpio_wakeirq_map *wakeirq_map;
        unsigned int nwakeirq_map;
        bool wakeirq_dual_edge_errata;
+       unsigned int gpio_func;
 };
 
 extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops;
index 33040b0b3b799c2d520f001b85ef9f3af3eab971..2c941cdac9eedc6fb569f0d912a82361a02bb17c 100644 (file)
@@ -5,6 +5,7 @@
 
 menuconfig SURFACE_PLATFORMS
        bool "Microsoft Surface Platform-Specific Device Drivers"
+       depends on ACPI
        default y
        help
          Say Y here to get to see options for platform-specific device drivers
@@ -29,20 +30,19 @@ config SURFACE3_WMI
 
 config SURFACE_3_BUTTON
        tristate "Power/home/volume buttons driver for Microsoft Surface 3 tablet"
-       depends on ACPI && KEYBOARD_GPIO && I2C
+       depends on KEYBOARD_GPIO && I2C
        help
          This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet.
 
 config SURFACE_3_POWER_OPREGION
        tristate "Surface 3 battery platform operation region support"
-       depends on ACPI && I2C
+       depends on I2C
        help
          This driver provides support for ACPI operation
          region of the Surface 3 battery platform driver.
 
 config SURFACE_GPE
        tristate "Surface GPE/Lid Support Driver"
-       depends on ACPI
        depends on DMI
        help
          This driver marks the GPEs related to the ACPI lid device found on
@@ -52,7 +52,7 @@ config SURFACE_GPE
 
 config SURFACE_PRO3_BUTTON
        tristate "Power/home/volume buttons driver for Microsoft Surface Pro 3/4 tablet"
-       depends on ACPI && INPUT
+       depends on INPUT
        help
          This driver handles the power/home/volume buttons on the Microsoft Surface Pro 3/4 tablet.
 
index e49e5d6d5d4e134e3800d4d1449caeaa7082608c..86f6991b1215710307b6965e5643043a3da964c7 100644 (file)
@@ -181,12 +181,12 @@ static int surface_lid_enable_wakeup(struct device *dev, bool enable)
        return 0;
 }
 
-static int surface_gpe_suspend(struct device *dev)
+static int __maybe_unused surface_gpe_suspend(struct device *dev)
 {
        return surface_lid_enable_wakeup(dev, true);
 }
 
-static int surface_gpe_resume(struct device *dev)
+static int __maybe_unused surface_gpe_resume(struct device *dev)
 {
        return surface_lid_enable_wakeup(dev, false);
 }
index 0102bf1c7916028b0b785c19e1f42e1fa211872f..ef83425724634a1d41862d6d307170dcc7ce305c 100644 (file)
@@ -85,7 +85,7 @@ static inline void amd_pmc_reg_write(struct amd_pmc_dev *dev, int reg_offset, u3
        iowrite32(val, dev->regbase + reg_offset);
 }
 
-#if CONFIG_DEBUG_FS
+#ifdef CONFIG_DEBUG_FS
 static int smu_fw_info_show(struct seq_file *s, void *unused)
 {
        struct amd_pmc_dev *dev = s->private;
index ecd477964d117a13235c5bc212217daa803fff7c..18bf8aeb5f870c699f930572848c5dfab75b442d 100644 (file)
@@ -247,7 +247,8 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
        ret = bios_return->return_code;
 
        if (ret) {
-               if (ret != HPWMI_RET_UNKNOWN_CMDTYPE)
+               if (ret != HPWMI_RET_UNKNOWN_COMMAND &&
+                   ret != HPWMI_RET_UNKNOWN_CMDTYPE)
                        pr_warn("query 0x%x returned error 0x%x\n", query, ret);
                goto out_free;
        }
index b457b0babde390a9b3108103f81c9817d64ca834..2cce82579d09164a95876e7924ee19265425fdc5 100644 (file)
@@ -164,13 +164,29 @@ static const struct i2c_inst_data bsg2150_data[]  = {
        {}
 };
 
-static const struct i2c_inst_data int3515_data[]  = {
-       { "tps6598x", IRQ_RESOURCE_APIC, 0 },
-       { "tps6598x", IRQ_RESOURCE_APIC, 1 },
-       { "tps6598x", IRQ_RESOURCE_APIC, 2 },
-       { "tps6598x", IRQ_RESOURCE_APIC, 3 },
-       {}
-};
+/*
+ * Device with _HID INT3515 (TI PD controllers) has some unresolved interrupt
+ * issues. The most common problem seen is interrupt flood.
+ *
+ * There are at least two known causes. Firstly, on some boards, the
+ * I2CSerialBus resource index does not match the Interrupt resource, i.e. they
+ * are not one-to-one mapped like in the array below. Secondly, on some boards
+ * the IRQ line from the PD controller is not actually connected at all. But the
+ * interrupt flood is also seen on some boards where those are not a problem, so
+ * there are some other problems as well.
+ *
+ * Because of the issues with the interrupt, the device is disabled for now. If
+ * you wish to debug the issues, uncomment the below, and add an entry for the
+ * INT3515 device to the i2c_multi_instance_ids table.
+ *
+ * static const struct i2c_inst_data int3515_data[]  = {
+ *     { "tps6598x", IRQ_RESOURCE_APIC, 0 },
+ *     { "tps6598x", IRQ_RESOURCE_APIC, 1 },
+ *     { "tps6598x", IRQ_RESOURCE_APIC, 2 },
+ *     { "tps6598x", IRQ_RESOURCE_APIC, 3 },
+ *     { }
+ * };
+ */
 
 /*
  * Note new device-ids must also be added to i2c_multi_instantiate_ids in
@@ -179,7 +195,6 @@ static const struct i2c_inst_data int3515_data[]  = {
 static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
        { "BSG1160", (unsigned long)bsg1160_data },
        { "BSG2150", (unsigned long)bsg2150_data },
-       { "INT3515", (unsigned long)int3515_data },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
index 7598cd46cf606d441ce3f61d4837a59da5278bae..5b81bafa5c1650fb591889365db072ccd7f4e06e 100644 (file)
@@ -92,6 +92,7 @@ struct ideapad_private {
        struct dentry *debug;
        unsigned long cfg;
        bool has_hw_rfkill_switch;
+       bool has_touchpad_switch;
        const char *fnesc_guid;
 };
 
@@ -535,7 +536,9 @@ static umode_t ideapad_is_visible(struct kobject *kobj,
        } else if (attr == &dev_attr_fn_lock.attr) {
                supported = acpi_has_method(priv->adev->handle, "HALS") &&
                        acpi_has_method(priv->adev->handle, "SALS");
-       } else
+       } else if (attr == &dev_attr_touchpad.attr)
+               supported = priv->has_touchpad_switch;
+       else
                supported = true;
 
        return supported ? attr->mode : 0;
@@ -867,6 +870,9 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
 {
        unsigned long value;
 
+       if (!priv->has_touchpad_switch)
+               return;
+
        /* Without reading from EC touchpad LED doesn't switch state */
        if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
                /* Some IdeaPads don't really turn off touchpad - they only
@@ -989,6 +995,9 @@ static int ideapad_acpi_add(struct platform_device *pdev)
        priv->platform_device = pdev;
        priv->has_hw_rfkill_switch = dmi_check_system(hw_rfkill_list);
 
+       /* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */
+       priv->has_touchpad_switch = !acpi_dev_present("ELAN0634", NULL, -1);
+
        ret = ideapad_sysfs_init(priv);
        if (ret)
                return ret;
@@ -1006,6 +1015,10 @@ static int ideapad_acpi_add(struct platform_device *pdev)
        if (!priv->has_hw_rfkill_switch)
                write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
 
+       /* The same for Touchpad */
+       if (!priv->has_touchpad_switch)
+               write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, 1);
+
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
                if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
                        ideapad_register_rfkill(priv, i);
index 3b49a1f4061bcdaf689cdcda28980d3b924debd8..30a9062d2b4b8858d05846a1ffb9f6475e0288fd 100644 (file)
@@ -207,19 +207,19 @@ static const struct dmi_system_id dmi_switches_allow_list[] = {
        {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Stream x360 Convertible PC 11"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion 13 x360 PC"),
                },
        },
        {
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion 13 x360 PC"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271"),
                },
        },
        {
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7352"),
                },
        },
        {} /* Array terminator */
index e03df2881dc6dfff51ebbd366892fd6f4c1f96e5..f3e8eca8d86d6c5d5c638aea97c6493e0ce81d7b 100644 (file)
@@ -8783,6 +8783,7 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
        TPACPI_Q_LNV3('N', '1', 'T', TPACPI_FAN_2CTL),  /* P71 */
        TPACPI_Q_LNV3('N', '1', 'U', TPACPI_FAN_2CTL),  /* P51 */
        TPACPI_Q_LNV3('N', '2', 'C', TPACPI_FAN_2CTL),  /* P52 / P72 */
+       TPACPI_Q_LNV3('N', '2', 'N', TPACPI_FAN_2CTL),  /* P53 / P73 */
        TPACPI_Q_LNV3('N', '2', 'E', TPACPI_FAN_2CTL),  /* P1 / X1 Extreme (1st gen) */
        TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2CTL),  /* P1 / X1 Extreme (2nd gen) */
        TPACPI_Q_LNV3('N', '2', 'V', TPACPI_FAN_2CTL),  /* P1 / X1 Extreme (3nd gen) */
@@ -9951,9 +9952,9 @@ static int tpacpi_proxsensor_init(struct ibm_init_struct *iibm)
        if ((palm_err == -ENODEV) && (lap_err == -ENODEV))
                return 0;
        /* Otherwise, if there was an error return it */
-       if (palm_err && (palm_err != ENODEV))
+       if (palm_err && (palm_err != -ENODEV))
                return palm_err;
-       if (lap_err && (lap_err != ENODEV))
+       if (lap_err && (lap_err != -ENODEV))
                return lap_err;
 
        if (has_palmsensor) {
index 5783139d0a1198abcaccf112a955ee14398ed243..c4de932302d6b5f52479d99b95e9558deddaa0ba 100644 (file)
@@ -263,6 +263,16 @@ static const struct ts_dmi_data digma_citi_e200_data = {
        .properties     = digma_citi_e200_props,
 };
 
+static const struct property_entry estar_beauty_hd_props[] = {
+       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+       { }
+};
+
+static const struct ts_dmi_data estar_beauty_hd_data = {
+       .acpi_name      = "GDIX1001:00",
+       .properties     = estar_beauty_hd_props,
+};
+
 static const struct property_entry gp_electronic_t701_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 960),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 640),
@@ -942,6 +952,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
                },
        },
+       {
+               /* Estar Beauty HD (MID 7316R) */
+               .driver_data = (void *)&estar_beauty_hd_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Estar"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"),
+               },
+       },
        {
                /* GP-electronic T701 */
                .driver_data = (void *)&gp_electronic_t701_data,
index a2beee6e09f06b2cdd644e1e819e69e1cdc427f2..5988c300cc82edf1d6fe1f1f4c8b909653ffee91 100644 (file)
@@ -444,7 +444,8 @@ static int vnic_dev_init_devcmd2(struct vnic_dev *vdev)
        fetch_index = ioread32(&vdev->devcmd2->wq.ctrl->fetch_index);
        if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone  */
                pr_err("error in devcmd2 init");
-               return -ENODEV;
+               err = -ENODEV;
+               goto err_free_wq;
        }
 
        /*
@@ -460,7 +461,7 @@ static int vnic_dev_init_devcmd2(struct vnic_dev *vdev)
        err = vnic_dev_alloc_desc_ring(vdev, &vdev->devcmd2->results_ring,
                        DEVCMD2_RING_SIZE, DEVCMD2_DESC_SIZE);
        if (err)
-               goto err_free_wq;
+               goto err_disable_wq;
 
        vdev->devcmd2->result =
                (struct devcmd2_result *) vdev->devcmd2->results_ring.descs;
@@ -481,8 +482,9 @@ static int vnic_dev_init_devcmd2(struct vnic_dev *vdev)
 
 err_free_desc_ring:
        vnic_dev_free_desc_ring(vdev, &vdev->devcmd2->results_ring);
-err_free_wq:
+err_disable_wq:
        vnic_wq_disable(&vdev->devcmd2->wq);
+err_free_wq:
        vnic_wq_free(&vdev->devcmd2->wq);
 err_free_devcmd2:
        kfree(vdev->devcmd2);
index 42e4d35e0d3556985e1685c642c9cfcb04f84930..65f168c41d233211ea6a34f294ce11ca2bf14af5 100644 (file)
@@ -1744,7 +1744,7 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
                iu->pri_task_attr = IBMVFC_SIMPLE_TASK;
        }
 
-       vfc_cmd->correlation = cpu_to_be64(evt);
+       vfc_cmd->correlation = cpu_to_be64((u64)evt);
 
        if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev))))
                return ibmvfc_send_event(evt, vhost, 0);
@@ -2418,7 +2418,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
                tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF));
                evt->sync_iu = &rsp_iu;
 
-               tmf->correlation = cpu_to_be64(evt);
+               tmf->correlation = cpu_to_be64((u64)evt);
 
                init_completion(&evt->comp);
                rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout);
@@ -3007,8 +3007,10 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev)
        unsigned long flags = 0;
 
        spin_lock_irqsave(shost->host_lock, flags);
-       if (sdev->type == TYPE_DISK)
+       if (sdev->type == TYPE_DISK) {
                sdev->allow_restart = 1;
+               blk_queue_rq_timeout(sdev->request_queue, 120 * HZ);
+       }
        spin_unlock_irqrestore(shost->host_lock, flags);
        return 0;
 }
index d71afae6191cbe7be99f006e563dda0ec89b8643..841000445b9a16f31a28b94f4aa7bd2d4ad4bd7d 100644 (file)
@@ -1623,8 +1623,13 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
                rc = fc_exch_done_locked(ep);
                WARN_ON(fc_seq_exch(sp) != ep);
                spin_unlock_bh(&ep->ex_lock);
-               if (!rc)
+               if (!rc) {
                        fc_exch_delete(ep);
+               } else {
+                       FC_EXCH_DBG(ep, "ep is completed already,"
+                                       "hence skip calling the resp\n");
+                       goto skip_resp;
+               }
        }
 
        /*
@@ -1643,6 +1648,7 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
        if (!fc_invoke_resp(ep, sp, fp))
                fc_frame_free(fp);
 
+skip_resp:
        fc_exch_release(ep);
        return;
 rel:
@@ -1899,10 +1905,16 @@ static void fc_exch_reset(struct fc_exch *ep)
 
        fc_exch_hold(ep);
 
-       if (!rc)
+       if (!rc) {
                fc_exch_delete(ep);
+       } else {
+               FC_EXCH_DBG(ep, "ep is completed already,"
+                               "hence skip calling the resp\n");
+               goto skip_resp;
+       }
 
        fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_CLOSED));
+skip_resp:
        fc_seq_set_resp(sp, NULL, ep->arg);
        fc_exch_release(ep);
 }
index af192096a82b172ec188d83e2619f8da4216f21d..63a4f48bdc755a76c421a42976b2ba28b3f68bbe 100644 (file)
@@ -8244,11 +8244,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
                        goto out;
                }
 
+               /* always store 64 bits regardless of addressing */
                sense_ptr = (void *)cmd->frame + ioc->sense_off;
-               if (instance->consistent_mask_64bit)
-                       put_unaligned_le64(sense_handle, sense_ptr);
-               else
-                       put_unaligned_le32(sense_handle, sense_ptr);
+               put_unaligned_le64(sense_handle, sense_ptr);
        }
 
        /*
index 86209455172d69e440b8794b55342d18d065b81e..c299f7e078fb97c79a13d57c1f7918c4fd84e2a5 100644 (file)
@@ -79,5 +79,5 @@ config SCSI_MPT2SAS
        select SCSI_MPT3SAS
        depends on PCI && SCSI
        help
-       Dummy config option for backwards compatiblity: configure the MPT3SAS
+       Dummy config option for backwards compatibility: configure the MPT3SAS
        driver instead.
index f5fc7f518f8afea5e05504400450422b0905bc42..47ad64b06623696ca510da02ffafa0d0149256ce 100644 (file)
@@ -2245,7 +2245,7 @@ qedi_show_boot_tgt_info(struct qedi_ctx *qedi, int type,
                             chap_name);
                break;
        case ISCSI_BOOT_TGT_CHAP_SECRET:
-               rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN,
+               rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_PWD_MAX_LEN,
                             chap_secret);
                break;
        case ISCSI_BOOT_TGT_REV_CHAP_NAME:
@@ -2253,7 +2253,7 @@ qedi_show_boot_tgt_info(struct qedi_ctx *qedi, int type,
                             mchap_name);
                break;
        case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
-               rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN,
+               rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_PWD_MAX_LEN,
                             mchap_secret);
                break;
        case ISCSI_BOOT_TGT_FLAGS:
index 24c0f7ec03511b31791ad399f43e10e88b20fb6a..4a08c450b756f3399116e4dc61ae67e4b8c20d53 100644 (file)
@@ -6740,7 +6740,7 @@ static int __init scsi_debug_init(void)
                k = sdeb_zbc_model_str(sdeb_zbc_model_s);
                if (k < 0) {
                        ret = k;
-                       goto free_vm;
+                       goto free_q_arr;
                }
                sdeb_zbc_model = k;
                switch (sdeb_zbc_model) {
@@ -6753,7 +6753,8 @@ static int __init scsi_debug_init(void)
                        break;
                default:
                        pr_err("Invalid ZBC model\n");
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto free_q_arr;
                }
        }
        if (sdeb_zbc_model != BLK_ZONED_NONE) {
index cba1cf6a1c12dc720277b20e6ecafbc30a3e5677..1e939a2a387f3f60d26cc35577aff20d22522534 100644 (file)
@@ -541,7 +541,14 @@ int srp_reconnect_rport(struct srp_rport *rport)
        res = mutex_lock_interruptible(&rport->mutex);
        if (res)
                goto out;
-       scsi_target_block(&shost->shost_gendev);
+       if (rport->state != SRP_RPORT_FAIL_FAST)
+               /*
+                * sdev state must be SDEV_TRANSPORT_OFFLINE, transition
+                * to SDEV_BLOCK is illegal. Calling scsi_target_unblock()
+                * later is ok though, scsi_internal_device_unblock_nowait()
+                * treats SDEV_TRANSPORT_OFFLINE like SDEV_BLOCK.
+                */
+               scsi_target_block(&shost->shost_gendev);
        res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV;
        pr_debug("%s (state %d): transport.reconnect() returned %d\n",
                 dev_name(&shost->shost_gendev), rport->state, res);
index 679c2c02504763ba31a21c425d58bdfca02baba8..a3d2d4bc4a3dcda79a3b1368bc397eccc6a90549 100644 (file)
@@ -984,8 +984,10 @@ static blk_status_t sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd)
                }
        }
 
-       if (sdp->no_write_same)
+       if (sdp->no_write_same) {
+               rq->rq_flags |= RQF_QUIET;
                return BLK_STS_TARGET;
+       }
 
        if (sdkp->ws16 || lba > 0xffffffff || nr_blocks > 0xffff)
                return sd_setup_write_same16_cmnd(cmd, false);
@@ -3510,10 +3512,8 @@ static int sd_probe(struct device *dev)
 static int sd_remove(struct device *dev)
 {
        struct scsi_disk *sdkp;
-       dev_t devt;
 
        sdkp = dev_get_drvdata(dev);
-       devt = disk_devt(sdkp->disk);
        scsi_autopm_get_device(sdkp->device);
 
        async_synchronize_full_domain(&scsi_sd_pm_domain);
index 3f6dfed4fe84b2178695c851f2892457e82bcb68..b915b38c2b277c5f132a90cdd31d3e9d931fd5ea 100644 (file)
@@ -72,6 +72,7 @@ config SCSI_UFS_DWC_TC_PCI
 config SCSI_UFSHCD_PLATFORM
        tristate "Platform bus based UFS Controller support"
        depends on SCSI_UFSHCD
+       depends on HAS_IOMEM
        help
        This selects the UFS host controller support. Select this if
        you have an UFS controller on Platform bus.
index 82ad31781bc9e127d9fc6834f3b704e69f1d179c..fb32d122f2e3866f6ce3053f4dfc4c07732142b1 100644 (file)
@@ -289,7 +289,8 @@ static inline void ufshcd_wb_config(struct ufs_hba *hba)
        if (ret)
                dev_err(hba->dev, "%s: En WB flush during H8: failed: %d\n",
                        __func__, ret);
-       ufshcd_wb_toggle_flush(hba, true);
+       if (!(hba->quirks & UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL))
+               ufshcd_wb_toggle_flush(hba, true);
 }
 
 static void ufshcd_scsi_unblock_requests(struct ufs_hba *hba)
@@ -3995,6 +3996,8 @@ int ufshcd_link_recovery(struct ufs_hba *hba)
        if (ret)
                dev_err(hba->dev, "%s: link recovery failed, err %d",
                        __func__, ret);
+       else
+               ufshcd_clear_ua_wluns(hba);
 
        return ret;
 }
@@ -4991,7 +4994,8 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
                break;
        } /* end of switch */
 
-       if ((host_byte(result) != DID_OK) && !hba->silence_err_logs)
+       if ((host_byte(result) != DID_OK) &&
+           (host_byte(result) != DID_REQUEUE) && !hba->silence_err_logs)
                ufshcd_print_trs(hba, 1 << lrbp->task_tag, true);
        return result;
 }
@@ -5436,9 +5440,6 @@ static int ufshcd_wb_toggle_flush_during_h8(struct ufs_hba *hba, bool set)
 
 static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable)
 {
-       if (hba->quirks & UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL)
-               return;
-
        if (enable)
                ufshcd_wb_buf_flush_enable(hba);
        else
@@ -6003,6 +6004,9 @@ skip_err_handling:
        ufshcd_scsi_unblock_requests(hba);
        ufshcd_err_handling_unprepare(hba);
        up(&hba->eh_sem);
+
+       if (!err && needs_reset)
+               ufshcd_clear_ua_wluns(hba);
 }
 
 /**
@@ -6297,9 +6301,13 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)
                intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
        }
 
-       if (enabled_intr_status && retval == IRQ_NONE) {
-               dev_err(hba->dev, "%s: Unhandled interrupt 0x%08x\n",
-                                       __func__, intr_status);
+       if (enabled_intr_status && retval == IRQ_NONE &&
+                               !ufshcd_eh_in_progress(hba)) {
+               dev_err(hba->dev, "%s: Unhandled interrupt 0x%08x (0x%08x, 0x%08x)\n",
+                                       __func__,
+                                       intr_status,
+                                       hba->ufs_stats.last_intr_status,
+                                       enabled_intr_status);
                ufshcd_dump_regs(hba, 0, UFSHCI_REG_SPACE_SIZE, "host_regs: ");
        }
 
@@ -6343,7 +6351,10 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
         * Even though we use wait_event() which sleeps indefinitely,
         * the maximum wait time is bounded by %TM_CMD_TIMEOUT.
         */
-       req = blk_get_request(q, REQ_OP_DRV_OUT, BLK_MQ_REQ_RESERVED);
+       req = blk_get_request(q, REQ_OP_DRV_OUT, 0);
+       if (IS_ERR(req))
+               return PTR_ERR(req);
+
        req->end_io_data = &wait;
        free_slot = req->tag;
        WARN_ON_ONCE(free_slot < 0 || free_slot >= hba->nutmrs);
@@ -6661,19 +6672,16 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
 {
        struct Scsi_Host *host;
        struct ufs_hba *hba;
-       unsigned int tag;
        u32 pos;
        int err;
-       u8 resp = 0xF;
-       struct ufshcd_lrb *lrbp;
+       u8 resp = 0xF, lun;
        unsigned long flags;
 
        host = cmd->device->host;
        hba = shost_priv(host);
-       tag = cmd->request->tag;
 
-       lrbp = &hba->lrb[tag];
-       err = ufshcd_issue_tm_cmd(hba, lrbp->lun, 0, UFS_LOGICAL_RESET, &resp);
+       lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
+       err = ufshcd_issue_tm_cmd(hba, lun, 0, UFS_LOGICAL_RESET, &resp);
        if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
                if (!err)
                        err = resp;
@@ -6682,7 +6690,7 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
 
        /* clear the commands that were pending for corresponding LUN */
        for_each_set_bit(pos, &hba->outstanding_reqs, hba->nutrs) {
-               if (hba->lrb[pos].lun == lrbp->lun) {
+               if (hba->lrb[pos].lun == lun) {
                        err = ufshcd_clear_cmd(hba, pos);
                        if (err)
                                break;
@@ -6943,14 +6951,11 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
        ufshcd_set_clk_freq(hba, true);
 
        err = ufshcd_hba_enable(hba);
-       if (err)
-               goto out;
 
        /* Establish the link again and restore the device */
-       err = ufshcd_probe_hba(hba, false);
        if (!err)
-               ufshcd_clear_ua_wluns(hba);
-out:
+               err = ufshcd_probe_hba(hba, false);
+
        if (err)
                dev_err(hba->dev, "%s: Host init failed %d\n", __func__, err);
        ufshcd_update_evt_hist(hba, UFS_EVT_HOST_RESET, (u32)err);
@@ -7721,6 +7726,8 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
        if (ret)
                goto out;
 
+       ufshcd_clear_ua_wluns(hba);
+
        /* Initialize devfreq after UFS device is detected */
        if (ufshcd_is_clkscaling_supported(hba)) {
                memcpy(&hba->clk_scaling.saved_pwr_info.info,
@@ -7922,8 +7929,6 @@ out:
                pm_runtime_put_sync(hba->dev);
                ufshcd_exit_clk_scaling(hba);
                ufshcd_hba_exit(hba);
-       } else {
-               ufshcd_clear_ua_wluns(hba);
        }
 }
 
@@ -8698,6 +8703,8 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
                        ufshcd_wb_need_flush(hba));
        }
 
+       flush_work(&hba->eeh_work);
+
        if (req_dev_pwr_mode != hba->curr_dev_pwr_mode) {
                if (!ufshcd_is_runtime_pm(pm_op))
                        /* ensure that bkops is disabled */
@@ -8710,8 +8717,6 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
                }
        }
 
-       flush_work(&hba->eeh_work);
-
        /*
         * In the case of DeepSleep, the device is expected to remain powered
         * with the link off, so do not check for bkops.
@@ -8780,6 +8785,7 @@ enable_gating:
                ufshcd_resume_clkscaling(hba);
        hba->clk_gating.is_suspended = false;
        hba->dev_info.b_rpm_dev_flush_capable = false;
+       ufshcd_clear_ua_wluns(hba);
        ufshcd_release(hba);
 out:
        if (hba->dev_info.b_rpm_dev_flush_capable) {
@@ -8890,6 +8896,8 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
                cancel_delayed_work(&hba->rpm_dev_flush_recheck_work);
        }
 
+       ufshcd_clear_ua_wluns(hba);
+
        /* Schedule clock gating in case of no access to UFS device yet */
        ufshcd_release(hba);
 
@@ -8938,7 +8946,8 @@ int ufshcd_system_suspend(struct ufs_hba *hba)
        if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) ==
             hba->curr_dev_pwr_mode) &&
            (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) ==
-            hba->uic_link_state))
+            hba->uic_link_state) &&
+            !hba->dev_info.b_rpm_dev_flush_capable)
                goto out;
 
        if (pm_runtime_suspended(hba->dev)) {
index 1217cafdfd4d1d2b691bc6d487dcce5d63755d3e..9b076638457087a01ea168dd67eb8f3981d58e9b 100644 (file)
@@ -140,12 +140,13 @@ struct litex_soc_ctrl_device {
        void __iomem *base;
 };
 
+#ifdef CONFIG_OF
 static const struct of_device_id litex_soc_ctrl_of_match[] = {
        {.compatible = "litex,soc-controller"},
        {},
 };
-
 MODULE_DEVICE_TABLE(of, litex_soc_ctrl_of_match);
+#endif /* CONFIG_OF */
 
 static int litex_soc_ctrl_probe(struct platform_device *pdev)
 {
index 70467b9d61baa3d13e3851e3abd25a36b2f5919e..a3afd1b9ac567bcc48c809edef5d0509ae5dd0aa 100644 (file)
@@ -115,6 +115,7 @@ struct cdns_spi {
        void __iomem *regs;
        struct clk *ref_clk;
        struct clk *pclk;
+       unsigned int clk_rate;
        u32 speed_hz;
        const u8 *txbuf;
        u8 *rxbuf;
@@ -250,7 +251,7 @@ static void cdns_spi_config_clock_freq(struct spi_device *spi,
        u32 ctrl_reg, baud_rate_val;
        unsigned long frequency;
 
-       frequency = clk_get_rate(xspi->ref_clk);
+       frequency = xspi->clk_rate;
 
        ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
 
@@ -558,8 +559,9 @@ static int cdns_spi_probe(struct platform_device *pdev)
        master->auto_runtime_pm = true;
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
+       xspi->clk_rate = clk_get_rate(xspi->ref_clk);
        /* Set to default valid value */
-       master->max_speed_hz = clk_get_rate(xspi->ref_clk) / 4;
+       master->max_speed_hz = xspi->clk_rate / 4;
        xspi->speed_hz = master->max_speed_hz;
 
        master->bits_per_word_mask = SPI_BPW_MASK(8);
index 9494257e1c33f56173dfefb7ef7c2b49100adc01..6d8e0a05a53554b4393752a6a6cad93b6276d548 100644 (file)
@@ -115,14 +115,13 @@ static void fsl_spi_chipselect(struct spi_device *spi, int value)
 {
        struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
        struct fsl_spi_platform_data *pdata;
-       bool pol = spi->mode & SPI_CS_HIGH;
        struct spi_mpc8xxx_cs   *cs = spi->controller_state;
 
        pdata = spi->dev.parent->parent->platform_data;
 
        if (value == BITBANG_CS_INACTIVE) {
                if (pdata->cs_control)
-                       pdata->cs_control(spi, !pol);
+                       pdata->cs_control(spi, false);
        }
 
        if (value == BITBANG_CS_ACTIVE) {
@@ -134,7 +133,7 @@ static void fsl_spi_chipselect(struct spi_device *spi, int value)
                fsl_spi_change_mode(spi);
 
                if (pdata->cs_control)
-                       pdata->cs_control(spi, pol);
+                       pdata->cs_control(spi, true);
        }
 }
 
index 6b171fff007b63dec6d1cb2d0a4e1cd96bc76b63..a5991df2358113cfc7639a23182cc7d5c814392a 100644 (file)
@@ -562,8 +562,6 @@ tcmu_get_block_page(struct tcmu_dev *udev, uint32_t dbi)
 
 static inline void tcmu_free_cmd(struct tcmu_cmd *tcmu_cmd)
 {
-       if (tcmu_cmd->se_cmd)
-               tcmu_cmd->se_cmd->priv = NULL;
        kfree(tcmu_cmd->dbi);
        kmem_cache_free(tcmu_cmd_cache, tcmu_cmd);
 }
@@ -1174,11 +1172,12 @@ tcmu_queue_cmd(struct se_cmd *se_cmd)
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
        mutex_lock(&udev->cmdr_lock);
-       se_cmd->priv = tcmu_cmd;
        if (!(se_cmd->transport_state & CMD_T_ABORTED))
                ret = queue_cmd_ring(tcmu_cmd, &scsi_ret);
        if (ret < 0)
                tcmu_free_cmd(tcmu_cmd);
+       else
+               se_cmd->priv = tcmu_cmd;
        mutex_unlock(&udev->cmdr_lock);
        return scsi_ret;
 }
@@ -1241,6 +1240,7 @@ tcmu_tmr_notify(struct se_device *se_dev, enum tcm_tmreq_table tmf,
 
                list_del_init(&cmd->queue_entry);
                tcmu_free_cmd(cmd);
+               se_cmd->priv = NULL;
                target_complete_cmd(se_cmd, SAM_STAT_TASK_ABORTED);
                unqueued = true;
        }
@@ -1332,6 +1332,7 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
        }
 
 done:
+       se_cmd->priv = NULL;
        if (read_len_valid) {
                pr_debug("read_len = %d\n", read_len);
                target_complete_cmd_with_length(cmd->se_cmd,
@@ -1478,6 +1479,7 @@ static void tcmu_check_expired_queue_cmd(struct tcmu_cmd *cmd)
        se_cmd = cmd->se_cmd;
        tcmu_free_cmd(cmd);
 
+       se_cmd->priv = NULL;
        target_complete_cmd(se_cmd, SAM_STAT_TASK_SET_FULL);
 }
 
@@ -1592,6 +1594,7 @@ static void run_qfull_queue(struct tcmu_dev *udev, bool fail)
                         * removed then LIO core will do the right thing and
                         * fail the retry.
                         */
+                       tcmu_cmd->se_cmd->priv = NULL;
                        target_complete_cmd(tcmu_cmd->se_cmd, SAM_STAT_BUSY);
                        tcmu_free_cmd(tcmu_cmd);
                        continue;
@@ -1605,6 +1608,7 @@ static void run_qfull_queue(struct tcmu_dev *udev, bool fail)
                         * Ignore scsi_ret for now. target_complete_cmd
                         * drops it.
                         */
+                       tcmu_cmd->se_cmd->priv = NULL;
                        target_complete_cmd(tcmu_cmd->se_cmd,
                                            SAM_STAT_CHECK_CONDITION);
                        tcmu_free_cmd(tcmu_cmd);
@@ -2212,6 +2216,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
                if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
                        WARN_ON(!cmd->se_cmd);
                        list_del_init(&cmd->queue_entry);
+                       cmd->se_cmd->priv = NULL;
                        if (err_level == 1) {
                                /*
                                 * Userspace was not able to start the
index 44e15d7fb2f09ea4f90a4fb94bf68ae9e5bf8a89..66d6f1d06f219d716e3ce7895b49984b8cbad432 100644 (file)
@@ -46,60 +46,83 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf)
        return 0;
 }
 
-struct xcopy_dev_search_info {
-       const unsigned char *dev_wwn;
-       struct se_device *found_dev;
-};
-
+/**
+ * target_xcopy_locate_se_dev_e4_iter - compare XCOPY NAA device identifiers
+ *
+ * @se_dev: device being considered for match
+ * @dev_wwn: XCOPY requested NAA dev_wwn
+ * @return: 1 on match, 0 on no-match
+ */
 static int target_xcopy_locate_se_dev_e4_iter(struct se_device *se_dev,
-                                             void *data)
+                                             const unsigned char *dev_wwn)
 {
-       struct xcopy_dev_search_info *info = data;
        unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
        int rc;
 
-       if (!se_dev->dev_attrib.emulate_3pc)
+       if (!se_dev->dev_attrib.emulate_3pc) {
+               pr_debug("XCOPY: emulate_3pc disabled on se_dev %p\n", se_dev);
                return 0;
+       }
 
        memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
        target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]);
 
-       rc = memcmp(&tmp_dev_wwn[0], info->dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
-       if (rc != 0)
-               return 0;
-
-       info->found_dev = se_dev;
-       pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
-
-       rc = target_depend_item(&se_dev->dev_group.cg_item);
+       rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
        if (rc != 0) {
-               pr_err("configfs_depend_item attempt failed: %d for se_dev: %p\n",
-                      rc, se_dev);
-               return rc;
+               pr_debug("XCOPY: skip non-matching: %*ph\n",
+                        XCOPY_NAA_IEEE_REGEX_LEN, tmp_dev_wwn);
+               return 0;
        }
+       pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
 
-       pr_debug("Called configfs_depend_item for se_dev: %p se_dev->se_dev_group: %p\n",
-                se_dev, &se_dev->dev_group);
        return 1;
 }
 
-static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn,
-                                       struct se_device **found_dev)
+static int target_xcopy_locate_se_dev_e4(struct se_session *sess,
+                                       const unsigned char *dev_wwn,
+                                       struct se_device **_found_dev,
+                                       struct percpu_ref **_found_lun_ref)
 {
-       struct xcopy_dev_search_info info;
-       int ret;
-
-       memset(&info, 0, sizeof(info));
-       info.dev_wwn = dev_wwn;
-
-       ret = target_for_each_device(target_xcopy_locate_se_dev_e4_iter, &info);
-       if (ret == 1) {
-               *found_dev = info.found_dev;
-               return 0;
-       } else {
-               pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
-               return -EINVAL;
+       struct se_dev_entry *deve;
+       struct se_node_acl *nacl;
+       struct se_lun *this_lun = NULL;
+       struct se_device *found_dev = NULL;
+
+       /* cmd with NULL sess indicates no associated $FABRIC_MOD */
+       if (!sess)
+               goto err_out;
+
+       pr_debug("XCOPY 0xe4: searching for: %*ph\n",
+                XCOPY_NAA_IEEE_REGEX_LEN, dev_wwn);
+
+       nacl = sess->se_node_acl;
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) {
+               struct se_device *this_dev;
+               int rc;
+
+               this_lun = rcu_dereference(deve->se_lun);
+               this_dev = rcu_dereference_raw(this_lun->lun_se_dev);
+
+               rc = target_xcopy_locate_se_dev_e4_iter(this_dev, dev_wwn);
+               if (rc) {
+                       if (percpu_ref_tryget_live(&this_lun->lun_ref))
+                               found_dev = this_dev;
+                       break;
+               }
        }
+       rcu_read_unlock();
+       if (found_dev == NULL)
+               goto err_out;
+
+       pr_debug("lun_ref held for se_dev: %p se_dev->se_dev_group: %p\n",
+                found_dev, &found_dev->dev_group);
+       *_found_dev = found_dev;
+       *_found_lun_ref = &this_lun->lun_ref;
+       return 0;
+err_out:
+       pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
+       return -EINVAL;
 }
 
 static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop,
@@ -246,12 +269,16 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
 
        switch (xop->op_origin) {
        case XCOL_SOURCE_RECV_OP:
-               rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn,
-                                               &xop->dst_dev);
+               rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
+                                               xop->dst_tid_wwn,
+                                               &xop->dst_dev,
+                                               &xop->remote_lun_ref);
                break;
        case XCOL_DEST_RECV_OP:
-               rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn,
-                                               &xop->src_dev);
+               rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
+                                               xop->src_tid_wwn,
+                                               &xop->src_dev,
+                                               &xop->remote_lun_ref);
                break;
        default:
                pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - "
@@ -391,18 +418,12 @@ static int xcopy_pt_get_cmd_state(struct se_cmd *se_cmd)
 
 static void xcopy_pt_undepend_remotedev(struct xcopy_op *xop)
 {
-       struct se_device *remote_dev;
-
        if (xop->op_origin == XCOL_SOURCE_RECV_OP)
-               remote_dev = xop->dst_dev;
+               pr_debug("putting dst lun_ref for %p\n", xop->dst_dev);
        else
-               remote_dev = xop->src_dev;
-
-       pr_debug("Calling configfs_undepend_item for"
-                 " remote_dev: %p remote_dev->dev_group: %p\n",
-                 remote_dev, &remote_dev->dev_group.cg_item);
+               pr_debug("putting src lun_ref for %p\n", xop->src_dev);
 
-       target_undepend_item(&remote_dev->dev_group.cg_item);
+       percpu_ref_put(xop->remote_lun_ref);
 }
 
 static void xcopy_pt_release_cmd(struct se_cmd *se_cmd)
index c56a1bde9417bc34ae1a6432d35f2acb2ca93067..e5f20005179a86d1414ddbd87939f142b959400c 100644 (file)
@@ -27,6 +27,7 @@ struct xcopy_op {
        struct se_device *dst_dev;
        unsigned char dst_tid_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
        unsigned char local_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
+       struct percpu_ref *remote_lun_ref;
 
        sector_t src_lba;
        sector_t dst_lba;
index 1066eebe3b28b046deb69348b1357c77eed90185..328d5a78792fe78c19400fb78373fcee440c3a99 100644 (file)
@@ -1000,6 +1000,7 @@ static int sifive_serial_probe(struct platform_device *pdev)
        /* Set up clock divider */
        ssp->clkin_rate = clk_get_rate(ssp->clk);
        ssp->baud_rate = SIFIVE_DEFAULT_BAUD_RATE;
+       ssp->port.uartclk = ssp->baud_rate * 16;
        __ssp_update_div(ssp);
 
        platform_set_drvdata(pdev, ssp);
index a8030332a19169b4805c8537b2a0df359a491833..e850f79351cbb4690fe757293935daeab179c5bf 100644 (file)
@@ -2060,16 +2060,6 @@ static struct irq_chip xen_percpu_chip __read_mostly = {
        .irq_ack                = ack_dynirq,
 };
 
-int xen_set_callback_via(uint64_t via)
-{
-       struct xen_hvm_param a;
-       a.domid = DOMID_SELF;
-       a.index = HVM_PARAM_CALLBACK_IRQ;
-       a.value = via;
-       return HYPERVISOR_hvm_op(HVMOP_set_param, &a);
-}
-EXPORT_SYMBOL_GPL(xen_set_callback_via);
-
 #ifdef CONFIG_XEN_PVHVM
 /* Vector callbacks are better than PCI interrupts to receive event
  * channel notifications because we can receive vector callbacks on any
index dd911e1ff782cc4d54556d1d034fa9ed15c0b7bd..18f0ed8b1f93b8fab25824162f86bac9beb2d781 100644 (file)
@@ -132,6 +132,13 @@ static int platform_pci_probe(struct pci_dev *pdev,
                        dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret);
                        goto out;
                }
+               /*
+                * It doesn't strictly *have* to run on CPU0 but it sure
+                * as hell better process the event channel ports delivered
+                * to CPU0.
+                */
+               irq_set_affinity(pdev->irq, cpumask_of(0));
+
                callback_via = get_callback_via(pdev);
                ret = xen_set_callback_via(callback_via);
                if (ret) {
@@ -149,7 +156,6 @@ static int platform_pci_probe(struct pci_dev *pdev,
        ret = gnttab_init();
        if (ret)
                goto grant_out;
-       xenbus_probe(NULL);
        return 0;
 grant_out:
        gnttab_free_auto_xlat_frames();
index b0c73c58f9874a34f81fcd4477cc752cdfdbf381..720a7b7abd46d690f2ed86f544064403ab4f1647 100644 (file)
@@ -717,14 +717,15 @@ static long privcmd_ioctl_restrict(struct file *file, void __user *udata)
        return 0;
 }
 
-static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata)
+static long privcmd_ioctl_mmap_resource(struct file *file,
+                               struct privcmd_mmap_resource __user *udata)
 {
        struct privcmd_data *data = file->private_data;
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
        struct privcmd_mmap_resource kdata;
        xen_pfn_t *pfns = NULL;
-       struct xen_mem_acquire_resource xdata;
+       struct xen_mem_acquire_resource xdata = { };
        int rc;
 
        if (copy_from_user(&kdata, udata, sizeof(kdata)))
@@ -734,6 +735,22 @@ static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata)
        if (data->domid != DOMID_INVALID && data->domid != kdata.dom)
                return -EPERM;
 
+       /* Both fields must be set or unset */
+       if (!!kdata.addr != !!kdata.num)
+               return -EINVAL;
+
+       xdata.domid = kdata.dom;
+       xdata.type = kdata.type;
+       xdata.id = kdata.id;
+
+       if (!kdata.addr && !kdata.num) {
+               /* Query the size of the resource. */
+               rc = HYPERVISOR_memory_op(XENMEM_acquire_resource, &xdata);
+               if (rc)
+                       return rc;
+               return __put_user(xdata.nr_frames, &udata->num);
+       }
+
        mmap_write_lock(mm);
 
        vma = find_vma(mm, kdata.addr);
@@ -768,10 +785,6 @@ static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata)
        } else
                vma->vm_private_data = PRIV_VMA_LOCKED;
 
-       memset(&xdata, 0, sizeof(xdata));
-       xdata.domid = kdata.dom;
-       xdata.type = kdata.type;
-       xdata.id = kdata.id;
        xdata.frame = kdata.idx;
        xdata.nr_frames = kdata.num;
        set_xen_guest_handle(xdata.frame_list, pfns);
index 2a93b7c9c159929557f845c549b7f7676efd3a11..dc153733541441ed624066829d88b407effe429a 100644 (file)
@@ -115,6 +115,7 @@ int xenbus_probe_node(struct xen_bus_type *bus,
                      const char *type,
                      const char *nodename);
 int xenbus_probe_devices(struct xen_bus_type *bus);
+void xenbus_probe(void);
 
 void xenbus_dev_changed(const char *node, struct xen_bus_type *bus);
 
index eb5151fc8efab02899ce764b99a8d6f2955e9ca7..e5fda0256feb3d476aeee5f2d1e28ac7bd29f226 100644 (file)
@@ -57,16 +57,8 @@ DEFINE_MUTEX(xs_response_mutex);
 static int xenbus_irq;
 static struct task_struct *xenbus_task;
 
-static DECLARE_WORK(probe_work, xenbus_probe);
-
-
 static irqreturn_t wake_waiting(int irq, void *unused)
 {
-       if (unlikely(xenstored_ready == 0)) {
-               xenstored_ready = 1;
-               schedule_work(&probe_work);
-       }
-
        wake_up(&xb_waitq);
        return IRQ_HANDLED;
 }
index 44634d970a5ca1f3bb4b0a1278e245121cd69135..c8f0282bb64975b34f44459c0565156293b0ea64 100644 (file)
@@ -683,29 +683,76 @@ void unregister_xenstore_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(unregister_xenstore_notifier);
 
-void xenbus_probe(struct work_struct *unused)
+void xenbus_probe(void)
 {
        xenstored_ready = 1;
 
+       /*
+        * In the HVM case, xenbus_init() deferred its call to
+        * xs_init() in case callbacks were not operational yet.
+        * So do it now.
+        */
+       if (xen_store_domain_type == XS_HVM)
+               xs_init();
+
        /* Notify others that xenstore is up */
        blocking_notifier_call_chain(&xenstore_chain, 0, NULL);
 }
-EXPORT_SYMBOL_GPL(xenbus_probe);
 
-static int __init xenbus_probe_initcall(void)
+/*
+ * Returns true when XenStore init must be deferred in order to
+ * allow the PCI platform device to be initialised, before we
+ * can actually have event channel interrupts working.
+ */
+static bool xs_hvm_defer_init_for_callback(void)
 {
-       if (!xen_domain())
-               return -ENODEV;
+#ifdef CONFIG_XEN_PVHVM
+       return xen_store_domain_type == XS_HVM &&
+               !xen_have_vector_callback;
+#else
+       return false;
+#endif
+}
 
-       if (xen_initial_domain() || xen_hvm_domain())
-               return 0;
+static int __init xenbus_probe_initcall(void)
+{
+       /*
+        * Probe XenBus here in the XS_PV case, and also XS_HVM unless we
+        * need to wait for the platform PCI device to come up.
+        */
+       if (xen_store_domain_type == XS_PV ||
+           (xen_store_domain_type == XS_HVM &&
+            !xs_hvm_defer_init_for_callback()))
+               xenbus_probe();
 
-       xenbus_probe(NULL);
        return 0;
 }
-
 device_initcall(xenbus_probe_initcall);
 
+int xen_set_callback_via(uint64_t via)
+{
+       struct xen_hvm_param a;
+       int ret;
+
+       a.domid = DOMID_SELF;
+       a.index = HVM_PARAM_CALLBACK_IRQ;
+       a.value = via;
+
+       ret = HYPERVISOR_hvm_op(HVMOP_set_param, &a);
+       if (ret)
+               return ret;
+
+       /*
+        * If xenbus_probe_initcall() deferred the xenbus_probe()
+        * due to the callback not functioning yet, we can do it now.
+        */
+       if (!xenstored_ready && xs_hvm_defer_init_for_callback())
+               xenbus_probe();
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(xen_set_callback_via);
+
 /* Set up event channel for xenstored which is run as a local process
  * (this is normally used only in dom0)
  */
@@ -818,11 +865,17 @@ static int __init xenbus_init(void)
                break;
        }
 
-       /* Initialize the interface to xenstore. */
-       err = xs_init();
-       if (err) {
-               pr_warn("Error initializing xenstore comms: %i\n", err);
-               goto out_error;
+       /*
+        * HVM domains may not have a functional callback yet. In that
+        * case let xs_init() be called from xenbus_probe(), which will
+        * get invoked at an appropriate time.
+        */
+       if (xen_store_domain_type != XS_HVM) {
+               err = xs_init();
+               if (err) {
+                       pr_warn("Error initializing xenstore comms: %i\n", err);
+                       goto out_error;
+               }
        }
 
        if ((xen_store_domain_type != XS_LOCAL) &&
index 02d7d7b2563b5cb9f0fdc7e8fc9e910731016fe3..9cadacf3ec2754def54db3505c4a5cc565329be2 100644 (file)
@@ -3117,7 +3117,7 @@ void btrfs_backref_error_cleanup(struct btrfs_backref_cache *cache,
                list_del_init(&lower->list);
                if (lower == node)
                        node = NULL;
-               btrfs_backref_free_node(cache, lower);
+               btrfs_backref_drop_node(cache, lower);
        }
 
        btrfs_backref_cleanup_node(cache, node);
index 52f2198d44c95c513d942af7a50f6807820cd931..0886e81e554020daf145ba6a0b0044e6aeb5fc54 100644 (file)
@@ -2669,7 +2669,8 @@ again:
         * Go through delayed refs for all the stuff we've just kicked off
         * and then loop back (just once)
         */
-       ret = btrfs_run_delayed_refs(trans, 0);
+       if (!ret)
+               ret = btrfs_run_delayed_refs(trans, 0);
        if (!ret && loops == 0) {
                loops++;
                spin_lock(&cur_trans->dirty_bgs_lock);
index 1dfd4b2d0e1e8f868f654beb25826c050b8fb1a8..6b35b7e8813697e59c3e97b27e4c952a8973edfd 100644 (file)
@@ -1457,7 +1457,7 @@ void btrfs_check_leaked_roots(struct btrfs_fs_info *fs_info)
                root = list_first_entry(&fs_info->allocated_roots,
                                        struct btrfs_root, leak_list);
                btrfs_err(fs_info, "leaked root %s refcount %d",
-                         btrfs_root_name(root->root_key.objectid, buf),
+                         btrfs_root_name(&root->root_key, buf),
                          refcount_read(&root->refs));
                while (refcount_read(&root->refs) > 1)
                        btrfs_put_root(root);
index d79b8369e6aafedfae71c0a7dcb1299c6c655aee..30b1a630dc2f88b13d1612d5ec8f1dc4cf3f4ad7 100644 (file)
@@ -5549,7 +5549,15 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref, int for_reloc)
                                goto out_free;
                        }
 
-                       trans = btrfs_start_transaction(tree_root, 0);
+                      /*
+                       * Use join to avoid potential EINTR from transaction
+                       * start. See wait_reserve_ticket and the whole
+                       * reservation callchain.
+                       */
+                       if (for_reloc)
+                               trans = btrfs_join_transaction(tree_root);
+                       else
+                               trans = btrfs_start_transaction(tree_root, 0);
                        if (IS_ERR(trans)) {
                                err = PTR_ERR(trans);
                                goto out_free;
index 6e3b72e63e4226d50014f5058da3b3cabd2c31a8..c9cee458e001bf8bfe5bd00d2aa8e5c68d51bcdd 100644 (file)
@@ -676,9 +676,7 @@ alloc_extent_state_atomic(struct extent_state *prealloc)
 
 static void extent_io_tree_panic(struct extent_io_tree *tree, int err)
 {
-       struct inode *inode = tree->private_data;
-
-       btrfs_panic(btrfs_sb(inode->i_sb), err,
+       btrfs_panic(tree->fs_info, err,
        "locking error: extent tree was modified by another thread while locked");
 }
 
index 070716650df87e2dc85700209f2b5eb73fc3206a..a8e0a6b038d3efb2c53a98ae8370262cd4101369 100644 (file)
@@ -9390,7 +9390,8 @@ static struct btrfs_delalloc_work *btrfs_alloc_delalloc_work(struct inode *inode
  * some fairly slow code that needs optimization. This walks the list
  * of all the inodes with pending delalloc and forces them to disk.
  */
-static int start_delalloc_inodes(struct btrfs_root *root, u64 *nr, bool snapshot,
+static int start_delalloc_inodes(struct btrfs_root *root,
+                                struct writeback_control *wbc, bool snapshot,
                                 bool in_reclaim_context)
 {
        struct btrfs_inode *binode;
@@ -9399,6 +9400,7 @@ static int start_delalloc_inodes(struct btrfs_root *root, u64 *nr, bool snapshot
        struct list_head works;
        struct list_head splice;
        int ret = 0;
+       bool full_flush = wbc->nr_to_write == LONG_MAX;
 
        INIT_LIST_HEAD(&works);
        INIT_LIST_HEAD(&splice);
@@ -9427,18 +9429,24 @@ static int start_delalloc_inodes(struct btrfs_root *root, u64 *nr, bool snapshot
                if (snapshot)
                        set_bit(BTRFS_INODE_SNAPSHOT_FLUSH,
                                &binode->runtime_flags);
-               work = btrfs_alloc_delalloc_work(inode);
-               if (!work) {
-                       iput(inode);
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               list_add_tail(&work->list, &works);
-               btrfs_queue_work(root->fs_info->flush_workers,
-                                &work->work);
-               if (*nr != U64_MAX) {
-                       (*nr)--;
-                       if (*nr == 0)
+               if (full_flush) {
+                       work = btrfs_alloc_delalloc_work(inode);
+                       if (!work) {
+                               iput(inode);
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+                       list_add_tail(&work->list, &works);
+                       btrfs_queue_work(root->fs_info->flush_workers,
+                                        &work->work);
+               } else {
+                       ret = sync_inode(inode, wbc);
+                       if (!ret &&
+                           test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
+                                    &BTRFS_I(inode)->runtime_flags))
+                               ret = sync_inode(inode, wbc);
+                       btrfs_add_delayed_iput(inode);
+                       if (ret || wbc->nr_to_write <= 0)
                                goto out;
                }
                cond_resched();
@@ -9464,18 +9472,29 @@ out:
 
 int btrfs_start_delalloc_snapshot(struct btrfs_root *root)
 {
+       struct writeback_control wbc = {
+               .nr_to_write = LONG_MAX,
+               .sync_mode = WB_SYNC_NONE,
+               .range_start = 0,
+               .range_end = LLONG_MAX,
+       };
        struct btrfs_fs_info *fs_info = root->fs_info;
-       u64 nr = U64_MAX;
 
        if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state))
                return -EROFS;
 
-       return start_delalloc_inodes(root, &nr, true, false);
+       return start_delalloc_inodes(root, &wbc, true, false);
 }
 
 int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, u64 nr,
                               bool in_reclaim_context)
 {
+       struct writeback_control wbc = {
+               .nr_to_write = (nr == U64_MAX) ? LONG_MAX : (unsigned long)nr,
+               .sync_mode = WB_SYNC_NONE,
+               .range_start = 0,
+               .range_end = LLONG_MAX,
+       };
        struct btrfs_root *root;
        struct list_head splice;
        int ret;
@@ -9489,6 +9508,13 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, u64 nr,
        spin_lock(&fs_info->delalloc_root_lock);
        list_splice_init(&fs_info->delalloc_roots, &splice);
        while (!list_empty(&splice) && nr) {
+               /*
+                * Reset nr_to_write here so we know that we're doing a full
+                * flush.
+                */
+               if (nr == U64_MAX)
+                       wbc.nr_to_write = LONG_MAX;
+
                root = list_first_entry(&splice, struct btrfs_root,
                                        delalloc_root);
                root = btrfs_grab_root(root);
@@ -9497,9 +9523,9 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, u64 nr,
                               &fs_info->delalloc_roots);
                spin_unlock(&fs_info->delalloc_root_lock);
 
-               ret = start_delalloc_inodes(root, &nr, false, in_reclaim_context);
+               ret = start_delalloc_inodes(root, &wbc, false, in_reclaim_context);
                btrfs_put_root(root);
-               if (ret < 0)
+               if (ret < 0 || wbc.nr_to_write <= 0)
                        goto out;
                spin_lock(&fs_info->delalloc_root_lock);
        }
index fe5e0026129d521041f78f08c8a5b83a54b7620a..aae1027bd76a1379e9397bef191b97ef3d978189 100644 (file)
@@ -26,22 +26,22 @@ static const struct root_name_map root_map[] = {
        { BTRFS_DATA_RELOC_TREE_OBJECTID,       "DATA_RELOC_TREE"       },
 };
 
-const char *btrfs_root_name(u64 objectid, char *buf)
+const char *btrfs_root_name(const struct btrfs_key *key, char *buf)
 {
        int i;
 
-       if (objectid == BTRFS_TREE_RELOC_OBJECTID) {
+       if (key->objectid == BTRFS_TREE_RELOC_OBJECTID) {
                snprintf(buf, BTRFS_ROOT_NAME_BUF_LEN,
-                        "TREE_RELOC offset=%llu", objectid);
+                        "TREE_RELOC offset=%llu", key->offset);
                return buf;
        }
 
        for (i = 0; i < ARRAY_SIZE(root_map); i++) {
-               if (root_map[i].id == objectid)
+               if (root_map[i].id == key->objectid)
                        return root_map[i].name;
        }
 
-       snprintf(buf, BTRFS_ROOT_NAME_BUF_LEN, "%llu", objectid);
+       snprintf(buf, BTRFS_ROOT_NAME_BUF_LEN, "%llu", key->objectid);
        return buf;
 }
 
index 78b99385a503fb9bc78fc4edf49fe38838837174..8c3e9319ec4efe455709f1ac5fb63a45302e4833 100644 (file)
@@ -11,6 +11,6 @@
 
 void btrfs_print_leaf(struct extent_buffer *l);
 void btrfs_print_tree(struct extent_buffer *c, bool follow);
-const char *btrfs_root_name(u64 objectid, char *buf);
+const char *btrfs_root_name(const struct btrfs_key *key, char *buf);
 
 #endif
index 19b7db8b211719b33938dcefeaaa07640787509b..df63ef64c5c0dd3512eaa70aabcf0db8509abef6 100644 (file)
@@ -2975,11 +2975,16 @@ static int delete_v1_space_cache(struct extent_buffer *leaf,
                return 0;
 
        for (i = 0; i < btrfs_header_nritems(leaf); i++) {
+               u8 type;
+
                btrfs_item_key_to_cpu(leaf, &key, i);
                if (key.type != BTRFS_EXTENT_DATA_KEY)
                        continue;
                ei = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item);
-               if (btrfs_file_extent_type(leaf, ei) == BTRFS_FILE_EXTENT_REG &&
+               type = btrfs_file_extent_type(leaf, ei);
+
+               if ((type == BTRFS_FILE_EXTENT_REG ||
+                    type == BTRFS_FILE_EXTENT_PREALLOC) &&
                    btrfs_file_extent_disk_bytenr(leaf, ei) == data_bytenr) {
                        found = true;
                        space_cache_ino = key.objectid;
index ae97f4dbaff30f9004f915e91d2672f694db74f5..78a35374d492914d94004d65268bda8d4da54a01 100644 (file)
@@ -5512,6 +5512,21 @@ static int clone_range(struct send_ctx *sctx,
                        break;
                offset += clone_len;
                clone_root->offset += clone_len;
+
+               /*
+                * If we are cloning from the file we are currently processing,
+                * and using the send root as the clone root, we must stop once
+                * the current clone offset reaches the current eof of the file
+                * at the receiver, otherwise we would issue an invalid clone
+                * operation (source range going beyond eof) and cause the
+                * receiver to fail. So if we reach the current eof, bail out
+                * and fallback to a regular write.
+                */
+               if (clone_root->root == sctx->send_root &&
+                   clone_root->ino == sctx->cur_ino &&
+                   clone_root->offset >= sctx->cur_inode_next_write_offset)
+                       break;
+
                data_offset += clone_len;
 next:
                path->slots[0]++;
index 67e55c5479b8e2b66024d4d5525867dc3ee0e567..e8347461c8ddddeee4169dc8df66171b7f0dce7f 100644 (file)
@@ -532,7 +532,9 @@ static void shrink_delalloc(struct btrfs_fs_info *fs_info,
 
        loops = 0;
        while ((delalloc_bytes || dio_bytes) && loops < 3) {
-               btrfs_start_delalloc_roots(fs_info, items, true);
+               u64 nr_pages = min(delalloc_bytes, to_reclaim) >> PAGE_SHIFT;
+
+               btrfs_start_delalloc_roots(fs_info, nr_pages, true);
 
                loops++;
                if (wait_ordered && !trans) {
index 8e0f7a1029c6c8002b08a781efd17be012330a1c..6af7f2bf92de7d18c834147b6fbc09eb0dc6f062 100644 (file)
@@ -2264,14 +2264,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
         */
        btrfs_free_log_root_tree(trans, fs_info);
 
-       /*
-        * commit_fs_roots() can call btrfs_save_ino_cache(), which generates
-        * new delayed refs. Must handle them or qgroup can be wrong.
-        */
-       ret = btrfs_run_delayed_refs(trans, (unsigned long)-1);
-       if (ret)
-               goto unlock_tree_log;
-
        /*
         * Since fs roots are all committed, we can get a quite accurate
         * new_roots. So let's do quota accounting.
index 028e733e42f3b5fe01668b69e9c2a552722c231c..582061c7b54716e71563790beda87baa7fb26460 100644 (file)
@@ -760,6 +760,7 @@ int btrfs_check_chunk_valid(struct extent_buffer *leaf,
 {
        struct btrfs_fs_info *fs_info = leaf->fs_info;
        u64 length;
+       u64 chunk_end;
        u64 stripe_len;
        u16 num_stripes;
        u16 sub_stripes;
@@ -814,6 +815,12 @@ int btrfs_check_chunk_valid(struct extent_buffer *leaf,
                          "invalid chunk length, have %llu", length);
                return -EUCLEAN;
        }
+       if (unlikely(check_add_overflow(logical, length, &chunk_end))) {
+               chunk_err(leaf, chunk, logical,
+"invalid chunk logical start and length, have logical start %llu length %llu",
+                         logical, length);
+               return -EUCLEAN;
+       }
        if (unlikely(!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN)) {
                chunk_err(leaf, chunk, logical,
                          "invalid chunk stripe length: %llu",
index b62be84833e9a84654b581bdc287e4ffe6d952f8..0a6de859eb2226a2283076659fffe4afd22dd32b 100644 (file)
@@ -4317,6 +4317,8 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info)
                btrfs_warn(fs_info,
        "balance: cannot set exclusive op status, resume manually");
 
+       btrfs_release_path(path);
+
        mutex_lock(&fs_info->balance_mutex);
        BUG_ON(fs_info->balance_ctl);
        spin_lock(&fs_info->balance_lock);
index 8bda092e60c5a00118ec8d5159f8a30bdcd38a04..e027c718ca01adea87dbd12bd5fa7b2945fb9c0c 100644 (file)
@@ -413,7 +413,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
 
        inode = d_backing_inode(object->backer);
        ASSERT(S_ISREG(inode->i_mode));
-       ASSERT(inode->i_mapping->a_ops->readpages);
 
        /* calculate the shift required to use bmap */
        shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits;
@@ -713,7 +712,6 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
 
        inode = d_backing_inode(object->backer);
        ASSERT(S_ISREG(inode->i_mode));
-       ASSERT(inode->i_mapping->a_ops->readpages);
 
        /* calculate the shift required to use bmap */
        shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits;
index 840587037b59bcceefd8a715482c05249c3d3e88..d87bd852ed961d3e99d676479bea899aacf65ac2 100644 (file)
@@ -5038,7 +5038,7 @@ bad:
        return;
 }
 
-static struct ceph_connection *con_get(struct ceph_connection *con)
+static struct ceph_connection *mds_get_con(struct ceph_connection *con)
 {
        struct ceph_mds_session *s = con->private;
 
@@ -5047,7 +5047,7 @@ static struct ceph_connection *con_get(struct ceph_connection *con)
        return NULL;
 }
 
-static void con_put(struct ceph_connection *con)
+static void mds_put_con(struct ceph_connection *con)
 {
        struct ceph_mds_session *s = con->private;
 
@@ -5058,7 +5058,7 @@ static void con_put(struct ceph_connection *con)
  * if the client is unresponsive for long enough, the mds will kill
  * the session entirely.
  */
-static void peer_reset(struct ceph_connection *con)
+static void mds_peer_reset(struct ceph_connection *con)
 {
        struct ceph_mds_session *s = con->private;
        struct ceph_mds_client *mdsc = s->s_mdsc;
@@ -5067,7 +5067,7 @@ static void peer_reset(struct ceph_connection *con)
        send_mds_reconnect(mdsc, s);
 }
 
-static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
+static void mds_dispatch(struct ceph_connection *con, struct ceph_msg *msg)
 {
        struct ceph_mds_session *s = con->private;
        struct ceph_mds_client *mdsc = s->s_mdsc;
@@ -5125,8 +5125,8 @@ out:
  * Note: returned pointer is the address of a structure that's
  * managed separately.  Caller must *not* attempt to free it.
  */
-static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
-                                       int *proto, int force_new)
+static struct ceph_auth_handshake *
+mds_get_authorizer(struct ceph_connection *con, int *proto, int force_new)
 {
        struct ceph_mds_session *s = con->private;
        struct ceph_mds_client *mdsc = s->s_mdsc;
@@ -5142,7 +5142,7 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
        return auth;
 }
 
-static int add_authorizer_challenge(struct ceph_connection *con,
+static int mds_add_authorizer_challenge(struct ceph_connection *con,
                                    void *challenge_buf, int challenge_buf_len)
 {
        struct ceph_mds_session *s = con->private;
@@ -5153,7 +5153,7 @@ static int add_authorizer_challenge(struct ceph_connection *con,
                                            challenge_buf, challenge_buf_len);
 }
 
-static int verify_authorizer_reply(struct ceph_connection *con)
+static int mds_verify_authorizer_reply(struct ceph_connection *con)
 {
        struct ceph_mds_session *s = con->private;
        struct ceph_mds_client *mdsc = s->s_mdsc;
@@ -5165,7 +5165,7 @@ static int verify_authorizer_reply(struct ceph_connection *con)
                NULL, NULL, NULL, NULL);
 }
 
-static int invalidate_authorizer(struct ceph_connection *con)
+static int mds_invalidate_authorizer(struct ceph_connection *con)
 {
        struct ceph_mds_session *s = con->private;
        struct ceph_mds_client *mdsc = s->s_mdsc;
@@ -5288,15 +5288,15 @@ static int mds_check_message_signature(struct ceph_msg *msg)
 }
 
 static const struct ceph_connection_operations mds_con_ops = {
-       .get = con_get,
-       .put = con_put,
-       .dispatch = dispatch,
-       .get_authorizer = get_authorizer,
-       .add_authorizer_challenge = add_authorizer_challenge,
-       .verify_authorizer_reply = verify_authorizer_reply,
-       .invalidate_authorizer = invalidate_authorizer,
-       .peer_reset = peer_reset,
+       .get = mds_get_con,
+       .put = mds_put_con,
        .alloc_msg = mds_alloc_msg,
+       .dispatch = mds_dispatch,
+       .peer_reset = mds_peer_reset,
+       .get_authorizer = mds_get_authorizer,
+       .add_authorizer_challenge = mds_add_authorizer_challenge,
+       .verify_authorizer_reply = mds_verify_authorizer_reply,
+       .invalidate_authorizer = mds_invalidate_authorizer,
        .sign_message = mds_sign_message,
        .check_message_signature = mds_check_message_signature,
        .get_auth_request = mds_get_auth_request,
index b9df85506938d55fa86ac2ceaf19ad61ad188b43..c8ef24bac94fc7015df7358f52a2478ec8355f74 100644 (file)
@@ -2195,7 +2195,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
        if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
                tcon->nohandlecache = ctx->nohandlecache;
        else
-               tcon->nohandlecache = 1;
+               tcon->nohandlecache = true;
        tcon->nodelete = ctx->nodelete;
        tcon->local_lease = ctx->local_lease;
        INIT_LIST_HEAD(&tcon->pending_opens);
@@ -2628,7 +2628,7 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
        } else if (ctx)
                tcon->unix_ext = 1; /* Unix Extensions supported */
 
-       if (tcon->unix_ext == 0) {
+       if (!tcon->unix_ext) {
                cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
                return;
        }
@@ -3740,7 +3740,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
 
        if (!ses->binding) {
                ses->capabilities = server->capabilities;
-               if (linuxExtEnabled == 0)
+               if (!linuxExtEnabled)
                        ses->capabilities &= (~server->vals->cap_unix);
 
                if (ses->auth_key.response) {
index 6ad6ba5f6ebeef20bcf68f2d3ae27e432dcd4d04..0fdb0de7ff861b89e90ebc43b40921f79411eef2 100644 (file)
@@ -1260,7 +1260,8 @@ void dfs_cache_del_vol(const char *fullpath)
        vi = find_vol(fullpath);
        spin_unlock(&vol_list_lock);
 
-       kref_put(&vi->refcnt, vol_release);
+       if (!IS_ERR(vi))
+               kref_put(&vi->refcnt, vol_release);
 }
 
 /**
index 0afccbbed2e65363ef029eb6c5caf3af2cb77a70..076bcadc756a751ffaa43b55a107404b33b203fa 100644 (file)
@@ -303,8 +303,6 @@ do {                                                                        \
 int
 smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx)
 {
-       int rc = 0;
-
        memcpy(new_ctx, ctx, sizeof(*ctx));
        new_ctx->prepath = NULL;
        new_ctx->mount_options = NULL;
@@ -327,7 +325,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx
        DUP_CTX_STR(nodename);
        DUP_CTX_STR(iocharset);
 
-       return rc;
+       return 0;
 }
 
 static int
index 067eb44c7baa863c1e7ccd2c2f599be0b067f320..794fc3b68b4f96905eef5c0d6e27b03656753c1b 100644 (file)
@@ -3248,7 +3248,7 @@ close_exit:
        free_rsp_buf(resp_buftype, rsp);
 
        /* retry close in a worker thread if this one is interrupted */
-       if (rc == -EINTR) {
+       if (is_interrupt_error(rc)) {
                int tmp_rc;
 
                tmp_rc = smb2_handle_cancelled_close(tcon, persistent_fid,
index 204a622b89ed3575d3e5cda23e115341615afb7a..d85edf5d1429418728d9fa44fac2a2d9a6df7684 100644 (file)
@@ -424,7 +424,7 @@ struct smb2_rdma_transform_capabilities_context {
        __le16  TransformCount;
        __u16   Reserved1;
        __u32   Reserved2;
-       __le16  RDMATransformIds[1];
+       __le16  RDMATransformIds[];
 } __packed;
 
 /* Signing algorithms */
index e9abb41aa89bcc12002c61d777d4c4f728e9ffb8..95ef26b555b911c620a5c357bea82bb25e3c8f11 100644 (file)
@@ -338,7 +338,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
        if (ssocket == NULL)
                return -EAGAIN;
 
-       if (signal_pending(current)) {
+       if (fatal_signal_pending(current)) {
                cifs_dbg(FYI, "signal pending before send request\n");
                return -ERESTARTSYS;
        }
@@ -429,7 +429,7 @@ unmask:
 
        if (signal_pending(current) && (total_len != send_length)) {
                cifs_dbg(FYI, "signal is pending after attempt to send\n");
-               rc = -EINTR;
+               rc = -ERESTARTSYS;
        }
 
        /* uncork it */
index 1a0a827a7f34578984f6185c9d235d4248bae8a7..be799040a4154ab075a7aeb104309730ce8ddc8e 100644 (file)
@@ -372,20 +372,3 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
        }
        return err;
 }
-
-int __ext4_handle_dirty_super(const char *where, unsigned int line,
-                             handle_t *handle, struct super_block *sb)
-{
-       struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
-       int err = 0;
-
-       ext4_superblock_csum_set(sb);
-       if (ext4_handle_valid(handle)) {
-               err = jbd2_journal_dirty_metadata(handle, bh);
-               if (err)
-                       ext4_journal_abort_handle(where, line, __func__,
-                                                 bh, handle, err);
-       } else
-               mark_buffer_dirty(bh);
-       return err;
-}
index a124c68b0c75e10938578dab8f257c09e70cff86..0d2fa423b7adbea8e4e12eec74552ee71884b861 100644 (file)
@@ -244,9 +244,6 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
                                 handle_t *handle, struct inode *inode,
                                 struct buffer_head *bh);
 
-int __ext4_handle_dirty_super(const char *where, unsigned int line,
-                             handle_t *handle, struct super_block *sb);
-
 #define ext4_journal_get_write_access(handle, bh) \
        __ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh))
 #define ext4_forget(handle, is_metadata, inode, bh, block_nr) \
@@ -257,8 +254,6 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
 #define ext4_handle_dirty_metadata(handle, inode, bh) \
        __ext4_handle_dirty_metadata(__func__, __LINE__, (handle), (inode), \
                                     (bh))
-#define ext4_handle_dirty_super(handle, sb) \
-       __ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb))
 
 handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
                                  int type, int blocks, int rsv_blocks,
index 4fcc21c25e79399c8b3ae9069d93d063e78d50d2..0a14a7c87bf82e3b20748cc627fb40d03dad6268 100644 (file)
@@ -604,13 +604,13 @@ void ext4_fc_track_range(handle_t *handle, struct inode *inode, ext4_lblk_t star
        trace_ext4_fc_track_range(inode, start, end, ret);
 }
 
-static void ext4_fc_submit_bh(struct super_block *sb)
+static void ext4_fc_submit_bh(struct super_block *sb, bool is_tail)
 {
        int write_flags = REQ_SYNC;
        struct buffer_head *bh = EXT4_SB(sb)->s_fc_bh;
 
-       /* TODO: REQ_FUA | REQ_PREFLUSH is unnecessarily expensive. */
-       if (test_opt(sb, BARRIER))
+       /* Add REQ_FUA | REQ_PREFLUSH only its tail */
+       if (test_opt(sb, BARRIER) && is_tail)
                write_flags |= REQ_FUA | REQ_PREFLUSH;
        lock_buffer(bh);
        set_buffer_dirty(bh);
@@ -684,7 +684,7 @@ static u8 *ext4_fc_reserve_space(struct super_block *sb, int len, u32 *crc)
                *crc = ext4_chksum(sbi, *crc, tl, sizeof(*tl));
        if (pad_len > 0)
                ext4_fc_memzero(sb, tl + 1, pad_len, crc);
-       ext4_fc_submit_bh(sb);
+       ext4_fc_submit_bh(sb, false);
 
        ret = jbd2_fc_get_buf(EXT4_SB(sb)->s_journal, &bh);
        if (ret)
@@ -741,7 +741,7 @@ static int ext4_fc_write_tail(struct super_block *sb, u32 crc)
        tail.fc_crc = cpu_to_le32(crc);
        ext4_fc_memcpy(sb, dst, &tail.fc_crc, sizeof(tail.fc_crc), NULL);
 
-       ext4_fc_submit_bh(sb);
+       ext4_fc_submit_bh(sb, true);
 
        return 0;
 }
@@ -1268,7 +1268,7 @@ static void ext4_fc_cleanup(journal_t *journal, int full)
        list_splice_init(&sbi->s_fc_dentry_q[FC_Q_STAGING],
                                &sbi->s_fc_dentry_q[FC_Q_MAIN]);
        list_splice_init(&sbi->s_fc_q[FC_Q_STAGING],
-                               &sbi->s_fc_q[FC_Q_STAGING]);
+                               &sbi->s_fc_q[FC_Q_MAIN]);
 
        ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING);
        ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
@@ -1318,14 +1318,14 @@ static int ext4_fc_replay_unlink(struct super_block *sb, struct ext4_fc_tl *tl)
        entry.len = darg.dname_len;
        inode = ext4_iget(sb, darg.ino, EXT4_IGET_NORMAL);
 
-       if (IS_ERR_OR_NULL(inode)) {
+       if (IS_ERR(inode)) {
                jbd_debug(1, "Inode %d not found", darg.ino);
                return 0;
        }
 
        old_parent = ext4_iget(sb, darg.parent_ino,
                                EXT4_IGET_NORMAL);
-       if (IS_ERR_OR_NULL(old_parent)) {
+       if (IS_ERR(old_parent)) {
                jbd_debug(1, "Dir with inode  %d not found", darg.parent_ino);
                iput(inode);
                return 0;
@@ -1410,7 +1410,7 @@ static int ext4_fc_replay_link(struct super_block *sb, struct ext4_fc_tl *tl)
                        darg.parent_ino, darg.dname_len);
 
        inode = ext4_iget(sb, darg.ino, EXT4_IGET_NORMAL);
-       if (IS_ERR_OR_NULL(inode)) {
+       if (IS_ERR(inode)) {
                jbd_debug(1, "Inode not found.");
                return 0;
        }
@@ -1466,10 +1466,11 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl)
        trace_ext4_fc_replay(sb, tag, ino, 0, 0);
 
        inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
-       if (!IS_ERR_OR_NULL(inode)) {
+       if (!IS_ERR(inode)) {
                ext4_ext_clear_bb(inode);
                iput(inode);
        }
+       inode = NULL;
 
        ext4_fc_record_modified_inode(sb, ino);
 
@@ -1512,7 +1513,7 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl)
 
        /* Given that we just wrote the inode on disk, this SHOULD succeed. */
        inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
-       if (IS_ERR_OR_NULL(inode)) {
+       if (IS_ERR(inode)) {
                jbd_debug(1, "Inode not found.");
                return -EFSCORRUPTED;
        }
@@ -1564,7 +1565,7 @@ static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl)
                goto out;
 
        inode = ext4_iget(sb, darg.ino, EXT4_IGET_NORMAL);
-       if (IS_ERR_OR_NULL(inode)) {
+       if (IS_ERR(inode)) {
                jbd_debug(1, "inode %d not found.", darg.ino);
                inode = NULL;
                ret = -EINVAL;
@@ -1577,7 +1578,7 @@ static int ext4_fc_replay_create(struct super_block *sb, struct ext4_fc_tl *tl)
                 * dot and dot dot dirents are setup properly.
                 */
                dir = ext4_iget(sb, darg.parent_ino, EXT4_IGET_NORMAL);
-               if (IS_ERR_OR_NULL(dir)) {
+               if (IS_ERR(dir)) {
                        jbd_debug(1, "Dir %d not found.", darg.ino);
                        goto out;
                }
@@ -1653,7 +1654,7 @@ static int ext4_fc_replay_add_range(struct super_block *sb,
 
        inode = ext4_iget(sb, le32_to_cpu(fc_add_ex->fc_ino),
                                EXT4_IGET_NORMAL);
-       if (IS_ERR_OR_NULL(inode)) {
+       if (IS_ERR(inode)) {
                jbd_debug(1, "Inode not found.");
                return 0;
        }
@@ -1777,7 +1778,7 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl)
                le32_to_cpu(lrange->fc_ino), cur, remaining);
 
        inode = ext4_iget(sb, le32_to_cpu(lrange->fc_ino), EXT4_IGET_NORMAL);
-       if (IS_ERR_OR_NULL(inode)) {
+       if (IS_ERR(inode)) {
                jbd_debug(1, "Inode %d not found", le32_to_cpu(lrange->fc_ino));
                return 0;
        }
@@ -1832,7 +1833,7 @@ static void ext4_fc_set_bitmaps_and_counters(struct super_block *sb)
        for (i = 0; i < state->fc_modified_inodes_used; i++) {
                inode = ext4_iget(sb, state->fc_modified_inodes[i],
                        EXT4_IGET_NORMAL);
-               if (IS_ERR_OR_NULL(inode)) {
+               if (IS_ERR(inode)) {
                        jbd_debug(1, "Inode %d not found.",
                                state->fc_modified_inodes[i]);
                        continue;
@@ -1849,7 +1850,7 @@ static void ext4_fc_set_bitmaps_and_counters(struct super_block *sb)
 
                        if (ret > 0) {
                                path = ext4_find_extent(inode, map.m_lblk, NULL, 0);
-                               if (!IS_ERR_OR_NULL(path)) {
+                               if (!IS_ERR(path)) {
                                        for (j = 0; j < path->p_depth; j++)
                                                ext4_mb_mark_bb(inode->i_sb,
                                                        path[j].p_block, 1, 1);
index 3ed8c048fb12c547775850ba62d364bc08362c20..349b27f0dda0cba64cc10575bb233b9b52de2bd4 100644 (file)
@@ -809,9 +809,12 @@ static int ext4_sample_last_mounted(struct super_block *sb,
        err = ext4_journal_get_write_access(handle, sbi->s_sbh);
        if (err)
                goto out_journal;
-       strlcpy(sbi->s_es->s_last_mounted, cp,
+       lock_buffer(sbi->s_sbh);
+       strncpy(sbi->s_es->s_last_mounted, cp,
                sizeof(sbi->s_es->s_last_mounted));
-       ext4_handle_dirty_super(handle, sb);
+       ext4_superblock_csum_set(sb);
+       unlock_buffer(sbi->s_sbh);
+       ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
 out_journal:
        ext4_journal_stop(handle);
 out:
index 27946882d4ce45b7b544bce1b28a26eef006cd64..c173c840585618b0be404937154dd8516eccf60a 100644 (file)
@@ -5150,9 +5150,13 @@ static int ext4_do_update_inode(handle_t *handle,
                err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
                if (err)
                        goto out_brelse;
+               lock_buffer(EXT4_SB(sb)->s_sbh);
                ext4_set_feature_large_file(sb);
+               ext4_superblock_csum_set(sb);
+               unlock_buffer(EXT4_SB(sb)->s_sbh);
                ext4_handle_sync(handle);
-               err = ext4_handle_dirty_super(handle, sb);
+               err = ext4_handle_dirty_metadata(handle, NULL,
+                                                EXT4_SB(sb)->s_sbh);
        }
        ext4_update_inode_fsync_trans(handle, inode, need_datasync);
 out_brelse:
index 524e134324475e4fffd769b30e5b13bc5cb258f9..d9665d2f82db845175e290b70d1ea7cb26f9b938 100644 (file)
@@ -1157,7 +1157,10 @@ resizefs_out:
                        err = ext4_journal_get_write_access(handle, sbi->s_sbh);
                        if (err)
                                goto pwsalt_err_journal;
+                       lock_buffer(sbi->s_sbh);
                        generate_random_uuid(sbi->s_es->s_encrypt_pw_salt);
+                       ext4_superblock_csum_set(sb);
+                       unlock_buffer(sbi->s_sbh);
                        err = ext4_handle_dirty_metadata(handle, NULL,
                                                         sbi->s_sbh);
                pwsalt_err_journal:
index b17a082b7db15298e99813cb22d07fd4d0c2e458..cf652ba3e74d29f122b960bab6dc2aa93bb4945c 100644 (file)
@@ -2976,14 +2976,17 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
            (le32_to_cpu(sbi->s_es->s_inodes_count))) {
                /* Insert this inode at the head of the on-disk orphan list */
                NEXT_ORPHAN(inode) = le32_to_cpu(sbi->s_es->s_last_orphan);
+               lock_buffer(sbi->s_sbh);
                sbi->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
+               ext4_superblock_csum_set(sb);
+               unlock_buffer(sbi->s_sbh);
                dirty = true;
        }
        list_add(&EXT4_I(inode)->i_orphan, &sbi->s_orphan);
        mutex_unlock(&sbi->s_orphan_lock);
 
        if (dirty) {
-               err = ext4_handle_dirty_super(handle, sb);
+               err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
                rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
                if (!err)
                        err = rc;
@@ -3059,9 +3062,12 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode)
                        mutex_unlock(&sbi->s_orphan_lock);
                        goto out_brelse;
                }
+               lock_buffer(sbi->s_sbh);
                sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
+               ext4_superblock_csum_set(inode->i_sb);
+               unlock_buffer(sbi->s_sbh);
                mutex_unlock(&sbi->s_orphan_lock);
-               err = ext4_handle_dirty_super(handle, inode->i_sb);
+               err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
        } else {
                struct ext4_iloc iloc2;
                struct inode *i_prev =
@@ -3593,9 +3599,6 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
                        return retval2;
                }
        }
-       brelse(ent->bh);
-       ent->bh = NULL;
-
        return retval;
 }
 
@@ -3794,6 +3797,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
                }
        }
 
+       old_file_type = old.de->file_type;
        if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir))
                ext4_handle_sync(handle);
 
@@ -3821,7 +3825,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
        force_reread = (new.dir->i_ino == old.dir->i_ino &&
                        ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA));
 
-       old_file_type = old.de->file_type;
        if (whiteout) {
                /*
                 * Do this before adding a new entry, so the old entry is sure
@@ -3919,15 +3922,19 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
        retval = 0;
 
 end_rename:
-       brelse(old.dir_bh);
-       brelse(old.bh);
-       brelse(new.bh);
        if (whiteout) {
-               if (retval)
+               if (retval) {
+                       ext4_setent(handle, &old,
+                               old.inode->i_ino, old_file_type);
                        drop_nlink(whiteout);
+               }
                unlock_new_inode(whiteout);
                iput(whiteout);
+
        }
+       brelse(old.dir_bh);
+       brelse(old.bh);
+       brelse(new.bh);
        if (handle)
                ext4_journal_stop(handle);
        return retval;
index 928700d57eb67e5bc01340af2dd8826a6e9c6718..bd0d185654f3357cdc7a5826a6d3afa87c052dff 100644 (file)
@@ -899,8 +899,11 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        EXT4_SB(sb)->s_gdb_count++;
        ext4_kvfree_array_rcu(o_group_desc);
 
+       lock_buffer(EXT4_SB(sb)->s_sbh);
        le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
-       err = ext4_handle_dirty_super(handle, sb);
+       ext4_superblock_csum_set(sb);
+       unlock_buffer(EXT4_SB(sb)->s_sbh);
+       err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
        if (err)
                ext4_std_error(sb, err);
        return err;
@@ -1384,6 +1387,7 @@ static void ext4_update_super(struct super_block *sb,
        reserved_blocks *= blocks_count;
        do_div(reserved_blocks, 100);
 
+       lock_buffer(sbi->s_sbh);
        ext4_blocks_count_set(es, ext4_blocks_count(es) + blocks_count);
        ext4_free_blocks_count_set(es, ext4_free_blocks_count(es) + free_blocks);
        le32_add_cpu(&es->s_inodes_count, EXT4_INODES_PER_GROUP(sb) *
@@ -1421,6 +1425,8 @@ static void ext4_update_super(struct super_block *sb,
         * active. */
        ext4_r_blocks_count_set(es, ext4_r_blocks_count(es) +
                                reserved_blocks);
+       ext4_superblock_csum_set(sb);
+       unlock_buffer(sbi->s_sbh);
 
        /* Update the free space counts */
        percpu_counter_add(&sbi->s_freeclusters_counter,
@@ -1515,7 +1521,7 @@ static int ext4_flex_group_add(struct super_block *sb,
 
        ext4_update_super(sb, flex_gd);
 
-       err = ext4_handle_dirty_super(handle, sb);
+       err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
 
 exit_journal:
        err2 = ext4_journal_stop(handle);
@@ -1717,15 +1723,18 @@ static int ext4_group_extend_no_check(struct super_block *sb,
                goto errout;
        }
 
+       lock_buffer(EXT4_SB(sb)->s_sbh);
        ext4_blocks_count_set(es, o_blocks_count + add);
        ext4_free_blocks_count_set(es, ext4_free_blocks_count(es) + add);
+       ext4_superblock_csum_set(sb);
+       unlock_buffer(EXT4_SB(sb)->s_sbh);
        ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,
                   o_blocks_count + add);
        /* We add the blocks to the bitmap and set the group need init bit */
        err = ext4_group_add_blocks(handle, sb, o_blocks_count, add);
        if (err)
                goto errout;
-       ext4_handle_dirty_super(handle, sb);
+       ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
        ext4_debug("freed blocks %llu through %llu\n", o_blocks_count,
                   o_blocks_count + add);
 errout:
@@ -1874,12 +1883,15 @@ static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode)
        if (err)
                goto errout;
 
+       lock_buffer(sbi->s_sbh);
        ext4_clear_feature_resize_inode(sb);
        ext4_set_feature_meta_bg(sb);
        sbi->s_es->s_first_meta_bg =
                cpu_to_le32(num_desc_blocks(sb, sbi->s_groups_count));
+       ext4_superblock_csum_set(sb);
+       unlock_buffer(sbi->s_sbh);
 
-       err = ext4_handle_dirty_super(handle, sb);
+       err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
        if (err) {
                ext4_std_error(sb, err);
                goto errout;
index 21121787c874e186ed547177adcffdebbd3891a6..9a6f9875aa3499fb7ac3a48a062f933b162aa2b9 100644 (file)
@@ -65,7 +65,8 @@ static struct ratelimit_state ext4_mount_msg_ratelimit;
 static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
                             unsigned long journal_devnum);
 static int ext4_show_options(struct seq_file *seq, struct dentry *root);
-static int ext4_commit_super(struct super_block *sb, int sync);
+static void ext4_update_super(struct super_block *sb);
+static int ext4_commit_super(struct super_block *sb);
 static int ext4_mark_recovery_complete(struct super_block *sb,
                                        struct ext4_super_block *es);
 static int ext4_clear_journal_err(struct super_block *sb,
@@ -586,15 +587,12 @@ static int ext4_errno_to_code(int errno)
        return EXT4_ERR_UNKNOWN;
 }
 
-static void __save_error_info(struct super_block *sb, int error,
-                             __u32 ino, __u64 block,
-                             const char *func, unsigned int line)
+static void save_error_info(struct super_block *sb, int error,
+                           __u32 ino, __u64 block,
+                           const char *func, unsigned int line)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
-       EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
-       if (bdev_read_only(sb->s_bdev))
-               return;
        /* We default to EFSCORRUPTED error... */
        if (error == 0)
                error = EFSCORRUPTED;
@@ -618,15 +616,6 @@ static void __save_error_info(struct super_block *sb, int error,
        spin_unlock(&sbi->s_error_lock);
 }
 
-static void save_error_info(struct super_block *sb, int error,
-                           __u32 ino, __u64 block,
-                           const char *func, unsigned int line)
-{
-       __save_error_info(sb, error, ino, block, func, line);
-       if (!bdev_read_only(sb->s_bdev))
-               ext4_commit_super(sb, 1);
-}
-
 /* Deal with the reporting of failure conditions on a filesystem such as
  * inconsistencies detected or read IO failures.
  *
@@ -647,19 +636,40 @@ static void save_error_info(struct super_block *sb, int error,
  * used to deal with unrecoverable failures such as journal IO errors or ENOMEM
  * at a critical moment in log management.
  */
-static void ext4_handle_error(struct super_block *sb, bool force_ro)
+static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,
+                             __u32 ino, __u64 block,
+                             const char *func, unsigned int line)
 {
        journal_t *journal = EXT4_SB(sb)->s_journal;
+       bool continue_fs = !force_ro && test_opt(sb, ERRORS_CONT);
 
+       EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
        if (test_opt(sb, WARN_ON_ERROR))
                WARN_ON_ONCE(1);
 
-       if (sb_rdonly(sb) || (!force_ro && test_opt(sb, ERRORS_CONT)))
+       if (!continue_fs && !sb_rdonly(sb)) {
+               ext4_set_mount_flag(sb, EXT4_MF_FS_ABORTED);
+               if (journal)
+                       jbd2_journal_abort(journal, -EIO);
+       }
+
+       if (!bdev_read_only(sb->s_bdev)) {
+               save_error_info(sb, error, ino, block, func, line);
+               /*
+                * In case the fs should keep running, we need to writeout
+                * superblock through the journal. Due to lock ordering
+                * constraints, it may not be safe to do it right here so we
+                * defer superblock flushing to a workqueue.
+                */
+               if (continue_fs)
+                       schedule_work(&EXT4_SB(sb)->s_error_work);
+               else
+                       ext4_commit_super(sb);
+       }
+
+       if (sb_rdonly(sb) || continue_fs)
                return;
 
-       ext4_set_mount_flag(sb, EXT4_MF_FS_ABORTED);
-       if (journal)
-               jbd2_journal_abort(journal, -EIO);
        /*
         * We force ERRORS_RO behavior when system is rebooting. Otherwise we
         * could panic during 'reboot -f' as the underlying device got already
@@ -682,8 +692,39 @@ static void flush_stashed_error_work(struct work_struct *work)
 {
        struct ext4_sb_info *sbi = container_of(work, struct ext4_sb_info,
                                                s_error_work);
+       journal_t *journal = sbi->s_journal;
+       handle_t *handle;
 
-       ext4_commit_super(sbi->s_sb, 1);
+       /*
+        * If the journal is still running, we have to write out superblock
+        * through the journal to avoid collisions of other journalled sb
+        * updates.
+        *
+        * We use directly jbd2 functions here to avoid recursing back into
+        * ext4 error handling code during handling of previous errors.
+        */
+       if (!sb_rdonly(sbi->s_sb) && journal) {
+               handle = jbd2_journal_start(journal, 1);
+               if (IS_ERR(handle))
+                       goto write_directly;
+               if (jbd2_journal_get_write_access(handle, sbi->s_sbh)) {
+                       jbd2_journal_stop(handle);
+                       goto write_directly;
+               }
+               ext4_update_super(sbi->s_sb);
+               if (jbd2_journal_dirty_metadata(handle, sbi->s_sbh)) {
+                       jbd2_journal_stop(handle);
+                       goto write_directly;
+               }
+               jbd2_journal_stop(handle);
+               return;
+       }
+write_directly:
+       /*
+        * Write through journal failed. Write sb directly to get error info
+        * out and hope for the best.
+        */
+       ext4_commit_super(sbi->s_sb);
 }
 
 #define ext4_error_ratelimit(sb)                                       \
@@ -710,8 +751,7 @@ void __ext4_error(struct super_block *sb, const char *function,
                       sb->s_id, function, line, current->comm, &vaf);
                va_end(args);
        }
-       save_error_info(sb, error, 0, block, function, line);
-       ext4_handle_error(sb, force_ro);
+       ext4_handle_error(sb, force_ro, error, 0, block, function, line);
 }
 
 void __ext4_error_inode(struct inode *inode, const char *function,
@@ -741,9 +781,8 @@ void __ext4_error_inode(struct inode *inode, const char *function,
                               current->comm, &vaf);
                va_end(args);
        }
-       save_error_info(inode->i_sb, error, inode->i_ino, block,
-                       function, line);
-       ext4_handle_error(inode->i_sb, false);
+       ext4_handle_error(inode->i_sb, false, error, inode->i_ino, block,
+                         function, line);
 }
 
 void __ext4_error_file(struct file *file, const char *function,
@@ -780,9 +819,8 @@ void __ext4_error_file(struct file *file, const char *function,
                               current->comm, path, &vaf);
                va_end(args);
        }
-       save_error_info(inode->i_sb, EFSCORRUPTED, inode->i_ino, block,
-                       function, line);
-       ext4_handle_error(inode->i_sb, false);
+       ext4_handle_error(inode->i_sb, false, EFSCORRUPTED, inode->i_ino, block,
+                         function, line);
 }
 
 const char *ext4_decode_error(struct super_block *sb, int errno,
@@ -849,8 +887,7 @@ void __ext4_std_error(struct super_block *sb, const char *function,
                       sb->s_id, function, line, errstr);
        }
 
-       save_error_info(sb, -errno, 0, 0, function, line);
-       ext4_handle_error(sb, false);
+       ext4_handle_error(sb, false, -errno, 0, 0, function, line);
 }
 
 void __ext4_msg(struct super_block *sb,
@@ -944,13 +981,16 @@ __acquires(bitlock)
        if (test_opt(sb, ERRORS_CONT)) {
                if (test_opt(sb, WARN_ON_ERROR))
                        WARN_ON_ONCE(1);
-               __save_error_info(sb, EFSCORRUPTED, ino, block, function, line);
-               schedule_work(&EXT4_SB(sb)->s_error_work);
+               EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+               if (!bdev_read_only(sb->s_bdev)) {
+                       save_error_info(sb, EFSCORRUPTED, ino, block, function,
+                                       line);
+                       schedule_work(&EXT4_SB(sb)->s_error_work);
+               }
                return;
        }
        ext4_unlock_group(sb, grp);
-       save_error_info(sb, EFSCORRUPTED, ino, block, function, line);
-       ext4_handle_error(sb, false);
+       ext4_handle_error(sb, false, EFSCORRUPTED, ino, block, function, line);
        /*
         * We only get here in the ERRORS_RO case; relocking the group
         * may be dangerous, but nothing bad will happen since the
@@ -1152,7 +1192,7 @@ static void ext4_put_super(struct super_block *sb)
                es->s_state = cpu_to_le16(sbi->s_mount_state);
        }
        if (!sb_rdonly(sb))
-               ext4_commit_super(sb, 1);
+               ext4_commit_super(sb);
 
        rcu_read_lock();
        group_desc = rcu_dereference(sbi->s_group_desc);
@@ -2642,7 +2682,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
        if (sbi->s_journal)
                ext4_set_feature_journal_needs_recovery(sb);
 
-       err = ext4_commit_super(sb, 1);
+       err = ext4_commit_super(sb);
 done:
        if (test_opt(sb, DEBUG))
                printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
@@ -4868,7 +4908,7 @@ no_journal:
        if (DUMMY_ENCRYPTION_ENABLED(sbi) && !sb_rdonly(sb) &&
            !ext4_has_feature_encrypt(sb)) {
                ext4_set_feature_encrypt(sb);
-               ext4_commit_super(sb, 1);
+               ext4_commit_super(sb);
        }
 
        /*
@@ -5418,7 +5458,7 @@ static int ext4_load_journal(struct super_block *sb,
                es->s_journal_dev = cpu_to_le32(journal_devnum);
 
                /* Make sure we flush the recovery flag to disk. */
-               ext4_commit_super(sb, 1);
+               ext4_commit_super(sb);
        }
 
        return 0;
@@ -5428,16 +5468,14 @@ err_out:
        return err;
 }
 
-static int ext4_commit_super(struct super_block *sb, int sync)
+/* Copy state of EXT4_SB(sb) into buffer for on-disk superblock */
+static void ext4_update_super(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       struct ext4_super_block *es = EXT4_SB(sb)->s_es;
-       struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
-       int error = 0;
-
-       if (!sbh || block_device_ejected(sb))
-               return error;
+       struct ext4_super_block *es = sbi->s_es;
+       struct buffer_head *sbh = sbi->s_sbh;
 
+       lock_buffer(sbh);
        /*
         * If the file system is mounted read-only, don't update the
         * superblock write time.  This avoids updating the superblock
@@ -5451,17 +5489,17 @@ static int ext4_commit_super(struct super_block *sb, int sync)
        if (!(sb->s_flags & SB_RDONLY))
                ext4_update_tstamp(es, s_wtime);
        es->s_kbytes_written =
-               cpu_to_le64(EXT4_SB(sb)->s_kbytes_written +
+               cpu_to_le64(sbi->s_kbytes_written +
                    ((part_stat_read(sb->s_bdev, sectors[STAT_WRITE]) -
-                     EXT4_SB(sb)->s_sectors_written_start) >> 1));
-       if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeclusters_counter))
+                     sbi->s_sectors_written_start) >> 1));
+       if (percpu_counter_initialized(&sbi->s_freeclusters_counter))
                ext4_free_blocks_count_set(es,
-                       EXT4_C2B(EXT4_SB(sb), percpu_counter_sum_positive(
-                               &EXT4_SB(sb)->s_freeclusters_counter)));
-       if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeinodes_counter))
+                       EXT4_C2B(sbi, percpu_counter_sum_positive(
+                               &sbi->s_freeclusters_counter)));
+       if (percpu_counter_initialized(&sbi->s_freeinodes_counter))
                es->s_free_inodes_count =
                        cpu_to_le32(percpu_counter_sum_positive(
-                               &EXT4_SB(sb)->s_freeinodes_counter));
+                               &sbi->s_freeinodes_counter));
        /* Copy error information to the on-disk superblock */
        spin_lock(&sbi->s_error_lock);
        if (sbi->s_add_error_count > 0) {
@@ -5502,10 +5540,20 @@ static int ext4_commit_super(struct super_block *sb, int sync)
        }
        spin_unlock(&sbi->s_error_lock);
 
-       BUFFER_TRACE(sbh, "marking dirty");
        ext4_superblock_csum_set(sb);
-       if (sync)
-               lock_buffer(sbh);
+       unlock_buffer(sbh);
+}
+
+static int ext4_commit_super(struct super_block *sb)
+{
+       struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
+       int error = 0;
+
+       if (!sbh || block_device_ejected(sb))
+               return error;
+
+       ext4_update_super(sb);
+
        if (buffer_write_io_error(sbh) || !buffer_uptodate(sbh)) {
                /*
                 * Oh, dear.  A previous attempt to write the
@@ -5520,17 +5568,15 @@ static int ext4_commit_super(struct super_block *sb, int sync)
                clear_buffer_write_io_error(sbh);
                set_buffer_uptodate(sbh);
        }
+       BUFFER_TRACE(sbh, "marking dirty");
        mark_buffer_dirty(sbh);
-       if (sync) {
-               unlock_buffer(sbh);
-               error = __sync_dirty_buffer(sbh,
-                       REQ_SYNC | (test_opt(sb, BARRIER) ? REQ_FUA : 0));
-               if (buffer_write_io_error(sbh)) {
-                       ext4_msg(sb, KERN_ERR, "I/O error while writing "
-                              "superblock");
-                       clear_buffer_write_io_error(sbh);
-                       set_buffer_uptodate(sbh);
-               }
+       error = __sync_dirty_buffer(sbh,
+               REQ_SYNC | (test_opt(sb, BARRIER) ? REQ_FUA : 0));
+       if (buffer_write_io_error(sbh)) {
+               ext4_msg(sb, KERN_ERR, "I/O error while writing "
+                      "superblock");
+               clear_buffer_write_io_error(sbh);
+               set_buffer_uptodate(sbh);
        }
        return error;
 }
@@ -5561,7 +5607,7 @@ static int ext4_mark_recovery_complete(struct super_block *sb,
 
        if (ext4_has_feature_journal_needs_recovery(sb) && sb_rdonly(sb)) {
                ext4_clear_feature_journal_needs_recovery(sb);
-               ext4_commit_super(sb, 1);
+               ext4_commit_super(sb);
        }
 out:
        jbd2_journal_unlock_updates(journal);
@@ -5603,7 +5649,7 @@ static int ext4_clear_journal_err(struct super_block *sb,
 
                EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
                es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
-               ext4_commit_super(sb, 1);
+               ext4_commit_super(sb);
 
                jbd2_journal_clear_err(journal);
                jbd2_journal_update_sb_errno(journal);
@@ -5705,7 +5751,7 @@ static int ext4_freeze(struct super_block *sb)
                ext4_clear_feature_journal_needs_recovery(sb);
        }
 
-       error = ext4_commit_super(sb, 1);
+       error = ext4_commit_super(sb);
 out:
        if (journal)
                /* we rely on upper layer to stop further updates */
@@ -5727,7 +5773,7 @@ static int ext4_unfreeze(struct super_block *sb)
                ext4_set_feature_journal_needs_recovery(sb);
        }
 
-       ext4_commit_super(sb, 1);
+       ext4_commit_super(sb);
        return 0;
 }
 
@@ -5987,7 +6033,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
        }
 
        if (sbi->s_journal == NULL && !(old_sb_flags & SB_RDONLY)) {
-               err = ext4_commit_super(sb, 1);
+               err = ext4_commit_super(sb);
                if (err)
                        goto restore_opts;
        }
index 4e3b1f8c2e81eaaf5489ee96f2c63a5d6e8681da..372208500f4e766f0167ce4597f777dafc6891f2 100644 (file)
@@ -792,8 +792,11 @@ static void ext4_xattr_update_super_block(handle_t *handle,
 
        BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");
        if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) {
+               lock_buffer(EXT4_SB(sb)->s_sbh);
                ext4_set_feature_xattr(sb);
-               ext4_handle_dirty_super(handle, sb);
+               ext4_superblock_csum_set(sb);
+               unlock_buffer(EXT4_SB(sb)->s_sbh);
+               ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
        }
 }
 
index acfb55834af23c437d4e166b50d15486c200a709..c41cb887eb7d3cbe3114147cea8fd0321767b831 100644 (file)
@@ -1474,21 +1474,25 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
        }
 
        /*
-        * Some filesystems may redirty the inode during the writeback
-        * due to delalloc, clear dirty metadata flags right before
-        * write_inode()
+        * If the inode has dirty timestamps and we need to write them, call
+        * mark_inode_dirty_sync() to notify the filesystem about it and to
+        * change I_DIRTY_TIME into I_DIRTY_SYNC.
         */
-       spin_lock(&inode->i_lock);
-
-       dirty = inode->i_state & I_DIRTY;
        if ((inode->i_state & I_DIRTY_TIME) &&
-           ((dirty & I_DIRTY_INODE) ||
-            wbc->sync_mode == WB_SYNC_ALL || wbc->for_sync ||
+           (wbc->sync_mode == WB_SYNC_ALL || wbc->for_sync ||
             time_after(jiffies, inode->dirtied_time_when +
                        dirtytime_expire_interval * HZ))) {
-               dirty |= I_DIRTY_TIME;
                trace_writeback_lazytime(inode);
+               mark_inode_dirty_sync(inode);
        }
+
+       /*
+        * Some filesystems may redirty the inode during the writeback
+        * due to delalloc, clear dirty metadata flags right before
+        * write_inode()
+        */
+       spin_lock(&inode->i_lock);
+       dirty = inode->i_state & I_DIRTY;
        inode->i_state &= ~dirty;
 
        /*
@@ -1509,8 +1513,6 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 
        spin_unlock(&inode->i_lock);
 
-       if (dirty & I_DIRTY_TIME)
-               mark_inode_dirty_sync(inode);
        /* Don't write the inode if only I_DIRTY_PAGES was set */
        if (dirty & ~I_DIRTY_PAGES) {
                int err = write_inode(inode, wbc);
index 2f305c097bd5bb20cec05e633b201e07b99ade29..985a9e3f976d3bf1e8b6da3aebbb6495fe875dc9 100644 (file)
@@ -354,6 +354,7 @@ struct io_ring_ctx {
                unsigned                cq_entries;
                unsigned                cq_mask;
                atomic_t                cq_timeouts;
+               unsigned                cq_last_tm_flush;
                unsigned long           cq_check_overflow;
                struct wait_queue_head  cq_wait;
                struct fasync_struct    *cq_fasync;
@@ -1106,6 +1107,9 @@ static void io_sq_thread_drop_mm_files(void)
 
 static int __io_sq_thread_acquire_files(struct io_ring_ctx *ctx)
 {
+       if (current->flags & PF_EXITING)
+               return -EFAULT;
+
        if (!current->files) {
                struct files_struct *files;
                struct nsproxy *nsproxy;
@@ -1133,6 +1137,8 @@ static int __io_sq_thread_acquire_mm(struct io_ring_ctx *ctx)
 {
        struct mm_struct *mm;
 
+       if (current->flags & PF_EXITING)
+               return -EFAULT;
        if (current->mm)
                return 0;
 
@@ -1634,19 +1640,38 @@ static void __io_queue_deferred(struct io_ring_ctx *ctx)
 
 static void io_flush_timeouts(struct io_ring_ctx *ctx)
 {
-       while (!list_empty(&ctx->timeout_list)) {
+       u32 seq;
+
+       if (list_empty(&ctx->timeout_list))
+               return;
+
+       seq = ctx->cached_cq_tail - atomic_read(&ctx->cq_timeouts);
+
+       do {
+               u32 events_needed, events_got;
                struct io_kiocb *req = list_first_entry(&ctx->timeout_list,
                                                struct io_kiocb, timeout.list);
 
                if (io_is_timeout_noseq(req))
                        break;
-               if (req->timeout.target_seq != ctx->cached_cq_tail
-                                       - atomic_read(&ctx->cq_timeouts))
+
+               /*
+                * Since seq can easily wrap around over time, subtract
+                * the last seq at which timeouts were flushed before comparing.
+                * Assuming not more than 2^31-1 events have happened since,
+                * these subtractions won't have wrapped, so we can check if
+                * target is in [last_seq, current_seq] by comparing the two.
+                */
+               events_needed = req->timeout.target_seq - ctx->cq_last_tm_flush;
+               events_got = seq - ctx->cq_last_tm_flush;
+               if (events_got < events_needed)
                        break;
 
                list_del_init(&req->timeout.list);
                io_kill_timeout(req);
-       }
+       } while (!list_empty(&ctx->timeout_list));
+
+       ctx->cq_last_tm_flush = seq;
 }
 
 static void io_commit_cqring(struct io_ring_ctx *ctx)
@@ -5832,6 +5857,12 @@ static int io_timeout(struct io_kiocb *req)
        tail = ctx->cached_cq_tail - atomic_read(&ctx->cq_timeouts);
        req->timeout.target_seq = tail + off;
 
+       /* Update the last seq here in case io_flush_timeouts() hasn't.
+        * This is safe because ->completion_lock is held, and submissions
+        * and completions are never mixed in the same ->completion_lock section.
+        */
+       ctx->cq_last_tm_flush = tail;
+
        /*
         * Insertion sort, ensuring the first entry in the list is always
         * the one we need first.
@@ -7056,6 +7087,7 @@ static int io_sq_thread(void *data)
 
                if (sqt_spin || !time_after(jiffies, timeout)) {
                        io_run_task_work();
+                       io_sq_thread_drop_mm_files();
                        cond_resched();
                        if (sqt_spin)
                                timeout = jiffies + sqd->sq_thread_idle;
@@ -7093,6 +7125,7 @@ static int io_sq_thread(void *data)
        }
 
        io_run_task_work();
+       io_sq_thread_drop_mm_files();
 
        if (cur_css)
                io_sq_thread_unassociate_blkcg();
@@ -8888,7 +8921,8 @@ static void io_disable_sqo_submit(struct io_ring_ctx *ctx)
        mutex_unlock(&ctx->uring_lock);
 
        /* make sure callers enter the ring to get error */
-       io_ring_set_wakeup_flag(ctx);
+       if (ctx->rings)
+               io_ring_set_wakeup_flag(ctx);
 }
 
 /*
@@ -9067,6 +9101,7 @@ void __io_uring_task_cancel(void)
                finish_wait(&tctx->wait, &wait);
        } while (1);
 
+       finish_wait(&tctx->wait, &wait);
        atomic_dec(&tctx->in_idle);
 
        io_uring_remove_task_files(tctx);
@@ -9700,6 +9735,7 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p,
         */
        ret = io_uring_install_fd(ctx, file);
        if (ret < 0) {
+               io_disable_sqo_submit(ctx);
                /* fput will clean it up */
                fput(file);
                return ret;
index d2db7dfe232b3ecd299187ed477ad2fd7a0fd1a5..9d33909d0f9e34d8a54c7d0d1d7b44652cc8b69e 100644 (file)
@@ -1713,8 +1713,6 @@ static int can_umount(const struct path *path, int flags)
 {
        struct mount *mnt = real_mount(path->mnt);
 
-       if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
-               return -EINVAL;
        if (!may_mount())
                return -EPERM;
        if (path->dentry != path->mnt->mnt_root)
@@ -1728,6 +1726,7 @@ static int can_umount(const struct path *path, int flags)
        return 0;
 }
 
+// caller is responsible for flags being sane
 int path_umount(struct path *path, int flags)
 {
        struct mount *mnt = real_mount(path->mnt);
@@ -1749,6 +1748,10 @@ static int ksys_umount(char __user *name, int flags)
        struct path path;
        int ret;
 
+       // basic validity checks done first
+       if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
+               return -EINVAL;
+
        if (!(flags & UMOUNT_NOFOLLOW))
                lookup_flags |= LOOKUP_FOLLOW;
        ret = user_path_at(AT_FDCWD, name, lookup_flags, &path);
index 816e1427f17eb15f8a7b5abda8c554ce56ac9a5a..04bf8066980c1d9fd32b85927dbe51ac025b3512 100644 (file)
@@ -1011,22 +1011,24 @@ nfs_delegation_find_inode_server(struct nfs_server *server,
                                 const struct nfs_fh *fhandle)
 {
        struct nfs_delegation *delegation;
-       struct inode *freeme, *res = NULL;
+       struct super_block *freeme = NULL;
+       struct inode *res = NULL;
 
        list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
                spin_lock(&delegation->lock);
                if (delegation->inode != NULL &&
                    !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) &&
                    nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
-                       freeme = igrab(delegation->inode);
-                       if (freeme && nfs_sb_active(freeme->i_sb))
-                               res = freeme;
+                       if (nfs_sb_active(server->super)) {
+                               freeme = server->super;
+                               res = igrab(delegation->inode);
+                       }
                        spin_unlock(&delegation->lock);
                        if (res != NULL)
                                return res;
                        if (freeme) {
                                rcu_read_unlock();
-                               iput(freeme);
+                               nfs_sb_deactive(freeme);
                                rcu_read_lock();
                        }
                        return ERR_PTR(-EAGAIN);
index b840d0a91c9d8f2d7f704eb2ab1b1eb311dc1539..62d3189745cdc7461e49109156c170ca0f2c988b 100644 (file)
@@ -136,9 +136,29 @@ struct nfs_fs_context {
        } clone_data;
 };
 
-#define nfs_errorf(fc, fmt, ...) errorf(fc, fmt, ## __VA_ARGS__)
-#define nfs_invalf(fc, fmt, ...) invalf(fc, fmt, ## __VA_ARGS__)
-#define nfs_warnf(fc, fmt, ...) warnf(fc, fmt, ## __VA_ARGS__)
+#define nfs_errorf(fc, fmt, ...) ((fc)->log.log ?              \
+       errorf(fc, fmt, ## __VA_ARGS__) :                       \
+       ({ dprintk(fmt "\n", ## __VA_ARGS__); }))
+
+#define nfs_ferrorf(fc, fac, fmt, ...) ((fc)->log.log ?                \
+       errorf(fc, fmt, ## __VA_ARGS__) :                       \
+       ({ dfprintk(fac, fmt "\n", ## __VA_ARGS__); }))
+
+#define nfs_invalf(fc, fmt, ...) ((fc)->log.log ?              \
+       invalf(fc, fmt, ## __VA_ARGS__) :                       \
+       ({ dprintk(fmt "\n", ## __VA_ARGS__);  -EINVAL; }))
+
+#define nfs_finvalf(fc, fac, fmt, ...) ((fc)->log.log ?                \
+       invalf(fc, fmt, ## __VA_ARGS__) :                       \
+       ({ dfprintk(fac, fmt "\n", ## __VA_ARGS__);  -EINVAL; }))
+
+#define nfs_warnf(fc, fmt, ...) ((fc)->log.log ?               \
+       warnf(fc, fmt, ## __VA_ARGS__) :                        \
+       ({ dprintk(fmt "\n", ## __VA_ARGS__); }))
+
+#define nfs_fwarnf(fc, fac, fmt, ...) ((fc)->log.log ?         \
+       warnf(fc, fmt, ## __VA_ARGS__) :                        \
+       ({ dfprintk(fac, fmt "\n", ## __VA_ARGS__); }))
 
 static inline struct nfs_fs_context *nfs_fc2context(const struct fs_context *fc)
 {
@@ -579,12 +599,14 @@ extern void nfs4_test_session_trunk(struct rpc_clnt *clnt,
 
 static inline struct inode *nfs_igrab_and_active(struct inode *inode)
 {
-       inode = igrab(inode);
-       if (inode != NULL && !nfs_sb_active(inode->i_sb)) {
-               iput(inode);
-               inode = NULL;
+       struct super_block *sb = inode->i_sb;
+
+       if (sb && nfs_sb_active(sb)) {
+               if (igrab(inode))
+                       return inode;
+               nfs_sb_deactive(sb);
        }
-       return inode;
+       return NULL;
 }
 
 static inline void nfs_iput_and_deactive(struct inode *inode)
index 0ce04e0e5d829003f72670500632352b7694577b..2f4679a62712a9dd8406ac73f2961ea5d69c3480 100644 (file)
@@ -3536,10 +3536,8 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
        trace_nfs4_close(state, &calldata->arg, &calldata->res, task->tk_status);
 
        /* Handle Layoutreturn errors */
-       if (pnfs_roc_done(task, calldata->inode,
-                               &calldata->arg.lr_args,
-                               &calldata->res.lr_res,
-                               &calldata->res.lr_ret) == -EAGAIN)
+       if (pnfs_roc_done(task, &calldata->arg.lr_args, &calldata->res.lr_res,
+                         &calldata->res.lr_ret) == -EAGAIN)
                goto out_restart;
 
        /* hmm. we are done with the inode, and in the process of freeing
@@ -6384,10 +6382,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
        trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status);
 
        /* Handle Layoutreturn errors */
-       if (pnfs_roc_done(task, data->inode,
-                               &data->args.lr_args,
-                               &data->res.lr_res,
-                               &data->res.lr_ret) == -EAGAIN)
+       if (pnfs_roc_done(task, &data->args.lr_args, &data->res.lr_res,
+                         &data->res.lr_ret) == -EAGAIN)
                goto out_restart;
 
        switch (task->tk_status) {
@@ -6441,10 +6437,10 @@ static void nfs4_delegreturn_release(void *calldata)
        struct nfs4_delegreturndata *data = calldata;
        struct inode *inode = data->inode;
 
+       if (data->lr.roc)
+               pnfs_roc_release(&data->lr.arg, &data->lr.res,
+                                data->res.lr_ret);
        if (inode) {
-               if (data->lr.roc)
-                       pnfs_roc_release(&data->lr.arg, &data->lr.res,
-                                       data->res.lr_ret);
                nfs_post_op_update_inode_force_wcc(inode, &data->fattr);
                nfs_iput_and_deactive(inode);
        }
@@ -6520,16 +6516,14 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
        nfs_fattr_init(data->res.fattr);
        data->timestamp = jiffies;
        data->rpc_status = 0;
-       data->lr.roc = pnfs_roc(inode, &data->lr.arg, &data->lr.res, cred);
        data->inode = nfs_igrab_and_active(inode);
-       if (data->inode) {
+       if (data->inode || issync) {
+               data->lr.roc = pnfs_roc(inode, &data->lr.arg, &data->lr.res,
+                                       cred);
                if (data->lr.roc) {
                        data->args.lr_args = &data->lr.arg;
                        data->res.lr_res = &data->lr.res;
                }
-       } else if (data->lr.roc) {
-               pnfs_roc_release(&data->lr.arg, &data->lr.res, 0);
-               data->lr.roc = false;
        }
 
        task_setup_data.callback_data = data;
@@ -7111,9 +7105,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
                                        data->arg.new_lock_owner, ret);
        } else
                data->cancelled = true;
+       trace_nfs4_set_lock(fl, state, &data->res.stateid, cmd, ret);
        rpc_put_task(task);
        dprintk("%s: done, ret = %d!\n", __func__, ret);
-       trace_nfs4_set_lock(fl, state, &data->res.stateid, cmd, ret);
        return ret;
 }
 
index 984cc42ee54d8ccd93e3ba8a0afa9eb85e0c2042..d09bcfd7db89488eec9291c4e985e13953f079d3 100644 (file)
@@ -227,7 +227,7 @@ int nfs4_try_get_tree(struct fs_context *fc)
                           fc, ctx->nfs_server.hostname,
                           ctx->nfs_server.export_path);
        if (err) {
-               nfs_errorf(fc, "NFS4: Couldn't follow remote path");
+               nfs_ferrorf(fc, MOUNT, "NFS4: Couldn't follow remote path");
                dfprintk(MOUNT, "<-- nfs4_try_get_tree() = %d [error]\n", err);
        } else {
                dfprintk(MOUNT, "<-- nfs4_try_get_tree() = 0\n");
@@ -250,7 +250,7 @@ int nfs4_get_referral_tree(struct fs_context *fc)
                            fc, ctx->nfs_server.hostname,
                            ctx->nfs_server.export_path);
        if (err) {
-               nfs_errorf(fc, "NFS4: Couldn't follow remote path");
+               nfs_ferrorf(fc, MOUNT, "NFS4: Couldn't follow remote path");
                dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = %d [error]\n", err);
        } else {
                dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = 0\n");
index 07f59dc8cb2e77e17c8d7cbcbbac94a58c9b9256..4f274f21c4abcb9c2d96bc4088c3f1f4003258f0 100644 (file)
@@ -1152,7 +1152,7 @@ void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo,
        LIST_HEAD(freeme);
 
        spin_lock(&inode->i_lock);
-       if (!pnfs_layout_is_valid(lo) || !arg_stateid ||
+       if (!pnfs_layout_is_valid(lo) ||
            !nfs4_stateid_match_other(&lo->plh_stateid, arg_stateid))
                goto out_unlock;
        if (stateid) {
@@ -1509,10 +1509,8 @@ out_noroc:
        return false;
 }
 
-int pnfs_roc_done(struct rpc_task *task, struct inode *inode,
-               struct nfs4_layoutreturn_args **argpp,
-               struct nfs4_layoutreturn_res **respp,
-               int *ret)
+int pnfs_roc_done(struct rpc_task *task, struct nfs4_layoutreturn_args **argpp,
+                 struct nfs4_layoutreturn_res **respp, int *ret)
 {
        struct nfs4_layoutreturn_args *arg = *argpp;
        int retval = -EAGAIN;
@@ -1545,7 +1543,7 @@ int pnfs_roc_done(struct rpc_task *task, struct inode *inode,
                return 0;
        case -NFS4ERR_OLD_STATEID:
                if (!nfs4_layout_refresh_old_stateid(&arg->stateid,
-                                       &arg->range, inode))
+                                                    &arg->range, arg->inode))
                        break;
                *ret = -NFS4ERR_NOMATCHING_LAYOUT;
                return -EAGAIN;
@@ -1560,23 +1558,28 @@ void pnfs_roc_release(struct nfs4_layoutreturn_args *args,
                int ret)
 {
        struct pnfs_layout_hdr *lo = args->layout;
-       const nfs4_stateid *arg_stateid = NULL;
+       struct inode *inode = args->inode;
        const nfs4_stateid *res_stateid = NULL;
        struct nfs4_xdr_opaque_data *ld_private = args->ld_private;
 
        switch (ret) {
        case -NFS4ERR_NOMATCHING_LAYOUT:
+               spin_lock(&inode->i_lock);
+               if (pnfs_layout_is_valid(lo) &&
+                   nfs4_stateid_match_other(&args->stateid, &lo->plh_stateid))
+                       pnfs_set_plh_return_info(lo, args->range.iomode, 0);
+               pnfs_clear_layoutreturn_waitbit(lo);
+               spin_unlock(&inode->i_lock);
                break;
        case 0:
                if (res->lrs_present)
                        res_stateid = &res->stateid;
                fallthrough;
        default:
-               arg_stateid = &args->stateid;
+               pnfs_layoutreturn_free_lsegs(lo, &args->stateid, &args->range,
+                                            res_stateid);
        }
        trace_nfs4_layoutreturn_on_close(args->inode, &args->stateid, ret);
-       pnfs_layoutreturn_free_lsegs(lo, arg_stateid, &args->range,
-                       res_stateid);
        if (ld_private && ld_private->ops && ld_private->ops->free)
                ld_private->ops->free(ld_private);
        pnfs_put_layout_hdr(lo);
@@ -2015,6 +2018,27 @@ lookup_again:
                goto lookup_again;
        }
 
+       /*
+        * Because we free lsegs when sending LAYOUTRETURN, we need to wait
+        * for LAYOUTRETURN.
+        */
+       if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) {
+               spin_unlock(&ino->i_lock);
+               dprintk("%s wait for layoutreturn\n", __func__);
+               lseg = ERR_PTR(pnfs_prepare_to_retry_layoutget(lo));
+               if (!IS_ERR(lseg)) {
+                       pnfs_put_layout_hdr(lo);
+                       dprintk("%s retrying\n", __func__);
+                       trace_pnfs_update_layout(ino, pos, count, iomode, lo,
+                                                lseg,
+                                                PNFS_UPDATE_LAYOUT_RETRY);
+                       goto lookup_again;
+               }
+               trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
+                                        PNFS_UPDATE_LAYOUT_RETURN);
+               goto out_put_layout_hdr;
+       }
+
        lseg = pnfs_find_lseg(lo, &arg, strict_iomode);
        if (lseg) {
                trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
@@ -2067,28 +2091,6 @@ lookup_again:
                nfs4_stateid_copy(&stateid, &lo->plh_stateid);
        }
 
-       /*
-        * Because we free lsegs before sending LAYOUTRETURN, we need to wait
-        * for LAYOUTRETURN even if first is true.
-        */
-       if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) {
-               spin_unlock(&ino->i_lock);
-               dprintk("%s wait for layoutreturn\n", __func__);
-               lseg = ERR_PTR(pnfs_prepare_to_retry_layoutget(lo));
-               if (!IS_ERR(lseg)) {
-                       if (first)
-                               pnfs_clear_first_layoutget(lo);
-                       pnfs_put_layout_hdr(lo);
-                       dprintk("%s retrying\n", __func__);
-                       trace_pnfs_update_layout(ino, pos, count, iomode, lo,
-                                       lseg, PNFS_UPDATE_LAYOUT_RETRY);
-                       goto lookup_again;
-               }
-               trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
-                               PNFS_UPDATE_LAYOUT_RETURN);
-               goto out_put_layout_hdr;
-       }
-
        if (pnfs_layoutgets_blocked(lo)) {
                trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
                                PNFS_UPDATE_LAYOUT_BLOCKED);
@@ -2242,6 +2244,7 @@ static void _lgopen_prepare_attached(struct nfs4_opendata *data,
                                             &rng, GFP_KERNEL);
        if (!lgp) {
                pnfs_clear_first_layoutget(lo);
+               nfs_layoutget_end(lo);
                pnfs_put_layout_hdr(lo);
                return;
        }
index bbd3de1025f23cb3bc5e78a46abef5e1ae56eba5..d810ae674f4e8aba15c34d2bf730a8c95d0aa5db 100644 (file)
@@ -297,10 +297,8 @@ bool pnfs_roc(struct inode *ino,
                struct nfs4_layoutreturn_args *args,
                struct nfs4_layoutreturn_res *res,
                const struct cred *cred);
-int pnfs_roc_done(struct rpc_task *task, struct inode *inode,
-               struct nfs4_layoutreturn_args **argpp,
-               struct nfs4_layoutreturn_res **respp,
-               int *ret);
+int pnfs_roc_done(struct rpc_task *task, struct nfs4_layoutreturn_args **argpp,
+                 struct nfs4_layoutreturn_res **respp, int *ret);
 void pnfs_roc_release(struct nfs4_layoutreturn_args *args,
                struct nfs4_layoutreturn_res *res,
                int ret);
@@ -772,7 +770,7 @@ pnfs_roc(struct inode *ino,
 }
 
 static inline int
-pnfs_roc_done(struct rpc_task *task, struct inode *inode,
+pnfs_roc_done(struct rpc_task *task,
                struct nfs4_layoutreturn_args **argpp,
                struct nfs4_layoutreturn_res **respp,
                int *ret)
index 2efcfdd348a111a86c9647250a9d51b6d21f2dc0..49d3389bd81300f1a14ca91e2b5e80195e776aaf 100644 (file)
@@ -78,22 +78,18 @@ void
 pnfs_generic_clear_request_commit(struct nfs_page *req,
                                  struct nfs_commit_info *cinfo)
 {
-       struct pnfs_layout_segment *freeme = NULL;
+       struct pnfs_commit_bucket *bucket = NULL;
 
        if (!test_and_clear_bit(PG_COMMIT_TO_DS, &req->wb_flags))
                goto out;
        cinfo->ds->nwritten--;
-       if (list_is_singular(&req->wb_list)) {
-               struct pnfs_commit_bucket *bucket;
-
+       if (list_is_singular(&req->wb_list))
                bucket = list_first_entry(&req->wb_list,
-                                         struct pnfs_commit_bucket,
-                                         written);
-               freeme = pnfs_free_bucket_lseg(bucket);
-       }
+                                         struct pnfs_commit_bucket, written);
 out:
        nfs_request_remove_commit_list(req, cinfo);
-       pnfs_put_lseg(freeme);
+       if (bucket)
+               pnfs_put_lseg(pnfs_free_bucket_lseg(bucket));
 }
 EXPORT_SYMBOL_GPL(pnfs_generic_clear_request_commit);
 
@@ -407,12 +403,16 @@ pnfs_bucket_get_committing(struct list_head *head,
                           struct pnfs_commit_bucket *bucket,
                           struct nfs_commit_info *cinfo)
 {
+       struct pnfs_layout_segment *lseg;
        struct list_head *pos;
 
        list_for_each(pos, &bucket->committing)
                cinfo->ds->ncommitting--;
        list_splice_init(&bucket->committing, head);
-       return pnfs_free_bucket_lseg(bucket);
+       lseg = pnfs_free_bucket_lseg(bucket);
+       if (!lseg)
+               lseg = pnfs_get_lseg(bucket->lseg);
+       return lseg;
 }
 
 static struct nfs_commit_data *
@@ -424,8 +424,6 @@ pnfs_bucket_fetch_commitdata(struct pnfs_commit_bucket *bucket,
        if (!data)
                return NULL;
        data->lseg = pnfs_bucket_get_committing(&data->pages, bucket, cinfo);
-       if (!data->lseg)
-               data->lseg = pnfs_get_lseg(bucket->lseg);
        return data;
 }
 
index 821db21ba072cd7dbf7a70c69bd8f0ee378758f6..34b880211e5eab8e63fd3d034a9a3b6aa8b4fa40 100644 (file)
@@ -865,9 +865,14 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
        if (isdotent(name, namlen)) {
                if (namlen == 2) {
                        dchild = dget_parent(dparent);
-                       /* filesystem root - cannot return filehandle for ".." */
+                       /*
+                        * Don't return filehandle for ".." if we're at
+                        * the filesystem or export root:
+                        */
                        if (dchild == dparent)
                                goto out;
+                       if (dparent == exp->ex_path.dentry)
+                               goto out;
                } else
                        dchild = dget(dparent);
        } else
index 4727b7f03c5bb24a260465b70788db5e2e1baee6..8d6d2678abade46ac06ba69a8a84700335c424de 100644 (file)
 #include "pnfs.h"
 #include "trace.h"
 
+static bool inter_copy_offload_enable;
+module_param(inter_copy_offload_enable, bool, 0644);
+MODULE_PARM_DESC(inter_copy_offload_enable,
+                "Enable inter server to server copy offload. Default: false");
+
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
 #include <linux/security.h>
 
index 45ee6b12ce5b70d327d08bb9a10745d659383a90..eaaa1605b5b5f38a51065a8bcc21ebc76d5a0190 100644 (file)
@@ -147,6 +147,25 @@ svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len)
        return p;
 }
 
+static void *
+svcxdr_savemem(struct nfsd4_compoundargs *argp, __be32 *p, u32 len)
+{
+       __be32 *tmp;
+
+       /*
+        * The location of the decoded data item is stable,
+        * so @p is OK to use. This is the common case.
+        */
+       if (p != argp->xdr->scratch.iov_base)
+               return p;
+
+       tmp = svcxdr_tmpalloc(argp, len);
+       if (!tmp)
+               return NULL;
+       memcpy(tmp, p, len);
+       return tmp;
+}
+
 /*
  * NFSv4 basic data type decoders
  */
@@ -183,11 +202,10 @@ nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o)
        p = xdr_inline_decode(argp->xdr, len);
        if (!p)
                return nfserr_bad_xdr;
-       o->data = svcxdr_tmpalloc(argp, len);
+       o->data = svcxdr_savemem(argp, p, len);
        if (!o->data)
                return nfserr_jukebox;
        o->len = len;
-       memcpy(o->data, p, len);
 
        return nfs_ok;
 }
@@ -205,10 +223,9 @@ nfsd4_decode_component4(struct nfsd4_compoundargs *argp, char **namp, u32 *lenp)
        status = check_filename((char *)p, *lenp);
        if (status)
                return status;
-       *namp = svcxdr_tmpalloc(argp, *lenp);
+       *namp = svcxdr_savemem(argp, p, *lenp);
        if (!*namp)
                return nfserr_jukebox;
-       memcpy(*namp, p, *lenp);
 
        return nfs_ok;
 }
@@ -1200,10 +1217,9 @@ nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
        p = xdr_inline_decode(argp->xdr, putfh->pf_fhlen);
        if (!p)
                return nfserr_bad_xdr;
-       putfh->pf_fhval = svcxdr_tmpalloc(argp, putfh->pf_fhlen);
+       putfh->pf_fhval = svcxdr_savemem(argp, p, putfh->pf_fhlen);
        if (!putfh->pf_fhval)
                return nfserr_jukebox;
-       memcpy(putfh->pf_fhval, p, putfh->pf_fhlen);
 
        return nfs_ok;
 }
@@ -1318,24 +1334,20 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient
        p = xdr_inline_decode(argp->xdr, setclientid->se_callback_netid_len);
        if (!p)
                return nfserr_bad_xdr;
-       setclientid->se_callback_netid_val = svcxdr_tmpalloc(argp,
+       setclientid->se_callback_netid_val = svcxdr_savemem(argp, p,
                                                setclientid->se_callback_netid_len);
        if (!setclientid->se_callback_netid_val)
                return nfserr_jukebox;
-       memcpy(setclientid->se_callback_netid_val, p,
-              setclientid->se_callback_netid_len);
 
        if (xdr_stream_decode_u32(argp->xdr, &setclientid->se_callback_addr_len) < 0)
                return nfserr_bad_xdr;
        p = xdr_inline_decode(argp->xdr, setclientid->se_callback_addr_len);
        if (!p)
                return nfserr_bad_xdr;
-       setclientid->se_callback_addr_val = svcxdr_tmpalloc(argp,
+       setclientid->se_callback_addr_val = svcxdr_savemem(argp, p,
                                                setclientid->se_callback_addr_len);
        if (!setclientid->se_callback_addr_val)
                return nfserr_jukebox;
-       memcpy(setclientid->se_callback_addr_val, p,
-              setclientid->se_callback_addr_len);
        if (xdr_stream_decode_u32(argp->xdr, &setclientid->se_callback_ident) < 0)
                return nfserr_bad_xdr;
 
@@ -1375,10 +1387,9 @@ nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify
        p = xdr_inline_decode(argp->xdr, verify->ve_attrlen);
        if (!p)
                return nfserr_bad_xdr;
-       verify->ve_attrval = svcxdr_tmpalloc(argp, verify->ve_attrlen);
+       verify->ve_attrval = svcxdr_savemem(argp, p, verify->ve_attrlen);
        if (!verify->ve_attrval)
                return nfserr_jukebox;
-       memcpy(verify->ve_attrval, p, verify->ve_attrlen);
 
        return nfs_ok;
 }
@@ -2333,10 +2344,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
                p = xdr_inline_decode(argp->xdr, argp->taglen);
                if (!p)
                        return 0;
-               argp->tag = svcxdr_tmpalloc(argp, argp->taglen);
+               argp->tag = svcxdr_savemem(argp, p, argp->taglen);
                if (!argp->tag)
                        return 0;
-               memcpy(argp->tag, p, argp->taglen);
                max_reply += xdr_align_size(argp->taglen);
        }
 
@@ -4756,6 +4766,7 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp,
                            resp->rqstp->rq_vec, read->rd_vlen, maxcount, eof);
        if (nfserr)
                return nfserr;
+       xdr_truncate_encode(xdr, starting_len + 16 + xdr_align_size(*maxcount));
 
        tmp = htonl(NFS4_CONTENT_DATA);
        write_bytes_to_xdr_buf(xdr->buf, starting_len,      &tmp,   4);
@@ -4763,6 +4774,10 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp,
        write_bytes_to_xdr_buf(xdr->buf, starting_len + 4,  &tmp64, 8);
        tmp = htonl(*maxcount);
        write_bytes_to_xdr_buf(xdr->buf, starting_len + 12, &tmp,   4);
+
+       tmp = xdr_zero;
+       write_bytes_to_xdr_buf(xdr->buf, starting_len + 16 + *maxcount, &tmp,
+                              xdr_pad_size(*maxcount));
        return nfs_ok;
 }
 
@@ -4855,14 +4870,15 @@ out:
        if (nfserr && segments == 0)
                xdr_truncate_encode(xdr, starting_len);
        else {
-               tmp = htonl(eof);
-               write_bytes_to_xdr_buf(xdr->buf, starting_len,     &tmp, 4);
-               tmp = htonl(segments);
-               write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4);
                if (nfserr) {
                        xdr_truncate_encode(xdr, last_segment);
                        nfserr = nfs_ok;
+                       eof = 0;
                }
+               tmp = htonl(eof);
+               write_bytes_to_xdr_buf(xdr->buf, starting_len,     &tmp, 4);
+               tmp = htonl(segments);
+               write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4);
        }
 
        return nfserr;
index 00384c332f9bb657a41654c99628d59cddb3b3df..f9c9f4c63cc77db4b67700e66cf521caa11a7017 100644 (file)
 
 #define NFSDDBG_FACILITY       NFSDDBG_SVC
 
-bool inter_copy_offload_enable;
-EXPORT_SYMBOL_GPL(inter_copy_offload_enable);
-module_param(inter_copy_offload_enable, bool, 0644);
-MODULE_PARM_DESC(inter_copy_offload_enable,
-                "Enable inter server to server copy offload. Default: false");
-
 extern struct svc_program      nfsd_program;
 static int                     nfsd(void *vrqstp);
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
index a60ff5ce1a375732df4552d3bb1d52b49f9c15bf..c300885ae75ddee7866e519c0d71cebadfa5d6da 100644 (file)
@@ -568,7 +568,6 @@ struct nfsd4_copy {
        struct nfs_fh           c_fh;
        nfs4_stateid            stateid;
 };
-extern bool inter_copy_offload_enable;
 
 struct nfsd4_seek {
        /* request */
index ee5a235b30562721d9800dbfafc3b958d51d8135..602e3a52884d883c639420e426b539fd74ef35c5 100644 (file)
@@ -1035,6 +1035,25 @@ struct clear_refs_private {
 };
 
 #ifdef CONFIG_MEM_SOFT_DIRTY
+
+#define is_cow_mapping(flags) (((flags) & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE)
+
+static inline bool pte_is_pinned(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
+{
+       struct page *page;
+
+       if (!pte_write(pte))
+               return false;
+       if (!is_cow_mapping(vma->vm_flags))
+               return false;
+       if (likely(!atomic_read(&vma->vm_mm->has_pinned)))
+               return false;
+       page = vm_normal_page(vma, addr, pte);
+       if (!page)
+               return false;
+       return page_maybe_dma_pinned(page);
+}
+
 static inline void clear_soft_dirty(struct vm_area_struct *vma,
                unsigned long addr, pte_t *pte)
 {
@@ -1049,6 +1068,8 @@ static inline void clear_soft_dirty(struct vm_area_struct *vma,
        if (pte_present(ptent)) {
                pte_t old_pte;
 
+               if (pte_is_pinned(vma, addr, ptent))
+                       return;
                old_pte = ptep_modify_prot_start(vma, addr, pte);
                ptent = pte_wrprotect(old_pte);
                ptent = pte_clear_soft_dirty(ptent);
@@ -1215,41 +1236,26 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
                        .type = type,
                };
 
+               if (mmap_write_lock_killable(mm)) {
+                       count = -EINTR;
+                       goto out_mm;
+               }
                if (type == CLEAR_REFS_MM_HIWATER_RSS) {
-                       if (mmap_write_lock_killable(mm)) {
-                               count = -EINTR;
-                               goto out_mm;
-                       }
-
                        /*
                         * Writing 5 to /proc/pid/clear_refs resets the peak
                         * resident set size to this mm's current rss value.
                         */
                        reset_mm_hiwater_rss(mm);
-                       mmap_write_unlock(mm);
-                       goto out_mm;
+                       goto out_unlock;
                }
 
-               if (mmap_read_lock_killable(mm)) {
-                       count = -EINTR;
-                       goto out_mm;
-               }
                tlb_gather_mmu(&tlb, mm, 0, -1);
                if (type == CLEAR_REFS_SOFT_DIRTY) {
                        for (vma = mm->mmap; vma; vma = vma->vm_next) {
                                if (!(vma->vm_flags & VM_SOFTDIRTY))
                                        continue;
-                               mmap_read_unlock(mm);
-                               if (mmap_write_lock_killable(mm)) {
-                                       count = -EINTR;
-                                       goto out_mm;
-                               }
-                               for (vma = mm->mmap; vma; vma = vma->vm_next) {
-                                       vma->vm_flags &= ~VM_SOFTDIRTY;
-                                       vma_set_page_prot(vma);
-                               }
-                               mmap_write_downgrade(mm);
-                               break;
+                               vma->vm_flags &= ~VM_SOFTDIRTY;
+                               vma_set_page_prot(vma);
                        }
 
                        mmu_notifier_range_init(&range, MMU_NOTIFY_SOFT_DIRTY,
@@ -1261,7 +1267,8 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
                if (type == CLEAR_REFS_SOFT_DIRTY)
                        mmu_notifier_invalidate_range_end(&range);
                tlb_finish_mmu(&tlb, 0, -1);
-               mmap_read_unlock(mm);
+out_unlock:
+               mmap_write_unlock(mm);
 out_mm:
                mmput(mm);
        }
index 5bef3a68395d8d32f4f686370846e7b6909ca728..d0df217f4712a5f6b7ca875239fa7a9a0d361800 100644 (file)
@@ -705,6 +705,7 @@ static int udf_check_vsd(struct super_block *sb)
        struct buffer_head *bh = NULL;
        int nsr = 0;
        struct udf_sb_info *sbi;
+       loff_t session_offset;
 
        sbi = UDF_SB(sb);
        if (sb->s_blocksize < sizeof(struct volStructDesc))
@@ -712,7 +713,8 @@ static int udf_check_vsd(struct super_block *sb)
        else
                sectorsize = sb->s_blocksize;
 
-       sector += (((loff_t)sbi->s_session) << sb->s_blocksize_bits);
+       session_offset = (loff_t)sbi->s_session << sb->s_blocksize_bits;
+       sector += session_offset;
 
        udf_debug("Starting at sector %u (%lu byte sectors)\n",
                  (unsigned int)(sector >> sb->s_blocksize_bits),
@@ -757,8 +759,7 @@ static int udf_check_vsd(struct super_block *sb)
 
        if (nsr > 0)
                return 1;
-       else if (!bh && sector - (sbi->s_session << sb->s_blocksize_bits) ==
-                       VSD_FIRST_SECTOR_OFFSET)
+       else if (!bh && sector - session_offset == VSD_FIRST_SECTOR_OFFSET)
                return -1;
        else
                return 0;
index dd90c9792909d1db39c2a8a52cc78216a034f1ba..0e7316a86240b8c309d6b49ba0d8c1663d2159e5 100644 (file)
  * See Documentation/atomic_bitops.txt for details.
  */
 
-static inline void set_bit(unsigned int nr, volatile unsigned long *p)
+static __always_inline void set_bit(unsigned int nr, volatile unsigned long *p)
 {
        p += BIT_WORD(nr);
        atomic_long_or(BIT_MASK(nr), (atomic_long_t *)p);
 }
 
-static inline void clear_bit(unsigned int nr, volatile unsigned long *p)
+static __always_inline void clear_bit(unsigned int nr, volatile unsigned long *p)
 {
        p += BIT_WORD(nr);
        atomic_long_andnot(BIT_MASK(nr), (atomic_long_t *)p);
 }
 
-static inline void change_bit(unsigned int nr, volatile unsigned long *p)
+static __always_inline void change_bit(unsigned int nr, volatile unsigned long *p)
 {
        p += BIT_WORD(nr);
        atomic_long_xor(BIT_MASK(nr), (atomic_long_t *)p);
index 74c6c0486eed782e267b1addd65669f1422bad65..555ab0fddbef7dc937a178e49621598736408c05 100644 (file)
 /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 */
 #if GCC_VERSION < 40900
 # error Sorry, your version of GCC is too old - please use 4.9 or newer.
+#elif defined(CONFIG_ARM64) && GCC_VERSION < 50100
+/*
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63293
+ * https://lore.kernel.org/r/20210107111841.GN1551@shell.armlinux.org.uk
+ */
+# error Sorry, your version of GCC is too old - please use 5.1 or newer.
 #endif
 
 /*
index 29d255fdd5d641cf31eefefcc3d47744e87734d3..90bd558a17f516780329589ea6a07d62b9909c5a 100644 (file)
@@ -150,6 +150,7 @@ void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n);
 
 unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
 sector_t dm_bufio_get_device_size(struct dm_bufio_client *c);
+struct dm_io_client *dm_bufio_get_dm_io_client(struct dm_bufio_client *c);
 sector_t dm_bufio_get_block_number(struct dm_buffer *b);
 void *dm_bufio_get_block_data(struct dm_buffer *b);
 void *dm_bufio_get_aux_data(struct dm_buffer *b);
index 5e0655fb2a6f7767572f6b82275abfd306a4b386..fe1ae73ff8b574a8ee31e03b07f06cb6d5ca2473 100644 (file)
@@ -35,8 +35,12 @@ struct kunit_kasan_expectation {
 #define KASAN_SHADOW_INIT 0
 #endif
 
+#ifndef PTE_HWTABLE_PTRS
+#define PTE_HWTABLE_PTRS 0
+#endif
+
 extern unsigned char kasan_early_shadow_page[PAGE_SIZE];
-extern pte_t kasan_early_shadow_pte[PTRS_PER_PTE];
+extern pte_t kasan_early_shadow_pte[PTRS_PER_PTE + PTE_HWTABLE_PTRS];
 extern pmd_t kasan_early_shadow_pmd[PTRS_PER_PMD];
 extern pud_t kasan_early_shadow_pud[PTRS_PER_PUD];
 extern p4d_t kasan_early_shadow_p4d[MAX_PTRS_PER_P4D];
index 5d71e8a8500f5ed13872c19b01cf7a8af9d62c11..aca4dc037b70b7284e6f997264c4c66d2701d8ac 100644 (file)
@@ -35,6 +35,9 @@ struct mdiobb_ctrl {
        const struct mdiobb_ops *ops;
 };
 
+int mdiobb_read(struct mii_bus *bus, int phy, int reg);
+int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val);
+
 /* The returned bus is not yet registered with the phy layer. */
 struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl);
 
index d827bd7f3bfe3a01e3c638ab43fa9673ab0b4cc3..eeb0b52203e929bb0c0e4f869abf395d29d5760d 100644 (file)
@@ -665,7 +665,7 @@ static inline struct lruvec *mem_cgroup_page_lruvec(struct page *page,
 {
        struct mem_cgroup *memcg = page_memcg(page);
 
-       VM_WARN_ON_ONCE_PAGE(!memcg, page);
+       VM_WARN_ON_ONCE_PAGE(!memcg && !mem_cgroup_disabled(), page);
        return mem_cgroup_lruvec(memcg, pgdat);
 }
 
index bf7966776c5577fd4a92a8c0837943b4f0aa5c54..505480217cf1a9b4f779b454d42bc78c464e189b 100644 (file)
@@ -163,8 +163,6 @@ int arm_pmu_acpi_probe(armpmu_init_fn init_fn);
 static inline int arm_pmu_acpi_probe(armpmu_init_fn init_fn) { return 0; }
 #endif
 
-bool arm_pmu_irq_is_nmi(void);
-
 /* Internal functions only for core arm_pmu code */
 struct arm_pmu *armpmu_alloc(void);
 struct arm_pmu *armpmu_alloc_atomic(void);
index 333bcdc39635bcfd2d2682891831bae613c6fa5e..5f60c9e907c9d8eae1e85ae0329838383e3325df 100644 (file)
@@ -366,7 +366,7 @@ static inline void skb_frag_size_sub(skb_frag_t *frag, int delta)
 static inline bool skb_frag_must_loop(struct page *p)
 {
 #if defined(CONFIG_HIGHMEM)
-       if (PageHighMem(p))
+       if (IS_ENABLED(CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP) || PageHighMem(p))
                return true;
 #endif
        return false;
@@ -1203,6 +1203,7 @@ struct skb_seq_state {
        struct sk_buff  *root_skb;
        struct sk_buff  *cur_skb;
        __u8            *frag_data;
+       __u32           frag_off;
 };
 
 void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from,
index 88a7673894d5e624e7ffa51eb3c16d9043080e88..cfbfd6fe01dfad22f81c8090c4a9dfdcb1d6a28a 100644 (file)
@@ -81,6 +81,8 @@ struct usbnet {
 #              define EVENT_LINK_CHANGE        11
 #              define EVENT_SET_RX_MODE        12
 #              define EVENT_NO_IP_ALIGN        13
+       u32                     rx_speed;       /* in bps - NOT Mbps */
+       u32                     tx_speed;       /* in bps - NOT Mbps */
 };
 
 static inline struct usb_driver *driver_of(struct usb_interface *intf)
index 9a4bbccddc7f7fff5a86109eef2dd2f831a3b5ad..0d6f7ec860615c6146d677bda5a652ad205c03f2 100644 (file)
@@ -1756,7 +1756,7 @@ struct cfg80211_sar_specs {
 
 
 /**
- * @struct cfg80211_sar_chan_ranges - sar frequency ranges
+ * struct cfg80211_sar_freq_ranges - sar frequency ranges
  * @start_freq:  start range edge frequency
  * @end_freq:    end range edge frequency
  */
@@ -3972,6 +3972,8 @@ struct mgmt_frame_regs {
  *     This callback may sleep.
  * @reset_tid_config: Reset TID specific configuration for the peer, for the
  *     given TIDs. This callback may sleep.
+ *
+ * @set_sar_specs: Update the SAR (TX power) settings.
  */
 struct cfg80211_ops {
        int     (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -4929,6 +4931,7 @@ struct wiphy_iftype_akm_suites {
  * @max_data_retry_count: maximum supported per TID retry count for
  *     configuration through the %NL80211_TID_CONFIG_ATTR_RETRY_SHORT and
  *     %NL80211_TID_CONFIG_ATTR_RETRY_LONG attributes
+ * @sar_capa: SAR control capabilities
  */
 struct wiphy {
        /* assign these fields before you register the wiphy */
index 7338b3865a2a3d278dc27c0167bba1b966bbda9f..111d7771b208150d4e6f445b2675648b4de0eb7d 100644 (file)
@@ -76,6 +76,8 @@ struct inet_connection_sock_af_ops {
  * @icsk_ext_hdr_len:     Network protocol overhead (IP/IPv6 options)
  * @icsk_ack:             Delayed ACK control data
  * @icsk_mtup;            MTU probing control data
+ * @icsk_probes_tstamp:    Probe timestamp (cleared by non-zero window ack)
+ * @icsk_user_timeout:    TCP_USER_TIMEOUT value
  */
 struct inet_connection_sock {
        /* inet_sock has to be the first member! */
@@ -129,6 +131,7 @@ struct inet_connection_sock {
 
                u32               probe_timestamp;
        } icsk_mtup;
+       u32                       icsk_probes_tstamp;
        u32                       icsk_user_timeout;
 
        u64                       icsk_ca_priv[104 / sizeof(u64)];
index d315740581f1ebc46de1e4180cc6ad9023cf1897..2bdbf62f4ecd7b4e7e62e45263176733fc5db02a 100644 (file)
@@ -3880,6 +3880,7 @@ enum ieee80211_reconfig_type {
  *     This callback may sleep.
  * @sta_set_4addr: Called to notify the driver when a station starts/stops using
  *     4-address mode
+ * @set_sar_specs: Update the SAR (TX power) settings.
  */
 struct ieee80211_ops {
        void (*tx)(struct ieee80211_hw *hw,
index bdc4323ce53c957c30809b0773b2d558dce555b7..129d200bccb46581f9959a8ee553acbed94466cf 100644 (file)
@@ -1921,10 +1921,13 @@ static inline void sk_set_txhash(struct sock *sk)
        sk->sk_txhash = net_tx_rndhash();
 }
 
-static inline void sk_rethink_txhash(struct sock *sk)
+static inline bool sk_rethink_txhash(struct sock *sk)
 {
-       if (sk->sk_txhash)
+       if (sk->sk_txhash) {
                sk_set_txhash(sk);
+               return true;
+       }
+       return false;
 }
 
 static inline struct dst_entry *
@@ -1947,12 +1950,10 @@ sk_dst_get(struct sock *sk)
        return dst;
 }
 
-static inline void dst_negative_advice(struct sock *sk)
+static inline void __dst_negative_advice(struct sock *sk)
 {
        struct dst_entry *ndst, *dst = __sk_dst_get(sk);
 
-       sk_rethink_txhash(sk);
-
        if (dst && dst->ops->negative_advice) {
                ndst = dst->ops->negative_advice(dst);
 
@@ -1964,6 +1965,12 @@ static inline void dst_negative_advice(struct sock *sk)
        }
 }
 
+static inline void dst_negative_advice(struct sock *sk)
+{
+       sk_rethink_txhash(sk);
+       __dst_negative_advice(sk);
+}
+
 static inline void
 __sk_dst_set(struct sock *sk, struct dst_entry *dst)
 {
index 58994e01302216d9b935f6ac3a3bb4e7fb794077..6f89c27265f5895587416a2ff1aae928c18543c0 100644 (file)
@@ -1424,13 +1424,61 @@ TRACE_EVENT(rpcb_unregister,
        )
 );
 
+/* Record an xdr_buf containing a fully-formed RPC message */
+DECLARE_EVENT_CLASS(svc_xdr_msg_class,
+       TP_PROTO(
+               const struct xdr_buf *xdr
+       ),
+
+       TP_ARGS(xdr),
+
+       TP_STRUCT__entry(
+               __field(u32, xid)
+               __field(const void *, head_base)
+               __field(size_t, head_len)
+               __field(const void *, tail_base)
+               __field(size_t, tail_len)
+               __field(unsigned int, page_len)
+               __field(unsigned int, msg_len)
+       ),
+
+       TP_fast_assign(
+               __be32 *p = (__be32 *)xdr->head[0].iov_base;
+
+               __entry->xid = be32_to_cpu(*p);
+               __entry->head_base = p;
+               __entry->head_len = xdr->head[0].iov_len;
+               __entry->tail_base = xdr->tail[0].iov_base;
+               __entry->tail_len = xdr->tail[0].iov_len;
+               __entry->page_len = xdr->page_len;
+               __entry->msg_len = xdr->len;
+       ),
+
+       TP_printk("xid=0x%08x head=[%p,%zu] page=%u tail=[%p,%zu] len=%u",
+               __entry->xid,
+               __entry->head_base, __entry->head_len, __entry->page_len,
+               __entry->tail_base, __entry->tail_len, __entry->msg_len
+       )
+);
+
+#define DEFINE_SVCXDRMSG_EVENT(name)                                   \
+               DEFINE_EVENT(svc_xdr_msg_class,                         \
+                               svc_xdr_##name,                         \
+                               TP_PROTO(                               \
+                                       const struct xdr_buf *xdr       \
+                               ),                                      \
+                               TP_ARGS(xdr))
+
+DEFINE_SVCXDRMSG_EVENT(recvfrom);
+
+/* Record an xdr_buf containing arbitrary data, tagged with an XID */
 DECLARE_EVENT_CLASS(svc_xdr_buf_class,
        TP_PROTO(
-               const struct svc_rqst *rqst,
+               __be32 xid,
                const struct xdr_buf *xdr
        ),
 
-       TP_ARGS(rqst, xdr),
+       TP_ARGS(xid, xdr),
 
        TP_STRUCT__entry(
                __field(u32, xid)
@@ -1443,7 +1491,7 @@ DECLARE_EVENT_CLASS(svc_xdr_buf_class,
        ),
 
        TP_fast_assign(
-               __entry->xid = be32_to_cpu(rqst->rq_xid);
+               __entry->xid = be32_to_cpu(xid);
                __entry->head_base = xdr->head[0].iov_base;
                __entry->head_len = xdr->head[0].iov_len;
                __entry->tail_base = xdr->tail[0].iov_base;
@@ -1463,12 +1511,11 @@ DECLARE_EVENT_CLASS(svc_xdr_buf_class,
                DEFINE_EVENT(svc_xdr_buf_class,                         \
                                svc_xdr_##name,                         \
                                TP_PROTO(                               \
-                                       const struct svc_rqst *rqst,    \
+                                       __be32 xid,                     \
                                        const struct xdr_buf *xdr       \
                                ),                                      \
-                               TP_ARGS(rqst, xdr))
+                               TP_ARGS(xid, xdr))
 
-DEFINE_SVCXDRBUF_EVENT(recvfrom);
 DEFINE_SVCXDRBUF_EVENT(sendto);
 
 /*
index 00c7235ae93e7daae3ce106f76fc5dfce1cd1bdd..2c43b0ef1e4d504a652d0d574d5b6e41fa107091 100644 (file)
@@ -192,7 +192,7 @@ void xs_suspend_cancel(void);
 
 struct work_struct;
 
-void xenbus_probe(struct work_struct *);
+void xenbus_probe(void);
 
 #define XENBUS_IS_ERR_READ(str) ({                     \
        if (!IS_ERR(str) && strlen(str) == 0) {         \
index 6edff97ad594bd5d6e98a8971723a4c07436db1b..2f0597320b6d279871834c2deea3a662736b7373 100644 (file)
@@ -176,14 +176,14 @@ BPF_CALL_4(bpf_inode_storage_get, struct bpf_map *, map, struct inode *, inode,
         * bpf_local_storage_update expects the owner to have a
         * valid storage pointer.
         */
-       if (!inode_storage_ptr(inode))
+       if (!inode || !inode_storage_ptr(inode))
                return (unsigned long)NULL;
 
        sdata = inode_storage_lookup(inode, map, true);
        if (sdata)
                return (unsigned long)sdata->data;
 
-       /* This helper must only called from where the inode is gurranteed
+       /* This helper must only called from where the inode is guaranteed
         * to have a refcount and cannot be freed.
         */
        if (flags & BPF_LOCAL_STORAGE_GET_F_CREATE) {
@@ -200,7 +200,10 @@ BPF_CALL_4(bpf_inode_storage_get, struct bpf_map *, map, struct inode *, inode,
 BPF_CALL_2(bpf_inode_storage_delete,
           struct bpf_map *, map, struct inode *, inode)
 {
-       /* This helper must only called from where the inode is gurranteed
+       if (!inode)
+               return -EINVAL;
+
+       /* This helper must only called from where the inode is guaranteed
         * to have a refcount and cannot be freed.
         */
        return inode_storage_delete(inode, map);
index 4ef1959a78f27fcc610b1d31dcc6f4ca489f2f72..e0da0258b732dd318304a6357984ec6f50947f42 100644 (file)
@@ -218,7 +218,7 @@ BPF_CALL_4(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *,
         * bpf_local_storage_update expects the owner to have a
         * valid storage pointer.
         */
-       if (!task_storage_ptr(task))
+       if (!task || !task_storage_ptr(task))
                return (unsigned long)NULL;
 
        sdata = task_storage_lookup(task, map, true);
@@ -243,6 +243,9 @@ BPF_CALL_4(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *,
 BPF_CALL_2(bpf_task_storage_delete, struct bpf_map *, map, struct task_struct *,
           task)
 {
+       if (!task)
+               return -EINVAL;
+
        /* This helper must only be called from places where the lifetime of the task
         * is guaranteed. Either by being refcounted or by being protected
         * by an RCU read-side critical section.
index 8d6bdb4f4d61819c873a437a8d3ef50eebe767fc..84a36ee4a4c20fa894a2b82cf05820e2576e7a03 100644 (file)
@@ -4172,7 +4172,7 @@ static int btf_parse_hdr(struct btf_verifier_env *env)
                return -ENOTSUPP;
        }
 
-       if (btf_data_size == hdr->hdr_len) {
+       if (!btf->base_btf && btf_data_size == hdr->hdr_len) {
                btf_verifier_log(env, "No data");
                return -EINVAL;
        }
index 6ec088a96302f980ee7e56feaf626ad078d03a77..96555a8a2c545435aee44fd2fe4bbc37532357c5 100644 (file)
@@ -1391,12 +1391,13 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level,
                if (ctx.optlen != 0) {
                        *optlen = ctx.optlen;
                        *kernel_optval = ctx.optval;
+                       /* export and don't free sockopt buf */
+                       return 0;
                }
        }
 
 out:
-       if (ret)
-               sockopt_free_buf(&ctx);
+       sockopt_free_buf(&ctx);
        return ret;
 }
 
index bd8a3183d0302efd7147e84b30054cf9aa6c10e5..41ca280b1dc19428d626ef16ed8db8eab58892df 100644 (file)
@@ -108,7 +108,7 @@ BPF_CALL_2(bpf_map_peek_elem, struct bpf_map *, map, void *, value)
 }
 
 const struct bpf_func_proto bpf_map_peek_elem_proto = {
-       .func           = bpf_map_pop_elem,
+       .func           = bpf_map_peek_elem,
        .gpl_only       = false,
        .ret_type       = RET_INTEGER,
        .arg1_type      = ARG_CONST_MAP_PTR,
index c3bb03c8371fc7aabc60245780582a6fed05b12a..e5999d86c76ea17ca49a4cf8851cf51cc20d9a3d 100644 (file)
@@ -2712,7 +2712,6 @@ out_unlock:
 out_put_prog:
        if (tgt_prog_fd && tgt_prog)
                bpf_prog_put(tgt_prog);
-       bpf_prog_put(prog);
        return err;
 }
 
@@ -2825,7 +2824,10 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
                        tp_name = prog->aux->attach_func_name;
                        break;
                }
-               return bpf_tracing_prog_attach(prog, 0, 0);
+               err = bpf_tracing_prog_attach(prog, 0, 0);
+               if (err >= 0)
+                       return err;
+               goto out_put_prog;
        case BPF_PROG_TYPE_RAW_TRACEPOINT:
        case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
                if (strncpy_from_user(buf,
index 17270b8404f173ff8e164fa542d11fa73b571cf9..e7368c5eacb7bdc508099841bc447612624faa7c 100644 (file)
@@ -2217,6 +2217,8 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
        case PTR_TO_RDWR_BUF:
        case PTR_TO_RDWR_BUF_OR_NULL:
        case PTR_TO_PERCPU_BTF_ID:
+       case PTR_TO_MEM:
+       case PTR_TO_MEM_OR_NULL:
                return true;
        default:
                return false;
@@ -5311,7 +5313,7 @@ static bool signed_add_overflows(s64 a, s64 b)
        return res < a;
 }
 
-static bool signed_add32_overflows(s64 a, s64 b)
+static bool signed_add32_overflows(s32 a, s32 b)
 {
        /* Do the add in u32, where overflow is well-defined */
        s32 res = (s32)((u32)a + (u32)b);
@@ -5321,7 +5323,7 @@ static bool signed_add32_overflows(s64 a, s64 b)
        return res < a;
 }
 
-static bool signed_sub_overflows(s32 a, s32 b)
+static bool signed_sub_overflows(s64 a, s64 b)
 {
        /* Do the sub in u64, where overflow is well-defined */
        s64 res = (s64)((u64)a - (u64)b);
@@ -5333,7 +5335,7 @@ static bool signed_sub_overflows(s32 a, s32 b)
 
 static bool signed_sub32_overflows(s32 a, s32 b)
 {
-       /* Do the sub in u64, where overflow is well-defined */
+       /* Do the sub in u32, where overflow is well-defined */
        s32 res = (s32)((u32)a - (u32)b);
 
        if (b < 0)
index ffdd0dc7ec6df809101f3a618cb3a65e31e434d9..6639a0cfe0aca6591a1934fbaef32efc2da788d3 100644 (file)
@@ -1291,11 +1291,16 @@ static size_t info_print_prefix(const struct printk_info  *info, bool syslog,
  * done:
  *
  *   - Add prefix for each line.
+ *   - Drop truncated lines that no longer fit into the buffer.
  *   - Add the trailing newline that has been removed in vprintk_store().
- *   - Drop truncated lines that do not longer fit into the buffer.
+ *   - Add a string terminator.
+ *
+ * Since the produced string is always terminated, the maximum possible
+ * return value is @r->text_buf_size - 1;
  *
  * Return: The length of the updated/prepared text, including the added
- * prefixes and the newline. The dropped line(s) are not counted.
+ * prefixes and the newline. The terminator is not counted. The dropped
+ * line(s) are not counted.
  */
 static size_t record_print_text(struct printk_record *r, bool syslog,
                                bool time)
@@ -1338,26 +1343,31 @@ static size_t record_print_text(struct printk_record *r, bool syslog,
 
                /*
                 * Truncate the text if there is not enough space to add the
-                * prefix and a trailing newline.
+                * prefix and a trailing newline and a terminator.
                 */
-               if (len + prefix_len + text_len + 1 > buf_size) {
+               if (len + prefix_len + text_len + 1 + 1 > buf_size) {
                        /* Drop even the current line if no space. */
-                       if (len + prefix_len + line_len + 1 > buf_size)
+                       if (len + prefix_len + line_len + 1 + 1 > buf_size)
                                break;
 
-                       text_len = buf_size - len - prefix_len - 1;
+                       text_len = buf_size - len - prefix_len - 1 - 1;
                        truncated = true;
                }
 
                memmove(text + prefix_len, text, text_len);
                memcpy(text, prefix, prefix_len);
 
+               /*
+                * Increment the prepared length to include the text and
+                * prefix that were just moved+copied. Also increment for the
+                * newline at the end of this line. If this is the last line,
+                * there is no newline, but it will be added immediately below.
+                */
                len += prefix_len + line_len + 1;
-
                if (text_len == line_len) {
                        /*
-                        * Add the trailing newline removed in
-                        * vprintk_store().
+                        * This is the last line. Add the trailing newline
+                        * removed in vprintk_store().
                         */
                        text[prefix_len + line_len] = '\n';
                        break;
@@ -1382,6 +1392,14 @@ static size_t record_print_text(struct printk_record *r, bool syslog,
                text_len -= line_len + 1;
        }
 
+       /*
+        * If a buffer was provided, it will be terminated. Space for the
+        * string terminator is guaranteed to be available. The terminator is
+        * not counted in the return value.
+        */
+       if (buf_size > 0)
+               text[len] = 0;
+
        return len;
 }
 
@@ -3427,7 +3445,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
        while (prb_read_valid_info(prb, seq, &info, &line_count)) {
                if (r.info->seq >= dumper->next_seq)
                        break;
-               l += get_record_print_text_size(&info, line_count, true, time);
+               l += get_record_print_text_size(&info, line_count, syslog, time);
                seq = r.info->seq + 1;
        }
 
@@ -3437,7 +3455,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
                                                &info, &line_count)) {
                if (r.info->seq >= dumper->next_seq)
                        break;
-               l -= get_record_print_text_size(&info, line_count, true, time);
+               l -= get_record_print_text_size(&info, line_count, syslog, time);
                seq = r.info->seq + 1;
        }
 
index 6704f06e0417134cb661d42463a36f9321a65d15..8a7b7362c0dd4765ef414ed1f0945d0470f9ed30 100644 (file)
@@ -1718,7 +1718,7 @@ static bool copy_data(struct prb_data_ring *data_ring,
 
        /* Caller interested in the line count? */
        if (line_count)
-               *line_count = count_lines(data, data_size);
+               *line_count = count_lines(data, len);
 
        /* Caller interested in the data content? */
        if (!buf || !buf_size)
index 546b860c6514dcc22bd33bdd12766e75f40d8b69..5ad8566534e7604d275e60cd4bd2ba78a1eb0b3e 100644 (file)
@@ -2550,6 +2550,9 @@ bool get_signal(struct ksignal *ksig)
        struct signal_struct *signal = current->signal;
        int signr;
 
+       if (unlikely(current->task_works))
+               task_work_run();
+
        /*
         * For non-generic architectures, check for TIF_NOTIFY_SIGNAL so
         * that the arch handlers don't all have to do it. If we get here
index d5a19413d4f8a3945cdb53cd64c2fd887773730d..c1a62ae7e8128f8a0b89ac5c6faa0756a4665907 100644 (file)
@@ -538,7 +538,7 @@ config KPROBE_EVENTS
 config KPROBE_EVENTS_ON_NOTRACE
        bool "Do NOT protect notrace function from kprobe events"
        depends on KPROBE_EVENTS
-       depends on KPROBES_ON_FTRACE
+       depends on DYNAMIC_FTRACE
        default n
        help
          This is only for the developers who want to debug ftrace itself
index 9c31f42245e93b6ae6386da8370274f61f1de173..e6fba1798771b401eaf97d08b2c4d5926eb81995 100644 (file)
@@ -434,7 +434,7 @@ static int disable_trace_kprobe(struct trace_event_call *call,
        return 0;
 }
 
-#if defined(CONFIG_KPROBES_ON_FTRACE) && \
+#if defined(CONFIG_DYNAMIC_FTRACE) && \
        !defined(CONFIG_KPROBE_EVENTS_ON_NOTRACE)
 static bool __within_notrace_func(unsigned long addr)
 {
index 1635111c5bd2af92ae6683b97040ebf941266a28..a21e6a5792c5a53fcdb3ffd29328d9d5f6d5afad 100644 (file)
@@ -1658,7 +1658,7 @@ static int copy_compat_iovec_from_user(struct iovec *iov,
                (const struct compat_iovec __user *)uvec;
        int ret = -EFAULT, i;
 
-       if (!user_access_begin(uvec, nr_segs * sizeof(*uvec)))
+       if (!user_access_begin(uiov, nr_segs * sizeof(*uiov)))
                return -EFAULT;
 
        for (i = 0; i < nr_segs; i++) {
index a2602969873dcf6c6bc989bcccb2136bc45348b0..18f6ee3179002a7f218dfafb4e7724685ff1c215 100644 (file)
@@ -4371,7 +4371,7 @@ retry:
                 * So we need to block hugepage fault by PG_hwpoison bit check.
                 */
                if (unlikely(PageHWPoison(page))) {
-                       ret = VM_FAULT_HWPOISON |
+                       ret = VM_FAULT_HWPOISON_LARGE |
                                VM_FAULT_SET_HINDEX(hstate_index(h));
                        goto backout_unlocked;
                }
index bc0ad208b3a7a3751f00c46f3365fab7528fe949..7ca0b92d5886dca033e6b2a050441fd01b71c048 100644 (file)
@@ -64,7 +64,8 @@ static inline bool kasan_pmd_table(pud_t pud)
        return false;
 }
 #endif
-pte_t kasan_early_shadow_pte[PTRS_PER_PTE] __page_aligned_bss;
+pte_t kasan_early_shadow_pte[PTRS_PER_PTE + PTE_HWTABLE_PTRS]
+       __page_aligned_bss;
 
 static inline bool kasan_pte_table(pmd_t pmd)
 {
index d24bcfa88d2f1bd42d96f4e52a6f3e8c2cd91396..1eaaec1e7687cc0c15c5d19ecee92e201875dadf 100644 (file)
@@ -1427,7 +1427,7 @@ phys_addr_t __init memblock_phys_alloc_range(phys_addr_t size,
 }
 
 /**
- * memblock_phys_alloc_try_nid - allocate a memory block from specified MUMA node
+ * memblock_phys_alloc_try_nid - allocate a memory block from specified NUMA node
  * @size: size of memory block to be allocated in bytes
  * @align: alignment of the region and block's size
  * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
index 5a38e9eade946b66b98730ec57ff80efeec93004..04d9f154a130d28f38d26dfb0a897656d747cd71 100644 (file)
@@ -1940,7 +1940,7 @@ retry:
                        goto retry;
                }
        } else if (ret == -EIO) {
-               pr_info("%s: %#lx: unknown page type: %lx (%pGP)\n",
+               pr_info("%s: %#lx: unknown page type: %lx (%pGp)\n",
                         __func__, pfn, page->flags, &page->flags);
        }
 
index 8cf96bd21341cf30e186c5bb1f893ab267149860..2c3a8650205343c54e451b98e5d7022c2c4b7109 100644 (file)
@@ -1111,7 +1111,7 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
                     const nodemask_t *to, int flags)
 {
        int busy = 0;
-       int err;
+       int err = 0;
        nodemask_t tmp;
 
        migrate_prep();
index bdbec4c981738dc4e821564d32abc0d897de29d1..027f6481ba59bca36ff024dbbf62cfa3f7ef04e9 100644 (file)
@@ -2862,20 +2862,20 @@ __rmqueue(struct zone *zone, unsigned int order, int migratetype,
 {
        struct page *page;
 
-#ifdef CONFIG_CMA
-       /*
-        * Balance movable allocations between regular and CMA areas by
-        * allocating from CMA when over half of the zone's free memory
-        * is in the CMA area.
-        */
-       if (alloc_flags & ALLOC_CMA &&
-           zone_page_state(zone, NR_FREE_CMA_PAGES) >
-           zone_page_state(zone, NR_FREE_PAGES) / 2) {
-               page = __rmqueue_cma_fallback(zone, order);
-               if (page)
-                       return page;
+       if (IS_ENABLED(CONFIG_CMA)) {
+               /*
+                * Balance movable allocations between regular and CMA areas by
+                * allocating from CMA when over half of the zone's free memory
+                * is in the CMA area.
+                */
+               if (alloc_flags & ALLOC_CMA &&
+                   zone_page_state(zone, NR_FREE_CMA_PAGES) >
+                   zone_page_state(zone, NR_FREE_PAGES) / 2) {
+                       page = __rmqueue_cma_fallback(zone, order);
+                       if (page)
+                               goto out;
+               }
        }
-#endif
 retry:
        page = __rmqueue_smallest(zone, order, migratetype);
        if (unlikely(!page)) {
@@ -2886,8 +2886,9 @@ retry:
                                                                alloc_flags))
                        goto retry;
        }
-
-       trace_mm_page_alloc_zone_locked(page, order, migratetype);
+out:
+       if (page)
+               trace_mm_page_alloc_zone_locked(page, order, migratetype);
        return page;
 }
 
index 4bcc119580890753d27d25807a18ab58b520b002..f5fee9cf90f8bb35d81a1424947c9299b09959a0 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/uio.h>
 #include <linux/sched.h>
+#include <linux/compat.h>
 #include <linux/sched/mm.h>
 #include <linux/highmem.h>
 #include <linux/ptrace.h>
index dc5b42e700b853eabd668d56fd04f9eb64c5c4d0..d9e4e10683cc129c33c67864e75c926a5a7bf9d6 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1973,7 +1973,7 @@ static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n,
 
                t = acquire_slab(s, n, page, object == NULL, &objects);
                if (!t)
-                       break;
+                       continue; /* cmpxchg raced */
 
                available += objects;
                if (!object) {
index 4d88fe5a277ac2d0e520f37f4dc7ec0a779fc9fe..e6f352bf0498248a5f36c991f56c80ac9cf290c3 100644 (file)
@@ -2420,8 +2420,10 @@ void *vmap(struct page **pages, unsigned int count,
                return NULL;
        }
 
-       if (flags & VM_MAP_PUT_PAGES)
+       if (flags & VM_MAP_PUT_PAGES) {
                area->pages = pages;
+               area->nr_pages = count;
+       }
        return area->addr;
 }
 EXPORT_SYMBOL(vmap);
index 257cba79a96dd024251478235b237f60b048cb70..b1b574ad199d2ca8bde196e73de0a129e8a61e43 100644 (file)
@@ -1238,6 +1238,8 @@ static unsigned int shrink_page_list(struct list_head *page_list,
                        if (!PageSwapCache(page)) {
                                if (!(sc->gfp_mask & __GFP_IO))
                                        goto keep_locked;
+                               if (page_maybe_dma_pinned(page))
+                                       goto keep_locked;
                                if (PageTransHuge(page)) {
                                        /* cannot split THP, skip it */
                                        if (!can_split_huge_page(page, NULL))
index 15bbfaf943fd12dea78bf8eda8f024a49005e6ef..8b644113715e9db49effcaa60cfe45572304bb13 100644 (file)
@@ -284,9 +284,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
        return 0;
 
 out_free_newdev:
-       if (new_dev->reg_state == NETREG_UNINITIALIZED ||
-           new_dev->reg_state == NETREG_UNREGISTERED)
-               free_netdev(new_dev);
+       free_netdev(new_dev);
        return err;
 }
 
index c1c30a9f76f343e90570102e6eb9d8407ae563ea..8b796c499cbb243f7cfa9552d02703602316fd70 100644 (file)
@@ -272,7 +272,8 @@ int bpf_prog_test_run_raw_tp(struct bpf_prog *prog,
            kattr->test.repeat)
                return -EINVAL;
 
-       if (ctx_size_in < prog->aux->max_ctx_offset)
+       if (ctx_size_in < prog->aux->max_ctx_offset ||
+           ctx_size_in > MAX_BPF_FUNC_ARGS * sizeof(u64))
                return -EINVAL;
 
        if ((kattr->test.flags & BPF_F_TEST_RUN_ON_CPU) == 0 && cpu != 0)
index 7839c3b9e5bea29e204461b58fcd868cef303c3a..3ef7f78e553bc93e2c24db9b5b8a016cc0235f28 100644 (file)
@@ -1155,6 +1155,7 @@ static int isotp_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
        if (peer)
                return -EOPNOTSUPP;
 
+       memset(addr, 0, sizeof(*addr));
        addr->can_family = AF_CAN;
        addr->can_ifindex = so->ifindex;
        addr->can_addr.tp.rx_id = so->rxid;
index 9815cfe42af097a274957ee73cb4d4c2f3fe8985..ca44c327bacedb8a218d404503c59c2d6e60649a 100644 (file)
@@ -569,6 +569,34 @@ e_range:
        return -ERANGE;
 }
 
+static int decode_con_secret(void **p, void *end, u8 *con_secret,
+                            int *con_secret_len)
+{
+       int len;
+
+       ceph_decode_32_safe(p, end, len, bad);
+       ceph_decode_need(p, end, len, bad);
+
+       dout("%s len %d\n", __func__, len);
+       if (con_secret) {
+               if (len > CEPH_MAX_CON_SECRET_LEN) {
+                       pr_err("connection secret too big %d\n", len);
+                       goto bad_memzero;
+               }
+               memcpy(con_secret, *p, len);
+               *con_secret_len = len;
+       }
+       memzero_explicit(*p, len);
+       *p += len;
+       return 0;
+
+bad_memzero:
+       memzero_explicit(*p, len);
+bad:
+       pr_err("failed to decode connection secret\n");
+       return -EINVAL;
+}
+
 static int handle_auth_session_key(struct ceph_auth_client *ac,
                                   void **p, void *end,
                                   u8 *session_key, int *session_key_len,
@@ -612,17 +640,9 @@ static int handle_auth_session_key(struct ceph_auth_client *ac,
                dout("%s decrypted %d bytes\n", __func__, ret);
                dend = dp + ret;
 
-               ceph_decode_32_safe(&dp, dend, len, e_inval);
-               if (len > CEPH_MAX_CON_SECRET_LEN) {
-                       pr_err("connection secret too big %d\n", len);
-                       return -EINVAL;
-               }
-
-               dout("%s connection secret len %d\n", __func__, len);
-               if (con_secret) {
-                       memcpy(con_secret, dp, len);
-                       *con_secret_len = len;
-               }
+               ret = decode_con_secret(&dp, dend, con_secret, con_secret_len);
+               if (ret)
+                       return ret;
        }
 
        /* service tickets */
@@ -828,7 +848,6 @@ static int decrypt_authorizer_reply(struct ceph_crypto_key *secret,
 {
        void *dp, *dend;
        u8 struct_v;
-       int len;
        int ret;
 
        dp = *p + ceph_x_encrypt_offset();
@@ -843,17 +862,9 @@ static int decrypt_authorizer_reply(struct ceph_crypto_key *secret,
        ceph_decode_64_safe(&dp, dend, *nonce_plus_one, e_inval);
        dout("%s nonce_plus_one %llu\n", __func__, *nonce_plus_one);
        if (struct_v >= 2) {
-               ceph_decode_32_safe(&dp, dend, len, e_inval);
-               if (len > CEPH_MAX_CON_SECRET_LEN) {
-                       pr_err("connection secret too big %d\n", len);
-                       return -EINVAL;
-               }
-
-               dout("%s connection secret len %d\n", __func__, len);
-               if (con_secret) {
-                       memcpy(con_secret, dp, len);
-                       *con_secret_len = len;
-               }
+               ret = decode_con_secret(&dp, dend, con_secret, con_secret_len);
+               if (ret)
+                       return ret;
        }
 
        return 0;
index 4f75df40fb121f3c955f916fac5a3bb7f64d7f40..92d89b3316459858668f9ad2adabb859552bdb8d 100644 (file)
@@ -96,6 +96,7 @@ int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end)
        key->len = ceph_decode_16(p);
        ceph_decode_need(p, end, key->len, bad);
        ret = set_secret(key, *p);
+       memzero_explicit(*p, key->len);
        *p += key->len;
        return ret;
 
@@ -134,7 +135,7 @@ int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *inkey)
 void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
 {
        if (key) {
-               kfree(key->key);
+               kfree_sensitive(key->key);
                key->key = NULL;
                if (key->tfm) {
                        crypto_free_sync_skcipher(key->tfm);
index 04f653b3c89733bba8771d79399af0053243957c..2cb5ffdf071af76a679a0f1cdae2f7b1a13a909d 100644 (file)
@@ -1100,7 +1100,7 @@ static int read_partial_message(struct ceph_connection *con)
                if (ret < 0)
                        return ret;
 
-               BUG_ON(!con->in_msg ^ skip);
+               BUG_ON((!con->in_msg) ^ skip);
                if (skip) {
                        /* skip this message */
                        dout("alloc_msg said skip message\n");
index c38d8de93836371f0beb51bee80c1ef9b81485f2..cc40ce4e02fbc44cfc3460fc5c52f5a04886295b 100644 (file)
@@ -689,11 +689,10 @@ static int verify_epilogue_crcs(struct ceph_connection *con, u32 front_crc,
 }
 
 static int setup_crypto(struct ceph_connection *con,
-                       u8 *session_key, int session_key_len,
-                       u8 *con_secret, int con_secret_len)
+                       const u8 *session_key, int session_key_len,
+                       const u8 *con_secret, int con_secret_len)
 {
        unsigned int noio_flag;
-       void *p;
        int ret;
 
        dout("%s con %p con_mode %d session_key_len %d con_secret_len %d\n",
@@ -751,15 +750,14 @@ static int setup_crypto(struct ceph_connection *con,
                return ret;
        }
 
-       p = con_secret;
-       WARN_ON((unsigned long)p & crypto_aead_alignmask(con->v2.gcm_tfm));
-       ret = crypto_aead_setkey(con->v2.gcm_tfm, p, CEPH_GCM_KEY_LEN);
+       WARN_ON((unsigned long)con_secret &
+               crypto_aead_alignmask(con->v2.gcm_tfm));
+       ret = crypto_aead_setkey(con->v2.gcm_tfm, con_secret, CEPH_GCM_KEY_LEN);
        if (ret) {
                pr_err("failed to set gcm key: %d\n", ret);
                return ret;
        }
 
-       p += CEPH_GCM_KEY_LEN;
        WARN_ON(crypto_aead_ivsize(con->v2.gcm_tfm) != CEPH_GCM_IV_LEN);
        ret = crypto_aead_setauthsize(con->v2.gcm_tfm, CEPH_GCM_TAG_LEN);
        if (ret) {
@@ -777,8 +775,11 @@ static int setup_crypto(struct ceph_connection *con,
        aead_request_set_callback(con->v2.gcm_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                                  crypto_req_done, &con->v2.gcm_wait);
 
-       memcpy(&con->v2.in_gcm_nonce, p, CEPH_GCM_IV_LEN);
-       memcpy(&con->v2.out_gcm_nonce, p + CEPH_GCM_IV_LEN, CEPH_GCM_IV_LEN);
+       memcpy(&con->v2.in_gcm_nonce, con_secret + CEPH_GCM_KEY_LEN,
+              CEPH_GCM_IV_LEN);
+       memcpy(&con->v2.out_gcm_nonce,
+              con_secret + CEPH_GCM_KEY_LEN + CEPH_GCM_IV_LEN,
+              CEPH_GCM_IV_LEN);
        return 0;  /* auth_x, secure mode */
 }
 
@@ -800,7 +801,7 @@ static int hmac_sha256(struct ceph_connection *con, const struct kvec *kvecs,
        desc->tfm = con->v2.hmac_tfm;
        ret = crypto_shash_init(desc);
        if (ret)
-               return ret;
+               goto out;
 
        for (i = 0; i < kvec_cnt; i++) {
                WARN_ON((unsigned long)kvecs[i].iov_base &
@@ -808,15 +809,14 @@ static int hmac_sha256(struct ceph_connection *con, const struct kvec *kvecs,
                ret = crypto_shash_update(desc, kvecs[i].iov_base,
                                          kvecs[i].iov_len);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
        ret = crypto_shash_final(desc, hmac);
-       if (ret)
-               return ret;
 
+out:
        shash_desc_zero(desc);
-       return 0;  /* auth_x, both plain and secure modes */
+       return ret;  /* auth_x, both plain and secure modes */
 }
 
 static void gcm_inc_nonce(struct ceph_gcm_nonce *nonce)
@@ -2072,27 +2072,32 @@ static int process_auth_done(struct ceph_connection *con, void *p, void *end)
        if (con->state != CEPH_CON_S_V2_AUTH) {
                dout("%s con %p state changed to %d\n", __func__, con,
                     con->state);
-               return -EAGAIN;
+               ret = -EAGAIN;
+               goto out;
        }
 
        dout("%s con %p handle_auth_done ret %d\n", __func__, con, ret);
        if (ret)
-               return ret;
+               goto out;
 
        ret = setup_crypto(con, session_key, session_key_len, con_secret,
                           con_secret_len);
        if (ret)
-               return ret;
+               goto out;
 
        reset_out_kvecs(con);
        ret = prepare_auth_signature(con);
        if (ret) {
                pr_err("prepare_auth_signature failed: %d\n", ret);
-               return ret;
+               goto out;
        }
 
        con->state = CEPH_CON_S_V2_AUTH_SIGNATURE;
-       return 0;
+
+out:
+       memzero_explicit(session_key_buf, sizeof(session_key_buf));
+       memzero_explicit(con_secret_buf, sizeof(con_secret_buf));
+       return ret;
 
 bad:
        pr_err("failed to decode auth_done\n");
@@ -3436,6 +3441,8 @@ void ceph_con_v2_reset_protocol(struct ceph_connection *con)
        }
 
        con->v2.con_mode = CEPH_CON_MODE_UNKNOWN;
+       memzero_explicit(&con->v2.in_gcm_nonce, CEPH_GCM_IV_LEN);
+       memzero_explicit(&con->v2.out_gcm_nonce, CEPH_GCM_IV_LEN);
 
        if (con->v2.hmac_tfm) {
                crypto_free_shash(con->v2.hmac_tfm);
index b9d54ed9f33841d546bca9b79c04bbef6654b70d..195ceb8afb061ce2938f0f61ce21b88ee7174cf4 100644 (file)
@@ -1433,7 +1433,7 @@ static int mon_handle_auth_bad_method(struct ceph_connection *con,
 /*
  * handle incoming message
  */
-static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
+static void mon_dispatch(struct ceph_connection *con, struct ceph_msg *msg)
 {
        struct ceph_mon_client *monc = con->private;
        int type = le16_to_cpu(msg->hdr.type);
@@ -1565,21 +1565,21 @@ static void mon_fault(struct ceph_connection *con)
  * will come from the messenger workqueue, which is drained prior to
  * mon_client destruction.
  */
-static struct ceph_connection *con_get(struct ceph_connection *con)
+static struct ceph_connection *mon_get_con(struct ceph_connection *con)
 {
        return con;
 }
 
-static void con_put(struct ceph_connection *con)
+static void mon_put_con(struct ceph_connection *con)
 {
 }
 
 static const struct ceph_connection_operations mon_con_ops = {
-       .get = con_get,
-       .put = con_put,
-       .dispatch = dispatch,
-       .fault = mon_fault,
+       .get = mon_get_con,
+       .put = mon_put_con,
        .alloc_msg = mon_alloc_msg,
+       .dispatch = mon_dispatch,
+       .fault = mon_fault,
        .get_auth_request = mon_get_auth_request,
        .handle_auth_reply_more = mon_handle_auth_reply_more,
        .handle_auth_done = mon_handle_auth_done,
index 61229c5e22cb84e6943978671b3b8bb1749243e6..ff8624a7c96438df6b691cdc536a7b196919df95 100644 (file)
@@ -5412,7 +5412,7 @@ void ceph_osdc_cleanup(void)
 /*
  * handle incoming message
  */
-static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
+static void osd_dispatch(struct ceph_connection *con, struct ceph_msg *msg)
 {
        struct ceph_osd *osd = con->private;
        struct ceph_osd_client *osdc = osd->o_osdc;
@@ -5534,9 +5534,9 @@ static struct ceph_msg *alloc_msg_with_page_vector(struct ceph_msg_header *hdr)
        return m;
 }
 
-static struct ceph_msg *alloc_msg(struct ceph_connection *con,
-                                 struct ceph_msg_header *hdr,
-                                 int *skip)
+static struct ceph_msg *osd_alloc_msg(struct ceph_connection *con,
+                                     struct ceph_msg_header *hdr,
+                                     int *skip)
 {
        struct ceph_osd *osd = con->private;
        int type = le16_to_cpu(hdr->type);
@@ -5560,7 +5560,7 @@ static struct ceph_msg *alloc_msg(struct ceph_connection *con,
 /*
  * Wrappers to refcount containing ceph_osd struct
  */
-static struct ceph_connection *get_osd_con(struct ceph_connection *con)
+static struct ceph_connection *osd_get_con(struct ceph_connection *con)
 {
        struct ceph_osd *osd = con->private;
        if (get_osd(osd))
@@ -5568,7 +5568,7 @@ static struct ceph_connection *get_osd_con(struct ceph_connection *con)
        return NULL;
 }
 
-static void put_osd_con(struct ceph_connection *con)
+static void osd_put_con(struct ceph_connection *con)
 {
        struct ceph_osd *osd = con->private;
        put_osd(osd);
@@ -5582,8 +5582,8 @@ static void put_osd_con(struct ceph_connection *con)
  * Note: returned pointer is the address of a structure that's
  * managed separately.  Caller must *not* attempt to free it.
  */
-static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
-                                       int *proto, int force_new)
+static struct ceph_auth_handshake *
+osd_get_authorizer(struct ceph_connection *con, int *proto, int force_new)
 {
        struct ceph_osd *o = con->private;
        struct ceph_osd_client *osdc = o->o_osdc;
@@ -5599,7 +5599,7 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
        return auth;
 }
 
-static int add_authorizer_challenge(struct ceph_connection *con,
+static int osd_add_authorizer_challenge(struct ceph_connection *con,
                                    void *challenge_buf, int challenge_buf_len)
 {
        struct ceph_osd *o = con->private;
@@ -5610,7 +5610,7 @@ static int add_authorizer_challenge(struct ceph_connection *con,
                                            challenge_buf, challenge_buf_len);
 }
 
-static int verify_authorizer_reply(struct ceph_connection *con)
+static int osd_verify_authorizer_reply(struct ceph_connection *con)
 {
        struct ceph_osd *o = con->private;
        struct ceph_osd_client *osdc = o->o_osdc;
@@ -5622,7 +5622,7 @@ static int verify_authorizer_reply(struct ceph_connection *con)
                NULL, NULL, NULL, NULL);
 }
 
-static int invalidate_authorizer(struct ceph_connection *con)
+static int osd_invalidate_authorizer(struct ceph_connection *con)
 {
        struct ceph_osd *o = con->private;
        struct ceph_osd_client *osdc = o->o_osdc;
@@ -5731,18 +5731,18 @@ static int osd_check_message_signature(struct ceph_msg *msg)
 }
 
 static const struct ceph_connection_operations osd_con_ops = {
-       .get = get_osd_con,
-       .put = put_osd_con,
-       .dispatch = dispatch,
-       .get_authorizer = get_authorizer,
-       .add_authorizer_challenge = add_authorizer_challenge,
-       .verify_authorizer_reply = verify_authorizer_reply,
-       .invalidate_authorizer = invalidate_authorizer,
-       .alloc_msg = alloc_msg,
+       .get = osd_get_con,
+       .put = osd_put_con,
+       .alloc_msg = osd_alloc_msg,
+       .dispatch = osd_dispatch,
+       .fault = osd_fault,
        .reencode_message = osd_reencode_message,
+       .get_authorizer = osd_get_authorizer,
+       .add_authorizer_challenge = osd_add_authorizer_challenge,
+       .verify_authorizer_reply = osd_verify_authorizer_reply,
+       .invalidate_authorizer = osd_invalidate_authorizer,
        .sign_message = osd_sign_message,
        .check_message_signature = osd_check_message_signature,
-       .fault = osd_fault,
        .get_auth_request = osd_get_auth_request,
        .handle_auth_reply_more = osd_handle_auth_reply_more,
        .handle_auth_done = osd_handle_auth_done,
index 8fa739259041aaa03585b5a7b8ebce862f4b7d1d..a979b86dbacda9dfe31dd8b269024f7f0f5a8ef1 100644 (file)
@@ -9661,9 +9661,20 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
                }
        }
 
-       if ((features & NETIF_F_HW_TLS_TX) && !(features & NETIF_F_HW_CSUM)) {
-               netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n");
-               features &= ~NETIF_F_HW_TLS_TX;
+       if (features & NETIF_F_HW_TLS_TX) {
+               bool ip_csum = (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) ==
+                       (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+               bool hw_csum = features & NETIF_F_HW_CSUM;
+
+               if (!ip_csum && !hw_csum) {
+                       netdev_dbg(dev, "Dropping TLS TX HW offload feature since no CSUM feature.\n");
+                       features &= ~NETIF_F_HW_TLS_TX;
+               }
+       }
+
+       if ((features & NETIF_F_HW_TLS_RX) && !(features & NETIF_F_RXCSUM)) {
+               netdev_dbg(dev, "Dropping TLS RX HW offload feature since no RXCSUM feature.\n");
+               features &= ~NETIF_F_HW_TLS_RX;
        }
 
        return features;
@@ -10077,17 +10088,11 @@ int register_netdevice(struct net_device *dev)
        ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
        ret = notifier_to_errno(ret);
        if (ret) {
+               /* Expect explicit free_netdev() on failure */
+               dev->needs_free_netdev = false;
                rollback_registered(dev);
-               rcu_barrier();
-
-               dev->reg_state = NETREG_UNREGISTERED;
-               /* We should put the kobject that hold in
-                * netdev_unregister_kobject(), otherwise
-                * the net device cannot be freed when
-                * driver calls free_netdev(), because the
-                * kobject is being hold.
-                */
-               kobject_put(&dev->dev.kobj);
+               net_set_todo(dev);
+               goto out;
        }
        /*
         *      Prevent userspace races by waiting until the network
@@ -10631,6 +10636,17 @@ void free_netdev(struct net_device *dev)
        struct napi_struct *p, *n;
 
        might_sleep();
+
+       /* When called immediately after register_netdevice() failed the unwind
+        * handling may still be dismantling the device. Handle that case by
+        * deferring the free.
+        */
+       if (dev->reg_state == NETREG_UNREGISTERING) {
+               ASSERT_RTNL();
+               dev->needs_free_netdev = true;
+               return;
+       }
+
        netif_free_tx_queues(dev);
        netif_free_rx_queues(dev);
 
index ee828e4b1007e9809e2495a759b869dafb8daa14..738d4344d6799a0dda3051e265da84fcabc0d86c 100644 (file)
@@ -4146,7 +4146,7 @@ out:
 static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
                                              struct genl_info *info)
 {
-       struct devlink_port *devlink_port = info->user_ptr[0];
+       struct devlink_port *devlink_port = info->user_ptr[1];
        struct devlink_param_item *param_item;
        struct sk_buff *msg;
        int err;
@@ -4175,7 +4175,7 @@ static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
 static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
                                              struct genl_info *info)
 {
-       struct devlink_port *devlink_port = info->user_ptr[0];
+       struct devlink_port *devlink_port = info->user_ptr[1];
 
        return __devlink_nl_cmd_param_set_doit(devlink_port->devlink,
                                               devlink_port->index,
index 80dbf2f4016e26824bc968115503ca2072933f63..8e582e29a41e39809cc534865bb3c91c05b3d9f2 100644 (file)
@@ -80,11 +80,11 @@ static void est_timer(struct timer_list *t)
        u64 rate, brate;
 
        est_fetch_counters(est, &b);
-       brate = (b.bytes - est->last_bytes) << (10 - est->ewma_log - est->intvl_log);
-       brate -= (est->avbps >> est->ewma_log);
+       brate = (b.bytes - est->last_bytes) << (10 - est->intvl_log);
+       brate = (brate >> est->ewma_log) - (est->avbps >> est->ewma_log);
 
-       rate = (b.packets - est->last_packets) << (10 - est->ewma_log - est->intvl_log);
-       rate -= (est->avpps >> est->ewma_log);
+       rate = (b.packets - est->last_packets) << (10 - est->intvl_log);
+       rate = (rate >> est->ewma_log) - (est->avpps >> est->ewma_log);
 
        write_seqcount_begin(&est->seq);
        est->avbps += brate;
@@ -143,6 +143,9 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
        if (parm->interval < -2 || parm->interval > 3)
                return -EINVAL;
 
+       if (parm->ewma_log == 0 || parm->ewma_log >= 31)
+               return -EINVAL;
+
        est = kzalloc(sizeof(*est), GFP_KERNEL);
        if (!est)
                return -ENOBUFS;
index bb0596c41b3efb8b86de22797891c0e88fc9cbb4..3d6ab194d0f58c909ada67d6bd6dd6f28576c932 100644 (file)
@@ -3439,26 +3439,15 @@ replay:
 
        dev->ifindex = ifm->ifi_index;
 
-       if (ops->newlink) {
+       if (ops->newlink)
                err = ops->newlink(link_net ? : net, dev, tb, data, extack);
-               /* Drivers should call free_netdev() in ->destructor
-                * and unregister it on failure after registration
-                * so that device could be finally freed in rtnl_unlock.
-                */
-               if (err < 0) {
-                       /* If device is not registered at all, free it now */
-                       if (dev->reg_state == NETREG_UNINITIALIZED ||
-                           dev->reg_state == NETREG_UNREGISTERED)
-                               free_netdev(dev);
-                       goto out;
-               }
-       } else {
+       else
                err = register_netdevice(dev);
-               if (err < 0) {
-                       free_netdev(dev);
-                       goto out;
-               }
+       if (err < 0) {
+               free_netdev(dev);
+               goto out;
        }
+
        err = rtnl_configure_link(dev, ifm);
        if (err < 0)
                goto out_unregister;
index f62cae3f75d877adec1efbf9726c42515f3912e8..785daff48030d328b879afe58db35c8d96a58ea7 100644 (file)
@@ -437,7 +437,11 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,
 
        len += NET_SKB_PAD;
 
-       if ((len > SKB_WITH_OVERHEAD(PAGE_SIZE)) ||
+       /* If requested length is either too small or too big,
+        * we use kmalloc() for skb->head allocation.
+        */
+       if (len <= SKB_WITH_OVERHEAD(1024) ||
+           len > SKB_WITH_OVERHEAD(PAGE_SIZE) ||
            (gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) {
                skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX, NUMA_NO_NODE);
                if (!skb)
@@ -501,13 +505,17 @@ EXPORT_SYMBOL(__netdev_alloc_skb);
 struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len,
                                 gfp_t gfp_mask)
 {
-       struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache);
+       struct napi_alloc_cache *nc;
        struct sk_buff *skb;
        void *data;
 
        len += NET_SKB_PAD + NET_IP_ALIGN;
 
-       if ((len > SKB_WITH_OVERHEAD(PAGE_SIZE)) ||
+       /* If requested length is either too small or too big,
+        * we use kmalloc() for skb->head allocation.
+        */
+       if (len <= SKB_WITH_OVERHEAD(1024) ||
+           len > SKB_WITH_OVERHEAD(PAGE_SIZE) ||
            (gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) {
                skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX, NUMA_NO_NODE);
                if (!skb)
@@ -515,6 +523,7 @@ struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len,
                goto skb_success;
        }
 
+       nc = this_cpu_ptr(&napi_alloc_cache);
        len += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
        len = SKB_DATA_ALIGN(len);
 
@@ -3442,6 +3451,7 @@ void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from,
        st->root_skb = st->cur_skb = skb;
        st->frag_idx = st->stepped_offset = 0;
        st->frag_data = NULL;
+       st->frag_off = 0;
 }
 EXPORT_SYMBOL(skb_prepare_seq_read);
 
@@ -3496,14 +3506,27 @@ next_skb:
                st->stepped_offset += skb_headlen(st->cur_skb);
 
        while (st->frag_idx < skb_shinfo(st->cur_skb)->nr_frags) {
+               unsigned int pg_idx, pg_off, pg_sz;
+
                frag = &skb_shinfo(st->cur_skb)->frags[st->frag_idx];
-               block_limit = skb_frag_size(frag) + st->stepped_offset;
 
+               pg_idx = 0;
+               pg_off = skb_frag_off(frag);
+               pg_sz = skb_frag_size(frag);
+
+               if (skb_frag_must_loop(skb_frag_page(frag))) {
+                       pg_idx = (pg_off + st->frag_off) >> PAGE_SHIFT;
+                       pg_off = offset_in_page(pg_off + st->frag_off);
+                       pg_sz = min_t(unsigned int, pg_sz - st->frag_off,
+                                                   PAGE_SIZE - pg_off);
+               }
+
+               block_limit = pg_sz + st->stepped_offset;
                if (abs_offset < block_limit) {
                        if (!st->frag_data)
-                               st->frag_data = kmap_atomic(skb_frag_page(frag));
+                               st->frag_data = kmap_atomic(skb_frag_page(frag) + pg_idx);
 
-                       *data = (u8 *) st->frag_data + skb_frag_off(frag) +
+                       *data = (u8 *)st->frag_data + pg_off +
                                (abs_offset - st->stepped_offset);
 
                        return block_limit - abs_offset;
@@ -3514,8 +3537,12 @@ next_skb:
                        st->frag_data = NULL;
                }
 
-               st->frag_idx++;
-               st->stepped_offset += skb_frag_size(frag);
+               st->stepped_offset += pg_sz;
+               st->frag_off += pg_sz;
+               if (st->frag_off == skb_frag_size(frag)) {
+                       st->frag_off = 0;
+                       st->frag_idx++;
+               }
        }
 
        if (st->frag_data) {
@@ -3655,7 +3682,8 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
        unsigned int delta_truesize = 0;
        unsigned int delta_len = 0;
        struct sk_buff *tail = NULL;
-       struct sk_buff *nskb;
+       struct sk_buff *nskb, *tmp;
+       int err;
 
        skb_push(skb, -skb_network_offset(skb) + offset);
 
@@ -3665,11 +3693,28 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
                nskb = list_skb;
                list_skb = list_skb->next;
 
+               err = 0;
+               if (skb_shared(nskb)) {
+                       tmp = skb_clone(nskb, GFP_ATOMIC);
+                       if (tmp) {
+                               consume_skb(nskb);
+                               nskb = tmp;
+                               err = skb_unclone(nskb, GFP_ATOMIC);
+                       } else {
+                               err = -ENOMEM;
+                       }
+               }
+
                if (!tail)
                        skb->next = nskb;
                else
                        tail->next = nskb;
 
+               if (unlikely(err)) {
+                       nskb->next = list_skb;
+                       goto err_linearize;
+               }
+
                tail = nskb;
 
                delta_len += nskb->len;
index bbdd3c7b6cb5b960e4d107c3f25e7067db938483..b065f0a103ed06e40105967b9926679d5840d00a 100644 (file)
@@ -293,7 +293,7 @@ select_by_hash:
                        i = j = reciprocal_scale(hash, socks);
                        while (reuse->socks[i]->sk_state == TCP_ESTABLISHED) {
                                i++;
-                               if (i >= reuse->num_socks)
+                               if (i >= socks)
                                        i = 0;
                                if (i == j)
                                        goto out;
index 7d49b6fd6cef966ac0c01d40e0925e655ef36597..653e3bc9c87b9161d75a3682d096177d2a3e56bf 100644 (file)
@@ -1765,7 +1765,7 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
        fn = &reply_funcs[dcb->cmd];
        if (!fn->cb)
                return -EOPNOTSUPP;
-       if (fn->type != nlh->nlmsg_type)
+       if (fn->type == RTM_SETDCB && !netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        if (!tb[DCB_ATTR_IFNAME])
index 183003e45762ad312a4f0802351535dd5b115f33..a47e0f9b20d0a98e04486b4104e90b41122eca36 100644 (file)
@@ -353,9 +353,13 @@ static int dsa_port_devlink_setup(struct dsa_port *dp)
 
 static void dsa_port_teardown(struct dsa_port *dp)
 {
+       struct devlink_port *dlp = &dp->devlink_port;
+
        if (!dp->setup)
                return;
 
+       devlink_port_type_clear(dlp);
+
        switch (dp->type) {
        case DSA_PORT_TYPE_UNUSED:
                break;
index 5a0f6fec4271d4ca1484003bff29e651ad67c785..cb3a5cf99b2583f4255471d242b27cd36e34f9e1 100644 (file)
@@ -309,8 +309,18 @@ static struct lock_class_key dsa_master_addr_list_lock_key;
 int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
 {
        int mtu = ETH_DATA_LEN + cpu_dp->tag_ops->overhead;
+       struct dsa_switch *ds = cpu_dp->ds;
+       struct device_link *consumer_link;
        int ret;
 
+       /* The DSA master must use SET_NETDEV_DEV for this to work. */
+       consumer_link = device_link_add(ds->dev, dev->dev.parent,
+                                       DL_FLAG_AUTOREMOVE_CONSUMER);
+       if (!consumer_link)
+               netdev_err(dev,
+                          "Failed to create a device link to DSA switch %s\n",
+                          dev_name(ds->dev));
+
        rtnl_lock();
        ret = dev_set_mtu(dev, mtu);
        rtnl_unlock();
index 8b07f3a4f2db2509bed581ab549c09b621c8b7ea..a3271ec3e1627fb4f6e29da0e0fb1a638fe7e789 100644 (file)
@@ -443,7 +443,6 @@ static int esp_output_encap(struct xfrm_state *x, struct sk_buff *skb,
 int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
 {
        u8 *tail;
-       u8 *vaddr;
        int nfrags;
        int esph_offset;
        struct page *page;
@@ -485,14 +484,10 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
                        page = pfrag->page;
                        get_page(page);
 
-                       vaddr = kmap_atomic(page);
-
-                       tail = vaddr + pfrag->offset;
+                       tail = page_address(page) + pfrag->offset;
 
                        esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
 
-                       kunmap_atomic(vaddr);
-
                        nfrags = skb_shinfo(skb)->nr_frags;
 
                        __skb_fill_page_desc(skb, nfrags, page, pfrag->offset,
index fd8b8800a2c3022666f46b9ba2ac984f7cf6b04d..6bd7ca09af03dd5385096f749cf05afecb4b7795 100644 (file)
@@ -851,6 +851,7 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
                newicsk->icsk_retransmits = 0;
                newicsk->icsk_backoff     = 0;
                newicsk->icsk_probes_out  = 0;
+               newicsk->icsk_probes_tstamp = 0;
 
                /* Deinitialize accept_queue to trap illegal accesses. */
                memset(&newicsk->icsk_accept_queue, 0, sizeof(newicsk->icsk_accept_queue));
index cc23f1ce239c28ac9c12ef1a5ef5316407e2bee9..8cd3224d913e0ca5cc0c227e813b5f279fed5545 100644 (file)
@@ -76,7 +76,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
        flow.daddr = iph->saddr;
        flow.saddr = rpfilter_get_saddr(iph->daddr);
        flow.flowi4_mark = info->flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0;
-       flow.flowi4_tos = RT_TOS(iph->tos);
+       flow.flowi4_tos = iph->tos & IPTOS_RT_MASK;
        flow.flowi4_scope = RT_SCOPE_UNIVERSE;
        flow.flowi4_oif = l3mdev_master_ifindex_rcu(xt_in(par));
 
index ed42d2193c5c76bc9d48f36c13e72ca5be8aee1f..32545ecf2ab105739e9a751b5202a7b3c9d6b22e 100644 (file)
@@ -2937,6 +2937,7 @@ int tcp_disconnect(struct sock *sk, int flags)
 
        icsk->icsk_backoff = 0;
        icsk->icsk_probes_out = 0;
+       icsk->icsk_probes_tstamp = 0;
        icsk->icsk_rto = TCP_TIMEOUT_INIT;
        icsk->icsk_rto_min = TCP_RTO_MIN;
        icsk->icsk_delack_max = TCP_DELACK_MAX;
index c7e16b0ed791fcbd864860d6216339542e286929..a7dfca0a38cd7a0cdbe0a1c6d9b17866a33ebdc1 100644 (file)
@@ -3384,6 +3384,7 @@ static void tcp_ack_probe(struct sock *sk)
                return;
        if (!after(TCP_SKB_CB(head)->end_seq, tcp_wnd_end(tp))) {
                icsk->icsk_backoff = 0;
+               icsk->icsk_probes_tstamp = 0;
                inet_csk_clear_xmit_timer(sk, ICSK_TIME_PROBE0);
                /* Socket must be waked up by subsequent tcp_data_snd_check().
                 * This function is not for random using!
@@ -4396,10 +4397,9 @@ static void tcp_rcv_spurious_retrans(struct sock *sk, const struct sk_buff *skb)
         * The receiver remembers and reflects via DSACKs. Leverage the
         * DSACK state and change the txhash to re-route speculatively.
         */
-       if (TCP_SKB_CB(skb)->seq == tcp_sk(sk)->duplicate_sack[0].start_seq) {
-               sk_rethink_txhash(sk);
+       if (TCP_SKB_CB(skb)->seq == tcp_sk(sk)->duplicate_sack[0].start_seq &&
+           sk_rethink_txhash(sk))
                NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDUPLICATEDATAREHASH);
-       }
 }
 
 static void tcp_send_dupack(struct sock *sk, const struct sk_buff *skb)
index 58207c7769d05693b650e3c93e4ef405a5d4b23a..777306b5bc224d6e36da13641b5cdf4f0dba81fd 100644 (file)
@@ -1595,6 +1595,8 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
                tcp_move_syn(newtp, req);
                ireq->ireq_opt = NULL;
        } else {
+               newinet->inet_opt = NULL;
+
                if (!req_unhash && found_dup_sk) {
                        /* This code path should only be executed in the
                         * syncookie case only
@@ -1602,8 +1604,6 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
                        bh_unlock_sock(newsk);
                        sock_put(newsk);
                        newsk = NULL;
-               } else {
-                       newinet->inet_opt = NULL;
                }
        }
        return newsk;
@@ -1760,6 +1760,7 @@ int tcp_v4_early_demux(struct sk_buff *skb)
 bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
 {
        u32 limit = READ_ONCE(sk->sk_rcvbuf) + READ_ONCE(sk->sk_sndbuf);
+       u32 tail_gso_size, tail_gso_segs;
        struct skb_shared_info *shinfo;
        const struct tcphdr *th;
        struct tcphdr *thtail;
@@ -1767,6 +1768,7 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
        unsigned int hdrlen;
        bool fragstolen;
        u32 gso_segs;
+       u32 gso_size;
        int delta;
 
        /* In case all data was pulled from skb frags (in __pskb_pull_tail()),
@@ -1792,13 +1794,6 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
         */
        th = (const struct tcphdr *)skb->data;
        hdrlen = th->doff * 4;
-       shinfo = skb_shinfo(skb);
-
-       if (!shinfo->gso_size)
-               shinfo->gso_size = skb->len - hdrlen;
-
-       if (!shinfo->gso_segs)
-               shinfo->gso_segs = 1;
 
        tail = sk->sk_backlog.tail;
        if (!tail)
@@ -1821,6 +1816,15 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
                goto no_coalesce;
 
        __skb_pull(skb, hdrlen);
+
+       shinfo = skb_shinfo(skb);
+       gso_size = shinfo->gso_size ?: skb->len;
+       gso_segs = shinfo->gso_segs ?: 1;
+
+       shinfo = skb_shinfo(tail);
+       tail_gso_size = shinfo->gso_size ?: (tail->len - hdrlen);
+       tail_gso_segs = shinfo->gso_segs ?: 1;
+
        if (skb_try_coalesce(tail, skb, &fragstolen, &delta)) {
                TCP_SKB_CB(tail)->end_seq = TCP_SKB_CB(skb)->end_seq;
 
@@ -1847,11 +1851,8 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
                }
 
                /* Not as strict as GRO. We only need to carry mss max value */
-               skb_shinfo(tail)->gso_size = max(shinfo->gso_size,
-                                                skb_shinfo(tail)->gso_size);
-
-               gso_segs = skb_shinfo(tail)->gso_segs + shinfo->gso_segs;
-               skb_shinfo(tail)->gso_segs = min_t(u32, gso_segs, 0xFFFF);
+               shinfo->gso_size = max(gso_size, tail_gso_size);
+               shinfo->gso_segs = min_t(u32, gso_segs + tail_gso_segs, 0xFFFF);
 
                sk->sk_backlog.len += delta;
                __NET_INC_STATS(sock_net(sk),
index f322e798a3519153472434a0a4a85449a2da20ce..ab458697881eda4503d6f223480deadf754d2d22 100644 (file)
@@ -4084,6 +4084,7 @@ void tcp_send_probe0(struct sock *sk)
                /* Cancel probe timer, if it is not required. */
                icsk->icsk_probes_out = 0;
                icsk->icsk_backoff = 0;
+               icsk->icsk_probes_tstamp = 0;
                return;
        }
 
index 6c62b9ea1320d9bbd26ed86b9f41de02fee6c491..faa92948441ba28a821034f18a6e4cc252da2c99 100644 (file)
@@ -219,14 +219,8 @@ static int tcp_write_timeout(struct sock *sk)
        int retry_until;
 
        if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
-               if (icsk->icsk_retransmits) {
-                       dst_negative_advice(sk);
-               } else {
-                       sk_rethink_txhash(sk);
-                       tp->timeout_rehash++;
-                       __NET_INC_STATS(sock_net(sk),
-                                       LINUX_MIB_TCPTIMEOUTREHASH);
-               }
+               if (icsk->icsk_retransmits)
+                       __dst_negative_advice(sk);
                retry_until = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries;
                expired = icsk->icsk_retransmits >= retry_until;
        } else {
@@ -234,12 +228,7 @@ static int tcp_write_timeout(struct sock *sk)
                        /* Black hole detection */
                        tcp_mtu_probing(icsk, sk);
 
-                       dst_negative_advice(sk);
-               } else {
-                       sk_rethink_txhash(sk);
-                       tp->timeout_rehash++;
-                       __NET_INC_STATS(sock_net(sk),
-                                       LINUX_MIB_TCPTIMEOUTREHASH);
+                       __dst_negative_advice(sk);
                }
 
                retry_until = net->ipv4.sysctl_tcp_retries2;
@@ -270,6 +259,11 @@ static int tcp_write_timeout(struct sock *sk)
                return 1;
        }
 
+       if (sk_rethink_txhash(sk)) {
+               tp->timeout_rehash++;
+               __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPTIMEOUTREHASH);
+       }
+
        return 0;
 }
 
@@ -349,6 +343,7 @@ static void tcp_probe_timer(struct sock *sk)
 
        if (tp->packets_out || !skb) {
                icsk->icsk_probes_out = 0;
+               icsk->icsk_probes_tstamp = 0;
                return;
        }
 
@@ -360,13 +355,12 @@ static void tcp_probe_timer(struct sock *sk)
         * corresponding system limit. We also implement similar policy when
         * we use RTO to probe window in tcp_retransmit_timer().
         */
-       if (icsk->icsk_user_timeout) {
-               u32 elapsed = tcp_model_timeout(sk, icsk->icsk_probes_out,
-                                               tcp_probe0_base(sk));
-
-               if (elapsed >= icsk->icsk_user_timeout)
-                       goto abort;
-       }
+       if (!icsk->icsk_probes_tstamp)
+               icsk->icsk_probes_tstamp = tcp_jiffies32;
+       else if (icsk->icsk_user_timeout &&
+                (s32)(tcp_jiffies32 - icsk->icsk_probes_tstamp) >=
+                msecs_to_jiffies(icsk->icsk_user_timeout))
+               goto abort;
 
        max_probes = sock_net(sk)->ipv4.sysctl_tcp_retries2;
        if (sock_flag(sk, SOCK_DEAD)) {
index 7103b0a89756e24203261684e88432615c344581..69ea76578abb95c613ef20f4fc0751e1ff81ac7b 100644 (file)
@@ -2555,7 +2555,8 @@ int udp_v4_early_demux(struct sk_buff *skb)
                 */
                if (!inet_sk(sk)->inet_daddr && in_dev)
                        return ip_mc_validate_source(skb, iph->daddr,
-                                                    iph->saddr, iph->tos,
+                                                    iph->saddr,
+                                                    iph->tos & IPTOS_RT_MASK,
                                                     skb->dev, in_dev, &itag);
        }
        return 0;
index eff2cacd52093962d17bb9798b21ed20d7b1a995..9edc5bb2d531aeffef448ef049ed8a745fe61544 100644 (file)
@@ -2467,8 +2467,9 @@ static void addrconf_add_mroute(struct net_device *dev)
                .fc_ifindex = dev->ifindex,
                .fc_dst_len = 8,
                .fc_flags = RTF_UP,
-               .fc_type = RTN_UNICAST,
+               .fc_type = RTN_MULTICAST,
                .fc_nlinfo.nl_net = dev_net(dev),
+               .fc_protocol = RTPROT_KERNEL,
        };
 
        ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0);
index 52c2f063529fbf9e33326eb6d3887f8c810b26eb..2b804fcebcc6511d32f18d99da596f9221e98551 100644 (file)
@@ -478,7 +478,6 @@ static int esp6_output_encap(struct xfrm_state *x, struct sk_buff *skb,
 int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
 {
        u8 *tail;
-       u8 *vaddr;
        int nfrags;
        int esph_offset;
        struct page *page;
@@ -519,14 +518,10 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
                        page = pfrag->page;
                        get_page(page);
 
-                       vaddr = kmap_atomic(page);
-
-                       tail = vaddr + pfrag->offset;
+                       tail = page_address(page) + pfrag->offset;
 
                        esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
 
-                       kunmap_atomic(vaddr);
-
                        nfrags = skb_shinfo(skb)->nr_frags;
 
                        __skb_fill_page_desc(skb, nfrags, page, pfrag->offset,
index 749ad72386b232183315d43ab12efc9b90e841f8..077d43af8226bd202be878885eaaf274776bf648 100644 (file)
@@ -125,8 +125,43 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
        return -EINVAL;
 }
 
+static int
+ip6_finish_output_gso_slowpath_drop(struct net *net, struct sock *sk,
+                                   struct sk_buff *skb, unsigned int mtu)
+{
+       struct sk_buff *segs, *nskb;
+       netdev_features_t features;
+       int ret = 0;
+
+       /* Please see corresponding comment in ip_finish_output_gso
+        * describing the cases where GSO segment length exceeds the
+        * egress MTU.
+        */
+       features = netif_skb_features(skb);
+       segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+       if (IS_ERR_OR_NULL(segs)) {
+               kfree_skb(skb);
+               return -ENOMEM;
+       }
+
+       consume_skb(skb);
+
+       skb_list_walk_safe(segs, segs, nskb) {
+               int err;
+
+               skb_mark_not_on_list(segs);
+               err = ip6_fragment(net, sk, segs, ip6_finish_output2);
+               if (err && ret == 0)
+                       ret = err;
+       }
+
+       return ret;
+}
+
 static int __ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       unsigned int mtu;
+
 #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
        /* Policy lookup after SNAT yielded a new policy */
        if (skb_dst(skb)->xfrm) {
@@ -135,7 +170,11 @@ static int __ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff
        }
 #endif
 
-       if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
+       mtu = ip6_skb_dst_mtu(skb);
+       if (skb_is_gso(skb) && !skb_gso_validate_network_len(skb, mtu))
+               return ip6_finish_output_gso_slowpath_drop(net, sk, skb, mtu);
+
+       if ((skb->len > mtu && !skb_is_gso(skb)) ||
            dst_allfrag(skb_dst(skb)) ||
            (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size))
                return ip6_fragment(net, sk, skb, ip6_finish_output2);
index 2da0ee70377959b1c87e23fae244ac79195ad997..93636867aee28dac0d166a4919ee26c77cb692a3 100644 (file)
@@ -1645,8 +1645,11 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev,
        }
 
 #ifdef CONFIG_IPV6_SIT_6RD
-       if (ipip6_netlink_6rd_parms(data, &ip6rd))
+       if (ipip6_netlink_6rd_parms(data, &ip6rd)) {
                err = ipip6_tunnel_update_6rd(nt, &ip6rd);
+               if (err < 0)
+                       unregister_netdevice_queue(dev, NULL);
+       }
 #endif
 
        return err;
index 48f144f107d536eb96d08f438ad21e5a9e3c8c1e..9e723d943421907abb6664bbdad92c9b416efde0 100644 (file)
@@ -120,18 +120,17 @@ static ssize_t aqm_write(struct file *file,
 {
        struct ieee80211_local *local = file->private_data;
        char buf[100];
-       size_t len;
 
-       if (count > sizeof(buf))
+       if (count >= sizeof(buf))
                return -EINVAL;
 
        if (copy_from_user(buf, user_buf, count))
                return -EFAULT;
 
-       buf[sizeof(buf) - 1] = '\0';
-       len = strlen(buf);
-       if (len > 0 && buf[len-1] == '\n')
-               buf[len-1] = 0;
+       if (count && buf[count - 1] == '\n')
+               buf[count - 1] = '\0';
+       else
+               buf[count] = '\0';
 
        if (sscanf(buf, "fq_limit %u", &local->fq.limit) == 1)
                return count;
@@ -177,18 +176,17 @@ static ssize_t airtime_flags_write(struct file *file,
 {
        struct ieee80211_local *local = file->private_data;
        char buf[16];
-       size_t len;
 
-       if (count > sizeof(buf))
+       if (count >= sizeof(buf))
                return -EINVAL;
 
        if (copy_from_user(buf, user_buf, count))
                return -EFAULT;
 
-       buf[sizeof(buf) - 1] = 0;
-       len = strlen(buf);
-       if (len > 0 && buf[len - 1] == '\n')
-               buf[len - 1] = 0;
+       if (count && buf[count - 1] == '\n')
+               buf[count - 1] = '\0';
+       else
+               buf[count] = '\0';
 
        if (kstrtou16(buf, 0, &local->airtime_flags))
                return -EINVAL;
@@ -237,20 +235,19 @@ static ssize_t aql_txq_limit_write(struct file *file,
 {
        struct ieee80211_local *local = file->private_data;
        char buf[100];
-       size_t len;
        u32 ac, q_limit_low, q_limit_high, q_limit_low_old, q_limit_high_old;
        struct sta_info *sta;
 
-       if (count > sizeof(buf))
+       if (count >= sizeof(buf))
                return -EINVAL;
 
        if (copy_from_user(buf, user_buf, count))
                return -EFAULT;
 
-       buf[sizeof(buf) - 1] = 0;
-       len = strlen(buf);
-       if (len > 0 && buf[len - 1] == '\n')
-               buf[len - 1] = 0;
+       if (count && buf[count - 1] == '\n')
+               buf[count - 1] = '\0';
+       else
+               buf[count] = '\0';
 
        if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
                return -EINVAL;
@@ -306,18 +303,17 @@ static ssize_t force_tx_status_write(struct file *file,
 {
        struct ieee80211_local *local = file->private_data;
        char buf[3];
-       size_t len;
 
-       if (count > sizeof(buf))
+       if (count >= sizeof(buf))
                return -EINVAL;
 
        if (copy_from_user(buf, user_buf, count))
                return -EFAULT;
 
-       buf[sizeof(buf) - 1] = '\0';
-       len = strlen(buf);
-       if (len > 0 && buf[len - 1] == '\n')
-               buf[len - 1] = 0;
+       if (count && buf[count - 1] == '\n')
+               buf[count - 1] = '\0';
+       else
+               buf[count] = '\0';
 
        if (buf[0] == '0' && buf[1] == '\0')
                local->force_tx_status = 0;
index 13b9bcc4865deb38644d15bbe0cdc4ee28f5bdd2..972895e9f22dc5e4b977087bba880f9a40fcdcdb 100644 (file)
@@ -4176,6 +4176,8 @@ void ieee80211_check_fast_rx(struct sta_info *sta)
 
        rcu_read_lock();
        key = rcu_dereference(sta->ptk[sta->ptk_idx]);
+       if (!key)
+               key = rcu_dereference(sdata->default_unicast_key);
        if (key) {
                switch (key->conf.cipher) {
                case WLAN_CIPHER_SUITE_TKIP:
index 6422da6690f795890286113c3e6a46fbe271d4d7..ebb3228ce9718fd52bb2e481874508397fea47d0 100644 (file)
@@ -649,7 +649,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
                if (!skip_hw && tx->key &&
                    tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
                        info->control.hw_key = &tx->key->conf;
-       } else if (!ieee80211_is_mgmt(hdr->frame_control) && tx->sta &&
+       } else if (ieee80211_is_data_present(hdr->frame_control) && tx->sta &&
                   test_sta_flag(tx->sta, WLAN_STA_USES_ENCRYPTION)) {
                return TX_DROP;
        }
@@ -3809,7 +3809,7 @@ void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
                 * get immediately moved to the back of the list on the next
                 * call to ieee80211_next_txq().
                 */
-               if (txqi->txq.sta &&
+               if (txqi->txq.sta && local->airtime_flags &&
                    wiphy_ext_feature_isset(local->hw.wiphy,
                                            NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
                        list_add(&txqi->schedule_order,
@@ -4251,7 +4251,6 @@ netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
        struct ethhdr *ehdr = (struct ethhdr *)skb->data;
        struct ieee80211_key *key;
        struct sta_info *sta;
-       bool offload = true;
 
        if (unlikely(skb->len < ETH_HLEN)) {
                kfree_skb(skb);
@@ -4267,18 +4266,22 @@ netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
 
        if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded ||
            !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
-               sdata->control_port_protocol == ehdr->h_proto))
-               offload = false;
-       else if ((key = rcu_dereference(sta->ptk[sta->ptk_idx])) &&
-                (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
-                 key->conf.cipher == WLAN_CIPHER_SUITE_TKIP))
-               offload = false;
-
-       if (offload)
-               ieee80211_8023_xmit(sdata, dev, sta, key, skb);
-       else
-               ieee80211_subif_start_xmit(skb, dev);
+           sdata->control_port_protocol == ehdr->h_proto))
+               goto skip_offload;
+
+       key = rcu_dereference(sta->ptk[sta->ptk_idx]);
+       if (!key)
+               key = rcu_dereference(sdata->default_unicast_key);
+
+       if (key && (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
+                   key->conf.cipher == WLAN_CIPHER_SUITE_TKIP))
+               goto skip_offload;
+
+       ieee80211_8023_xmit(sdata, dev, sta, key, skb);
+       goto out;
 
+skip_offload:
+       ieee80211_subif_start_xmit(skb, dev);
 out:
        rcu_read_unlock();
 
index 6628d8d742030736f7ede56fdfca1cc5b0b4f152..f998a077c7dd04a319c1de11cb37a07fdbb3eb88 100644 (file)
@@ -427,7 +427,7 @@ static bool mptcp_subflow_active(struct mptcp_subflow_context *subflow)
 static 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_SYN_SENT | TCPF_SYN_RECV | TCPF_TIME_WAIT | TCPF_CLOSE | TCPF_LISTEN));
 }
 
 static void mptcp_send_ack(struct mptcp_sock *msk)
@@ -2642,11 +2642,17 @@ static void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
 
 static int mptcp_disconnect(struct sock *sk, int flags)
 {
-       /* Should never be called.
-        * inet_stream_connect() calls ->disconnect, but that
-        * refers to the subflow socket, not the mptcp one.
-        */
-       WARN_ON_ONCE(1);
+       struct mptcp_subflow_context *subflow;
+       struct mptcp_sock *msk = mptcp_sk(sk);
+
+       __mptcp_flush_join_list(msk);
+       mptcp_for_each_subflow(msk, subflow) {
+               struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+
+               lock_sock(ssk);
+               tcp_disconnect(ssk, flags);
+               release_sock(ssk);
+       }
        return 0;
 }
 
@@ -3089,6 +3095,14 @@ bool mptcp_finish_join(struct sock *ssk)
        return true;
 }
 
+static void mptcp_shutdown(struct sock *sk, int how)
+{
+       pr_debug("sk=%p, how=%d", sk, how);
+
+       if ((how & SEND_SHUTDOWN) && mptcp_close_state(sk))
+               __mptcp_wr_shutdown(sk);
+}
+
 static struct proto mptcp_prot = {
        .name           = "MPTCP",
        .owner          = THIS_MODULE,
@@ -3098,7 +3112,7 @@ static struct proto mptcp_prot = {
        .accept         = mptcp_accept,
        .setsockopt     = mptcp_setsockopt,
        .getsockopt     = mptcp_getsockopt,
-       .shutdown       = tcp_shutdown,
+       .shutdown       = mptcp_shutdown,
        .destroy        = mptcp_destroy,
        .sendmsg        = mptcp_sendmsg,
        .recvmsg        = mptcp_recvmsg,
@@ -3344,43 +3358,6 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
        return mask;
 }
 
-static int mptcp_shutdown(struct socket *sock, int how)
-{
-       struct mptcp_sock *msk = mptcp_sk(sock->sk);
-       struct sock *sk = sock->sk;
-       int ret = 0;
-
-       pr_debug("sk=%p, how=%d", msk, how);
-
-       lock_sock(sk);
-
-       how++;
-       if ((how & ~SHUTDOWN_MASK) || !how) {
-               ret = -EINVAL;
-               goto out_unlock;
-       }
-
-       if (sock->state == SS_CONNECTING) {
-               if ((1 << sk->sk_state) &
-                   (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_CLOSE))
-                       sock->state = SS_DISCONNECTING;
-               else
-                       sock->state = SS_CONNECTED;
-       }
-
-       sk->sk_shutdown |= how;
-       if ((how & SEND_SHUTDOWN) && mptcp_close_state(sk))
-               __mptcp_wr_shutdown(sk);
-
-       /* Wake up anyone sleeping in poll. */
-       sk->sk_state_change(sk);
-
-out_unlock:
-       release_sock(sk);
-
-       return ret;
-}
-
 static const struct proto_ops mptcp_stream_ops = {
        .family            = PF_INET,
        .owner             = THIS_MODULE,
@@ -3394,7 +3371,7 @@ static const struct proto_ops mptcp_stream_ops = {
        .ioctl             = inet_ioctl,
        .gettstamp         = sock_gettstamp,
        .listen            = mptcp_listen,
-       .shutdown          = mptcp_shutdown,
+       .shutdown          = inet_shutdown,
        .setsockopt        = sock_common_setsockopt,
        .getsockopt        = sock_common_getsockopt,
        .sendmsg           = inet_sendmsg,
@@ -3444,7 +3421,7 @@ static const struct proto_ops mptcp_v6_stream_ops = {
        .ioctl             = inet6_ioctl,
        .gettstamp         = sock_gettstamp,
        .listen            = mptcp_listen,
-       .shutdown          = mptcp_shutdown,
+       .shutdown          = inet_shutdown,
        .setsockopt        = sock_common_setsockopt,
        .getsockopt        = sock_common_getsockopt,
        .sendmsg           = inet6_sendmsg,
index 46c5557c1fecfd56bc81c86b85ce1dac2c025f9a..0ee702d374b028df2cc8fdaa3fe1cbd1450819db 100644 (file)
@@ -523,6 +523,9 @@ nf_conntrack_hash_sysctl(struct ctl_table *table, int write,
 {
        int ret;
 
+       /* module_param hashsize could have changed value */
+       nf_conntrack_htable_size_user = nf_conntrack_htable_size;
+
        ret = proc_dointvec(table, write, buffer, lenp, ppos);
        if (ret < 0 || !write)
                return ret;
index ea923f8cf9c4258bf0288169a6ecac73f039c25c..b7c3c902290f1486a981c841317334320e01b82c 100644 (file)
@@ -1174,6 +1174,7 @@ static int __init nf_nat_init(void)
        ret = register_pernet_subsys(&nat_net_ops);
        if (ret < 0) {
                nf_ct_extend_unregister(&nat_extend);
+               kvfree(nf_nat_bysource);
                return ret;
        }
 
index e64727e1a72f9c2ffb830de8492b1e64d2d7963b..02a1f13f07980fd16bef7008a184c891369f3626 100644 (file)
@@ -508,7 +508,7 @@ static int nci_open_device(struct nci_dev *ndev)
                };
                unsigned long opt = 0;
 
-               if (!(ndev->nci_ver & NCI_VER_2_MASK))
+               if (ndev->nci_ver & NCI_VER_2_MASK)
                        opt = (unsigned long)&nci_init_v2_cmd;
 
                rc = __nci_request(ndev, nci_init_req, opt,
index 667c44aa5a63cb1abd90564ac67dccf094a3c0b2..dc201363f2c485fe12893a212829c45c91a99edd 100644 (file)
@@ -430,7 +430,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
                return;
        }
 
-       if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) {
+       if (state == RXRPC_CALL_SERVER_RECV_REQUEST) {
                unsigned long timo = READ_ONCE(call->next_req_timo);
                unsigned long now, expect_req_by;
 
index 9631aa8543b51e31ee9da5bb679b29cd39a401ec..8d2073e0e3da5deb0c207670052df280d45fbfd6 100644 (file)
@@ -598,7 +598,7 @@ static long rxrpc_read(const struct key *key,
                default: /* we have a ticket we can't encode */
                        pr_err("Unsupported key token type (%u)\n",
                               token->security_index);
-                       continue;
+                       return -ENOPKG;
                }
 
                _debug("token[%u]: toksize=%u", ntoks, toksize);
@@ -674,7 +674,9 @@ static long rxrpc_read(const struct key *key,
                        break;
 
                default:
-                       break;
+                       pr_err("Unsupported key token type (%u)\n",
+                              token->security_index);
+                       return -ENOPKG;
                }
 
                ASSERTCMP((unsigned long)xdr - (unsigned long)oldxdr, ==,
index 1319986693fc8826330e0a7dc49143d1d7518d64..84f932532db7dc39e23d946cd73e97ba042795a4 100644 (file)
@@ -1272,6 +1272,10 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key,
 
                nla_opt_msk = nla_data(tb[TCA_FLOWER_KEY_ENC_OPTS_MASK]);
                msk_depth = nla_len(tb[TCA_FLOWER_KEY_ENC_OPTS_MASK]);
+               if (!nla_ok(nla_opt_msk, msk_depth)) {
+                       NL_SET_ERR_MSG(extack, "Invalid nested attribute for masks");
+                       return -EINVAL;
+               }
        }
 
        nla_for_each_attr(nla_opt_key, nla_enc_key,
@@ -1307,9 +1311,6 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key,
                                NL_SET_ERR_MSG(extack, "Key and mask miss aligned");
                                return -EINVAL;
                        }
-
-                       if (msk_depth)
-                               nla_opt_msk = nla_next(nla_opt_msk, &msk_depth);
                        break;
                case TCA_FLOWER_KEY_ENC_OPTS_VXLAN:
                        if (key->enc_opts.dst_opt_type) {
@@ -1340,9 +1341,6 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key,
                                NL_SET_ERR_MSG(extack, "Key and mask miss aligned");
                                return -EINVAL;
                        }
-
-                       if (msk_depth)
-                               nla_opt_msk = nla_next(nla_opt_msk, &msk_depth);
                        break;
                case TCA_FLOWER_KEY_ENC_OPTS_ERSPAN:
                        if (key->enc_opts.dst_opt_type) {
@@ -1373,14 +1371,20 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key,
                                NL_SET_ERR_MSG(extack, "Key and mask miss aligned");
                                return -EINVAL;
                        }
-
-                       if (msk_depth)
-                               nla_opt_msk = nla_next(nla_opt_msk, &msk_depth);
                        break;
                default:
                        NL_SET_ERR_MSG(extack, "Unknown tunnel option type");
                        return -EINVAL;
                }
+
+               if (!msk_depth)
+                       continue;
+
+               if (!nla_ok(nla_opt_msk, msk_depth)) {
+                       NL_SET_ERR_MSG(extack, "A mask attribute is invalid");
+                       return -EINVAL;
+               }
+               nla_opt_msk = nla_next(nla_opt_msk, &msk_depth);
        }
 
        return 0;
index 78bec347b8b66f660e620dd715d0eb68f9bcd2d3..c4007b9cd16d6a200d943e3e0536d6b20022ba77 100644 (file)
@@ -366,9 +366,13 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        if (tb[TCA_TCINDEX_MASK])
                cp->mask = nla_get_u16(tb[TCA_TCINDEX_MASK]);
 
-       if (tb[TCA_TCINDEX_SHIFT])
+       if (tb[TCA_TCINDEX_SHIFT]) {
                cp->shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]);
-
+               if (cp->shift > 16) {
+                       err = -EINVAL;
+                       goto errout;
+               }
+       }
        if (!cp->hash) {
                /* Hash not specified, use perfect hash if the upper limit
                 * of the hashing index is below the threshold.
index 51cb553e4317a3e2bca1996e0df004aab8111d58..6fe4e5cc807c90b046a16f014df43bfe841cbc43 100644 (file)
@@ -412,7 +412,8 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
 {
        struct qdisc_rate_table *rtab;
 
-       if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
+       if (tab == NULL || r->rate == 0 ||
+           r->cell_log == 0 || r->cell_log >= 32 ||
            nla_len(tab) != TC_RTAB_SIZE) {
                NL_SET_ERR_MSG(extack, "Invalid rate table parameters for searching");
                return NULL;
index 59342b519e347cdca6681b80ab65ef22121d60c6..0df85a12651e96e87c97031316cd94585456cc08 100644 (file)
@@ -246,7 +246,8 @@ int smc_nl_get_sys_info(struct sk_buff *skb, struct netlink_callback *cb)
                goto errattr;
        smc_clc_get_hostname(&host);
        if (host) {
-               snprintf(hostname, sizeof(hostname), "%s", host);
+               memcpy(hostname, host, SMC_MAX_HOSTNAME_LEN);
+               hostname[SMC_MAX_HOSTNAME_LEN] = 0;
                if (nla_put_string(skb, SMC_NLA_SYS_LOCAL_HOST, hostname))
                        goto errattr;
        }
@@ -257,7 +258,8 @@ int smc_nl_get_sys_info(struct sk_buff *skb, struct netlink_callback *cb)
                smc_ism_get_system_eid(smcd_dev, &seid);
        mutex_unlock(&smcd_dev_list.mutex);
        if (seid && smc_ism_is_v2_capable()) {
-               snprintf(smc_seid, sizeof(smc_seid), "%s", seid);
+               memcpy(smc_seid, seid, SMC_MAX_EID_LEN);
+               smc_seid[SMC_MAX_EID_LEN] = 0;
                if (nla_put_string(skb, SMC_NLA_SYS_SEID, smc_seid))
                        goto errattr;
        }
@@ -295,7 +297,8 @@ static int smc_nl_fill_lgr(struct smc_link_group *lgr,
                goto errattr;
        if (nla_put_u8(skb, SMC_NLA_LGR_R_VLAN_ID, lgr->vlan_id))
                goto errattr;
-       snprintf(smc_target, sizeof(smc_target), "%s", lgr->pnet_id);
+       memcpy(smc_target, lgr->pnet_id, SMC_MAX_PNETID_LEN);
+       smc_target[SMC_MAX_PNETID_LEN] = 0;
        if (nla_put_string(skb, SMC_NLA_LGR_R_PNETID, smc_target))
                goto errattr;
 
@@ -312,7 +315,7 @@ static int smc_nl_fill_lgr_link(struct smc_link_group *lgr,
                                struct sk_buff *skb,
                                struct netlink_callback *cb)
 {
-       char smc_ibname[IB_DEVICE_NAME_MAX + 1];
+       char smc_ibname[IB_DEVICE_NAME_MAX];
        u8 smc_gid_target[41];
        struct nlattr *attrs;
        u32 link_uid = 0;
@@ -461,7 +464,8 @@ static int smc_nl_fill_smcd_lgr(struct smc_link_group *lgr,
                goto errattr;
        if (nla_put_u32(skb, SMC_NLA_LGR_D_CHID, smc_ism_get_chid(lgr->smcd)))
                goto errattr;
-       snprintf(smc_pnet, sizeof(smc_pnet), "%s", lgr->smcd->pnetid);
+       memcpy(smc_pnet, lgr->smcd->pnetid, SMC_MAX_PNETID_LEN);
+       smc_pnet[SMC_MAX_PNETID_LEN] = 0;
        if (nla_put_string(skb, SMC_NLA_LGR_D_PNETID, smc_pnet))
                goto errattr;
 
@@ -474,10 +478,12 @@ static int smc_nl_fill_smcd_lgr(struct smc_link_group *lgr,
                goto errv2attr;
        if (nla_put_u8(skb, SMC_NLA_LGR_V2_OS, lgr->peer_os))
                goto errv2attr;
-       snprintf(smc_host, sizeof(smc_host), "%s", lgr->peer_hostname);
+       memcpy(smc_host, lgr->peer_hostname, SMC_MAX_HOSTNAME_LEN);
+       smc_host[SMC_MAX_HOSTNAME_LEN] = 0;
        if (nla_put_string(skb, SMC_NLA_LGR_V2_PEER_HOST, smc_host))
                goto errv2attr;
-       snprintf(smc_eid, sizeof(smc_eid), "%s", lgr->negotiated_eid);
+       memcpy(smc_eid, lgr->negotiated_eid, SMC_MAX_EID_LEN);
+       smc_eid[SMC_MAX_EID_LEN] = 0;
        if (nla_put_string(skb, SMC_NLA_LGR_V2_NEG_EID, smc_eid))
                goto errv2attr;
 
index ddd7fac98b1d6558a5968d5e4a50e899d5492674..7d7ba0320d5aefc539838c0bf13e365e181d43a7 100644 (file)
@@ -371,8 +371,8 @@ static int smc_nl_handle_dev_port(struct sk_buff *skb,
        if (nla_put_u8(skb, SMC_NLA_DEV_PORT_PNET_USR,
                       smcibdev->pnetid_by_user[port]))
                goto errattr;
-       snprintf(smc_pnet, sizeof(smc_pnet), "%s",
-                (char *)&smcibdev->pnetid[port]);
+       memcpy(smc_pnet, &smcibdev->pnetid[port], SMC_MAX_PNETID_LEN);
+       smc_pnet[SMC_MAX_PNETID_LEN] = 0;
        if (nla_put_string(skb, SMC_NLA_DEV_PORT_PNETID, smc_pnet))
                goto errattr;
        if (nla_put_u32(skb, SMC_NLA_DEV_PORT_NETDEV,
@@ -414,7 +414,7 @@ static int smc_nl_handle_smcr_dev(struct smc_ib_device *smcibdev,
                                  struct sk_buff *skb,
                                  struct netlink_callback *cb)
 {
-       char smc_ibname[IB_DEVICE_NAME_MAX + 1];
+       char smc_ibname[IB_DEVICE_NAME_MAX];
        struct smc_pci_dev smc_pci_dev;
        struct pci_dev *pci_dev;
        unsigned char is_crit;
index 524ef64a191a5b31788c2750fbcb58876ee77874..9c6e95882553eb97374e3d080b581308bba91a89 100644 (file)
@@ -250,7 +250,8 @@ static int smc_nl_handle_smcd_dev(struct smcd_dev *smcd,
                goto errattr;
        if (nla_put_u8(skb, SMC_NLA_DEV_PORT_PNET_USR, smcd->pnetid_by_user))
                goto errportattr;
-       snprintf(smc_pnet, sizeof(smc_pnet), "%s", smcd->pnetid);
+       memcpy(smc_pnet, smcd->pnetid, SMC_MAX_PNETID_LEN);
+       smc_pnet[SMC_MAX_PNETID_LEN] = 0;
        if (nla_put_string(skb, SMC_NLA_DEV_PORT_PNETID, smc_pnet))
                goto errportattr;
 
index 010dcb876f9d72dc85b5e4ff327e927999b7d242..6e4dbd577a39fa701460ade9cd1fde4563b63057 100644 (file)
@@ -185,7 +185,7 @@ static int rpc_parse_scope_id(struct net *net, const char *buf,
                        scope_id = dev->ifindex;
                        dev_put(dev);
                } else {
-                       if (kstrtou32(p, 10, &scope_id) == 0) {
+                       if (kstrtou32(p, 10, &scope_id) != 0) {
                                kfree(p);
                                return 0;
                        }
index 5fb9164aa69059f77158a9f6ec796381474641ae..dcc50ae545506f39d04908f6168c36ddda350f6f 100644 (file)
@@ -857,6 +857,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
        err = -EAGAIN;
        if (len <= 0)
                goto out_release;
+       trace_svc_xdr_recvfrom(&rqstp->rq_arg);
 
        clear_bit(XPT_OLD, &xprt->xpt_flags);
 
@@ -866,7 +867,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
 
        if (serv->sv_stats)
                serv->sv_stats->netcnt++;
-       trace_svc_xdr_recvfrom(rqstp, &rqstp->rq_arg);
        return len;
 out_release:
        rqstp->rq_res.len = 0;
@@ -904,7 +904,7 @@ int svc_send(struct svc_rqst *rqstp)
        xb->len = xb->head[0].iov_len +
                xb->page_len +
                xb->tail[0].iov_len;
-       trace_svc_xdr_sendto(rqstp, xb);
+       trace_svc_xdr_sendto(rqstp->rq_xid, xb);
        trace_svc_stats_latency(rqstp);
 
        len = xprt->xpt_ops->xpo_sendto(rqstp);
index b248f2349437da03e1d2e7e5f4d44886779eef90..c9766d07eb81a1cdee4cad8bfc4a393114543e6f 100644 (file)
@@ -1062,6 +1062,90 @@ err_noclose:
        return 0;       /* record not complete */
 }
 
+static int svc_tcp_send_kvec(struct socket *sock, const struct kvec *vec,
+                             int flags)
+{
+       return kernel_sendpage(sock, virt_to_page(vec->iov_base),
+                              offset_in_page(vec->iov_base),
+                              vec->iov_len, flags);
+}
+
+/*
+ * kernel_sendpage() is used exclusively to reduce the number of
+ * copy operations in this path. Therefore the caller must ensure
+ * that the pages backing @xdr are unchanging.
+ *
+ * In addition, the logic assumes that * .bv_len is never larger
+ * than PAGE_SIZE.
+ */
+static int svc_tcp_sendmsg(struct socket *sock, struct msghdr *msg,
+                          struct xdr_buf *xdr, rpc_fraghdr marker,
+                          unsigned int *sentp)
+{
+       const struct kvec *head = xdr->head;
+       const struct kvec *tail = xdr->tail;
+       struct kvec rm = {
+               .iov_base       = &marker,
+               .iov_len        = sizeof(marker),
+       };
+       int flags, ret;
+
+       *sentp = 0;
+       xdr_alloc_bvec(xdr, GFP_KERNEL);
+
+       msg->msg_flags = MSG_MORE;
+       ret = kernel_sendmsg(sock, msg, &rm, 1, rm.iov_len);
+       if (ret < 0)
+               return ret;
+       *sentp += ret;
+       if (ret != rm.iov_len)
+               return -EAGAIN;
+
+       flags = head->iov_len < xdr->len ? MSG_MORE | MSG_SENDPAGE_NOTLAST : 0;
+       ret = svc_tcp_send_kvec(sock, head, flags);
+       if (ret < 0)
+               return ret;
+       *sentp += ret;
+       if (ret != head->iov_len)
+               goto out;
+
+       if (xdr->page_len) {
+               unsigned int offset, len, remaining;
+               struct bio_vec *bvec;
+
+               bvec = xdr->bvec;
+               offset = xdr->page_base;
+               remaining = xdr->page_len;
+               flags = MSG_MORE | MSG_SENDPAGE_NOTLAST;
+               while (remaining > 0) {
+                       if (remaining <= PAGE_SIZE && tail->iov_len == 0)
+                               flags = 0;
+                       len = min(remaining, bvec->bv_len);
+                       ret = kernel_sendpage(sock, bvec->bv_page,
+                                             bvec->bv_offset + offset,
+                                             len, flags);
+                       if (ret < 0)
+                               return ret;
+                       *sentp += ret;
+                       if (ret != len)
+                               goto out;
+                       remaining -= len;
+                       offset = 0;
+                       bvec++;
+               }
+       }
+
+       if (tail->iov_len) {
+               ret = svc_tcp_send_kvec(sock, tail, 0);
+               if (ret < 0)
+                       return ret;
+               *sentp += ret;
+       }
+
+out:
+       return 0;
+}
+
 /**
  * svc_tcp_sendto - Send out a reply on a TCP socket
  * @rqstp: completed svc_rqst
@@ -1089,7 +1173,7 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp)
        mutex_lock(&xprt->xpt_mutex);
        if (svc_xprt_is_dead(xprt))
                goto out_notconn;
-       err = xprt_sock_sendmsg(svsk->sk_sock, &msg, xdr, 0, marker, &sent);
+       err = svc_tcp_sendmsg(svsk->sk_sock, &msg, xdr, marker, &sent);
        xdr_free_bvec(xdr);
        trace_svcsock_tcp_send(xprt, err < 0 ? err : sent);
        if (err < 0 || sent != (xdr->len + sizeof(marker)))
index 6ae2140eb4f7498f262bcb722f5d365188b20794..11510925943020b96436ab3a371f7e9e2a100dfe 100644 (file)
@@ -1030,7 +1030,6 @@ void tipc_link_reset(struct tipc_link *l)
 int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
                   struct sk_buff_head *xmitq)
 {
-       struct tipc_msg *hdr = buf_msg(skb_peek(list));
        struct sk_buff_head *backlogq = &l->backlogq;
        struct sk_buff_head *transmq = &l->transmq;
        struct sk_buff *skb, *_skb;
@@ -1038,13 +1037,18 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
        u16 ack = l->rcv_nxt - 1;
        u16 seqno = l->snd_nxt;
        int pkt_cnt = skb_queue_len(list);
-       int imp = msg_importance(hdr);
        unsigned int mss = tipc_link_mss(l);
        unsigned int cwin = l->window;
        unsigned int mtu = l->mtu;
+       struct tipc_msg *hdr;
        bool new_bundle;
        int rc = 0;
+       int imp;
+
+       if (pkt_cnt <= 0)
+               return 0;
 
+       hdr = buf_msg(skb_peek(list));
        if (unlikely(msg_size(hdr) > mtu)) {
                pr_warn("Too large msg, purging xmit list %d %d %d %d %d!\n",
                        skb_queue_len(list), msg_user(hdr),
@@ -1053,6 +1057,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
                return -EMSGSIZE;
        }
 
+       imp = msg_importance(hdr);
        /* Allow oversubscription of one data msg per source at congestion */
        if (unlikely(l->backlog[imp].len >= l->backlog[imp].limit)) {
                if (imp == TIPC_SYSTEM_IMPORTANCE) {
@@ -2539,7 +2544,7 @@ void tipc_link_set_queue_limits(struct tipc_link *l, u32 min_win, u32 max_win)
 }
 
 /**
- * link_reset_stats - reset link statistics
+ * tipc_link_reset_stats - reset link statistics
  * @l: pointer to link
  */
 void tipc_link_reset_stats(struct tipc_link *l)
index 83d9eb8305928d9bb1f8523a503b13c77546c2c1..008670d1f43e1c2e9153a706cc18cc8e8ba62a6c 100644 (file)
@@ -1665,7 +1665,7 @@ static void tipc_lxc_xmit(struct net *peer_net, struct sk_buff_head *list)
 }
 
 /**
- * tipc_node_xmit() is the general link level function for message sending
+ * tipc_node_xmit() - general link level function for message sending
  * @net: the applicable net namespace
  * @list: chain of buffers containing message
  * @dnode: address of destination node
index bb72447ad960271ab1aaec43867202763f8bc6f6..8114bba8556c72a1ed173cb7c29232ed9dbdf7a0 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright      2017  Intel Deutschland GmbH
- * Copyright (C) 2018 - 2019 Intel Corporation
+ * Copyright (C) 2018 - 2021 Intel Corporation
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -139,6 +139,11 @@ static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
        return rcu_dereference_rtnl(cfg80211_regdomain);
 }
 
+/*
+ * Returns the regulatory domain associated with the wiphy.
+ *
+ * Requires either RTNL or RCU protection
+ */
 const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
 {
        return rcu_dereference_rtnl(wiphy->regd);
@@ -2571,9 +2576,13 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
        if (IS_ERR(new_regd))
                return;
 
+       rtnl_lock();
+
        tmp = get_wiphy_regdom(wiphy);
        rcu_assign_pointer(wiphy->regd, new_regd);
        rcu_free_regdom(tmp);
+
+       rtnl_unlock();
 }
 EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
 
index 8037b04a9edd11cad8845d95a06b2d442c29f8f5..4a83117507f5a867412e350b27577a7832e16c22 100644 (file)
@@ -108,9 +108,9 @@ EXPORT_SYMBOL(xsk_get_pool_from_qid);
 
 void xsk_clear_pool_at_qid(struct net_device *dev, u16 queue_id)
 {
-       if (queue_id < dev->real_num_rx_queues)
+       if (queue_id < dev->num_rx_queues)
                dev->_rx[queue_id].pool = NULL;
-       if (queue_id < dev->real_num_tx_queues)
+       if (queue_id < dev->num_tx_queues)
                dev->_tx[queue_id].pool = NULL;
 }
 
index 7d8026f3f377256292b5b7bd133d865b37f4b5a3..a0cd28cd31a852c50ca7f2500f64d91f6b60f53b 100644 (file)
@@ -275,7 +275,9 @@ static void dump_common_audit_data(struct audit_buffer *ab,
                struct inode *inode;
 
                audit_log_format(ab, " name=");
+               spin_lock(&a->u.dentry->d_lock);
                audit_log_untrustedstring(ab, a->u.dentry->d_name.name);
+               spin_unlock(&a->u.dentry->d_lock);
 
                inode = d_backing_inode(a->u.dentry);
                if (inode) {
@@ -293,8 +295,9 @@ static void dump_common_audit_data(struct audit_buffer *ab,
                dentry = d_find_alias(inode);
                if (dentry) {
                        audit_log_format(ab, " name=");
-                       audit_log_untrustedstring(ab,
-                                        dentry->d_name.name);
+                       spin_lock(&dentry->d_lock);
+                       audit_log_untrustedstring(ab, dentry->d_name.name);
+                       spin_unlock(&dentry->d_lock);
                        dput(dentry);
                }
                audit_log_format(ab, " dev=");
index 11554d0412f06f0d77b6cbe82a77ea051cb36eaf..1b8409ec2c97f69460441bc3fcdd6b700ca820d4 100644 (file)
@@ -611,7 +611,8 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
 
        if (info->is_midi) {
                struct midi_info minf;
-               snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf);
+               if (snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf))
+                       return -ENXIO;
                inf->synth_type = SYNTH_TYPE_MIDI;
                inf->synth_subtype = 0;
                inf->nr_voices = 16;
index 7f82762ccc8c80ba791894c4add0a66ca718947e..ee7122c461d46f442cfdea976c337b97ac640bba 100644 (file)
@@ -88,7 +88,7 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port)
 
        /* Set interval to next transaction. */
        ff->next_ktime[port] = ktime_add_ns(ktime_get(),
-                               ff->rx_bytes[port] * 8 * NSEC_PER_SEC / 31250);
+                       ff->rx_bytes[port] * 8 * (NSEC_PER_SEC / 31250));
 
        if (quad_count == 1)
                tcode = TCODE_WRITE_QUADLET_REQUEST;
index 90288b4b46379526527d953ee7a9ca9f2fe9eb3e..a073cece4a7d5e3aa2a45c1d5d148eb940cf67ae 100644 (file)
@@ -209,7 +209,7 @@ static void midi_port_work(struct work_struct *work)
 
        /* Set interval to next transaction. */
        port->next_ktime = ktime_add_ns(ktime_get(),
-                               port->consume_bytes * 8 * NSEC_PER_SEC / 31250);
+                       port->consume_bytes * 8 * (NSEC_PER_SEC / 31250));
 
        /* Start this transaction. */
        port->idling = false;
index 687216e7452675e9fc9d9d888d7aa8ead2ba961b..eec1775dfffe9fc57278f75669337e5d703c28c5 100644 (file)
@@ -2934,7 +2934,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
        snd_hdac_leave_pm(&codec->core);
 }
 
-static int hda_codec_suspend(struct device *dev)
+static int hda_codec_runtime_suspend(struct device *dev)
 {
        struct hda_codec *codec = dev_to_hda_codec(dev);
        unsigned int state;
@@ -2953,7 +2953,7 @@ static int hda_codec_suspend(struct device *dev)
        return 0;
 }
 
-static int hda_codec_resume(struct device *dev)
+static int hda_codec_runtime_resume(struct device *dev)
 {
        struct hda_codec *codec = dev_to_hda_codec(dev);
 
@@ -2968,16 +2968,6 @@ static int hda_codec_resume(struct device *dev)
        return 0;
 }
 
-static int hda_codec_runtime_suspend(struct device *dev)
-{
-       return hda_codec_suspend(dev);
-}
-
-static int hda_codec_runtime_resume(struct device *dev)
-{
-       return hda_codec_resume(dev);
-}
-
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_PM_SLEEP
@@ -2998,31 +2988,31 @@ static void hda_codec_pm_complete(struct device *dev)
 static int hda_codec_pm_suspend(struct device *dev)
 {
        dev->power.power_state = PMSG_SUSPEND;
-       return hda_codec_suspend(dev);
+       return pm_runtime_force_suspend(dev);
 }
 
 static int hda_codec_pm_resume(struct device *dev)
 {
        dev->power.power_state = PMSG_RESUME;
-       return hda_codec_resume(dev);
+       return pm_runtime_force_resume(dev);
 }
 
 static int hda_codec_pm_freeze(struct device *dev)
 {
        dev->power.power_state = PMSG_FREEZE;
-       return hda_codec_suspend(dev);
+       return pm_runtime_force_suspend(dev);
 }
 
 static int hda_codec_pm_thaw(struct device *dev)
 {
        dev->power.power_state = PMSG_THAW;
-       return hda_codec_resume(dev);
+       return pm_runtime_force_resume(dev);
 }
 
 static int hda_codec_pm_restore(struct device *dev)
 {
        dev->power.power_state = PMSG_RESTORE;
-       return hda_codec_resume(dev);
+       return pm_runtime_force_resume(dev);
 }
 #endif /* CONFIG_PM_SLEEP */
 
index 770ad25f1907cdec5d0c86822af92fb74c3ff465..5a50d3a46445931afe6b859eb7f5301a4b6864d5 100644 (file)
@@ -2484,6 +2484,9 @@ static const struct pci_device_id azx_ids[] = {
        /* CometLake-S */
        { PCI_DEVICE(0x8086, 0xa3f0),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       /* CometLake-R */
+       { PCI_DEVICE(0x8086, 0xf0c8),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Icelake */
        { PCI_DEVICE(0x8086, 0x34c8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
@@ -2507,6 +2510,9 @@ static const struct pci_device_id azx_ids[] = {
        /* Alderlake-S */
        { PCI_DEVICE(0x8086, 0x7ad0),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       /* Alderlake-P */
+       { PCI_DEVICE(0x8086, 0x51c8),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Elkhart Lake */
        { PCI_DEVICE(0x8086, 0x4b55),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
@@ -2598,7 +2604,8 @@ static const struct pci_device_id azx_ids[] = {
          .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
        /* ATI HDMI */
        { PCI_DEVICE(0x1002, 0x0002),
-         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
        { PCI_DEVICE(0x1002, 0x1308),
          .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
        { PCI_DEVICE(0x1002, 0x157a),
@@ -2660,9 +2667,11 @@ static const struct pci_device_id azx_ids[] = {
        { PCI_DEVICE(0x1002, 0xaab0),
          .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
        { PCI_DEVICE(0x1002, 0xaac0),
-         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
        { PCI_DEVICE(0x1002, 0xaac8),
-         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
        { PCI_DEVICE(0x1002, 0xaad8),
          .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
          AZX_DCAPS_PM_RUNTIME },
index 70164d1428d404661120da07b4f1baf3b0185df5..361cf2041911ad754970b9ee0f3a48cfedbd97e9 100644 (file)
@@ -388,7 +388,7 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
         * in powers of 2, next available ratio is 16 which can be
         * used as a limiting factor here.
         */
-       if (of_device_is_compatible(np, "nvidia,tegra194-hda"))
+       if (of_device_is_compatible(np, "nvidia,tegra30-hda"))
                chip->bus.core.sdo_limit = 16;
 
        /* codec detection */
index 74d246a0dc6de2cedfa8f24ccb9d8378d7e3bf84..97adff0cbcab4bfcec1934a264941ca4d584710a 100644 (file)
@@ -4346,6 +4346,7 @@ HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI",       patch_i915_icl_hdmi),
 HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI",  patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI",        patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI",  patch_i915_tgl_hdmi),
+HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi),
 HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI",        patch_i915_icl_hdmi),
index 3c1d2a3fb1a4fd74b7f7189a96a09a8287d832b1..ed5b6b894dc1941c5d6ca0426b9e24d6ab78889e 100644 (file)
@@ -6371,6 +6371,7 @@ enum {
        ALC256_FIXUP_HP_HEADSET_MIC,
        ALC236_FIXUP_DELL_AIO_HEADSET_MIC,
        ALC282_FIXUP_ACER_DISABLE_LINEOUT,
+       ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -7808,6 +7809,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_HEADSET_MODE
        },
+       [ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc269_fixup_limit_int_mic_boost,
+               .chained = true,
+               .chain_id = ALC255_FIXUP_ACER_MIC_NO_PRESENCE,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -7826,6 +7833,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x1065, "Acer Aspire C20-820", ALC269VC_FIXUP_ACER_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
+       SND_PCI_QUIRK(0x1025, 0x1094, "Acer Aspire E5-575T", ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1025, 0x1099, "Acer Aspire E5-523G", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x110e, "Acer Aspire ES1-432", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x1166, "Acer Veriton N4640G", ALC269_FIXUP_LIFEBOOK),
@@ -7970,6 +7978,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED),
+       SND_PCI_QUIRK(0x103c, 0x8780, "HP ZBook Fury 17 G7 Mobile Workstation",
+                     ALC285_FIXUP_HP_GPIO_AMP_INIT),
+       SND_PCI_QUIRK(0x103c, 0x8783, "HP ZBook Fury 15 G7 Mobile Workstation",
+                     ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
index 0ab40a8a68fb50d3033cfc8306e44a18803e7841..834367dd54e1b651c8bc34588cb84224d2919b8d 100644 (file)
@@ -113,6 +113,7 @@ static struct via_spec *via_new_spec(struct hda_codec *codec)
                spec->codec_type = VT1708S;
        spec->gen.indep_hp = 1;
        spec->gen.keep_eapd_on = 1;
+       spec->gen.dac_min_mute = 1;
        spec->gen.pcm_playback_hook = via_playback_pcm_hook;
        spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
        codec->power_save_node = 1;
index 8c138e490f0c54fb20bb6800447eae53640c2802..d3536fd6a12400644a4cfa5b26795956fd2cedb3 100644 (file)
@@ -140,21 +140,14 @@ static int snd_acp3x_probe(struct pci_dev *pci,
                goto release_regions;
        }
 
-       /* check for msi interrupt support */
-       ret = pci_enable_msi(pci);
-       if (ret)
-               /* msi is not enabled */
-               irqflags = IRQF_SHARED;
-       else
-               /* msi is enabled */
-               irqflags = 0;
+       irqflags = IRQF_SHARED;
 
        addr = pci_resource_start(pci, 0);
        adata->acp3x_base = devm_ioremap(&pci->dev, addr,
                                        pci_resource_len(pci, 0));
        if (!adata->acp3x_base) {
                ret = -ENOMEM;
-               goto disable_msi;
+               goto release_regions;
        }
        pci_set_master(pci);
        pci_set_drvdata(pci, adata);
@@ -162,7 +155,7 @@ static int snd_acp3x_probe(struct pci_dev *pci,
        adata->pme_en = rv_readl(adata->acp3x_base + mmACP_PME_EN);
        ret = acp3x_init(adata);
        if (ret)
-               goto disable_msi;
+               goto release_regions;
 
        val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
        switch (val) {
@@ -251,8 +244,6 @@ unregister_devs:
 de_init:
        if (acp3x_deinit(adata->acp3x_base))
                dev_err(&pci->dev, "ACP de-init failed\n");
-disable_msi:
-       pci_disable_msi(pci);
 release_regions:
        pci_release_regions(pci);
 disable_pci:
@@ -311,7 +302,6 @@ static void snd_acp3x_remove(struct pci_dev *pci)
                dev_err(&pci->dev, "ACP de-init failed\n");
        pm_runtime_forbid(&pci->dev);
        pm_runtime_get_noresume(&pci->dev);
-       pci_disable_msi(pci);
        pci_release_regions(pci);
        pci_disable_device(pci);
 }
index fa169bf09886fd046fef231230975e1aad11f461..deca8c7a0e8784b82458bc9b5d9d0d12adbd58e7 100644 (file)
@@ -171,6 +171,20 @@ static const struct dmi_system_id rn_acp_quirk_table[] = {
                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "LNVNB161216"),
                }
        },
+       {
+               /* Lenovo ThinkPad E14 Gen 2 */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_EXACT_MATCH(DMI_BOARD_NAME, "20T6CTO1WW"),
+               }
+       },
+       {
+               /* Lenovo ThinkPad X395 */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_EXACT_MATCH(DMI_BOARD_NAME, "20NLCTO1WW"),
+               }
+       },
        {}
 };
 
index 142373ec411adb31ed33f5a7cf0a321c72c91de8..9fe9471f4514dc61ebf97678930fe48b7b184372 100644 (file)
@@ -143,7 +143,7 @@ config SND_MCHP_SOC_SPDIFTX
          - sama7g5
 
          This S/PDIF TX driver is compliant with IEC-60958 standard and
-         includes programable User Data and Channel Status fields.
+         includes programmable User Data and Channel Status fields.
 
 config SND_MCHP_SOC_SPDIFRX
        tristate "Microchip ASoC driver for boards using S/PDIF RX"
@@ -157,5 +157,5 @@ config SND_MCHP_SOC_SPDIFRX
          - sama7g5
 
          This S/PDIF RX driver is compliant with IEC-60958 standard and
-         includes programable User Data and Channel Status fields.
+         includes programmable User Data and Channel Status fields.
 endif
index ba4eb54aafcb9f4e181d9692fe331863537b6bc3..9bf6bfdaf11e4e6fc8f30403700855a9f38f46bd 100644 (file)
@@ -457,7 +457,7 @@ config SND_SOC_ADAU7118_HW
        help
          Enable support for the Analog Devices ADAU7118 8 Channel PDM-to-I2S/TDM
          Converter. In this mode, the device works in standalone mode which
-         means that there is no bus to comunicate with it. Stereo mode is not
+         means that there is no bus to communicate with it. Stereo mode is not
          supported in this mode.
 
          To compile this driver as a module, choose M here: the module
index d5fcc4db8284afccb24778ba76a323c73068388f..0f3ac22f2cf8ee124281e1b5247be38604f0d30a 100644 (file)
@@ -717,7 +717,7 @@ static int hdmi_codec_set_jack(struct snd_soc_component *component,
                               void *data)
 {
        struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
-       int ret = -EOPNOTSUPP;
+       int ret = -ENOTSUPP;
 
        if (hcp->hcd.ops->hook_plugged_cb) {
                hcp->jack = jack;
index 92921e34f9486708242b60d6dfd02828c3c8f834..85f6865019d4a82d9ac924294c32452c86f8d028 100644 (file)
 #include <sound/tlv.h>
 #include "max98373.h"
 
+static const u32 max98373_i2c_cache_reg[] = {
+       MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK,
+       MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK,
+       MAX98373_R20B6_BDE_CUR_STATE_READBACK,
+};
+
 static struct reg_default max98373_reg[] = {
        {MAX98373_R2000_SW_RESET, 0x00},
        {MAX98373_R2001_INT_RAW1, 0x00},
@@ -472,6 +478,11 @@ static struct snd_soc_dai_driver max98373_dai[] = {
 static int max98373_suspend(struct device *dev)
 {
        struct max98373_priv *max98373 = dev_get_drvdata(dev);
+       int i;
+
+       /* cache feedback register values before suspend */
+       for (i = 0; i < max98373->cache_num; i++)
+               regmap_read(max98373->regmap, max98373->cache[i].reg, &max98373->cache[i].val);
 
        regcache_cache_only(max98373->regmap, true);
        regcache_mark_dirty(max98373->regmap);
@@ -509,6 +520,7 @@ static int max98373_i2c_probe(struct i2c_client *i2c,
 {
        int ret = 0;
        int reg = 0;
+       int i;
        struct max98373_priv *max98373 = NULL;
 
        max98373 = devm_kzalloc(&i2c->dev, sizeof(*max98373), GFP_KERNEL);
@@ -534,6 +546,14 @@ static int max98373_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
+       max98373->cache_num = ARRAY_SIZE(max98373_i2c_cache_reg);
+       max98373->cache = devm_kcalloc(&i2c->dev, max98373->cache_num,
+                                      sizeof(*max98373->cache),
+                                      GFP_KERNEL);
+
+       for (i = 0; i < max98373->cache_num; i++)
+               max98373->cache[i].reg = max98373_i2c_cache_reg[i];
+
        /* voltage/current slot & gpio configuration */
        max98373_slot_config(&i2c->dev, max98373);
 
index ec2e79c57357729835f6165b9eeb999832656135..b8d471d79e939e885553691565cbf036d3afaa4c 100644 (file)
@@ -23,6 +23,12 @@ struct sdw_stream_data {
        struct sdw_stream_runtime *sdw_stream;
 };
 
+static const u32 max98373_sdw_cache_reg[] = {
+       MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK,
+       MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK,
+       MAX98373_R20B6_BDE_CUR_STATE_READBACK,
+};
+
 static struct reg_default max98373_reg[] = {
        {MAX98373_R0040_SCP_INIT_STAT_1, 0x00},
        {MAX98373_R0041_SCP_INIT_MASK_1, 0x00},
@@ -245,6 +251,11 @@ static const struct regmap_config max98373_sdw_regmap = {
 static __maybe_unused int max98373_suspend(struct device *dev)
 {
        struct max98373_priv *max98373 = dev_get_drvdata(dev);
+       int i;
+
+       /* cache feedback register values before suspend */
+       for (i = 0; i < max98373->cache_num; i++)
+               regmap_read(max98373->regmap, max98373->cache[i].reg, &max98373->cache[i].val);
 
        regcache_cache_only(max98373->regmap, true);
 
@@ -757,6 +768,7 @@ static int max98373_init(struct sdw_slave *slave, struct regmap *regmap)
 {
        struct max98373_priv *max98373;
        int ret;
+       int i;
        struct device *dev = &slave->dev;
 
        /*  Allocate and assign private driver data structure  */
@@ -768,6 +780,14 @@ static int max98373_init(struct sdw_slave *slave, struct regmap *regmap)
        max98373->regmap = regmap;
        max98373->slave = slave;
 
+       max98373->cache_num = ARRAY_SIZE(max98373_sdw_cache_reg);
+       max98373->cache = devm_kcalloc(dev, max98373->cache_num,
+                                      sizeof(*max98373->cache),
+                                      GFP_KERNEL);
+
+       for (i = 0; i < max98373->cache_num; i++)
+               max98373->cache[i].reg = max98373_sdw_cache_reg[i];
+
        /* Read voltage and slot configuration */
        max98373_slot_config(dev, max98373);
 
index 929bb1798c43f9a5c03af199052a9682aae8ae34..31d571d4fac1ce590e51386759ede696ab7ddba6 100644 (file)
@@ -168,6 +168,31 @@ static SOC_ENUM_SINGLE_DECL(max98373_adc_samplerate_enum,
                            MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0,
                            max98373_ADC_samplerate_text);
 
+static int max98373_feedback_get(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component);
+       int i;
+
+       if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
+               /*
+                * Register values will be cached before suspend. The cached value
+                * will be a valid value and userspace will happy with that.
+                */
+               for (i = 0; i < max98373->cache_num; i++) {
+                       if (mc->reg == max98373->cache[i].reg) {
+                               ucontrol->value.integer.value[0] = max98373->cache[i].val;
+                               return 0;
+                       }
+               }
+       }
+
+       return snd_soc_put_volsw(kcontrol, ucontrol);
+}
+
 static const struct snd_kcontrol_new max98373_snd_controls[] = {
 SOC_SINGLE("Digital Vol Sel Switch", MAX98373_R203F_AMP_DSP_CFG,
        MAX98373_AMP_VOL_SEL_SHIFT, 1, 0),
@@ -209,8 +234,10 @@ SOC_SINGLE("ADC PVDD FLT Switch", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG,
        MAX98373_FLT_EN_SHIFT, 1, 0),
 SOC_SINGLE("ADC TEMP FLT Switch", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG,
        MAX98373_FLT_EN_SHIFT, 1, 0),
-SOC_SINGLE("ADC PVDD", MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0, 0xFF, 0),
-SOC_SINGLE("ADC TEMP", MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0, 0xFF, 0),
+SOC_SINGLE_EXT("ADC PVDD", MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0, 0xFF, 0,
+       max98373_feedback_get, NULL),
+SOC_SINGLE_EXT("ADC TEMP", MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0, 0xFF, 0,
+       max98373_feedback_get, NULL),
 SOC_SINGLE("ADC PVDD FLT Coeff", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG,
        0, 0x3, 0),
 SOC_SINGLE("ADC TEMP FLT Coeff", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG,
@@ -226,7 +253,8 @@ SOC_SINGLE("BDE LVL1 Thresh", MAX98373_R2097_BDE_L1_THRESH, 0, 0xFF, 0),
 SOC_SINGLE("BDE LVL2 Thresh", MAX98373_R2098_BDE_L2_THRESH, 0, 0xFF, 0),
 SOC_SINGLE("BDE LVL3 Thresh", MAX98373_R2099_BDE_L3_THRESH, 0, 0xFF, 0),
 SOC_SINGLE("BDE LVL4 Thresh", MAX98373_R209A_BDE_L4_THRESH, 0, 0xFF, 0),
-SOC_SINGLE("BDE Active Level", MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0, 8, 0),
+SOC_SINGLE_EXT("BDE Active Level", MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0, 8, 0,
+       max98373_feedback_get, NULL),
 SOC_SINGLE("BDE Clip Mode Switch", MAX98373_R2092_BDE_CLIPPER_MODE, 0, 1, 0),
 SOC_SINGLE("BDE Thresh Hysteresis", MAX98373_R209B_BDE_THRESH_HYST, 0, 0xFF, 0),
 SOC_SINGLE("BDE Hold Time", MAX98373_R2090_BDE_LVL_HOLD, 0, 0xFF, 0),
index 4ab29b9d51c74edd602d036e13c110b14ceb56f1..71f5a5228f34b1629644723bfb5bd47808bc6900 100644 (file)
 /* MAX98373_R2000_SW_RESET */
 #define MAX98373_SOFT_RESET (0x1 << 0)
 
+struct max98373_cache {
+       u32 reg;
+       u32 val;
+};
+
 struct max98373_priv {
        struct regmap *regmap;
        int reset_gpio;
@@ -212,6 +217,9 @@ struct max98373_priv {
        bool interleave_mode;
        unsigned int ch_size;
        bool tdm_mode;
+       /* cache for reading a valid fake feedback value */
+       struct max98373_cache *cache;
+       int cache_num;
        /* variables to support soundwire */
        struct sdw_slave *slave;
        bool hw_init;
index 5771c02c34596f5d5cc4f06f243f57f771ef95cc..85f744184a60fe4302baf6e9a58f0190d23ab5a3 100644 (file)
@@ -462,6 +462,8 @@ static int rt711_set_amp_gain_put(struct snd_kcontrol *kcontrol,
        unsigned int read_ll, read_rl;
        int i;
 
+       mutex_lock(&rt711->calibrate_mutex);
+
        /* Can't use update bit function, so read the original value first */
        addr_h = mc->reg;
        addr_l = mc->rreg;
@@ -547,6 +549,8 @@ static int rt711_set_amp_gain_put(struct snd_kcontrol *kcontrol,
        if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
                regmap_write(rt711->regmap,
                                RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
+
+       mutex_unlock(&rt711->calibrate_mutex);
        return 0;
 }
 
@@ -859,9 +863,11 @@ static int rt711_set_bias_level(struct snd_soc_component *component,
                break;
 
        case SND_SOC_BIAS_STANDBY:
+               mutex_lock(&rt711->calibrate_mutex);
                regmap_write(rt711->regmap,
                        RT711_SET_AUDIO_POWER_STATE,
                        AC_PWRST_D3);
+               mutex_unlock(&rt711->calibrate_mutex);
                break;
 
        default:
index 2c2a76a719401daa2751a1d72391164fe101f205..dbbb7618351c78b79627db8031a8fa9d7e32376c 100644 (file)
@@ -90,7 +90,7 @@ static int imx_hdmi_init(struct snd_soc_pcm_runtime *rtd)
        }
 
        ret = snd_soc_component_set_jack(component, &data->hdmi_jack, NULL);
-       if (ret && ret != -EOPNOTSUPP) {
+       if (ret && ret != -ENOTSUPP) {
                dev_err(card->dev, "Can't set HDMI Jack %d\n", ret);
                return ret;
        }
@@ -164,6 +164,7 @@ static int imx_hdmi_probe(struct platform_device *pdev)
 
        if ((hdmi_out && hdmi_in) || (!hdmi_out && !hdmi_in)) {
                dev_err(&pdev->dev, "Invalid HDMI DAI link\n");
+               ret = -EINVAL;
                goto fail;
        }
 
index c55d1239e705b50e639cb543bb29a383510748dd..c763bfeb1f38fbfe89f3462a6ad866115ecc4d1f 100644 (file)
@@ -189,6 +189,7 @@ static struct platform_driver haswell_audio = {
        .probe = haswell_audio_probe,
        .driver = {
                .name = "haswell-audio",
+               .pm = &snd_soc_pm_ops,
        },
 };
 
index fcd8dff27ae8e837f88ab83e00920b0eded02e31..1275c149acc021986feb2048c12c63d91d75fe89 100644 (file)
@@ -224,6 +224,7 @@ static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
                                "dsp boot timeout, status=%#x error=%#x\n",
                                sst_dsp_shim_read(ctx, CNL_ADSP_FW_STATUS),
                                sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE));
+                       ret = -ETIMEDOUT;
                        goto err;
                }
        } else {
index c8664ab80d45ad0b0774370221938a9d79f75620..87cac440b36933dc6180c13b9dec766d7b0725e5 100644 (file)
@@ -467,8 +467,20 @@ static int axg_tdm_iface_set_bias_level(struct snd_soc_component *component,
        return ret;
 }
 
+static const struct snd_soc_dapm_widget axg_tdm_iface_dapm_widgets[] = {
+       SND_SOC_DAPM_SIGGEN("Playback Signal"),
+};
+
+static const struct snd_soc_dapm_route axg_tdm_iface_dapm_routes[] = {
+       { "Loopback", NULL, "Playback Signal" },
+};
+
 static const struct snd_soc_component_driver axg_tdm_iface_component_drv = {
-       .set_bias_level = axg_tdm_iface_set_bias_level,
+       .dapm_widgets           = axg_tdm_iface_dapm_widgets,
+       .num_dapm_widgets       = ARRAY_SIZE(axg_tdm_iface_dapm_widgets),
+       .dapm_routes            = axg_tdm_iface_dapm_routes,
+       .num_dapm_routes        = ARRAY_SIZE(axg_tdm_iface_dapm_routes),
+       .set_bias_level         = axg_tdm_iface_set_bias_level,
 };
 
 static const struct of_device_id axg_tdm_iface_of_match[] = {
index 88ed95ae886bb506cda8c8ac74dae2babcd568c0..b4faf9d5c1aad15edb2ab34cf13b87e926c7fc87 100644 (file)
@@ -224,15 +224,6 @@ static const struct axg_tdm_formatter_ops axg_tdmin_ops = {
 };
 
 static const struct axg_tdm_formatter_driver axg_tdmin_drv = {
-       .component_drv  = &axg_tdmin_component_drv,
-       .regmap_cfg     = &axg_tdmin_regmap_cfg,
-       .ops            = &axg_tdmin_ops,
-       .quirks         = &(const struct axg_tdm_formatter_hw) {
-               .skew_offset    = 2,
-       },
-};
-
-static const struct axg_tdm_formatter_driver g12a_tdmin_drv = {
        .component_drv  = &axg_tdmin_component_drv,
        .regmap_cfg     = &axg_tdmin_regmap_cfg,
        .ops            = &axg_tdmin_ops,
@@ -247,10 +238,10 @@ static const struct of_device_id axg_tdmin_of_match[] = {
                .data = &axg_tdmin_drv,
        }, {
                .compatible = "amlogic,g12a-tdmin",
-               .data = &g12a_tdmin_drv,
+               .data = &axg_tdmin_drv,
        }, {
                .compatible = "amlogic,sm1-tdmin",
-               .data = &g12a_tdmin_drv,
+               .data = &axg_tdmin_drv,
        }, {}
 };
 MODULE_DEVICE_TABLE(of, axg_tdmin_of_match);
index af684fd19ab9e7b50f8f3147bb32e66ff1c2c2aa..c5e99c2d89c7ed65b3ae4eacd69a449df5b37d4b 100644 (file)
@@ -270,18 +270,6 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
        struct lpaif_i2sctl *i2sctl = drvdata->i2sctl;
        unsigned int id = dai->driver->id;
        int ret = -EINVAL;
-       unsigned int val = 0;
-
-       ret = regmap_read(drvdata->lpaif_map,
-                               LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), &val);
-       if (ret) {
-               dev_err(dai->dev, "error reading from i2sctl reg: %d\n", ret);
-               return ret;
-       }
-       if (val == LPAIF_I2SCTL_RESET_STATE) {
-               dev_err(dai->dev, "error in i2sctl register state\n");
-               return -ENOTRECOVERABLE;
-       }
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -454,20 +442,16 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg)
        struct lpass_variant *v = drvdata->variant;
        int i;
 
-       for (i = 0; i < v->i2s_ports; ++i)
-               if (reg == LPAIF_I2SCTL_REG(v, i))
-                       return true;
        for (i = 0; i < v->irq_ports; ++i)
                if (reg == LPAIF_IRQSTAT_REG(v, i))
                        return true;
 
        for (i = 0; i < v->rdma_channels; ++i)
-               if (reg == LPAIF_RDMACURR_REG(v, i) || reg == LPAIF_RDMACTL_REG(v, i))
+               if (reg == LPAIF_RDMACURR_REG(v, i))
                        return true;
 
        for (i = 0; i < v->wrdma_channels; ++i)
-               if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start) ||
-                       reg == LPAIF_WRDMACTL_REG(v, i + v->wrdma_channel_start))
+               if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start))
                        return true;
 
        return false;
index 80b09dede5f9cbefb4f6a6a7d968ea2166ada871..d1c248590f3ab6da7622dcf8d1909d74c340c88a 100644 (file)
@@ -452,7 +452,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
        unsigned int reg_irqclr = 0, val_irqclr = 0;
        unsigned int  reg_irqen = 0, val_irqen = 0, val_mask = 0;
        unsigned int dai_id = cpu_dai->driver->id;
-       unsigned int dma_ctrl_reg = 0;
 
        ch = pcm_data->dma_ch;
        if (dir ==  SNDRV_PCM_STREAM_PLAYBACK) {
@@ -469,17 +468,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
                id = pcm_data->dma_ch - v->wrdma_channel_start;
                map = drvdata->lpaif_map;
        }
-       ret = regmap_read(map, LPAIF_DMACTL_REG(v, ch, dir, dai_id), &dma_ctrl_reg);
-       if (ret) {
-               dev_err(soc_runtime->dev, "error reading from rdmactl reg: %d\n", ret);
-               return ret;
-       }
 
-       if (dma_ctrl_reg == LPAIF_DMACTL_RESET_STATE ||
-               dma_ctrl_reg == LPAIF_DMACTL_RESET_STATE + 1) {
-               dev_err(soc_runtime->dev, "error in rdmactl register state\n");
-               return -ENOTRECOVERABLE;
-       }
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
@@ -500,7 +489,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
                                        "error writing to rdmactl reg: %d\n", ret);
                                return ret;
                        }
-                       map = drvdata->hdmiif_map;
                        reg_irqclr = LPASS_HDMITX_APP_IRQCLEAR_REG(v);
                        val_irqclr = (LPAIF_IRQ_ALL(ch) |
                                        LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) |
@@ -519,7 +507,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
                        break;
                case MI2S_PRIMARY:
                case MI2S_SECONDARY:
-                       map = drvdata->lpaif_map;
                        reg_irqclr = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
                        val_irqclr = LPAIF_IRQ_ALL(ch);
 
@@ -563,7 +550,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
                                        "error writing to rdmactl reg: %d\n", ret);
                                return ret;
                        }
-                       map = drvdata->hdmiif_map;
                        reg_irqen = LPASS_HDMITX_APP_IRQEN_REG(v);
                        val_mask = (LPAIF_IRQ_ALL(ch) |
                                        LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) |
@@ -573,7 +559,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
                        break;
                case MI2S_PRIMARY:
                case MI2S_SECONDARY:
-                       map = drvdata->lpaif_map;
                        reg_irqen = LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST);
                        val_mask = LPAIF_IRQ_ALL(ch);
                        val_irqen = 0;
@@ -838,6 +823,39 @@ static void lpass_platform_pcm_free(struct snd_soc_component *component,
        }
 }
 
+static int lpass_platform_pcmops_suspend(struct snd_soc_component *component)
+{
+       struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
+       struct regmap *map;
+       unsigned int dai_id = component->id;
+
+       if (dai_id == LPASS_DP_RX)
+               map = drvdata->hdmiif_map;
+       else
+               map = drvdata->lpaif_map;
+
+       regcache_cache_only(map, true);
+       regcache_mark_dirty(map);
+
+       return 0;
+}
+
+static int lpass_platform_pcmops_resume(struct snd_soc_component *component)
+{
+       struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
+       struct regmap *map;
+       unsigned int dai_id = component->id;
+
+       if (dai_id == LPASS_DP_RX)
+               map = drvdata->hdmiif_map;
+       else
+               map = drvdata->lpaif_map;
+
+       regcache_cache_only(map, false);
+       return regcache_sync(map);
+}
+
+
 static const struct snd_soc_component_driver lpass_component_driver = {
        .name           = DRV_NAME,
        .open           = lpass_platform_pcmops_open,
@@ -850,6 +868,8 @@ static const struct snd_soc_component_driver lpass_component_driver = {
        .mmap           = lpass_platform_pcmops_mmap,
        .pcm_construct  = lpass_platform_pcm_new,
        .pcm_destruct   = lpass_platform_pcm_free,
+       .suspend                = lpass_platform_pcmops_suspend,
+       .resume                 = lpass_platform_pcmops_resume,
 
 };
 
index b9aacf3d3b29c9b0de99830a568371edbffffbe8..abdfd9cf91e2a06e2db05193dbe3ab0a31cc2307 100644 (file)
@@ -366,25 +366,27 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
        struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
        struct device *dev = rsnd_priv_to_dev(priv);
        struct clk *clk;
-       int i, ret;
+       int i;
 
        for_each_rsnd_clk(clk, adg, i) {
-               ret = 0;
                if (enable) {
-                       ret = clk_prepare_enable(clk);
+                       int ret = clk_prepare_enable(clk);
 
                        /*
                         * We shouldn't use clk_get_rate() under
                         * atomic context. Let's keep it when
                         * rsnd_adg_clk_enable() was called
                         */
-                       adg->clk_rate[i] = clk_get_rate(adg->clk[i]);
+                       adg->clk_rate[i] = 0;
+                       if (ret < 0)
+                               dev_warn(dev, "can't use clk %d\n", i);
+                       else
+                               adg->clk_rate[i] = clk_get_rate(clk);
                } else {
-                       clk_disable_unprepare(clk);
+                       if (adg->clk_rate[i])
+                               clk_disable_unprepare(clk);
+                       adg->clk_rate[i] = 0;
                }
-
-               if (ret < 0)
-                       dev_warn(dev, "can't use clk %d\n", i);
        }
 }
 
index 9f0c86cbdcca2160d4e75c0db226f36b5b86a9aa..2b75d0139e478c6f1feaff88601ecb15933c6221 100644 (file)
@@ -2486,6 +2486,7 @@ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w)
        enum snd_soc_dapm_direction dir;
 
        list_del(&w->list);
+       list_del(&w->dirty);
        /*
         * remove source and sink paths associated to this widget.
         * While removing the path, remove reference to it from both
index 031dad5fc4c701b8107828927e34ae7c2513eb63..3e8b6c035ce3ffba2cbe48c7b69597d3a71ecc0b 100644 (file)
@@ -122,7 +122,7 @@ config SND_SOC_SOF_DEBUG_XRUN_STOP
        bool "SOF stop on XRUN"
        help
          This option forces PCMs to stop on any XRUN event. This is useful to
-         preserve any trace data ond pipeline status prior to the XRUN.
+         preserve any trace data and pipeline status prior to the XRUN.
          Say Y if you are debugging SOF FW pipeline XRUNs.
          If unsure select "N".
 
index 6875fa570c2c55bf86d919624db577e35f9b177b..6744318de612e567ceab15b22df953686222a50e 100644 (file)
@@ -63,16 +63,18 @@ static int hda_codec_load_module(struct hda_codec *codec)
 }
 
 /* enable controller wake up event for all codecs with jack connectors */
-void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev)
+void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev, bool enable)
 {
        struct hda_bus *hbus = sof_to_hbus(sdev);
        struct hdac_bus *bus = sof_to_bus(sdev);
        struct hda_codec *codec;
        unsigned int mask = 0;
 
-       list_for_each_codec(codec, hbus)
-               if (codec->jacktbl.used)
-                       mask |= BIT(codec->core.addr);
+       if (enable) {
+               list_for_each_codec(codec, hbus)
+                       if (codec->jacktbl.used)
+                               mask |= BIT(codec->core.addr);
+       }
 
        snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, mask);
 }
@@ -81,23 +83,18 @@ void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev)
 void hda_codec_jack_check(struct snd_sof_dev *sdev)
 {
        struct hda_bus *hbus = sof_to_hbus(sdev);
-       struct hdac_bus *bus = sof_to_bus(sdev);
        struct hda_codec *codec;
 
-       /* disable controller Wake Up event*/
-       snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, 0);
-
        list_for_each_codec(codec, hbus)
                /*
                 * Wake up all jack-detecting codecs regardless whether an event
                 * has been recorded in STATESTS
                 */
                if (codec->jacktbl.used)
-                       schedule_delayed_work(&codec->jackpoll_work,
-                                             codec->jackpoll_interval);
+                       pm_request_resume(&codec->core.dev);
 }
 #else
-void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev) {}
+void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev, bool enable) {}
 void hda_codec_jack_check(struct snd_sof_dev *sdev) {}
 #endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */
 EXPORT_SYMBOL_NS(hda_codec_jack_wake_enable, SND_SOC_SOF_HDA_AUDIO_CODEC);
@@ -156,7 +153,8 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
                if (!hdev->bus->audio_component) {
                        dev_dbg(sdev->dev,
                                "iDisp hw present but no driver\n");
-                       goto error;
+                       ret = -ENOENT;
+                       goto out;
                }
                hda_priv->need_display_power = true;
        }
@@ -173,24 +171,23 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
                 * other return codes without modification
                 */
                if (ret == 0)
-                       goto error;
+                       ret = -ENOENT;
        }
 
-       return ret;
-
-error:
-       snd_hdac_ext_bus_device_exit(hdev);
-       return -ENOENT;
-
+out:
+       if (ret < 0) {
+               snd_hdac_device_unregister(hdev);
+               put_device(&hdev->dev);
+       }
 #else
        hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL);
        if (!hdev)
                return -ENOMEM;
 
        ret = snd_hdac_ext_bus_device_init(&hbus->core, address, hdev, HDA_DEV_ASOC);
+#endif
 
        return ret;
-#endif
 }
 
 /* Codec initialization */
index 2b001151fe376c83b55066513a487f1524b0d8df..1c5e05b88a90d7a25d21ab2830fc1e80f309254c 100644 (file)
@@ -617,7 +617,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
 
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
        if (runtime_suspend)
-               hda_codec_jack_wake_enable(sdev);
+               hda_codec_jack_wake_enable(sdev, true);
 
        /* power down all hda link */
        snd_hdac_ext_bus_link_power_down_all(bus);
@@ -683,8 +683,11 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume)
 
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
        /* check jack status */
-       if (runtime_resume)
-               hda_codec_jack_check(sdev);
+       if (runtime_resume) {
+               hda_codec_jack_wake_enable(sdev, false);
+               if (sdev->system_suspend_target == SOF_SUSPEND_NONE)
+                       hda_codec_jack_check(sdev);
+       }
 
        /* turn off the links that were off before suspend */
        list_for_each_entry(hlink, &bus->hlink_list, list) {
index 9ec8ae0fd6495505e59e9e9aef71d576465631e2..a3b6f3e9121c495813a65724763e7a29c5621e8f 100644 (file)
@@ -650,7 +650,7 @@ void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev);
  */
 void hda_codec_probe_bus(struct snd_sof_dev *sdev,
                         bool hda_codec_use_common_hdmi);
-void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev);
+void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev, bool enable);
 void hda_codec_jack_check(struct snd_sof_dev *sdev);
 
 #endif /* CONFIG_SND_SOC_SOF_HDA */
index d731ca62d59943304fc552f7fa839bd035227cb6..e08fbf8e3ee0f66027d6989e26c846edc4d563fb 100644 (file)
@@ -450,10 +450,8 @@ lookup_device_name(u32 id)
 static void snd_usb_audio_free(struct snd_card *card)
 {
        struct snd_usb_audio *chip = card->private_data;
-       struct snd_usb_endpoint *ep, *n;
 
-       list_for_each_entry_safe(ep, n, &chip->ep_list, list)
-               snd_usb_endpoint_free(ep);
+       snd_usb_endpoint_free_all(chip);
 
        mutex_destroy(&chip->mutex);
        if (!atomic_read(&chip->shutdown))
@@ -611,6 +609,7 @@ static int snd_usb_audio_create(struct usb_interface *intf,
        chip->usb_id = usb_id;
        INIT_LIST_HEAD(&chip->pcm_list);
        INIT_LIST_HEAD(&chip->ep_list);
+       INIT_LIST_HEAD(&chip->iface_ref_list);
        INIT_LIST_HEAD(&chip->midi_list);
        INIT_LIST_HEAD(&chip->mixer_list);
 
index 6a027c349194a4a0c37ebf8ee3dae34c441dab65..37091b11761434a5ccfb6b40e3906ea184d9a52b 100644 (file)
@@ -18,6 +18,7 @@ struct audioformat {
        unsigned int frame_size;        /* samples per frame for non-audio */
        unsigned char iface;            /* interface number */
        unsigned char altsetting;       /* corresponding alternate setting */
+       unsigned char ep_idx;           /* endpoint array index */
        unsigned char altset_idx;       /* array index of altenate setting */
        unsigned char attributes;       /* corresponding attributes of cs endpoint */
        unsigned char endpoint;         /* endpoint */
@@ -42,6 +43,7 @@ struct audioformat {
 };
 
 struct snd_usb_substream;
+struct snd_usb_iface_ref;
 struct snd_usb_endpoint;
 struct snd_usb_power_domain;
 
@@ -58,6 +60,7 @@ struct snd_urb_ctx {
 
 struct snd_usb_endpoint {
        struct snd_usb_audio *chip;
+       struct snd_usb_iface_ref *iface_ref;
 
        int opened;             /* open refcount; protect with chip->mutex */
        atomic_t running;       /* running status */
index 31051f2be46da9434851dd06272f4fbe318c41ae..dc68ed65e47877a31b6fcb1144246337f5a5213d 100644 (file)
@@ -485,18 +485,9 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip,
                              const struct audioformat *fmt, int rate)
 {
        struct usb_device *dev = chip->dev;
-       struct usb_host_interface *alts;
-       unsigned int ep;
        unsigned char data[3];
        int err, crate;
 
-       alts = snd_usb_get_host_interface(chip, fmt->iface, fmt->altsetting);
-       if (!alts)
-               return -EINVAL;
-       if (get_iface_desc(alts)->bNumEndpoints < 1)
-               return -EINVAL;
-       ep = get_endpoint(alts, 0)->bEndpointAddress;
-
        /* if endpoint doesn't have sampling rate control, bail out */
        if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE))
                return 0;
@@ -506,11 +497,11 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip,
        data[2] = rate >> 16;
        err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
                              USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
-                             UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
-                             data, sizeof(data));
+                             UAC_EP_CS_ATTR_SAMPLE_RATE << 8,
+                             fmt->endpoint, data, sizeof(data));
        if (err < 0) {
                dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n",
-                       fmt->iface, fmt->altsetting, rate, ep);
+                       fmt->iface, fmt->altsetting, rate, fmt->endpoint);
                return err;
        }
 
@@ -524,11 +515,11 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip,
 
        err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
                              USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
-                             UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
-                             data, sizeof(data));
+                             UAC_EP_CS_ATTR_SAMPLE_RATE << 8,
+                             fmt->endpoint, data, sizeof(data));
        if (err < 0) {
                dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n",
-                       fmt->iface, fmt->altsetting, ep);
+                       fmt->iface, fmt->altsetting, fmt->endpoint);
                chip->sample_rate_read_error++;
                return 0; /* some devices don't support reading */
        }
index 162da7a500463f672992843ae3e952088c8504c7..8e568823c99246ff66d88be10bf0d692e4bad95b 100644 (file)
 #define EP_FLAG_RUNNING                1
 #define EP_FLAG_STOPPING       2
 
+/* interface refcounting */
+struct snd_usb_iface_ref {
+       unsigned char iface;
+       bool need_setup;
+       int opened;
+       struct list_head list;
+};
+
 /*
  * snd_usb_endpoint is a model that abstracts everything related to an
  * USB endpoint and its streaming.
@@ -488,6 +496,28 @@ exit_clear:
        clear_bit(ctx->index, &ep->active_mask);
 }
 
+/*
+ * Find or create a refcount object for the given interface
+ *
+ * The objects are released altogether in snd_usb_endpoint_free_all()
+ */
+static struct snd_usb_iface_ref *
+iface_ref_find(struct snd_usb_audio *chip, int iface)
+{
+       struct snd_usb_iface_ref *ip;
+
+       list_for_each_entry(ip, &chip->iface_ref_list, list)
+               if (ip->iface == iface)
+                       return ip;
+
+       ip = kzalloc(sizeof(*ip), GFP_KERNEL);
+       if (!ip)
+               return NULL;
+       ip->iface = iface;
+       list_add_tail(&ip->list, &chip->iface_ref_list);
+       return ip;
+}
+
 /*
  * Get the existing endpoint object corresponding EP
  * Returns NULL if not present.
@@ -520,8 +550,8 @@ snd_usb_get_endpoint(struct snd_usb_audio *chip, int ep_num)
  *
  * Returns zero on success or a negative error code.
  *
- * New endpoints will be added to chip->ep_list and must be freed by
- * calling snd_usb_endpoint_free().
+ * New endpoints will be added to chip->ep_list and freed by
+ * calling snd_usb_endpoint_free_all().
  *
  * For SND_USB_ENDPOINT_TYPE_SYNC, the caller needs to guarantee that
  * bNumEndpoints > 1 beforehand.
@@ -653,11 +683,17 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
                } else {
                        ep->iface = fp->iface;
                        ep->altsetting = fp->altsetting;
-                       ep->ep_idx = 0;
+                       ep->ep_idx = fp->ep_idx;
                }
                usb_audio_dbg(chip, "Open EP 0x%x, iface=%d:%d, idx=%d\n",
                              ep_num, ep->iface, ep->altsetting, ep->ep_idx);
 
+               ep->iface_ref = iface_ref_find(chip, ep->iface);
+               if (!ep->iface_ref) {
+                       ep = NULL;
+                       goto unlock;
+               }
+
                ep->cur_audiofmt = fp;
                ep->cur_channels = fp->channels;
                ep->cur_rate = params_rate(params);
@@ -681,6 +717,11 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
                              ep->implicit_fb_sync);
 
        } else {
+               if (WARN_ON(!ep->iface_ref)) {
+                       ep = NULL;
+                       goto unlock;
+               }
+
                if (!endpoint_compatible(ep, fp, params)) {
                        usb_audio_err(chip, "Incompatible EP setup for 0x%x\n",
                                      ep_num);
@@ -692,6 +733,9 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
                              ep_num, ep->opened);
        }
 
+       if (!ep->iface_ref->opened++)
+               ep->iface_ref->need_setup = true;
+
        ep->opened++;
 
  unlock:
@@ -760,12 +804,16 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
        mutex_lock(&chip->mutex);
        usb_audio_dbg(chip, "Closing EP 0x%x (count %d)\n",
                      ep->ep_num, ep->opened);
-       if (!--ep->opened) {
+
+       if (!--ep->iface_ref->opened)
                endpoint_set_interface(chip, ep, false);
+
+       if (!--ep->opened) {
                ep->iface = 0;
                ep->altsetting = 0;
                ep->cur_audiofmt = NULL;
                ep->cur_rate = 0;
+               ep->iface_ref = NULL;
                usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num);
        }
        mutex_unlock(&chip->mutex);
@@ -775,6 +823,8 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
 void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep)
 {
        ep->need_setup = true;
+       if (ep->iface_ref)
+               ep->iface_ref->need_setup = true;
 }
 
 /*
@@ -1195,11 +1245,22 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
        int err = 0;
 
        mutex_lock(&chip->mutex);
+       if (WARN_ON(!ep->iface_ref))
+               goto unlock;
        if (!ep->need_setup)
                goto unlock;
 
-       /* No need to (re-)configure the sync EP belonging to the same altset */
-       if (ep->ep_idx) {
+       /* If the interface has been already set up, just set EP parameters */
+       if (!ep->iface_ref->need_setup) {
+               /* sample rate setup of UAC1 is per endpoint, and we need
+                * to update at each EP configuration
+                */
+               if (ep->cur_audiofmt->protocol == UAC_VERSION_1) {
+                       err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt,
+                                                      ep->cur_rate);
+                       if (err < 0)
+                               goto unlock;
+               }
                err = snd_usb_endpoint_set_params(chip, ep);
                if (err < 0)
                        goto unlock;
@@ -1242,6 +1303,8 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
                        goto unlock;
        }
 
+       ep->iface_ref->need_setup = false;
+
  done:
        ep->need_setup = false;
        err = 1;
@@ -1387,15 +1450,21 @@ void snd_usb_endpoint_release(struct snd_usb_endpoint *ep)
 }
 
 /**
- * snd_usb_endpoint_free: Free the resources of an snd_usb_endpoint
+ * snd_usb_endpoint_free_all: Free the resources of an snd_usb_endpoint
+ * @card: The chip
  *
- * @ep: the endpoint to free
- *
- * This free all resources of the given ep.
+ * This free all endpoints and those resources
  */
-void snd_usb_endpoint_free(struct snd_usb_endpoint *ep)
+void snd_usb_endpoint_free_all(struct snd_usb_audio *chip)
 {
-       kfree(ep);
+       struct snd_usb_endpoint *ep, *en;
+       struct snd_usb_iface_ref *ip, *in;
+
+       list_for_each_entry_safe(ep, en, &chip->ep_list, list)
+               kfree(ep);
+
+       list_for_each_entry_safe(ip, in, &chip->iface_ref_list, list)
+               kfree(ip);
 }
 
 /*
index 11e3bb839fd7e2a17c70067e402f90376e056401..eea4ca49876d67bb15bdd9b089a0f52760008224 100644 (file)
@@ -42,7 +42,7 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_release(struct snd_usb_endpoint *ep);
-void snd_usb_endpoint_free(struct snd_usb_endpoint *ep);
+void snd_usb_endpoint_free_all(struct snd_usb_audio *chip);
 
 int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep);
 int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep,
index 931042a6a051e5ca125ae2f8dce959ddbd6b1273..521cc846d9d9fec8246e38f22fb01fd0030d2fe0 100644 (file)
@@ -58,8 +58,6 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
        IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */
        IMPLICIT_FB_FIXED_DEV(0x0d9a, 0x00df, 0x81, 2), /* RTX6001 */
        IMPLICIT_FB_FIXED_DEV(0x22f0, 0x0006, 0x81, 3), /* Allen&Heath Qu-16 */
-       IMPLICIT_FB_FIXED_DEV(0x2b73, 0x000a, 0x82, 0), /* Pioneer DJ DJM-900NXS2 */
-       IMPLICIT_FB_FIXED_DEV(0x2b73, 0x0017, 0x82, 0), /* Pioneer DJ DJM-250MK2 */
        IMPLICIT_FB_FIXED_DEV(0x1686, 0xf029, 0x82, 2), /* Zoom UAC-2 */
        IMPLICIT_FB_FIXED_DEV(0x2466, 0x8003, 0x86, 2), /* Fractal Audio Axe-Fx II */
        IMPLICIT_FB_FIXED_DEV(0x0499, 0x172a, 0x86, 2), /* Yamaha MODX */
@@ -100,7 +98,7 @@ static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = {
 /* set up sync EP information on the audioformat */
 static int add_implicit_fb_sync_ep(struct snd_usb_audio *chip,
                                   struct audioformat *fmt,
-                                  int ep, int ifnum,
+                                  int ep, int ep_idx, int ifnum,
                                   const struct usb_host_interface *alts)
 {
        struct usb_interface *iface;
@@ -115,7 +113,7 @@ static int add_implicit_fb_sync_ep(struct snd_usb_audio *chip,
        fmt->sync_ep = ep;
        fmt->sync_iface = ifnum;
        fmt->sync_altsetting = alts->desc.bAlternateSetting;
-       fmt->sync_ep_idx = 0;
+       fmt->sync_ep_idx = ep_idx;
        fmt->implicit_fb = 1;
        usb_audio_dbg(chip,
                      "%d:%d: added %s implicit_fb sync_ep %x, iface %d:%d\n",
@@ -147,7 +145,7 @@ static int add_generic_uac2_implicit_fb(struct snd_usb_audio *chip,
            (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
                                        USB_ENDPOINT_USAGE_IMPLICIT_FB)
                return 0;
-       return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress,
+       return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
                                       ifnum, alts);
 }
 
@@ -173,10 +171,33 @@ static int add_roland_implicit_fb(struct snd_usb_audio *chip,
            (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
                                        USB_ENDPOINT_USAGE_IMPLICIT_FB)
                return 0;
-       return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress,
+       return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
                                       ifnum, alts);
 }
 
+/* Playback and capture EPs on Pioneer devices share the same iface/altset,
+ * but they don't seem working with the implicit fb mode well, hence we
+ * just return as if the sync were already set up.
+ */
+static int skip_pioneer_sync_ep(struct snd_usb_audio *chip,
+                               struct audioformat *fmt,
+                               struct usb_host_interface *alts)
+{
+       struct usb_endpoint_descriptor *epd;
+
+       if (alts->desc.bNumEndpoints != 2)
+               return 0;
+
+       epd = get_endpoint(alts, 1);
+       if (!usb_endpoint_is_isoc_in(epd) ||
+           (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC ||
+           ((epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
+            USB_ENDPOINT_USAGE_DATA &&
+            (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
+            USB_ENDPOINT_USAGE_IMPLICIT_FB))
+               return 0;
+       return 1; /* don't handle with the implicit fb, just skip sync EP */
+}
 
 static int __add_generic_implicit_fb(struct snd_usb_audio *chip,
                                     struct audioformat *fmt,
@@ -197,7 +218,7 @@ static int __add_generic_implicit_fb(struct snd_usb_audio *chip,
        if (!usb_endpoint_is_isoc_in(epd) ||
            (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
                return 0;
-       return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress,
+       return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
                                       iface, alts);
 }
 
@@ -250,7 +271,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
                case IMPLICIT_FB_NONE:
                        return 0; /* No quirk */
                case IMPLICIT_FB_FIXED:
-                       return add_implicit_fb_sync_ep(chip, fmt, p->ep_num,
+                       return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, 0,
                                                       p->iface, NULL);
                }
        }
@@ -278,6 +299,14 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
                        return 1;
        }
 
+       /* Pioneer devices with vendor spec class */
+       if (attr == USB_ENDPOINT_SYNC_ASYNC &&
+           alts->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
+           USB_ID_VENDOR(chip->usb_id) == 0x2b73 /* Pioneer */) {
+               if (skip_pioneer_sync_ep(chip, fmt, alts))
+                       return 1;
+       }
+
        /* Try the generic implicit fb if available */
        if (chip->generic_implicit_fb)
                return add_generic_implicit_fb(chip, fmt, alts);
@@ -295,8 +324,8 @@ static int audioformat_capture_quirk(struct snd_usb_audio *chip,
 
        p = find_implicit_fb_entry(chip, capture_implicit_fb_quirks, alts);
        if (p && p->type == IMPLICIT_FB_FIXED)
-               return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, p->iface,
-                                              NULL);
+               return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, 0,
+                                              p->iface, NULL);
        return 0;
 }
 
@@ -378,20 +407,19 @@ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
                                     int stream)
 {
        struct snd_usb_substream *subs;
-       const struct audioformat *fp, *sync_fmt;
+       const struct audioformat *fp, *sync_fmt = NULL;
        int score, high_score;
 
-       /* When sharing the same altset, use the original audioformat */
+       /* Use the original audioformat as fallback for the shared altset */
        if (target->iface == target->sync_iface &&
            target->altsetting == target->sync_altsetting)
-               return target;
+               sync_fmt = target;
 
        subs = find_matching_substream(chip, stream, target->sync_ep,
                                       target->fmt_type);
        if (!subs)
-               return NULL;
+               return sync_fmt;
 
-       sync_fmt = NULL;
        high_score = 0;
        list_for_each_entry(fp, &subs->fmt_list, list) {
                score = match_endpoint_audioformats(subs, fp,
index 56079901769fd93413df9c24f49dbd9ff76d4cf0..078bb4c94033498e7ddcc938aa31eb1a5a471e2e 100644 (file)
@@ -663,7 +663,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
        check_fmts.bits[1] = (u32)(fp->formats >> 32);
        snd_mask_intersect(&check_fmts, fmts);
        if (snd_mask_empty(&check_fmts)) {
-               hwc_debug("   > check: no supported format %d\n", fp->format);
+               hwc_debug("   > check: no supported format 0x%llx\n", fp->formats);
                return 0;
        }
        /* check the channels */
@@ -775,24 +775,11 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
        return apply_hw_params_minmax(it, rmin, rmax);
 }
 
-static int hw_rule_format(struct snd_pcm_hw_params *params,
-                         struct snd_pcm_hw_rule *rule)
+static int apply_hw_params_format_bits(struct snd_mask *fmt, u64 fbits)
 {
-       struct snd_usb_substream *subs = rule->private;
-       const struct audioformat *fp;
-       struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
-       u64 fbits;
        u32 oldbits[2];
        int changed;
 
-       hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]);
-       fbits = 0;
-       list_for_each_entry(fp, &subs->fmt_list, list) {
-               if (!hw_check_valid_format(subs, params, fp))
-                       continue;
-               fbits |= fp->formats;
-       }
-
        oldbits[0] = fmt->bits[0];
        oldbits[1] = fmt->bits[1];
        fmt->bits[0] &= (u32)fbits;
@@ -806,6 +793,24 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
        return changed;
 }
 
+static int hw_rule_format(struct snd_pcm_hw_params *params,
+                         struct snd_pcm_hw_rule *rule)
+{
+       struct snd_usb_substream *subs = rule->private;
+       const struct audioformat *fp;
+       struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+       u64 fbits;
+
+       hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]);
+       fbits = 0;
+       list_for_each_entry(fp, &subs->fmt_list, list) {
+               if (!hw_check_valid_format(subs, params, fp))
+                       continue;
+               fbits |= fp->formats;
+       }
+       return apply_hw_params_format_bits(fmt, fbits);
+}
+
 static int hw_rule_period_time(struct snd_pcm_hw_params *params,
                               struct snd_pcm_hw_rule *rule)
 {
@@ -833,64 +838,92 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params,
        return apply_hw_params_minmax(it, pmin, UINT_MAX);
 }
 
-/* apply PCM hw constraints from the concurrent sync EP */
-static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime,
-                                        struct snd_usb_substream *subs)
+/* get the EP or the sync EP for implicit fb when it's already set up */
+static const struct snd_usb_endpoint *
+get_sync_ep_from_substream(struct snd_usb_substream *subs)
 {
        struct snd_usb_audio *chip = subs->stream->chip;
-       struct snd_usb_endpoint *ep;
        const struct audioformat *fp;
-       int err;
+       const struct snd_usb_endpoint *ep;
 
        list_for_each_entry(fp, &subs->fmt_list, list) {
                ep = snd_usb_get_endpoint(chip, fp->endpoint);
                if (ep && ep->cur_rate)
-                       goto found;
+                       return ep;
                if (!fp->implicit_fb)
                        continue;
                /* for the implicit fb, check the sync ep as well */
                ep = snd_usb_get_endpoint(chip, fp->sync_ep);
                if (ep && ep->cur_rate)
-                       goto found;
+                       return ep;
        }
-       return 0;
+       return NULL;
+}
 
- found:
-       if (!find_format(&subs->fmt_list, ep->cur_format, ep->cur_rate,
-                        ep->cur_channels, false, NULL)) {
-               usb_audio_dbg(chip, "EP 0x%x being used, but not applicable\n",
-                             ep->ep_num);
+/* additional hw constraints for implicit feedback mode */
+static int hw_rule_format_implicit_fb(struct snd_pcm_hw_params *params,
+                                     struct snd_pcm_hw_rule *rule)
+{
+       struct snd_usb_substream *subs = rule->private;
+       const struct snd_usb_endpoint *ep;
+       struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+
+       ep = get_sync_ep_from_substream(subs);
+       if (!ep)
                return 0;
-       }
 
-       usb_audio_dbg(chip, "EP 0x%x being used, using fixed params:\n",
-                     ep->ep_num);
-       usb_audio_dbg(chip, "rate=%d, period_size=%d, periods=%d\n",
-                     ep->cur_rate, ep->cur_period_frames,
-                     ep->cur_buffer_periods);
+       hwc_debug("applying %s\n", __func__);
+       return apply_hw_params_format_bits(fmt, pcm_format_to_bits(ep->cur_format));
+}
 
-       runtime->hw.formats = subs->formats;
-       runtime->hw.rate_min = runtime->hw.rate_max = ep->cur_rate;
-       runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
-       runtime->hw.periods_min = runtime->hw.periods_max =
-               ep->cur_buffer_periods;
+static int hw_rule_rate_implicit_fb(struct snd_pcm_hw_params *params,
+                                   struct snd_pcm_hw_rule *rule)
+{
+       struct snd_usb_substream *subs = rule->private;
+       const struct snd_usb_endpoint *ep;
+       struct snd_interval *it;
 
-       err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-                                 hw_rule_channels, subs,
-                                 SNDRV_PCM_HW_PARAM_FORMAT,
-                                 SNDRV_PCM_HW_PARAM_RATE,
-                                 -1);
-       if (err < 0)
-               return err;
+       ep = get_sync_ep_from_substream(subs);
+       if (!ep)
+               return 0;
 
-       err = snd_pcm_hw_constraint_minmax(runtime,
-                                          SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
-                                          ep->cur_period_frames,
-                                          ep->cur_period_frames);
-       if (err < 0)
-               return err;
+       hwc_debug("applying %s\n", __func__);
+       it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+       return apply_hw_params_minmax(it, ep->cur_rate, ep->cur_rate);
+}
 
-       return 1; /* notify the finding */
+static int hw_rule_period_size_implicit_fb(struct snd_pcm_hw_params *params,
+                                          struct snd_pcm_hw_rule *rule)
+{
+       struct snd_usb_substream *subs = rule->private;
+       const struct snd_usb_endpoint *ep;
+       struct snd_interval *it;
+
+       ep = get_sync_ep_from_substream(subs);
+       if (!ep)
+               return 0;
+
+       hwc_debug("applying %s\n", __func__);
+       it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+       return apply_hw_params_minmax(it, ep->cur_period_frames,
+                                     ep->cur_period_frames);
+}
+
+static int hw_rule_periods_implicit_fb(struct snd_pcm_hw_params *params,
+                                      struct snd_pcm_hw_rule *rule)
+{
+       struct snd_usb_substream *subs = rule->private;
+       const struct snd_usb_endpoint *ep;
+       struct snd_interval *it;
+
+       ep = get_sync_ep_from_substream(subs);
+       if (!ep)
+               return 0;
+
+       hwc_debug("applying %s\n", __func__);
+       it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIODS);
+       return apply_hw_params_minmax(it, ep->cur_buffer_periods,
+                                     ep->cur_buffer_periods);
 }
 
 /*
@@ -899,20 +932,11 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime,
 
 static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs)
 {
-       struct snd_usb_audio *chip = subs->stream->chip;
        const struct audioformat *fp;
        unsigned int pt, ptmin;
        int param_period_time_if_needed = -1;
        int err;
 
-       mutex_lock(&chip->mutex);
-       err = apply_hw_constraint_from_sync(runtime, subs);
-       mutex_unlock(&chip->mutex);
-       if (err < 0)
-               return err;
-       if (err > 0) /* found the matching? */
-               goto add_extra_rules;
-
        runtime->hw.formats = subs->formats;
 
        runtime->hw.rate_min = 0x7fffffff;
@@ -957,6 +981,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 
        err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                  hw_rule_rate, subs,
+                                 SNDRV_PCM_HW_PARAM_RATE,
                                  SNDRV_PCM_HW_PARAM_FORMAT,
                                  SNDRV_PCM_HW_PARAM_CHANNELS,
                                  param_period_time_if_needed,
@@ -964,9 +989,9 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
        if (err < 0)
                return err;
 
-add_extra_rules:
        err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
                                  hw_rule_channels, subs,
+                                 SNDRV_PCM_HW_PARAM_CHANNELS,
                                  SNDRV_PCM_HW_PARAM_FORMAT,
                                  SNDRV_PCM_HW_PARAM_RATE,
                                  param_period_time_if_needed,
@@ -975,6 +1000,7 @@ add_extra_rules:
                return err;
        err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
                                  hw_rule_format, subs,
+                                 SNDRV_PCM_HW_PARAM_FORMAT,
                                  SNDRV_PCM_HW_PARAM_RATE,
                                  SNDRV_PCM_HW_PARAM_CHANNELS,
                                  param_period_time_if_needed,
@@ -993,6 +1019,28 @@ add_extra_rules:
                        return err;
        }
 
+       /* additional hw constraints for implicit fb */
+       err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
+                                 hw_rule_format_implicit_fb, subs,
+                                 SNDRV_PCM_HW_PARAM_FORMAT, -1);
+       if (err < 0)
+               return err;
+       err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+                                 hw_rule_rate_implicit_fb, subs,
+                                 SNDRV_PCM_HW_PARAM_RATE, -1);
+       if (err < 0)
+               return err;
+       err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+                                 hw_rule_period_size_implicit_fb, subs,
+                                 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
+       if (err < 0)
+               return err;
+       err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS,
+                                 hw_rule_periods_implicit_fb, subs,
+                                 SNDRV_PCM_HW_PARAM_PERIODS, -1);
+       if (err < 0)
+               return err;
+
        return 0;
 }
 
index 0e11cb96fa8cfe01215782d6e6b3d9fde5e18ccd..c8a4bdf18207c915486b0ebcdaa9f9405f8ebe44 100644 (file)
@@ -3362,6 +3362,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                                        .altsetting = 1,
                                        .altset_idx = 1,
                                        .endpoint = 0x86,
+                                       .ep_idx = 1,
                                        .ep_attr = USB_ENDPOINT_XFER_ISOC|
                                                 USB_ENDPOINT_SYNC_ASYNC|
                                                 USB_ENDPOINT_USAGE_IMPLICIT_FB,
@@ -3450,6 +3451,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                                        .altsetting = 1,
                                        .altset_idx = 1,
                                        .endpoint = 0x82,
+                                       .ep_idx = 1,
                                        .ep_attr = USB_ENDPOINT_XFER_ISOC|
                                                USB_ENDPOINT_SYNC_ASYNC|
                                                USB_ENDPOINT_USAGE_IMPLICIT_FB,
@@ -3506,6 +3508,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                                        .altsetting = 1,
                                        .altset_idx = 1,
                                        .endpoint = 0x82,
+                                       .ep_idx = 1,
                                        .ep_attr = USB_ENDPOINT_XFER_ISOC|
                                                 USB_ENDPOINT_SYNC_ASYNC|
                                                 USB_ENDPOINT_USAGE_IMPLICIT_FB,
@@ -3562,6 +3565,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                                        .altsetting = 1,
                                        .altset_idx = 1,
                                        .endpoint = 0x82,
+                                       .ep_idx = 1,
                                        .ep_attr = USB_ENDPOINT_XFER_ISOC|
                                                 USB_ENDPOINT_SYNC_ASYNC|
                                                 USB_ENDPOINT_USAGE_IMPLICIT_FB,
@@ -3619,6 +3623,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                                        .altsetting = 1,
                                        .altset_idx = 1,
                                        .endpoint = 0x82,
+                                       .ep_idx = 1,
                                        .ep_attr = USB_ENDPOINT_XFER_ISOC|
                                                USB_ENDPOINT_SYNC_ASYNC|
                                        USB_ENDPOINT_USAGE_IMPLICIT_FB,
@@ -3679,6 +3684,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                                        .altsetting = 1,
                                        .altset_idx = 1,
                                        .endpoint = 0x82,
+                                       .ep_idx = 1,
                                        .ep_attr = USB_ENDPOINT_XFER_ISOC|
                                            USB_ENDPOINT_SYNC_ASYNC|
                                            USB_ENDPOINT_USAGE_IMPLICIT_FB,
index e4a690bb4c996b7670186e078ec8063e26af799e..e196e364cef19401c5557bc5bf6a05d5843e3206 100644 (file)
@@ -120,6 +120,40 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
        return 0;
 }
 
+/* create the audio stream and the corresponding endpoints from the fixed
+ * audioformat object; this is used for quirks with the fixed EPs
+ */
+static int add_audio_stream_from_fixed_fmt(struct snd_usb_audio *chip,
+                                          struct audioformat *fp)
+{
+       int stream, err;
+
+       stream = (fp->endpoint & USB_DIR_IN) ?
+               SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
+
+       snd_usb_audioformat_set_sync_ep(chip, fp);
+
+       err = snd_usb_add_audio_stream(chip, stream, fp);
+       if (err < 0)
+               return err;
+
+       err = snd_usb_add_endpoint(chip, fp->endpoint,
+                                  SND_USB_ENDPOINT_TYPE_DATA);
+       if (err < 0)
+               return err;
+
+       if (fp->sync_ep) {
+               err = snd_usb_add_endpoint(chip, fp->sync_ep,
+                                          fp->implicit_fb ?
+                                          SND_USB_ENDPOINT_TYPE_DATA :
+                                          SND_USB_ENDPOINT_TYPE_SYNC);
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
 /*
  * create a stream for an endpoint/altsetting without proper descriptors
  */
@@ -131,8 +165,8 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
        struct audioformat *fp;
        struct usb_host_interface *alts;
        struct usb_interface_descriptor *altsd;
-       int stream, err;
        unsigned *rate_table = NULL;
+       int err;
 
        fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
        if (!fp)
@@ -153,11 +187,6 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
                fp->rate_table = rate_table;
        }
 
-       stream = (fp->endpoint & USB_DIR_IN)
-               ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-       err = snd_usb_add_audio_stream(chip, stream, fp);
-       if (err < 0)
-               goto error;
        if (fp->iface != get_iface_desc(&iface->altsetting[0])->bInterfaceNumber ||
            fp->altset_idx >= iface->num_altsetting) {
                err = -EINVAL;
@@ -165,7 +194,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
        }
        alts = &iface->altsetting[fp->altset_idx];
        altsd = get_iface_desc(alts);
-       if (altsd->bNumEndpoints < 1) {
+       if (altsd->bNumEndpoints <= fp->ep_idx) {
                err = -EINVAL;
                goto error;
        }
@@ -175,7 +204,14 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
        if (fp->datainterval == 0)
                fp->datainterval = snd_usb_parse_datainterval(chip, alts);
        if (fp->maxpacksize == 0)
-               fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
+               fp->maxpacksize = le16_to_cpu(get_endpoint(alts, fp->ep_idx)->wMaxPacketSize);
+       if (!fp->fmt_type)
+               fp->fmt_type = UAC_FORMAT_TYPE_I;
+
+       err = add_audio_stream_from_fixed_fmt(chip, fp);
+       if (err < 0)
+               goto error;
+
        usb_set_interface(chip->dev, fp->iface, 0);
        snd_usb_init_pitch(chip, fp);
        snd_usb_init_sample_rate(chip, fp, fp->rate_max);
@@ -417,7 +453,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
        struct usb_host_interface *alts;
        struct usb_interface_descriptor *altsd;
        struct audioformat *fp;
-       int stream, err;
+       int err;
 
        /* both PCM and MIDI interfaces have 2 or more altsettings */
        if (iface->num_altsetting < 2)
@@ -482,9 +518,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
                return -ENXIO;
        }
 
-       stream = (fp->endpoint & USB_DIR_IN)
-               ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-       err = snd_usb_add_audio_stream(chip, stream, fp);
+       err = add_audio_stream_from_fixed_fmt(chip, fp);
        if (err < 0) {
                list_del(&fp->list); /* unlink for avoiding double-free */
                kfree(fp);
@@ -1436,30 +1470,6 @@ static void set_format_emu_quirk(struct snd_usb_substream *subs,
        subs->pkt_offset_adj = (emu_samplerate_id >= EMU_QUIRK_SR_176400HZ) ? 4 : 0;
 }
 
-
-/*
- * Pioneer DJ DJM-900NXS2
- * Device needs to know the sample rate each time substream is started
- */
-static int pioneer_djm_set_format_quirk(struct snd_usb_substream *subs)
-{
-       unsigned int cur_rate = subs->data_endpoint->cur_rate;
-       /* Convert sample rate value to little endian */
-       u8 sr[3];
-
-       sr[0] = cur_rate & 0xff;
-       sr[1] = (cur_rate >> 8) & 0xff;
-       sr[2] = (cur_rate >> 16) & 0xff;
-
-       /* Configure device */
-       usb_set_interface(subs->dev, 0, 1);
-       snd_usb_ctl_msg(subs->stream->chip->dev,
-               usb_rcvctrlpipe(subs->stream->chip->dev, 0),
-               0x01, 0x22, 0x0100, 0x0082, &sr, 0x0003);
-
-       return 0;
-}
-
 void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
                              const struct audioformat *fmt)
 {
@@ -1470,10 +1480,6 @@ 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(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */
-       case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
-               pioneer_djm_set_format_quirk(subs);
-               break;
        case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */
                subs->stream_offset_adj = 2;
                break;
index 980287aadd361b4b48f3aaa63faa6e05495805e0..215c1771dd570725671ceab9913ca2cdadc33126 100644 (file)
@@ -44,6 +44,7 @@ struct snd_usb_audio {
 
        struct list_head pcm_list;      /* list of pcm streams */
        struct list_head ep_list;       /* list of audio-related endpoints */
+       struct list_head iface_ref_list; /* list of interface refcounts */
        int pcm_devs;
 
        struct list_head midi_list;     /* list of midi interfaces */
index 595e164dc352f08d97125f04e49efd89e9281811..feb30c2c788159008c6caa00fe11b48a27b8a9b3 100755 (executable)
@@ -152,6 +152,7 @@ setup_instance() { # [instance]
        set_array_of ${instance}.options ${instancedir}/trace_options
        set_value_of ${instance}.trace_clock ${instancedir}/trace_clock
        set_value_of ${instance}.cpumask ${instancedir}/tracing_cpumask
+       set_value_of ${instance}.tracing_on ${instancedir}/tracing_on
        set_value_of ${instance}.tracer ${instancedir}/current_tracer
        set_array_of ${instance}.ftrace.filters \
                ${instancedir}/set_ftrace_filter
index 6c0d4b61e0c260a9e213453b76e887282a1edde1..a0c3bcc6da4f36c24bc29efa4ec8a718d213e3c1 100755 (executable)
@@ -221,6 +221,10 @@ instance_options() { # [instance-name]
        if [ `echo $val | sed -e s/f//g`x != x ]; then
                emit_kv $PREFIX.cpumask = $val
        fi
+       val=`cat $INSTANCE/tracing_on`
+       if [ `echo $val | sed -e s/f//g`x != x ]; then
+               emit_kv $PREFIX.tracing_on = $val
+       fi
 
        val=
        for i in `cat $INSTANCE/set_event`; do
index cacd66ad792610e673969cc2056391218496fc28..a2b233fdb572eb687674315054e19bfe7e070d3b 100644 (file)
@@ -107,8 +107,8 @@ int monitor_device(const char *device_name,
                        ret = -EIO;
                        break;
                }
-               fprintf(stdout, "GPIO EVENT at %llu on line %d (%d|%d) ",
-                       event.timestamp_ns, event.offset, event.line_seqno,
+               fprintf(stdout, "GPIO EVENT at %" PRIu64 " on line %d (%d|%d) ",
+                       (uint64_t)event.timestamp_ns, event.offset, event.line_seqno,
                        event.seqno);
                switch (event.id) {
                case GPIO_V2_LINE_EVENT_RISING_EDGE:
index f229ec62301b7e17c827a1532f34e0b8c3341b72..41e76d244192244d6326f764378576fbbbfa7dc9 100644 (file)
@@ -10,6 +10,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <linux/gpio.h>
 #include <poll.h>
 #include <stdbool.h>
@@ -86,8 +87,8 @@ int main(int argc, char **argv)
                                return EXIT_FAILURE;
                        }
 
-                       printf("line %u: %s at %llu\n",
-                              chg.info.offset, event, chg.timestamp_ns);
+                       printf("line %u: %s at %" PRIu64 "\n",
+                              chg.info.offset, event, (uint64_t)chg.timestamp_ns);
                }
        }
 
index ce365d212768211b8812054bae5399f464d67acb..cc7070c7439ba6a5327d992a6cebf4fdc591f7ab 100644 (file)
@@ -79,9 +79,4 @@
 #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
 #endif // static_assert
 
-#ifdef __GENKSYMS__
-/* genksyms gets confused by _Static_assert */
-#define _Static_assert(expr, ...)
-#endif
-
 #endif /* _LINUX_BUILD_BUG_H */
index 886802b8ffba3617f64b47f7f6f452335fdfa23e..374c67875cdbd5c60eb15c1b932e7fcdc7f9fa7d 100644 (file)
@@ -251,6 +251,7 @@ struct kvm_hyperv_exit {
 #define KVM_EXIT_X86_RDMSR        29
 #define KVM_EXIT_X86_WRMSR        30
 #define KVM_EXIT_DIRTY_RING_FULL  31
+#define KVM_EXIT_AP_RESET_HOLD    32
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -573,6 +574,7 @@ struct kvm_vapic_addr {
 #define KVM_MP_STATE_CHECK_STOP        6
 #define KVM_MP_STATE_OPERATING         7
 #define KVM_MP_STATE_LOAD              8
+#define KVM_MP_STATE_AP_RESET_HOLD     9
 
 struct kvm_mp_state {
        __u32 mp_state;
index 3c3f2bc6c6528e08fdaa913f1da43e2c02799b48..9970a288dda536768b5878f5f0a2c71dc0af8a97 100644 (file)
@@ -240,11 +240,6 @@ static int btf_parse_hdr(struct btf *btf)
        }
 
        meta_left = btf->raw_size - sizeof(*hdr);
-       if (!meta_left) {
-               pr_debug("BTF has no data\n");
-               return -EINVAL;
-       }
-
        if (meta_left < hdr->str_off + hdr->str_len) {
                pr_debug("Invalid BTF total size:%u\n", btf->raw_size);
                return -EINVAL;
index cfcdbd7be066eaaac7677c5e723d5eef9f999fbb..17465d454a0e31d912f7d0782d3f0bc19b6bfcdd 100644 (file)
@@ -367,21 +367,13 @@ static struct perf_mmap* perf_evlist__alloc_mmap(struct perf_evlist *evlist, boo
        return map;
 }
 
-static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
-                                    struct perf_evsel *evsel, int idx, int cpu,
-                                    int thread)
+static void perf_evsel__set_sid_idx(struct perf_evsel *evsel, int idx, int cpu, int thread)
 {
        struct perf_sample_id *sid = SID(evsel, cpu, thread);
 
        sid->idx = idx;
-       if (evlist->cpus && cpu >= 0)
-               sid->cpu = evlist->cpus->map[cpu];
-       else
-               sid->cpu = -1;
-       if (!evsel->system_wide && evlist->threads && thread >= 0)
-               sid->tid = perf_thread_map__pid(evlist->threads, thread);
-       else
-               sid->tid = -1;
+       sid->cpu = perf_cpu_map__cpu(evsel->cpus, cpu);
+       sid->tid = perf_thread_map__pid(evsel->threads, thread);
 }
 
 static struct perf_mmap*
@@ -500,8 +492,7 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
                        if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
                                                   fd) < 0)
                                return -1;
-                       perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
-                                                thread);
+                       perf_evsel__set_sid_idx(evsel, idx, cpu, thread);
                }
        }
 
index c8d45091e7c26a3bede00f38dc72b03f83d435b4..c70e9e03af3e9929813017c48df7f063f9f701e4 100644 (file)
@@ -27,5 +27,5 @@ int main(int argc, char **argv)
        perf_cpu_map__put(cpus);
 
        __T_END;
-       return 0;
+       return tests_failed == 0 ? 0 : -1;
 }
index 6d8ebe0c25042f7c6902744967c0cb7074db62c8..e2ac0b7f432eaa87aeab1b8952ca27d675ae962a 100644 (file)
@@ -208,13 +208,13 @@ static int test_mmap_thread(void)
        char path[PATH_MAX];
        int id, err, pid, go_pipe[2];
        union perf_event *event;
-       char bf;
        int count = 0;
 
        snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
                 sysfs__mountpoint());
 
        if (filename__read_int(path, &id)) {
+               tests_failed++;
                fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
                return -1;
        }
@@ -229,6 +229,7 @@ static int test_mmap_thread(void)
        pid = fork();
        if (!pid) {
                int i;
+               char bf;
 
                read(go_pipe[0], &bf, 1);
 
@@ -266,7 +267,7 @@ static int test_mmap_thread(void)
        perf_evlist__enable(evlist);
 
        /* kick the child and wait for it to finish */
-       write(go_pipe[1], &bf, 1);
+       write(go_pipe[1], "A", 1);
        waitpid(pid, NULL, 0);
 
        /*
@@ -409,5 +410,5 @@ int main(int argc, char **argv)
        test_mmap_cpus();
 
        __T_END;
-       return 0;
+       return tests_failed == 0 ? 0 : -1;
 }
index 135722ac965bf7dcd75a3d50dc2bc9250cfd89a2..0ad82d7a2a51b690e57d2d28f16531fe7df40609 100644 (file)
@@ -131,5 +131,5 @@ int main(int argc, char **argv)
        test_stat_thread_enable();
 
        __T_END;
-       return 0;
+       return tests_failed == 0 ? 0 : -1;
 }
index 7dc4d6fbeddee5bdc4b0f0316f8b6a1814fa2c6b..384471441b4842e8cd472d2750e267dcbb05ec3f 100644 (file)
@@ -27,5 +27,5 @@ int main(int argc, char **argv)
        perf_thread_map__put(threads);
 
        __T_END;
-       return 0;
+       return tests_failed == 0 ? 0 : -1;
 }
index edacfa98d073b38bdbc70754a4b795ec82cb53c2..42dad4a0f8cf49eecd17fe129134cb5f9aef2db3 100644 (file)
@@ -186,6 +186,7 @@ struct output_option {
 
 enum {
        OUTPUT_TYPE_SYNTH = PERF_TYPE_MAX,
+       OUTPUT_TYPE_OTHER,
        OUTPUT_TYPE_MAX
 };
 
@@ -283,6 +284,18 @@ static struct {
 
                .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
        },
+
+       [OUTPUT_TYPE_OTHER] = {
+               .user_set = false,
+
+               .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
+                             PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
+                             PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+                             PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
+                             PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
+
+               .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
+       },
 };
 
 struct evsel_script {
@@ -343,8 +356,11 @@ static inline int output_type(unsigned int type)
        case PERF_TYPE_SYNTH:
                return OUTPUT_TYPE_SYNTH;
        default:
-               return type;
+               if (type < PERF_TYPE_MAX)
+                       return type;
        }
+
+       return OUTPUT_TYPE_OTHER;
 }
 
 static inline unsigned int attr_type(unsigned int type)
index 65c4ff6892d967ab02459ba14f258d7080d6e078..e6b6181c6dc63b29abf7463c7bee52c048e5e112 100644 (file)
@@ -39,7 +39,7 @@
    Copyright (C) 2018 Red Hat, Inc., Arnaldo Carvalho de Melo <acme@redhat.com>
 */
 
-#include <bpf/bpf.h>
+#include <bpf.h>
 
 #define NSEC_PER_SEC   1000000000L
 
index 249dfe48cf6ad490d1f3066e137d7f843cce00ab..ebebd3596cf99379d92600bcdae786e9c45e3694 100755 (executable)
@@ -9,31 +9,29 @@ perf stat -a true > /dev/null 2>&1 || exit 2
 
 test_global_aggr()
 {
-       local cyc
-
        perf stat -a --no-big-num -e cycles,instructions sleep 1  2>&1 | \
        grep -e cycles -e instructions | \
        while read num evt hash ipc rest
        do
                # skip not counted events
-               if [[ $num == "<not" ]]; then
+               if [ "$num" = "<not" ]; then
                        continue
                fi
 
                # save cycles count
-               if [[ $evt == "cycles" ]]; then
+               if [ "$evt" = "cycles" ]; then
                        cyc=$num
                        continue
                fi
 
                # skip if no cycles
-               if [[ -z $cyc ]]; then
+               if [ -z "$cyc" ]; then
                        continue
                fi
 
                # use printf for rounding and a leading zero
-               local res=`printf "%.2f" $(echo "scale=6; $num / $cyc" | bc -q)`
-               if [[ $ipc != $res ]]; then
+               res=`printf "%.2f" $(echo "scale=6; $num / $cyc" | bc -q)`
+               if [ "$ipc" != "$res" ]; then
                        echo "IPC is different: $res != $ipc  ($num / $cyc)"
                        exit 1
                fi
@@ -42,32 +40,32 @@ test_global_aggr()
 
 test_no_aggr()
 {
-       declare -A results
-
        perf stat -a -A --no-big-num -e cycles,instructions sleep 1  2>&1 | \
        grep ^CPU | \
        while read cpu num evt hash ipc rest
        do
                # skip not counted events
-               if [[ $num == "<not" ]]; then
+               if [ "$num" = "<not" ]; then
                        continue
                fi
 
                # save cycles count
-               if [[ $evt == "cycles" ]]; then
-                       results[$cpu]=$num
+               if [ "$evt" = "cycles" ]; then
+                       results="$results $cpu:$num"
                        continue
                fi
 
+               cyc=${results##* $cpu:}
+               cyc=${cyc%% *}
+
                # skip if no cycles
-               local cyc=${results[$cpu]}
-               if [[ -z $cyc ]]; then
+               if [ -z "$cyc" ]; then
                        continue
                fi
 
                # use printf for rounding and a leading zero
-               local res=`printf "%.2f" $(echo "scale=6; $num / $cyc" | bc -q)`
-               if [[ $ipc != $res ]]; then
+               res=`printf "%.2f" $(echo "scale=6; $num / $cyc" | bc -q)`
+               if [ "$ipc" != "$res" ]; then
                        echo "IPC is different for $cpu: $res != $ipc  ($num / $cyc)"
                        exit 1
                fi
index 062383e225a3e9e64f229b739d2c155b5430e28d..c4ed3dc2c8f405323854e81225b2e1b32bbc7f7d 100644 (file)
@@ -3323,6 +3323,14 @@ int perf_session__write_header(struct perf_session *session,
        attr_offset = lseek(ff.fd, 0, SEEK_CUR);
 
        evlist__for_each_entry(evlist, evsel) {
+               if (evsel->core.attr.size < sizeof(evsel->core.attr)) {
+                       /*
+                        * We are likely in "perf inject" and have read
+                        * from an older file. Update attr size so that
+                        * reader gets the right offset to the ids.
+                        */
+                       evsel->core.attr.size = sizeof(evsel->core.attr);
+               }
                f_attr = (struct perf_file_attr){
                        .attr = evsel->core.attr,
                        .ids  = {
index f841f3503cae61de55ce1b8dbe912b7b0f8e2f53..1e9d3f982b47742f8c5c043c131945c2b18151cd 100644 (file)
@@ -2980,7 +2980,7 @@ int machines__for_each_thread(struct machines *machines,
 
 pid_t machine__get_current_tid(struct machine *machine, int cpu)
 {
-       int nr_cpus = min(machine->env->nr_cpus_online, MAX_NR_CPUS);
+       int nr_cpus = min(machine->env->nr_cpus_avail, MAX_NR_CPUS);
 
        if (cpu < 0 || cpu >= nr_cpus || !machine->current_tid)
                return -1;
@@ -2992,7 +2992,7 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
                             pid_t tid)
 {
        struct thread *thread;
-       int nr_cpus = min(machine->env->nr_cpus_online, MAX_NR_CPUS);
+       int nr_cpus = min(machine->env->nr_cpus_avail, MAX_NR_CPUS);
 
        if (cpu < 0)
                return -EINVAL;
index ee94d3e8dd654e389eeb811af211e0d4c0a92149..e6d3452031e52efac75566a0ffd2a926fd7aeac9 100644 (file)
@@ -162,6 +162,14 @@ static bool contains_event(struct evsel **metric_events, int num_events,
        return false;
 }
 
+static bool evsel_same_pmu(struct evsel *ev1, struct evsel *ev2)
+{
+       if (!ev1->pmu_name || !ev2->pmu_name)
+               return false;
+
+       return !strcmp(ev1->pmu_name, ev2->pmu_name);
+}
+
 /**
  * Find a group of events in perf_evlist that correspond to those from a parsed
  * metric expression. Note, as find_evsel_group is called in the same order as
@@ -280,8 +288,7 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist,
                         */
                        if (!has_constraint &&
                            ev->leader != metric_events[i]->leader &&
-                           !strcmp(ev->leader->pmu_name,
-                                   metric_events[i]->leader->pmu_name))
+                           evsel_same_pmu(ev->leader, metric_events[i]->leader))
                                break;
                        if (!strcmp(metric_events[i]->name, ev->name)) {
                                set_bit(ev->idx, evlist_used);
@@ -766,7 +773,6 @@ int __weak arch_get_runtimeparam(struct pmu_event *pe __maybe_unused)
 struct metricgroup_add_iter_data {
        struct list_head *metric_list;
        const char *metric;
-       struct metric **m;
        struct expr_ids *ids;
        int *ret;
        bool *has_match;
@@ -1058,12 +1064,13 @@ static int metricgroup__add_metric_sys_event_iter(struct pmu_event *pe,
                                                  void *data)
 {
        struct metricgroup_add_iter_data *d = data;
+       struct metric *m = NULL;
        int ret;
 
        if (!match_pe_metric(pe, d->metric))
                return 0;
 
-       ret = add_metric(d->metric_list, pe, d->metric_no_group, d->m, NULL, d->ids);
+       ret = add_metric(d->metric_list, pe, d->metric_no_group, &m, NULL, d->ids);
        if (ret)
                return ret;
 
@@ -1114,7 +1121,6 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group,
                                .metric_list = &list,
                                .metric = metric,
                                .metric_no_group = metric_no_group,
-                               .m = &m,
                                .ids = &ids,
                                .has_match = &has_match,
                                .ret = &ret,
index 50ff9795a4f112acb8f73e6750fef60f26d6f48a..25adbcce02814145650819cf9cbf76284c3e434d 100644 (file)
@@ -2404,7 +2404,7 @@ int perf_session__cpu_bitmap(struct perf_session *session,
 {
        int i, err = -1;
        struct perf_cpu_map *map;
-       int nr_cpus = min(session->header.env.nr_cpus_online, MAX_NR_CPUS);
+       int nr_cpus = min(session->header.env.nr_cpus_avail, MAX_NR_CPUS);
 
        for (i = 0; i < PERF_TYPE_MAX; ++i) {
                struct evsel *evsel;
index 901265127e3698126bc9f395058ee4f12fd05419..12eafd12a693c077178be44b5b60620dee0d03cc 100644 (file)
@@ -8,6 +8,7 @@
 #include "evlist.h"
 #include "expr.h"
 #include "metricgroup.h"
+#include "cgroup.h"
 #include <linux/zalloc.h>
 
 /*
@@ -28,6 +29,7 @@ struct saved_value {
        enum stat_type type;
        int ctx;
        int cpu;
+       struct cgroup *cgrp;
        struct runtime_stat *stat;
        struct stats stats;
        u64 metric_total;
@@ -57,6 +59,9 @@ static int saved_value_cmp(struct rb_node *rb_node, const void *entry)
        if (a->ctx != b->ctx)
                return a->ctx - b->ctx;
 
+       if (a->cgrp != b->cgrp)
+               return (char *)a->cgrp < (char *)b->cgrp ? -1 : +1;
+
        if (a->evsel == NULL && b->evsel == NULL) {
                if (a->stat == b->stat)
                        return 0;
@@ -100,7 +105,8 @@ static struct saved_value *saved_value_lookup(struct evsel *evsel,
                                              bool create,
                                              enum stat_type type,
                                              int ctx,
-                                             struct runtime_stat *st)
+                                             struct runtime_stat *st,
+                                             struct cgroup *cgrp)
 {
        struct rblist *rblist;
        struct rb_node *nd;
@@ -110,10 +116,15 @@ static struct saved_value *saved_value_lookup(struct evsel *evsel,
                .type = type,
                .ctx = ctx,
                .stat = st,
+               .cgrp = cgrp,
        };
 
        rblist = &st->value_list;
 
+       /* don't use context info for clock events */
+       if (type == STAT_NSECS)
+               dm.ctx = 0;
+
        nd = rblist__find(rblist, &dm);
        if (nd)
                return container_of(nd, struct saved_value, rb_node);
@@ -191,12 +202,18 @@ void perf_stat__reset_shadow_per_stat(struct runtime_stat *st)
        reset_stat(st);
 }
 
+struct runtime_stat_data {
+       int ctx;
+       struct cgroup *cgrp;
+};
+
 static void update_runtime_stat(struct runtime_stat *st,
                                enum stat_type type,
-                               int ctx, int cpu, u64 count)
+                               int cpu, u64 count,
+                               struct runtime_stat_data *rsd)
 {
-       struct saved_value *v = saved_value_lookup(NULL, cpu, true,
-                                                  type, ctx, st);
+       struct saved_value *v = saved_value_lookup(NULL, cpu, true, type,
+                                                  rsd->ctx, st, rsd->cgrp);
 
        if (v)
                update_stats(&v->stats, count);
@@ -210,82 +227,86 @@ static void update_runtime_stat(struct runtime_stat *st,
 void perf_stat__update_shadow_stats(struct evsel *counter, u64 count,
                                    int cpu, struct runtime_stat *st)
 {
-       int ctx = evsel_context(counter);
        u64 count_ns = count;
        struct saved_value *v;
+       struct runtime_stat_data rsd = {
+               .ctx = evsel_context(counter),
+               .cgrp = counter->cgrp,
+       };
 
        count *= counter->scale;
 
        if (evsel__is_clock(counter))
-               update_runtime_stat(st, STAT_NSECS, 0, cpu, count_ns);
+               update_runtime_stat(st, STAT_NSECS, cpu, count_ns, &rsd);
        else if (evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
-               update_runtime_stat(st, STAT_CYCLES, ctx, cpu, count);
+               update_runtime_stat(st, STAT_CYCLES, cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, CYCLES_IN_TX))
-               update_runtime_stat(st, STAT_CYCLES_IN_TX, ctx, cpu, count);
+               update_runtime_stat(st, STAT_CYCLES_IN_TX, cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, TRANSACTION_START))
-               update_runtime_stat(st, STAT_TRANSACTION, ctx, cpu, count);
+               update_runtime_stat(st, STAT_TRANSACTION, cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, ELISION_START))
-               update_runtime_stat(st, STAT_ELISION, ctx, cpu, count);
+               update_runtime_stat(st, STAT_ELISION, cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, TOPDOWN_TOTAL_SLOTS))
                update_runtime_stat(st, STAT_TOPDOWN_TOTAL_SLOTS,
-                                   ctx, cpu, count);
+                                   cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_ISSUED))
                update_runtime_stat(st, STAT_TOPDOWN_SLOTS_ISSUED,
-                                   ctx, cpu, count);
+                                   cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_RETIRED))
                update_runtime_stat(st, STAT_TOPDOWN_SLOTS_RETIRED,
-                                   ctx, cpu, count);
+                                   cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, TOPDOWN_FETCH_BUBBLES))
                update_runtime_stat(st, STAT_TOPDOWN_FETCH_BUBBLES,
-                                   ctx, cpu, count);
+                                   cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, TOPDOWN_RECOVERY_BUBBLES))
                update_runtime_stat(st, STAT_TOPDOWN_RECOVERY_BUBBLES,
-                                   ctx, cpu, count);
+                                   cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, TOPDOWN_RETIRING))
                update_runtime_stat(st, STAT_TOPDOWN_RETIRING,
-                                   ctx, cpu, count);
+                                   cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, TOPDOWN_BAD_SPEC))
                update_runtime_stat(st, STAT_TOPDOWN_BAD_SPEC,
-                                   ctx, cpu, count);
+                                   cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, TOPDOWN_FE_BOUND))
                update_runtime_stat(st, STAT_TOPDOWN_FE_BOUND,
-                                   ctx, cpu, count);
+                                   cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, TOPDOWN_BE_BOUND))
                update_runtime_stat(st, STAT_TOPDOWN_BE_BOUND,
-                                   ctx, cpu, count);
+                                   cpu, count, &rsd);
        else if (evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
                update_runtime_stat(st, STAT_STALLED_CYCLES_FRONT,
-                                   ctx, cpu, count);
+                                   cpu, count, &rsd);
        else if (evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
                update_runtime_stat(st, STAT_STALLED_CYCLES_BACK,
-                                   ctx, cpu, count);
+                                   cpu, count, &rsd);
        else if (evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
-               update_runtime_stat(st, STAT_BRANCHES, ctx, cpu, count);
+               update_runtime_stat(st, STAT_BRANCHES, cpu, count, &rsd);
        else if (evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
-               update_runtime_stat(st, STAT_CACHEREFS, ctx, cpu, count);
+               update_runtime_stat(st, STAT_CACHEREFS, cpu, count, &rsd);
        else if (evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
-               update_runtime_stat(st, STAT_L1_DCACHE, ctx, cpu, count);
+               update_runtime_stat(st, STAT_L1_DCACHE, cpu, count, &rsd);
        else if (evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
-               update_runtime_stat(st, STAT_L1_ICACHE, ctx, cpu, count);
+               update_runtime_stat(st, STAT_L1_ICACHE, cpu, count, &rsd);
        else if (evsel__match(counter, HW_CACHE, HW_CACHE_LL))
-               update_runtime_stat(st, STAT_LL_CACHE, ctx, cpu, count);
+               update_runtime_stat(st, STAT_LL_CACHE, cpu, count, &rsd);
        else if (evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
-               update_runtime_stat(st, STAT_DTLB_CACHE, ctx, cpu, count);
+               update_runtime_stat(st, STAT_DTLB_CACHE, cpu, count, &rsd);
        else if (evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
-               update_runtime_stat(st, STAT_ITLB_CACHE, ctx, cpu, count);
+               update_runtime_stat(st, STAT_ITLB_CACHE, cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, SMI_NUM))
-               update_runtime_stat(st, STAT_SMI_NUM, ctx, cpu, count);
+               update_runtime_stat(st, STAT_SMI_NUM, cpu, count, &rsd);
        else if (perf_stat_evsel__is(counter, APERF))
-               update_runtime_stat(st, STAT_APERF, ctx, cpu, count);
+               update_runtime_stat(st, STAT_APERF, cpu, count, &rsd);
 
        if (counter->collect_stat) {
-               v = saved_value_lookup(counter, cpu, true, STAT_NONE, 0, st);
+               v = saved_value_lookup(counter, cpu, true, STAT_NONE, 0, st,
+                                      rsd.cgrp);
                update_stats(&v->stats, count);
                if (counter->metric_leader)
                        v->metric_total += count;
        } else if (counter->metric_leader) {
                v = saved_value_lookup(counter->metric_leader,
-                                      cpu, true, STAT_NONE, 0, st);
+                                      cpu, true, STAT_NONE, 0, st, rsd.cgrp);
                v->metric_total += count;
                v->metric_other++;
        }
@@ -422,11 +443,12 @@ void perf_stat__collect_metric_expr(struct evlist *evsel_list)
 }
 
 static double runtime_stat_avg(struct runtime_stat *st,
-                              enum stat_type type, int ctx, int cpu)
+                              enum stat_type type, int cpu,
+                              struct runtime_stat_data *rsd)
 {
        struct saved_value *v;
 
-       v = saved_value_lookup(NULL, cpu, false, type, ctx, st);
+       v = saved_value_lookup(NULL, cpu, false, type, rsd->ctx, st, rsd->cgrp);
        if (!v)
                return 0.0;
 
@@ -434,11 +456,12 @@ static double runtime_stat_avg(struct runtime_stat *st,
 }
 
 static double runtime_stat_n(struct runtime_stat *st,
-                            enum stat_type type, int ctx, int cpu)
+                            enum stat_type type, int cpu,
+                            struct runtime_stat_data *rsd)
 {
        struct saved_value *v;
 
-       v = saved_value_lookup(NULL, cpu, false, type, ctx, st);
+       v = saved_value_lookup(NULL, cpu, false, type, rsd->ctx, st, rsd->cgrp);
        if (!v)
                return 0.0;
 
@@ -446,16 +469,15 @@ static double runtime_stat_n(struct runtime_stat *st,
 }
 
 static void print_stalled_cycles_frontend(struct perf_stat_config *config,
-                                         int cpu,
-                                         struct evsel *evsel, double avg,
+                                         int cpu, double avg,
                                          struct perf_stat_output_ctx *out,
-                                         struct runtime_stat *st)
+                                         struct runtime_stat *st,
+                                         struct runtime_stat_data *rsd)
 {
        double total, ratio = 0.0;
        const char *color;
-       int ctx = evsel_context(evsel);
 
-       total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
+       total = runtime_stat_avg(st, STAT_CYCLES, cpu, rsd);
 
        if (total)
                ratio = avg / total * 100.0;
@@ -470,16 +492,15 @@ static void print_stalled_cycles_frontend(struct perf_stat_config *config,
 }
 
 static void print_stalled_cycles_backend(struct perf_stat_config *config,
-                                        int cpu,
-                                        struct evsel *evsel, double avg,
+                                        int cpu, double avg,
                                         struct perf_stat_output_ctx *out,
-                                        struct runtime_stat *st)
+                                        struct runtime_stat *st,
+                                        struct runtime_stat_data *rsd)
 {
        double total, ratio = 0.0;
        const char *color;
-       int ctx = evsel_context(evsel);
 
-       total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
+       total = runtime_stat_avg(st, STAT_CYCLES, cpu, rsd);
 
        if (total)
                ratio = avg / total * 100.0;
@@ -490,17 +511,15 @@ static void print_stalled_cycles_backend(struct perf_stat_config *config,
 }
 
 static void print_branch_misses(struct perf_stat_config *config,
-                               int cpu,
-                               struct evsel *evsel,
-                               double avg,
+                               int cpu, double avg,
                                struct perf_stat_output_ctx *out,
-                               struct runtime_stat *st)
+                               struct runtime_stat *st,
+                               struct runtime_stat_data *rsd)
 {
        double total, ratio = 0.0;
        const char *color;
-       int ctx = evsel_context(evsel);
 
-       total = runtime_stat_avg(st, STAT_BRANCHES, ctx, cpu);
+       total = runtime_stat_avg(st, STAT_BRANCHES, cpu, rsd);
 
        if (total)
                ratio = avg / total * 100.0;
@@ -511,18 +530,15 @@ static void print_branch_misses(struct perf_stat_config *config,
 }
 
 static void print_l1_dcache_misses(struct perf_stat_config *config,
-                                  int cpu,
-                                  struct evsel *evsel,
-                                  double avg,
+                                  int cpu, double avg,
                                   struct perf_stat_output_ctx *out,
-                                  struct runtime_stat *st)
-
+                                  struct runtime_stat *st,
+                                  struct runtime_stat_data *rsd)
 {
        double total, ratio = 0.0;
        const char *color;
-       int ctx = evsel_context(evsel);
 
-       total = runtime_stat_avg(st, STAT_L1_DCACHE, ctx, cpu);
+       total = runtime_stat_avg(st, STAT_L1_DCACHE, cpu, rsd);
 
        if (total)
                ratio = avg / total * 100.0;
@@ -533,18 +549,15 @@ static void print_l1_dcache_misses(struct perf_stat_config *config,
 }
 
 static void print_l1_icache_misses(struct perf_stat_config *config,
-                                  int cpu,
-                                  struct evsel *evsel,
-                                  double avg,
+                                  int cpu, double avg,
                                   struct perf_stat_output_ctx *out,
-                                  struct runtime_stat *st)
-
+                                  struct runtime_stat *st,
+                                  struct runtime_stat_data *rsd)
 {
        double total, ratio = 0.0;
        const char *color;
-       int ctx = evsel_context(evsel);
 
-       total = runtime_stat_avg(st, STAT_L1_ICACHE, ctx, cpu);
+       total = runtime_stat_avg(st, STAT_L1_ICACHE, cpu, rsd);
 
        if (total)
                ratio = avg / total * 100.0;
@@ -554,17 +567,15 @@ static void print_l1_icache_misses(struct perf_stat_config *config,
 }
 
 static void print_dtlb_cache_misses(struct perf_stat_config *config,
-                                   int cpu,
-                                   struct evsel *evsel,
-                                   double avg,
+                                   int cpu, double avg,
                                    struct perf_stat_output_ctx *out,
-                                   struct runtime_stat *st)
+                                   struct runtime_stat *st,
+                                   struct runtime_stat_data *rsd)
 {
        double total, ratio = 0.0;
        const char *color;
-       int ctx = evsel_context(evsel);
 
-       total = runtime_stat_avg(st, STAT_DTLB_CACHE, ctx, cpu);
+       total = runtime_stat_avg(st, STAT_DTLB_CACHE, cpu, rsd);
 
        if (total)
                ratio = avg / total * 100.0;
@@ -574,17 +585,15 @@ static void print_dtlb_cache_misses(struct perf_stat_config *config,
 }
 
 static void print_itlb_cache_misses(struct perf_stat_config *config,
-                                   int cpu,
-                                   struct evsel *evsel,
-                                   double avg,
+                                   int cpu, double avg,
                                    struct perf_stat_output_ctx *out,
-                                   struct runtime_stat *st)
+                                   struct runtime_stat *st,
+                                   struct runtime_stat_data *rsd)
 {
        double total, ratio = 0.0;
        const char *color;
-       int ctx = evsel_context(evsel);
 
-       total = runtime_stat_avg(st, STAT_ITLB_CACHE, ctx, cpu);
+       total = runtime_stat_avg(st, STAT_ITLB_CACHE, cpu, rsd);
 
        if (total)
                ratio = avg / total * 100.0;
@@ -594,17 +603,15 @@ static void print_itlb_cache_misses(struct perf_stat_config *config,
 }
 
 static void print_ll_cache_misses(struct perf_stat_config *config,
-                                 int cpu,
-                                 struct evsel *evsel,
-                                 double avg,
+                                 int cpu, double avg,
                                  struct perf_stat_output_ctx *out,
-                                 struct runtime_stat *st)
+                                 struct runtime_stat *st,
+                                 struct runtime_stat_data *rsd)
 {
        double total, ratio = 0.0;
        const char *color;
-       int ctx = evsel_context(evsel);
 
-       total = runtime_stat_avg(st, STAT_LL_CACHE, ctx, cpu);
+       total = runtime_stat_avg(st, STAT_LL_CACHE, cpu, rsd);
 
        if (total)
                ratio = avg / total * 100.0;
@@ -662,56 +669,61 @@ static double sanitize_val(double x)
        return x;
 }
 
-static double td_total_slots(int ctx, int cpu, struct runtime_stat *st)
+static double td_total_slots(int cpu, struct runtime_stat *st,
+                            struct runtime_stat_data *rsd)
 {
-       return runtime_stat_avg(st, STAT_TOPDOWN_TOTAL_SLOTS, ctx, cpu);
+       return runtime_stat_avg(st, STAT_TOPDOWN_TOTAL_SLOTS, cpu, rsd);
 }
 
-static double td_bad_spec(int ctx, int cpu, struct runtime_stat *st)
+static double td_bad_spec(int cpu, struct runtime_stat *st,
+                         struct runtime_stat_data *rsd)
 {
        double bad_spec = 0;
        double total_slots;
        double total;
 
-       total = runtime_stat_avg(st, STAT_TOPDOWN_SLOTS_ISSUED, ctx, cpu) -
-               runtime_stat_avg(st, STAT_TOPDOWN_SLOTS_RETIRED, ctx, cpu) +
-               runtime_stat_avg(st, STAT_TOPDOWN_RECOVERY_BUBBLES, ctx, cpu);
+       total = runtime_stat_avg(st, STAT_TOPDOWN_SLOTS_ISSUED, cpu, rsd) -
+               runtime_stat_avg(st, STAT_TOPDOWN_SLOTS_RETIRED, cpu, rsd) +
+               runtime_stat_avg(st, STAT_TOPDOWN_RECOVERY_BUBBLES, cpu, rsd);
 
-       total_slots = td_total_slots(ctx, cpu, st);
+       total_slots = td_total_slots(cpu, st, rsd);
        if (total_slots)
                bad_spec = total / total_slots;
        return sanitize_val(bad_spec);
 }
 
-static double td_retiring(int ctx, int cpu, struct runtime_stat *st)
+static double td_retiring(int cpu, struct runtime_stat *st,
+                         struct runtime_stat_data *rsd)
 {
        double retiring = 0;
-       double total_slots = td_total_slots(ctx, cpu, st);
+       double total_slots = td_total_slots(cpu, st, rsd);
        double ret_slots = runtime_stat_avg(st, STAT_TOPDOWN_SLOTS_RETIRED,
-                                           ctx, cpu);
+                                           cpu, rsd);
 
        if (total_slots)
                retiring = ret_slots / total_slots;
        return retiring;
 }
 
-static double td_fe_bound(int ctx, int cpu, struct runtime_stat *st)
+static double td_fe_bound(int cpu, struct runtime_stat *st,
+                         struct runtime_stat_data *rsd)
 {
        double fe_bound = 0;
-       double total_slots = td_total_slots(ctx, cpu, st);
+       double total_slots = td_total_slots(cpu, st, rsd);
        double fetch_bub = runtime_stat_avg(st, STAT_TOPDOWN_FETCH_BUBBLES,
-                                           ctx, cpu);
+                                           cpu, rsd);
 
        if (total_slots)
                fe_bound = fetch_bub / total_slots;
        return fe_bound;
 }
 
-static double td_be_bound(int ctx, int cpu, struct runtime_stat *st)
+static double td_be_bound(int cpu, struct runtime_stat *st,
+                         struct runtime_stat_data *rsd)
 {
-       double sum = (td_fe_bound(ctx, cpu, st) +
-                     td_bad_spec(ctx, cpu, st) +
-                     td_retiring(ctx, cpu, st));
+       double sum = (td_fe_bound(cpu, st, rsd) +
+                     td_bad_spec(cpu, st, rsd) +
+                     td_retiring(cpu, st, rsd));
        if (sum == 0)
                return 0;
        return sanitize_val(1.0 - sum);
@@ -722,15 +734,15 @@ static double td_be_bound(int ctx, int cpu, struct runtime_stat *st)
  * the ratios we need to recreate the sum.
  */
 
-static double td_metric_ratio(int ctx, int cpu,
-                             enum stat_type type,
-                             struct runtime_stat *stat)
+static double td_metric_ratio(int cpu, enum stat_type type,
+                             struct runtime_stat *stat,
+                             struct runtime_stat_data *rsd)
 {
-       double sum = runtime_stat_avg(stat, STAT_TOPDOWN_RETIRING, ctx, cpu) +
-               runtime_stat_avg(stat, STAT_TOPDOWN_FE_BOUND, ctx, cpu) +
-               runtime_stat_avg(stat, STAT_TOPDOWN_BE_BOUND, ctx, cpu) +
-               runtime_stat_avg(stat, STAT_TOPDOWN_BAD_SPEC, ctx, cpu);
-       double d = runtime_stat_avg(stat, type, ctx, cpu);
+       double sum = runtime_stat_avg(stat, STAT_TOPDOWN_RETIRING, cpu, rsd) +
+               runtime_stat_avg(stat, STAT_TOPDOWN_FE_BOUND, cpu, rsd) +
+               runtime_stat_avg(stat, STAT_TOPDOWN_BE_BOUND, cpu, rsd) +
+               runtime_stat_avg(stat, STAT_TOPDOWN_BAD_SPEC, cpu, rsd);
+       double d = runtime_stat_avg(stat, type, cpu, rsd);
 
        if (sum)
                return d / sum;
@@ -742,34 +754,33 @@ static double td_metric_ratio(int ctx, int cpu,
  * We allow two missing.
  */
 
-static bool full_td(int ctx, int cpu,
-                   struct runtime_stat *stat)
+static bool full_td(int cpu, struct runtime_stat *stat,
+                   struct runtime_stat_data *rsd)
 {
        int c = 0;
 
-       if (runtime_stat_avg(stat, STAT_TOPDOWN_RETIRING, ctx, cpu) > 0)
+       if (runtime_stat_avg(stat, STAT_TOPDOWN_RETIRING, cpu, rsd) > 0)
                c++;
-       if (runtime_stat_avg(stat, STAT_TOPDOWN_BE_BOUND, ctx, cpu) > 0)
+       if (runtime_stat_avg(stat, STAT_TOPDOWN_BE_BOUND, cpu, rsd) > 0)
                c++;
-       if (runtime_stat_avg(stat, STAT_TOPDOWN_FE_BOUND, ctx, cpu) > 0)
+       if (runtime_stat_avg(stat, STAT_TOPDOWN_FE_BOUND, cpu, rsd) > 0)
                c++;
-       if (runtime_stat_avg(stat, STAT_TOPDOWN_BAD_SPEC, ctx, cpu) > 0)
+       if (runtime_stat_avg(stat, STAT_TOPDOWN_BAD_SPEC, cpu, rsd) > 0)
                c++;
        return c >= 2;
 }
 
-static void print_smi_cost(struct perf_stat_config *config,
-                          int cpu, struct evsel *evsel,
+static void print_smi_cost(struct perf_stat_config *config, int cpu,
                           struct perf_stat_output_ctx *out,
-                          struct runtime_stat *st)
+                          struct runtime_stat *st,
+                          struct runtime_stat_data *rsd)
 {
        double smi_num, aperf, cycles, cost = 0.0;
-       int ctx = evsel_context(evsel);
        const char *color = NULL;
 
-       smi_num = runtime_stat_avg(st, STAT_SMI_NUM, ctx, cpu);
-       aperf = runtime_stat_avg(st, STAT_APERF, ctx, cpu);
-       cycles = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
+       smi_num = runtime_stat_avg(st, STAT_SMI_NUM, cpu, rsd);
+       aperf = runtime_stat_avg(st, STAT_APERF, cpu, rsd);
+       cycles = runtime_stat_avg(st, STAT_CYCLES, cpu, rsd);
 
        if ((cycles == 0) || (aperf == 0))
                return;
@@ -804,7 +815,8 @@ static int prepare_metric(struct evsel **metric_events,
                        scale = 1e-9;
                } else {
                        v = saved_value_lookup(metric_events[i], cpu, false,
-                                              STAT_NONE, 0, st);
+                                              STAT_NONE, 0, st,
+                                              metric_events[i]->cgrp);
                        if (!v)
                                break;
                        stats = &v->stats;
@@ -930,12 +942,15 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
        print_metric_t print_metric = out->print_metric;
        double total, ratio = 0.0, total2;
        const char *color = NULL;
-       int ctx = evsel_context(evsel);
+       struct runtime_stat_data rsd = {
+               .ctx = evsel_context(evsel),
+               .cgrp = evsel->cgrp,
+       };
        struct metric_event *me;
        int num = 1;
 
        if (evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
-               total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
+               total = runtime_stat_avg(st, STAT_CYCLES, cpu, &rsd);
 
                if (total) {
                        ratio = avg / total;
@@ -945,12 +960,11 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                        print_metric(config, ctxp, NULL, NULL, "insn per cycle", 0);
                }
 
-               total = runtime_stat_avg(st, STAT_STALLED_CYCLES_FRONT,
-                                        ctx, cpu);
+               total = runtime_stat_avg(st, STAT_STALLED_CYCLES_FRONT, cpu, &rsd);
 
                total = max(total, runtime_stat_avg(st,
                                                    STAT_STALLED_CYCLES_BACK,
-                                                   ctx, cpu));
+                                                   cpu, &rsd));
 
                if (total && avg) {
                        out->new_line(config, ctxp);
@@ -960,8 +974,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                        ratio);
                }
        } else if (evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) {
-               if (runtime_stat_n(st, STAT_BRANCHES, ctx, cpu) != 0)
-                       print_branch_misses(config, cpu, evsel, avg, out, st);
+               if (runtime_stat_n(st, STAT_BRANCHES, cpu, &rsd) != 0)
+                       print_branch_misses(config, cpu, avg, out, st, &rsd);
                else
                        print_metric(config, ctxp, NULL, NULL, "of all branches", 0);
        } else if (
@@ -970,8 +984,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                        ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
                                         ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
-               if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0)
-                       print_l1_dcache_misses(config, cpu, evsel, avg, out, st);
+               if (runtime_stat_n(st, STAT_L1_DCACHE, cpu, &rsd) != 0)
+                       print_l1_dcache_misses(config, cpu, avg, out, st, &rsd);
                else
                        print_metric(config, ctxp, NULL, NULL, "of all L1-dcache accesses", 0);
        } else if (
@@ -980,8 +994,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                        ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
                                         ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
-               if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0)
-                       print_l1_icache_misses(config, cpu, evsel, avg, out, st);
+               if (runtime_stat_n(st, STAT_L1_ICACHE, cpu, &rsd) != 0)
+                       print_l1_icache_misses(config, cpu, avg, out, st, &rsd);
                else
                        print_metric(config, ctxp, NULL, NULL, "of all L1-icache accesses", 0);
        } else if (
@@ -990,8 +1004,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                        ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
                                         ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
-               if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0)
-                       print_dtlb_cache_misses(config, cpu, evsel, avg, out, st);
+               if (runtime_stat_n(st, STAT_DTLB_CACHE, cpu, &rsd) != 0)
+                       print_dtlb_cache_misses(config, cpu, avg, out, st, &rsd);
                else
                        print_metric(config, ctxp, NULL, NULL, "of all dTLB cache accesses", 0);
        } else if (
@@ -1000,8 +1014,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                        ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
                                         ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
-               if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0)
-                       print_itlb_cache_misses(config, cpu, evsel, avg, out, st);
+               if (runtime_stat_n(st, STAT_ITLB_CACHE, cpu, &rsd) != 0)
+                       print_itlb_cache_misses(config, cpu, avg, out, st, &rsd);
                else
                        print_metric(config, ctxp, NULL, NULL, "of all iTLB cache accesses", 0);
        } else if (
@@ -1010,27 +1024,27 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                        ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
                                         ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
-               if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0)
-                       print_ll_cache_misses(config, cpu, evsel, avg, out, st);
+               if (runtime_stat_n(st, STAT_LL_CACHE, cpu, &rsd) != 0)
+                       print_ll_cache_misses(config, cpu, avg, out, st, &rsd);
                else
                        print_metric(config, ctxp, NULL, NULL, "of all LL-cache accesses", 0);
        } else if (evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) {
-               total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu);
+               total = runtime_stat_avg(st, STAT_CACHEREFS, cpu, &rsd);
 
                if (total)
                        ratio = avg * 100 / total;
 
-               if (runtime_stat_n(st, STAT_CACHEREFS, ctx, cpu) != 0)
+               if (runtime_stat_n(st, STAT_CACHEREFS, cpu, &rsd) != 0)
                        print_metric(config, ctxp, NULL, "%8.3f %%",
                                     "of all cache refs", ratio);
                else
                        print_metric(config, ctxp, NULL, NULL, "of all cache refs", 0);
        } else if (evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
-               print_stalled_cycles_frontend(config, cpu, evsel, avg, out, st);
+               print_stalled_cycles_frontend(config, cpu, avg, out, st, &rsd);
        } else if (evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
-               print_stalled_cycles_backend(config, cpu, evsel, avg, out, st);
+               print_stalled_cycles_backend(config, cpu, avg, out, st, &rsd);
        } else if (evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
-               total = runtime_stat_avg(st, STAT_NSECS, 0, cpu);
+               total = runtime_stat_avg(st, STAT_NSECS, cpu, &rsd);
 
                if (total) {
                        ratio = avg / total;
@@ -1039,7 +1053,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                        print_metric(config, ctxp, NULL, NULL, "Ghz", 0);
                }
        } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) {
-               total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
+               total = runtime_stat_avg(st, STAT_CYCLES, cpu, &rsd);
 
                if (total)
                        print_metric(config, ctxp, NULL,
@@ -1049,8 +1063,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                        print_metric(config, ctxp, NULL, NULL, "transactional cycles",
                                     0);
        } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) {
-               total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
-               total2 = runtime_stat_avg(st, STAT_CYCLES_IN_TX, ctx, cpu);
+               total = runtime_stat_avg(st, STAT_CYCLES, cpu, &rsd);
+               total2 = runtime_stat_avg(st, STAT_CYCLES_IN_TX, cpu, &rsd);
 
                if (total2 < avg)
                        total2 = avg;
@@ -1060,21 +1074,19 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                else
                        print_metric(config, ctxp, NULL, NULL, "aborted cycles", 0);
        } else if (perf_stat_evsel__is(evsel, TRANSACTION_START)) {
-               total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
-                                        ctx, cpu);
+               total = runtime_stat_avg(st, STAT_CYCLES_IN_TX, cpu, &rsd);
 
                if (avg)
                        ratio = total / avg;
 
-               if (runtime_stat_n(st, STAT_CYCLES_IN_TX, ctx, cpu) != 0)
+               if (runtime_stat_n(st, STAT_CYCLES_IN_TX, cpu, &rsd) != 0)
                        print_metric(config, ctxp, NULL, "%8.0f",
                                     "cycles / transaction", ratio);
                else
                        print_metric(config, ctxp, NULL, NULL, "cycles / transaction",
                                      0);
        } else if (perf_stat_evsel__is(evsel, ELISION_START)) {
-               total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
-                                        ctx, cpu);
+               total = runtime_stat_avg(st, STAT_CYCLES_IN_TX, cpu, &rsd);
 
                if (avg)
                        ratio = total / avg;
@@ -1087,28 +1099,28 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                else
                        print_metric(config, ctxp, NULL, NULL, "CPUs utilized", 0);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) {
-               double fe_bound = td_fe_bound(ctx, cpu, st);
+               double fe_bound = td_fe_bound(cpu, st, &rsd);
 
                if (fe_bound > 0.2)
                        color = PERF_COLOR_RED;
                print_metric(config, ctxp, color, "%8.1f%%", "frontend bound",
                                fe_bound * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) {
-               double retiring = td_retiring(ctx, cpu, st);
+               double retiring = td_retiring(cpu, st, &rsd);
 
                if (retiring > 0.7)
                        color = PERF_COLOR_GREEN;
                print_metric(config, ctxp, color, "%8.1f%%", "retiring",
                                retiring * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) {
-               double bad_spec = td_bad_spec(ctx, cpu, st);
+               double bad_spec = td_bad_spec(cpu, st, &rsd);
 
                if (bad_spec > 0.1)
                        color = PERF_COLOR_RED;
                print_metric(config, ctxp, color, "%8.1f%%", "bad speculation",
                                bad_spec * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) {
-               double be_bound = td_be_bound(ctx, cpu, st);
+               double be_bound = td_be_bound(cpu, st, &rsd);
                const char *name = "backend bound";
                static int have_recovery_bubbles = -1;
 
@@ -1121,43 +1133,43 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
 
                if (be_bound > 0.2)
                        color = PERF_COLOR_RED;
-               if (td_total_slots(ctx, cpu, st) > 0)
+               if (td_total_slots(cpu, st, &rsd) > 0)
                        print_metric(config, ctxp, color, "%8.1f%%", name,
                                        be_bound * 100.);
                else
                        print_metric(config, ctxp, NULL, NULL, name, 0);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_RETIRING) &&
-                       full_td(ctx, cpu, st)) {
-               double retiring = td_metric_ratio(ctx, cpu,
-                                                 STAT_TOPDOWN_RETIRING, st);
-
+                  full_td(cpu, st, &rsd)) {
+               double retiring = td_metric_ratio(cpu,
+                                                 STAT_TOPDOWN_RETIRING, st,
+                                                 &rsd);
                if (retiring > 0.7)
                        color = PERF_COLOR_GREEN;
                print_metric(config, ctxp, color, "%8.1f%%", "retiring",
                                retiring * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_FE_BOUND) &&
-                       full_td(ctx, cpu, st)) {
-               double fe_bound = td_metric_ratio(ctx, cpu,
-                                                 STAT_TOPDOWN_FE_BOUND, st);
-
+                  full_td(cpu, st, &rsd)) {
+               double fe_bound = td_metric_ratio(cpu,
+                                                 STAT_TOPDOWN_FE_BOUND, st,
+                                                 &rsd);
                if (fe_bound > 0.2)
                        color = PERF_COLOR_RED;
                print_metric(config, ctxp, color, "%8.1f%%", "frontend bound",
                                fe_bound * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_BE_BOUND) &&
-                       full_td(ctx, cpu, st)) {
-               double be_bound = td_metric_ratio(ctx, cpu,
-                                                 STAT_TOPDOWN_BE_BOUND, st);
-
+                  full_td(cpu, st, &rsd)) {
+               double be_bound = td_metric_ratio(cpu,
+                                                 STAT_TOPDOWN_BE_BOUND, st,
+                                                 &rsd);
                if (be_bound > 0.2)
                        color = PERF_COLOR_RED;
                print_metric(config, ctxp, color, "%8.1f%%", "backend bound",
                                be_bound * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_BAD_SPEC) &&
-                       full_td(ctx, cpu, st)) {
-               double bad_spec = td_metric_ratio(ctx, cpu,
-                                                 STAT_TOPDOWN_BAD_SPEC, st);
-
+                  full_td(cpu, st, &rsd)) {
+               double bad_spec = td_metric_ratio(cpu,
+                                                 STAT_TOPDOWN_BAD_SPEC, st,
+                                                 &rsd);
                if (bad_spec > 0.1)
                        color = PERF_COLOR_RED;
                print_metric(config, ctxp, color, "%8.1f%%", "bad speculation",
@@ -1165,11 +1177,11 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
        } else if (evsel->metric_expr) {
                generic_metric(config, evsel->metric_expr, evsel->metric_events, NULL,
                                evsel->name, evsel->metric_name, NULL, 1, cpu, out, st);
-       } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) {
+       } else if (runtime_stat_n(st, STAT_NSECS, cpu, &rsd) != 0) {
                char unit = 'M';
                char unit_buf[10];
 
-               total = runtime_stat_avg(st, STAT_NSECS, 0, cpu);
+               total = runtime_stat_avg(st, STAT_NSECS, cpu, &rsd);
 
                if (total)
                        ratio = 1000.0 * avg / total;
@@ -1180,7 +1192,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
                print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio);
        } else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
-               print_smi_cost(config, cpu, evsel, out, st);
+               print_smi_cost(config, cpu, out, st, &rsd);
        } else {
                num = 0;
        }
index 5390158cdb401ebbfa7940118827c58382559a2c..09cb3a6672f3e45061c6332301f9178435b1ad43 100644 (file)
@@ -1249,6 +1249,8 @@ static void dump_isst_config(int arg)
        isst_ctdp_display_information_end(outf);
 }
 
+static void adjust_scaling_max_from_base_freq(int cpu);
+
 static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
                                  void *arg4)
 {
@@ -1267,6 +1269,9 @@ static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
                        int pkg_id = get_physical_package_id(cpu);
                        int die_id = get_physical_die_id(cpu);
 
+                       /* Wait for updated base frequencies */
+                       usleep(2000);
+
                        fprintf(stderr, "Option is set to online/offline\n");
                        ctdp_level.core_cpumask_size =
                                alloc_cpu_set(&ctdp_level.core_cpumask);
@@ -1283,6 +1288,7 @@ static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
                                        if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
                                                fprintf(stderr, "online cpu %d\n", i);
                                                set_cpu_online_offline(i, 1);
+                                               adjust_scaling_max_from_base_freq(i);
                                        } else {
                                                fprintf(stderr, "offline cpu %d\n", i);
                                                set_cpu_online_offline(i, 0);
@@ -1440,6 +1446,31 @@ static int set_cpufreq_scaling_min_max(int cpu, int max, int freq)
        return 0;
 }
 
+static int no_turbo(void)
+{
+       return parse_int_file(0, "/sys/devices/system/cpu/intel_pstate/no_turbo");
+}
+
+static void adjust_scaling_max_from_base_freq(int cpu)
+{
+       int base_freq, scaling_max_freq;
+
+       scaling_max_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
+       base_freq = get_cpufreq_base_freq(cpu);
+       if (scaling_max_freq < base_freq || no_turbo())
+               set_cpufreq_scaling_min_max(cpu, 1, base_freq);
+}
+
+static void adjust_scaling_min_from_base_freq(int cpu)
+{
+       int base_freq, scaling_min_freq;
+
+       scaling_min_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
+       base_freq = get_cpufreq_base_freq(cpu);
+       if (scaling_min_freq < base_freq)
+               set_cpufreq_scaling_min_max(cpu, 0, base_freq);
+}
+
 static int set_clx_pbf_cpufreq_scaling_min_max(int cpu)
 {
        struct isst_pkg_ctdp_level_info *ctdp_level;
@@ -1537,6 +1568,7 @@ static void set_scaling_min_to_cpuinfo_max(int cpu)
                        continue;
 
                set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 0);
+               adjust_scaling_min_from_base_freq(i);
        }
 }
 
index 21516e293d1711462af704366f7e1b8512325e44..e808a47c839bf6131f22debd2936f42bc9fdae27 100755 (executable)
@@ -43,9 +43,9 @@ class KunitStatus(Enum):
        BUILD_FAILURE = auto()
        TEST_FAILURE = auto()
 
-def get_kernel_root_path():
-       parts = sys.argv[0] if not __file__ else __file__
-       parts = os.path.realpath(parts).split('tools/testing/kunit')
+def get_kernel_root_path() -> str:
+       path = sys.argv[0] if not __file__ else __file__
+       parts = os.path.realpath(path).split('tools/testing/kunit')
        if len(parts) != 2:
                sys.exit(1)
        return parts[0]
@@ -171,7 +171,7 @@ def run_tests(linux: kunit_kernel.LinuxSourceTree,
                                exec_result.elapsed_time))
        return parse_result
 
-def add_common_opts(parser):
+def add_common_opts(parser) -> None:
        parser.add_argument('--build_dir',
                            help='As in the make command, it specifies the build '
                            'directory.',
@@ -183,13 +183,13 @@ def add_common_opts(parser):
                            help='Run all KUnit tests through allyesconfig',
                            action='store_true')
 
-def add_build_opts(parser):
+def add_build_opts(parser) -> None:
        parser.add_argument('--jobs',
                            help='As in the make command, "Specifies  the number of '
                            'jobs (commands) to run simultaneously."',
                            type=int, default=8, metavar='jobs')
 
-def add_exec_opts(parser):
+def add_exec_opts(parser) -> None:
        parser.add_argument('--timeout',
                            help='maximum number of seconds to allow for all tests '
                            'to run. This does not include time taken to build the '
@@ -198,7 +198,7 @@ def add_exec_opts(parser):
                            default=300,
                            metavar='timeout')
 
-def add_parse_opts(parser):
+def add_parse_opts(parser) -> None:
        parser.add_argument('--raw_output', help='don\'t format output from kernel',
                            action='store_true')
        parser.add_argument('--json',
@@ -256,10 +256,7 @@ def main(argv, linux=None):
                        os.mkdir(cli_args.build_dir)
 
                if not linux:
-                       linux = kunit_kernel.LinuxSourceTree()
-
-               linux.create_kunitconfig(cli_args.build_dir)
-               linux.read_kunitconfig(cli_args.build_dir)
+                       linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir)
 
                request = KunitRequest(cli_args.raw_output,
                                       cli_args.timeout,
@@ -277,10 +274,7 @@ def main(argv, linux=None):
                        os.mkdir(cli_args.build_dir)
 
                if not linux:
-                       linux = kunit_kernel.LinuxSourceTree()
-
-               linux.create_kunitconfig(cli_args.build_dir)
-               linux.read_kunitconfig(cli_args.build_dir)
+                       linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir)
 
                request = KunitConfigRequest(cli_args.build_dir,
                                             cli_args.make_options)
@@ -292,10 +286,7 @@ def main(argv, linux=None):
                        sys.exit(1)
        elif cli_args.subcommand == 'build':
                if not linux:
-                       linux = kunit_kernel.LinuxSourceTree()
-
-               linux.create_kunitconfig(cli_args.build_dir)
-               linux.read_kunitconfig(cli_args.build_dir)
+                       linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir)
 
                request = KunitBuildRequest(cli_args.jobs,
                                            cli_args.build_dir,
@@ -309,10 +300,7 @@ def main(argv, linux=None):
                        sys.exit(1)
        elif cli_args.subcommand == 'exec':
                if not linux:
-                       linux = kunit_kernel.LinuxSourceTree()
-
-               linux.create_kunitconfig(cli_args.build_dir)
-               linux.read_kunitconfig(cli_args.build_dir)
+                       linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir)
 
                exec_request = KunitExecRequest(cli_args.timeout,
                                                cli_args.build_dir,
index 02ffc3a3e5dc7f4b85156de813460ee89847fa61..bdd60230764b02fe120a01942e49ebf0983af592 100644 (file)
@@ -8,6 +8,7 @@
 
 import collections
 import re
+from typing import List, Set
 
 CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_(\w+) is not set$'
 CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+|".*")$'
@@ -30,10 +31,10 @@ class KconfigParseError(Exception):
 class Kconfig(object):
        """Represents defconfig or .config specified using the Kconfig language."""
 
-       def __init__(self):
-               self._entries = []
+       def __init__(self) -> None:
+               self._entries = []  # type: List[KconfigEntry]
 
-       def entries(self):
+       def entries(self) -> Set[KconfigEntry]:
                return set(self._entries)
 
        def add_entry(self, entry: KconfigEntry) -> None:
index 624b31b2dbd620cf1fb8bf6e301d517d55c2ee5a..f5cca5c38cacfc6617de2bf931b6ca2bfb7c185d 100644 (file)
@@ -13,7 +13,7 @@ import kunit_parser
 
 from kunit_parser import TestStatus
 
-def get_json_result(test_result, def_config, build_dir, json_path):
+def get_json_result(test_result, def_config, build_dir, json_path) -> str:
        sub_groups = []
 
        # Each test suite is mapped to a KernelCI sub_group
index 698358c9c0d60951eade09cc50e012a00a8eb446..2076a5a2d060a680793b24fb15c09ec2ed80cb1b 100644 (file)
@@ -11,6 +11,7 @@ import subprocess
 import os
 import shutil
 import signal
+from typing import Iterator
 
 from contextlib import ExitStack
 
@@ -39,7 +40,7 @@ class BuildError(Exception):
 class LinuxSourceTreeOperations(object):
        """An abstraction over command line operations performed on a source tree."""
 
-       def make_mrproper(self):
+       def make_mrproper(self) -> None:
                try:
                        subprocess.check_output(['make', 'mrproper'], stderr=subprocess.STDOUT)
                except OSError as e:
@@ -47,7 +48,7 @@ class LinuxSourceTreeOperations(object):
                except subprocess.CalledProcessError as e:
                        raise ConfigError(e.output.decode())
 
-       def make_olddefconfig(self, build_dir, make_options):
+       def make_olddefconfig(self, build_dir, make_options) -> None:
                command = ['make', 'ARCH=um', 'olddefconfig']
                if make_options:
                        command.extend(make_options)
@@ -60,7 +61,7 @@ class LinuxSourceTreeOperations(object):
                except subprocess.CalledProcessError as e:
                        raise ConfigError(e.output.decode())
 
-       def make_allyesconfig(self, build_dir, make_options):
+       def make_allyesconfig(self, build_dir, make_options) -> None:
                kunit_parser.print_with_timestamp(
                        'Enabling all CONFIGs for UML...')
                command = ['make', 'ARCH=um', 'allyesconfig']
@@ -82,7 +83,7 @@ class LinuxSourceTreeOperations(object):
                kunit_parser.print_with_timestamp(
                        'Starting Kernel with all configs takes a few minutes...')
 
-       def make(self, jobs, build_dir, make_options):
+       def make(self, jobs, build_dir, make_options) -> None:
                command = ['make', 'ARCH=um', '--jobs=' + str(jobs)]
                if make_options:
                        command.extend(make_options)
@@ -100,7 +101,7 @@ class LinuxSourceTreeOperations(object):
                if stderr:  # likely only due to build warnings
                        print(stderr.decode())
 
-       def linux_bin(self, params, timeout, build_dir):
+       def linux_bin(self, params, timeout, build_dir) -> None:
                """Runs the Linux UML binary. Must be named 'linux'."""
                linux_bin = get_file_path(build_dir, 'linux')
                outfile = get_outfile_path(build_dir)
@@ -110,41 +111,42 @@ class LinuxSourceTreeOperations(object):
                                                   stderr=subprocess.STDOUT)
                        process.wait(timeout)
 
-def get_kconfig_path(build_dir):
+def get_kconfig_path(build_dir) -> str:
        return get_file_path(build_dir, KCONFIG_PATH)
 
-def get_kunitconfig_path(build_dir):
+def get_kunitconfig_path(build_dir) -> str:
        return get_file_path(build_dir, KUNITCONFIG_PATH)
 
-def get_outfile_path(build_dir):
+def get_outfile_path(build_dir) -> str:
        return get_file_path(build_dir, OUTFILE_PATH)
 
 class LinuxSourceTree(object):
        """Represents a Linux kernel source tree with KUnit tests."""
 
-       def __init__(self):
-               self._ops = LinuxSourceTreeOperations()
+       def __init__(self, build_dir: str, load_config=True, defconfig=DEFAULT_KUNITCONFIG_PATH) -> None:
                signal.signal(signal.SIGINT, self.signal_handler)
 
-       def clean(self):
-               try:
-                       self._ops.make_mrproper()
-               except ConfigError as e:
-                       logging.error(e)
-                       return False
-               return True
+               self._ops = LinuxSourceTreeOperations()
+
+               if not load_config:
+                       return
 
-       def create_kunitconfig(self, build_dir, defconfig=DEFAULT_KUNITCONFIG_PATH):
                kunitconfig_path = get_kunitconfig_path(build_dir)
                if not os.path.exists(kunitconfig_path):
                        shutil.copyfile(defconfig, kunitconfig_path)
 
-       def read_kunitconfig(self, build_dir):
-               kunitconfig_path = get_kunitconfig_path(build_dir)
                self._kconfig = kunit_config.Kconfig()
                self._kconfig.read_from_file(kunitconfig_path)
 
-       def validate_config(self, build_dir):
+       def clean(self) -> bool:
+               try:
+                       self._ops.make_mrproper()
+               except ConfigError as e:
+                       logging.error(e)
+                       return False
+               return True
+
+       def validate_config(self, build_dir) -> bool:
                kconfig_path = get_kconfig_path(build_dir)
                validated_kconfig = kunit_config.Kconfig()
                validated_kconfig.read_from_file(kconfig_path)
@@ -158,7 +160,7 @@ class LinuxSourceTree(object):
                        return False
                return True
 
-       def build_config(self, build_dir, make_options):
+       def build_config(self, build_dir, make_options) -> bool:
                kconfig_path = get_kconfig_path(build_dir)
                if build_dir and not os.path.exists(build_dir):
                        os.mkdir(build_dir)
@@ -170,7 +172,7 @@ class LinuxSourceTree(object):
                        return False
                return self.validate_config(build_dir)
 
-       def build_reconfig(self, build_dir, make_options):
+       def build_reconfig(self, build_dir, make_options) -> bool:
                """Creates a new .config if it is not a subset of the .kunitconfig."""
                kconfig_path = get_kconfig_path(build_dir)
                if os.path.exists(kconfig_path):
@@ -186,7 +188,7 @@ class LinuxSourceTree(object):
                        print('Generating .config ...')
                        return self.build_config(build_dir, make_options)
 
-       def build_um_kernel(self, alltests, jobs, build_dir, make_options):
+       def build_um_kernel(self, alltests, jobs, build_dir, make_options) -> bool:
                try:
                        if alltests:
                                self._ops.make_allyesconfig(build_dir, make_options)
@@ -197,7 +199,7 @@ class LinuxSourceTree(object):
                        return False
                return self.validate_config(build_dir)
 
-       def run_kernel(self, args=[], build_dir='', timeout=None):
+       def run_kernel(self, args=[], build_dir='', timeout=None) -> Iterator[str]:
                args.extend(['mem=1G', 'console=tty'])
                self._ops.linux_bin(args, timeout, build_dir)
                outfile = get_outfile_path(build_dir)
@@ -206,6 +208,6 @@ class LinuxSourceTree(object):
                        for line in file:
                                yield line
 
-       def signal_handler(self, sig, frame):
+       def signal_handler(self, sig, frame) -> None:
                logging.error('Build interruption occurred. Cleaning console.')
                subprocess.call(['stty', 'sane'])
index 6614ec4d08989696b82cc67c1b8c3a92707da740..e8bcc139702e29da713a5275624c9b1693fa91eb 100644 (file)
@@ -12,32 +12,32 @@ from collections import namedtuple
 from datetime import datetime
 from enum import Enum, auto
 from functools import reduce
-from typing import List, Optional, Tuple
+from typing import Iterable, Iterator, List, Optional, Tuple
 
 TestResult = namedtuple('TestResult', ['status','suites','log'])
 
 class TestSuite(object):
-       def __init__(self):
-               self.status = None
-               self.name = None
-               self.cases = []
+       def __init__(self) -> None:
+               self.status = TestStatus.SUCCESS
+               self.name = ''
+               self.cases = []  # type: List[TestCase]
 
-       def __str__(self):
-               return 'TestSuite(' + self.status + ',' + self.name + ',' + str(self.cases) + ')'
+       def __str__(self) -> str:
+               return 'TestSuite(' + str(self.status) + ',' + self.name + ',' + str(self.cases) + ')'
 
-       def __repr__(self):
+       def __repr__(self) -> str:
                return str(self)
 
 class TestCase(object):
-       def __init__(self):
-               self.status = None
+       def __init__(self) -> None:
+               self.status = TestStatus.SUCCESS
                self.name = ''
-               self.log = []
+               self.log = []  # type: List[str]
 
-       def __str__(self):
-               return 'TestCase(' + self.status + ',' + self.name + ',' + str(self.log) + ')'
+       def __str__(self) -> str:
+               return 'TestCase(' + str(self.status) + ',' + self.name + ',' + str(self.log) + ')'
 
-       def __repr__(self):
+       def __repr__(self) -> str:
                return str(self)
 
 class TestStatus(Enum):
@@ -51,7 +51,7 @@ kunit_start_re = re.compile(r'TAP version [0-9]+$')
 kunit_end_re = re.compile('(List of all partitions:|'
                          'Kernel panic - not syncing: VFS:)')
 
-def isolate_kunit_output(kernel_output):
+def isolate_kunit_output(kernel_output) -> Iterator[str]:
        started = False
        for line in kernel_output:
                line = line.rstrip()  # line always has a trailing \n
@@ -64,7 +64,7 @@ def isolate_kunit_output(kernel_output):
                elif started:
                        yield line[prefix_len:] if prefix_len > 0 else line
 
-def raw_output(kernel_output):
+def raw_output(kernel_output) -> None:
        for line in kernel_output:
                print(line.rstrip())
 
@@ -72,36 +72,36 @@ DIVIDER = '=' * 60
 
 RESET = '\033[0;0m'
 
-def red(text):
+def red(text) -> str:
        return '\033[1;31m' + text + RESET
 
-def yellow(text):
+def yellow(text) -> str:
        return '\033[1;33m' + text + RESET
 
-def green(text):
+def green(text) -> str:
        return '\033[1;32m' + text + RESET
 
-def print_with_timestamp(message):
+def print_with_timestamp(message) -> None:
        print('[%s] %s' % (datetime.now().strftime('%H:%M:%S'), message))
 
-def format_suite_divider(message):
+def format_suite_divider(message) -> str:
        return '======== ' + message + ' ========'
 
-def print_suite_divider(message):
+def print_suite_divider(message) -> None:
        print_with_timestamp(DIVIDER)
        print_with_timestamp(format_suite_divider(message))
 
-def print_log(log):
+def print_log(log) -> None:
        for m in log:
                print_with_timestamp(m)
 
 TAP_ENTRIES = re.compile(r'^(TAP|[\s]*ok|[\s]*not ok|[\s]*[0-9]+\.\.[0-9]+|[\s]*#).*$')
 
-def consume_non_diagnositic(lines: List[str]) -> None:
+def consume_non_diagnostic(lines: List[str]) -> None:
        while lines and not TAP_ENTRIES.match(lines[0]):
                lines.pop(0)
 
-def save_non_diagnositic(lines: List[str], test_case: TestCase) -> None:
+def save_non_diagnostic(lines: List[str], test_case: TestCase) -> None:
        while lines and not TAP_ENTRIES.match(lines[0]):
                test_case.log.append(lines[0])
                lines.pop(0)
@@ -113,7 +113,7 @@ OK_NOT_OK_SUBTEST = re.compile(r'^[\s]+(ok|not ok) [0-9]+ - (.*)$')
 OK_NOT_OK_MODULE = re.compile(r'^(ok|not ok) ([0-9]+) - (.*)$')
 
 def parse_ok_not_ok_test_case(lines: List[str], test_case: TestCase) -> bool:
-       save_non_diagnositic(lines, test_case)
+       save_non_diagnostic(lines, test_case)
        if not lines:
                test_case.status = TestStatus.TEST_CRASHED
                return True
@@ -139,7 +139,7 @@ SUBTEST_DIAGNOSTIC = re.compile(r'^[\s]+# (.*)$')
 DIAGNOSTIC_CRASH_MESSAGE = re.compile(r'^[\s]+# .*?: kunit test case crashed!$')
 
 def parse_diagnostic(lines: List[str], test_case: TestCase) -> bool:
-       save_non_diagnositic(lines, test_case)
+       save_non_diagnostic(lines, test_case)
        if not lines:
                return False
        line = lines[0]
@@ -155,7 +155,7 @@ def parse_diagnostic(lines: List[str], test_case: TestCase) -> bool:
 
 def parse_test_case(lines: List[str]) -> Optional[TestCase]:
        test_case = TestCase()
-       save_non_diagnositic(lines, test_case)
+       save_non_diagnostic(lines, test_case)
        while parse_diagnostic(lines, test_case):
                pass
        if parse_ok_not_ok_test_case(lines, test_case):
@@ -166,7 +166,7 @@ def parse_test_case(lines: List[str]) -> Optional[TestCase]:
 SUBTEST_HEADER = re.compile(r'^[\s]+# Subtest: (.*)$')
 
 def parse_subtest_header(lines: List[str]) -> Optional[str]:
-       consume_non_diagnositic(lines)
+       consume_non_diagnostic(lines)
        if not lines:
                return None
        match = SUBTEST_HEADER.match(lines[0])
@@ -179,7 +179,7 @@ def parse_subtest_header(lines: List[str]) -> Optional[str]:
 SUBTEST_PLAN = re.compile(r'[\s]+[0-9]+\.\.([0-9]+)')
 
 def parse_subtest_plan(lines: List[str]) -> Optional[int]:
-       consume_non_diagnositic(lines)
+       consume_non_diagnostic(lines)
        match = SUBTEST_PLAN.match(lines[0])
        if match:
                lines.pop(0)
@@ -202,7 +202,7 @@ def max_status(left: TestStatus, right: TestStatus) -> TestStatus:
 def parse_ok_not_ok_test_suite(lines: List[str],
                               test_suite: TestSuite,
                               expected_suite_index: int) -> bool:
-       consume_non_diagnositic(lines)
+       consume_non_diagnostic(lines)
        if not lines:
                test_suite.status = TestStatus.TEST_CRASHED
                return False
@@ -224,18 +224,17 @@ def parse_ok_not_ok_test_suite(lines: List[str],
        else:
                return False
 
-def bubble_up_errors(to_status, status_container_list) -> TestStatus:
-       status_list = map(to_status, status_container_list)
-       return reduce(max_status, status_list, TestStatus.SUCCESS)
+def bubble_up_errors(statuses: Iterable[TestStatus]) -> TestStatus:
+       return reduce(max_status, statuses, TestStatus.SUCCESS)
 
 def bubble_up_test_case_errors(test_suite: TestSuite) -> TestStatus:
-       max_test_case_status = bubble_up_errors(lambda x: x.status, test_suite.cases)
+       max_test_case_status = bubble_up_errors(x.status for x in test_suite.cases)
        return max_status(max_test_case_status, test_suite.status)
 
 def parse_test_suite(lines: List[str], expected_suite_index: int) -> Optional[TestSuite]:
        if not lines:
                return None
-       consume_non_diagnositic(lines)
+       consume_non_diagnostic(lines)
        test_suite = TestSuite()
        test_suite.status = TestStatus.SUCCESS
        name = parse_subtest_header(lines)
@@ -264,7 +263,7 @@ def parse_test_suite(lines: List[str], expected_suite_index: int) -> Optional[Te
 TAP_HEADER = re.compile(r'^TAP version 14$')
 
 def parse_tap_header(lines: List[str]) -> bool:
-       consume_non_diagnositic(lines)
+       consume_non_diagnostic(lines)
        if TAP_HEADER.match(lines[0]):
                lines.pop(0)
                return True
@@ -274,7 +273,7 @@ def parse_tap_header(lines: List[str]) -> bool:
 TEST_PLAN = re.compile(r'[0-9]+\.\.([0-9]+)')
 
 def parse_test_plan(lines: List[str]) -> Optional[int]:
-       consume_non_diagnositic(lines)
+       consume_non_diagnostic(lines)
        match = TEST_PLAN.match(lines[0])
        if match:
                lines.pop(0)
@@ -282,11 +281,11 @@ def parse_test_plan(lines: List[str]) -> Optional[int]:
        else:
                return None
 
-def bubble_up_suite_errors(test_suite_list: List[TestSuite]) -> TestStatus:
-       return bubble_up_errors(lambda x: x.status, test_suite_list)
+def bubble_up_suite_errors(test_suites: Iterable[TestSuite]) -> TestStatus:
+       return bubble_up_errors(x.status for x in test_suites)
 
 def parse_test_result(lines: List[str]) -> TestResult:
-       consume_non_diagnositic(lines)
+       consume_non_diagnostic(lines)
        if not lines or not parse_tap_header(lines):
                return TestResult(TestStatus.NO_TESTS, [], lines)
        expected_test_suite_num = parse_test_plan(lines)
index afbab4aeef3c894546e95d44f9d9e539e50ae945..8a917cb4426a05e30f718764485025ffab99ed39 100644 (file)
@@ -77,8 +77,10 @@ TARGETS += zram
 TARGETS_HOTPLUG = cpu-hotplug
 TARGETS_HOTPLUG += memory-hotplug
 
-# User can optionally provide a TARGETS skiplist.
-SKIP_TARGETS ?=
+# User can optionally provide a TARGETS skiplist.  By default we skip
+# BPF since it has cutting edge build time dependencies which require
+# more effort to install.
+SKIP_TARGETS ?= bpf
 ifneq ($(SKIP_TARGETS),)
        TMP := $(filter-out $(SKIP_TARGETS), $(TARGETS))
        override TARGETS := $(TMP)
index 1c5556bdd11d16e599677f661a6997cdd7f27538..0dbd594c2747cb0e82f9f27970e0905108069a3a 100644 (file)
@@ -457,7 +457,7 @@ function barf
        mov     x11, x1 // actual data
        mov     x12, x2 // data size
 
-       puts    "Mistatch: PID="
+       puts    "Mismatch: PID="
        mov     x0, x20
        bl      putdec
        puts    ", iteration="
index f95074c9b48b730e3055a70f121a8cd3e11783bc..9210691aa9985601995eef4b8af58da33cd993b9 100644 (file)
@@ -625,7 +625,7 @@ function barf
        mov     x11, x1 // actual data
        mov     x12, x2 // data size
 
-       puts    "Mistatch: PID="
+       puts    "Mismatch: PID="
        mov     x0, x20
        bl      putdec
        puts    ", iteration="
index c0fe73a17ed1234ae7517b452364b32e58760771..3bfcf00c0a673771498f586410b062a115bd8220 100644 (file)
@@ -34,61 +34,6 @@ struct storage {
        struct bpf_spin_lock lock;
 };
 
-/* Copies an rm binary to a temp file. dest is a mkstemp template */
-static int copy_rm(char *dest)
-{
-       int fd_in, fd_out = -1, ret = 0;
-       struct stat stat;
-       char *buf = NULL;
-
-       fd_in = open("/bin/rm", O_RDONLY);
-       if (fd_in < 0)
-               return -errno;
-
-       fd_out = mkstemp(dest);
-       if (fd_out < 0) {
-               ret = -errno;
-               goto out;
-       }
-
-       ret = fstat(fd_in, &stat);
-       if (ret == -1) {
-               ret = -errno;
-               goto out;
-       }
-
-       buf = malloc(stat.st_blksize);
-       if (!buf) {
-               ret = -errno;
-               goto out;
-       }
-
-       while (ret = read(fd_in, buf, stat.st_blksize), ret > 0) {
-               ret = write(fd_out, buf, ret);
-               if (ret < 0) {
-                       ret = -errno;
-                       goto out;
-
-               }
-       }
-       if (ret < 0) {
-               ret = -errno;
-               goto out;
-
-       }
-
-       /* Set executable permission on the copied file */
-       ret = chmod(dest, 0100);
-       if (ret == -1)
-               ret = -errno;
-
-out:
-       free(buf);
-       close(fd_in);
-       close(fd_out);
-       return ret;
-}
-
 /* Fork and exec the provided rm binary and return the exit code of the
  * forked process and its pid.
  */
@@ -168,9 +113,11 @@ static bool check_syscall_operations(int map_fd, int obj_fd)
 
 void test_test_local_storage(void)
 {
-       char tmp_exec_path[PATH_MAX] = "/tmp/copy_of_rmXXXXXX";
+       char tmp_dir_path[64] = "/tmp/local_storageXXXXXX";
        int err, serv_sk = -1, task_fd = -1, rm_fd = -1;
        struct local_storage *skel = NULL;
+       char tmp_exec_path[64];
+       char cmd[256];
 
        skel = local_storage__open_and_load();
        if (CHECK(!skel, "skel_load", "lsm skeleton failed\n"))
@@ -189,18 +136,24 @@ void test_test_local_storage(void)
                                      task_fd))
                goto close_prog;
 
-       err = copy_rm(tmp_exec_path);
-       if (CHECK(err < 0, "copy_rm", "err %d errno %d\n", err, errno))
+       if (CHECK(!mkdtemp(tmp_dir_path), "mkdtemp",
+                 "unable to create tmpdir: %d\n", errno))
                goto close_prog;
 
+       snprintf(tmp_exec_path, sizeof(tmp_exec_path), "%s/copy_of_rm",
+                tmp_dir_path);
+       snprintf(cmd, sizeof(cmd), "cp /bin/rm %s", tmp_exec_path);
+       if (CHECK_FAIL(system(cmd)))
+               goto close_prog_rmdir;
+
        rm_fd = open(tmp_exec_path, O_RDONLY);
        if (CHECK(rm_fd < 0, "open", "failed to open %s err:%d, errno:%d",
                  tmp_exec_path, rm_fd, errno))
-               goto close_prog;
+               goto close_prog_rmdir;
 
        if (!check_syscall_operations(bpf_map__fd(skel->maps.inode_storage_map),
                                      rm_fd))
-               goto close_prog;
+               goto close_prog_rmdir;
 
        /* Sets skel->bss->monitored_pid to the pid of the forked child
         * forks a child process that executes tmp_exec_path and tries to
@@ -209,33 +162,36 @@ void test_test_local_storage(void)
         */
        err = run_self_unlink(&skel->bss->monitored_pid, tmp_exec_path);
        if (CHECK(err != EPERM, "run_self_unlink", "err %d want EPERM\n", err))
-               goto close_prog_unlink;
+               goto close_prog_rmdir;
 
        /* Set the process being monitored to be the current process */
        skel->bss->monitored_pid = getpid();
 
-       /* Remove the temporary created executable */
-       err = unlink(tmp_exec_path);
-       if (CHECK(err != 0, "unlink", "unable to unlink %s: %d", tmp_exec_path,
-                 errno))
-               goto close_prog_unlink;
+       /* Move copy_of_rm to a new location so that it triggers the
+        * inode_rename LSM hook with a new_dentry that has a NULL inode ptr.
+        */
+       snprintf(cmd, sizeof(cmd), "mv %s/copy_of_rm %s/check_null_ptr",
+                tmp_dir_path, tmp_dir_path);
+       if (CHECK_FAIL(system(cmd)))
+               goto close_prog_rmdir;
 
        CHECK(skel->data->inode_storage_result != 0, "inode_storage_result",
              "inode_local_storage not set\n");
 
        serv_sk = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0);
        if (CHECK(serv_sk < 0, "start_server", "failed to start server\n"))
-               goto close_prog;
+               goto close_prog_rmdir;
 
        CHECK(skel->data->sk_storage_result != 0, "sk_storage_result",
              "sk_local_storage not set\n");
 
        if (!check_syscall_operations(bpf_map__fd(skel->maps.sk_storage_map),
                                      serv_sk))
-               goto close_prog;
+               goto close_prog_rmdir;
 
-close_prog_unlink:
-       unlink(tmp_exec_path);
+close_prog_rmdir:
+       snprintf(cmd, sizeof(cmd), "rm -rf %s", tmp_dir_path);
+       system(cmd);
 close_prog:
        close(serv_sk);
        close(rm_fd);
index 3e3de130f28f303e30a45bff6501e502f905fa93..95868bc7ada9873efcbf9edb16b6bed5f8ec1b4c 100644 (file)
@@ -50,7 +50,6 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim)
        __u32 pid = bpf_get_current_pid_tgid() >> 32;
        struct local_storage *storage;
        bool is_self_unlink;
-       int err;
 
        if (pid != monitored_pid)
                return 0;
@@ -66,8 +65,27 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim)
                        return -EPERM;
        }
 
-       storage = bpf_inode_storage_get(&inode_storage_map, victim->d_inode, 0,
-                                       BPF_LOCAL_STORAGE_GET_F_CREATE);
+       return 0;
+}
+
+SEC("lsm/inode_rename")
+int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry,
+            struct inode *new_dir, struct dentry *new_dentry,
+            unsigned int flags)
+{
+       __u32 pid = bpf_get_current_pid_tgid() >> 32;
+       struct local_storage *storage;
+       int err;
+
+       /* new_dentry->d_inode can be NULL when the inode is renamed to a file
+        * that did not exist before. The helper should be able to handle this
+        * NULL pointer.
+        */
+       bpf_inode_storage_get(&inode_storage_map, new_dentry->d_inode, 0,
+                             BPF_LOCAL_STORAGE_GET_F_CREATE);
+
+       storage = bpf_inode_storage_get(&inode_storage_map, old_dentry->d_inode,
+                                       0, 0);
        if (!storage)
                return 0;
 
@@ -76,7 +94,7 @@ int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim)
                inode_storage_result = -1;
        bpf_spin_unlock(&storage->lock);
 
-       err = bpf_inode_storage_delete(&inode_storage_map, victim->d_inode);
+       err = bpf_inode_storage_delete(&inode_storage_map, old_dentry->d_inode);
        if (!err)
                inode_storage_result = err;
 
@@ -133,37 +151,18 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
        return 0;
 }
 
-SEC("lsm/file_open")
-int BPF_PROG(file_open, struct file *file)
-{
-       __u32 pid = bpf_get_current_pid_tgid() >> 32;
-       struct local_storage *storage;
-
-       if (pid != monitored_pid)
-               return 0;
-
-       if (!file->f_inode)
-               return 0;
-
-       storage = bpf_inode_storage_get(&inode_storage_map, file->f_inode, 0,
-                                       BPF_LOCAL_STORAGE_GET_F_CREATE);
-       if (!storage)
-               return 0;
-
-       bpf_spin_lock(&storage->lock);
-       storage->value = DUMMY_STORAGE_VALUE;
-       bpf_spin_unlock(&storage->lock);
-       return 0;
-}
-
 /* This uses the local storage to remember the inode of the binary that a
  * process was originally executing.
  */
 SEC("lsm/bprm_committed_creds")
 void BPF_PROG(exec, struct linux_binprm *bprm)
 {
+       __u32 pid = bpf_get_current_pid_tgid() >> 32;
        struct local_storage *storage;
 
+       if (pid != monitored_pid)
+               return;
+
        storage = bpf_task_storage_get(&task_storage_map,
                                       bpf_get_current_task_btf(), 0,
                                       BPF_LOCAL_STORAGE_GET_F_CREATE);
@@ -172,4 +171,13 @@ void BPF_PROG(exec, struct linux_binprm *bprm)
                storage->exec_inode = bprm->file->f_inode;
                bpf_spin_unlock(&storage->lock);
        }
+
+       storage = bpf_inode_storage_get(&inode_storage_map, bprm->file->f_inode,
+                                       0, BPF_LOCAL_STORAGE_GET_F_CREATE);
+       if (!storage)
+               return;
+
+       bpf_spin_lock(&storage->lock);
+       storage->value = DUMMY_STORAGE_VALUE;
+       bpf_spin_unlock(&storage->lock);
 }
index 777a81404fdbd15a9643151c108a51db7d4478f3..f8569f04064b7e9684e3a93e1e03ab1e2f13fa7c 100644 (file)
@@ -50,7 +50,7 @@
 #define MAX_INSNS      BPF_MAXINSNS
 #define MAX_TEST_INSNS 1000000
 #define MAX_FIXUPS     8
-#define MAX_NR_MAPS    20
+#define MAX_NR_MAPS    21
 #define MAX_TEST_RUNS  8
 #define POINTER_VALUE  0xcafe4all
 #define TEST_DATA_LEN  64
@@ -87,6 +87,7 @@ struct bpf_test {
        int fixup_sk_storage_map[MAX_FIXUPS];
        int fixup_map_event_output[MAX_FIXUPS];
        int fixup_map_reuseport_array[MAX_FIXUPS];
+       int fixup_map_ringbuf[MAX_FIXUPS];
        const char *errstr;
        const char *errstr_unpriv;
        uint32_t insn_processed;
@@ -640,6 +641,7 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type,
        int *fixup_sk_storage_map = test->fixup_sk_storage_map;
        int *fixup_map_event_output = test->fixup_map_event_output;
        int *fixup_map_reuseport_array = test->fixup_map_reuseport_array;
+       int *fixup_map_ringbuf = test->fixup_map_ringbuf;
 
        if (test->fill_helper) {
                test->fill_insns = calloc(MAX_TEST_INSNS, sizeof(struct bpf_insn));
@@ -817,6 +819,14 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type,
                        fixup_map_reuseport_array++;
                } while (*fixup_map_reuseport_array);
        }
+       if (*fixup_map_ringbuf) {
+               map_fds[20] = create_map(BPF_MAP_TYPE_RINGBUF, 0,
+                                          0, 4096);
+               do {
+                       prog[*fixup_map_ringbuf].imm = map_fds[20];
+                       fixup_map_ringbuf++;
+               } while (*fixup_map_ringbuf);
+       }
 }
 
 struct libcap {
index 45d43bf82f269190bc51ab29f7032e909103dca0..0b943897aaf6c136a8fea40a3804042b28c44e37 100644 (file)
        .result = ACCEPT,
        .result_unpriv = ACCEPT,
 },
+{
+       "check valid spill/fill, ptr to mem",
+       .insns = {
+       /* reserve 8 byte ringbuf memory */
+       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_MOV64_IMM(BPF_REG_2, 8),
+       BPF_MOV64_IMM(BPF_REG_3, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_ringbuf_reserve),
+       /* store a pointer to the reserved memory in R6 */
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       /* check whether the reservation was successful */
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
+       /* spill R6(mem) into the stack */
+       BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -8),
+       /* fill it back in R7 */
+       BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_10, -8),
+       /* should be able to access *(R7) = 0 */
+       BPF_ST_MEM(BPF_DW, BPF_REG_7, 0, 0),
+       /* submit the reserved ringbuf memory */
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
+       BPF_MOV64_IMM(BPF_REG_2, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_ringbuf_submit),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_ringbuf = { 1 },
+       .result = ACCEPT,
+       .result_unpriv = ACCEPT,
+},
 {
        "check corrupted spill/fill",
        .insns = {
index 84205c3a55ebed11ddbbf307d771338e0f4d1ac5..2b5707738609ef313e533c78492e25bbc6a02313 100755 (executable)
@@ -1055,7 +1055,6 @@ ipv6_addr_metric_test()
 
        check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260"
        log_test $? 0 "Set metric with peer route on local side"
-       log_test $? 0 "User specified metric on local address"
        check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260"
        log_test $? 0 "Set metric with peer route on peer side"
 
index cb0d1890a860fb91128f51c1029fce0fec502823..e0088c2d38a5d7ecf952bc8deb931c29b615d52b 100644 (file)
@@ -103,8 +103,8 @@ FIXTURE(tls)
 
 FIXTURE_VARIANT(tls)
 {
-       u16 tls_version;
-       u16 cipher_type;
+       uint16_t tls_version;
+       uint16_t cipher_type;
 };
 
 FIXTURE_VARIANT_ADD(tls, 12_gcm)
index edf0a48da6bf80650720471cc3913521330073d7..bf6b9626c7dd2749547cb13062188d4bb834c5b6 100755 (executable)
@@ -94,7 +94,13 @@ check_for_helper()
        local message=$2
        local port=$3
 
-       ip netns exec ${netns} conntrack -L -p tcp --dport $port 2> /dev/null |grep -q 'helper=ftp'
+       if echo $message |grep -q 'ipv6';then
+               local family="ipv6"
+       else
+               local family="ipv4"
+       fi
+
+       ip netns exec ${netns} conntrack -L -f $family -p tcp --dport $port 2> /dev/null |grep -q 'helper=ftp'
        if [ $? -ne 0 ] ; then
                echo "FAIL: ${netns} did not show attached helper $message" 1>&2
                ret=1
@@ -111,8 +117,8 @@ test_helper()
 
        sleep 3 | ip netns exec ${ns2} nc -w 2 -l -p $port > /dev/null &
 
-       sleep 1
        sleep 1 | ip netns exec ${ns1} nc -w 2 10.0.1.2 $port > /dev/null &
+       sleep 1
 
        check_for_helper "$ns1" "ip $msg" $port
        check_for_helper "$ns2" "ip $msg" $port
@@ -128,8 +134,8 @@ test_helper()
 
        sleep 3 | ip netns exec ${ns2} nc -w 2 -6 -l -p $port > /dev/null &
 
-       sleep 1
        sleep 1 | ip netns exec ${ns1} nc -w 2 -6 dead:1::2 $port > /dev/null &
+       sleep 1
 
        check_for_helper "$ns1" "ipv6 $msg" $port
        check_for_helper "$ns2" "ipv6 $msg" $port